📄 snmpusm.c
字号:
}
if (*signature_length != 0) /* Blanking for authentication step later */
{
memset (next_ptr-(u_long)*signature_length,
0, *signature_length);
}
/*
* Retrieve the salt.
*
* Note that the next ptr is where the data section starts.
*/
DEBUGDUMPHEADER("dump_recv", "Parsing msgPrivacyParameters\n");
if ( (*data_ptr
= asn_parse_string (next_ptr, &remaining_bytes, &type_value,
salt, salt_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;
}
return 0;
} /* end usm_parse_security_parameters() */
/*******************************************************************-o-******
* usm_check_and_update_timeliness
*
* Parameters:
* *secEngineID
* secEngineIDen
* boots_uint
* time_uint
* *error
*
* Returns:
* 0 On success,
* -1 Otherwise.
*
*
* Performs the incoming timeliness checking and setting.
*/
int
usm_check_and_update_timeliness(
u_char *secEngineID,
size_t secEngineIDLen,
u_int boots_uint,
u_int time_uint,
int *error)
{
u_char myID[USM_MAX_ID_LENGTH];
int myIDLength = snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH);
u_int myBoots;
u_int myTime;
if ( (myIDLength > USM_MAX_ID_LENGTH) || (myIDLength < 0) )
{
/* We're probably already screwed...buffer overwrite. XXX? */
DEBUGMSGTL(("usm","Buffer overflow.\n"));
*error = SNMPERR_USM_GENERICERROR;
return -1;
}
myBoots = snmpv3_local_snmpEngineBoots();
myTime = snmpv3_local_snmpEngineTime();
/*
* IF the time involved is local
* Make sure message is inside the time window
* ELSE
* IF boots is higher or boots is the same and time is higher
* remember this new data
* ELSE
* IF !(boots same and time within USM_TIME_WINDOW secs)
* Message is too old
* ELSE
* Message is ok, but don't take time
* ENDIF
* ENDIF
* ENDIF
*/
/*
* This is a local reference.
*/
if ( (int)secEngineIDLen == myIDLength
&& memcmp (secEngineID, myID, myIDLength) == 0 )
{
u_int time_difference = myTime > time_uint ?
myTime - time_uint : time_uint - myTime;
if (boots_uint == ENGINEBOOT_MAX
|| boots_uint != myBoots
|| time_difference > USM_TIME_WINDOW)
{
if ( snmp_increment_statistic(
STAT_USMSTATSNOTINTIMEWINDOWS) == 0 )
{
DEBUGMSGTL(("usm","%s\n",
"Failed to increment statistic."));
}
DEBUGMSGTL(("usm","%s\n", "Not in local time window."));
*error = SNMPERR_USM_NOTINTIMEWINDOW;
return -1;
}
*error = SNMPERR_SUCCESS;
return 0;
}
/*
* This is a remote reference.
*/
else
{
u_int theirBoots,
theirTime,
theirLastTime;
u_int time_difference;
if ( get_enginetime_ex( secEngineID, secEngineIDLen,
&theirBoots, &theirTime,
&theirLastTime,
TRUE)
!= SNMPERR_SUCCESS)
{
DEBUGMSGTL(("usm","%s\n",
"Failed to get remote engine's times."));
*error = SNMPERR_USM_GENERICERROR;
return -1;
}
time_difference = theirTime > time_uint ?
theirTime - time_uint : time_uint - theirTime;
/*
* XXX Contrary to the pseudocode:
* See if boots is invalid first.
*/
if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint)
{
DEBUGMSGTL(("usm","%s\n", "Remote boot count invalid."));
*error = SNMPERR_USM_NOTINTIMEWINDOW;
return -1;
}
/*
* Boots is ok, see if the boots is the same but the time
* is old.
*/
if (theirBoots == boots_uint && time_uint < theirLastTime)
{
if(time_difference > USM_TIME_WINDOW)
{
DEBUGMSGTL(("usm","%s\n", "Message too old."));
*error = SNMPERR_USM_NOTINTIMEWINDOW;
return -1;
}
else /* Old, but acceptable */
{
*error = SNMPERR_SUCCESS;
return 0;
}
}
/*
Message is ok, either boots has been advanced, or
time is greater than before with the same boots.
*/
if ( set_enginetime( secEngineID, secEngineIDLen,
boots_uint, time_uint,
TRUE)
!= SNMPERR_SUCCESS)
{
DEBUGMSGTL(("usm","%s\n", "Failed updating remote boot/time."));
*error = SNMPERR_USM_GENERICERROR;
return -1;
}
*error = SNMPERR_SUCCESS;
return 0; /* Fresh message and time updated */
} /* endif -- local or remote time reference. */
} /* end usm_check_and_update_timeliness() */
/*******************************************************************-o-******
* usm_process_in_msg
*
* Parameters:
* (See list below...)
*
* Returns:
* SNMPERR_SUCCESS On success.
* SNMPERR_USM_AUTHENTICATIONFAILURE
* SNMPERR_USM_DECRYPTIONERROR
* SNMPERR_USM_GENERICERROR
* SNMPERR_USM_PARSEERROR
* SNMPERR_USM_UNKNOWNENGINEID
* SNMPERR_USM_PARSEERROR
* SNMPERR_USM_UNKNOWNSECURITYNAME
* SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL
*
*
* ASSUMES size of decrypt_buf will always be >= size of encrypted sPDU.
*
* FIX Memory leaks if secStateRef is allocated and a return occurs
* without cleaning up. May contain secrets...
*/
int
usm_process_in_msg (
int msgProcModel, /* (UNUSED) */
size_t maxMsgSize, /* IN - Used to calc maxSizeResponse. */
u_char *secParams, /* IN - BER encoded securityParameters.*/
int secModel, /* (UNUSED) */
int secLevel, /* IN - AuthNoPriv, authPriv etc. */
u_char *wholeMsg, /* IN - Original v3 message. */
size_t wholeMsgLen, /* IN - Msg length. */
u_char *secEngineID, /* OUT - Pointer snmpEngineID. */
size_t *secEngineIDLen, /* IN/OUT - Len available, len returned. */
/* NOTE: Memory provided by caller. */
char *secName, /* OUT - Pointer to securityName. */
size_t *secNameLen, /* IN/OUT - Len available, len returned. */
u_char **scopedPdu, /* OUT - Pointer to plaintext scopedPdu.*/
size_t *scopedPduLen, /* IN/OUT - Len available, len returned. */
size_t *maxSizeResponse, /* OUT - Max size of Response PDU. */
void **secStateRf) /* OUT - Ref to security state. */
{
size_t remaining = wholeMsgLen
- (u_int)
((u_long)*secParams-(u_long)*wholeMsg);
u_int boots_uint;
u_int time_uint;
u_char signature[BYTESIZE(USM_MAX_KEYEDHASH_LENGTH)];
size_t signature_length = BYTESIZE(USM_MAX_KEYEDHASH_LENGTH);
u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)];
u_int iv_length = BYTESIZE(USM_MAX_SALT_LENGTH);
u_char *data_ptr;
u_char *value_ptr;
u_char type_value;
u_char *end_of_overhead;
int error;
int i;
struct usmStateReference **secStateRef = (struct usmStateReference **)secStateRf;
struct usmUser *user;
DEBUGMSGTL(("usm","USM processing begun...\n"));
if (secStateRef) /* FIX -- huh? destroy it? */
{
*secStateRef = usm_malloc_usmStateReference();
if (*secStateRef == NULL)
{
DEBUGMSGTL(("usm", "Out of memory.\n"));
return SNMPERR_USM_GENERICERROR;
}
}
/*
* Make sure the *secParms is an OCTET STRING.
* Extract the user name, engine ID, and security level.
*/
if ( usm_parse_security_parameters (
secParams, remaining,
secEngineID, secEngineIDLen,
&boots_uint, &time_uint,
secName, secNameLen,
signature, &signature_length,
salt, &salt_length,
&data_ptr)
== -1 )
{
DEBUGMSGTL(("usm","Parsing failed.\n"));
if (snmp_increment_statistic (STAT_SNMPINASNPARSEERRS)==0)
{
DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic."));
}
return SNMPERR_USM_PARSEERROR;
}
if (secStateRef)
{
/* Cache the name, engine ID, and security level,
* per step 2 (section 3.2)
*/
if ( usm_set_usmStateReference_name (
*secStateRef, secName, *secNameLen) == -1 )
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache name."));
return SNMPERR_USM_GENERICERROR;
}
if ( usm_set_usmStateReference_engine_id (
*secStateRef, secEngineID, *secEngineIDLen) == -1 )
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache engine id."));
return SNMPERR_USM_GENERICERROR;
}
if ( usm_set_usmStateReference_sec_level (
*secStateRef, secLevel) == -1 )
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache security level."));
return SNMPERR_USM_GENERICERROR;
}
}
/*
* Locate the engine ID record.
* If it is unknown, then either create one or note this as an error.
*/
if (reportErrorOnUnknownID)
{
if (ISENGINEKNOWN(secEngineID, *secEngineIDLen)==FALSE)
{
DEBUGMSGTL(("usm","Unknown Engine ID.\n"));
if (snmp_increment_statistic (
STAT_USMSTATSUNKNOWNENGINEIDS)==0)
{
DEBUGMSGTL(("usm","%s\n",
"Failed to increment statistic."));
}
return SNMPERR_USM_UNKNOWNENGINEID;
}
}
else
{
if ( ENSURE_ENGINE_RECORD(secEngineID,*secEngineIDLen)
!= SNMPERR_SUCCESS )
{
DEBUGMSGTL(("usm","%s\n", "Couldn't ensure engine record."));
return SNMPERR_USM_GENERICERROR;
}
}
/*
* Locate the User record.
* If the user/engine ID is unknown, report this as an error.
*/
if ( (user =
usm_get_user(secEngineID, *secEngineIDLen, secName))
== NULL )
{
DEBUGMSGTL(("usm","Unknown User.\n"));
if (snmp_increment_statistic (STAT_USMSTATSUNKNOWNUSERNAMES)==0)
{
DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic."));
}
return SNMPERR_USM_UNKNOWNSECURITYNAME;
}
/*
* Make sure the security level is appropriate.
*/
if (usm_check_secLevel(secLevel, user) == 1)
{
DEBUGMSGTL(("usm","Unsupported Security Level.\n"));
if (snmp_increment_statistic
(STAT_USMSTATSUNSUPPORTEDSECLEVELS)==0)
{
DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic."));
}
return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
}
/*
* Check the authentication credentials of the message.
*/
if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
|| secLevel == SNMP_SEC_LEVEL_AUTHPRIV)
{
if ( sc_check_keyed_hash (
user->authProtocol, user->authProtocolLen,
user->authKey, user->authKeyLen,
wholeMsg, wholeMsgLen,
signature, signature_length)
!= SNMP_ERR_NOERROR )
{
DEBUGMSGTL(("usm","Verification failed.\n"));
if (snmp_increment_statistic
(STAT_USMSTATSWRONGDIGESTS)==0)
{
DEBUGMSGTL(("usm","%s\n",
"Failed to increment statistic."));
}
return SNMPERR_USM_AUTHENTICATIONFAILURE;
}
DEBUGMSGTL(("usm","Verification succeeded.\n"));
}
/*
* Steps 10-11 user is already set - relocated before timeliness
* check in case it fails - still save user data for response.
*
* Cache the keys and protocol oids, per step 11 (s3.2).
*/
if (secStateRef)
{
if (usm_set_usmStateReference_auth_protocol (*secStateRef,
user->authProtocol, user->authProtocolLen) ==-1)
{
DEBUGMSGTL(("usm","%s\n",
"Couldn't cache authentication protocol."));
return SNMPERR_USM_GENERICERROR;
}
if (usm_set_usmStateReference_auth_key (*secStateRef,
user->authKey, user->authKeyLen) == -1)
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache authentiation key."));
return SNMPERR_USM_GENERICERROR;
}
if (usm_set_usmStateReference_priv_protocol (*secStateRef,
user->privProtocol, user->privProtocolLen) ==-1)
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy protocol."));
return SNMPERR_USM_GENERICERROR;
}
if (usm_set_usmStateReference_priv_key (*secStateRef,
user->privKey, user->privKeyLen) == -1)
{
DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy key."));
return SNMPERR_USM_GENERICERROR;
}
}
/*
* Perform the timeliness/time manager functions.
*/
if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
|| secLevel == SNMP_SEC_LEVEL_AUTHPRIV)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -