/**
* collectd - src/libcollectdclient/network_buffer.c
- * Copyright (C) 2010-2012 Florian octo Forster
+ * Copyright (C) 2010-2014 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Florian octo Forster <octo at collectd.org>
**/
-#include "config.h"
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if WIN32
+
+#include <windows.h>
+#include <math.h>
+#include <assert.h>
+
+#else
#include <stdlib.h>
#include <string.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif
+#endif /* !WIN32 */
+
#include "collectd/network_buffer.h"
+#if WIN32
+# include "collectd/win_hmac.h"
+#endif
#define TYPE_HOST 0x0000
#define TYPE_TIME 0x0001
#define PART_SIGNATURE_SHA256_SIZE 36
#define PART_ENCRYPTION_AES256_SIZE 42
+#ifndef ENOTSUP
+# define ENOTSUP -1
+#endif
+
#define ADD_GENERIC(nb,srcptr,size) do { \
assert ((size) <= (nb)->free); \
memcpy ((nb)->ptr, (srcptr), (size)); \
char *username;
char *password;
+#if HAVE_LIBGCRYPT
gcry_cipher_hd_t encr_cypher;
size_t encr_header_len;
char encr_iv[16];
+#endif
};
#define SSTRNCPY(dst,src,sz) do { \
return (result);
need_init = 0;
+#if HAVE_LIBGCRYPT
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
if (!gcry_check_version (GCRYPT_VERSION))
result = 1;
return (1);
+#else
+ return(0);
+#endif
} /* }}} _Bool have_gcrypt */
+#ifndef HAVE_HTONLL
static uint64_t htonll (uint64_t val) /* {{{ */
{
static int config = 0;
return ((((uint64_t) lo) << 32) | ((uint64_t) hi));
} /* }}} uint64_t htonll */
+#endif
static double htond (double val) /* {{{ */
{
return (0);
} /* }}} int nb_add_value_list */
+/* TODO: Add encryption for Windows */
+#if WIN32
+static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
+{
+ BYTE *buffer;
+ DWORD buffer_size;
+
+ BYTE hash[32] = { 0 };
+ DWORD hash_size = sizeof (hash) / sizeof (hash[0]);
+
+ HCRYPTPROV hProv;
+ HCRYPTHASH hHash;
+ HCRYPTKEY hKey;
+ BOOL status;
+
+ /* The type, length and username have already been filled in by
+ * "lcc_network_buffer_initialize". All we do here is calculate the hash over
+ * the username and the data and add the hash value to the buffer. */
+ buffer = (LPBYTE) (nb->buffer + PART_SIGNATURE_SHA256_SIZE);
+ assert (nb->size >= (nb->free + PART_SIGNATURE_SHA256_SIZE));
+ buffer_size = (DWORD) (nb->size - (nb->free + PART_SIGNATURE_SHA256_SIZE));
+
+ status = CryptAcquireContext (&hProv,
+ /* szContainer = */ NULL,
+ /* CSP name = */ NULL,
+ /* provider type = */ PROV_RSA_AES,
+ /* flags = */ CRYPT_VERIFYCONTEXT);
+ if (!status)
+ return (-1);
+
+ status = CreateHMAC (hProv,
+ /* algorithm = */ CALG_SHA_256,
+ /* lpbKey = */ (LPBYTE) nb->password,
+ /* dwKeySize = */ (DWORD) strlen (nb->password),
+ /* dwFlags = */ 0,
+ /* lphHash = */ &hHash,
+ /* lphKey = */ &hKey);
+ if (!status)
+ {
+ CryptReleaseContext (hProv, /* dwFlags = */ 0);
+ return (-1);
+ }
+
+ status = CryptHashData (hHash,
+ /* pbData = */ buffer,
+ /* dwDataSize = */ buffer_size,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ CryptDestroyKey (hKey);
+ CryptReleaseContext (hProv, /* dwFlags = */ 0);
+ return (-1);
+ }
+
+ status = CryptGetHashParam (hHash,
+ /* dwParam = */ HP_HASHVAL,
+ /* pbData = */ hash,
+ /* pwdDataLen = */ &hash_size,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ CryptDestroyKey (hKey);
+ CryptReleaseContext (hProv, /* dwFlags = */ 0);
+ return (-1);
+ }
+
+ assert (((2 * sizeof (uint16_t)) + hash_size) == PART_SIGNATURE_SHA256_SIZE);
+ memcpy (nb->buffer + (2 * sizeof (uint16_t)), hash, hash_size);
+
+ CryptDestroyHash (hHash);
+ CryptDestroyKey (hKey);
+ CryptReleaseContext (hProv, /* dwFlags = */ 0);
+ return (0);
+} /* }}} int nb_add_signature */
+#elif HAVE_LIBGCRYPT
static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
{
char *buffer;
return (0);
} /* }}} int nb_add_encryption */
+#endif
/*
* Public functions
nb->ptr = nb->buffer;
nb->free = nb->size;
+#if HAVE_LIBGCRYPT
if (nb->seclevel == SIGN)
{
size_t username_len;
ADD_GENERIC (nb, hash, sizeof (hash));
assert ((nb->encr_header_len + nb->free) == nb->size);
}
+#endif
return (0);
} /* }}} int lcc_network_buffer_initialize */
if (nb == NULL)
return (EINVAL);
+#if WIN32
+ if (nb->seclevel == SIGN)
+ nb_add_signature (nb);
+#elif HAVE_LIBGCRYPT
if (nb->seclevel == SIGN)
nb_add_signature (nb);
else if (nb->seclevel == ENCRYPT)
nb_add_encryption (nb);
+#endif
return (0);
} /* }}} int lcc_network_buffer_finalize */