Exemple #1
0
int
decode_MechType(const unsigned char *p, size_t len, MechType *data, size_t *size)
{
size_t ret = 0;
size_t l;
int e;

memset(data, 0, sizeof(*data));
e = decode_oid(p, len, data, &l);
FORW;
if(size) *size = ret;
return 0;
fail:
free_MechType(data);
return e;
}
Exemple #2
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;
}