예제 #1
0
파일: ber.c 프로젝트: 12019/ccid-utils
int ber_decode(const struct ber_tag *tags, unsigned int num_tags,
		const uint8_t *ptr, size_t len, void *priv)
{
	const uint8_t *end = ptr + len;
	unsigned int i;
	uint32_t clen;

//	printf("BER DECODE:\n");
//	hex_dump(ptr, len, 16, 0);

	for(i = 0; ptr < end; ptr += clen) {
		const uint8_t *idb;
		const struct ber_tag *tag;
		size_t tag_len;

		idb = decode_tag(&ptr, end, &tag_len);
		if ( ptr >= end )
			return 0;

		clen = decode_len(&ptr, end);
		if ( ptr + clen > end )
			return 0;

		tag = find_tag(tags, num_tags, idb, tag_len);
		if ( tag ) {
			if ( tag->op && !(*tag->op)(ptr, clen, priv) )
				return 0;
			i++;
		}else{
			size_t i;
			printf("unknown tag: ");
			for(i = 0; i < tag_len; i++)
				printf("%.2x ", idb[i]);
			printf("\n");
			hex_dump(ptr, clen, 16, 0);
		}
	}

	return i;
}
예제 #2
0
파일: ber.c 프로젝트: 12019/ccid-utils
size_t ber_decode_len(const uint8_t **ptr, const uint8_t *end)
{
	return decode_len(ptr, end);
}
예제 #3
0
static int decode_snmp_request(request_t *request, client_t *client)
{
	int type;
	size_t pos = 0, len = 0;
	const char *header_msg  = "Unexpected SNMP header";
	const char *error_msg   = "Unexpected SNMP error";
	const char *request_msg = "Unexpected SNMP request";
	const char *varbind_msg = "Unexpected SNMP varbindings";
	const char *commun_msg  = "SNMP community";
	const char *version_msg = "SNMP version";

	/* The SNMP message is enclosed in a sequence */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_SEQUENCE || len != (client->size - pos)) {
		lprintf(LOG_DEBUG, "%s type %02X length %zu\n", header_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	/* The first element of the sequence is the version */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_INTEGER || len != 1) {
		lprintf(LOG_DEBUG, "Unexpected %s type %02X length %zu\n", version_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	if (decode_int(client->packet, client->size, &pos, len, &request->version) == -1)
		return -1;

	if (request->version != SNMP_VERSION_1 && request->version != SNMP_VERSION_2C) {
		lprintf(LOG_DEBUG, "Unsupported %s %d\n", version_msg, request->version);
		errno = EINVAL;
		return -1;
	}

	/* The second element of the sequence is the community string */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_OCTET_STRING || len >= sizeof(request->community)) {
		lprintf(LOG_DEBUG, "Unexpected %s type %02X length %zu\n", commun_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	if (decode_str(client->packet, client->size, &pos, len, request->community, sizeof(request->community)) == -1)
		return -1;

	if (strlen(request->community) < 1) {
		lprintf(LOG_DEBUG, "unsupported %s '%s'\n", commun_msg, request->community);
		errno = EINVAL;
		return -1;
	}

	/* The third element of the sequence is the SNMP request */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (len != (client->size - pos)) {
		lprintf(LOG_DEBUG, "%s type type %02X length %zu\n", request_msg, type, len);
		errno = EINVAL;
		return -1;
	}
	request->type = type;

	/* The first element of the SNMP request is the request ID */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_INTEGER || len < 1) {
		lprintf(LOG_DEBUG, "%s id type %02X length %zu\n", request_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	if (decode_int(client->packet, client->size, &pos, len, &request->id) == -1)
		return -1;

	/* The second element of the SNMP request is the error state / non repeaters (0..2147483647) */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_INTEGER || len < 1) {
		lprintf(LOG_DEBUG, "%s state type %02X length %zu\n", error_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	if (decode_cnt(client->packet, client->size, &pos, len, &request->non_repeaters) == -1)
		return -1;

	/* The third element of the SNMP request is the error index / max repetitions (0..2147483647) */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_INTEGER || len < 1) {
		lprintf(LOG_DEBUG, "%s index type %02X length %zu\n", error_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	if (decode_cnt(client->packet, client->size, &pos, len, &request->max_repetitions) == -1)
		return -1;

	/* The fourth element of the SNMP request are the variable bindings */
	if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
		return -1;

	if (type != BER_TYPE_SEQUENCE || len != (client->size - pos)) {
		lprintf(LOG_DEBUG, "%s type %02X length %zu\n", varbind_msg, type, len);
		errno = EINVAL;
		return -1;
	}

	/* Loop through the variable bindings */
	request->oid_list_length = 0;
	while (pos < client->size) {
		/* If there is not enough room in the OID list, bail out now */
		if (request->oid_list_length >= MAX_NR_OIDS) {
			lprintf(LOG_DEBUG, "Overflow in OID list\n");
			errno = EFAULT;
			return -1;
		}

		/* Each variable binding is a sequence describing the variable */
		if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
			return -1;

		if (type != BER_TYPE_SEQUENCE || len < 1) {
			lprintf(LOG_DEBUG, "%s type %02X length %zu\n", varbind_msg, type, len);
			errno = EINVAL;
			return -1;
		}

		/* The first element of the variable binding is the OID */
		if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
			return -1;

		if (type != BER_TYPE_OID || len < 1) {
			lprintf(LOG_DEBUG, "%s OID type %02X length %zu\n", varbind_msg, type, len);
			errno = EINVAL;
			return -1;
		}

		if (decode_oid(client->packet, client->size, &pos, len, &request->oid_list[request->oid_list_length]) == -1)
			return -1;

		/* The second element of the variable binding is the new type and value */
		if (decode_len(client->packet, client->size, &pos, &type, &len) == -1)
			return -1;

		if ((type == BER_TYPE_NULL && len) || (type != BER_TYPE_NULL && !len)) {
			lprintf(LOG_DEBUG, "%s value type %02X length %zu\n", varbind_msg, type, len);
			errno = EINVAL;
			return -1;
		}

		if (decode_ptr(client->packet, client->size, &pos, len) == -1)
			return -1;

		/* Now the OID list has one more entry */
		request->oid_list_length++;
	}

	return 0;
}