Esempio n. 1
0
int send_packet(const byte buffer[], byte len, void (*send_cb)(byte[], byte len)) {
    int byte_counter=0;
    byte *payload_buf = (byte *)malloc(len*2);
    byte actual_length_payload = escape_buffer(buffer, payload_buf, len);
    byte actual_length_buf[2];
    // we also need to escape the length byte
    byte actual_length_length = escape_buffer(&len, actual_length_buf, 1);
    send_cb(&start_byte, 1);
    send_cb(actual_length_buf, actual_length_length);
    send_cb(payload_buf, actual_length_payload);
    send_cb(&stop_byte, 1);
    free(payload_buf);
    byte_counter += (1 + 1 + actual_length_length + actual_length_payload);
    return byte_counter;
}
Esempio n. 2
0
int botnet_send_file(BOTNET_REC *botnet, const char *target, const char *fname)
{
	GNode *node;
	GString *str;
	char buffer[1024];
	int f, len;

	node = bot_find_path(botnet, target);
	if (node == NULL) {
		g_warning("Can't find route for target %s", target);
		return FALSE;
	}

	f = open(fname, O_RDONLY);
	if (f == -1) return FALSE;

	str = g_string_new(NULL);

	g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, g_basename(fname));
	bot_send_cmd(node->data, str->str);

	while ((len = read(f, buffer, sizeof(buffer)/2-2)) > 0) {
		escape_buffer(buffer, len);

		g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, buffer);
		bot_send_cmd(node->data, str->str);
	}

	g_string_sprintf(str, "%s %s FILE", botnet->nick, target);
	bot_send_cmd(node->data, str->str);
	g_string_free(str, TRUE);

	close(f);
	return TRUE;
}
Esempio n. 3
0
static void
handle_vmsg_time_sync_reply(const struct gnutella_header *header,
    const char *data, size_t size)
{
  if (size < 17) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    bool used_ntp = data[8] & 0x1;
    char buf[32], *p;

    printf("NTP: %s\n", used_ntp ? "yes" : "no");

    p = print_iso8601_date(buf, sizeof buf, peek_be32(&header->guid.data[0]));
    *p = '\0';
    printf("T1: %s (%lu us)\n",
      buf, (unsigned long) peek_be32(&header->guid.data[4]));

    p = print_iso8601_date(buf, sizeof buf, peek_be32(&data[9]));
    *p = '\0';
    printf("T2: %s (%lu us)\n",
      buf, (unsigned long) peek_be32(&data[13]));

    p = print_iso8601_date(buf, sizeof buf, peek_be32(&header->guid.data[8]));
    *p = '\0';
    printf("T3: %s (%lu us)\n",
      buf, (unsigned long) peek_be32(&header->guid.data[12]));

    if (size > 17) {
      handle_extension(&data[17], size - 17);
    }
  }
}
Esempio n. 4
0
static void
handle_extension(const char * const data, const size_t size)
{
  if (size > 0) {
    const char *g_ptr;

    g_ptr = memchr(data, GGEP_MAGIC, size);
    if (g_ptr) {
      size_t g_len = &data[size] - g_ptr;
      handle_ggep(g_ptr, g_len);
    }
    printf("Raw data: \"%s\"\n", escape_buffer(data, size));
  }
}
Esempio n. 5
0
static void
handle_vmsg_oob_reply(const struct gnutella_header *header,
  const char *data, size_t size)
{
  (void) header;

  if (size < 9) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    printf("Hits: %u\n", (uint8_t) data[8]);
    if (size > 9) {
      handle_extension(&data[9], size - 9);
    }
  }
}
Esempio n. 6
0
static void
handle_pong(const char * const data, const size_t size)
{
  if (size < 14) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    printf("Source: %s\n",
      net_addr_port_to_string(net_addr_peek_ipv4(&data[2]), peek_le16(data)));
    printf("Files:  %lu\n", (unsigned long) peek_le32(&data[6]));
    printf("Volume: %lu KiB\n", (unsigned long) peek_le32(&data[10]));

    if (size > 14) {
      handle_extension(&data[14], size - 14);
    }
  }
}
Esempio n. 7
0
static void 
handle_ggep_h(const char *data, size_t size)
{
  static const struct {
    const char * const prefix;
    const uint8_t base;
  } hashes[] = {
    { NULL, 0 },
    { "urn:sha1:", 32 },
    { "urn:bitprint:", 32 },
    { "urn:md5:", 64 },
    { "urn:uuid:", 16 },
    { "urn:md4:", 64 },
  };
  unsigned char h;
  const char *prefix;
  uint8_t base;

  if (size < 1) {
    printf(" <No payload>");
    return;
  }
  
  h = data[0];
  if (h < ARRAY_LEN(hashes)) {
    prefix = hashes[h].prefix;
    base = hashes[h].base;
  } else {
    prefix = NULL;
    base = 0;
  }

  if (prefix && base) {
    printf(": %s", prefix);

    if (32 == base) {
      char base32[256];
      size_t base32_len;

      base32_len = base32_encode(base32, sizeof base32, &data[1], size - 1);
      base32[base32_len] = '\0';
      printf("%s", base32);
    }
  } else {
    printf(": <%u> \"%s\"", h, escape_buffer(&data[1], size - 1));
  }
}
Esempio n. 8
0
static void
handle_vmsg_time_sync_request(const struct gnutella_header *header,
  const char *data, size_t size)
{
  (void) header;

  if (size < 9) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    bool used_ntp = data[8] & 0x1;

    printf("NTP: %s\n", used_ntp ? "yes" : "no");

    if (size > 9) {
      handle_extension(&data[9], size - 9);
    }
  }
}
Esempio n. 9
0
static void
handle_vmsg_priv(const struct gnutella_header *header,
    const char *data, size_t size)
{
  if (size < 8) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    char vendor[32], *p;
    size_t vendor_size = sizeof vendor;
    struct vmsg_head vh;
    unsigned i;

    p = append_escaped_chars(vendor, &vendor_size, data, 4);
    *p = '\0';

    vh.vendor = peek_be32(&data[0]);
    vh.selector = peek_le16(&data[4]);
    vh.version = peek_le16(&data[6]);
    printf("%s/%uv%u", vendor, vh.selector, vh.version);

    for (i = 0; i < ARRAY_LEN(vmsg_table); i++) {
      if (
        vmsg_table[i].vendor == vh.vendor &&
        vmsg_table[i].selector == vh.selector &&
        vmsg_table[i].version == vh.version
      ) {
        printf(" %s\n", vmsg_table[i].name);
        vmsg_table[i].handler(header, data, size);
        break;
      }
    }

    if (ARRAY_LEN(vmsg_table) == i) {
      printf("\n");
      handle_extension(&data[8], size - 8);
    }
  }
}
Esempio n. 10
0
static void
handle_query(const struct gnutella_header *header,
  const char * const data, const size_t size)
{
  const char *end;

  if (size < 2) {
    printf("Too short:  %s\n", escape_buffer(data, size));
  } else {
    uint16_t flags;
    int swapped = 0;

    flags = peek_be16(data);
    if (!(flags & QUERY_F_MARK)) {
        uint16_t mask = QUERY_F_MARK | QUERY_F_GGEP_H | QUERY_F_LEAF_GUIDED;
        uint16_t reversed;

        /* Try to decode endian swapped flags as emitted by RAZA */
        reversed = peek_le16(data);
        if ((reversed & mask) == mask) {
          swapped = 1;
          flags = reversed;
        }
    }
    if (flags & QUERY_F_MARK) {
      int is_firewalled = flags & QUERY_F_FIREWALLED;
      int want_xml = flags & QUERY_F_WANT_XML;
      int leaf_guided = flags & QUERY_F_LEAF_GUIDED;
      int ggep_h = flags & QUERY_F_GGEP_H;
      int is_oob = flags & QUERY_F_OOB;
      int rudp_supp = flags & QUERY_F_RUDP;
      int bit8 = flags & QUERY_F_BIT8;
      
      printf("Flags:  %s%s%s%s%s%s%s%s\n"
        , is_firewalled ? "firewalled " : ""
        , want_xml ? "XML " : ""
        , leaf_guided ? "leaf-guided " : ""
        , ggep_h ? "GGEP/H " : ""
        , is_oob ? "OOB " : ""
        , rudp_supp ? "RUDP " : ""
        , bit8 ? "bit8 " : ""
        , swapped ? "[SWAPPED]" : ""
      );
      if (is_oob) {
        printf("OOB address:  %s\n",
          net_addr_port_to_string(net_addr_peek_ipv4(&header->guid.data[0]),
            peek_le16(&header->guid.data[13]))
        );
      }
    } else {
      printf("Flags:  0x%04X\n", flags);
    }

    end = memchr(&data[2], '\0', size - 2);
    if (end) {
      end++;
    } else {
      end = &data[size];
    }
    printf("Query:  \"%s\"\n", escape_buffer(&data[2], (end - &data[2]) - 1));

    if (&data[size] != end) {
      size_t ext_len;
      
      ext_len = &data[size] - end;
      if ('\0' == data[size - 1]) {
        ext_len--;
      }
      handle_extension(end, ext_len);
    }
  }
}
Esempio n. 11
0
static void
handle_qhit(const char *data, size_t size)
{
  const struct gnutella_qhit_header *header;
  const struct gnutella_guid *guid;
  const struct gnutella_qhit_item *item;
  size_t guid_offset = size - sizeof *guid;
  unsigned hits;
  size_t pos;
  
  RUNTIME_ASSERT(size <= GNUTELLA_MAX_PAYLOAD);
  
  if (size < sizeof *header) {
    fprintf(stderr, "handle_qhit(): Too little payload for header.\n");
    return;
  }
  header = cast_to_const_void_ptr(data);
  
  hits = (unsigned char) header->hits;
  printf("Hits: %u\n", hits);
  printf("Address: %s\n",
    net_addr_port_to_string(net_addr_peek_ipv4(cast_to_const_char_ptr(header->addr)),
      peek_le16(header->port)));
  printf("Speed: %lu\n", (unsigned long) peek_le32(header->speed));

  if (size < sizeof *header + sizeof *guid) {
    fprintf(stderr, "handle_qhit(): Insufficient payload for query hit.\n");
    return;
  }
  if (size >= sizeof *header + sizeof *guid) {
    
    guid = cast_to_const_void_ptr(&data[guid_offset]);
    printf("Servent ID: %08lx-%08lx-%08lx-%08lx\n",
        (unsigned long) peek_be32(&guid->data[0]),
        (unsigned long) peek_be32(&guid->data[4]),
        (unsigned long) peek_be32(&guid->data[8]),
        (unsigned long) peek_be32(&guid->data[12]));
  }
  printf("----\n");

  pos = sizeof *header;
  for (/* NOTHING */; hits > 0; hits--) {
    const char *nul_ptr;
   
    if (pos >= guid_offset || guid_offset - pos < sizeof *item + 2)
      break;

    item = cast_to_const_void_ptr(&data[pos]);
    printf("Index: %lu\n", (unsigned long) peek_le32(item->index));
    printf("Size:  %lu\n", (unsigned long) peek_le32(item->size));

    pos += sizeof *item; 

    nul_ptr = memchr(&data[pos], 0, guid_offset - pos);
    if (!nul_ptr) {
      fprintf(stderr, "handle_qhit(): Non-terminated filename.\n");
      return;
    } else {
      size_t len;

      len = (nul_ptr - &data[pos]);
      if (len > (((size_t) -1) / 4 - 1)) {
        fprintf(stderr, "handle_qhit(): Filename is too long.\n");
        /* Ignore */
      } else {
        const char *p;
        size_t avail;
        
        printf("Filename: ");

        avail = len;
        p = &data[pos];
        while (avail > 0) {
          uint32_t cp;
          cp = utf8_decode(p, avail);
          if ((uint32_t) -1 != cp) {
            uint8_t u_len, i;

            u_len = utf8_first_byte_length_hint((unsigned char) *p);
            RUNTIME_ASSERT(u_len > 0);
            RUNTIME_ASSERT(avail >= u_len);
            avail -= u_len;

            if (cp >= 0x20 && cp != 0x7f) {
              for (i = 0; i < u_len; i++) {
                putchar((unsigned char) p[i]);
              }
            } else {
              char ch = cp & 0xff;
              printf("%s", escape_buffer(&ch, 1)); 
            }
            
            p += u_len;
          } else {
            if (verbosity > 0) {
              fprintf(stderr, "handle_qhit(): Invalid UTF-8.\n");
            }
            break;
          }
        }
      }
      printf("\n");

      pos += len;
    }

    RUNTIME_ASSERT(nul_ptr);
    RUNTIME_ASSERT(&data[pos] == nul_ptr);
    RUNTIME_ASSERT('\0' == *nul_ptr);

    pos++;
    RUNTIME_ASSERT(pos <= guid_offset);

    nul_ptr = memchr(&data[pos], 0, guid_offset - pos);
    if (!nul_ptr) {
      fprintf(stderr, "handle_qhit(): Non-terminated extension block.\n");
      return;
    } else if (nul_ptr != &data[pos]) {
      size_t len = nul_ptr - &data[pos];
      
      printf("Extension size:  %lu\n", (unsigned long) len);
     
      handle_extension(&data[pos], len);
      pos += len;
    }

    RUNTIME_ASSERT(nul_ptr);
    RUNTIME_ASSERT(&data[pos] == nul_ptr);
    RUNTIME_ASSERT('\0' == *nul_ptr);

    pos++;
    RUNTIME_ASSERT(pos <= guid_offset);

    printf("------\n");
  }

  if (hits > 0) {
    fprintf(stderr, "handle_qhit(): Expected %u more hits.\n", hits);
  }

  if (pos < guid_offset) {
      static const unsigned vendor_id_len = 4;
      
      printf("Extended QHD size:  %lu\n", (unsigned long) guid_offset - pos);
      if (guid_offset - pos >= vendor_id_len) {

        printf("Vendor ID: %s\n", escape_buffer(&data[pos], vendor_id_len));

        pos += vendor_id_len;
        if (pos < guid_offset) {
          uint8_t open_data_size = data[pos];
          bool has_ggep = false;
          
          printf("Open data size:  %u\n", open_data_size);
          pos++;

          if (open_data_size > guid_offset - pos) {
            printf("Open data size is too large.\n");
            return;
          }

          if (open_data_size >= 2) {
            uint8_t mask = data[pos];
            uint8_t value = data[pos + 1];
          
            printf("mask:  0x%02x\n", mask);
            printf("value: 0x%02x\n", value);
            
            if (0x20 & mask) {
              has_ggep = 0x20 & value;
              printf("Has GGEP: %s\n", has_ggep ? "yes" : "no");
            }
            if (0x10 & mask) {
              printf("Has speed: %s\n", (0x10 & value) ? "yes" : "no");
            }
            if (0x08 & mask) {
              printf("Has uploaded: %s\n", (0x08 & value) ? "yes" : "no");
            }
            if (0x04 & mask) {
              printf("Busy: %s\n", (0x04 & value) ? "yes" : "no");
            }
            /* mask and value are swapped */
            if (0x01 & value) {
              printf("Must push: %s\n", (0x01 & mask) ? "yes" : "no");
            }
          }

          pos += open_data_size;

          if (pos < guid_offset) {
            size_t priv_data_size = guid_offset - pos;
            static const char id_deflate[] = "{deflate}";
            const char *priv_data, *x;
            
            priv_data = &data[pos];
            priv_data_size = guid_offset - pos;
            
            printf("Private data area size:  %lu\n",
              (unsigned long) priv_data_size);

            handle_extension(priv_data, priv_data_size);

            x = compat_memmem(priv_data, priv_data_size,
                    id_deflate, STATIC_STRLEN(id_deflate));
            if (x) {
              char buf[64 * 1024];
              const char *src;
              size_t n, src_len;

              src = &x[STATIC_STRLEN(id_deflate)];
              src_len = priv_data_size - STATIC_STRLEN(id_deflate);
              n = buffer_inflate(buf, sizeof buf, src, src_len);
              if ((size_t) -1 != n) {
                printf("Inflated:  %s\n", escape_buffer(buf, n));
              }
            }

            pos += priv_data_size;
          }

          RUNTIME_ASSERT(pos == guid_offset);
        }
      }
  }
  
  printf("----\n");
}
Esempio n. 12
0
static int
handle_ggep(const char *data, size_t size)
{
  char ggep_buf[4096];
  ggep_t gtx;

  if (!ggep_decode(&gtx, data, size)) {
    return -1;
  }
  
  for (;;) {
    char id_name[GGEP_ID_BUFLEN];
    const char *data_ptr;
    size_t data_len;
    ggep_id_t id;
    int ret;

    ret = ggep_next(&gtx, id_name);
    if (0 == ret)
      break;

    if (-1 == ret) {
      /* Could not get next GGEP block */
      break;
    }

    printf("GGEP \"%s\"", id_name);
    id = ggep_map_id_name(id_name, NULL);
    if (GGEP_ID_INVALID == id) {
      printf(" <Unknown GGEP ID>\n");
    }

    data_len = ggep_data(&gtx, &data_ptr, ggep_buf, sizeof ggep_buf);
    if ((size_t) -1 == data_len) {
      if (verbosity > 0) {
        fprintf(stderr, "Decoding of GGEP block failed\n");
      }
      printf("<GGEP decoding failure>\n");
      continue;
    }

    switch (id) {
    case GGEP_ID_ALT:     handle_ggep_alt(data_ptr, data_len); break;
    case GGEP_ID_CT:      handle_ggep_ct(data_ptr, data_len); break;
    case GGEP_ID_DU:      handle_ggep_du(data_ptr, data_len); break;
    case GGEP_ID_H:       handle_ggep_h(data_ptr, data_len); break;
    case GGEP_ID_IPP:     handle_ggep_ipp(data_ptr, data_len); break;
    case GGEP_ID_IP:      handle_ggep_ip(data_ptr, data_len); break;
    case GGEP_ID_UDPNFW:  handle_ggep_udpnfw(data_ptr, data_len); break;
    case GGEP_ID_M:       handle_ggep_m(data_ptr, data_len); break;
    case GGEP_ID_PUSH:    handle_ggep_push(data_ptr, data_len); break;
    default:
      if (data_len > 0) {
        printf(" raw data (%lu bytes): \"%s\"",
          (unsigned long) data_len, escape_buffer(data_ptr, data_len));
      } else {
        printf(" <No payload>");
      }
    }

    printf("\n");
  }

  return 0;
}