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