struct ev_io io;
ref_entry_t ref;
struct fuzzy_key_stat *key_stat;
+ struct rspamd_fuzzy_cmd_extension *extensions;
guchar nm[rspamd_cryptobox_MAX_NMBYTES];
};
return TRUE;
}
+
+static gboolean
+rspamd_fuzzy_extensions_from_wire (struct fuzzy_session *s, guchar *buf, gsize buflen)
+{
+ struct rspamd_fuzzy_cmd_extension *ext;
+ guchar *storage, *p = buf, *end = buf + buflen;
+ gsize st_len = 0, n_ext = 0;
+
+ /* Read number of extensions to allocate array */
+ while (p < end) {
+ guchar cmd = *p++;
+
+ if (p < end) {
+ if (cmd == RSPAMD_FUZZY_EXT_SOURCE_DOMAIN) {
+ /* Next byte is buf length */
+ guchar dom_len = *p++;
+
+ if (dom_len <= (end - p)) {
+ st_len += dom_len;
+ n_ext ++;
+ }
+ else {
+ /* Truncation */
+ return FALSE;
+ }
+
+ p += dom_len;
+ }
+ else if (cmd == RSPAMD_FUZZY_EXT_SOURCE_IP4) {
+ if (end - p >= sizeof (in_addr_t)) {
+ p += sizeof (in_addr_t);
+ n_ext ++;
+ st_len += sizeof (in_addr_t);
+ }
+ else {
+ /* Truncation */
+ return FALSE;
+ }
+
+ p += sizeof (in_addr_t);
+ }
+ else if (cmd == RSPAMD_FUZZY_EXT_SOURCE_IP6) {
+ if (end - p >= sizeof (in6_addr_t)) {
+ p += sizeof (in6_addr_t);
+ n_ext ++;
+ st_len += sizeof (in6_addr_t);
+ }
+ else {
+ /* Truncation */
+ return FALSE;
+ }
+
+ p += sizeof (in6_addr_t);
+ }
+ }
+ else {
+ /* Truncated extension */
+ return FALSE;
+ }
+ }
+
+ if (n_ext > 0) {
+ p = buf;
+ /*
+ * Memory layout: n_ext of struct rspamd_fuzzy_cmd_extension
+ * payload for each extension in a continious data segment
+ */
+ storage = g_malloc (n_ext * sizeof (struct rspamd_fuzzy_cmd_extension) +
+ st_len);
+
+ guchar *data_buf = storage +
+ n_ext * sizeof (struct rspamd_fuzzy_cmd_extension);
+ ext = (struct rspamd_fuzzy_cmd_extension *)storage;
+
+ /* All validation has been done, so we can just go further */
+ while (p < end) {
+ guchar cmd = *p++;
+
+ if (cmd == RSPAMD_FUZZY_EXT_SOURCE_DOMAIN) {
+ /* Next byte is buf length */
+ guchar dom_len = *p++;
+ guchar *dest = data_buf;
+
+ ext->ext = RSPAMD_FUZZY_EXT_SOURCE_DOMAIN;
+ ext->next = ext + 1;
+ ext->length = dom_len;
+ ext->payload = dest;
+ memcpy (dest, p, dom_len);
+ p += dom_len;
+ data_buf += dom_len;
+ ext = ext->next;
+ }
+ else if (cmd == RSPAMD_FUZZY_EXT_SOURCE_IP4) {
+ guchar *dest = data_buf;
+
+ ext->ext = RSPAMD_FUZZY_EXT_SOURCE_IP4;
+ ext->next = ext + 1;
+ ext->length = sizeof (in_addr_t);
+ ext->payload = dest;
+ memcpy (dest, p, sizeof (in_addr_t));
+ p += sizeof (in_addr_t);
+ data_buf += sizeof (in_addr_t);
+ ext = ext->next;
+ }
+ else if (cmd == RSPAMD_FUZZY_EXT_SOURCE_IP6) {
+ guchar *dest = data_buf;
+
+ ext->ext = RSPAMD_FUZZY_EXT_SOURCE_IP6;
+ ext->next = ext + 1;
+ ext->length = sizeof (in6_addr_t);
+ ext->payload = dest;
+ memcpy (dest, p, sizeof (in6_addr_t));
+ p += sizeof (in_addr_t);
+ data_buf += sizeof (in6_addr_t);
+ ext = ext->next;
+ }
+ }
+
+ /* Last next should be NULL */
+ ext->next = NULL;
+
+ /* Rewind to the begin */
+ ext = (struct rspamd_fuzzy_cmd_extension *)storage;
+ s->extensions = ext;
+ }
+
+ return TRUE;
+}
+
static gboolean
rspamd_fuzzy_cmd_from_wire (guchar *buf, guint buflen, struct fuzzy_session *s)
{
}
}
+ if (buflen > 0) {
+ /* Process possible extensions */
+ if (!rspamd_fuzzy_extensions_from_wire (s, buf, buflen)) {
+ msg_debug ("truncated fuzzy shingles command of size %d received", buflen);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
REF_RELEASE (session->ip_stat);
}
+ if (session->extensions) {
+ g_free (session->extensions);
+ }
+
g_free (session);
}