Skip to content

0xARK/file-extractor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Installation

The server private key and public certificate were included in the submission. This means they were pushed to GitHub and it is not good practice. I did this because I wanted you to only have to run a single command to test the project; however, it is possible to regenerate these keys by following the steps below.

The precompiled executables of the latest version were also included in the submission. However, it is possible to regenerate them by following the steps described below.

Installing the libssl development package:

sudo apt-get install libssl-dev

Creating the private key and certificate for the server:

openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

Compiling the executables using cmake:

cd build
cmake ..
make

The executables generated by cmake are then respectively placed in the server/ and client/ folders. Compiling the executables using gcc:

gcc server.c -o server -lcrypto -lssl
gcc client.c -o client -lcrypto -lssl

Usage

The GitHub repository contains all the files required to perform tests. It is therefore possible to test this project simply by running the following commands:

./client -p 80 -h 127.0.0.1 ./monitored-folder/
./server -p 80 -l 127.0.0.1
bash generate_file.sh

Files received by the server can be observed in the server/client-files/<client-id>/ folder, generated automatically.

The server executable must be placed in the same folder as the private key and certificate generated previously.

More generally, the executables can be launched by providing the following arguments:

./client -p <port> -h <host> <folder1> ...
./server -p <port> -l <host>

Notes

Notes

Here is a short explanation of what I implemented in order to meet the requirements.

The chosen development platform is Linux. This project was developed on an Ubuntu 20.04 virtual machine.

The first real issue encountered was the unique identification of clients. There are several ways to uniquely identify a machine, such as the MAC address, generating a UUID stored on the client, or reading hardware information such as motherboard serial numbers or disk serial IDs. I chose not to use the MAC address for several reasons, such as the fact that a machine can have multiple ones or that they may be virtual addresses reused by other clients (for example Docker MAC addresses). I also preferred to avoid creating a file on the client side to store its UUID for stealth reasons. Finally, reading system information sometimes requires root access, which is why I did not choose this solution either. I therefore ultimately decided to use the /etc/machine-id file, which contains a unique UUID generated by Linux during installation (or at boot if it is not present).

The second issue was securing the connection to ensure the confidentiality of exchanged data. At first, I planned to simply encrypt the file being transmitted, but I realized that I would need to send more data to the server than just this file. I therefore looked into implementing an SSL/TLS connection in order to secure all exchanges performed. I had never implemented this in C before, but I managed to do it in part thanks to the official OpenSSL documentation, which helped me a lot.

The third issue encountered was integrating an integrity verification system. I know that the TCP/IP stack already includes a packet integrity verification system based on the CRC algorithm, but I thought that would not be sufficient. I admit I did not spend too much time on this issue: I simply generated a checksum of the file before sending it, which I then transmitted to the server so it could verify the integrity of the file that had just been written. If the file is corrupted, it is then renamed so that it can easily be identified as corrupted.

Finally, the last blocking point concerned the inotify API: indeed, from the start I was using the IN_CREATE event to detect the creation of a new file within monitored folders. However, during my tests, I noticed a particular behavior: newly created and very large files often tended to become corrupted once transmitted. This happened because inotify emitted the creation event as soon as the file was created, and at the moment this event was emitted, the file content had not yet been fully written to disk, or had only been partially written. I therefore first added a sleep between event detection and file processing, but I thought this was a terrible way to handle the issue, since if an even larger file was created, writing it would simply take longer than the sleep duration. I therefore chose to use the IN_CLOSE_WRITE event, which is emitted once a file opened for writing has been closed. This has the advantage of handling large files, the downside being that now even modified files are transmitted to the server. I think this could be an improvement area in my program, but I ran out of time to address it.

Regarding concurrent client handling on the server side, I used the fork() system call to create child processes, in which each client’s processing is performed in order not to block subsequent requests.

I also wanted to highlight the termination of the client and server programs: since this was not specified in the requirements, I assumed they would be launched manually. That is why, in order to stop them properly by closing sockets and freeing allocated memory, I chose to intercept the SIGINT signal (CTRL+C) to perform these actions. Of course, this may not correspond to the intended usage in some cases, for example if the program is launched by another process. In that case, the way we want to gracefully terminate the program would need to be reworked.

Finally, here are the main libraries I relied on to develop this project:

  • getopt is used on both the client and server sides to parse the input arguments.
  • inotify is used to monitor folders on the client side.
  • openssl is used on both the client and server sides to secure the connection between both parties using TLS.

About

Secure client/server file monitoring system written in C. The client monitors folders and securely transmits files to the server with integrity verification and concurrent client handling.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors