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 + -
显示快捷键?