📄 snmpusm.c
字号:
*/ 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() */#ifdef USE_REVERSE_ASNENCODINGintusm_secmod_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms){ if (!parms) return SNMPERR_GENERR; return usm_rgenerate_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->wholeMsg, parms->wholeMsgLen, parms->wholeMsgOffset);}intusm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */ u_char * globalData, /* IN */ /* * points at the msgGlobalData, which is of length given by next * parameter. */ 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 ** wholeMsg, /* IN/OUT */ /* * Points at the pointer to the packet buffer, which might get extended * if necessary via realloc(). */ size_t * wholeMsgLen, /* IN/OUT */ /* * Length of the entire packet buffer, **not** the length of the * packet. */ size_t * offset /* IN/OUT */ /* * Offset from the end of the packet buffer to the start of the packet, * also known as the packet length. */ ){ size_t msgAuthParmLen = 0;#ifdef SNMP_TESTING_CODE size_t theTotalLength;#endif 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; const oid *theAuthProtocol = NULL; u_int theAuthProtocolLength = 0; u_char *thePrivKey = NULL; u_int thePrivKeyLength = 0; const oid *thePrivProtocol = NULL; u_int thePrivProtocolLength = 0; int theSecLevel = 0; /* No defined const for bad * value (other then err). */ size_t salt_length = 0, save_salt_length = 0, save_salt_offset = 0; u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; u_char authParams[USM_MAX_AUTHSIZE]; u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)]; size_t sp_offset = 0, mac_offset = 0; int rc = 0; DEBUGMSGTL(("usm", "USM processing has begun (offset %d)\n", *offset)); 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, thePrivProtocol, thePrivProtocolLength) == 1) { DEBUGMSGTL(("usm", "Unsupported Security Level or type (%d)\n", theSecLevel)); 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; if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { /* * Initially assume that the ciphertext will end up the same size as * the plaintext plus some padding. Really sc_encrypt ought to be able * to grow this for us, a la asn_realloc_rbuild_<type> functions, but * this will do for now. */ u_char *ciphertext = NULL; size_t ciphertextlen = scopedPduLen + 64; if ((ciphertext = (u_char *) malloc(ciphertextlen)) == NULL) { DEBUGMSGTL(("usm", "couldn't malloc %d bytes for encrypted PDU\n", ciphertextlen)); usm_free_usmStateReference(secStateRef); return SNMPERR_MALLOC; } /* * XXX Hardwired to seek into a 1DES private key! */#ifdef HAVE_AES if (ISTRANSFORM(thePrivProtocol, AES128Priv) || ISTRANSFORM(thePrivProtocol, AES192Priv) || ISTRANSFORM(thePrivProtocol, AES256Priv)) { salt_length = BYTESIZE(USM_AES_SALT_LENGTH); save_salt_length = BYTESIZE(USM_AES_SALT_LENGTH)/2; save_salt_offset = 0; if (!thePrivKey || usm_set_aes_iv(salt, &salt_length, htonl(boots_uint), htonl(time_uint), iv) == -1) { DEBUGMSGTL(("usm", "Can't set AES iv.\n")); usm_free_usmStateReference(secStateRef); free(ciphertext); return SNMPERR_USM_GENERICERROR; } } else if (ISTRANSFORM(thePrivProtocol, DESPriv)) {#endif salt_length = BYTESIZE(USM_DES_SALT_LENGTH); save_salt_length = BYTESIZE(USM_DES_SALT_LENGTH); save_salt_offset = 0; if (!thePrivKey || (usm_set_salt(salt, &salt_length, thePrivKey + 8, thePrivKeyLength - 8, iv) == -1)) { DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n")); usm_free_usmStateReference(secStateRef); free(ciphertext); return SNMPERR_USM_GENERICERROR; }#ifdef HAVE_AES }#endif#ifdef SNMP_TESTING_CODE if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { dump_chunk("usm/dump", "This data was encrypted:", scopedPdu, scopedPduLen); }#endif if (sc_encrypt(thePrivProtocol, thePrivProtocolLength, thePrivKey, thePrivKeyLength, salt, salt_length, scopedPdu, scopedPduLen, ciphertext, &ciphertextlen) != SNMP_ERR_NOERROR) { DEBUGMSGTL(("usm", "DES-CBC error.\n")); usm_free_usmStateReference(secStateRef); free(ciphertext); return SNMPERR_USM_ENCRYPTIONERROR; } /* * Write the encrypted scopedPdu back into the packet buffer. */#ifdef SNMP_TESTING_CODE theTotalLength = *wholeMsgLen;#endif *offset = 0; rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), ciphertext, ciphertextlen);#ifdef SNMP_TESTING_CODE if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { dump_chunk("usm/dump", "salt + Encrypted form: ", salt, salt_length); dump_chunk("usm/dump", "wholeMsg:", (*wholeMsg + *wholeMsgLen - *offset), *offset); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -