diff options
author | Stefan Zegenhagen <[email protected]> | 2013-06-10 11:07:00 +0200 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2013-06-10 11:54:24 +0200 |
commit | a31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7 (patch) | |
tree | e66af7fdcc6fe9e545c5c97d62821dccef9e1b82 /lib | |
parent | a49832f74d364e01d9fb7a98caf3ca942a0a0341 (diff) | |
download | otp-a31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7.tar.gz otp-a31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7.tar.bz2 otp-a31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7.zip |
SNMP/VACM: bugfix for vacmViewTreeFamilyMask
Dear all,
it's almost a year since I sent the patch attached to this e-mail, and I
just found out that I have not yet gotten a response to it.
I would consider this patch important because it fixes an issue with the
interpretation of data that might be critical for SNMPv3 operation. I
confirmed at that time that erlangs interpretation of
vacmViewTreeFamilyMask is indeed not interoperable with other SNMP
stacks.
Kind regards,
> > > the implementation of SNMP-VIEW-BASED-ACM.mib assumes that the input for
> > > vacmViewTreeFamilyMask is an OID consisting of 1's and 0's only to form
> > > the mask. However, the MIB states that the input should be a bitstring.
> > >
> > > The OID representation of the mask is useful in the code as it speeds up
> > > time-critical code paths when checking access permissions for EACH SNMP
> > > access. Reading/writing the view mask objects is less time-critical.
> > >
> > > Therefore, to fix the issue, convert between OID representation and
> > > bitstring when the vacmViewTreeFamilyMask objects are accessed. This is
> > > done by the patch attached to this e-mail.
>
>
> I'm very sorry for the troubles that I am causing but it seems that the
> previous version of the patch did more than it should: the OID-bitstring
> conversion was also applied to other tables in the same MIB on
> get/get-next requests.
>
> The version of the patch that is attached to this e-mail restricts the
> OID-bitstring conversion to vacmViewTreeFamilyMask alone.
--
Dr. Stefan Zegenhagen
arcutronix GmbH
Garbsener Landstr. 10
30419 Hannover
Germany
Tel: +49 511 277-2734
Fax: +49 511 277-2709
Email: [email protected]
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.
>From aa2acfb8a0b5ae05fc5ba982d78ee5607384a2be Mon Sep 17 00:00:00 2001
From: Stefan Zegenhagen <[email protected]>
Date: Wed, 1 Aug 2012 09:56:15 +0200
Subject: [PATCH] bugfix for vacmViewTreeFamilyMask
The vacmViewTreeFamilyMask is defined to be a bit string in the MIB, not
an OID. However, the MIB implementation assumed the latter, effectively
rendering all attempts to read/set masks via SNMP unsuccessful.
Since the mask is used in hot paths (e.g. access permission checks for
each SNMP operation, the OID representation of the mask has benefits
(e.g. faster processing). Therefore, convert the bitstring to/from its
OID representation when reading/setting any mask object.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index ad9540e886..0acef780f8 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -957,9 +957,9 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyMask, Mask) -> null -> []; [] -> []; _ -> - case (catch snmp_conf:check_oid(Mask)) of + case (catch check_mask(Mask)) of ok -> - Mask; + mask2oid(Mask); _ -> wrongValue(?vacmViewTreeFamilyMask) end @@ -975,7 +975,54 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyType, Type) -> end; verify_vacmViewTreeFamilyTable_col(_, Val) -> Val. - + + +check_mask([]) -> + ok; +check_mask([Head | Tail]) when is_integer(Head) -> +% we can cause exception here because the caller catches + if + Head > -1 andalso Head < 256 -> + check_mask(Tail) + end. + +% internally (for easier computations), the mask is stored +% as OID and not as bit-field. Therefore, we have to convert +% the bitstring to a list of integers before storing it. +mask2oid(Mask) -> + Func = fun(Byte) -> + % what's a nice syntax for extracting bits + % from a byte??? + <<A:1, B:1, C:1, D:1, E:1, F:1, G:1, H:1>> = <<Byte>>, + [A, B, C, D, E, F, G, H] + end, + lists:flatten(lists:map(Func, Mask)). + +oid2mask(Oid) -> + % convert all suboids to either 1 or 0 for sure + Func = fun + (0) -> 0; + (_) -> 1 + end, + oid2mask(lists:map(Func, Oid), []). + +oid2mask([], Mask) -> + % end-of-list, return bitstring + lists:reverse(Mask); +oid2mask(Oid, Mask) -> + % check whether we've got at least 8 sub-identifiers. if not, + % extend with 1's until there are enough to fill a byte + NOid = case length(Oid) of + Small when Small < 8 -> + Oid ++ lists:duplicate(8-Small, 1); + _ -> + Oid + end, + % extract sufficient suboids for 8 bits + [A, B, C, D, E, F, G, H | Tail] = NOid, + <<Byte:8>> = <<A:1, B:1, C:1, D:1, E:1, F:1, G:1, H:1>>, + oid2mask(Tail, [Byte | Mask]). + table_next(Name, RestOid) -> snmp_generic:table_next(db(Name), RestOid). @@ -1014,11 +1061,43 @@ stc(vacmSecurityToGroupTable) -> ?vacmSecurityToGroupStorageType; stc(vacmViewTreeFamilyTable) -> ?vacmViewTreeFamilyStorageType. next(Name, RowIndex, Cols) -> - snmp_generic:handle_table_next(db(Name), RowIndex, Cols, - fa(Name), foi(Name), noc(Name)). + Ans = snmp_generic:handle_table_next(db(Name), RowIndex, Cols, + fa(Name), foi(Name), noc(Name)), + patch_next(Name, Ans). get(Name, RowIndex, Cols) -> - snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)). + Ans = snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)), + patch(Name, Cols, Ans). + + +patch(Name, Cols, Ans) when is_list(Ans) -> + % function to patch returned values + Func = fun + ({Col, {value, Val}}) -> {value, do_patch(Name, Col, Val)}; + ({_, Other}) -> Other + end, + % merge column numbers and return values. there must be as much + % return values as there are columns requested + Tmp = lists:zip(Cols, Ans), + % and patch all values + lists:map(Func, Tmp); +patch(_, _, Ans) -> + Ans. + +patch_next(Name, Ans) when is_list(Ans) -> + Func = fun + ({[C | _] = Idx, Val}) -> {Idx, do_patch(Name, C, Val)}; + (Other) -> Other + end, + lists:map(Func, Ans); +patch_next(_, Ans) -> + Ans. + +do_patch(vacmViewTreeFamilyTable, ?vacmViewTreeFamilyMask, Val) -> + oid2mask(Val); +do_patch(_, _, Val) -> + Val. + wrongValue(V) -> throw({wrongValue, V}). |