snmpusm.c

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

C
2,486
字号
 *	[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 */intusm_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. */intusm_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! */intusm_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         * 	unknown engines, processing continues w/ boots/time == (0,0).	 */	if (get_enginetime (theEngineID, theEngineIDLength, 			    &boots_uint, &time_uint, FALSE) == -1)	{		DEBUGMSGTL(("usm","%s\n", "Failed to find engine data."));	}	boots_long = boots_uint;	time_long  = time_uint;		/* 	 * Set up the Offsets.	 */	if (usm_calc_offsets (globalDataLen, theSecLevel, theEngineIDLength,		theNameLength, scopedPduLen, boots_long, time_long,		&theTotalLength, &authParamsOffset,		&privParamsOffset, &dataOffset, &datalen,		&msgAuthParmLen, &msgPrivParmLen,		&otstlen, &seq_len, &msgSecParmLen) == -1)	{		DEBUGMSGTL(("usm","Failed calculating offsets.\n"));		usm_free_usmStateReference (secStateRef);		return SNMPERR_USM_GENERICERROR;	}	/*		So, we have the offsets for the three parts that need to be		determined, and an overall length.  Now we need to make		sure all of this would fit in the outgoing buffer, and		whether or not we need to make a new buffer, etc.	*/	/* 

⌨️ 快捷键说明

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