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