diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e367eb2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "client/others/hmac"] + path = client/others/hmac + url = https://github.com/ogay/hmac.git diff --git a/README.md b/README.md new file mode 100644 index 0000000..37177d5 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# D4 core + +Software components used for the D4 project + +## D4 core client + +~~~~ +git submodule init +git submodule update +~~~~ + +### Requirements + +- uuid-dev +- make +- a recent C compiler + diff --git a/client/Makefile b/client/Makefile index c60d46c..90a2b15 100644 --- a/client/Makefile +++ b/client/Makefile @@ -1,2 +1,20 @@ -d4: d4.c - gcc -Wall -o d4 d4.c +all: d4 + + +hmac: hmac.o sha2.o + $(CC) sha2.o hmac.o -o hmac + +hmac.o: ./others/hmac/hmac_sha2.c ./others/hmac/hmac_sha2.h + $(CC) -Wall -c ./others/hmac/hmac_sha2.c -o hmac.o + +sha2.o: ./others/hmac/sha2.c ./others/hmac/sha2.h + $(CC) -c ./others/hmac/sha2.c -o sha2.o + +clean: + - rm -rf *.o hmac + +d4: d4.o sha2.o hmac.o + gcc -Wall -o d4 d4.o hmac.o sha2.o -luuid + +d4.o: d4.c + gcc -Wall -c d4.c diff --git a/client/conf.sample/destination b/client/conf.sample/destination new file mode 100644 index 0000000..faa3a15 --- /dev/null +++ b/client/conf.sample/destination @@ -0,0 +1 @@ +stdout diff --git a/client/conf.sample/key b/client/conf.sample/key new file mode 100644 index 0000000..577c30e --- /dev/null +++ b/client/conf.sample/key @@ -0,0 +1 @@ +private key to change diff --git a/client/conf.sample/snaplen b/client/conf.sample/snaplen new file mode 100644 index 0000000..801c306 --- /dev/null +++ b/client/conf.sample/snaplen @@ -0,0 +1 @@ +4096 diff --git a/client/conf.sample/source b/client/conf.sample/source new file mode 100644 index 0000000..cf52303 --- /dev/null +++ b/client/conf.sample/source @@ -0,0 +1 @@ +stdin diff --git a/client/conf.sample/type b/client/conf.sample/type new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/client/conf.sample/type @@ -0,0 +1 @@ +1 diff --git a/client/conf.sample/version b/client/conf.sample/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/client/conf.sample/version @@ -0,0 +1 @@ +1 diff --git a/client/d4.c b/client/d4.c index ab4afcb..941a2a2 100644 --- a/client/d4.c +++ b/client/d4.c @@ -8,10 +8,75 @@ #include #include #include -#include +#include +#include #include "d4.h" // + + +void usage(void) +{ + printf("d4 - d4 client\n"); + printf("Read data from the configured and send it to \n"); + printf("\n"); + printf("Usage: d4 -c config_directory\n"); + printf("\n"); + + printf("Configuration\n\n"); + printf("The configuration settings are stored in files in the configuration directory\n"); + printf("specified with the -c command line switch.\n\n"); + printf("Files in the configuration directory\n"); + printf("\n"); + printf("key - is the private HMAC-SHA-256-128 key.\n"); + printf(" The HMAC is computed on the header with a HMAC value set to 0\n"); + printf(" which is updated later.\n"); + printf("snaplen - the length of bytes that is read from the \n"); + printf("version - the version of the d4 client\n"); + printf("type - the type of data that is send. pcap, netflow, ...\n"); + printf("source - the source where the data is read from\n"); + printf("destination - the destination where the data is written to\n"); +} + +/* + * Generate a uuid if no one was set. + * If no errors occured textual representation of uuid is stored in the + * configuration array + */ +void d4_update_uuid(d4_t* d4) +{ + uuid_t uuid; + int fd,ret; + char* filename; + char* uuid_text; + + if (d4->conf[UUID][0] == 0){ + uuid_generate(uuid); + filename = calloc(1,2*FILENAME_MAX); + uuid_text = calloc(1, SZUUID_TEXT); + if ((filename != NULL) && (uuid != NULL)) { + snprintf(filename, 2*FILENAME_MAX, "%s/%s",d4->confdir, d4params[UUID]); + fd = open(filename, O_CREAT | O_WRONLY, S_IRUSR |S_IWUSR); + if (fd > 0) { + uuid_unparse(uuid, uuid_text); + ret = write(fd, uuid_text, SZUUID_TEXT-1); + if (ret > 0) { + memcpy(d4->conf[UUID], uuid_text, SZUUID_TEXT); + } else { + d4->errno_copy = errno; + } + close(fd); + } else { + // Cannot open file + d4->errno_copy = errno; + } + } + /* If there is an error the uuid is not stored and a new one is + * generated for the next boot + */ + } +} + int d4_check_config(d4_t* d4) { // TODO implement other sources, file, fifo, unix_socket ... @@ -28,13 +93,15 @@ int d4_check_config(d4_t* d4) } } d4->snaplen = atoi(d4->conf[SNAPLEN]); + + d4_update_uuid(d4); + if ((d4->snaplen < 0) || (d4->snaplen > MAXSNAPLEN)) { d4->snaplen = 0; } - printf("TEST snaplen %d stdin %d stdout %d\n", d4->snaplen, STDIN_FILENO, STDOUT_FILENO); //FIXME Check other parameters - if (( d4->destination.fd > 0 ) && ( d4->snaplen >0 )) { + if ((atoi(d4->conf[VERSION])>0) && ( d4->destination.fd > 0 ) && ( d4->snaplen >0 )) { return 1; } return -1; @@ -63,11 +130,6 @@ int d4_load_config(d4_t* d4) return d4_check_config(d4); } -void usage(void) -{ - printf("d4 client help\n"); -} - d4_t* d4_init(char* confdir) { d4_t* out; @@ -85,16 +147,33 @@ d4_t* d4_init(char* confdir) } -//FIXME split in prepare and update. Do not copy uuid each time -void d4_update_header(d4_t* d4, ssize_t nread) { - bzero(&d4->header,sizeof(d4_update_header)); - //TODO Check format + +void d4_prepare_header(d4_t* d4) +{ + char uuid_text[24]; + uuid_t uuid; + + bzero(&d4->header,sizeof(d4->header)); + bzero(&uuid_text, 24); d4->header.version = atoi(d4->conf[VERSION]); - //TODO set type - d4->header.timestamp = time(NULL); - //FIXME length handling - strncpy((char*)&(d4->header.uuid), d4->conf[UUID], SZUUID); - //TODO hmac + if (!uuid_parse(d4->conf[UUID],uuid)) { + memcpy(d4->header.uuid, uuid, SZUUID); + } + // If UUID cannot be parsed it is set to 0 + d4->header.type = atoi(d4->conf[TYPE]); + + d4->ctx = calloc(sizeof(hmac_sha256_ctx),1); + if (d4->ctx) { + //FIXME check cast of the key + hmac_sha256_init(d4->ctx, (uint8_t*)d4->conf[KEY], strlen(d4->conf[KEY])); + } +} + +void d4_update_header(d4_t* d4, ssize_t nread) { + struct timeval tv; + bzero(&tv,sizeof(struct timeval)); + gettimeofday(&tv,NULL); + d4->header.timestamp = tv.tv_sec; d4->header.size=nread; } @@ -103,18 +182,28 @@ void d4_transfert(d4_t* d4) { ssize_t nread; char* buf; + unsigned char* hmac; buf = calloc(1, d4->snaplen); + hmac = calloc(1,SZHMAC); //TODO error handling -> insert error message - if (!buf) + if ((buf == NULL) && (hmac == NULL)) return; + d4_prepare_header(d4); while ( 1 ) { //In case of errors see block of 0 bytes bzero(buf, d4->snaplen); nread = read(d4->source.fd, buf, d4->snaplen); if ( nread > 0 ) { d4_update_header(d4, nread); + //Do HMAC on header and payload. HMAC field is 0 during computation + hmac_sha256_update(d4->ctx, (const unsigned char*)&d4->header, + sizeof(d4_header_t)); + hmac_sha256_update(d4->ctx, (const unsigned char*)buf, nread); + hmac_sha256_final(d4->ctx, hmac, SZHMAC); + //Add it to the header + memcpy(d4->header.hmac, hmac, SZHMAC); write(d4->destination.fd, &d4->header, sizeof(d4->header)); write(d4->destination.fd,buf,nread); } else{ diff --git a/client/d4.h b/client/d4.h index 71a7e58..7c91fc8 100644 --- a/client/d4.h +++ b/client/d4.h @@ -1,16 +1,19 @@ #ifndef D4_H #define D4_H -#define ND4PARAMS 6 +#include "others/hmac/hmac_sha2.h" + +#define ND4PARAMS 7 #define NERRORS 100 #define SZCONFVALUE 1024 #define SZERRVALUE 1024 +#define SZHMAC 32 #define STDIN "stdin" #define STDOUT "stdout" #define MAXSNAPLEN 65535 -#define SZUUID 128 - +#define SZUUID 16 +#define SZUUID_TEXT 37 #define INSERT_ERROR(...) do { \ if (d4->err_idx < NERRORS) \ snprintf(d4->errors[d4->err_idx],SZERRVALUE,__VA_ARGS__); \ @@ -20,9 +23,9 @@ typedef struct d4_header_s { uint8_t version; uint8_t type; - uint8_t uuid[128]; + uint8_t uuid[SZUUID]; uint64_t timestamp; - uint8_t hmac[256]; + uint8_t hmac[SZHMAC]; uint32_t size; } d4_header_t; @@ -49,6 +52,7 @@ typedef struct d4_s { char errors[NERRORS][SZERRVALUE]; int err_idx; d4_header_t header; + hmac_sha256_ctx *ctx; } d4_t; @@ -59,7 +63,7 @@ typedef struct d4_s { * d4-conf/collector */ -const char* d4params[] = {"uuid", "snaplen", "key", "version", "source", "destination"}; +const char* d4params[] = {"uuid", "snaplen", "key", "version", "source", "destination","type"}; #define UUID 0 #define SNAPLEN 1 @@ -67,5 +71,6 @@ const char* d4params[] = {"uuid", "snaplen", "key", "version", "source", "destin #define VERSION 3 #define SOURCE 4 #define DESTINATION 5 +#define TYPE 6 #endif diff --git a/client/others/hmac b/client/others/hmac new file mode 160000 index 0000000..5efc450 --- /dev/null +++ b/client/others/hmac @@ -0,0 +1 @@ +Subproject commit 5efc450f9dd204059b2f29808deaf2f8239b8129