PER, asn2wrs: Fix permitted-alphabet constrained character strings

Effective permitted-alphabet constraints are only PER-visible for
the known-multiplier character string types (X.691 27.1). When
PER-visible, the upper bound of any code point used in the
alphabet needs to be calculated, in particular for the ALIGNED
variant, because that determines whether or not canonical order
is used (X.691 27.5.2, 27.5.4).

Note that even with the change to asn2wrs.py none of the generated
dissectors change, because we don't have any example of ASN.1
with non-PER visible permitted alphabet constraints because of
using them on non known-multiplier character string types
(like UTF8String).

There's some various edge cases that we still don't handle, but
nothing that any of the ASN.1 modules in the repository use.
(Permitted-alphabet constraints using characters outside the
ASCII range, possibly with "CharacterStringList", "Quadruple",
or "Tuple" notation, permitted-alphabet constraints that are
extensible and thus not PER-visible, etc.)

Also fix a fencepost error with the length of the octets to highlight.

Fix #18468
This commit is contained in:
John Thacker 2022-10-15 00:14:16 -04:00
parent 21b3529be4
commit cb23c5e8d7
2 changed files with 39 additions and 7 deletions

View File

@ -774,7 +774,7 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
str_len = (int)wmem_strbuf_get_len(buf);
str = wmem_strbuf_finalize(buf);
/* Note that str can contain embedded nulls */
proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), (offset>>3)-(old_offset>>3), str);
proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), (offset>>3)-(old_offset>>3)+1, str);
if (value_tvb) {
*value_tvb = tvb_new_child_real_data(tvb, str, str_len, str_len);
}
@ -782,7 +782,7 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
}
static const char*
sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length, guint16 *lb, guint16 *ub)
{
int i, j;
guchar c, c_max, c_min;
@ -790,7 +790,10 @@ sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
/*
* XXX - presumably all members of alphabet will be in the
* range 0 to 127.
* range 0 to 127. asn2wrs.py doesn't properly handle the
* Quadruple or CharacterStringList types needed for other
* characters, nor representing characters outside ASCII
* in the "cstring" notation (possibly in UTF-8?)
*/
if (!alphabet_length) return sorted_alphabet;
memset(tmp_buf, 0, 256);
@ -804,6 +807,8 @@ sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
for (i=c_min,j=0; i<=c_max; i++) {
if (tmp_buf[i]) sorted_alphabet[j++] = i;
}
*lb = (guint16)c_min;
*ub = (guint16)c_max;
return sorted_alphabet;
}
@ -812,14 +817,24 @@ dissect_per_restricted_character_string(tvbuff_t *tvb, guint32 offset, asn1_ctx_
{
const char *alphabet_ptr;
char sorted_alphabet[128];
guint16 lb = 0;
guint16 ub = 65535;
/* XXX: We don't handle permitted-alphabet characters outside the
* ASCII range if used in BMPString (UCS2) or UniversalString (UCS4)
*/
if (alphabet_length > 127) {
alphabet_ptr = alphabet;
} else {
alphabet_ptr = sort_alphabet(sorted_alphabet, alphabet, alphabet_length);
alphabet_ptr = sort_alphabet(sorted_alphabet, alphabet, alphabet_length, &lb, &ub);
}
/* Not a known-multiplier character string: enforce lb and ub to max values */
return dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension, 0, 65535, alphabet_ptr, alphabet_length, value_tvb);
/* This is for a restricted character string type with a permitted-
* alphabet constraint type. Such constraints are only PER-visible for
* the known-multiplier character string types.
*/
return dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension, lb, ub, alphabet_ptr, alphabet_length, value_tvb);
}
guint32

View File

@ -326,6 +326,19 @@ StringTypes = ['Numeric', 'Printable', 'IA5', 'BMP', 'Universal', 'UTF8',
'Teletex', 'T61', 'Videotex', 'Graphic', 'ISO646', 'Visible',
'General']
# Effective permitted-alphabet constraints are PER-visible only
# for the known-multiplier character string types (X.691 27.1)
#
# XXX: This should include BMPString (UCS2) and UniversalString (UCS4),
# but asn2wrs only suports the RestrictedCharacterStringValue
# notation of "cstring", but not that of "CharacterStringList",
# "Quadruple", or "Tuple" (See X.680 41.8), and packet-per.c does
# not support members of the permitted-alphabet being outside the
# ASCII range. We don't currently have any ASN.1 modules that need it,
# anyway.
KnownMultiplierStringTypes = ('NumericString', 'PrintableString', 'IA5String',
'ISO646String', 'VisibleString')
for s in StringTypes:
reserved_words[s + 'String'] = s + 'String'
@ -5147,7 +5160,11 @@ class RestrictedCharacterStringType (CharacterStringType):
par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
('%(VAL_PTR)s',),))
elif (ectx.Per() and self.HasPermAlph()):
elif (ectx.Per() and self.HasPermAlph() and self.eth_tsname() in KnownMultiplierStringTypes):
# XXX: If there is a permitted alphabet but it is extensible,
# then the permitted-alphabet is not PER-visible and should be
# ignored. (X.691 9.3.10, 9.3.18) We don't handle extensible
# permitted-alphabets.
body = ectx.eth_fn_call('dissect_%(ER)s_restricted_character_string', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(ALPHABET)s', '%(ALPHABET_LEN)s'),