+#if HAVE_GCRYPT_H
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ char *buffer = *ret_buffer;
+ size_t buffer_len = (size_t) *ret_buffer_len;
+
+ part_signature_sha256_t ps_received;
+ part_signature_sha256_t ps_expected;
+
+ if (se->shared_secret == NULL)
+ {
+ NOTICE ("network plugin: Received signed network packet but can't verify "
+ "it because no shared secret has been configured. Will accept it.");
+ return (0);
+ }
+
+ if (buffer_len < sizeof (ps_received))
+ return (-ENOMEM);
+
+ memcpy (&ps_received, buffer, sizeof (ps_received));
+
+ memset (&ps_expected, 0, sizeof (ps_expected));
+ ps_expected.head.type = htons (TYPE_SIGN_SHA256);
+ ps_expected.head.length = htons (sizeof (ps_expected));
+ sstrncpy (ps_expected.hash, se->shared_secret, sizeof (ps_expected.hash));
+ memcpy (buffer, &ps_expected, sizeof (ps_expected));
+
+ gcry_md_hash_buffer (GCRY_MD_SHA256, ps_expected.hash, buffer, buffer_len);
+
+ *ret_buffer += sizeof (ps_received);
+
+ if (memcmp (ps_received.hash, ps_expected.hash,
+ sizeof (ps_received.hash)) == 0)
+ return (0);
+ else /* hashes do not match. */
+ return (1);
+} /* }}} int parse_part_sign_sha256 */
+/* #endif HAVE_GCRYPT_H */
+
+#else /* if !HAVE_GCRYPT_H */
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ INFO ("network plugin: Received signed packet, but the network "
+ "plugin was not linked with libgcrypt, so I cannot "
+ "verify the signature. The packet will be accepted.");
+ return (0);
+} /* }}} int parse_part_sign_sha256 */
+#endif /* !HAVE_GCRYPT_H */
+
+#if HAVE_GCRYPT_H
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ int orig_buffer_len;
+ part_encryption_aes256_t pea;
+ char hash[28];
+ gcry_error_t err;
+
+ if (se->cypher == NULL)
+ {
+ NOTICE ("network plugin: Unable to decrypt packet, because no cypher "
+ "instance is present.");
+ return (-1);
+ }
+
+ /* Decrypt the packet in-place */
+ err = gcry_cipher_decrypt (se->cypher,
+ buffer + sizeof (pea.head), buffer_len - sizeof (pea.head),
+ /* in = */ NULL, /* in len = */ 0);
+ gcry_cipher_reset (se->cypher);
+ if (err != 0)
+ {
+ ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
+ gcry_strerror (err));
+ return (-1);
+ }
+
+ /* Copy the header information to `pea' */
+ memcpy (&pea, buffer, sizeof (pea));
+ buffer += sizeof (pea);
+ buffer_len -= sizeof (pea);
+
+ /* Check sanity of the original length */
+ orig_buffer_len = ntohs (pea.orig_length);
+ if (orig_buffer_len > buffer_len)
+ {
+ ERROR ("network plugin: Decryption failed: Invalid original length.");
+ return (-1);
+ }
+
+ /* Check hash sum */
+ memset (hash, 0, sizeof (hash));
+ gcry_md_hash_buffer (GCRY_MD_SHA224, hash, buffer, orig_buffer_len);
+
+ if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
+ {
+ ERROR ("network plugin: Decryption failed: Checksum mismatch.");
+ return (-1);
+ }
+
+ /* Update return values */
+ *ret_buffer = buffer;
+ *ret_buffer_len = orig_buffer_len;
+
+ return (0);
+} /* }}} int parse_part_encr_aes256 */
+/* #endif HAVE_GCRYPT_H */
+
+#else /* if !HAVE_GCRYPT_H */
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ INFO ("network plugin: Received encrypted packet, but the network "
+ "plugin was not linked with libgcrypt, so I cannot "
+ "decrypt it. The packet will be discarded.");
+ return (-1);
+} /* }}} int parse_part_encr_aes256 */
+#endif /* !HAVE_GCRYPT_H */
+
+static int parse_packet (receive_list_entry_t *rle) /* {{{ */