X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Flibcollectdclient%2Fnetwork_parse.c;h=49b1a007b8920f079b8afcf0f7ef8788e905dcea;hp=3a428892e9b5e5edeba10f6cc7d3940a89249203;hb=a9e50e9e30ecde17e167e271060c8183bfcbf407;hpb=a81a7365e671cf02d88448e6c536c678a5a9d67c diff --git a/src/libcollectdclient/network_parse.c b/src/libcollectdclient/network_parse.c index 3a428892..49b1a007 100644 --- a/src/libcollectdclient/network_parse.c +++ b/src/libcollectdclient/network_parse.c @@ -23,9 +23,7 @@ * Florian octo Forster **/ -#if HAVE_CONFIG_H #include "config.h" -#endif #if !defined(__GNUC__) || !__GNUC__ #define __attribute__(x) /**/ @@ -33,24 +31,58 @@ #include "collectd/lcc_features.h" #include "collectd/network_parse.h" +#include "globals.h" #include #include #include +#include +#include + +/* for be{16,64}toh */ +#if HAVE_ENDIAN_H +#include +#elif HAVE_SYS_ENDIAN_H +#include +#else /* fallback */ +__attribute__((const)) static uint16_t be16toh(uint16_t n) { + uint8_t tmp[2]; + memmove(tmp, &n, sizeof(tmp)); + + return ((uint16_t)tmp[0] << 8) | ((uint16_t)tmp[1] << 0); +} + +__attribute__((const)) static uint64_t be64toh(uint64_t n) { + uint8_t tmp[8]; + memmove(tmp, &n, sizeof(tmp)); + + return ((uint64_t)tmp[0] << 56) | ((uint64_t)tmp[1] << 48) | + ((uint64_t)tmp[2] << 40) | ((uint64_t)tmp[3] << 32) | + ((uint64_t)tmp[4] << 24) | ((uint64_t)tmp[5] << 16) | + ((uint64_t)tmp[6] << 8) | ((uint64_t)tmp[7] << 0); +} +#endif +#if HAVE_GCRYPT_H #define GCRYPT_NO_DEPRECATED #include +#endif #include #define DEBUG(...) printf(__VA_ARGS__) +#if HAVE_GCRYPT_H +#if GCRYPT_VERSION_NUMBER < 0x010600 GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif +#endif /* forward declaration because parse_sign_sha256()/parse_encrypt_aes256() and * network_parse() need to call each other. */ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, lcc_network_parse_options_t const *opts); +#if HAVE_GCRYPT_H static int init_gcrypt() { /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html * Because you can't know in a library whether another library has @@ -80,6 +112,7 @@ static int init_gcrypt() { gcry_control(GCRYCTL_INITIALIZATION_FINISHED); return 0; } +#endif typedef struct { uint8_t *data; @@ -287,8 +320,6 @@ static int parse_values(void *payload, size_t payload_size, state->values = calloc(sizeof(*state->values), state->values_len); state->values_types = calloc(sizeof(*state->values_types), state->values_len); if ((state->values == NULL) || (state->values_types == NULL)) { - free(state->values); - free(state->values_types); return ENOMEM; } @@ -332,6 +363,7 @@ static int parse_values(void *payload, size_t payload_size, return 0; } +#if HAVE_GCRYPT_H static int verify_sha256(void *payload, size_t payload_size, char const *username, char const *password, uint8_t hash_provided[32]) { @@ -339,14 +371,13 @@ static int verify_sha256(void *payload, size_t payload_size, gcry_error_t err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); if (err != 0) { - /* TODO(octo): use gcry_strerror(err) to create an error string. */ - return -1; + return (int)err; } err = gcry_md_setkey(hd, password, strlen(password)); if (err != 0) { gcry_md_close(hd); - return -1; + return (int)err; } gcry_md_write(hd, username, strlen(username)); @@ -365,12 +396,20 @@ static int verify_sha256(void *payload, size_t payload_size, return !!ret; } +#else /* !HAVE_GCRYPT_H */ +static int verify_sha256(void *payload, size_t payload_size, + char const *username, char const *password, + uint8_t hash_provided[32]) { + return ENOTSUP; +} +#endif static int parse_sign_sha256(void *signature, size_t signature_len, void *payload, size_t payload_size, lcc_network_parse_options_t const *opts) { if (opts->password_lookup == NULL) { - /* TODO(octo): print warning */ + /* The sender signed the packet but we can't verify it. Handle it as if it + * were unsigned, i.e. security level NONE. */ return network_parse(payload, payload_size, NONE, opts); } @@ -399,6 +438,7 @@ static int parse_sign_sha256(void *signature, size_t signature_len, return network_parse(payload, payload_size, SIGN, opts); } +#if HAVE_GCRYPT_H static int decrypt_aes256(buffer_t *b, void *iv, size_t iv_size, char const *password) { gcry_cipher_hd_t cipher = NULL; @@ -410,7 +450,7 @@ static int decrypt_aes256(buffer_t *b, void *iv, size_t iv_size, uint8_t pwhash[32] = {0}; gcry_md_hash_buffer(GCRY_MD_SHA256, pwhash, password, strlen(password)); - fprintf(stderr, "sizeof(iv) = %zu\n", sizeof(iv)); + fprintf(stderr, "sizeof(iv) = %" PRIsz "\n", sizeof(iv)); if (gcry_cipher_setkey(cipher, pwhash, sizeof(pwhash)) || gcry_cipher_setiv(cipher, iv, iv_size) || gcry_cipher_decrypt(cipher, b->data, b->len, /* in = */ NULL, @@ -426,7 +466,8 @@ static int decrypt_aes256(buffer_t *b, void *iv, size_t iv_size, static int parse_encrypt_aes256(void *data, size_t data_size, lcc_network_parse_options_t const *opts) { if (opts->password_lookup == NULL) { - /* TODO(octo): print warning */ + /* Without a password source it's (hopefully) impossible to decrypt the + * network packet. */ return ENOENT; } @@ -470,6 +511,12 @@ static int parse_encrypt_aes256(void *data, size_t data_size, return network_parse(b->data, b->len, ENCRYPT, opts); } +#else /* !HAVE_GCRYPT_H */ +static int parse_encrypt_aes256(void *data, size_t data_size, + lcc_network_parse_options_t const *opts) { + return ENOTSUP; +} +#endif static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, lcc_network_parse_options_t const *opts) { @@ -488,7 +535,7 @@ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, if ((sz < 5) || (((size_t)sz - 4) > b->len)) { DEBUG("lcc_network_parse(): invalid 'sz' field: sz = %" PRIu16 - ", b->len = %zu\n", + ", b->len = %" PRIsz "\n", sz, b->len); return EINVAL; } @@ -525,6 +572,8 @@ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, case TYPE_VALUES: { lcc_value_list_t vl = state; if (parse_values(payload, sizeof(payload), &vl)) { + free(vl.values); + free(vl.values_types); DEBUG("lcc_network_parse(): parse_values failed.\n"); return EINVAL; } @@ -578,10 +627,14 @@ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, int lcc_network_parse(void *data, size_t data_size, lcc_network_parse_options_t opts) { if (opts.password_lookup) { +#if HAVE_GCRYPT_H int status; if ((status = init_gcrypt())) { return status; } +#else + return ENOTSUP; +#endif } return network_parse(data, data_size, NONE, &opts);