diff options
Diffstat (limited to 'receiver.cpp')
-rw-r--r-- | receiver.cpp | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/receiver.cpp b/receiver.cpp index a3a0dc9..6be0f8a 100644 --- a/receiver.cpp +++ b/receiver.cpp | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <fcntl.h> | 7 | #include <fcntl.h> |
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <sys/socket.h> | 9 | #include <sys/socket.h> |
10 | #include <sys/stat.h> | ||
11 | #include <limits.h> | ||
10 | #include <netinet/in.h> | 12 | #include <netinet/in.h> |
11 | 13 | ||
12 | #include <mbedtls/pk.h> | 14 | #include <mbedtls/pk.h> |
@@ -78,15 +80,16 @@ static time_t now() { | |||
78 | 80 | ||
79 | // Constants | 81 | // Constants |
80 | enum { SESSION_ID_LENGTH = 8, AES_KEY_LENGTH = 16, GCM_IV_LENGTH = 16, GCM_TAG_LENGTH = 16, MIN_PACKET_SIZE = 40 }; | 82 | enum { SESSION_ID_LENGTH = 8, AES_KEY_LENGTH = 16, GCM_IV_LENGTH = 16, GCM_TAG_LENGTH = 16, MIN_PACKET_SIZE = 40 }; |
81 | enum { FILENAME_LENGTH = 73, SIDOFFS = 20, KEYOFFS = 37 }; | 83 | enum { DIRNAME_LENGTH = 10, FILENAME_LENGTH = 73, SIDOFFS = 20, KEYOFFS = 37 }; |
82 | 84 | ||
83 | class Session { | 85 | class Session { |
84 | public: | 86 | public: |
85 | Session(uint64_t session_id, uint8_t key[AES_KEY_LENGTH], const std::string &filename) : | 87 | Session(uint64_t session_id, uint8_t key[AES_KEY_LENGTH], const std::string &dirname, const std::string &filename) : |
86 | _session_id(session_id), _filename(filename) { | 88 | _session_id(session_id), _dirname(dirname), _filename(filename) { |
87 | memcpy(_key, key, AES_KEY_LENGTH); | 89 | memcpy(_key, key, AES_KEY_LENGTH); |
88 | mbedtls_gcm_init(&_ctx); | 90 | mbedtls_gcm_init(&_ctx); |
89 | mbedtls_gcm_setkey(&_ctx, MBEDTLS_CIPHER_ID_AES, _key, 8 * AES_KEY_LENGTH); | 91 | mbedtls_gcm_setkey(&_ctx, MBEDTLS_CIPHER_ID_AES, _key, 8 * AES_KEY_LENGTH); |
92 | // std::cerr << "Imported file " << _filename << " in dir " << _dirname << std::endl; | ||
90 | } | 93 | } |
91 | 94 | ||
92 | Session(uint64_t session_id, uint8_t key[AES_KEY_LENGTH]) : _session_id(session_id) { | 95 | Session(uint64_t session_id, uint8_t key[AES_KEY_LENGTH]) : _session_id(session_id) { |
@@ -98,7 +101,7 @@ public: | |||
98 | char tprefix[32]; | 101 | char tprefix[32]; |
99 | time_t t = time(NULL); | 102 | time_t t = time(NULL); |
100 | struct tm * jetzt = localtime(&t); | 103 | struct tm * jetzt = localtime(&t); |
101 | size_t nlen = strftime(tprefix, sizeof(tprefix), "%F-%H-%M-%S", jetzt); | 104 | strftime(tprefix, sizeof(tprefix), "%F-%H-%M-%S", jetzt); |
102 | 105 | ||
103 | // Dump key | 106 | // Dump key |
104 | char hexkey[2*AES_KEY_LENGTH + 1]; | 107 | char hexkey[2*AES_KEY_LENGTH + 1]; |
@@ -107,18 +110,24 @@ public: | |||
107 | 110 | ||
108 | // Glue together serialisation | 111 | // Glue together serialisation |
109 | char filename[FILENAME_LENGTH + 1]; | 112 | char filename[FILENAME_LENGTH + 1]; |
110 | snprintf(filename, sizeof(filename), "%s-%016" PRIx64 "-%s.log", tprefix, _session_id, hexkey); | 113 | size_t nlen = snprintf(filename, sizeof(filename), "%s-%016" PRIx64 "-%s.log", tprefix, _session_id, hexkey); |
114 | _filename = std::string(filename, filename + nlen); | ||
111 | 115 | ||
112 | // Touch file to save session_id and key | 116 | _dirname = std::string(filename, DIRNAME_LENGTH); |
113 | close(open(filename, O_WRONLY|O_CREAT, 0755)); | ||
114 | 117 | ||
115 | _filename = std::string(filename, filename + FILENAME_LENGTH); | 118 | // Touch file to save session_id and key |
119 | close(ensure_file()); | ||
116 | } | 120 | } |
117 | 121 | ||
118 | ~Session() { | 122 | ~Session() { |
119 | mbedtls_gcm_free(&_ctx); | 123 | mbedtls_gcm_free(&_ctx); |
120 | } | 124 | } |
121 | 125 | ||
126 | int ensure_file() { | ||
127 | mkdir(_dirname.c_str(), 0755); | ||
128 | return open((_dirname + "/" + _filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0755); | ||
129 | } | ||
130 | |||
122 | void write_log(const uint8_t *packet, size_t len) { | 131 | void write_log(const uint8_t *packet, size_t len) { |
123 | // First check if the packet holds enough space for session id, iv and at least one gcm block | 132 | // First check if the packet holds enough space for session id, iv and at least one gcm block |
124 | if (len < GCM_IV_LENGTH + GCM_TAG_LENGTH) { | 133 | if (len < GCM_IV_LENGTH + GCM_TAG_LENGTH) { |
@@ -140,7 +149,7 @@ public: | |||
140 | 149 | ||
141 | // Create output file if it doesn't exist | 150 | // Create output file if it doesn't exist |
142 | if (_fd < 0) | 151 | if (_fd < 0) |
143 | _fd = ::open(_filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0755); | 152 | _fd = ensure_file(); |
144 | if (_fd < 0) { | 153 | if (_fd < 0) { |
145 | std::cerr << "Error: Can't create file " << _filename << " for session " << std::hex << _session_id; | 154 | std::cerr << "Error: Can't create file " << _filename << " for session " << std::hex << _session_id; |
146 | return; | 155 | return; |
@@ -179,6 +188,7 @@ private: | |||
179 | uint8_t _key[AES_KEY_LENGTH]; | 188 | uint8_t _key[AES_KEY_LENGTH]; |
180 | int _fd = -1; | 189 | int _fd = -1; |
181 | time_t _last_access = 0; | 190 | time_t _last_access = 0; |
191 | std::string _dirname; | ||
182 | std::string _filename; | 192 | std::string _filename; |
183 | std::set<std::string> _used_ivs; | 193 | std::set<std::string> _used_ivs; |
184 | mbedtls_gcm_context _ctx; | 194 | mbedtls_gcm_context _ctx; |
@@ -194,10 +204,10 @@ static uint8_t hex2nyble(char c) | |||
194 | : 0; | 204 | : 0; |
195 | } | 205 | } |
196 | 206 | ||
197 | static void import_sessions(const char *dirname) { | 207 | static void import_directory(const char *path, std::string dirname) { |
198 | DIR * dirp = opendir(dirname); | 208 | DIR * dirp = opendir(path); |
199 | if (!dirp) | 209 | if (!dirp) |
200 | errx(-1, "Fatal: Can't open dir %s\n", dirname); | 210 | errx(-1, "Fatal: Can't open dir %s\n", path); |
201 | 211 | ||
202 | regex_t regex; | 212 | regex_t regex; |
203 | if (regcomp(®ex, "^[[:digit:]]{4}-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-" | 213 | if (regcomp(®ex, "^[[:digit:]]{4}-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-[[:digit:]][[:digit:]]-" |
@@ -223,12 +233,29 @@ static void import_sessions(const char *dirname) { | |||
223 | const char * hexkey = filename.c_str() + KEYOFFS; | 233 | const char * hexkey = filename.c_str() + KEYOFFS; |
224 | for (int i=0; i<16; ++i) | 234 | for (int i=0; i<16; ++i) |
225 | aeskey[i] = (hex2nyble(hexkey[2*i]) << 4 ) | hex2nyble(hexkey[2*i+1]); | 235 | aeskey[i] = (hex2nyble(hexkey[2*i]) << 4 ) | hex2nyble(hexkey[2*i+1]); |
226 | g_sessions[session_id] = std::make_unique<Session>(session_id, aeskey, filename); | 236 | g_sessions[session_id] = std::make_unique<Session>(session_id, aeskey, dirname, filename); |
227 | } | 237 | } |
228 | closedir(dirp); | 238 | closedir(dirp); |
229 | regfree(®ex); | 239 | regfree(®ex); |
230 | } | 240 | } |
231 | 241 | ||
242 | static void import_sessions(const char *root_dir) { | ||
243 | char dirpath[PATH_MAX]; | ||
244 | DIR * dirp = opendir(root_dir); | ||
245 | if (!dirp) | ||
246 | errx(-1, "Fatal: Can't open dir %s\n", root_dir); | ||
247 | |||
248 | struct dirent * entry; | ||
249 | while ((entry = readdir(dirp)) != NULL) { | ||
250 | if (entry->d_type != DT_DIR || entry->d_namlen != DIRNAME_LENGTH) | ||
251 | continue; | ||
252 | std::string dirname(entry->d_name, entry->d_name + entry->d_namlen); | ||
253 | snprintf(dirpath, PATH_MAX, "%s/%*s", root_dir, DIRNAME_LENGTH, entry->d_name); | ||
254 | import_directory(dirpath, dirname); | ||
255 | } | ||
256 | closedir(dirp); | ||
257 | } | ||
258 | |||
232 | int main() { | 259 | int main() { |
233 | mbedtls_ctr_drbg_context ctr_drbg; | 260 | mbedtls_ctr_drbg_context ctr_drbg; |
234 | mbedtls_entropy_context entropy; | 261 | mbedtls_entropy_context entropy; |