📄 snmpusm.c
字号:
* (See list below...) * * Returns: * 0 On success, * -1 Otherwise. * * * This routine calculates the offsets into an outgoing message buffer * for the necessary values. The outgoing buffer will generically * look like this: * * SNMPv3 Message * SEQ len[11] * INT len version * Header * 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 */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 = ROUNDUP8(scopedPduLen); 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_DES_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 || (*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); if (msgSalt) 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() */#ifdef HAVE_AES/*******************************************************************-o-****** * usm_set_aes_iv * * Parameters: * *iv (O) Buffer to contain IV. * *iv_length (O) Length of iv. * net_boots (I) the network byte order of the authEng boots val * net_time (I) the network byte order of the authEng time val * *salt (O) A buffer for the outgoing salt (= 8 bytes of iv) * * Returns: * 0 On success, * -1 Otherwise. * * Determine the initialization vector for AES encryption. * (draft-blumenthal-aes-usm-03.txt, 3.1.2.2) * * iv is defined as the concatenation of engineBoots, engineTime and a 64 bit salt-integer. * The 64 bit salt integer is incremented. * The resulting salt is copied into the salt buffer. * The IV result is returned individually for further use. */intusm_set_aes_iv(u_char * iv, size_t * iv_length, u_int net_boots, u_int net_time, u_char * salt){ /* * net_* should be encoded in network byte order. */ int net_salt_int1, net_salt_int2;#define PROPER_AES_IV_SIZE 64 /* * Sanity check. */ if (!iv || !iv_length) { return -1; } net_salt_int1 = htonl(salt_integer64_1); net_salt_int2 = htonl(salt_integer64_2); if ((salt_integer64_2 += 1) == 0) salt_integer64_2 += 1; /* XXX: warning: hard coded proper lengths */ memcpy(iv, &net_boots, 4); memcpy(iv+4, &net_time, 4); memcpy(iv+8, &net_salt_int1, 4); memcpy(iv+12, &net_salt_int2, 4); memcpy(salt, iv+8, 8); /* only copy the needed portion */ return 0;} /* end usm_set_salt() */#endif /* HAVE_AES */intusm_secmod_generate_out_msg(struct snmp_secmod_outgoing_params *parms){ if (!parms) return SNMPERR_GENERR; return usm_generate_out_msg(parms->msgProcModel, parms->globalData, parms->globalDataLen, parms->maxMsgSize, parms->secModel, parms->secEngineID, parms->secEngineIDLen, parms->secName, parms->secNameLen, parms->secLevel, parms->scopedPdu, parms->scopedPduLen, parms->secStateRef, parms->secParams, parms->secParamsLen, parms->wholeMsg, parms->wholeMsgLen);}/*******************************************************************-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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -