Example #1
0
static const char *
dump_header_addr_to_string(const struct dump_header *dh)
{
  in_port_t port = peek_be16(dh->port);

  if (DH_F_IPV4 & dh->flags) {
    return net_addr_port_to_string(net_addr_peek_ipv4(&dh->addr[0]), port);
  } else if (DH_F_IPV6 & dh->flags) {
    return net_addr_port_to_string(net_addr_peek_ipv6(&dh->addr[0]), port);
  } else {
    return "<unknown>";
  }
}
Example #2
0
/**
 * Decode major/minor and release information from the specified two
 * contiguous GUID bytes.
 *
 * @param guid is the GUID considered
 * @param start is the offset of the markup (2 or 4) in the GUID
 * @param majp is filled with the major version if it's a GTKG markup
 * @param minp is filled with the minor version if it's a GTKG markup
 * @param relp is filled with the release status if it's a GTKG markup
 *
 * @return whether we recognized a GTKG markup.
 */
static bool
guid_extract_gtkg_info(const guid_t *guid, size_t start,
	uint8 *majp, uint8 *minp, bool *relp)
{
	uint8 major;
	uint8 minor;
	bool release;
	uint16 mark;
	uint16 xmark;
	uint8 product_major;

	g_assert(start < GUID_RAW_SIZE - 1);
	major = peek_u8(&guid->v[start]) & 0x0f;
	minor = peek_u8(&guid->v[start + 1]) & 0x7f;
	release = booleanize(0 == (peek_u8(&guid->v[start + 1]) & 0x80));

	mark = guid_gtkg_encode_version(major, minor, release);
	xmark = peek_be16(&guid->v[start]);

	if (mark != xmark)
		return FALSE;

	/*
	 * Even if by extraordinary the above check matches, make sure we're
	 * not distant from more than one major version.  Since GTKG versions
	 * expire every year, and I don't foresee more than one major version
	 * release per year, this strengthens the positive check.
	 */

	product_major = product_get_major();

	if (major != product_major) {
		int8 delta = product_major - major;
		if (delta < -1 || delta > 1)
			return FALSE;
	}

	/*
	 * We've validated the GUID: the HEC is correct and the version is
	 * consistently encoded, judging by the highest 4 bits of guid.v[4].
	 */

	if (majp) *majp = major;
	if (minp) *minp = minor;
	if (relp) *relp = release;

	return TRUE;
}
Example #3
0
/**
 * Parse ``size'' bytes starting at ``data''  and fill-in the information
 * about the next record in ``header''.
 *
 * @return the length of the record successfully parsed, 0 on error (since
 * the minimal amount of bytes for an empty record would be DIME_HEADER_SIZE).
 */
static size_t
dime_parse_record_header(const char *data, size_t size,
	struct dime_record *header)
{
	const char * const data0 = data;
	size_t n;
	
	g_assert(data);
	g_assert(header);

	n = DIME_HEADER_SIZE;
	if (size < n) {
		goto failure;
	}
	
	header->version = peek_u8(&data[0]) >> 3;

	if (DIME_VERSION != header->version) {
		g_warning("dime_parse_record_header(): Cannot parse dime version %u, "
			"only version %u is supported",
			header->version, DIME_VERSION);
		goto failure;
	}

	header->flags = peek_u8(&data[0]) & (DIME_F_MB | DIME_F_ME | DIME_F_CF);
	header->type_t = peek_u8(&data[1]) >> 4;
	header->resrvd = peek_u8(&data[1]) & 0x0F;

	header->options_length	= peek_be16(&data[2]);
	header->id_length		= peek_be16(&data[4]);
	header->type_length		= peek_be16(&data[6]);
	header->data_length		= peek_be32(&data[8]);

	size -= n;
	data += n;
	header->options	= data;

	n = dime_ceil(header->options_length);
	if (size < n) {
		dime_log_truncated_record("options",
			header, header->options_length, size);
		goto failure;
	}
	size -= n;
	data += n;
	header->id = data;

	n = dime_ceil(header->id_length);
	if (size < n) {
		dime_log_truncated_record("ID", header, header->id_length, size);
		goto failure;
	}
	size -= n;
	data += n;
	header->type = data;

	n = dime_ceil(header->type_length);
	if (size < n) {
		dime_log_truncated_record("type", header, header->type_length, size);
		goto failure;
	}
	size -= n;
	data += n;
	header->data = data;

	n = dime_ceil(header->data_length);
	if (size < n) {
		dime_log_truncated_record("data", header, header->data_length, size);
		goto failure;
	}
	size -= n;
	data += n;

	return data - data0;

failure:
	return 0;
}
Example #4
0
/**
 * Validate a base64-encoded version token `tokenb64' of `len' bytes.
 * The `ip' is given only for clock update operations.
 *
 * @returns error code, or TOK_OK if token is valid.
 */
tok_error_t
tok_version_valid(
	const char *version, const char *tokenb64, int len, host_addr_t addr)
{
	time_t now = tm_time();
	time_t stamp;
	uint32 crc;
	const struct tokkey *tk;
	const struct tokkey *rtk;
	const struct tokkey *latest;
	uint idx;
	const char *key;
	SHA1Context ctx;
	char lvldigest[1024];
	char token[TOKEN_VERSION_SIZE];
	struct sha1 digest;
	version_t rver;
	char *end;
	int toklen;
	int lvllen;
	int lvlsize;
	uint i;

	end = strchr(tokenb64, ';');		/* After 25/02/2003 */
	toklen = end ? (end - tokenb64) : len;

	/*
	 * Verify token.
	 */

	if (toklen != TOKEN_BASE64_SIZE)
		return TOK_BAD_LENGTH;

	if (!base64_decode_into(tokenb64, toklen, token, TOKEN_VERSION_SIZE))
		return TOK_BAD_ENCODING;

	stamp = (time_t) peek_be32(&token);

	/*
	 * Use that stamp, whose precision is TOKEN_LIFE, to update our
	 * clock skew if necessary.
	 */

	clock_update(stamp, TOKEN_LIFE, addr);

	if (ABS(stamp - clock_loc2gmt(now)) > TOKEN_CLOCK_SKEW)
		return TOK_BAD_STAMP;

	if (!version_fill(version, &rver))		/* Remote version */
		return TOK_BAD_VERSION;

	tk = find_tokkey_version(&rver, stamp);	/* The keys they used */
	if (tk == NULL)
		return TOK_BAD_KEYS;

	idx = (uchar) token[6] & 0x1f;			/* 5 bits for the index */
	if (idx >= tk->count)
		return TOK_BAD_INDEX;

	key = tk->keys[idx];

	SHA1Reset(&ctx);
	SHA1Input(&ctx, key, strlen(key));
	SHA1Input(&ctx, token, 7);
	SHA1Input(&ctx, version, strlen(version));
	SHA1Result(&ctx, &digest);

	if (0 != memcmp(&token[7], digest.data, SHA1_RAW_SIZE))
		return TOK_INVALID;

	if (version_build_cmp(&rver, &tk->ver) < 0)
		return TOK_OLD_VERSION;

	if (end == NULL)
		return TOK_MISSING_LEVEL;

	latest = find_latest(&rver);
	if (latest == NULL)						/* Unknown in our key set */
		return TOK_OLD_VERSION;

	/*
	 * Verify build.
	 *
	 * Build numbers were emitted when we switched to SVN on 2006-08-26
	 * and stopped being a monotonous increasing function when we switched
	 * to git on 2011-09-11.
	 */

	if (
		rver.timestamp >= 1156543200 &&		/* 2006-08-26 */
		rver.timestamp < GIT_SWITCH			/* 2011-09-11 */
	) {
		if (0 == rver.build)
			return TOK_MISSING_BUILD;
		if (rver.build < latest->ver.build)
			return TOK_WRONG_BUILD;
	}

	/*
	 * Verify level.
	 */

	lvllen = len - toklen - 2;				/* Forget about "; " */
	end += 2;								/* Skip "; " */

	if (UNSIGNED(lvllen) >= sizeof(lvldigest) || lvllen <= 0)
		return TOK_BAD_LEVEL_LENGTH;

	if (lvllen & 0x3)
		return TOK_BAD_LEVEL_LENGTH;

	lvllen = base64_decode_into(end, lvllen, lvldigest, sizeof(lvldigest));

	if (lvllen == 0 || (lvllen & 0x1))
		return TOK_BAD_LEVEL_ENCODING;

	g_assert(lvllen >= 2);
	g_assert((lvllen & 0x1) == 0);

	/*
	 * Only check the highest keys we can check.
	 */

	lvllen /= 2;							/* # of keys held remotely */
	lvlsize = G_N_ELEMENTS(token_keys) - (tk - token_keys);
	lvlsize = MIN(lvllen, lvlsize);

	g_assert(lvlsize >= 1);

	rtk = tk + (lvlsize - 1);				/* Keys at that level */

	crc = crc32_update(0, token, TOKEN_VERSION_SIZE);
	crc = tok_crc(crc, rtk);

	lvlsize--;								/* Move to 0-based offset */

	if (peek_be16(&lvldigest[2*lvlsize]) != crc)
		return TOK_INVALID_LEVEL;

	for (i = 0; i < G_N_ELEMENTS(token_keys); i++) {
		rtk = &token_keys[i];
		if (rtk->ver.timestamp > rver.timestamp) {
			rtk--;							/* `rtk' could not exist remotely */
			break;
		}
	}

	if (lvlsize < rtk - tk)
		return TOK_SHORT_LEVEL;

	return TOK_OK;
}
Example #5
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);
    }
  }
}
Example #6
0
static inline bool
host_addr_is_6to4(const host_addr_t ha)
{
	return host_addr_is_ipv6(ha) && 0x2002 == peek_be16(&ha.addr.ipv6[0]);
}