[erlang-patches] SNMP: verify RowIndex in table set requests

Stefan Zegenhagen <>
Fri Jul 20 10:25:41 CEST 2012


Dear all,

I've not heard any comment on the patch below. Anyone interested???

Kind regards,

Stefan.

> Dear all,
> 
> during intensive testing it was found that it's possible to create table
> rows in snmpTargetAddrTable where the row index (snmpTargetAddrName ::
> SnmpAdminString(1..32)) is the empty string. This patch solves the issue
> generically by checking for all set-requests that the row index is of
> acceptable length before calling the table instrumentation function.
> 
> The same is not done for get requests because such invalid row indices
> should not be present if it's impossible to create them.
> 
> The same is not done for get-next requests because the semantic of the
> operation requires it to be able to cope with incomplete/overlong row
> indices.
> 
> Kind regards,
> 
> 
> --- snip ---
> 
> From be617c829a89dd9b73768181810776e50fb36c42 Mon Sep 17 00:00:00 2001
> From: Stefan Zegenhagen <>
> Date: Wed, 4 Jul 2012 14:34:46 +0200
> Subject: [PATCH 2/2] verify table row index constraints in SNMP set requests
> 
> When a set-request is received for table columns, check that the varbind
> OIDs are syntactically correct. This includes checking that Table Entry
> OID as well as the Column OID are present, and that the row index
> contains an acceptable number of subidentifiers.
> 
> This check was not done carefully enough before, giving the following
> test result from an erlang-snmp agent:
> 
>  Response: Version = SNMPv3, MsgId = 173, MaxSize = 2048
>  Flags = Auth/Priv, SecurityModel = USM
>  EngineId = [...], EngineBoots = 16, EngineTime = 81244, UserName = ...
>  ContextEngineId = [...], ContextName = [...]
>  Request Id = 173, Error Status = No Error , Error Index = 0
>  Oid1 = snmpTargetAddrRowStatus , Type = Integer, Value = 4
>  Oid2 = snmpTargetAddrTAddress , Type = OctetString, Value = ...
>  Oid3 = snmpTargetAddrTimeout , Type = Integer, Value = 100
>  Oid4 = snmpTargetAddrRetryCount , Type = Integer, Value = 3
>  Oid5 = snmpTargetAddrTagList , Type = OctetString, Value = abc
>  Oid6 = snmpTargetAddrParams , Type = OctetString, Value = abc
>  Oid7 = snmpTargetAddrStorageType , Type = Integer, Value = 2
>  Oid8 = snmpTargetAddrTDomain , Type = ObjectID, Value = 1.3.6.1.6.1.1
> 
> Please observe that a table row in snmptargetAddrParams is created
> without errors, although an empty RowIndex was specified for all
> columnar objects in the request. The index to that table is defined as
> IMPLIED SnmpAdminString(1..32).
> ---
>  lib/snmp/src/agent/snmpa_set_lib.erl |   65 ++++++++++++++++++++++++++++++++--
>  1 file changed, 63 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
> index f5218d5..ef9e20e 100644
> --- a/lib/snmp/src/agent/snmpa_set_lib.erl
> +++ b/lib/snmp/src/agent/snmpa_set_lib.erl
> @@ -70,8 +70,19 @@
>  %% Purpose: Call is_varbind_ok for each varbind
>  %% Returns: {noError, 0} | {ErrorStatus, ErrorIndex}
>  %%-----------------------------------------------------------------
> -is_varbinds_ok([{_TableOid, TableVbs} | IVarbinds]) -> 
> -    is_varbinds_ok(lists:append(TableVbs, IVarbinds));
> +is_varbinds_ok([{TableOid, TableVbs} | IVarbinds]) ->
> +    % TableOid points to the table entry, not the table itself.
> +    % for table row index checking, we need the table entry, though.
> +    % Hence, strip the last OID.
> +    NTableOid = lists:reverse(tl(lists:reverse(TableOid))),
> +    case is_table_varbinds_ok(NTableOid, TableVbs) of
> +        true ->
> +            is_varbinds_ok(lists:append(TableVbs, IVarbinds));
> +        {ErrorStatus, Varbind} ->
> +            ?vtrace("varbinds erroneous: ~p -> ~p",
> +                [Varbind#varbind.org_index,ErrorStatus]),
> +            {ErrorStatus, Varbind#varbind.org_index}
> +    end;
>  is_varbinds_ok([IVarbind | IVarbinds]) -> 
>      case catch is_varbind_ok(IVarbind) of
>  	true -> is_varbinds_ok(IVarbinds);
> @@ -85,6 +96,56 @@ is_varbinds_ok([]) ->
>      ?vtrace("varbinds ok",[]),
>      {noError, 0}.
>  
> +
> +%%-----------------------------------------------------------------
> +%% Func: is_table_varbinds_ok/2
> +%% Purpose: Perform basic checks on the RowIndex of varbinds against
> +%%          the MIB. Here we don't call any instrumentation functions.
> +%% Returns: true |
> +%% Fails:   with an <error-atom>.
> +%%-----------------------------------------------------------------
> +is_table_varbinds_ok(_TableOid, []) ->
> +    true;
> +is_table_varbinds_ok(TableOid, [Hd | _] = Varbinds) ->
> +    ErrResult = {noCreation, Hd#ivarbind.varbind},
> +    % resolve table information, it's required for the checks we do
> +    case snmpa_symbolic_store:oid_to_aliasname(TableOid) of
> +        {value, TableName} ->
> +            case snmpa_symbolic_store:table_info(TableName) of
> +                {value, #table_info{} = TableInfo} ->
> +                    is_table_varbinds_ok(TableOid, TableInfo, Varbinds);
> +                false ->
> +                    snmpa_error:user_err("Failed in table_info(~w)", [TableName]),
> +                    ErrResult
> +            end;
> +        false ->
> +            snmpa_error:user_err("Failed in oid_to_aliasname(~w)", [TableOid]),
> +            ErrResult
> +    end.
> +
> +is_table_varbinds_ok(TableOid, TableInfo, [#ivarbind{varbind = Varbind} | Varbinds]) ->
> +    Indices = TableInfo#table_info.index_types,
> +    Oid = Varbind#varbind.oid,
> +    case snmp_misc:diff(Oid, TableOid) of
> +        [_TblEntryId, _TblColumnId | RowIndex] ->
> +            case (catch snmp_generic:split_index_to_keys(Indices, RowIndex)) of
> +                Keys when is_list(Keys) ->
> +                    % RowIndex seems to be OK
> +                    is_table_varbinds_ok(TableOid, TableInfo, Varbinds);
> +                Error ->
> +                    % RowIndex is syntactically wrong...
> +                    ?vtrace("table varbind RowIndex erroneous: ~p", [Error]),
> +                    {noCreation, Varbind}
> +            end;
> +        _Else ->
> +            % OID is syntactically wrong...
> +            ?vtrace("table varbind OID erroneous: ~p", [Oid]),
> +            {noCreation, Varbind}
> +    end;
> +is_table_varbinds_ok(_TableOid, _TableInfo, []) ->
> +    true.
> +
> +
>  %%-----------------------------------------------------------------
>  %% Func: is_varbind_ok/1
>  %% Purpose: Check everything we can check about the varbind against
> -- 
> 1.7.9.5
> 
> 

-- 
Dr. Stefan Zegenhagen

arcutronix GmbH
Garbsener Landstr. 10
30419 Hannover
Germany

Tel:   +49 511 277-2734
Fax:   +49 511 277-2709
Email: 
Web:   www.arcutronix.com

*Synchronize the Ethernet*

General Managers: Dipl. Ing. Juergen Schroeder, Dr. Josef Gfrerer -
Legal Form: GmbH, Registered office: Hannover, HRB 202442, Amtsgericht
Hannover; Ust-Id: DE257551767.

Please consider the environment before printing this message.



More information about the erlang-patches mailing list