Пример #1
0
void gseDecodePDU(unsigned char *buf) {
	unsigned char	tag = 0;
	CTYPE_INT16U	lengthFieldSize = 0;
	CTYPE_INT16U	lengthValue = 0;
	CTYPE_INT16U	offsetForSequence = 0;
	CTYPE_INT16U	offsetForNonSequence = 0;
	unsigned char	*gocbRef = NULL;
	CTYPE_INT16U	gocbRefLength = 0;
	CTYPE_INT32U	timeAllowedToLive = 0;
	CTYPE_TIMESTAMP	T = 0;
	CTYPE_INT32U	sqNum = 0;
	CTYPE_INT32U	stNum = 0;

	while (1) {
		tag = (unsigned char) buf[0];	// assumes only one byte is used
		lengthFieldSize = getLengthFieldSize((unsigned char) buf[1]);
		lengthValue = decodeLength((unsigned char *) &buf[1]);
		offsetForSequence = 1 + lengthFieldSize;
		offsetForNonSequence = 1 + lengthFieldSize + lengthValue;

		switch (tag) {
		case GSE_TAG_GOCBREF:
			// save pointer to gocbRef name
			gocbRef = &buf[offsetForSequence];
			gocbRefLength = lengthValue;

			buf = &buf[offsetForNonSequence];
			break;
		case GSE_TAG_TIME_ALLOWED_TO_LIVE:
			ber_decode_integer(&buf[offsetForSequence], lengthValue, &timeAllowedToLive, SV_GET_LENGTH_INT32U);
			buf = &buf[offsetForNonSequence];
			break;
		case ASN1_TAG_SEQUENCE:
			buf = &buf[offsetForSequence];
			break;
		case GSE_TAG_DATSET:
			buf = &buf[offsetForNonSequence];
			break;
		case GSE_TAG_T:
			memcpy(&T, &buf[offsetForSequence], BER_GET_LENGTH_CTYPE_TIMESTAMP(&T));
			buf = &buf[offsetForNonSequence];
			break;
		case GSE_TAG_STNUM:
			ber_decode_integer(&buf[offsetForSequence], lengthValue, &stNum, SV_GET_LENGTH_INT32U);
			buf = &buf[offsetForNonSequence];
			break;
		case GSE_TAG_SQNUM:
			ber_decode_integer(&buf[offsetForSequence], lengthValue, &sqNum, SV_GET_LENGTH_INT32U);
			buf = &buf[offsetForNonSequence];
			break;
		case GSE_TAG_ALLDATA:
			gseDecodeDataset(&buf[offsetForSequence], lengthValue, gocbRef, gocbRefLength, timeAllowedToLive, T, stNum, sqNum);
			return;
		default:
			buf = &buf[offsetForNonSequence];
			break;
		}
	}
}
Пример #2
0
int BER_DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {	// assuming enum is an int - allows any enum type to be used
	CTYPE_INT16U offset = 0;
	CTYPE_INT16U len = 0;

	if (buf[offset++] == ASN1_TAG_UNSIGNED) {
		len += decodeLength(&buf[offset]);
		offset += getLengthFieldSize(buf[offset]);

#if GOOSE_FIXED_SIZE == 1
		ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT8);
#else
		ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
#endif
	}

	return offset + len;
}
Пример #3
0
int BER_DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
	CTYPE_INT16U offset = 0;
	CTYPE_INT16U len = 0;

	if (buf[offset++] == ASN1_TAG_UNSIGNED) {
		len += decodeLength(&buf[offset]);
		offset += getLengthFieldSize(buf[offset]);

		ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
	}

	return offset + len;
}
Пример #4
0
static s8t decode_USM_parameters(u8t* const input, const u16t input_len, u16t* pos, message_v3_t* request)
{
    u8t  type;
    u16t length;
    /* encoded as a string value */
    TRY(ber_decode_type_length(input, input_len, pos, &type, &length));
    if (type != BER_TYPE_OCTET_STRING) {
        snmp_log("bad type, expected string: type %02X length %d\n", type, length);
        return FAILURE;
    }
    /* sequence */
    TRY(ber_decode_sequence_length(input, input_len, pos, &length));

    /* msgAuthoritativeEngineID */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->msgAuthoritativeEngineID.ptr, &request->msgAuthoritativeEngineID.len));

    /* msgAuthoritativeEngineBoots */
    TRY(ber_decode_integer(input, input_len, pos, (s32t*)&request->msgAuthoritativeEngineBoots));

    /* msgAuthoritativeEngineTime */
    TRY(ber_decode_integer(input, input_len, pos, (s32t*)&request->msgAuthoritativeEngineTime));

    /* msgUserName */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->msgUserName.ptr, &request->msgUserName.len));

    /* msgAuthenticationParameters */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->msgAuthenticationParameters.ptr, &request->msgAuthenticationParameters.len));

    /* msgPrivacyParameters */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->msgPrivacyParameters.ptr, &request->msgPrivacyParameters.len));

    if (request->msgFlags & FLAG_PRIV) {
        TRY(ber_decode_type_length((u8t*)input, input_len, pos, &type, &length));
        if (type != BER_TYPE_OCTET_STRING || length != input_len - *pos) {
            return FAILURE;
        }
    }
    return 0;
}
Пример #5
0
s8t prepareDataElements_v3(u8t* const input, const u16t input_len, u16t* pos, message_v3_t* request)
{
    u8t type;
    u16t length;
    s32t int_value;
    /* msgGlobalData sequence */
    TRY(ber_decode_sequence_length(input, input_len, pos, &length));

    /* msgId */
    TRY(ber_decode_integer(input, input_len, pos, &int_value));
    request->msgId = int_value;
    snmp_log("msgId: %d\n", request->msgId);

    /* msgMaxSize */
    TRY(ber_decode_integer(input, input_len, pos, &int_value));
    snmp_log("msgMaxSize: %d\n", int_value);

    /* msgFlags */
    TRY(ber_decode_type_length(input, input_len, pos, &type, &length));
    if (type != BER_TYPE_OCTET_STRING || length != 1) {
        return FAILURE;
    }
    request->msgFlags = input[*pos];
    *pos = *pos + 1;
    snmp_log("msgFlags: %d\n", request->msgFlags);
    if (!(request->msgFlags & FLAG_AUTH) && (request->msgFlags & FLAG_PRIV)) {
        /* If the authFlag is not set and privFlag is set, then the message is discarded without further processing */
        return FAILURE;
    }

    /* msgSecurityModel */
    TRY(ber_decode_integer(input, input_len, pos, &int_value));
    snmp_log("msgSecurityModel: %d\n", int_value);

    /* treat Security Model */
    s8t ret;
    switch (int_value) {
        case USM_SECURITY_MODEL:
            /* Authentication & Privacy validations */            
            ret = processIncomingMsg_USM(input, input_len, pos, request);
            if (ret == FAILURE) {
                return FAILURE;
            } else if (ret == ERR_USM) {
                /* stop processing this message, a report will be sent */
                return 0;
            }
            break;
        default:
            snmp_log("unsupported security model [%d]\n", request->msgSecurityModel);
            return FAILURE;
    }

    /* ScopedPduData sequence */
    TRY(ber_decode_sequence_length(input, input_len, pos, &length));

    /* contextEngineID */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->contextEngineID.ptr, &request->contextEngineID.len));

    /* contextName */
    TRY(ber_decode_string((u8t*)input, input_len, pos, &request->contextName.ptr, &request->contextName.len));

    /* decode PDU */
    ber_decode_pdu(input, input_len, pos, &request->pdu);

    return 0;
}
Пример #6
0
/*
 * Handle an SNMP request
 */
s8t dispatch(u8t* const input,  const u16t input_len, u8t* output, u16t* output_len, const u16t max_output_len)
{
    snmpInPkts++;
    snmp_log("---------------------------------\n");
    
    /* too big incoming message */
    if (input_len > MAX_BUF_SIZE) {
        snmp_log("discard the message, its size [%d] is too big\n", input_len);
        return FAILURE;
    }
    
    u16t pos = 0;
    s32t tmp;

    /* decode sequence & version */
    if ((ber_decode_sequence(input, input_len, &pos)) != ERR_NO_ERROR ||
        ber_decode_integer(input, input_len, &pos, &tmp) != ERR_NO_ERROR) {
        snmpInASNParseErrs++;
        return FAILURE;
    }

    /* create the right message_t data structure */
    message_t* msg_ptr;    
    switch (tmp) {
#if ENABLE_SNMPv1
        case SNMP_VERSION_1:
            msg_ptr = malloc(sizeof(message_t));
            memset(msg_ptr, 0, sizeof(message_t));
            break;
#endif
#if ENABLE_SNMPv3
        case SNMP_VERSION_3:
            msg_ptr = malloc(sizeof(message_v3_t));
            memset(msg_ptr, 0, sizeof(message_v3_t));
            break;
#endif
        default:
            /* If the version is not supported, it discards the datagram and performs no further actions. */
            snmpInBadVersions++;
            snmp_log("unsupported SNMP version %d\n", tmp);
            return ERR_UNSUPPORTED_VERSION;
    }
    msg_ptr->version = (u8t)tmp;
    snmp_log("snmp version: %d\n", msg_ptr->version);

    /* dispatch processing to the version-specific Message Processing Model */
    switch (msg_ptr->version) {
#if ENABLE_SNMPv1
        case SNMP_VERSION_1:
            tmp = prepareDataElements_v1(input, input_len, &pos, (message_t*)msg_ptr);
            break;
#endif
#if ENABLE_SNMPv3
        case SNMP_VERSION_3:
            tmp = prepareDataElements_v3(input, input_len, &pos, (message_v3_t*)msg_ptr);
            break;
#endif
    }
    if (tmp != ERR_NO_ERROR) {
        snmpInASNParseErrs++;
        free_message(msg_ptr);
        return FAILURE;
    }

    /* delegate request processing to the Command Responder */
    handle(msg_ptr);

    /* dispatch preparing the response to the version-specific Message Processing Model */
    switch (msg_ptr->version) {
#if ENABLE_SNMPv1
        case SNMP_VERSION_1:
            tmp = prepareResponseMessage_v1((message_t*)msg_ptr, output, output_len, input, input_len, max_output_len);
            break;
#endif
#if ENABLE_SNMPv3
        case SNMP_VERSION_3:
            tmp = prepareResponseMessage_v3((message_v3_t*)msg_ptr, output, output_len, input, input_len, max_output_len);
            break;
#endif
    }
    free_message(msg_ptr);
    if (tmp != ERR_NO_ERROR) {
        return FAILURE;
    }
    return 0;
}