📄 v3_ber.c
字号:
if (asn_err || ((Lcl_Size(in_stream) + asn_length) != asn_size)) { SGRPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); }/* do bounds-checking on msg_id -- if it's too small or too large, it's a parse error */if ((rp->msg_id < ETC_MSGID_MIN) || (rp->msg_id > ETC_MSGID_MAX)) { SGRPv3_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); }/* do bounds-checking on mms -- if it's too small or too large, it's a parse error */if ((mms < ETC_MMS_MIN) || (mms > ETC_MMS_MAX)) { SGRPv3_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); }/* do bounds-checking on msg_sec_model -- if it's too small or too large, it's a parse error */if ((rp->msg_sec_model < ETC_SEC_MODEL_V1) || (rp->msg_sec_model > ETC_SEC_MODEL_MAX)) { SGRPv3_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); }/* If the security model isn't known, bump the counter and drop the message */if (rp->msg_sec_model != ETC_SEC_MODEL_USM) { SGRPv3_INC_COUNTER(snmp_stats.snmpUnknownSecurityModels); return(0); } /* work out the max packet size and update the value in the packet structure, if mms is greater than MAX_ALENGTH we leave maxpkt alone as it's already corect */if (mms < MAX_ALENGTH) rp->maxpkt = min(rp->maxpkt, max((ALENGTH_T)mms, 484));/* Pull out the security information */if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_PRIMITIVE)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_OCTETSTRING)) asn_err = 1;asn_length = A_DecodeLength(in_stream, &asn_err);if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_CONSTRUCTOR)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_SEQUENCE)) asn_err = 1;asn_length = A_DecodeLength(in_stream, &asn_err);asn_size = Lcl_Size(in_stream);A_DecodeOctetStringWTC(in_stream, &rp->msg_sec_id, &asn_err, A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);msg_boots = A_DecodeIntegerWTC(in_stream, &asn_err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);msg_time = A_DecodeIntegerWTC(in_stream, &asn_err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);A_DecodeOctetStringWTC(in_stream, &rp->msg_sec_name, &asn_err, A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);if ((msg_boots < 0) || (msg_time < 0) || (A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_PRIMITIVE)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_OCTETSTRING) || (EBufferUsed(&rp->msg_sec_name) > ETC_USER_USER_MAX)) asn_err = 1;digest_length = A_DecodeLength(in_stream, &asn_err);digest_ptr = Lcl_Next(in_stream);if (Lcl_Seek(in_stream, digest_length, 1)) asn_err = 1;if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_PRIMITIVE)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_OCTETSTRING)) asn_err = 1;priv_length = A_DecodeLength(in_stream, &asn_err);priv_ptr = Lcl_Next(in_stream);if (Lcl_Seek(in_stream, priv_length, 1)) asn_err = 1;if (asn_err || ((Lcl_Size(in_stream) + asn_length) != asn_size)) { SGRPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); }/* We allow noauth/nopriv, auth/nopriv & auth/priv but not noauth/priv */if ((rp->msg_flags & (ETC_V3_AUTH | ETC_V3_PRIV)) == ETC_V3_PRIV) { SGRPv3_INC_COUNTER(snmp_stats.snmpInvalidMsgs); return(0); }/* first, do a length check on the engine id */if ((EBufferUsed(&rp->msg_sec_id) < ETC_ENGINE_ENGINE_MIN) || (EBufferUsed(&rp->msg_sec_id) > ETC_ENGINE_ENGINE_MAX)) { SGRPv3_INC_COUNTER(snmp_stats.usmStatsUnknownEngineIDs); rp->msg_sec_boots = SNMP_Engine_Get_My_Boots(); rp->msg_sec_time = SNMP_Engine_Get_My_Time(); return(Send_Report_PDU(rp, in_stream, 0, V3_UNKNOWNENGINEIDS, sizeof(V3_UNKNOWNENGINEIDS)/sizeof(OIDC_T), snmp_stats.usmStatsUnknownEngineIDs, error_ret, pktsrc, pktdst)); } /* lookup security engine id, If we the engine id isn't one we know we see if the user wants to add the engine id that has come in. */engine = SNMP_Engine_Lookup(EBufferStart(&rp->msg_sec_id), EBufferUsed(&rp->msg_sec_id));#if defined(ENVOY_ADD_ENGINE_ADDRESS)#if (INSTALL_ENVOY_SNMP_LOCK)ENVOY_SNMP_RELEASE_READ_LOCK(*rp->coarse_lock);rp->lockflags = LOCK_NOLOCK;if (ENVOY_SNMP_GET_WRITE_LOCK(*rp->coarse_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "V3 Decode: coarse lock is broken", 0)); return(0); }rp->lockflags = LOCK_WRITE;if (ENVOY_ADD_ENGINE_ADDRESS(rp, pktsrc, ((engine == 0) ? 0 : 1))) if (engine == 0) engine = SNMP_Engine_Lookup(EBufferStart(&rp->msg_sec_id), EBufferUsed(&rp->msg_sec_id));ENVOY_SNMP_RELEASE_WRITE_LOCK(*rp->coarse_lock);rp->lockflags = LOCK_NOLOCK;if (ENVOY_SNMP_GET_READ_LOCK(*rp->coarse_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "V3 Decode: coarse lock is broken", 0)); return(0); }rp->lockflags = LOCK_READ;#else /* lock */if (ENVOY_ADD_ENGINE_ADDRESS(rp, pktsrc, ((engine == 0) ? 0 : 1))) if (engine == 0) engine = SNMP_Engine_Lookup(EBufferStart(&rp->msg_sec_id), EBufferUsed(&rp->msg_sec_id));#endif /* lock */#endif /* add engine macro */if (engine == 0) { SGRPv3_INC_COUNTER(snmp_stats.usmStatsUnknownEngineIDs); rp->msg_sec_boots = SNMP_Engine_Get_My_Boots(); rp->msg_sec_time = SNMP_Engine_Get_My_Time(); return(Send_Report_PDU(rp, in_stream, 0, V3_UNKNOWNENGINEIDS, sizeof(V3_UNKNOWNENGINEIDS)/sizeof(OIDC_T), snmp_stats.usmStatsUnknownEngineIDs, error_ret, pktsrc, pktdst)); }#if (INSTALL_ENVOY_SNMP_V3_NOTIFY)/* We need to update any Probe packets that may have had their * engine information made available. */#if (INSTALL_ENVOY_SNMP_LOCK)if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "V3 Decode: retrans lock is broken", 0)); return(0); }#endif for (retrans = root_retrans_block.retrans; retrans; retrans = retrans->next) { if (retrans->flags & SNMP_RETRANS_FLAGS_SENDING_PROBE) SNMP_Probe_Check(retrans); }ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endifif (engine == v3_my_engine) { rp->msg_sec_boots = SNMP_Engine_Get_My_Boots(); rp->msg_sec_time = SNMP_Engine_Get_My_Time(); }/* lookup engineid/username */user = SNMP_User_Lookup(EBufferStart(&rp->msg_sec_id), EBufferUsed(&rp->msg_sec_id), EBufferStart(&rp->msg_sec_name), EBufferUsed(&rp->msg_sec_name));if ((user == 0) || (SNMP_User_Get_Status(user) != ETC_RS_ACTIVE)) { SGRPv3_INC_COUNTER(snmp_stats.usmStatsUnknownUserNames); return(Send_Report_PDU(rp, in_stream, 0, V3_UNKNOWNUSERNAMES, sizeof(V3_UNKNOWNUSERNAMES)/sizeof(OIDC_T), snmp_stats.usmStatsUnknownUserNames, error_ret, pktsrc, pktdst)); }/* see if the user supports the requested security level */if (SNMP_User_Get_MaxSec(user) < (rp->msg_flags & (ETC_V3_AUTH | ETC_V3_PRIV))) { SGRPv3_INC_COUNTER(snmp_stats.usmStatsUnsupportedSecLevels); return(Send_Report_PDU(rp, in_stream, 0, V3_UNSUPPORTEDSECLEVELS, sizeof(V3_UNSUPPORTEDSECLEVELS)/sizeof(OIDC_T), snmp_stats.usmStatsUnsupportedSecLevels,error_ret, pktsrc, pktdst)); }if (rp->msg_flags & ETC_V3_AUTH) { /* copy the user auth info to the packet and run the verification routine */ rp->auth = SNMP_User_Get_Auth(user); MEMCPY(rp->msg_sec_auth, SNMP_User_Get_AuthKey(user), SNMP_Auth_Get_KeySize(rp->auth)); if ((digest_length != SNMP_Auth_Get_Need(rp->auth)) || SNMP_Auth_Verify(rp->auth, rp->msg_sec_auth, SNMP_Auth_Get_KeySize(rp->auth), Lcl_Start(in_stream), asn1leng, digest_ptr)) { SGRPv3_INC_COUNTER(snmp_stats.usmStatsWrongDigests); SNMPv3_AUTH_DECODE_VIOLATION(1); return(Send_Report_PDU(rp, in_stream, 0, V3_WRONGDIGESTS, sizeof(V3_WRONGDIGESTS)/sizeof(OIDC_T), snmp_stats.usmStatsWrongDigests, error_ret, pktsrc, pktdst)); } /* the time and boots check */ if (engine == v3_my_engine) { /* if we are the authoritative engine */ lcl_boots = SNMP_Engine_Get_Boots(engine); lcl_time = SNMP_Engine_Get_Time(engine); if ((lcl_boots == 0x7FFFFFFFL) || (lcl_boots != msg_boots) || (msg_time < (lcl_time - 150)) || ((msg_time - 150) > lcl_time)) { SNMPv3_AUTH_DECODE_VIOLATION(2); SGRPv3_INC_COUNTER(snmp_stats.usmStatsNotInTimeWindows); return(Send_Report_PDU(rp, in_stream, 1, V3_NOTINTIMEWINDOWS, sizeof(V3_NOTINTIMEWINDOWS)/sizeof(OIDC_T), snmp_stats.usmStatsNotInTimeWindows, error_ret, pktsrc, pktdst)); } } else { /* if we aren't the authoritative engine */ /* if necessary acquire the boots lock */#if (INSTALL_ENVOY_SNMP_LOCK) if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Boots_Lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "V3 Decode: boots lock is broken", 0)); return(0); }#endif lcl_boots = SNMP_Engine_Get_Boots(engine); lcl_time = SNMP_Engine_Get_Time(engine); if ((lcl_boots == 0x7FFFFFFFL) || (msg_boots < lcl_boots) || ((msg_boots == lcl_boots) && (msg_time < (lcl_time - 150)))) { /* out of time window, drop the packet */ ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Boots_Lock); return(0); } /* we are in the time window should we update our data? */ if ((msg_boots > lcl_boots) || ((msg_boots == lcl_boots) && (msg_time > SNMP_Engine_Get_LastTime(engine)))) { SNMP_Engine_Set_Info(engine, msg_boots, msg_time); rp->msg_sec_time = msg_time; } else rp->msg_sec_time = lcl_time; rp->msg_sec_boots = lcl_boots;#if (INSTALL_ENVOY_SNMP_V3_NOTIFY) /* We need to update any Informs that may need retransmitting * at this time. We have to check here, rather than in * retrans_timer_exp(), because we can't risk grabbing the * Coarse lock while we're running off of the timer queue. */#if (INSTALL_ENVOY_SNMP_LOCK) if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "V3 Decode: retrans lock is broken", 0)); return(0); }#endif for (retrans = root_retrans_block.retrans; retrans; retrans = retrans->next) { if ((retrans->pktp->pdu_type == INFORM_REQUEST_PDU) && (engine->id_len == EBufferUsed(&retrans->pktp->msg_sec_id)) && (MEMCMP(engine->id, EBufferStart(&retrans->pktp->msg_sec_id), engine->id_len) == 0)) { retrans->pktp->msg_sec_boots = SNMP_Engine_Get_Boots(engine); retrans->pktp->msg_sec_time = SNMP_Engine_Get_Time(engine); } } ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock); #endif ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Boots_Lock); } if (rp->msg_flags & ETC_V3_PRIV) { /* set up the user information into the packet structure */ rp->priv = SNMP_User_Get_Priv(user); MEMCPY(rp->msg_sec_priv, SNMP_User_Get_PrivKey(user), SNMP_Priv_Get_KeySize(rp->priv)); /* Remove the octet string tag and get the length of the encrypted string and consistency check them */ if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_PRIMITIVE)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_OCTETSTRING)) asn_err = 1; asn_length = A_DecodeLength(in_stream, &asn_err); if (asn_err || (asn_length > Lcl_Size(in_stream)) || (asn_length == 0)) { SGRPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); } /* get some space for the decoded stuff */ sec_buf = SNMP_memory_alloc(asn_length); if (sec_buf == 0) return(0); /* check that the security block is the right size and then try and do the decryption */ if ((priv_length != SNMP_Priv_Get_Need(rp->priv)) || SNMP_Priv_Decode(rp->priv, rp->msg_sec_priv, SNMP_Priv_Get_KeySize(rp->priv), Lcl_Next(in_stream), asn_length, priv_ptr, sec_buf)) { SNMP_memory_free(sec_buf); SNMPv3_AUTH_DECODE_VIOLATION(3); SGRPv3_INC_COUNTER(snmp_stats.usmStatsDecryptionErrors); return(Send_Report_PDU(rp, in_stream, 0, V3_DECRYPTIONERRORS, sizeof(V3_DECRYPTIONERRORS)/sizeof(OIDC_T), snmp_stats.usmStatsDecryptionErrors, error_ret, pktsrc, pktdst)); } /* attach sec_buf to sec_stream and send it through the decode */ (void) Lcl_Open(&sec_stream, sec_buf, asn_length); asn_err = decode_scoped_pdu(rp, &sec_stream, pktsrc, pktdst, asn1leng, user); SNMP_memory_free(sec_buf); } else asn_err = decode_scoped_pdu(rp, in_stream, pktsrc, pktdst, asn1leng, user); }else asn_err = decode_scoped_pdu(rp, in_stream, pktsrc, pktdst, asn1leng, user);switch(asn_err) { case DECODE_ASN_PARSE_ERROR: SGRPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs); return(0); case DECODE_UNKNOWN_PDU_HANDLERS: SGRPv3_INC_COUNTER(snmp_stats.snmpUnknownPDUHandlers); return(Send_Report_PDU(rp, in_stream, 2, V3_UNKNOWNPDUHANDLERS, sizeof(V3_UNKNOWNPDUHANDLERS)/sizeof(OIDC_T), snmp_stats.snmpUnknownPDUHandlers, error_ret, pktsrc, pktdst)); case DECODE_UNKNOWN_CONTEXTS: SGRPv3_INC_COUNTER(snmp_stats.snmpUnknownContexts); return(Send_Report_PDU(rp, in_stream, 2, V3_UNKNOWNCONTEXTS, sizeof(V3_UNKNOWNCONTEXTS)/sizeof(OIDC_T), snmp_stats.snmpUnknownContexts, error_ret, pktsrc, pktdst)); default: case 0: return(0); case 1: return(rp); case 2: *error_ret = 1; return(rp); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -