snmpusm.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,486 行 · 第 1/5 页
C
2,486 行
usm_check_and_update_timeliness( u_char *secEngineID, size_t secEngineIDLen, u_int boots_uint, u_int time_uint, int *error){ u_char myID[USM_MAX_ID_LENGTH]; int myIDLength = snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH); u_int myBoots; u_int myTime; if ( (myIDLength > USM_MAX_ID_LENGTH) || (myIDLength < 0) ) { /* We're probably already screwed...buffer overwrite. XXX? */ DEBUGMSGTL(("usm","Buffer overflow.\n")); *error = SNMPERR_USM_GENERICERROR; return -1; } myBoots = snmpv3_local_snmpEngineBoots(); myTime = snmpv3_local_snmpEngineTime(); /* * IF the time involved is local * Make sure message is inside the time window * ELSE * IF boots is higher or boots is the same and time is higher * remember this new data * ELSE * IF !(boots same and time within USM_TIME_WINDOW secs) * Message is too old * ELSE * Message is ok, but don't take time * ENDIF * ENDIF * ENDIF */ /* * This is a local reference. */ if ( (int)secEngineIDLen == myIDLength && memcmp (secEngineID, myID, myIDLength) == 0 ) { u_int time_difference = myTime > time_uint ? myTime - time_uint : time_uint - myTime; if (boots_uint == ENGINEBOOT_MAX || boots_uint != myBoots || time_difference > USM_TIME_WINDOW) { if ( snmp_increment_statistic( STAT_USMSTATSNOTINTIMEWINDOWS) == 0 ) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } DEBUGMSGTL(("usm","%s\n", "Not in local time window.")); *error = SNMPERR_USM_NOTINTIMEWINDOW; return -1; } *error = SNMPERR_SUCCESS; return 0; } /* * This is a remote reference. */ else { u_int theirBoots, theirTime, theirLastTime; u_int time_difference; if ( get_enginetime_ex( secEngineID, secEngineIDLen, &theirBoots, &theirTime, &theirLastTime, TRUE) != SNMPERR_SUCCESS) { DEBUGMSGTL(("usm","%s\n", "Failed to get remote engine's times.")); *error = SNMPERR_USM_GENERICERROR; return -1; } time_difference = theirTime > time_uint ? theirTime - time_uint : time_uint - theirTime; /* * XXX Contrary to the pseudocode: * See if boots is invalid first. */ if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) { DEBUGMSGTL(("usm","%s\n", "Remote boot count invalid.")); *error = SNMPERR_USM_NOTINTIMEWINDOW; return -1; } /* * Boots is ok, see if the boots is the same but the time * is old. */ if (theirBoots == boots_uint && time_uint < theirLastTime) { if(time_difference > USM_TIME_WINDOW) { DEBUGMSGTL(("usm","%s\n", "Message too old.")); *error = SNMPERR_USM_NOTINTIMEWINDOW; return -1; } else /* Old, but acceptable */ { *error = SNMPERR_SUCCESS; return 0; } } /* Message is ok, either boots has been advanced, or time is greater than before with the same boots. */ if ( set_enginetime( secEngineID, secEngineIDLen, boots_uint, time_uint, TRUE) != SNMPERR_SUCCESS) { DEBUGMSGTL(("usm","%s\n", "Failed updating remote boot/time.")); *error = SNMPERR_USM_GENERICERROR; return -1; } *error = SNMPERR_SUCCESS; return 0; /* Fresh message and time updated */ } /* endif -- local or remote time reference. */} /* end usm_check_and_update_timeliness() *//*******************************************************************-o-****** * usm_process_in_msg * * Parameters: * (See list below...) * * Returns: * SNMPERR_SUCCESS On success. * SNMPERR_USM_AUTHENTICATIONFAILURE * SNMPERR_USM_DECRYPTIONERROR * SNMPERR_USM_GENERICERROR * SNMPERR_USM_PARSEERROR * SNMPERR_USM_UNKNOWNENGINEID * SNMPERR_USM_PARSEERROR * SNMPERR_USM_UNKNOWNSECURITYNAME * SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL * * * ASSUMES size of decrypt_buf will always be >= size of encrypted sPDU. * * FIX Memory leaks if secStateRef is allocated and a return occurs * without cleaning up. May contain secrets... */intusm_process_in_msg ( int msgProcModel, /* (UNUSED) */ size_t maxMsgSize, /* IN - Used to calc maxSizeResponse. */ u_char *secParams, /* IN - BER encoded securityParameters.*/ int secModel, /* (UNUSED) */ int secLevel, /* IN - AuthNoPriv, authPriv etc. */ u_char *wholeMsg, /* IN - Original v3 message. */ size_t wholeMsgLen, /* IN - Msg length. */ u_char *secEngineID, /* OUT - Pointer snmpEngineID. */ size_t *secEngineIDLen, /* IN/OUT - Len available, len returned. */ /* NOTE: Memory provided by caller. */ char *secName, /* OUT - Pointer to securityName. */ size_t *secNameLen, /* IN/OUT - Len available, len returned. */ u_char **scopedPdu, /* OUT - Pointer to plaintext scopedPdu.*/ size_t *scopedPduLen, /* IN/OUT - Len available, len returned. */ size_t *maxSizeResponse, /* OUT - Max size of Response PDU. */ void **secStateRf) /* OUT - Ref to security state. */{ size_t remaining = wholeMsgLen - (u_int) ((u_long)*secParams-(u_long)*wholeMsg); u_int boots_uint; u_int time_uint; u_char signature[BYTESIZE(USM_MAX_KEYEDHASH_LENGTH)]; size_t signature_length = BYTESIZE(USM_MAX_KEYEDHASH_LENGTH); u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH); u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)]; u_int iv_length = BYTESIZE(USM_MAX_SALT_LENGTH); u_char *data_ptr; u_char *value_ptr; u_char type_value; u_char *end_of_overhead; int error; int i; struct usmStateReference **secStateRef = (struct usmStateReference **)secStateRf; struct usmUser *user; DEBUGMSGTL(("usm","USM processing begun...\n")); if (secStateRef) /* FIX -- huh? destroy it? */ { *secStateRef = usm_malloc_usmStateReference(); if (*secStateRef == NULL) { DEBUGMSGTL(("usm", "Out of memory.\n")); return SNMPERR_USM_GENERICERROR; } } /* * Make sure the *secParms is an OCTET STRING. * Extract the user name, engine ID, and security level. */ if ( usm_parse_security_parameters ( secParams, remaining, secEngineID, secEngineIDLen, &boots_uint, &time_uint, secName, secNameLen, signature, &signature_length, salt, &salt_length, &data_ptr) == -1 ) { DEBUGMSGTL(("usm","Parsing failed.\n")); if (snmp_increment_statistic (STAT_SNMPINASNPARSEERRS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } return SNMPERR_USM_PARSEERROR; } if (secStateRef) { /* Cache the name, engine ID, and security level, * per step 2 (section 3.2) */ if ( usm_set_usmStateReference_name ( *secStateRef, secName, *secNameLen) == -1 ) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache name.")); return SNMPERR_USM_GENERICERROR; } if ( usm_set_usmStateReference_engine_id ( *secStateRef, secEngineID, *secEngineIDLen) == -1 ) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache engine id.")); return SNMPERR_USM_GENERICERROR; } if ( usm_set_usmStateReference_sec_level ( *secStateRef, secLevel) == -1 ) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache security level.")); return SNMPERR_USM_GENERICERROR; } } /* * Locate the engine ID record. * If it is unknown, then either create one or note this as an error. */ if (reportErrorOnUnknownID) { if (ISENGINEKNOWN(secEngineID, *secEngineIDLen)==FALSE) { DEBUGMSGTL(("usm","Unknown Engine ID.\n")); if (snmp_increment_statistic ( STAT_USMSTATSUNKNOWNENGINEIDS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } return SNMPERR_USM_UNKNOWNENGINEID; } } else { if ( ENSURE_ENGINE_RECORD(secEngineID,*secEngineIDLen) != SNMPERR_SUCCESS ) { DEBUGMSGTL(("usm","%s\n", "Couldn't ensure engine record.")); return SNMPERR_USM_GENERICERROR; } } /* * Locate the User record. * If the user/engine ID is unknown, report this as an error. */ if ( (user = usm_get_user(secEngineID, *secEngineIDLen, secName)) == NULL ) { DEBUGMSGTL(("usm","Unknown User.\n")); if (snmp_increment_statistic (STAT_USMSTATSUNKNOWNUSERNAMES)==0) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } return SNMPERR_USM_UNKNOWNSECURITYNAME; } /* * Make sure the security level is appropriate. */ if (usm_check_secLevel(secLevel, user) == 1) { DEBUGMSGTL(("usm","Unsupported Security Level.\n")); if (snmp_increment_statistic (STAT_USMSTATSUNSUPPORTEDSECLEVELS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; } /* * Check the authentication credentials of the message. */ if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { if ( sc_check_keyed_hash ( user->authProtocol, user->authProtocolLen, user->authKey, user->authKeyLen, wholeMsg, wholeMsgLen, signature, signature_length) != SNMP_ERR_NOERROR ) { DEBUGMSGTL(("usm","Verification failed.\n")); if (snmp_increment_statistic (STAT_USMSTATSWRONGDIGESTS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); } return SNMPERR_USM_AUTHENTICATIONFAILURE; } DEBUGMSGTL(("usm","Verification succeeded.\n")); } /* * Steps 10-11 user is already set - relocated before timeliness * check in case it fails - still save user data for response. * * Cache the keys and protocol oids, per step 11 (s3.2). */ if (secStateRef) { if (usm_set_usmStateReference_auth_protocol (*secStateRef, user->authProtocol, user->authProtocolLen) ==-1) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache authentication protocol.")); return SNMPERR_USM_GENERICERROR; } if (usm_set_usmStateReference_auth_key (*secStateRef, user->authKey, user->authKeyLen) == -1) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache authentiation key.")); return SNMPERR_USM_GENERICERROR; } if (usm_set_usmStateReference_priv_protocol (*secStateRef, user->privProtocol, user->privProtocolLen) ==-1) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy protocol.")); return SNMPERR_USM_GENERICERROR; } if (usm_set_usmStateReference_priv_key (*secStateRef, user->privKey, user->privKeyLen) == -1) { DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy key.")); return SNMPERR_USM_GENERICERROR; } } /* * Perform the timeliness/time manager functions. */ if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { if ( usm_check_and_update_timeliness ( secEngineID, *secEngineIDLen, boots_uint, time_uint, &error) == -1 ) { return error; } }#ifdef LCD_TIME_SYNC_OPT /* * Cache the unauthenticated time to use in case we don't have * anything better - this guess will be no worse than (0,0) * that we normally use. */ else { set_enginetime(secEngineID, *secEngineIDLen, boots_uint, time_uint, FALSE); }#endif /* LCD_TIME_SYNC_OPT */ /* * If needed, decrypt the scoped PDU. */ if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { remaining = wholeMsgLen - (data_ptr - wholeMsg); if ((value_ptr = asn_parse_sequence (data_ptr, &remaining, &type_value, (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), "encrypted sPDU")) == NULL) { DEBUGMSGTL(("usm","%s\n", "Failed while parsing encrypted sPDU.")); if (snmp_increment_statistic (STAT_SNMPINASNPARSEERRS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed increment statistic.")); } return SNMPERR_USM_PARSEERROR; } end_of_overhead = value_ptr; /* * XOR the salt with the last (iv_length) bytes * of the priv_key to obtain the IV. */ for (i = 0; i < (int)iv_length; i++) iv[i] = salt[i] ^ user->privKey[iv_length + i]; if (sc_decrypt ( user->privProtocol, user->privProtocolLen, user->privKey, user->privKeyLen, iv, iv_length, value_ptr, remaining, *scopedPdu, scopedPduLen) != SNMP_ERR_NOERROR) { DEBUGMSGTL(("usm","%s\n", "Failed decryption.")); if (snmp_increment_statistic (STAT_USMSTATSDECRYPTIONERRORS)==0) { DEBUGMSGTL(("usm","%s\n", "Failed increment statistic.")); } return SNMPERR_USM_DECRYPTIONERROR; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?