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 + -
显示快捷键?