2 * collectd - src/libcollectdclient/network_buffer.c
3 * Copyright (C) 2010-2014 Florian octo Forster
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Florian octo Forster <octo at collectd.org>
44 #include <arpa/inet.h> /* htons */
50 # if defined __APPLE__
51 /* default xcode compiler throws warnings even when deprecated functionality
52 * is not used. -Werror breaks the build because of erroneous warnings.
53 * http://stackoverflow.com/questions/10556299/compiler-warnings-with-libgcrypt-v1-5-0/12830209#12830209
55 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 /* FreeBSD's copy of libgcrypt extends the existing GCRYPT_NO_DEPRECATED
58 * to properly hide all deprecated functionality.
59 * http://svnweb.freebsd.org/ports/head/security/libgcrypt/files/patch-src__gcrypt.h.in
61 # define GCRYPT_NO_DEPRECATED
63 # if defined __APPLE__
64 /* Re enable deprecation warnings */
65 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
67 GCRY_THREAD_OPTION_PTHREAD_IMPL;
72 #include "collectd/network_buffer.h"
74 # include "collectd/win_hmac.h"
77 #define TYPE_HOST 0x0000
78 #define TYPE_TIME 0x0001
79 #define TYPE_TIME_HR 0x0008
80 #define TYPE_PLUGIN 0x0002
81 #define TYPE_PLUGIN_INSTANCE 0x0003
82 #define TYPE_TYPE 0x0004
83 #define TYPE_TYPE_INSTANCE 0x0005
84 #define TYPE_VALUES 0x0006
85 #define TYPE_INTERVAL 0x0007
86 #define TYPE_INTERVAL_HR 0x0009
88 /* Types to transmit notifications */
89 #define TYPE_MESSAGE 0x0100
90 #define TYPE_SEVERITY 0x0101
92 #define TYPE_SIGN_SHA256 0x0200
93 #define TYPE_ENCR_AES256 0x0210
95 #define PART_SIGNATURE_SHA256_SIZE 36
96 #define PART_ENCRYPTION_AES256_SIZE 42
102 #define ADD_GENERIC(nb,srcptr,size) do { \
103 assert ((size) <= (nb)->free); \
104 memcpy ((nb)->ptr, (srcptr), (size)); \
105 (nb)->ptr += (size); \
106 (nb)->free -= (size); \
109 #define ADD_STATIC(nb,var) \
110 ADD_GENERIC(nb,&(var),sizeof(var));
115 struct lcc_network_buffer_s
120 lcc_value_list_t state;
124 lcc_security_level_t seclevel;
130 size_t encr_header_len;
133 gcry_cipher_hd_t encr_cypher;
134 size_t encr_header_len;
139 #define SSTRNCPY(dst,src,sz) do { \
140 strncpy ((dst), (src), (sz)); \
141 (dst)[(sz) - 1] = 0; \
147 static _Bool have_gcrypt (void) /* {{{ */
149 static _Bool result = 0;
150 static _Bool need_init = 1;
157 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
159 if (!gcry_check_version (GCRYPT_VERSION))
162 gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
163 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
170 } /* }}} _Bool have_gcrypt */
173 static uint64_t htonll (uint64_t val) /* {{{ */
175 static int config = 0;
183 uint16_t n = htons (h);
194 hi = (uint32_t) (val >> 32);
195 lo = (uint32_t) (val & 0x00000000FFFFFFFF);
200 return ((((uint64_t) lo) << 32) | ((uint64_t) hi));
201 } /* }}} uint64_t htonll */
204 static double htond (double val) /* {{{ */
206 static int config = 0;
208 union { uint8_t byte[8]; double floating; } in;
209 union { uint8_t byte[8]; double floating; } out;
213 double d = 8.642135e130;
218 if ((c[0] == 0x2f) && (c[1] == 0x25)
219 && (c[2] == 0xc0) && (c[3] == 0xc7)
220 && (c[4] == 0x43) && (c[5] == 0x2b)
221 && (c[6] == 0x1f) && (c[7] == 0x5b))
222 config = 1; /* need nothing */
223 else if ((c[7] == 0x2f) && (c[6] == 0x25)
224 && (c[5] == 0xc0) && (c[4] == 0xc7)
225 && (c[3] == 0x43) && (c[2] == 0x2b)
226 && (c[1] == 0x1f) && (c[0] == 0x5b))
227 config = 2; /* endian flip */
228 else if ((c[4] == 0x2f) && (c[5] == 0x25)
229 && (c[6] == 0xc0) && (c[7] == 0xc7)
230 && (c[0] == 0x43) && (c[1] == 0x2b)
231 && (c[2] == 0x1f) && (c[3] == 0x5b))
232 config = 3; /* int swap */
239 out.byte[0] = out.byte[1] = out.byte[2] = out.byte[3] = 0x00;
240 out.byte[4] = out.byte[5] = 0x00;
243 return (out.floating);
245 else if (config == 1)
247 else if (config == 2)
250 out.byte[0] = in.byte[7];
251 out.byte[1] = in.byte[6];
252 out.byte[2] = in.byte[5];
253 out.byte[3] = in.byte[4];
254 out.byte[4] = in.byte[3];
255 out.byte[5] = in.byte[2];
256 out.byte[6] = in.byte[1];
257 out.byte[7] = in.byte[0];
258 return (out.floating);
260 else if (config == 3)
263 out.byte[0] = in.byte[4];
264 out.byte[1] = in.byte[5];
265 out.byte[2] = in.byte[6];
266 out.byte[3] = in.byte[7];
267 out.byte[4] = in.byte[0];
268 out.byte[5] = in.byte[1];
269 out.byte[6] = in.byte[2];
270 out.byte[7] = in.byte[3];
271 return (out.floating);
275 /* If in doubt, just copy the value back to the caller. */
278 } /* }}} double htond */
280 static int nb_add_values (char **ret_buffer, /* {{{ */
281 size_t *ret_buffer_len,
282 const lcc_value_list_t *vl)
289 uint16_t pkg_num_values;
290 uint8_t pkg_values_types[vl->values_len];
291 value_t pkg_values[vl->values_len];
296 packet_len = sizeof (pkg_type) + sizeof (pkg_length)
297 + sizeof (pkg_num_values)
298 + sizeof (pkg_values_types)
299 + sizeof (pkg_values);
301 if (*ret_buffer_len < packet_len)
304 pkg_type = htons (TYPE_VALUES);
305 pkg_length = htons ((uint16_t) packet_len);
306 pkg_num_values = htons ((uint16_t) vl->values_len);
308 for (i = 0; i < vl->values_len; i++)
310 pkg_values_types[i] = (uint8_t) vl->values_types[i];
311 switch (vl->values_types[i])
313 case LCC_TYPE_COUNTER:
314 pkg_values[i].counter = (counter_t) htonll (vl->values[i].counter);
318 pkg_values[i].gauge = (gauge_t) htond (vl->values[i].gauge);
321 case LCC_TYPE_DERIVE:
322 pkg_values[i].derive = (derive_t) htonll (vl->values[i].derive);
325 case LCC_TYPE_ABSOLUTE:
326 pkg_values[i].absolute = (absolute_t) htonll (vl->values[i].absolute);
331 } /* switch (vl->values_types[i]) */
332 } /* for (vl->values_len) */
335 * Use `memcpy' to write everything to the buffer, because the pointer
336 * may be unaligned and some architectures, such as SPARC, can't handle
339 packet_ptr = *ret_buffer;
341 memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
342 offset += sizeof (pkg_type);
343 memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
344 offset += sizeof (pkg_length);
345 memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
346 offset += sizeof (pkg_num_values);
347 memcpy (packet_ptr + offset, pkg_values_types, sizeof (pkg_values_types));
348 offset += sizeof (pkg_values_types);
349 memcpy (packet_ptr + offset, pkg_values, sizeof (pkg_values));
350 offset += sizeof (pkg_values);
352 assert (offset == packet_len);
354 *ret_buffer = packet_ptr + packet_len;
355 *ret_buffer_len -= packet_len;
357 } /* }}} int nb_add_values */
359 static int nb_add_number (char **ret_buffer, /* {{{ */
360 size_t *ret_buffer_len,
361 uint16_t type, uint64_t value)
372 packet_len = sizeof (pkg_type)
373 + sizeof (pkg_length)
374 + sizeof (pkg_value);
376 if (*ret_buffer_len < packet_len)
379 pkg_type = htons (type);
380 pkg_length = htons ((uint16_t) packet_len);
381 pkg_value = htonll (value);
383 packet_ptr = *ret_buffer;
385 memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
386 offset += sizeof (pkg_type);
387 memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
388 offset += sizeof (pkg_length);
389 memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
390 offset += sizeof (pkg_value);
392 assert (offset == packet_len);
394 *ret_buffer = packet_ptr + packet_len;
395 *ret_buffer_len -= packet_len;
397 } /* }}} int nb_add_number */
399 static int nb_add_time (char **ret_buffer, /* {{{ */
400 size_t *ret_buffer_len,
401 uint16_t type, double value)
403 /* Convert to collectd's "cdtime" representation. */
404 uint64_t cdtime_value = (uint64_t) (value * 1073741824.0);
405 return (nb_add_number (ret_buffer, ret_buffer_len, type, cdtime_value));
406 } /* }}} int nb_add_time */
408 static int nb_add_string (char **ret_buffer, /* {{{ */
409 size_t *ret_buffer_len,
410 uint16_t type, const char *str, size_t str_len)
420 packet_len = sizeof (pkg_type)
421 + sizeof (pkg_length)
423 if (*ret_buffer_len < packet_len)
426 pkg_type = htons (type);
427 pkg_length = htons ((uint16_t) packet_len);
429 packet_ptr = *ret_buffer;
431 memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
432 offset += sizeof (pkg_type);
433 memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
434 offset += sizeof (pkg_length);
435 memcpy (packet_ptr + offset, str, str_len);
437 memset (packet_ptr + offset, 0, 1);
440 assert (offset == packet_len);
442 *ret_buffer = packet_ptr + packet_len;
443 *ret_buffer_len -= packet_len;
445 } /* }}} int nb_add_string */
447 static int nb_add_value_list (lcc_network_buffer_t *nb, /* {{{ */
448 const lcc_value_list_t *vl)
450 char *buffer = nb->ptr;
451 size_t buffer_size = nb->free;
453 const lcc_identifier_t *ident_src;
454 lcc_identifier_t *ident_dst;
456 ident_src = &vl->identifier;
457 ident_dst = &nb->state.identifier;
459 if (strcmp (ident_dst->host, ident_src->host) != 0)
461 if (nb_add_string (&buffer, &buffer_size, TYPE_HOST,
462 ident_src->host, strlen (ident_src->host)) != 0)
464 SSTRNCPY (ident_dst->host, ident_src->host, sizeof (ident_dst->host));
467 if (strcmp (ident_dst->plugin, ident_src->plugin) != 0)
469 if (nb_add_string (&buffer, &buffer_size, TYPE_PLUGIN,
470 ident_src->plugin, strlen (ident_src->plugin)) != 0)
472 SSTRNCPY (ident_dst->plugin, ident_src->plugin,
473 sizeof (ident_dst->plugin));
476 if (strcmp (ident_dst->plugin_instance,
477 ident_src->plugin_instance) != 0)
479 if (nb_add_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
480 ident_src->plugin_instance,
481 strlen (ident_src->plugin_instance)) != 0)
483 SSTRNCPY (ident_dst->plugin_instance, ident_src->plugin_instance,
484 sizeof (ident_dst->plugin_instance));
487 if (strcmp (ident_dst->type, ident_src->type) != 0)
489 if (nb_add_string (&buffer, &buffer_size, TYPE_TYPE,
490 ident_src->type, strlen (ident_src->type)) != 0)
492 SSTRNCPY (ident_dst->type, ident_src->type, sizeof (ident_dst->type));
495 if (strcmp (ident_dst->type_instance,
496 ident_src->type_instance) != 0)
498 if (nb_add_string (&buffer, &buffer_size, TYPE_TYPE_INSTANCE,
499 ident_src->type_instance,
500 strlen (ident_src->type_instance)) != 0)
502 SSTRNCPY (ident_dst->type_instance, ident_src->type_instance,
503 sizeof (ident_dst->type_instance));
506 if (nb->state.time != vl->time)
508 if (nb_add_time (&buffer, &buffer_size, TYPE_TIME_HR, vl->time))
510 nb->state.time = vl->time;
513 if (nb->state.interval != vl->interval)
515 if (nb_add_time (&buffer, &buffer_size, TYPE_INTERVAL_HR, vl->interval))
517 nb->state.interval = vl->interval;
520 if (nb_add_values (&buffer, &buffer_size, vl) != 0)
524 nb->free = buffer_size;
526 } /* }}} int nb_add_value_list */
529 static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
534 BYTE hash[32] = { 0 };
535 DWORD hash_size = sizeof (hash) / sizeof (hash[0]);
541 /* The type, length and username have already been filled in by
542 * "lcc_network_buffer_initialize". All we do here is calculate the hash over
543 * the username and the data and add the hash value to the buffer. */
544 buffer = (LPBYTE) (nb->buffer + PART_SIGNATURE_SHA256_SIZE);
545 assert (nb->size >= (nb->free + PART_SIGNATURE_SHA256_SIZE));
546 buffer_size = (DWORD) (nb->size - (nb->free + PART_SIGNATURE_SHA256_SIZE));
550 status = CryptAcquireContext (&nb->hProv,
551 /* szContainer = */ NULL,
552 /* CSP name = */ NULL,
553 /* provider type = */ PROV_RSA_AES,
554 /* flags = */ CRYPT_VERIFYCONTEXT);
559 status = CreateHMAC (nb->hProv,
560 /* algorithm = */ CALG_SHA_256,
561 /* lpbKey = */ (LPBYTE) nb->password,
562 /* dwKeySize = */ (DWORD) strlen (nb->password),
564 /* lphHash = */ &hHash,
565 /* lphKey = */ &hKey);
569 status = CryptHashData (hHash,
570 /* pbData = */ buffer,
571 /* dwDataSize = */ buffer_size,
575 CryptDestroyHash (hHash);
576 CryptDestroyKey (hKey);
580 status = CryptGetHashParam (hHash,
581 /* dwParam = */ HP_HASHVAL,
583 /* pwdDataLen = */ &hash_size,
587 CryptDestroyHash (hHash);
588 CryptDestroyKey (hKey);
592 assert (((2 * sizeof (uint16_t)) + hash_size) == PART_SIGNATURE_SHA256_SIZE);
593 memcpy (nb->buffer + (2 * sizeof (uint16_t)), hash, hash_size);
595 CryptDestroyHash (hHash);
596 CryptDestroyKey (hKey);
598 } /* }}} int nb_add_signature */
600 static int nb_key_from_password (HCRYPTPROV hProv, /* {{{ */
601 LPCSTR pbPassword, LPBYTE pbIv, HCRYPTKEY *phKey)
603 HCRYPTHASH hHash = 0;
612 DWORD cypherMode = CRYPT_MODE_OFB;
616 memset (&keyData, 0, sizeof (keyData));
617 keyData.pks.bType = PLAINTEXTKEYBLOB;
618 keyData.pks.bVersion = CUR_BLOB_VERSION;
619 keyData.pks.reserved = 0;
620 keyData.dwKeySize = 32;
622 status = CryptCreateHash (hProv,
623 /* algorithm = */ CALG_SHA_256,
626 /* out phHash = */ &hHash);
630 status = CryptHashData (hHash,
631 /* pbData = */ (void *) pbPassword,
632 /* dwDataSize = */ strlen (pbPassword),
636 CryptDestroyHash (hHash);
640 status = CryptGetHashParam (hHash,
641 /* dwParam = */ HP_HASHVAL,
642 /* pbData = */ keyData.pbKey,
643 /* pwdDataLen = */ &keyData.dwKeySize,
647 CryptDestroyHash (hHash);
650 CryptDestroyHash (hHash);
651 assert (keyData.dwKeySize == 32);
653 status = CryptImportKey (hProv,
654 /* pbData = */ (void *) &keyData,
655 /* dwDataLen = */ sizeof (keyData),
658 /* phKey = */ &hKey);
662 status = CryptSetKeyParam (hKey,
663 /* dwParam = */ KP_MODE,
664 /* pbData = */ (void *) &cypherMode,
668 CryptDestroyKey (hKey);
672 status = CryptSetKeyParam (hKey,
673 /* dwParam = */ KP_IV,
674 /* pbData = */ (void *) pbIv,
678 CryptDestroyKey (hKey);
684 } /* }}} nb_key_from_password */
686 static int nb_add_encryption (lcc_network_buffer_t *nb) /* {{{ */
688 HCRYPTHASH hHash = 0;
690 DWORD package_length;
691 BYTE *encr_ptr; /* pointer to data being encrypted */
694 BYTE *hash_data_ptr; /* pointer to data being hashed */
695 DWORD hash_data_size;
696 DWORD hash_code_size = 20;
701 /* Fill in the package length */
702 package_length = nb->size - nb->free;
703 pkg_length = htons ((uint16_t) package_length);
704 memcpy (nb->buffer + 2, &pkg_length, sizeof (pkg_length));
706 /* Calculate what to hash */
707 hash_data_ptr = (BYTE *) (nb->buffer + PART_ENCRYPTION_AES256_SIZE);
708 hash_data_size = package_length - nb->encr_header_len;
710 /* Calculate what to encrypt */
711 encr_ptr = hash_data_ptr - hash_code_size;
712 encr_size = hash_data_size + hash_code_size;
716 status = CryptAcquireContext (&nb->hProv,
717 /* szContainer = */ NULL,
718 /* CSP name = */ NULL,
719 /* provider type = */ PROV_RSA_AES,
720 /* flags = */ CRYPT_VERIFYCONTEXT);
725 status = CryptCreateHash (nb->hProv,
726 /* algorithm = */ CALG_SHA1,
729 /* out phHash = */ &hHash);
733 status = CryptHashData (hHash,
734 /* pbData = */ hash_data_ptr,
735 /* dwDataSize = */ hash_data_size,
739 CryptDestroyHash (hHash);
743 status = CryptGetHashParam (hHash,
744 /* dwParam = */ HP_HASHVAL,
745 /* pbData = */ (void *) encr_ptr,
746 /* pwdDataLen = */ &hash_code_size,
750 CryptDestroyHash (hHash);
753 CryptDestroyHash (hHash);
755 status = nb_key_from_password (nb->hProv,
756 nb->password, nb->encr_iv, &hKey);
760 status = CryptEncrypt (hKey,
762 /* Final = */ 1, /* last call to CryptEncrypt() */
764 /* pbData = */ encr_ptr,
765 /* pdwDataLen = */ &encr_size,
766 /* dwBufLen = */ encr_size);
769 CryptDestroyKey (hKey);
773 CryptDestroyKey (hKey);
775 } /* }}} int nb_add_encryption */
777 static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
785 const size_t hash_length = 32;
787 /* The type, length and username have already been filled in by
788 * "lcc_network_buffer_initialize". All we do here is calculate the hash over
789 * the username and the data and add the hash value to the buffer. */
791 buffer = nb->buffer + PART_SIGNATURE_SHA256_SIZE;
792 assert (nb->size >= (nb->free + PART_SIGNATURE_SHA256_SIZE));
793 buffer_size = nb->size - (nb->free + PART_SIGNATURE_SHA256_SIZE);
796 err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
800 assert (nb->password != NULL);
801 err = gcry_md_setkey (hd, nb->password, strlen (nb->password));
808 gcry_md_write (hd, buffer, buffer_size);
809 hash = gcry_md_read (hd, GCRY_MD_SHA256);
816 assert (((2 * sizeof (uint16_t)) + hash_length) == PART_SIGNATURE_SHA256_SIZE);
817 memcpy (nb->buffer + (2 * sizeof (uint16_t)), hash, hash_length);
821 } /* }}} int nb_add_signature */
823 static int nb_add_encryption (lcc_network_buffer_t *nb) /* {{{ */
825 size_t package_length;
826 char *encr_ptr; /* pointer to data being encrypted */
829 char *hash_ptr; /* pointer to data being hashed */
836 /* Fill in the package length */
837 package_length = nb->size - nb->free;
838 pkg_length = htons ((uint16_t) package_length);
839 memcpy (nb->buffer + 2, &pkg_length, sizeof (pkg_length));
841 /* Calculate what to hash */
842 hash_ptr = nb->buffer + PART_ENCRYPTION_AES256_SIZE;
843 hash_size = package_length - nb->encr_header_len;
845 /* Calculate what to encrypt */
846 encr_ptr = hash_ptr - sizeof (hash);
847 encr_size = hash_size + sizeof (hash);
849 /* Calculate the SHA-1 hash */
850 gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash_ptr, hash_size);
851 memcpy (encr_ptr, hash, sizeof (hash));
853 if (nb->encr_cypher == NULL)
855 unsigned char password_hash[32];
857 err = gcry_cipher_open (&nb->encr_cypher,
858 GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, /* flags = */ 0);
862 /* Calculate our 256bit key used for AES */
863 gcry_md_hash_buffer (GCRY_MD_SHA256, password_hash,
864 nb->password, strlen (nb->password));
866 err = gcry_cipher_setkey (nb->encr_cypher,
867 password_hash, sizeof (password_hash));
870 gcry_cipher_close (nb->encr_cypher);
871 nb->encr_cypher = NULL;
875 else /* if (nb->encr_cypher != NULL) */
877 gcry_cipher_reset (nb->encr_cypher);
880 /* Set the initialization vector */
881 err = gcry_cipher_setiv (nb->encr_cypher,
882 nb->encr_iv, sizeof (nb->encr_iv));
885 gcry_cipher_close (nb->encr_cypher);
886 nb->encr_cypher = NULL;
890 /* Encrypt the buffer in-place */
891 err = gcry_cipher_encrypt (nb->encr_cypher,
893 /* in = */ NULL, /* in len = */ 0);
896 gcry_cipher_close (nb->encr_cypher);
897 nb->encr_cypher = NULL;
902 } /* }}} int nb_add_encryption */
908 lcc_network_buffer_t *lcc_network_buffer_create (size_t size) /* {{{ */
910 lcc_network_buffer_t *nb;
913 size = LCC_NETWORK_BUFFER_SIZE_DEFAULT;
921 nb = malloc (sizeof (*nb));
924 memset (nb, 0, sizeof (*nb));
927 nb->buffer = malloc (nb->size);
928 if (nb->buffer == NULL)
933 memset (nb->buffer, 0, nb->size);
935 nb->ptr = nb->buffer;
943 } /* }}} lcc_network_buffer_t *lcc_network_buffer_create */
945 void lcc_network_buffer_destroy (lcc_network_buffer_t *nb) /* {{{ */
952 } /* }}} void lcc_network_buffer_destroy */
954 int lcc_network_buffer_set_security_level (lcc_network_buffer_t *nb, /* {{{ */
955 lcc_security_level_t level,
956 const char *username, const char *password)
968 lcc_network_buffer_initialize (nb);
975 username_copy = strdup (username);
976 password_copy = strdup (password);
977 if ((username_copy == NULL) || (password_copy == NULL))
979 free (username_copy);
980 free (password_copy);
986 nb->username = username_copy;
987 nb->password = password_copy;
988 nb->seclevel = level;
990 lcc_network_buffer_initialize (nb);
992 } /* }}} int lcc_network_buffer_set_security_level */
994 int lcc_network_buffer_initialize (lcc_network_buffer_t *nb) /* {{{ */
999 memset (nb->buffer, 0, nb->size);
1000 memset (&nb->state, 0, sizeof (nb->state));
1001 nb->ptr = nb->buffer;
1002 nb->free = nb->size;
1005 if (nb->seclevel == SIGN)
1007 size_t username_len;
1008 uint16_t pkg_type = htons (TYPE_SIGN_SHA256);
1009 uint16_t pkg_length = PART_SIGNATURE_SHA256_SIZE;
1011 assert (nb->username != NULL);
1012 username_len = strlen (nb->username);
1013 pkg_length = htons (pkg_length + ((uint16_t) username_len));
1015 /* Fill in everything but the hash value here. */
1016 memcpy (nb->ptr, &pkg_type, sizeof (pkg_type));
1017 memcpy (nb->ptr + sizeof (pkg_type), &pkg_length, sizeof (pkg_length));
1018 nb->ptr += PART_SIGNATURE_SHA256_SIZE;
1019 nb->free -= PART_SIGNATURE_SHA256_SIZE;
1021 memcpy (nb->ptr, nb->username, username_len);
1022 nb->ptr += username_len;
1023 nb->free -= username_len;
1025 else if (nb->seclevel == ENCRYPT)
1027 size_t username_length = strlen (nb->username);
1028 uint16_t pkg_type = htons (TYPE_ENCR_AES256);
1029 uint16_t pkg_length = 0; /* Filled in in finalize. */
1030 uint16_t pkg_user_len = htons ((uint16_t) username_length);
1033 nb->encr_header_len = username_length;
1034 nb->encr_header_len += PART_ENCRYPTION_AES256_SIZE;
1036 gcry_randomize ((void *) &nb->encr_iv, sizeof (nb->encr_iv),
1037 GCRY_STRONG_RANDOM);
1039 /* Filled in in finalize. */
1040 memset (hash, 0, sizeof (hash));
1042 ADD_STATIC (nb, pkg_type);
1043 ADD_STATIC (nb, pkg_length);
1044 ADD_STATIC (nb, pkg_user_len);
1045 ADD_GENERIC (nb, nb->username, username_length);
1046 ADD_GENERIC (nb, nb->encr_iv, sizeof (nb->encr_iv));
1047 ADD_GENERIC (nb, hash, sizeof (hash));
1048 assert ((nb->encr_header_len + nb->free) == nb->size);
1053 } /* }}} int lcc_network_buffer_initialize */
1055 int lcc_network_buffer_finalize (lcc_network_buffer_t *nb) /* {{{ */
1060 #if WIN32 || HAVE_LIBGCRYPT
1061 if (nb->seclevel == SIGN)
1062 nb_add_signature (nb);
1063 else if (nb->seclevel == ENCRYPT)
1064 nb_add_encryption (nb);
1068 } /* }}} int lcc_network_buffer_finalize */
1070 int lcc_network_buffer_add_value (lcc_network_buffer_t *nb, /* {{{ */
1071 const lcc_value_list_t *vl)
1075 if ((nb == NULL) || (vl == NULL))
1078 status = nb_add_value_list (nb, vl);
1080 } /* }}} int lcc_network_buffer_add_value */
1082 int lcc_network_buffer_get (lcc_network_buffer_t *nb, /* {{{ */
1083 void *buffer, size_t *buffer_size)
1086 size_t sz_available;
1088 if ((nb == NULL) || (buffer_size == NULL))
1091 assert (nb->size >= nb->free);
1092 sz_required = nb->size - nb->free;
1093 sz_available = *buffer_size;
1095 *buffer_size = sz_required;
1097 memcpy (buffer, nb->buffer,
1098 (sz_available < sz_required) ? sz_available : sz_required);
1101 } /* }}} int lcc_network_buffer_get */
1103 /* vim: set sw=2 sts=2 et fdm=marker : */