snmp_user_based_sm_mib.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,101 行 · 第 1/3 页
ERL
1,101 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(snmp_user_based_sm_mib).-export([configure/1, reconfigure/1, usmUserSpinLock/1, usmUserSpinLock/2, usmUserTable/1, usmUserTable/3, table_next/2, is_engine_id_known/1, get_user/2, get_user_from_security_name/2, mk_key_change/3, mk_key_change/5, extract_new_key/3, mk_random/1]).-export([add_user/13, delete_user/1]).%% Internal-export([check_usm/1]).-include("SNMP-USER-BASED-SM-MIB.hrl").-include("SNMP-USM-AES-MIB.hrl").-include("SNMPv2-TC.hrl").-include("snmpa_internal.hrl").-include("snmp_types.hrl").-define(VMODULE,"USB_MIB").-include("snmp_verbosity.hrl").-ifndef(default_verbosity).-define(default_verbosity,silence).-endif.%% Columns not accessible via SNMP-define(usmUserAuthKey, 14).-define(usmUserPrivKey, 15).%%%-----------------------------------------------------------------%%% Implements the instrumentation functions and additional %%% functions for the SNMP-USER-BASED-SM-MIB.%%%-----------------------------------------------------------------%%-----------------------------------------------------------------%% Func: configure/1%% Args: Dir is the directory where the configuration files are found.%% Purpose: If the tables doesn't exist, this function reads%% the config-files for the USM tables, and%% inserts the data. This means that the data in the tables%% survive a reboot. However, the StorageType column is%% checked for each row. If volatile, the row is deleted.%% Returns: ok%% Fails: exit(configuration_error)%%-----------------------------------------------------------------configure(Dir) -> set_sname(), case db(usmUserTable) of {_, mnesia} -> ?vdebug("usm user table in mnesia: init vars & cleanup",[]), init_vars(), gc_tabs(); TabDb -> case snmpa_local_db:table_exists(TabDb) of true -> ?vdebug("usm user table exists: init vars & cleanup",[]), init_vars(), gc_tabs(); false -> ?vdebug("usm user table does not exist: reconfigure",[]), reconfigure(Dir) end end.%%-----------------------------------------------------------------%% Func: reconfigure/1%% Args: Dir is the directory where the configuration files are found.%% Purpose: Reads the config-files for the USM tables, and%% inserts the data. Makes sure that all old data in%% the tables are deleted, and the new data inserted.%% This function makes sure that all (and only) %% config-file-data are in the tables. %% Returns: ok%% Fails: exit(configuration_error) |%% exit({unsupported_crypto, Function})%%-----------------------------------------------------------------reconfigure(Dir) -> set_sname(), case (catch do_reconfigure(Dir)) of ok -> ok; {error, Reason} -> ?vinfo("reconfigure error: ~p", [Reason]), config_err("reconfigure failed: ~p", [Reason]), exit(configuration_error); Error -> ?vinfo("reconfigure failed: ~p", [Error]), config_err("reconfigure failed: ~p", [Error]), exit(configuration_error) end.do_reconfigure(Dir) -> ?vdebug("read usm configuration files",[]), Users = read_usm_config_files(Dir), ?vdebug("check users",[]), check_users(Users), ?vdebug("initiate tables",[]), init_tabs(Users), ?vdebug("initiate vars",[]), init_vars(), ok.read_usm_config_files(Dir) -> ?vdebug("read usm config file",[]), Gen = fun(D) -> generate_usm(D) end, Filter = fun(Usms) -> Usms end, Check = fun(Entry) -> check_usm(Entry) end, [Usms] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "usm.conf"}]), Usms.generate_usm(Dir) -> info_msg("Incomplete configuration. Generating empty usm.conf.", []), USMFile = filename:join(Dir, "usm.conf"), ok = file:write_file(USMFile, list_to_binary([])).check_usm({EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey}) -> snmp_conf:check_string(EngineID), snmp_conf:check_string(Name), snmp_conf:check_string(SecName), CloneVal = case catch snmp_conf:check_atom(Clone,[{zeroDotZero,?zeroDotZero}]) of {error, _} -> snmp_conf:check_oid(Clone), Clone; {ok, X} -> X end, AuthProtoAlt = [{usmNoAuthProtocol, ?usmNoAuthProtocol}, {usmHMACSHAAuthProtocol, ?usmHMACSHAAuthProtocol}, {usmHMACMD5AuthProtocol, ?usmHMACMD5AuthProtocol}], {ok, AuthProto} = snmp_conf:check_atom(AuthP, AuthProtoAlt), snmp_conf:check_string(AuthKeyC), snmp_conf:check_string(OwnAuthKeyC), PrivProtoAlt = [{usmNoPrivProtocol, ?usmNoPrivProtocol}, {usmDESPrivProtocol, ?usmDESPrivProtocol}, {usmAesCfb128Protocol, ?usmAesCfb128Protocol}], {ok, PrivProto} = snmp_conf:check_atom(PrivP, PrivProtoAlt), snmp_conf:check_string(PrivKeyC), snmp_conf:check_string(OwnPrivKeyC), snmp_conf:check_string(Public), snmp_conf:check_string(AuthKey, alen(AuthP)), snmp_conf:check_string(PrivKey, plen(PrivP)), User = {EngineID, Name, SecName, CloneVal, AuthProto, AuthKeyC, OwnAuthKeyC, PrivProto, PrivKeyC, OwnPrivKeyC, Public, ?'StorageType_nonVolatile', ?'RowStatus_active', AuthKey, PrivKey}, {ok, User};check_usm(X) -> error({invalid_user, X}).alen(usmNoAuthProtocol) -> any;alen(usmHMACMD5AuthProtocol) -> 16;alen(usmHMACSHAAuthProtocol) -> 20.plen(usmNoPrivProtocol) -> any;plen(usmDESPrivProtocol) -> 16;plen(usmAesCfb128Protocol) -> 16.%%-----------------------------------------------------------------%% This function loops through all users, and check that the%% definition is constistent with the support for crypto on%% the system. Thus, it is not possible to define a user that%% uses authentication if 'crypto' is not started, or a user that%% uses DES if 'crypto' doesn't support DES.%%-----------------------------------------------------------------check_users([User | Users]) -> check_user(User), check_users(Users);check_users([]) -> ok.check_user(User) -> case element(?usmUserAuthProtocol, User) of ?usmNoAuthProtocol -> ok; ?usmHMACMD5AuthProtocol -> case is_crypto_supported(md5_mac_96) of true -> ok; false -> exit({unsupported_crypto, md5_mac_96}) end; ?usmHMACSHAAuthProtocol -> case is_crypto_supported(sha_mac_96) of true -> ok; false -> exit({unsupported_crypto, sha_mac_96}) end end, case element(?usmUserPrivProtocol, User) of ?usmNoPrivProtocol -> ok; ?usmDESPrivProtocol -> case is_crypto_supported(des_cbc_decrypt) of true -> ok; false -> exit({unsupported_crypto, des_cbc_decrypt}) end; ?usmAesCfb128Protocol -> case is_crypto_supported(aes_cfb_128_decrypt) of true -> ok; false -> exit({unsupported_crypto, aes_cfb_128_decrypt}) end end. % maybe_create_table(Name) ->% case snmpa_local_db:table_exists(db(Name)) of% true -> ok;% _ -> snmpa_local_db:table_create(db(Name))% end.init_tabs(Users) -> ?vdebug("create usm user table",[]), snmpa_local_db:table_delete(db(usmUserTable)), snmpa_local_db:table_create(db(usmUserTable)), init_user_table(Users). init_user_table([Row | T]) -> Key = mk_user_table_key(Row), snmpa_local_db:table_create_row(db(usmUserTable), Key, Row), init_user_table(T);init_user_table([]) -> true.mk_user_table_key(Row) -> Key1 = element(1, Row), Key2 = element(2, Row), [length(Key1) | Key1] ++ [length(Key2) | Key2].table_cre_row(Tab, Key, Row) -> snmpa_mib_lib:table_cre_row(db(Tab), Key, Row).table_del_row(Tab, Key) -> snmpa_mib_lib:table_del_row(db(Tab), Key).add_user(EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey) -> User = {EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey}, case (catch check_usm(User)) of {ok, Row} -> case (catch check_user(Row)) of {'EXIT', Reason} -> {error, Reason}; _ -> Key = mk_user_table_key(Row), case table_cre_row(usmUserTable, Key, Row) of true -> {ok, Key}; false -> {error, create_failed} end end; {error, Reason} -> {error, Reason}; Error -> {error, Error} end.delete_user(Key) -> case table_del_row(usmUserTable, Key) of true -> ok; false -> {error, delete_failed} end.gc_tabs() -> DB = db(usmUserTable), STC = stc(usmUserTable), FOI = foi(usmUserTable), snmpa_mib_lib:gc_tab(DB, STC, FOI), ok.%%-----------------------------------------------------------------%% Counter functions%%-----------------------------------------------------------------init_vars() -> lists:map(fun maybe_create_var/1, vars()).maybe_create_var(Var) -> case ets:lookup(snmp_agent_table, Var) of [_] -> ok; _ -> init_var(Var) end.init_var(Var) -> ets:insert(snmp_agent_table, {Var, 0}).vars() -> [usmStatsUnsupportedSecLevels, usmStatsNotInTimeWindows, usmStatsUnknownUserNames, usmStatsUnknownEngineIDs, usmStatsWrongDigests, usmStatsDecryptionErrors].%%-----------------------------------------------------------------%% API functions%%-----------------------------------------------------------------is_engine_id_known(EngineID) -> EngineKey = [length(EngineID) | EngineID], case table_next(usmUserTable, EngineKey) of endOfTable -> false; Key -> lists:prefix(EngineKey, Key) end.get_user(EngineID, UserName) -> Key = [length(EngineID) | EngineID] ++ [length(UserName) | UserName], snmp_generic:table_get_row(db(usmUserTable), Key, foi(usmUserTable)).get_user_from_security_name(EngineID, SecName) -> %% Since the normal mapping between UserName and SecName is the %% identityfunction, we first try to use the SecName as UserName, %% and check the resulting row. If it doesn't match, we'll have to %% loop through the entire table. Key = [length(EngineID) | EngineID] ++ [length(SecName) | SecName], case snmp_generic:table_get_row(db(usmUserTable), Key, foi(usmUserTable)) of Row when tuple(Row) -> Row; undefined -> F = fun(_, Row) when element(?usmUserEngineID,Row) == EngineID, element(?usmUserSecurityName,Row) == SecName -> throw({ok, Row}); (_, _) -> ok end, case catch snmp_generic:table_foreach(db(usmUserTable), F) of {ok, Row} -> Row; _Else -> undefined end end. %%-----------------------------------------------------------------%% Instrumentation Functions%%-----------------------------------------------------------------usmUserSpinLock(new) -> snmp_generic:variable_func(new, {usmUserSpinLock, volatile}), {A1,A2,A3} = erlang:now(), random:seed(A1,A2,A3), Val = random:uniform(2147483648) - 1,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?