⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snmpusm.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}

	if (*signature_length != 0) /* Blanking for authentication step later */
	{
		memset (next_ptr-(u_long)*signature_length,
						0, *signature_length);
	}


	/* 
	 * Retrieve the salt.
	 *
	 * Note that the next ptr is where the data section starts.
	 */
        DEBUGDUMPHEADER("dump_recv", "Parsing msgPrivacyParameters\n");
	if ( (*data_ptr
		= asn_parse_string (next_ptr, &remaining_bytes, &type_value,
			salt, salt_length)) == NULL )
	{
		DEBUGINDENTLESS();
                /* RETURN parse error */ return -1;
	}
        DEBUGINDENTLESS();

	if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR))
	{
		/* RETURN parse error */ return -1;
	}

	return 0;

}  /* end usm_parse_security_parameters() */




/*******************************************************************-o-******
 * usm_check_and_update_timeliness
 *
 * Parameters:
 *	*secEngineID
 *	 secEngineIDen
 *	 boots_uint
 *	 time_uint
 *	*error
 *      
 * Returns:
 *	0	On success,
 *	-1	Otherwise.
 *	
 *
 * Performs the incoming timeliness checking and setting.
 */
int
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...
 */
int
usm_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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -