snmpa_usm.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 544 行 · 第 1/2 页

ERL
544
字号
	    EncryptedPDU = snmp_pdus:dec_scoped_pdu_data(Data),	    SecName      = element(?usmUserSecurityName, UsmUser),	    PrivP        = element(?usmUserPrivProtocol, UsmUser),	    PrivKey      = element(?usmUserPrivKey,      UsmUser),     try_decrypt(PrivP, PrivKey, UsmSecParams, EncryptedPDU, SecName).try_decrypt(?usmNoPrivProtocol, _, _, _, SecName) -> % 3.2.5    error(usmStatsUnsupportedSecLevels, 	  ?usmStatsUnsupportedSecLevels_instance, SecName); % OTP-5464try_decrypt(?usmDESPrivProtocol, 	    PrivKey, UsmSecParams, EncryptedPDU, SecName) ->    case (catch des_decrypt(PrivKey, UsmSecParams, EncryptedPDU)) of	{ok, DecryptedData} ->	    DecryptedData;	_ ->	    error(usmStatsDecryptionErrors, 		  ?usmStatsDecryptionErrors_instance, % OTP-5464		  SecName)    end;try_decrypt(?usmAesCfb128Protocol, 	    PrivKey, UsmSecParams,  EncryptedPDU, SecName) ->    case (catch aes_decrypt(PrivKey, UsmSecParams, EncryptedPDU)) of	{ok, DecryptedData} ->	    DecryptedData;	_ ->	    error(usmStatsDecryptionErrors, 		  ?usmStatsDecryptionErrors_instance, % OTP-5464		  SecName)    end.generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) ->    %% 3.1.1    ?vtrace("generate_outgoing_msg -> [3.1.1] entry with"	    "~n   SecEngineID: ~p"	    "~n   SecName:     ~p"	    "~n   SecLevel:    ~w", 	    [SecEngineID, SecName, SecLevel]),    {UserName, AuthProtocol, PrivProtocol, AuthKey, PrivKey} =	case SecData of	    [] -> % 3.1.1b		%% Not a response - read from LCD		case snmp_user_based_sm_mib:get_user_from_security_name(		       SecEngineID, SecName) of		    User when element(?usmUserStatus, User) ==			      ?'RowStatus_active' ->			{element(?usmUserName, User),			 element(?usmUserAuthProtocol, User),			 element(?usmUserPrivProtocol, User),			 element(?usmUserAuthKey, User),			 element(?usmUserPrivKey, User)};		    {_, Name,_,_,_,_,_,_,_,_,_,_,_, RowStatus,_,_} ->			?vdebug("generate_outgoing_msg -> "				"found user ~p with wrong row status: ~p", 				[Name, RowStatus]),			error(unknownSecurityName);		    _ ->			error(unknownSecurityName)		end;	    [MsgUserName] ->		%% This means the user at the engine is unknown		{MsgUserName, ?usmNoAuthProtocol, ?usmNoPrivProtocol, "", ""};	    _ -> % 3.1.1a		SecData	end,    %% 3.1.4    ?vtrace("generate_outgoing_msg -> [3.1.4]"	    "~n   UserName:     ~p"	    "~n   AuthProtocol: ~p"	    "~n   PrivProtocol: ~p", 	    [UserName, AuthProtocol, PrivProtocol]),    ScopedPduBytes = Message#message.data,    {ScopedPduData, MsgPrivParams} =	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel),    SnmpEngineID = snmp_framework_mib:get_engine_id(),    ?vtrace("generate_outgoing_msg -> SnmpEngineID: ~p [3.1.6]",	    [SnmpEngineID]),    %% 3.1.6    {MsgAuthEngineBoots, MsgAuthEngineTime} =	case snmp_misc:is_auth(SecLevel) of	    false when SecData == [] -> % not a response		{0, 0}; 	    true when SecEngineID /= SnmpEngineID ->		{get_engine_boots(SecEngineID),		 get_engine_time(SecEngineID)};	    _ ->		{snmp_framework_mib:get_engine_boots(),		 snmp_framework_mib:get_engine_time()}	end,    %% 3.1.5 - 3.1.7    ?vtrace("generate_outgoing_msg -> [3.1.5 - 3.1.7]",[]),    UsmSecParams =	#usmSecurityParameters{msgAuthoritativeEngineID = SecEngineID,			       msgAuthoritativeEngineBoots = MsgAuthEngineBoots,			       msgAuthoritativeEngineTime = MsgAuthEngineTime,			       msgUserName = UserName,			       msgPrivacyParameters = MsgPrivParams},    Message2 = Message#message{data = ScopedPduData},    %% 3.1.8    ?vtrace("generate_outgoing_msg -> [3.1.8]",[]),    authenticate_outgoing(Message2, UsmSecParams,			  AuthKey, AuthProtocol, SecLevel).%% Ret: {ScopedPDU, MsgPrivParams} - both are already encoded as OCTET STRINGsencrypt(Data, PrivProtocol, PrivKey, SecLevel) ->    case snmp_misc:is_priv(SecLevel) of	false -> % 3.1.4b	    ?vtrace("encrypt -> 3.1.4b",[]),	    {Data, []};	true -> % 3.1.4a	    ?vtrace("encrypt -> 3.1.4a",[]),	    case (catch try_encrypt(PrivProtocol, PrivKey, Data)) of		{ok, ScopedPduData, MsgPrivParams} ->		    ?vtrace("encrypt -> encode tag",[]),		    {snmp_pdus:enc_oct_str_tag(ScopedPduData), MsgPrivParams};                {error, Reason} ->                    error(Reason); 		_ ->		    error(encryptionError)	    end    end.try_encrypt(?usmNoPrivProtocol, _PrivKey, _Data) -> % 3.1.2    error(unsupportedSecurityLevel);try_encrypt(?usmDESPrivProtocol, PrivKey, Data) ->    des_encrypt(PrivKey, Data);try_encrypt(?usmAesCfb128Protocol, PrivKey, Data) ->    aes_encrypt(PrivKey, Data).authenticate_outgoing(Message, UsmSecParams, 		      AuthKey, AuthProtocol, SecLevel) ->    Message2 = 	case snmp_misc:is_auth(SecLevel) of	    true ->		auth_out(AuthProtocol, AuthKey, Message, UsmSecParams);	    false ->		set_msg_auth_params(Message, UsmSecParams)	end,    ?vtrace("authenticate_outgoing -> encode message only",[]),    snmp_pdus:enc_message_only(Message2).    	    %%-----------------------------------------------------------------%% Auth and priv algorithms%%-----------------------------------------------------------------auth_in(AuthProtocol, AuthKey, AuthParams, Packet) ->    snmp_usm:auth_in(AuthProtocol, AuthKey, AuthParams, Packet).auth_out(AuthProtocol, AuthKey, Message, UsmSecParams) ->    snmp_usm:auth_out(AuthProtocol, AuthKey, Message, UsmSecParams).set_msg_auth_params(Message, UsmSecParams) ->    snmp_usm:set_msg_auth_params(Message, UsmSecParams, []).des_encrypt(PrivKey, Data) ->    snmp_usm:des_encrypt(PrivKey, Data, fun get_des_salt/0).des_decrypt(PrivKey, UsmSecParams, EncData) ->    #usmSecurityParameters{msgPrivacyParameters = PrivParms} = UsmSecParams,    snmp_usm:des_decrypt(PrivKey, PrivParms, EncData).get_des_salt() ->    SaltInt = 	case catch ets:update_counter(snmp_agent_table, usm_des_salt, 1) of	    N when N =< 4294967295 ->		N;	    N when integer(N) -> % wrap		ets:insert(snmp_agent_table, {usm_des_salt, 0}),		0;	    _ -> % it doesn't exist, initialize		{A1,A2,A3} = erlang:now(),		random:seed(A1,A2,A3),		R = random:uniform(4294967295),		ets:insert(snmp_agent_table, {usm_des_salt, R}),		R	end,    EngineBoots = snmp_framework_mib:get_engine_boots(),    [?i32(EngineBoots), ?i32(SaltInt)].aes_encrypt(PrivKey, Data) ->    snmp_usm:aes_encrypt(PrivKey, Data, fun get_aes_salt/0).aes_decrypt(PrivKey, UsmSecParams, EncData) ->    #usmSecurityParameters{msgPrivacyParameters        = PrivParams,			   msgAuthoritativeEngineTime  = EngineTime,			   msgAuthoritativeEngineBoots = EngineBoots} =	UsmSecParams,    snmp_usm:aes_decrypt(PrivKey, PrivParams, EncData, 			 EngineBoots, EngineTime).get_aes_salt() ->    SaltInt = 	case catch ets:update_counter(snmp_agent_table, usm_aes_salt, 1) of	    N when N =< 36893488147419103231  ->		N;	    N when integer(N) -> % wrap		ets:insert(snmp_agent_table, {usm_aes_salt, 0}),		0;	    _ -> % it doesn't exist, initialize		{A1,A2,A3} = erlang:now(),		random:seed(A1,A2,A3),		R = random:uniform(36893488147419103231),		ets:insert(snmp_agent_table, {usm_aes_salt, R}),		R	end,    [?i64(SaltInt)].%%-----------------------------------------------------------------%% We cache the local values of all non-auth engines we know.%% Keep the values in the snmp_agent_table.%% See section 2.3 of the RFC.%%-----------------------------------------------------------------get_engine_boots(SnmpEngineID) ->    case ets:lookup(snmp_agent_table, {usm_eboots, SnmpEngineID}) of	[{_Key, Boots}] -> Boots;	_ -> 0    end.get_engine_time(SnmpEngineID) ->    case ets:lookup(snmp_agent_table, {usm_etime, SnmpEngineID}) of	[{_Key, Diff}] -> snmp_misc:now(sec) - Diff;	_ -> 0    end.	    get_engine_latest_time(SnmpEngineID) ->    case ets:lookup(snmp_agent_table, {usm_eltime, SnmpEngineID}) of	[{_Key, Time}] -> Time;	_ -> 0    end.	    set_engine_boots(SnmpEngineID, EngineBoots) ->    ets:insert(snmp_agent_table, {{usm_eboots, SnmpEngineID}, EngineBoots}).set_engine_time(SnmpEngineID, EngineTime) ->    Diff = snmp_misc:now(sec) - EngineTime,    ets:insert(snmp_agent_table, {{usm_etime, SnmpEngineID}, Diff}).set_engine_latest_time(SnmpEngineID, EngineTime) ->    ets:insert(snmp_agent_table, {{usm_eltime, SnmpEngineID}, EngineTime}).%%-----------------------------------------------------------------%% Utility functions%%-----------------------------------------------------------------error(Reason) ->    throw({error, Reason}).error(Reason, ErrorInfo) ->    throw({error, Reason, ErrorInfo}).error(Variable, Oid, SecName) ->    error(Variable, Oid, SecName, []).error(Variable, Oid, SecName, Opts) ->    Val = inc(Variable),    ErrorInfo = {#varbind{oid = Oid,			  variabletype = 'Counter32',			  value = Val},		 SecName,		 Opts},    throw({error, Variable, ErrorInfo}).inc(Name) -> ets:update_counter(snmp_agent_table, Name, 1).

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?