aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Zegenhagen <[email protected]>2013-06-10 11:07:00 +0200
committerFredrik Gustafsson <[email protected]>2013-06-10 11:54:24 +0200
commita31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7 (patch)
treee66af7fdcc6fe9e545c5c97d62821dccef9e1b82
parenta49832f74d364e01d9fb7a98caf3ca942a0a0341 (diff)
downloadotp-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.
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl91
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}).