[erlang-questions] Process dictionary bug in SNMP agent, when changing own passphrase?

Scott Lystig Fritchie fritchie@REDACTED
Thu Apr 19 07:49:03 CEST 2007


Greetings, I think I've found another bug in passphrase handling in
the OTP SNMP agent.  I don't have a good suggestion for a fix yet, but
perhaps this is a simple one?

The NET-SNMP utility "snmpusm" seems to have changed the technique it
uses for changing passphrases (I think).  Version 5.1.2 uses the
usmUserAuthKeyChange and usmUserPrivKeyChange columns in the
usmUserTable table.  Version 5.4 uses the usmUserOwnAuthKeyChange and
usmUserOwnPrivKeyChange columns.  The OTP SNMP agent processes those
changes differently.

If my sys.config file uses:

     {multi_threaded, false},

... then I see no problem using 5.4 to change passphrases.  But if I
use {multi_threaded, true}, then any attempt by "snmpusm" to change a
passphrase gives this error:

    Error in packet.
    Reason: noAccess
    Failed object:
    SNMP-USER-BASED-SM-MIB::usmUserOwnPrivKeyChange."enginea0"."superuser-shaaes"

... even when the user's group & view *does* have read/write access to
all of the usmUserTable.

I think the bug lies in the snmp_master_agent process using its local
process dictionary to store info about the query.  snmp_acm:init_ca/2
has the put(), and snmp_user_based_sm_mib:validate_requester/3 has the
get(),

For now, I will use {multi_threaded, false}; I don't expect too much
performance trouble with that setting.  (Fingers crossed.)

-Scott

For example, in snmp_acm:init_ca/2:

init_ca(Pdu, {v3, _MsgID, SecModel, SecName, SecLevel,
	           _ContextEngineID, ContextName, _SecData}) ->
    %% [...]
    put(sec_model, SecModel),
    put(sec_name, SecName),
    %% [...]

And in snmp_user_based_sm_mib:validate_requester/3:

validate_requester(RowIndex, Cols, KeyChangeCol) ->
    case lists:keysearch(KeyChangeCol, 1, Cols) of
        {value, _} ->
            case get(sec_model) of % Check the securityModel in the request
                ?SEC_USM -> ok;
                _ -> noAccess(KeyChangeCol)
            end,
            %% The SecurityName may not be set yet.  First, check if it is set.
            SecNameForUser = 
                case snmp_generic:table_get_element(db(usmUserTable),
                                                    RowIndex,
                                                    ?usmUserSecurityName) of
                    {value, Val} when Val /= noinit -> Val;
                    _ -> get_user_name(RowIndex)
                end,
            %% SLF: This get() fails if {multi_threaded, true}
            case get(sec_name) of % Check the securityName in the request
                SecNameForUser -> ok;
                _ -> noAccess(KeyChangeCol)
            end;
        false ->
            ok
    end.



More information about the erlang-questions mailing list