snmpusm.c

来自「eCos操作系统源码」· C语言 代码 · 共 2,486 行 · 第 1/5 页

C
2,486
字号
	 * Set wholeMsg as a pointer to globalData.  Sanity check for	 * the proper size.	 * 	 * Mark workspace in the message with bytes of all 1's to make it	 * easier to find mistakes in raw message dumps.	 */	ptr = *wholeMsg = globalData;	if (theTotalLength > *wholeMsgLen)	{		DEBUGMSGTL(("usm","Message won't fit in buffer.\n"));		usm_free_usmStateReference (secStateRef);		return SNMPERR_USM_GENERICERROR;	}	ptr_len = *wholeMsgLen = theTotalLength;#ifdef SNMP_TESTING_CODE	memset (&ptr[globalDataLen], 0xFF, theTotalLength-globalDataLen);#endif /* SNMP_TESTING_CODE */	/* 	 * Do the encryption.	 */	if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV)	{		size_t	encrypted_length = theTotalLength - dataOffset;		size_t	salt_length	 = BYTESIZE(USM_MAX_SALT_LENGTH);                u_char	salt[BYTESIZE(USM_MAX_SALT_LENGTH)];		/* XXX  Hardwired to seek into a 1DES private key!		 */		if ( usm_set_salt(	salt,		&salt_length,					thePrivKey+8,	thePrivKeyLength-8,                        		&ptr[privParamsOffset])						== -1 )		{			DEBUGMSGTL(("usm","Can't set DES-CBC salt.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_GENERICERROR;		}		if ( sc_encrypt(			 thePrivProtocol,	 thePrivProtocolLength,			 thePrivKey,		 thePrivKeyLength,                         salt,			 salt_length,			 scopedPdu,		 scopedPduLen,			&ptr[dataOffset],	&encrypted_length)							!= SNMP_ERR_NOERROR )		{			DEBUGMSGTL(("usm","DES-CBC error.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_ENCRYPTIONERROR;		}#ifdef SNMP_TESTING_CODE		if ( debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {			dump_chunk("usm/dump", "This data was encrypted:",					scopedPdu, scopedPduLen);			dump_chunk("usm/dump", "salt + Encrypted form:",					salt, salt_length);			dump_chunk("usm/dump", NULL,					&ptr[dataOffset], encrypted_length);			dump_chunk("usm/dump", "*wholeMsg:",					*wholeMsg, theTotalLength);		}#endif		ptr 	= *wholeMsg;		ptr_len = *wholeMsgLen = theTotalLength;		/* 		 * XXX  Sanity check for salt length should be moved up		 *	under usm_calc_offsets() or tossed.		 */		if ( (encrypted_length != (theTotalLength - dataOffset))				|| (salt_length != msgPrivParmLen) )		{			DEBUGMSGTL(("usm","DES-CBC length error.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_ENCRYPTIONERROR;		}		DEBUGMSGTL(("usm","Encryption successful.\n"));	}	/* 	 * No encryption for you!	 */	else	{		memcpy( &ptr[dataOffset], scopedPdu, scopedPduLen );	}	/* 	 * Start filling in the other fields (in prep for authentication).	 * 	 * offSet is an octet string header, which is different from all	 * the other headers.	 */	remaining = ptr_len - globalDataLen;	offSet =  ptr_len - remaining;	asn_build_header (&ptr[offSet], &remaining, 		(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), otstlen);	offSet = ptr_len - remaining;	asn_build_sequence (&ptr[offSet], &remaining, 		(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len);		offSet = ptr_len - remaining;	asn_build_string (&ptr[offSet], &remaining,		(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),		theEngineID, theEngineIDLength);		offSet = ptr_len - remaining;	asn_build_int (&ptr[offSet], &remaining,		(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),		&boots_long, sizeof(long));		offSet = ptr_len - remaining;	asn_build_int (&ptr[offSet], &remaining,		(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),		&time_long, sizeof(long));		offSet = ptr_len - remaining;	asn_build_string (&ptr[offSet], &remaining,		(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),		(u_char *)theName, theNameLength);	/*		Note: if there is no authentication being done,		msgAuthParmLen is 0, and there is no effect (other than		inserting a zero-length header) of the following		statements.	*/	offSet = ptr_len - remaining;	asn_build_header(			&ptr[offSet],			&remaining,			(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),			msgAuthParmLen);	if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV		|| theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV)	{		offSet = ptr_len - remaining;		memset (&ptr[offSet],0,msgAuthParmLen);	}	remaining -= msgAuthParmLen;	/*		Note: if there is no encryption being done, msgPrivParmLen		is 0, and there is no effect (other than inserting a		zero-length header) of the following statements.	*/	offSet = ptr_len - remaining;	asn_build_header(		&ptr[offSet],		&remaining,		(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),		msgPrivParmLen);	remaining -= msgPrivParmLen;	/* Skipping the IV already there. */	/* 	 * For privacy, need to add the octet string header for it.	 */	if (theSecLevel==SNMP_SEC_LEVEL_AUTHPRIV)	{		offSet = ptr_len - remaining;		asn_build_header(			&ptr[offSet],			&remaining,			(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),			theTotalLength - dataOffset );	}	/* 	 * Adjust overall length and store it as the first SEQ length	 * of the SNMPv3Message.	 *	 * FIX	4 is a magic number!	 */	remaining = theTotalLength;	asn_build_sequence (ptr, &remaining, 		(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), theTotalLength-4);	/* 	 * Now, time to consider / do authentication.	 */	if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV		|| theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV)	{		size_t	temp_sig_len	= msgAuthParmLen;		u_char *temp_sig	= (u_char *) malloc (temp_sig_len);		if (temp_sig == NULL)		{			DEBUGMSGTL(("usm","Out of memory.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_GENERICERROR;		}		if ( sc_generate_keyed_hash (			theAuthProtocol,	 theAuthProtocolLength,			theAuthKey,		 theAuthKeyLength,			ptr,			 ptr_len,			temp_sig,		&temp_sig_len)							!= SNMP_ERR_NOERROR )		{			/* FIX temp_sig_len defined?!			 */			SNMP_ZERO(temp_sig, temp_sig_len);			SNMP_FREE(temp_sig);			DEBUGMSGTL(("usm","Signing failed.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_AUTHENTICATIONFAILURE;		}		if (temp_sig_len != msgAuthParmLen)		{			SNMP_ZERO(temp_sig, temp_sig_len);			SNMP_FREE(temp_sig);			DEBUGMSGTL(("usm","Signing lengths failed.\n"));			usm_free_usmStateReference (secStateRef);			return SNMPERR_USM_AUTHENTICATIONFAILURE;		}		memcpy (&ptr[authParamsOffset], temp_sig, msgAuthParmLen);		SNMP_ZERO(temp_sig, temp_sig_len);		SNMP_FREE(temp_sig);	}  /* endif -- create keyed hash */	usm_free_usmStateReference (secStateRef);	DEBUGMSGTL(("usm","USM processing completed.\n"));		return SNMPERR_SUCCESS;}  /* end usm_generate_out_msg() *//*******************************************************************-o-****** * usm_parse_security_parameters * * Parameters: *	(See list below...) *       * Returns: *	0	On success, *	-1	Otherwise. * *	tab stop 4 * *	Extracts values from the security header and data portions of the *	incoming buffer. */intusm_parse_security_parameters (	u_char  *secParams,	size_t   remaining,	u_char  *secEngineID,	size_t  *secEngineIDLen,	u_int   *boots_uint,	u_int   *time_uint,	char    *secName,	size_t  *secNameLen,	u_char  *signature,	size_t  *signature_length,	u_char  *salt,	size_t  *salt_length,	u_char **data_ptr){	u_char  *parse_ptr = secParams;	u_char  *value_ptr;	u_char  *next_ptr;	u_char   type_value;	size_t   octet_string_length = remaining;	size_t   sequence_length;	size_t   remaining_bytes;	long     boots_long;	long     time_long;	u_int    origNameLen;	/* 	 * Eat the first octet header.	 */	if ((value_ptr = asn_parse_sequence (parse_ptr, &octet_string_length,		&type_value,		(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),		"usm first octet")) == NULL)	{		/* RETURN parse error */ return -1;	}	/* 	 * Eat the sequence header.	 */	parse_ptr 	= value_ptr;	sequence_length = octet_string_length;	if ((value_ptr = asn_parse_sequence (parse_ptr, &sequence_length,		&type_value,		(ASN_SEQUENCE | ASN_CONSTRUCTOR),		"usm sequence")) == NULL)	{		/* RETURN parse error */ return -1;	}	/*	 * Retrieve the engineID.	 */	parse_ptr 	= value_ptr;	remaining_bytes = sequence_length;        DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineID\n");	if ( (next_ptr		= asn_parse_string (parse_ptr, &remaining_bytes, &type_value,			secEngineID, secEngineIDLen)) == 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;	}	/* 	 * Retrieve the engine boots, notice switch in the way next_ptr and	 * remaining_bytes are used (to accomodate the asn code).	 */        DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineBoots\n");	if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value,		&boots_long, sizeof(long))) == NULL)	{		DEBUGINDENTLESS();                /* RETURN parse error */ return -1;	}        DEBUGINDENTLESS();	if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER))	{		DEBUGINDENTLESS();                /* RETURN parse error */ return -1;	}	*boots_uint = (u_int) boots_long;	/* 	 * Retrieve the time value.	 */        DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineTime\n");	if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value,		&time_long, sizeof(long))) == NULL)	{		/* RETURN parse error */ return -1;	}	if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER))	{		  DEBUGINDENTLESS();                  /* RETURN parse error */ return -1;	}	*time_uint = (u_int) time_long;	/* 	 * Retrieve the secName.	 */	origNameLen = *secNameLen;        DEBUGDUMPHEADER("dump_recv", "Parsing msgUserName\n");	if ( (next_ptr		= asn_parse_string (next_ptr, &remaining_bytes, &type_value,			(u_char *)secName, secNameLen)) == NULL )	{                DEBUGINDENTLESS();		/* RETURN parse error */ return -1;	}        DEBUGINDENTLESS();	/* FIX -- doesn't this also indicate a buffer overrun?	 */	if ((int)origNameLen < *secNameLen + 1)	{		/* RETURN parse error, but it's really a parameter error */		return -1;	}	secName[*secNameLen] = '\0';	if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR))	{		/* RETURN parse error */ return -1;	}	/* 	 * Retrieve the signature and blank it if there.	 */        DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthenticationParameters\n");	if ( (next_ptr		= asn_parse_string (next_ptr, &remaining_bytes, &type_value,			signature, signature_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;	}	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

⌨️ 快捷键说明

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