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

📄 snmpusm.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *		SEQ len
 *			INT len MsgID
 *			INT len msgMaxSize
 *			OST len msgFlags (OST = OCTET STRING)
 *			INT len msgSecurityModel
 *	MsgSecurityParameters
 *		[1] OST len[2]
 *			SEQ len[3]
 *				OST len msgAuthoritativeEngineID
 *				INT len msgAuthoritativeEngineBoots
 *				INT len msgAuthoritativeEngineTime
 *				OST len msgUserName
 *				OST len[4] [5] msgAuthenticationParameters
 *				OST len[6] [7] msgPrivacyParameters
 *	MsgData
 *		[8] OST len[9] [10] encryptedPDU
 *		or
 *		[8,10] SEQUENCE len[9] scopedPDU
 *	[12]
 *
 *	The bracketed points will be needed to be identified ([x] is an index
 *	value, len[x] means a length value).  Here is a semantic guide to them:
 *
 *	[1] = globalDataLen (input)
 *	[2] = otstlen
 *	[3] = seq_len
 *	[4] = msgAuthParmLen (may be 0 or 12)
 *	[5] = authParamsOffset
 *	[6] = msgPrivParmLen (may be 0 or 8)
 *	[7] = privParamsOffset
 *	[8] = globalDataLen + msgSecParmLen
 *	[9] = datalen
 *	[10] = dataOffset
 *	[11] = theTotalLength - the length of the header itself
 *	[12] = theTotalLength
 */
int
usm_calc_offsets (
	size_t  globalDataLen,	/* SNMPv3Message + HeaderData */
	int     secLevel,
	size_t  secEngineIDLen,
	size_t  secNameLen,
	size_t  scopedPduLen,	/* An BER encoded sequence. */
	u_long  engineboots,	/* XXX (asn1.c works in long, not int.) */
	long    engine_time,	/* XXX (asn1.c works in long, not int.) */

	size_t *theTotalLength,	 /* globalDataLen + msgSecurityP. + msgData */
	size_t *authParamsOffset,/* Distance to auth bytes.                 */
	size_t *privParamsOffset,/* Distance to priv bytes.                 */
	size_t *dataOffset,	 /* Distance to scopedPdu SEQ  -or-  the
				  *   crypted (data) portion of msgData.    */

	size_t *datalen,	/* Size of msgData OCTET STRING encoding.  */
	size_t *msgAuthParmLen,	/* Size of msgAuthenticationParameters.    */
	size_t *msgPrivParmLen,	/* Size of msgPrivacyParameters.           */
	size_t *otstlen,	/* Size of msgSecurityP. O.S. encoding.    */
	size_t *seq_len,	/* Size of msgSecurityP. SEQ data.         */
	size_t *msgSecParmLen)	/* Size of msgSecurityP. SEQ.              */
{
	int	engIDlen,	/* Sizes of OCTET STRING and SEQ encodings */
		engBtlen,	/*   for fields within                     */
		engTmlen,	/*   msgSecurityParameters portion of      */
		namelen,	/*   SNMPv3Message.                        */
		authlen,
		privlen;

	/* 
	 * If doing authentication, msgAuthParmLen = 12 else msgAuthParmLen = 0.
	 * If doing encryption,     msgPrivParmLen = 8  else msgPrivParmLen = 0.
	 */
	*msgAuthParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
		|| secLevel == SNMP_SEC_LEVEL_AUTHPRIV)?12:0;

	*msgPrivParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHPRIV)?8:0;


	/* 
	 * Calculate lengths.
	 */
	if ( (engIDlen = asn_predict_length(ASN_OCTET_STR,
				0, secEngineIDLen)) == -1 )
	{
		return -1;
	}

	if ( (engBtlen = asn_predict_length (ASN_INTEGER,
				(u_char*)&engineboots,sizeof(long))) == -1 )
	{
		return -1;
	}

	if ( (engTmlen = asn_predict_length (ASN_INTEGER,
				(u_char*)&engine_time,sizeof(long))) == -1 )
	{
		return -1;
	}

	if ( (namelen = asn_predict_length (ASN_OCTET_STR,0,secNameLen))==-1 )
	{
		return -1;
	}

	if ( (authlen = asn_predict_length (ASN_OCTET_STR,
				0,*msgAuthParmLen)) == -1 )
	{
		return -1;
	}

	if ( (privlen = asn_predict_length (ASN_OCTET_STR,
				0,*msgPrivParmLen)) == -1 )
	{
		return -1;
	}

	*seq_len = engIDlen + engBtlen + engTmlen + namelen + authlen + privlen;

	if ( (*otstlen = asn_predict_length (ASN_SEQUENCE,
				0, *seq_len)) == -1 )
	{
		return -1;
	}

	if ( (*msgSecParmLen = asn_predict_length (ASN_OCTET_STR,
				0,*otstlen)) == -1 )
	{
		return -1;
	}

	*authParamsOffset =	globalDataLen +
		+ (*msgSecParmLen - *seq_len)
		+ engIDlen + engBtlen + engTmlen + namelen
		+ (authlen - *msgAuthParmLen);

	*privParamsOffset =	*authParamsOffset + *msgAuthParmLen
		+ (privlen - *msgPrivParmLen);


	/*
	 * Compute the size of the plaintext.  Round up to account for cipher
	 * block size, if necessary.
	 *
	 * XXX  This is hardwired for 1DES... If scopedPduLen is already
	 *	a multiple of 8, then *add* 8 more; otherwise, round up
	 *	to the next multiple of 8.
	 *
	 * FIX  Calculation of encrypted portion of msgData and consequent
	 *	setting and sanity checking of theTotalLength, et al. should
	 *	occur *after* encryption has taken place.
	 */
	if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV)
	{
		scopedPduLen = ( scopedPduLen % 8 )
					? ROUNDUP8(scopedPduLen)
					: scopedPduLen + 8;

		if ((*datalen = 
			asn_predict_length (ASN_OCTET_STR,0,scopedPduLen))==-1)
		{
			return -1;
		}
	}
	else
	{
		*datalen = scopedPduLen;
	}

	*dataOffset	= globalDataLen + *msgSecParmLen +
						(*datalen - scopedPduLen);
	*theTotalLength = globalDataLen + *msgSecParmLen + *datalen;

	return 0;

}  /* end usm_calc_offsets() */





/*******************************************************************-o-******
 * usm_set_salt
 *
 * Parameters:
 *	*iv		  (O)   Buffer to contain IV.
 *	*iv_length	  (O)   Length of iv.
 *	*priv_salt	  (I)   Salt portion of private key.
 *	 priv_salt_length (I)   Length of priv_salt.
 *	*msgSalt	  (I/O) Pointer salt portion of outgoing msg buffer.
 *      
 * Returns:
 *	0	On success,
 *	-1	Otherwise.
 *
 *	Determine the initialization vector for the DES-CBC encryption.
 *	(Cf. RFC 2274, 8.1.1.1.)
 *
 *	iv is defined as the concatenation of engineBoots and the
 *		salt integer.
 *	The salt integer is incremented.
 *	The resulting salt is copied into the msgSalt buffer.
 *	The result of the concatenation is then XORed with the salt
 *		portion of the private key (last 8 bytes).
 *	The IV result is returned individually for further use.
 */
int
usm_set_salt (	u_char		*iv,
		size_t		*iv_length,
		u_char		*priv_salt,
		size_t		 priv_salt_length,
		u_char		*msgSalt)
{
	size_t propersize_salt     = BYTESIZE(USM_MAX_SALT_LENGTH);
	int net_boots;
        int net_salt_int;
		/* net_* should be encoded in network byte order.  XXX  Why?
		 */
	int iindex;


	/*
	 * Sanity check.
	 */
	if ( !iv || !iv_length || !priv_salt || !msgSalt
		|| (*iv_length != propersize_salt)
             	|| (priv_salt_length < propersize_salt) )
	{
        	return -1;
	}


	net_boots 	= htonl(snmpv3_local_snmpEngineBoots());
        net_salt_int	= htonl(salt_integer);

	salt_integer += 1;

	memcpy(iv,			&net_boots,	propersize_salt/2);
	memcpy(iv+(propersize_salt/2), &net_salt_int,	propersize_salt/2);

	memcpy(msgSalt, iv, propersize_salt);


	/* 
	 * Turn the salt into an IV: XOR <boots, salt_int> with salt
	 * portion of priv_key.
	 */
	for (iindex = 0; iindex < (int)propersize_salt; iindex++)
		iv[iindex] ^= priv_salt[iindex];


	return 0;

}  /* end usm_set_salt() */




/*******************************************************************-o-******
 * usm_generate_out_msg
 *
 * Parameters:
 *	(See list below...)
 *      
 * Returns:
 *	SNMPERR_SUCCESS			On success.
 *	SNMPERR_USM_AUTHENTICATIONFAILURE
 *	SNMPERR_USM_ENCRYPTIONERROR
 *	SNMPERR_USM_GENERICERROR
 *	SNMPERR_USM_UNKNOWNSECURITYNAME
 *	SNMPERR_USM_GENERICERROR
 *	SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL
 *	
 *
 * Generates an outgoing message.
 *
 * XXX	Beware of misnomers!
 */
int
usm_generate_out_msg (
     int      msgProcModel,	/* (UNUSED) */

     u_char  *globalData,	/* IN */
		/* Pointer to msg header data will point to the beginning
		 * of the entire packet buffer to be transmitted on wire,
		 * memory will be contiguous with secParams, typically
		 * this pointer will be passed back as beginning of
		 * wholeMsg below.  asn seq. length is updated w/ new length.
		 *
		 * While this points to a buffer that should be big enough
		 * for the whole message, only the first two parts
		 * of the message are completed, namely SNMPv3Message and
		 * HeaderData.  globalDataLen (next parameter) represents
		 * the length of these two completed parts.
		 */

     size_t   globalDataLen,	/* IN - Length of msg header data.	*/
     int      maxMsgSize,	/* (UNUSED) */
     int      secModel,		/* (UNUSED) */
     u_char  *secEngineID,	/* IN - Pointer snmpEngineID.		*/
     size_t   secEngineIDLen,	/* IN - SnmpEngineID length.		*/
     char    *secName,		/* IN - Pointer to securityName.	*/
     size_t   secNameLen,	/* IN - SecurityName length.		*/
     int      secLevel,		/* IN - AuthNoPriv, authPriv etc.	*/

     u_char  *scopedPdu,	/* IN */
		/* Pointer to scopedPdu will be encrypted by USM if needed
		 * and written to packet buffer immediately following
		 * securityParameters, entire msg will be authenticated by
		 * USM if needed.
		 */

     size_t   scopedPduLen,	/* IN - scopedPdu length. */

     void    *secStateRef,	/* IN */
		/* secStateRef, pointer to cached info provided only for
		 * Response, otherwise NULL.
		 */

     u_char  *secParams,	/* OUT */
		/* BER encoded securityParameters pointer to offset within
		 * packet buffer where secParams should be written, the
		 * entire BER encoded OCTET STRING (including header) is
		 * written here by USM secParams = globalData +
		 * globalDataLen.
		 */

     size_t  *secParamsLen,	/* IN/OUT - Len available, len returned. */

     u_char **wholeMsg,         /* OUT */
		/* Complete authenticated/encrypted message - typically
		 * the pointer to start of packet buffer provided in
		 * globalData is returned here, could also be a separate
		 * buffer.
		 */

     size_t *wholeMsgLen)          /* IN/OUT - Len available, len returned. */
{
	size_t otstlen;
	size_t seq_len;
	size_t msgAuthParmLen;
	size_t msgPrivParmLen;
	size_t msgSecParmLen;
	size_t authParamsOffset;
	size_t privParamsOffset;
	size_t datalen;
	size_t dataOffset;
	size_t theTotalLength;

	u_char         *ptr;
	size_t          ptr_len;
	size_t          remaining;
	size_t          offSet;
	u_int           boots_uint;
	u_int           time_uint;
	long            boots_long;
	long            time_long;

	/*
		Indirection because secStateRef values override parameters.

		None of these are to be free'd - they are either pointing to
		what's in the secStateRef or to something either in the
		actual prarmeter list or the user list.
	*/

	char   *theName		 	= NULL;
	u_int   theNameLength		= 0;
	u_char *theEngineID		= NULL;
	u_int   theEngineIDLength	= 0;
	u_char *theAuthKey		= NULL;
	u_int   theAuthKeyLength	= 0;
	oid    *theAuthProtocol		= NULL;
	u_int   theAuthProtocolLength	= 0;
	u_char *thePrivKey		= NULL;
	u_int   thePrivKeyLength	= 0;
	oid    *thePrivProtocol		= NULL;
	u_int   thePrivProtocolLength	= 0;
	int     theSecLevel		= 0;	/* No defined const for bad
						 * value (other then err).
						 */


	DEBUGMSGTL(("usm","USM processing has begun.\n"));

	if (secStateRef != NULL)
	{
		/* To hush the compiler for now.  XXX */
		struct usmStateReference *ref
				= (struct usmStateReference *)secStateRef;

		theName		 	= ref->usr_name;
		theNameLength		= ref->usr_name_length;
		theEngineID		= ref->usr_engine_id;
		theEngineIDLength	= ref->usr_engine_id_length;

		if (!theEngineIDLength) {
		  theEngineID		= secEngineID;
		  theEngineIDLength	= secEngineIDLen;
		}

		theAuthProtocol		= ref->usr_auth_protocol;
		theAuthProtocolLength	= ref->usr_auth_protocol_length;
		theAuthKey		= ref->usr_auth_key;
		theAuthKeyLength	= ref->usr_auth_key_length;
		thePrivProtocol		= ref->usr_priv_protocol;
		thePrivProtocolLength	= ref->usr_priv_protocol_length;
		thePrivKey		= ref->usr_priv_key;
		thePrivKeyLength	= ref->usr_priv_key_length;
		theSecLevel		= ref->usr_sec_level;
	}

	/* 
	 * Identify the user record.
	 */
	else
	{
		struct usmUser *user;

                /* we do allow an unknown user name for
                   unauthenticated requests. */
		if ( (user = 
			usm_get_user(secEngineID, secEngineIDLen, secName))
				== NULL &&
                     			secLevel != SNMP_SEC_LEVEL_NOAUTH)
		{
			DEBUGMSGTL(("usm","Unknown User\n"));
			usm_free_usmStateReference (secStateRef);
			return SNMPERR_USM_UNKNOWNSECURITYNAME;
		}

		theName		 	= secName;
		theNameLength		= secNameLen;
		theEngineID		= secEngineID;
                theSecLevel		= secLevel;
		theEngineIDLength	= secEngineIDLen;
                if (user) {
                  theAuthProtocol	= user->authProtocol;
                  theAuthProtocolLength	= user->authProtocolLen;
                  theAuthKey		= user->authKey;
                  theAuthKeyLength	= user->authKeyLen;
                  thePrivProtocol	= user->privProtocol;
                  thePrivProtocolLength	= user->privProtocolLen;
                  thePrivKey		= user->privKey;
                  thePrivKeyLength	= user->privKeyLen;
                } else {
                  /* unknown users can not do authentication (obviously) */
                  theAuthProtocol	= usmNoAuthProtocol;
                  theAuthProtocolLength	= sizeof(usmNoAuthProtocol)/sizeof(oid);
                  theAuthKey		= NULL;
                  theAuthKeyLength	= 0;
                  thePrivProtocol	= usmNoPrivProtocol;
                  thePrivProtocolLength	= sizeof(usmNoPrivProtocol)/sizeof(oid);
                  thePrivKey		= NULL;
                  thePrivKeyLength	= 0;
                }
	}  /* endif -- secStateRef==NULL */


	/*
		From here to the end of the function, avoid reference to
		secName, secEngineID, secLevel, and associated lengths.
	*/


	/* 
	 * Check to see if the user can use the requested sec services.
	 */
	if (usm_check_secLevel_vs_protocols(
		theSecLevel,
		theAuthProtocol, theAuthProtocolLength,
		theAuthProtocol, theAuthProtocolLength) == 1)
	{
		DEBUGMSGTL(("usm","Unsupported Security Level\n"));
		usm_free_usmStateReference (secStateRef);
		return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
	}


	/* 
	 * Retrieve the engine information.
	 *
	 * XXX	No error is declared in the EoP when sending messages to

⌨️ 快捷键说明

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