📄 snmpusm.c
字号:
* 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.
*/
/*
* Set wholeMsg as a pointer to globalData. Sanity check for
* the proper size.
*
* Mark workspace in the message with bytes of all 1's to make it
* easier to find mistakes in raw message dumps.
*/
ptr = *wholeMsg = globalData;
if (theTotalLength > *wholeMsgLen)
{
DEBUGMSGTL(("usm","Message won't fit in buffer.\n"));
usm_free_usmStateReference (secStateRef);
return SNMPERR_USM_GENERICERROR;
}
ptr_len = *wholeMsgLen = theTotalLength;
#ifdef SNMP_TESTING_CODE
memset (&ptr[globalDataLen], 0xFF, theTotalLength-globalDataLen);
#endif /* SNMP_TESTING_CODE */
/*
* Do the encryption.
*/
if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV)
{
size_t encrypted_length = theTotalLength - dataOffset;
size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
/* XXX Hardwired to seek into a 1DES private key!
*/
if ( usm_set_salt( salt, &salt_length,
thePrivKey+8, thePrivKeyLength-8,
&ptr[privParamsOffset])
== -1 )
{
DEBUGMSGTL(("usm","Can't set DES-CBC salt.\n"));
usm_free_usmStateReference (secStateRef);
return SNMPERR_USM_GENERICERROR;
}
if ( sc_encrypt(
thePrivProtocol, thePrivProtocolLength,
thePrivKey, thePrivKeyLength,
salt, salt_length,
scopedPdu, scopedPduLen,
&ptr[dataOffset], &encrypted_length)
!= SNMP_ERR_NOERROR )
{
DEBUGMSGTL(("usm","DES-CBC error.\n"));
usm_free_usmStateReference (secStateRef);
return SNMPERR_USM_ENCRYPTIONERROR;
}
#ifdef SNMP_TESTING_CODE
if ( debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
dump_chunk("usm/dump", "This data was encrypted:",
scopedPdu, scopedPduLen);
dump_chunk("usm/dump", "salt + Encrypted form:",
salt, salt_length);
dump_chunk("usm/dump", NULL,
&ptr[dataOffset], encrypted_length);
dump_chunk("usm/dump", "*wholeMsg:",
*wholeMsg, theTotalLength);
}
#endif
ptr = *wholeMsg;
ptr_len = *wholeMsgLen = theTotalLength;
/*
* XXX Sanity check for salt length should be moved up
* under usm_calc_offsets() or tossed.
*/
if ( (encrypted_length != (theTotalLength - dataOffset))
|| (salt_length != msgPrivParmLen) )
{
DEBUGMSGTL(("usm","DES-CBC length error.\n"));
usm_free_usmStateReference (secStateRef);
return SNMPERR_USM_ENCRYPTIONERROR;
}
DEBUGMSGTL(("usm","Encryption successful.\n"));
}
/*
* No encryption for you!
*/
else
{
memcpy( &ptr[dataOffset], scopedPdu, scopedPduLen );
}
/*
* Start filling in the other fields (in prep for authentication).
*
* offSet is an octet string header, which is different from all
* the other headers.
*/
remaining = ptr_len - globalDataLen;
offSet = ptr_len - remaining;
asn_build_header (&ptr[offSet], &remaining,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), otstlen);
offSet = ptr_len - remaining;
asn_build_sequence (&ptr[offSet], &remaining,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len);
offSet = ptr_len - remaining;
asn_build_string (&ptr[offSet], &remaining,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
theEngineID, theEngineIDLength);
offSet = ptr_len - remaining;
asn_build_int (&ptr[offSet], &remaining,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&boots_long, sizeof(long));
offSet = ptr_len - remaining;
asn_build_int (&ptr[offSet], &remaining,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&time_long, sizeof(long));
offSet = ptr_len - remaining;
asn_build_string (&ptr[offSet], &remaining,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
(u_char *)theName, theNameLength);
/*
Note: if there is no authentication being done,
msgAuthParmLen is 0, and there is no effect (other than
inserting a zero-length header) of the following
statements.
*/
offSet = ptr_len - remaining;
asn_build_header(
&ptr[offSet],
&remaining,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
msgAuthParmLen);
if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
|| theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV)
{
offSet = ptr_len - remaining;
memset (&ptr[offSet],0,msgAuthParmLen);
}
remaining -= msgAuthParmLen;
/*
Note: if there is no encryption being done, msgPrivParmLen
is 0, and there is no effect (other than inserting a
zero-length header) of the following statements.
*/
offSet = ptr_len - remaining;
asn_build_header(
&ptr[offSet],
&remaining,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
msgPrivParmLen);
remaining -= msgPrivParmLen; /* Skipping the IV already there. */
/*
* For privacy, need to add the octet string header for it.
*/
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() */
/*******************************************************************-o-******
* usm_parse_security_parameters
*
* Parameters:
* (See list below...)
*
* Returns:
* 0 On success,
* -1 Otherwise.
*
* tab stop 4
*
* Extracts values from the security header and data portions of the
* incoming buffer.
*/
int
usm_parse_security_parameters (
u_char *secParams,
size_t remaining,
u_char *secEngineID,
size_t *secEngineIDLen,
u_int *boots_uint,
u_int *time_uint,
char *secName,
size_t *secNameLen,
u_char *signature,
size_t *signature_length,
u_char *salt,
size_t *salt_length,
u_char **data_ptr)
{
u_char *parse_ptr = secParams;
u_char *value_ptr;
u_char *next_ptr;
u_char type_value;
size_t octet_string_length = remaining;
size_t sequence_length;
size_t remaining_bytes;
long boots_long;
long time_long;
u_int origNameLen;
/*
* Eat the first octet header.
*/
if ((value_ptr = asn_parse_sequence (parse_ptr, &octet_string_length,
&type_value,
(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
"usm first octet")) == NULL)
{
/* RETURN parse error */ return -1;
}
/*
* Eat the sequence header.
*/
parse_ptr = value_ptr;
sequence_length = octet_string_length;
if ((value_ptr = asn_parse_sequence (parse_ptr, &sequence_length,
&type_value,
(ASN_SEQUENCE | ASN_CONSTRUCTOR),
"usm sequence")) == NULL)
{
/* RETURN parse error */ return -1;
}
/*
* Retrieve the engineID.
*/
parse_ptr = value_ptr;
remaining_bytes = sequence_length;
DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineID\n");
if ( (next_ptr
= asn_parse_string (parse_ptr, &remaining_bytes, &type_value,
secEngineID, secEngineIDLen)) == NULL )
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
DEBUGINDENTLESS();
if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR))
{
/* RETURN parse error */ return -1;
}
/*
* Retrieve the engine boots, notice switch in the way next_ptr and
* remaining_bytes are used (to accomodate the asn code).
*/
DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineBoots\n");
if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value,
&boots_long, sizeof(long))) == NULL)
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
DEBUGINDENTLESS();
if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER))
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
*boots_uint = (u_int) boots_long;
/*
* Retrieve the time value.
*/
DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineTime\n");
if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value,
&time_long, sizeof(long))) == NULL)
{
/* RETURN parse error */ return -1;
}
if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER))
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
*time_uint = (u_int) time_long;
/*
* Retrieve the secName.
*/
origNameLen = *secNameLen;
DEBUGDUMPHEADER("dump_recv", "Parsing msgUserName\n");
if ( (next_ptr
= asn_parse_string (next_ptr, &remaining_bytes, &type_value,
(u_char *)secName, secNameLen)) == NULL )
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
DEBUGINDENTLESS();
/* FIX -- doesn't this also indicate a buffer overrun?
*/
if ((int)origNameLen < *secNameLen + 1)
{
/* RETURN parse error, but it's really a parameter error */
return -1;
}
secName[*secNameLen] = '\0';
if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR))
{
/* RETURN parse error */ return -1;
}
/*
* Retrieve the signature and blank it if there.
*/
DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthenticationParameters\n");
if ( (next_ptr
= asn_parse_string (next_ptr, &remaining_bytes, &type_value,
signature, signature_length)) == NULL )
{
DEBUGINDENTLESS();
/* RETURN parse error */ return -1;
}
DEBUGINDENTLESS();
if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR))
{
/* RETURN parse error */ return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -