|
|
|
|
@ -294,6 +294,70 @@ snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t por
|
|
|
|
|
err = snmp_process_set_request(&request); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
struct snmp_varbind vb; |
|
|
|
|
|
|
|
|
|
vb.next = NULL; |
|
|
|
|
vb.prev = NULL; |
|
|
|
|
vb.type = SNMP_ASN1_TYPE_COUNTER32; |
|
|
|
|
vb.value_len = sizeof(u32_t); |
|
|
|
|
|
|
|
|
|
switch (request.error_status) { |
|
|
|
|
case SNMP_ERR_AUTHORIZATIONERROR: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.wrongdigests; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_ERR_UNKNOWN_ENGINEID: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.unknownengineids; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_ERR_UNKNOWN_SECURITYNAME: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.unknownusernames; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_ERR_UNSUPPORTED_SECLEVEL: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.unsupportedseclevels; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_ERR_NOTINTIMEWINDOW: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.notintimewindows; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_ERR_DECRYIPTION_ERROR: |
|
|
|
|
{ |
|
|
|
|
struct snmp_obj_id oid = { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 } }; |
|
|
|
|
vb.value = &snmp_stats.decryptionerrors; |
|
|
|
|
MEMCPY(&vb.oid, &oid, sizeof(struct snmp_obj_id)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
/* Unknown or unhandled error_status */ |
|
|
|
|
err = ERR_ARG; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (err == ERR_OK) { |
|
|
|
|
snmp_append_outbound_varbind(&(request.outbound_pbuf_stream), &vb); |
|
|
|
|
request.error_status = SNMP_ERR_NOERROR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
request.request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_REPORT); |
|
|
|
|
request.request_id = request.msg_id; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (err == ERR_OK) { |
|
|
|
|
err = snmp_complete_outbound_frame(&request); |
|
|
|
|
@ -703,6 +767,9 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
s32_t parent_tlv_value_len; |
|
|
|
|
s32_t s32_value; |
|
|
|
|
err_t err; |
|
|
|
|
#if LWIP_SNMP_V3 |
|
|
|
|
u8_t auth, priv; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); |
|
|
|
|
|
|
|
|
|
@ -828,7 +895,6 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); |
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); |
|
|
|
|
/* @todo: Implement time window checking */ |
|
|
|
|
|
|
|
|
|
/* msgUserName */ |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
@ -839,8 +905,6 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, |
|
|
|
|
&u16_value, SNMP_V3_MAX_USER_LENGTH)); |
|
|
|
|
request->msg_user_name_len = (u8_t)u16_value; |
|
|
|
|
/* @todo: Implement unknown user error response */ |
|
|
|
|
IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); |
|
|
|
|
|
|
|
|
|
/* msgAuthenticationParameters */ |
|
|
|
|
memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); |
|
|
|
|
@ -850,12 +914,92 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
/* Remember position */ |
|
|
|
|
inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; |
|
|
|
|
LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); |
|
|
|
|
LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); |
|
|
|
|
/* Read auth parameters */ |
|
|
|
|
IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); |
|
|
|
|
//IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH);
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, |
|
|
|
|
&u16_value, tlv.value_len)); |
|
|
|
|
request->msg_authentication_parameters_len = (u8_t)u16_value; |
|
|
|
|
|
|
|
|
|
/* msgPrivacyParameters */ |
|
|
|
|
memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); |
|
|
|
|
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); |
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, |
|
|
|
|
&u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); |
|
|
|
|
request->msg_privacy_parameters_len = (u8_t)u16_value; |
|
|
|
|
|
|
|
|
|
/* validate securityParameters here (do this after decoding because we don't want to increase other counters for wrong frames) */ |
|
|
|
|
// 1) securityParameters was correctly serialized if we reach here.
|
|
|
|
|
// 2) securityParameters are already cached.
|
|
|
|
|
// 3) if msgAuthoritativeEngineID is unknown, zero-length or too long:
|
|
|
|
|
// b) https://tools.ietf.org/html/rfc3414#section-7
|
|
|
|
|
{ |
|
|
|
|
const char *eid; |
|
|
|
|
u8_t eid_len; |
|
|
|
|
|
|
|
|
|
snmpv3_get_engine_id(&eid, &eid_len); |
|
|
|
|
|
|
|
|
|
if ((request->msg_authoritative_engine_id_len == 0) || |
|
|
|
|
(request->msg_authoritative_engine_id_len != eid_len) || |
|
|
|
|
(memcmp(eid, request->msg_authoritative_engine_id, eid_len) != 0)) { |
|
|
|
|
snmp_stats.unknownengineids++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNKNOWN_ENGINEID; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4) verify username
|
|
|
|
|
if(snmpv3_get_user((char*)request->msg_user_name, &auth, NULL, &priv, NULL)) { |
|
|
|
|
snmp_stats.unknownusernames++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNKNOWN_SECURITYNAME; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 5) verify security level
|
|
|
|
|
switch(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)) { |
|
|
|
|
case SNMP_V3_NOAUTHNOPRIV: |
|
|
|
|
if ((auth != SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { |
|
|
|
|
/* Invalid security level for user */ |
|
|
|
|
snmp_stats.unsupportedseclevels++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#if LWIP_SNMP_V3_CRYPTO |
|
|
|
|
case SNMP_V3_AUTHNOPRIV: |
|
|
|
|
if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { |
|
|
|
|
/* Invalid security level for user */ |
|
|
|
|
snmp_stats.unsupportedseclevels++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SNMP_V3_AUTHPRIV: |
|
|
|
|
if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv == SNMP_V3_PRIV_ALGO_INVAL)) { |
|
|
|
|
/* Invalid security level for user */ |
|
|
|
|
snmp_stats.unsupportedseclevels++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
default: |
|
|
|
|
snmp_stats.unsupportedseclevels++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 6) if securitylevel specifies authentication, authenticate message.
|
|
|
|
|
#if LWIP_SNMP_V3_CRYPTO |
|
|
|
|
if (request->msg_flags & SNMP_V3_AUTH_FLAG) { |
|
|
|
|
const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; |
|
|
|
|
@ -864,40 +1008,67 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; |
|
|
|
|
struct snmp_pbuf_stream auth_stream; |
|
|
|
|
|
|
|
|
|
if (request->msg_authentication_parameters_len > SNMP_V3_MAX_AUTH_PARAM_LENGTH) { |
|
|
|
|
snmp_stats.wrongdigests++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_AUTHORIZATIONERROR; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Rewind stream */ |
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); |
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); |
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); |
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&auth_stream, inbound_msgAuthenticationParameters_offset)); |
|
|
|
|
/* Set auth parameters to zero for verification */ |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_enc_raw(&auth_stream, zero_arr, request->msg_authentication_parameters_len)); |
|
|
|
|
|
|
|
|
|
/* Verify authentication */ |
|
|
|
|
IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); |
|
|
|
|
|
|
|
|
|
IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); |
|
|
|
|
IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac)); |
|
|
|
|
/* @todo: Implement error response */ |
|
|
|
|
IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
/* Ungraceful exit if we encounter cryptography and don't support it.
|
|
|
|
|
* @todo: Implement error response |
|
|
|
|
*/ |
|
|
|
|
IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG))); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* msgPrivacyParameters */ |
|
|
|
|
memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); |
|
|
|
|
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); |
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
if(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)) { |
|
|
|
|
snmp_stats.wrongdigests++; |
|
|
|
|
request->msg_flags = 0; // noauthnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_AUTHORIZATIONERROR; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, |
|
|
|
|
&u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); |
|
|
|
|
// 7) if securitylevel specifies authentication, verify engineboots, enginetime and lastenginetime
|
|
|
|
|
{ |
|
|
|
|
u32_t boots = snmpv3_get_engine_boots_internal(); |
|
|
|
|
if ((request->msg_authoritative_engine_boots != boots) || (boots == 2147483647UL)) { |
|
|
|
|
snmp_stats.notintimewindows++; |
|
|
|
|
request->msg_flags = SNMP_V3_AUTHNOPRIV; // authnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_NOTINTIMEWINDOW; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
u32_t time = snmpv3_get_engine_time_internal(); |
|
|
|
|
if (request->msg_authoritative_engine_time > time) { |
|
|
|
|
snmp_stats.notintimewindows++; |
|
|
|
|
request->msg_flags = SNMP_V3_AUTHNOPRIV; // authnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_NOTINTIMEWINDOW; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
else if (time > 150) { |
|
|
|
|
if (request->msg_authoritative_engine_time < time - 150) { |
|
|
|
|
snmp_stats.notintimewindows++; |
|
|
|
|
request->msg_flags = SNMP_V3_AUTHNOPRIV; // authnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_NOTINTIMEWINDOW; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// 8) if securitylevel specifies privacy, decrypt message.
|
|
|
|
|
#if LWIP_SNMP_V3_CRYPTO |
|
|
|
|
/* Decrypt message */ |
|
|
|
|
if (request->msg_flags & SNMP_V3_PRIV_FLAG) { |
|
|
|
|
/* Decrypt message */ |
|
|
|
|
|
|
|
|
|
u8_t key[20]; |
|
|
|
|
u8_t algo; |
|
|
|
|
|
|
|
|
|
@ -907,11 +1078,20 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
|
|
|
|
|
IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); |
|
|
|
|
IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, |
|
|
|
|
if(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, |
|
|
|
|
request->msg_privacy_parameters, request->msg_authoritative_engine_boots, |
|
|
|
|
request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT)); |
|
|
|
|
request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT) != ERR_OK) { |
|
|
|
|
snmp_stats.decryptionerrors++; |
|
|
|
|
request->msg_flags = SNMP_V3_AUTHNOPRIV; // authnopriv
|
|
|
|
|
request->error_status = SNMP_ERR_DECRYIPTION_ERROR; |
|
|
|
|
return ERR_OK; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
// 9) calculate max size of scoped pdu?
|
|
|
|
|
// 10) securityname for user is retrieved from usertable?
|
|
|
|
|
// 11) security data is cached?
|
|
|
|
|
// 12)
|
|
|
|
|
|
|
|
|
|
/* Scoped PDU
|
|
|
|
|
* Encryption context |
|
|
|
|
@ -930,6 +1110,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, |
|
|
|
|
&u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); |
|
|
|
|
request->context_engine_id_len = (u8_t)u16_value; |
|
|
|
|
// TODO: do we need to verify this contextengineid too?
|
|
|
|
|
|
|
|
|
|
/* contextName */ |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
@ -940,25 +1121,26 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, |
|
|
|
|
&u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); |
|
|
|
|
request->context_name_len = (u8_t)u16_value; |
|
|
|
|
// TODO: do we need to verify this contextname too?
|
|
|
|
|
} else |
|
|
|
|
#endif |
|
|
|
|
{ |
|
|
|
|
/* decode community */ |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); |
|
|
|
|
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); |
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
/* decode community */ |
|
|
|
|
IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); |
|
|
|
|
IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); |
|
|
|
|
parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); |
|
|
|
|
IF_PARSE_ASSERT(parent_tlv_value_len > 0); |
|
|
|
|
|
|
|
|
|
err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); |
|
|
|
|
if (err == ERR_MEM) { |
|
|
|
|
/* community string does not fit in our buffer -> its too long -> its invalid */ |
|
|
|
|
request->community_strlen = 0; |
|
|
|
|
snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); |
|
|
|
|
} else { |
|
|
|
|
IF_PARSE_ASSERT(err == ERR_OK); |
|
|
|
|
} |
|
|
|
|
/* add zero terminator */ |
|
|
|
|
request->community[request->community_strlen] = 0; |
|
|
|
|
err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); |
|
|
|
|
if (err == ERR_MEM) { |
|
|
|
|
/* community string does not fit in our buffer -> its too long -> its invalid */ |
|
|
|
|
request->community_strlen = 0; |
|
|
|
|
snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); |
|
|
|
|
} else { |
|
|
|
|
IF_PARSE_ASSERT(err == ERR_OK); |
|
|
|
|
} |
|
|
|
|
/* add zero terminator */ |
|
|
|
|
request->community[request->community_strlen] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* decode PDU type (next container level) */ |
|
|
|
|
@ -995,6 +1177,7 @@ snmp_parse_inbound_frame(struct snmp_request *request)
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; |
|
|
|
|
request->request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP); |
|
|
|
|
|
|
|
|
|
/* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ |
|
|
|
|
if (request->community_strlen == 0) { |
|
|
|
|
@ -1244,7 +1427,7 @@ snmp_prepare_outbound_frame(struct snmp_request *request)
|
|
|
|
|
|
|
|
|
|
/* 'PDU' sequence */ |
|
|
|
|
request->outbound_pdu_offset = pbuf_stream->offset; |
|
|
|
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0); |
|
|
|
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, 0); |
|
|
|
|
OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); |
|
|
|
|
|
|
|
|
|
/* request ID */ |
|
|
|
|
@ -1525,7 +1708,7 @@ snmp_complete_outbound_frame(struct snmp_request *request)
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* complete missing length in 'PDU' sequence */ |
|
|
|
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, |
|
|
|
|
SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, |
|
|
|
|
frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ |
|
|
|
|
OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); |
|
|
|
|
OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); |
|
|
|
|
|