From fde815444b60dffd16b2fcd14953c1f928991d59 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 24 Jan 2012 05:52:39 +0000 Subject: [PATCH] Redesign ASN.1 encoder engine, removing field_info Replace the "field" half of the ASN.1 encoder machinery with several new struct atype_info types (offset, counted, and int_immediate) and a new counted_type machinery used exclusively for object/integer pairs. This change eliminates the two-way entanglement between atypes and fields, and makes the encoder more independent of RFC 4120 ASN.1 conventions. Defining sequences with the preprocessor macros is now slightly more cumbersome; we need to define a type for each field and then string them together with an array of struct atype_info *. But it's not so bad, and hopefully we can auto-generate some of this soon. *_optional functions now return a bitmask of sequence field offsets not present in the C type. This will need some more attention before we add decoding support to the engine, since it means sequence fields no longer know whether they are optional or not. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25657 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/asn.1/asn1_encode.c | 364 ++--- src/lib/krb5/asn.1/asn1_encode.h | 591 +++----- src/lib/krb5/asn.1/asn1_k_encode.c | 2067 +++++++++++++--------------- src/lib/krb5/asn.1/ldap_key_seq.c | 69 +- 4 files changed, 1373 insertions(+), 1718 deletions(-) diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c index e579bb007..48ecc2ff6 100644 --- a/src/lib/krb5/asn.1/asn1_encode.c +++ b/src/lib/krb5/asn.1/asn1_encode.c @@ -99,26 +99,27 @@ asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, } asn1_error_code -asn1_encode_bytestring(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) +asn1_encode_bytestring(asn1buf *buf, unsigned char *const *val, + unsigned int len, unsigned int *retlen) { if (len > 0 && val == NULL) return ASN1_MISSING_FIELD; *retlen = len; - return asn1buf_insert_octetstring(buf, len, val); + return asn1buf_insert_octetstring(buf, len, *val); } asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen) { struct tm *gtime, gtimebuf; - char s[16], *sp; + char s[16]; + unsigned char *sp; time_t gmt_time = val; /* * Time encoding: YYYYMMDDhhmmssZ */ if (gmt_time == 0) { - sp = "19700101000000Z"; + sp = (unsigned char *)"19700101000000Z"; } else { int len; @@ -153,19 +154,19 @@ asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen) if (SNPRINTF_OVERFLOW(len, sizeof(s))) /* Shouldn't be possible given above tests. */ return ASN1_BAD_GMTIME; - sp = s; + sp = (unsigned char *)s; } - return asn1_encode_bytestring(buf, 15, sp, retlen); + return asn1_encode_bytestring(buf, &sp, 15, retlen); } asn1_error_code -asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) +asn1_encode_bitstring(asn1buf *buf, unsigned char *const *val, + unsigned int len, unsigned int *retlen) { asn1_error_code retval; - retval = asn1buf_insert_octetstring(buf, len, val); + retval = asn1buf_insert_octetstring(buf, len, *val); if (retval) return retval; *retlen = len + 1; return asn1buf_insert_octet(buf, '\0'); @@ -256,12 +257,61 @@ load_uint(const void *val, size_t size) } static asn1_error_code -just_encode_sequence(asn1buf *buf, const void *val, - const struct seq_info *seq, - unsigned int *retlen); +load_count(const void *val, const struct counted_info *counted, + unsigned int *retcount) +{ + const void *lenptr = (const char *)val + counted->lenoff; + + assert(sizeof(int) <= sizeof(asn1_intmax)); + assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); + if (counted->lensigned) { + asn1_intmax xlen = load_int(lenptr, counted->lensize); + if (xlen < 0) + return EINVAL; + if ((unsigned int)xlen != (asn1_uintmax)xlen) + return EINVAL; + if ((unsigned int)xlen > UINT_MAX) + return EINVAL; + *retcount = (unsigned int)xlen; + } else { + asn1_uintmax xlen = load_uint(lenptr, counted->lensize); + if ((unsigned int)xlen != xlen) + return EINVAL; + if (xlen > UINT_MAX) + return EINVAL; + *retcount = (unsigned int)xlen; + } + return 0; +} + +/* Split a DER encoding into tag and contents. Insert the contents into buf, + * then return the length of the contents and the tag. */ +static asn1_error_code +split_der(asn1buf *buf, unsigned char *const *der, unsigned int len, + taginfo *rettag) +{ + asn1buf der_buf; + krb5_data der_data = make_data(*der, len); + asn1_error_code retval; + + retval = asn1buf_wrap_data(&der_buf, &der_data); + if (retval) + return retval; + retval = asn1_get_tag_2(&der_buf, rettag); + if (retval) + return retval; + if ((unsigned int)asn1buf_remains(&der_buf, 0) != rettag->length) + return EINVAL; + return asn1buf_insert_bytestring(buf, rettag->length, + *der + len - rettag->length); +} + static asn1_error_code -encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, - taginfo *rettag); +encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq, + unsigned int *retlen); +static asn1_error_code +encode_cntype(asn1buf *buf, const void *val, unsigned int len, + const struct cntype_info *c, taginfo *rettag); /* Encode a value (contents only, no outer tag) according to a type, and return * its encoded tag information. */ @@ -271,6 +321,9 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, { asn1_error_code retval; + if (val == NULL) + return ASN1_MISSING_FIELD; + switch (a->type) { case atype_primitive: { const struct primitive_info *prim = a->tinfo; @@ -289,7 +342,7 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, } case atype_sequence: assert(a->tinfo != NULL); - retval = just_encode_sequence(buf, val, a->tinfo, &rettag->length); + retval = encode_sequence(buf, val, a->tinfo, &rettag->length); if (retval) return retval; rettag->asn1class = UNIVERSAL; @@ -302,9 +355,22 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, return krb5int_asn1_encode_type(buf, LOADPTR(val, ptr), ptr->basetype, rettag); } - case atype_field: - assert(a->tinfo != NULL); - return encode_a_field(buf, val, a->tinfo, rettag); + case atype_offset: { + const struct offset_info *off = a->tinfo; + assert(off->basetype != NULL); + return krb5int_asn1_encode_type(buf, (const char *)val + off->dataoff, + off->basetype, rettag); + } + case atype_counted: { + const struct counted_info *counted = a->tinfo; + const void *dataptr = (const char *)val + counted->dataoff; + unsigned int len; + assert(counted->basetype != NULL); + retval = load_count(val, counted, &len); + if (retval) + return retval; + return encode_cntype(buf, dataptr, len, counted->basetype, rettag); + } case atype_nullterm_sequence_of: case atype_nonempty_nullterm_sequence_of: assert(a->tinfo != NULL); @@ -337,7 +403,7 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, rettag->tagnum = tag->tagval; break; } - case atype_int: { + case atype_int: retval = asn1_encode_integer(buf, load_int(val, a->size), &rettag->length); if (retval) @@ -346,8 +412,7 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, rettag->construction = PRIMITIVE; rettag->tagnum = ASN1_INTEGER; break; - } - case atype_uint: { + case atype_uint: retval = asn1_encode_unsigned_integer(buf, load_uint(val, a->size), &rettag->length); if (retval) @@ -356,18 +421,19 @@ krb5int_asn1_encode_type(asn1buf *buf, const void *val, rettag->construction = PRIMITIVE; rettag->tagnum = ASN1_INTEGER; break; + case atype_int_immediate: { + const int *iptr = a->tinfo; + retval = asn1_encode_integer(buf, *iptr, &rettag->length); + if (retval) + return retval; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; + break; } - case atype_min: - case atype_max: - case atype_string: /* only usable with field_string */ - case atype_der: /* only usable with field_der */ - case atype_choice: /* only usable with field_choice */ default: assert(a->type > atype_min); assert(a->type < atype_max); - assert(a->type != atype_string); - assert(a->type != atype_der); - assert(a->type != atype_choice); abort(); } @@ -393,100 +459,37 @@ encode_type_and_tag(asn1buf *buf, const void *val, const struct atype_info *a, return 0; } +/* + * Encode an object and count according to a cntype_info structure. val is a + * pointer to the object being encoded, which in most cases is itself a + * pointer (but is a union in the cntype_choice case). + */ static asn1_error_code -get_field_len(const void *val, const struct field_info *field, - unsigned int *retlen) -{ - const void *lenptr = (const char *)val + field->lenoff; - - assert(field->lentype != NULL); - assert(field->lentype->type == atype_int || - field->lentype->type == atype_uint); - assert(sizeof(int) <= sizeof(asn1_intmax)); - assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); - if (field->lentype->type == atype_int) { - asn1_intmax xlen = load_int(lenptr, field->lentype->size); - if (xlen < 0) - return EINVAL; - if ((unsigned int)xlen != (asn1_uintmax)xlen) - return EINVAL; - if ((unsigned int)xlen > UINT_MAX) - return EINVAL; - *retlen = (unsigned int)xlen; - } else { - asn1_uintmax xlen = load_uint(lenptr, field->lentype->size); - if ((unsigned int)xlen != xlen) - return EINVAL; - if (xlen > UINT_MAX) - return EINVAL; - *retlen = (unsigned int)xlen; - } - return 0; -} - -/* Split a DER encoding into tag and contents. Insert the contents into buf, - * then return the length of the contents and the tag. */ -static asn1_error_code -split_der(asn1buf *buf, const unsigned char *der, unsigned int len, - taginfo *rettag) -{ - asn1buf der_buf; - krb5_data der_data = make_data((unsigned char *)der, len); - asn1_error_code retval; - - retval = asn1buf_wrap_data(&der_buf, &der_data); - if (retval) - return retval; - retval = asn1_get_tag_2(&der_buf, rettag); - if (retval) - return retval; - if ((unsigned int)asn1buf_remains(&der_buf, 0) != rettag->length) - return EINVAL; - return asn1buf_insert_bytestring(buf, rettag->length, - der + len - rettag->length); -} - -/* Encode part of a value (contents only, no tag) according to a field - * descriptor and return its encoded length and tag. */ -static asn1_error_code -encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, - taginfo *rettag) +encode_cntype(asn1buf *buf, const void *val, unsigned int count, + const struct cntype_info *c, taginfo *rettag) { asn1_error_code retval; - if (val == NULL) return ASN1_MISSING_FIELD; - assert(!(field->tag_implicit && field->tag < 0)); - - switch (field->ftype) { - case field_immediate: { - retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff, - &rettag->length); + switch (c->type) { + case cntype_string: { + const struct string_info *string = c->tinfo; + assert(string->enc != NULL); + retval = string->enc(buf, val, count, &rettag->length); if (retval) return retval; rettag->asn1class = UNIVERSAL; rettag->construction = PRIMITIVE; - rettag->tagnum = ASN1_INTEGER; + rettag->tagnum = string->tagval; break; } - case field_sequenceof_len: { - const void *dataptr = (const char *)val + field->dataoff; - unsigned int slen; - const struct ptr_info *ptrinfo; - - /* - * The field holds a pointer to the array of objects. So the - * address we compute is a pointer-to-pointer, and that's what - * field->atype must help us dereference. - */ - assert(field->atype->type == atype_ptr); - ptrinfo = field->atype->tinfo; - dataptr = LOADPTR(dataptr, ptrinfo); - retval = get_field_len(val, field, &slen); - if (retval) - return retval; - if (slen != 0 && dataptr == NULL) - return ASN1_MISSING_FIELD; - retval = encode_sequence_of(buf, slen, dataptr, ptrinfo->basetype, + case cntype_der: + return split_der(buf, val, count, rettag); + case cntype_seqof: { + const struct atype_info *a = c->tinfo; + const struct ptr_info *ptr = a->tinfo; + assert(a->type == atype_ptr); + val = LOADPTR(val, ptr); + retval = encode_sequence_of(buf, count, val, ptr->basetype, &rettag->length); if (retval) return retval; @@ -495,140 +498,47 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, rettag->tagnum = ASN1_SEQUENCE; break; } - case field_normal: { - const void *dataptr = (const char *)val + field->dataoff; - retval = krb5int_asn1_encode_type(buf, dataptr, field->atype, rettag); - if (retval) - return retval; - break; - } - case field_string: { - const void *dataptr = (const char *)val + field->dataoff; - const struct atype_info *a; - unsigned int slen; - const struct string_info *string; - - a = field->atype; - assert(a->type == atype_string); - retval = get_field_len(val, field, &slen); - if (retval) - return retval; - string = a->tinfo; - dataptr = LOADPTR(dataptr, string); - if (dataptr == NULL && slen != 0) - return ASN1_MISSING_FIELD; - assert(string->enclen != NULL); - retval = string->enclen(buf, slen, dataptr, &rettag->length); - if (retval) - return retval; - rettag->asn1class = UNIVERSAL; - rettag->construction = PRIMITIVE; - rettag->tagnum = string->tagval; - break; - } - case field_der: { - const void *dataptr = (const char *)val + field->dataoff; - const struct atype_info *a; - unsigned int slen; - const struct ptr_info *ptr; - - a = field->atype; - assert(a->type == atype_der); - retval = get_field_len(val, field, &slen); - if (retval) - return retval; - ptr = a->tinfo; - dataptr = LOADPTR(dataptr, ptr); - if (dataptr == NULL && slen != 0) + case cntype_choice: { + const struct choice_info *choice = c->tinfo; + if (count > choice->n_options) return ASN1_MISSING_FIELD; - retval = split_der(buf, dataptr, slen, rettag); - if (retval) - return retval; - break; - } - case field_choice: { - const void *dataptr = (const char *)val + field->dataoff; - unsigned int choice; - const struct seq_info *seq; - - assert(field->atype->type == atype_choice); - seq = field->atype->tinfo; - retval = get_field_len(val, field, &choice); - if (retval) - return retval; - if (choice > seq->n_fields) - return ASN1_MISSING_FIELD; - retval = encode_a_field(buf, dataptr, &seq->fields[choice], rettag); - if (retval) - return retval; - break; + return krb5int_asn1_encode_type(buf, val, choice->options[count], + rettag); } + default: - assert(field->ftype > field_min); - assert(field->ftype < field_max); - assert(__LINE__ == 0); + assert(c->type > cntype_min); + assert(c->type < cntype_max); abort(); } - if (field->tag >= 0) { - if (!field->tag_implicit) { - unsigned int tlen; - retval = asn1_make_tag(buf, rettag->asn1class, - rettag->construction, rettag->tagnum, - rettag->length, &tlen); - if (retval) - return retval; - rettag->length += tlen; - rettag->construction = CONSTRUCTED; - } - rettag->asn1class = CONTEXT_SPECIFIC; - rettag->tagnum = field->tag; - } return 0; } static asn1_error_code -encode_fields(asn1buf *buf, const void *val, - const struct field_info *fields, size_t nfields, - unsigned int optional, - unsigned int *retlen) +encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq, + unsigned int *retlen) { + asn1_error_code retval; + unsigned int not_present, length, sum = 0; size_t i; - unsigned int sum = 0; - for (i = nfields; i > 0; i--) { - const struct field_info *f = fields+i-1; - taginfo t; - asn1_error_code retval; + const struct atype_info *a; - if (f->opt != -1 && !((1u << f->opt) & optional)) + /* If any fields might be optional, get a bitmask of fields not present. */ + not_present = (seq->optional == NULL) ? 0 : seq->optional(val); + for (i = seq->n_fields; i > 0; i--) { + a = seq->fields[i - 1]; + if ((1u << (i - 1)) & not_present) continue; - retval = encode_a_field(buf, val, f, &t); - if (retval) - return retval; - sum += t.length; - retval = asn1_make_tag(buf, t.asn1class, t.construction, t.tagnum, - t.length, &t.length); + retval = encode_type_and_tag(buf, val, a, &length); if (retval) return retval; - sum += t.length; + sum += length; } *retlen = sum; return 0; } -static asn1_error_code -just_encode_sequence(asn1buf *buf, const void *val, - const struct seq_info *seq, - unsigned int *retlen) -{ - unsigned int optional; - - /* If any fields might be optional, get a bitmask of optional fields. */ - optional = (seq->optional == NULL) ? 0 : seq->optional(val); - return encode_fields(buf, val, seq->fields, seq->n_fields, optional, - retlen); -} - static asn1_error_code encode_sequence_of(asn1buf *buf, unsigned int seqlen, const void *val, const struct atype_info *eltinfo, diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h index cd7983ac7..4f302fee1 100644 --- a/src/lib/krb5/asn.1/asn1_encode.h +++ b/src/lib/krb5/asn.1/asn1_encode.h @@ -73,8 +73,8 @@ asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, * to expand the buffer. */ -asn1_error_code asn1_encode_bytestring(asn1buf *buf, unsigned int len, - const void *val, unsigned int *retlen); +asn1_error_code asn1_encode_bytestring(asn1buf *buf, unsigned char *const *val, + unsigned int len, unsigned int *retlen); /* * requires *buf is allocated * modifies *buf, *retlen @@ -106,11 +106,10 @@ asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, * Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ */ -asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, - const void *val, - unsigned int *retlen); +asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned char *const *val, + unsigned int len, unsigned int *retlen); /* - * requires *buf is allocated, val has a length of len characters + * requires *buf is allocated, *val has a length of len characters * modifies *buf, *retlen * effects Inserts the encoding of val into *buf and returns * the length of the encoding in *retlen. @@ -119,28 +118,8 @@ asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, */ /* - * Type descriptor info. - * - * In this context, a "type" is a combination of a C data type - * and an ASN.1 encoding scheme for it. So we would have to define - * different "types" for: - * - * * unsigned char* encoded as octet string - * * char* encoded as octet string - * * char* encoded as generalstring - * * krb5_data encoded as octet string - * * krb5_data encoded as generalstring - * * int32_t encoded as integer - * * unsigned char encoded as integer - * - * Perhaps someday some kind of flags could be defined so that minor - * variations on the C types could be handled via common routines. - * - * The handling of strings is pretty messy. Currently, we have a - * separate kind of encoder function that takes an extra length - * parameter. Perhaps we should just give up on that, always deal - * with just a single location, and handle strings by via encoder - * functions for krb5_data, keyblock, etc. + * An atype_info structure specifies how to encode a pointer to a C + * object as an ASN.1 type. * * We wind up with a lot of load-time relocations being done, which is * a bit annoying. Be careful about "fixing" that at the cost of too @@ -165,44 +144,23 @@ enum atype_type { * primitive_info *. */ atype_primitive, /* - * Encoder function to be called with address of . The encoder - * function must generate a sequence without the sequence tag. tinfo is a + * Encoder function to be called with address of . tinfo is a * struct fn_info *. Used only by kdc_req_body. */ atype_fn, + /* Pointer to actual thing to be encoded. tinfo is a struct ptr_info *. */ + atype_ptr, + /* Actual thing to be encoded is at an offset from the original pointer. + * tinfo is a struct offset_info *. */ + atype_offset, /* - * Encoder function (contents only) to be called with address of - * and a length (unsigned int), and wrapped with a universal primitive tag. - * tinfo is a struct string_info *. Only usable with the field_string - * field type. - */ - atype_string, - /* - * Pre-made DER encoding stored at the address of . tinfo is a - * struct ptr_info * with the basetype field ignored. Only usable with the - * field_der field type. - */ - atype_der, - /* - * Pointer to actual thing to be encoded. tinfo is a struct ptr_info *. - * - * Most of the fields are related only to the C type -- size, how - * to fetch a pointer in a type-safe fashion -- but since the base - * type descriptor encapsulates the encoding as well, different - * encodings for the same C type may require different pointer-to - * types as well. - * - * Must not refer to atype_fn_len. + * Actual thing to be encoded is an object at an offset from the original + * pointer, combined with an integer at a different offset, in a manner + * specified by a cntype_info base type. tinfo is a struct counted_info *. */ - atype_ptr, + atype_counted, /* Sequence. tinfo is a struct seq_info *. */ atype_sequence, - /* - * Choice. tinfo is a struct seq_info *, with the optional field ignored. - * Only usable with the field_choice field type. Cannot be used with an - * implicit context tag. - */ - atype_choice, /* * Sequence-of, with pointer to base type descriptor, represented * as a null-terminated array of pointers (and thus the "base" @@ -211,21 +169,15 @@ enum atype_type { */ atype_nullterm_sequence_of, atype_nonempty_nullterm_sequence_of, - /* - * Encode this object using a single field descriptor. tinfo is a struct - * field_info *. The presence of this type may mean the atype/field - * breakdown needs revision.... - * - * Main expected uses: Encode realm component of principal as a - * GENERALSTRING. Pluck data and length fields out of a structure - * and encode a counted SEQUENCE OF. - */ - atype_field, /* Tagged version of another type. tinfo is a struct tagged_info *. */ atype_tagged_thing, - /* Signed or unsigned integer. tinfo is NULL. */ + /* Signed or unsigned integer. tinfo is NULL (the atype_info size field is + * used to determine the width). */ atype_int, atype_uint, + /* Integer value taken from the type info, not from the object being + * encoded. tinfo is an int *. */ + atype_int_immediate, /* Unused except for bounds checking. */ atype_max }; @@ -245,30 +197,80 @@ struct fn_info { asn1_error_code (*enc)(asn1buf *, const void *, taginfo *); }; -struct string_info { - asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *, - unsigned int *); +struct ptr_info { const void *(*loadptr)(const void *); - unsigned int tagval; + const struct atype_info *basetype; }; -struct ptr_info { - const void *(*loadptr)(const void *); +struct offset_info { + unsigned int dataoff : 9; const struct atype_info *basetype; }; +struct counted_info { + unsigned int dataoff : 9; + unsigned int lenoff : 9; + unsigned int lensigned : 1; + unsigned int lensize : 5; + const struct cntype_info *basetype; +}; + struct tagged_info { unsigned int tagval : 16, tagtype : 8, construction : 6, implicit : 1; const struct atype_info *basetype; }; +/* A cntype_info structure specifies how to encode a pointer to a C object and + * count (length or union distinguisher) as an ASN.1 object. */ + +enum cntype_type { + cntype_min = 1, + + /* + * Apply an encoder function (contents only) and wrap it in a universal + * primitive tag. The object must be a char * or unsigned char *. tinfo + * is a struct string_info *. + */ + cntype_string, + + /* Insert a pre-made DER encoding contained at the pointer and length. The + * object must be a char * or unsigned char *. tinfo is NULL. */ + cntype_der, + + /* Encode a counted sequence of a given base type. tinfo is a struct + * atype_info * giving the base type, which must be of type atype_ptr. */ + cntype_seqof, + + /* Encode one of several alternatives from a union object, using the count + * as a distinguisher. tinfo is a struct choice_info *. */ + cntype_choice, + + cntype_max +}; + +struct cntype_info { + enum cntype_type type; + const void *tinfo; +}; + +struct string_info { + asn1_error_code (*enc)(asn1buf *, unsigned char *const *, unsigned int, + unsigned int *); + unsigned int tagval : 5; +}; + +struct choice_info { + const struct atype_info **options; + size_t n_options; +}; + /* * The various DEF*TYPE macros must: * * + Define a type named aux_typedefname_##DESCNAME, for use in any * types derived from the type being defined. * - * + Define an atype_info struct named krb5int_asn1type_##DESCNAME + * + Define an atype_info struct named k5_atype_##DESCNAME * * + Define a type-specific structure, referenced by the tinfo field * of the atype_info structure. @@ -304,7 +306,7 @@ struct tagged_info { static const struct primitive_info aux_info_##DESCNAME = { \ aux_encfn_##DESCNAME, TAG \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_primitive, sizeof(CTYPENAME), &aux_info_##DESCNAME \ } /* Define a type using an explicit (with tag) encoder function. */ @@ -313,101 +315,45 @@ struct tagged_info { static const struct fn_info aux_info_##DESCNAME = { \ ENCFN \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \ } -/* - * XXX The handling of data+length fields really needs reworking. - * A type descriptor probably isn't the right way. - * - * Also, the C type is likely to be one of char*, unsigned char*, - * or (maybe) void*. An enumerator or reference to an external - * function would be more compact. - * - * The supplied encoder function takes as an argument the data pointer - * loaded from the indicated location, not the address of the field. - * This isn't consistent with DEFFN[X]TYPE above, but all of the uses - * of DEFFNLENTYPE are for string encodings, and that's how our - * string-encoding primitives work. So be it. - */ -#ifdef POINTERS_ARE_ALL_THE_SAME -#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL) \ - typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const struct string_info aux_info_##DESCNAME = { \ - ENCFN, NULL, TAGVAL \ - } \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_string, 0, &aux_info_##DESCNAME \ - } -#else -#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL) \ - typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const void *loadptr_for_##DESCNAME(const void *pv) \ - { \ - const aux_typedefname_##DESCNAME *p = pv; \ - return *p; \ - } \ - static const struct string_info aux_info_##DESCNAME = { \ - ENCFN, loadptr_for_##DESCNAME, TAGVAL \ - }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_string, 0, &aux_info_##DESCNAME \ - } -#endif -/* Not used enough to justify a POINTERS_ARE_ALL_THE_SAME version. */ -#define DEFDERTYPE(DESCNAME, CTYPENAME) \ - typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const void *loadptr_for_##DESCNAME(const void *pv) \ - { \ - const aux_typedefname_##DESCNAME *p = pv; \ - return *p; \ - } \ - static const struct ptr_info aux_info_##DESCNAME = { \ - loadptr_for_##DESCNAME \ - }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_der, 0, &aux_info_##DESCNAME \ - } -/* - * A sequence, defined by the indicated series of fields, and an - * optional function indicating which fields are present. - */ +/* A sequence, defined by the indicated series of types, and an optional + * function indicating which fields are not present. */ #define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS, OPT) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ static const struct seq_info aux_seqinfo_##DESCNAME = { \ OPT, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_sequence, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \ } -/* A choice, selected from the indicated series of fields. */ -#define DEFCHOICETYPE(DESCNAME, CTYPENAME, FIELDS) \ - typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const struct seq_info aux_seqinfo_##DESCNAME = { \ - NULL, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \ - }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_choice, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \ - } /* Integer types. */ #define DEFINTTYPE(DESCNAME, CTYPENAME) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_int, sizeof(CTYPENAME), NULL \ } #define DEFUINTTYPE(DESCNAME, CTYPENAME) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_uint, sizeof(CTYPENAME), NULL \ } +#define DEFINT_IMMEDIATE(DESCNAME, VAL) \ + typedef void aux_typedefname_##DESCNAME; \ + static const int aux_int_##DESCNAME = VAL; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_int_immediate, 0, &aux_int_##DESCNAME \ + } + /* Pointers to other types, to be encoded as those other types. */ #ifdef POINTERS_ARE_ALL_THE_SAME #define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \ typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \ static const struct ptr_info aux_info_##DESCNAME = { \ - NULL, &krb5int_asn1type_##BASEDESCNAME \ + NULL, &k5_atype_##BASEDESCNAME \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_ptr, sizeof(aux_typedefname_##DESCNAME), \ &aux_info_##DESCNAME \ } @@ -424,13 +370,41 @@ struct tagged_info { } \ static const struct ptr_info aux_info_##DESCNAME = { \ loadptr_for_##BASEDESCNAME##_from_##DESCNAME, \ - &krb5int_asn1type_##BASEDESCNAME \ + &k5_atype_##BASEDESCNAME \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_ptr, sizeof(aux_typedefname_##DESCNAME), \ &aux_info_##DESCNAME \ } #endif +#define DEFOFFSETTYPE(DESCNAME, STYPE, FIELDNAME, BASEDESC) \ + typedef STYPE aux_typedefname_##DESCNAME; \ + static const struct offset_info aux_info_##DESCNAME = { \ + OFFOF(STYPE, FIELDNAME, aux_typedefname_##BASEDESC), \ + &k5_atype_##BASEDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_offset, sizeof(aux_typedefname_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +#define DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, SIGNED, \ + CDESC) \ + typedef STYPE aux_typedefname_##DESCNAME; \ + const struct counted_info aux_info_##DESCNAME = { \ + OFFOF(STYPE, DATAFIELD, aux_ptrtype_##CDESC), \ + OFFOF(STYPE, COUNTFIELD, aux_counttype_##CDESC), \ + SIGNED, sizeof(((STYPE*)0)->COUNTFIELD), \ + &k5_cntype_##CDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_counted, sizeof(STYPE), \ + &aux_info_##DESCNAME \ + } +#define DEFCOUNTEDTYPE(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \ + DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 0, CDESC) +#define DEFCOUNTEDTYPE_SIGNED(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \ + DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 1, CDESC) + /* * This encodes a pointer-to-pointer-to-thing where the passed-in * value points to a null-terminated list of pointers to objects to be @@ -445,54 +419,99 @@ struct tagged_info { */ #define DEFNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_nullterm_sequence_of, sizeof(aux_typedefname_##DESCNAME), \ - &krb5int_asn1type_##BASEDESCNAME \ + &k5_atype_##BASEDESCNAME \ } #define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_nonempty_nullterm_sequence_of, \ sizeof(aux_typedefname_##DESCNAME), \ - &krb5int_asn1type_##BASEDESCNAME \ - } -/* - * Encode a thing (probably sub-fields within the structure) as a - * single object. - */ -#define DEFFIELDTYPE(DESCNAME, CTYPENAME, FIELDINFO) \ - typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const struct field_info aux_fieldinfo_##DESCNAME = FIELDINFO; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_field, sizeof(CTYPENAME), &aux_fieldinfo_##DESCNAME \ + &k5_atype_##BASEDESCNAME \ } + /* Objects with an explicit or implicit tag. (Implicit tags will ignore the * construction field.) */ #define DEFTAGGEDTYPE(DESCNAME, CLASS, CONSTRUCTION, TAG, IMPLICIT, BASEDESC) \ typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME; \ static const struct tagged_info aux_info_##DESCNAME = { \ - TAG, CLASS, CONSTRUCTION, IMPLICIT, &krb5int_asn1type_##BASEDESC \ + TAG, CLASS, CONSTRUCTION, IMPLICIT, &k5_atype_##BASEDESC \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ + const struct atype_info k5_atype_##DESCNAME = { \ atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME), \ &aux_info_##DESCNAME \ } /* Objects with an explicit APPLICATION tag added. */ #define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \ - DEFTAGGEDTYPE(DESCNAME, APPLICATION, CONSTRUCTED, TAG, 0, BASEDESC) + DEFTAGGEDTYPE(DESCNAME, APPLICATION, CONSTRUCTED, TAG, 0, BASEDESC) +/* Object with a context-specific tag added */ +#define DEFCTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \ + DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 0, BASEDESC) +#define DEFCTAGGEDTYPE_IMPLICIT(DESCNAME, TAG, BASEDESC) \ + DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 1, BASEDESC) + +/* Define an offset type with an explicit context tag wrapper (the usual case + * for an RFC 4120 sequence field). */ +#define DEFFIELD(NAME, STYPE, FIELDNAME, TAG, DESC) \ + DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC); \ + DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged) +/* Define a counted type with an explicit context tag wrapper. */ +#define DEFCNFIELD(NAME, STYPE, DATAFIELD, LENFIELD, TAG, CDESC) \ + DEFCOUNTEDTYPE(NAME##_untagged, STYPE, DATAFIELD, LENFIELD, CDESC); \ + DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged) +/* Like DEFFIELD but with an implicit context tag. */ +#define DEFFIELD_IMPLICIT(NAME, STYPE, FIELDNAME, TAG, DESC) \ + DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC); \ + DEFCTAGGEDTYPE_IMPLICIT(NAME, TAG, NAME##_untagged) -/** - * An encoding wrapped in an octet string +/* + * DEFCOUNTED*TYPE macros must: + * + * + Define types named aux_ptrtype_##DESCNAME and aux_counttype_##DESCNAME, to + * allow type checking when the counted type is referenced with structure + * field offsets in DEFCOUNTEDTYPE. + * + * + Define a cntype_info struct named k5_cntype_##DESCNAME + * + * + Define a type-specific structure, referenced by the tinfo field of the + * cntype_info structure. + * + * + Accept a following semicolon syntactically. */ -#define DEFOCTETWRAPTYPE(DESCNAME, BASEDESC) \ - typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME; \ - static const struct tagged_info aux_info_##DESCNAME = { \ - ASN1_OCTETSTRING, UNIVERSAL, PRIMITIVE, 0, \ - &krb5int_asn1type_##BASEDESC \ + +#define DEFCOUNTEDSTRINGTYPE(DESCNAME, DTYPE, LTYPE, ENCFN, TAGVAL) \ + typedef DTYPE aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + static const struct string_info aux_info_##DESCNAME = { \ + ENCFN, TAGVAL \ }; \ - const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME), \ - &aux_info_##DESCNAME \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_string, &aux_info_##DESCNAME \ + } + +#define DEFCOUNTEDDERTYPE(DESCNAME, DTYPE, LTYPE) \ + typedef DTYPE aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_der, NULL \ + } + +#define DEFCOUNTEDSEQOFTYPE(DESCNAME, LTYPE, BASEDESC) \ + typedef aux_typedefname_##BASEDESC aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_seqof, &k5_atype_##BASEDESC \ + } + +#define DEFCHOICETYPE(DESCNAME, UTYPE, DTYPE, FIELDS) \ + typedef UTYPE aux_ptrtype_##DESCNAME; \ + typedef DTYPE aux_counttype_##DESCNAME; \ + static const struct choice_info aux_info_##DESCNAME = { \ + FIELDS, sizeof(FIELDS) / sizeof(FIELDS[0]) \ + }; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_choice, &aux_info_##DESCNAME \ } /* @@ -508,7 +527,7 @@ struct tagged_info { */ #define IMPORT_TYPE(DESCNAME, CTYPENAME) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ - extern const struct atype_info krb5int_asn1type_##DESCNAME + extern const struct atype_info k5_atype_##DESCNAME /* Partially encode the contents of a type and return its tag information. * Used only by asn1_encode_kdc_req_body. */ @@ -516,218 +535,14 @@ asn1_error_code krb5int_asn1_encode_type(asn1buf *buf, const void *val, const struct atype_info *a, taginfo *rettag); -/* - * Sequence field descriptor. - * - * Currently we assume everything is a single object with a type - * descriptor, and then we bolt on some ugliness on the side for - * handling strings with length fields. - * - * Anything with "interesting" encoding handling, like a sequence-of - * or a pointer to the actual value to encode, is handled via opaque - * types with their own encoder functions. Most of that should - * eventually change. - */ - -enum field_type { - /* Unused except for range checking. */ - field_min = 1, - /* Field ATYPE describes processing of field at DATAOFF. */ - field_normal, - /* - * Encode an "immediate" integer value stored in DATAOFF, with no - * reference to the data structure. - */ - field_immediate, - /* - * Encode some kind of string field encoded with pointer and - * length. (A GENERALSTRING represented as a null-terminated C - * string would be handled as field_normal.) - */ - field_string, - /* Insert a DER encoding given by the pointer and length. */ - field_der, - /* - * LENOFF indicates a value describing the length of the array at - * DATAOFF, encoded as a sequence-of with the element type - * described by ATYPE. - */ - field_sequenceof_len, - /* - * LENOFF indicates a distinguisher and DATAOFF indicates a union base - * address. ATYPE is an atype_choice type pointing to a seq_info - * containing a field type for each choice element. - */ - field_choice, - /* Unused except for range checking. */ - field_max -}; -/* To do: Consider using bitfields. */ -struct field_info { - /* Type of the field. */ - unsigned int /* enum field_type */ ftype : 3; - - /* - * Use of DATAOFF and LENOFF are described by the value in FTYPE. - * Generally DATAOFF will be the offset from the supplied pointer - * at which we find the object to be encoded. - */ - unsigned int dataoff : 9, lenoff : 9; - - /* - * If TAG is non-negative, a context tag with that value is added - * to the encoding of the thing. (XXX This would encode more - * compactly as an unsigned bitfield value tagnum+1, with 0=no - * tag.) The tag is omitted for optional fields that are not - * present. If tag_implicit is set, then the context tag replaces - * the outer tag of the field, and uses the same construction bit - * as the outer tag would have used. - * - * It's a bit illogical to combine the tag and other field info, - * since really a sequence field could have zero or several - * context tags, and of course a tag could be used elsewhere. But - * the normal mode in the Kerberos ASN.1 description is to use one - * context tag on each sequence field, so for now let's address - * that case primarily and work around the other cases (thus tag<0 - * means skip tagging). - */ - signed int tag : 5; - unsigned int tag_implicit : 1; - - /* - * If OPT is non-negative and the sequence header structure has a - * function pointer describing which fields are present, OPT is - * the bit position indicating whether the currently-described - * element is present. (XXX Similar encoding issue.) - * - * Note: Most of the time, I'm using the same number here as for - * the context tag. This is just because it's easier for me to - * keep track while working on the code by hand. The *only* - * meaningful correlation is of this value and the bits set by the - * "optional" function when examining the data structure. - */ - signed int opt : 5; - - /* - * For some values of FTYPE, this describes the type of the - * object(s) to be encoded. - */ - const struct atype_info *atype; - - /* - * We use different types for "length" fields in different places. - * So we need a good way to retrieve the various kinds of lengths - * in a compatible way. This may be a string length, or the - * length of an array of objects to encode in a SEQUENCE OF. - * - * In case the field is signed and negative, or larger than - * size_t, return SIZE_MAX as an error indication. We'll assume - * for now that we'll never have 4G-1 (or 2**64-1, or on tiny - * systems, 65535) sized values. On most if not all systems we - * care about, SIZE_MAX is equivalent to "all of addressable - * memory" minus one byte. That wouldn't leave enough extra room - * for the structure we're encoding, so it's pretty safe to assume - * SIZE_MAX won't legitimately come up on those systems. - * - * If this code gets ported to a segmented architecture or other - * system where it might be possible... figure it out then. - */ - const struct atype_info *lentype; -}; - -/* - * Normal or optional sequence fields at a particular offset, encoded - * as indicated by the listed DESCRiptor. - */ -#define FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,IMPLICIT,OPT) \ - { \ - field_normal, OFFOF(TYPE, FIELDNAME, aux_typedefname_##DESCR), \ - 0, TAG, IMPLICIT, OPT, &krb5int_asn1type_##DESCR \ - } -#define FIELDOF_NORM(TYPE,DESCR,FIELDNAME,TAG,IMPLICIT) \ - FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,IMPLICIT,-1) -/* - * If encoding a subset of the fields of the current structure (for - * example, a flat structure describing data that gets encoded as a - * sequence containing one or more sequences), use ENCODEAS, no struct - * field name(s), and the indicated type descriptor must support the - * current struct type. - */ -#define FIELDOF_ENCODEAS(TYPE,DESCR,TAG,IMPLICIT) \ - FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,IMPLICIT,-1) -#define FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,IMPLICIT,OPT) \ - { \ - field_normal, \ - 0 * sizeof(0 ? (TYPE *)0 : (aux_typedefname_##DESCR *) 0), \ - 0, TAG, IMPLICIT, OPT, &krb5int_asn1type_##DESCR \ - } - -/* - * Reinterpret some subset of the structure itself as something - * else. - */ -#define FIELD_SELF(DESCR, TAG, IMPLICIT) \ - { field_normal, 0, 0, TAG, IMPLICIT, -1, &krb5int_asn1type_##DESCR } - -#define FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,IMP,OPT) \ - { \ - field_string, \ - OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ - OFFOF(STYPE, LENFIELD, aux_typedefname_##LENDESC), \ - TAG, IMP, OPT, \ - &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENDESC \ - } -#define FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,IMPLICIT,OPT) \ - FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,uint,LENFIELD,TAG,IMPLICIT,OPT) -#define FIELDOF_STRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,IMPLICIT) \ - FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,IMPLICIT,-1) -#define FIELDOF_STRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,IMPLICIT) \ - FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,IMPLICIT,-1) -#define FIELD_INT_IMM(VALUE,TAG,IMPLICIT) \ - { field_immediate, VALUE, 0, TAG, IMPLICIT, -1, 0, } - -#define FIELDOF_OPTDER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT,OPT) \ - { field_der, \ - OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ - OFFOF(STYPE, LENFIELD, aux_typedefname_##LENTYPE), \ - TAG, IMPLICIT, OPT, \ - &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \ - } -#define FIELDOF_DER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT) \ - FIELDOF_OPTDER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT,-1) - -#define FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT) \ - { \ - field_sequenceof_len, \ - OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ - OFFOF(STYPE, LENFIELD, aux_typedefname_##LENTYPE), \ - TAG, IMPLICIT, -1, \ - &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \ - } -#define FIELDOF_SEQOF_INT32(STYPE,DESC,PTRFIELD,LENFIELD,TAG,IMPLICIT) \ - FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,int32,TAG,IMPLICIT) - -#define FIELDOF_OPTCHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG,OPT) \ - { \ - field_choice, \ - OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ - OFFOF(STYPE, CHOICEFIELD, aux_typedefname_##LENTYPE), \ - TAG, 0, OPT, \ - &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \ - } -#define FIELDOF_CHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG) \ - FIELDOF_OPTCHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG,-1) - struct seq_info { - /* - * If present, returns a bitmask indicating which fields are - * present. See the "opt" field in struct field_info. - */ + /* If present, returns a bitmask indicating which fields are present. The + * bit (1 << N) corresponds to index N in the fields array. */ unsigned int (*optional)(const void *); /* Indicates an array of sequence field descriptors. */ - const struct field_info *fields; + const struct atype_info **fields; size_t n_fields; - /* Missing: Extensibility handling. (New field type?) */ + /* Currently all sequences are assumed to be extensible. */ }; extern krb5_error_code @@ -739,7 +554,7 @@ krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, krb5_data **code) \ { \ return krb5int_asn1_do_full_encode(rep, code, \ - &krb5int_asn1type_##DESC); \ + &k5_atype_##DESC); \ } \ extern int dummy /* gobble semicolon */ diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index f9af88d75..6f05f1567 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -28,47 +28,45 @@ #include "asn1_encode.h" #include +DEFINT_IMMEDIATE(krb5_version, KVNO); + DEFINTTYPE(int32, krb5_int32); DEFPTRTYPE(int32_ptr, int32); +DEFCOUNTEDSEQOFTYPE(cseqof_int32, krb5_int32, int32_ptr); DEFUINTTYPE(uint, unsigned int); DEFUINTTYPE(octet, krb5_octet); DEFUINTTYPE(ui_4, krb5_ui_4); -DEFSTRINGTYPE(octetstring, unsigned char *, asn1_encode_bytestring, - ASN1_OCTETSTRING); -DEFSTRINGTYPE(s_octetstring, char *, asn1_encode_bytestring, ASN1_OCTETSTRING); -DEFSTRINGTYPE(generalstring, char *, asn1_encode_bytestring, - ASN1_GENERALSTRING); -DEFSTRINGTYPE(u_generalstring, unsigned char *, asn1_encode_bytestring, - ASN1_GENERALSTRING); -DEFDERTYPE(der, char *); - -DEFFIELDTYPE(gstring_data, krb5_data, - FIELDOF_STRING(krb5_data, generalstring, data, length, -1, 0)); -DEFPTRTYPE(gstring_data_ptr,gstring_data); - -DEFFIELDTYPE(ostring_data, krb5_data, - FIELDOF_STRING(krb5_data, s_octetstring, data, length, -1, 0)); -DEFPTRTYPE(ostring_data_ptr,ostring_data); - -DEFFIELDTYPE(der_data, krb5_data, - FIELDOF_DER(krb5_data, der, data, length, uint, -1, 0)); - -DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, - FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1, 0)); +DEFCOUNTEDDERTYPE(der, char *, unsigned int); +DEFCOUNTEDTYPE(der_data, krb5_data, data, length, der); + +DEFCOUNTEDSTRINGTYPE(octetstring, unsigned char *, unsigned int, + asn1_encode_bytestring, ASN1_OCTETSTRING); +DEFCOUNTEDSTRINGTYPE(s_octetstring, char *, unsigned int, + asn1_encode_bytestring, ASN1_OCTETSTRING); +DEFCOUNTEDTYPE(ostring_data, krb5_data, data, length, s_octetstring); +DEFPTRTYPE(ostring_data_ptr, ostring_data); + +DEFCOUNTEDSTRINGTYPE(generalstring, char *, unsigned int, + asn1_encode_bytestring, ASN1_GENERALSTRING); +DEFCOUNTEDSTRINGTYPE(u_generalstring, unsigned char *, unsigned int, + asn1_encode_bytestring, ASN1_GENERALSTRING); +DEFCOUNTEDTYPE(gstring_data, krb5_data, data, length, generalstring); +DEFPTRTYPE(gstring_data_ptr, gstring_data); +DEFCOUNTEDSEQOFTYPE(cseqof_gstring_data, krb5_int32, gstring_data_ptr); + +DEFOFFSETTYPE(realm_of_principal_data, krb5_principal_data, realm, + gstring_data); DEFPTRTYPE(realm_of_principal, realm_of_principal_data); -static const struct field_info princname_fields[] = { - FIELDOF_NORM(krb5_principal_data, int32, type, 0, 0), - FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, - 1, 0), +DEFFIELD(princname_0, krb5_principal_data, type, 0, int32); +DEFCNFIELD(princname_1, krb5_principal_data, data, length, 1, + cseqof_gstring_data); +static const struct atype_info *princname_fields[] = { + &k5_atype_princname_0, &k5_atype_princname_1 }; -/* - * krb5_principal is a typedef for krb5_principal_data*, so this is - * effectively "encode_principal_data_at" with an address arg. - */ -DEFSEQTYPE(principal_data, krb5_principal_data, princname_fields, 0); +DEFSEQTYPE(principal_data, krb5_principal_data, princname_fields, NULL); DEFPTRTYPE(principal, principal_data); static asn1_error_code @@ -82,33 +80,32 @@ asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val, DEFPRIMITIVETYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at, ASN1_GENERALTIME); -const static struct field_info address_fields[] = { - FIELDOF_NORM(krb5_address, int32, addrtype, 0, 0), - FIELDOF_STRING(krb5_address, octetstring, contents, length, 1, 0), +DEFFIELD(address_0, krb5_address, addrtype, 0, int32); +DEFCNFIELD(address_1, krb5_address, contents, length, 1, octetstring); +const static struct atype_info *address_fields[] = { + &k5_atype_address_0, &k5_atype_address_1 }; -DEFSEQTYPE(address, krb5_address, address_fields, 0); +DEFSEQTYPE(address, krb5_address, address_fields, NULL); DEFPTRTYPE(address_ptr, address); -DEFNULLTERMSEQOFTYPE(seq_of_host_addresses, address_ptr); -DEFPTRTYPE(ptr_seqof_host_addresses, seq_of_host_addresses); +DEFNULLTERMSEQOFTYPE(seqof_host_addresses, address_ptr); +DEFPTRTYPE(ptr_seqof_host_addresses, seqof_host_addresses); +DEFFIELD(enc_data_0, krb5_enc_data, enctype, 0, int32); +DEFFIELD(enc_data_1, krb5_enc_data, kvno, 1, uint); +DEFFIELD(enc_data_2, krb5_enc_data, ciphertext, 2, ostring_data); +static const struct atype_info *encrypted_data_fields[] = { + &k5_atype_enc_data_0, &k5_atype_enc_data_1, &k5_atype_enc_data_2 +}; static unsigned int optional_encrypted_data (const void *vptr) { const krb5_enc_data *val = vptr; - unsigned int optional = 0; - - if (val->kvno != 0) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->kvno == 0) + not_present |= (1u << 1); + return not_present; } - -static const struct field_info encrypted_data_fields[] = { - FIELDOF_NORM(krb5_enc_data, int32, enctype, 0, 0), - FIELDOF_OPT(krb5_enc_data, uint, kvno, 1, 0, 1), - FIELDOF_NORM(krb5_enc_data, ostring_data, ciphertext, 2, 0), -}; DEFSEQTYPE(encrypted_data, krb5_enc_data, encrypted_data_fields, optional_encrypted_data); @@ -121,124 +118,121 @@ static asn1_error_code asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val, unsigned int *retlen) { - unsigned char cbuf[4]; + unsigned char cbuf[4], *cptr = cbuf; store_32_be((krb5_ui_4) *val, cbuf); - return asn1_encode_bitstring(buf, 4, cbuf, retlen); + return asn1_encode_bitstring(buf, &cptr, 4, retlen); } DEFPRIMITIVETYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at, ASN1_BITSTRING); -const static struct field_info authdata_elt_fields[] = { - /* ad-type[0] INTEGER */ - FIELDOF_NORM(krb5_authdata, int32, ad_type, 0, 0), - /* ad-data[1] OCTET STRING */ - FIELDOF_STRING(krb5_authdata, octetstring, contents, length, 1, 0), +DEFFIELD(authdata_0, krb5_authdata, ad_type, 0, int32); +DEFCNFIELD(authdata_1, krb5_authdata, contents, length, 1, octetstring); +static const struct atype_info *authdata_elt_fields[] = { + &k5_atype_authdata_0, &k5_atype_authdata_1 }; -DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields, 0); +DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields, NULL); DEFPTRTYPE(authdata_elt_ptr, authdata_elt); DEFNONEMPTYNULLTERMSEQOFTYPE(auth_data, authdata_elt_ptr); DEFPTRTYPE(auth_data_ptr, auth_data); -static const struct field_info encryption_key_fields[] = { - FIELDOF_NORM(krb5_keyblock, int32, enctype, 0, 0), - FIELDOF_STRING(krb5_keyblock, octetstring, contents, length, 1, 0), +DEFFIELD(keyblock_0, krb5_keyblock, enctype, 0, int32); +DEFCNFIELD(keyblock_1, krb5_keyblock, contents, length, 1, octetstring); +static const struct atype_info *encryption_key_fields[] = { + &k5_atype_keyblock_0, &k5_atype_keyblock_1 }; -DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields, 0); +DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields, NULL); DEFPTRTYPE(ptr_encryption_key, encryption_key); -static const struct field_info checksum_fields[] = { - FIELDOF_NORM(krb5_checksum, int32, checksum_type, 0, 0), - FIELDOF_STRING(krb5_checksum, octetstring, contents, length, 1, 0), +DEFFIELD(checksum_0, krb5_checksum, checksum_type, 0, int32); +DEFCNFIELD(checksum_1, krb5_checksum, contents, length, 1, octetstring); +static const struct atype_info *checksum_fields[] = { + &k5_atype_checksum_0, &k5_atype_checksum_1 }; -DEFSEQTYPE(checksum, krb5_checksum, checksum_fields, 0); +DEFSEQTYPE(checksum, krb5_checksum, checksum_fields, NULL); DEFPTRTYPE(checksum_ptr, checksum); -DEFNULLTERMSEQOFTYPE(seq_of_checksum, checksum_ptr); -DEFPTRTYPE(ptr_seqof_checksum, seq_of_checksum); +DEFNULLTERMSEQOFTYPE(seqof_checksum, checksum_ptr); +DEFPTRTYPE(ptr_seqof_checksum, seqof_checksum); -static const struct field_info lr_fields[] = { - FIELDOF_NORM(krb5_last_req_entry, int32, lr_type, 0, 0), - FIELDOF_NORM(krb5_last_req_entry, kerberos_time, value, 1, 0), +DEFFIELD(last_req_0, krb5_last_req_entry, lr_type, 0, int32); +DEFFIELD(last_req_1, krb5_last_req_entry, value, 1, kerberos_time); +static const struct atype_info *lr_fields[] = { + &k5_atype_last_req_0, &k5_atype_last_req_1 }; -DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields, 0); +DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields, NULL); DEFPTRTYPE(last_req_ent_ptr, last_req_ent); DEFNONEMPTYNULLTERMSEQOFTYPE(last_req, last_req_ent_ptr); DEFPTRTYPE(last_req_ptr, last_req); -static const struct field_info ticket_fields[] = { - FIELD_INT_IMM(KVNO, 0, 0), - FIELDOF_NORM(krb5_ticket, realm_of_principal, server, 1, 0), - FIELDOF_NORM(krb5_ticket, principal, server, 2, 0), - FIELDOF_NORM(krb5_ticket, encrypted_data, enc_part, 3, 0), +DEFCTAGGEDTYPE(ticket_0, 0, krb5_version); +DEFFIELD(ticket_1, krb5_ticket, server, 1, realm_of_principal); +DEFFIELD(ticket_2, krb5_ticket, server, 2, principal); +DEFFIELD(ticket_3, krb5_ticket, enc_part, 3, encrypted_data); +static const struct atype_info *ticket_fields[] = { + &k5_atype_ticket_0, &k5_atype_ticket_1, &k5_atype_ticket_2, + &k5_atype_ticket_3 }; -DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields, 0); +DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields, NULL); DEFAPPTAGGEDTYPE(ticket, 1, untagged_ticket); -static const struct field_info pa_data_fields[] = { - FIELDOF_NORM(krb5_pa_data, int32, pa_type, 1, 0), - FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 2, 0), +/* First context tag is 1, not 0. */ +DEFFIELD(pa_data_1, krb5_pa_data, pa_type, 1, int32); +DEFCNFIELD(pa_data_2, krb5_pa_data, contents, length, 2, octetstring); +static const struct atype_info *pa_data_fields[] = { + &k5_atype_pa_data_1, &k5_atype_pa_data_2 }; DEFSEQTYPE(pa_data, krb5_pa_data, pa_data_fields, 0); DEFPTRTYPE(pa_data_ptr, pa_data); -DEFNULLTERMSEQOFTYPE(seq_of_pa_data, pa_data_ptr); -DEFPTRTYPE(ptr_seqof_pa_data, seq_of_pa_data); +DEFNULLTERMSEQOFTYPE(seqof_pa_data, pa_data_ptr); +DEFPTRTYPE(ptr_seqof_pa_data, seqof_pa_data); DEFPTRTYPE(ticket_ptr, ticket); -DEFNONEMPTYNULLTERMSEQOFTYPE(seq_of_ticket,ticket_ptr); -DEFPTRTYPE(ptr_seqof_ticket, seq_of_ticket); - -/* EncKDCRepPart ::= SEQUENCE */ -static const struct field_info enc_kdc_rep_part_fields[] = { - /* key[0] EncryptionKey */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, ptr_encryption_key, session, 0, 0), - /* last-req[1] LastReq */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, last_req_ptr, last_req, 1, 0), - /* nonce[2] INTEGER */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, int32, nonce, 2, 0), - /* key-expiration[3] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, key_exp, 3, 0, 3), - /* flags[4] TicketFlags */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, krb5_flags, flags, 4, 0), - /* authtime[5] KerberosTime */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.authtime, 5, 0), - /* starttime[6] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.starttime, - 6, 0, 6), - /* endtime[7] KerberosTime */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.endtime, 7, 0), - /* renew-till[8] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.renew_till, - 8, 0, 8), - /* srealm[9] Realm */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, realm_of_principal, server, 9, 0), - /* sname[10] PrincipalName */ - FIELDOF_NORM(krb5_enc_kdc_rep_part, principal, server, 10, 0), - /* caddr[11] HostAddresses OPTIONAL */ - FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_host_addresses, caddrs, - 11, 0, 11), - /* encrypted-pa-data[12] SEQUENCE OF PA-DATA OPTIONAL */ - FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_pa_data, enc_padata, - 12, 0, 12), +DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_ticket,ticket_ptr); +DEFPTRTYPE(ptr_seqof_ticket, seqof_ticket); + +DEFFIELD(enc_kdc_rep_0, krb5_enc_kdc_rep_part, session, 0, ptr_encryption_key); +DEFFIELD(enc_kdc_rep_1, krb5_enc_kdc_rep_part, last_req, 1, last_req_ptr); +DEFFIELD(enc_kdc_rep_2, krb5_enc_kdc_rep_part, nonce, 2, int32); +DEFFIELD(enc_kdc_rep_3, krb5_enc_kdc_rep_part, key_exp, 3, kerberos_time); +DEFFIELD(enc_kdc_rep_4, krb5_enc_kdc_rep_part, flags, 4, krb5_flags); +DEFFIELD(enc_kdc_rep_5, krb5_enc_kdc_rep_part, times.authtime, 5, + kerberos_time); +DEFFIELD(enc_kdc_rep_6, krb5_enc_kdc_rep_part, times.starttime, 6, + kerberos_time); +DEFFIELD(enc_kdc_rep_7, krb5_enc_kdc_rep_part, times.endtime, 7, + kerberos_time); +DEFFIELD(enc_kdc_rep_8, krb5_enc_kdc_rep_part, times.renew_till, 8, + kerberos_time); +DEFFIELD(enc_kdc_rep_9, krb5_enc_kdc_rep_part, server, 9, realm_of_principal); +DEFFIELD(enc_kdc_rep_10, krb5_enc_kdc_rep_part, server, 10, principal); +DEFFIELD(enc_kdc_rep_11, krb5_enc_kdc_rep_part, caddrs, 11, + ptr_seqof_host_addresses); +DEFFIELD(enc_kdc_rep_12, krb5_enc_kdc_rep_part, enc_padata, 12, + ptr_seqof_pa_data); +static const struct atype_info *enc_kdc_rep_part_fields[] = { + &k5_atype_enc_kdc_rep_0, &k5_atype_enc_kdc_rep_1, &k5_atype_enc_kdc_rep_2, + &k5_atype_enc_kdc_rep_3, &k5_atype_enc_kdc_rep_4, &k5_atype_enc_kdc_rep_5, + &k5_atype_enc_kdc_rep_6, &k5_atype_enc_kdc_rep_7, &k5_atype_enc_kdc_rep_8, + &k5_atype_enc_kdc_rep_9, &k5_atype_enc_kdc_rep_10, + &k5_atype_enc_kdc_rep_11, &k5_atype_enc_kdc_rep_12 }; static unsigned int optional_enc_kdc_rep_part(const void *p) { const krb5_enc_kdc_rep_part *val = p; - unsigned int optional = 0; - - if (val->key_exp) - optional |= (1u << 3); - if (val->times.starttime) - optional |= (1u << 6); - if (val->flags & TKT_FLG_RENEWABLE) - optional |= (1u << 8); - if (val->caddrs != NULL && val->caddrs[0] != NULL) - optional |= (1u << 11); - if (val->enc_padata != NULL) - optional |= (1u << 12); - - return optional; + unsigned int not_present = 0; + if (val->key_exp == 0) + not_present |= (1u << 3); + if (val->times.starttime == 0) + not_present |= (1u << 6); + if (!(val->flags & TKT_FLG_RENEWABLE)) + not_present |= (1u << 8); + if (val->caddrs == NULL || val->caddrs[0] == NULL) + not_present |= (1u << 11); + if (val->enc_padata == NULL) + not_present |= (1u << 12); + return not_present; } DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields, optional_enc_kdc_rep_part); @@ -249,59 +243,57 @@ DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields, * the same time, might as well add the msg-type field and encode both * AS-REQ and TGS-REQ through the same descriptor. */ -struct kdc_req_hack { +typedef struct kdc_req_hack { krb5_kdc_req v; krb5_data *server_realm; -}; -static const struct field_info kdc_req_hack_fields[] = { - FIELDOF_NORM(struct kdc_req_hack, krb5_flags, v.kdc_options, 0, 0), - FIELDOF_OPT(struct kdc_req_hack, principal, v.client, 1, 0, 1), - FIELDOF_NORM(struct kdc_req_hack, gstring_data_ptr, server_realm, 2, 0), - FIELDOF_OPT(struct kdc_req_hack, principal, v.server, 3, 0, 3), - FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.from, 4, 0, 4), - FIELDOF_NORM(struct kdc_req_hack, kerberos_time, v.till, 5, 0), - FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.rtime, 6, 0, 6), - FIELDOF_NORM(struct kdc_req_hack, int32, v.nonce, 7, 0), - FIELDOF_SEQOF_INT32(struct kdc_req_hack, int32_ptr, v.ktype, v.nktypes, - 8, 0), - FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_host_addresses, v.addresses, - 9, 0, 9), - FIELDOF_OPT(struct kdc_req_hack, encrypted_data, v.authorization_data, - 10, 0, 10), - FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_ticket, v.second_ticket, - 11, 0, 11), +} kdc_req_hack; +DEFFIELD(kdc_req_0, kdc_req_hack, v.kdc_options, 0, krb5_flags); +DEFFIELD(kdc_req_1, kdc_req_hack, v.client, 1, principal); +DEFFIELD(kdc_req_2, kdc_req_hack, server_realm, 2, gstring_data_ptr); +DEFFIELD(kdc_req_3, kdc_req_hack, v.server, 3, principal); +DEFFIELD(kdc_req_4, kdc_req_hack, v.from, 4, kerberos_time); +DEFFIELD(kdc_req_5, kdc_req_hack, v.till, 5, kerberos_time); +DEFFIELD(kdc_req_6, kdc_req_hack, v.rtime, 6, kerberos_time); +DEFFIELD(kdc_req_7, kdc_req_hack, v.nonce, 7, int32); +DEFCNFIELD(kdc_req_8, kdc_req_hack, v.ktype, v.nktypes, 8, cseqof_int32); +DEFFIELD(kdc_req_9, kdc_req_hack, v.addresses, 9, ptr_seqof_host_addresses); +DEFFIELD(kdc_req_10, kdc_req_hack, v.authorization_data, 10, encrypted_data); +DEFFIELD(kdc_req_11, kdc_req_hack, v.second_ticket, 11, ptr_seqof_ticket); +static const struct atype_info *kdc_req_hack_fields[] = { + &k5_atype_kdc_req_0, &k5_atype_kdc_req_1, &k5_atype_kdc_req_2, + &k5_atype_kdc_req_3, &k5_atype_kdc_req_4, &k5_atype_kdc_req_5, + &k5_atype_kdc_req_6, &k5_atype_kdc_req_7, &k5_atype_kdc_req_8, + &k5_atype_kdc_req_9, &k5_atype_kdc_req_10, &k5_atype_kdc_req_11 }; static unsigned int optional_kdc_req_hack(const void *p) { - const struct kdc_req_hack *val2 = p; + const kdc_req_hack *val2 = p; const krb5_kdc_req *val = &val2->v; - unsigned int optional = 0; - - if (val->second_ticket != NULL && val->second_ticket[0] != NULL) - optional |= (1u << 11); - if (val->authorization_data.ciphertext.data != NULL) - optional |= (1u << 10); - if (val->addresses != NULL && val->addresses[0] != NULL) - optional |= (1u << 9); - if (val->rtime) - optional |= (1u << 6); - if (val->from) - optional |= (1u << 4); - if (val->server != NULL) - optional |= (1u << 3); - if (val->client != NULL) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->second_ticket == NULL || val->second_ticket[0] == NULL) + not_present |= (1u << 11); + if (val->authorization_data.ciphertext.data == NULL) + not_present |= (1u << 10); + if (val->addresses == NULL || val->addresses[0] == NULL) + not_present |= (1u << 9); + if (val->rtime == 0) + not_present |= (1u << 6); + if (val->from == 0) + not_present |= (1u << 4); + if (val->server == NULL) + not_present |= (1u << 3); + if (val->client == NULL) + not_present |= (1u << 1); + return not_present; } -DEFSEQTYPE(kdc_req_body_hack, struct kdc_req_hack, kdc_req_hack_fields, +DEFSEQTYPE(kdc_req_body_hack, kdc_req_hack, kdc_req_hack_fields, optional_kdc_req_hack); static asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const void *ptr, taginfo *rettag) { const krb5_kdc_req *val = ptr; - struct kdc_req_hack val2; + kdc_req_hack val2; val2.v = *val; if (val->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { if (val->second_ticket != NULL && val->second_ticket[0] != NULL) { @@ -310,139 +302,127 @@ asn1_encode_kdc_req_body(asn1buf *buf, const void *ptr, taginfo *rettag) } else if (val->server != NULL) { val2.server_realm = &val->server->realm; } else return ASN1_MISSING_FIELD; - return krb5int_asn1_encode_type(buf, &val2, - &krb5int_asn1type_kdc_req_body_hack, + return krb5int_asn1_encode_type(buf, &val2, &k5_atype_kdc_req_body_hack, rettag); } DEFFNTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); /* end ugly hack */ -DEFPTRTYPE(ptr_kdc_req_body,kdc_req_body); - -static const struct field_info transited_fields[] = { - FIELDOF_NORM(krb5_transited, octet, tr_type, 0, 0), - FIELDOF_NORM(krb5_transited, ostring_data, tr_contents, 1, 0), +DEFFIELD(transited_0, krb5_transited, tr_type, 0, octet); +DEFFIELD(transited_1, krb5_transited, tr_contents, 1, ostring_data); +static const struct atype_info *transited_fields[] = { + &k5_atype_transited_0, &k5_atype_transited_1 }; -DEFSEQTYPE(transited, krb5_transited, transited_fields, 0); +DEFSEQTYPE(transited, krb5_transited, transited_fields, NULL); -static const struct field_info krb_safe_body_fields[] = { - FIELDOF_NORM(krb5_safe, ostring_data, user_data, 0, 0), - FIELDOF_OPT(krb5_safe, kerberos_time, timestamp, 1, 0, 1), - FIELDOF_OPT(krb5_safe, int32, usec, 2, 0, 2), - FIELDOF_OPT(krb5_safe, uint, seq_number, 3, 0, 3), - FIELDOF_NORM(krb5_safe, address_ptr, s_address, 4, 0), - FIELDOF_OPT(krb5_safe, address_ptr, r_address, 5, 0, 5), +DEFFIELD(safe_body_0, krb5_safe, user_data, 0, ostring_data); +DEFFIELD(safe_body_1, krb5_safe, timestamp, 1, kerberos_time); +DEFFIELD(safe_body_2, krb5_safe, usec, 2, int32); +DEFFIELD(safe_body_3, krb5_safe, seq_number, 3, uint); +DEFFIELD(safe_body_4, krb5_safe, s_address, 4, address_ptr); +DEFFIELD(safe_body_5, krb5_safe, r_address, 5, address_ptr); +static const struct atype_info *krb_safe_body_fields[] = { + &k5_atype_safe_body_0, &k5_atype_safe_body_1, &k5_atype_safe_body_2, + &k5_atype_safe_body_3, &k5_atype_safe_body_4, &k5_atype_safe_body_5 }; static unsigned int optional_krb_safe_body(const void *p) { const krb5_safe *val = p; - unsigned int optional = 0; - - if (val->timestamp) { - optional |= (1u << 1); - optional |= (1u << 2); - } - if (val->seq_number) - optional |= (1u << 3); - if (val->r_address != NULL) - optional |= (1u << 5); - - return optional; + unsigned int not_present = 0; + if (val->timestamp == 0) + not_present |= (1u << 1) | (1u << 2); + if (val->seq_number == 0) + not_present |= (1u << 3); + if (val->r_address == NULL) + not_present |= (1u << 5); + return not_present; } DEFSEQTYPE(krb_safe_body, krb5_safe, krb_safe_body_fields, optional_krb_safe_body); -static const struct field_info krb_cred_info_fields[] = { - FIELDOF_NORM(krb5_cred_info, ptr_encryption_key, session, 0, 0), - FIELDOF_OPT(krb5_cred_info, realm_of_principal, client, 1, 0, 1), - FIELDOF_OPT(krb5_cred_info, principal, client, 2, 0, 2), - FIELDOF_OPT(krb5_cred_info, krb5_flags, flags, 3, 0, 3), - FIELDOF_OPT(krb5_cred_info, kerberos_time, times.authtime, 4, 0, 4), - FIELDOF_OPT(krb5_cred_info, kerberos_time, times.starttime, 5, 0, 5), - FIELDOF_OPT(krb5_cred_info, kerberos_time, times.endtime, 6, 0, 6), - FIELDOF_OPT(krb5_cred_info, kerberos_time, times.renew_till, 7, 0, 7), - FIELDOF_OPT(krb5_cred_info, realm_of_principal, server, 8, 0, 8), - FIELDOF_OPT(krb5_cred_info, principal, server, 9, 0, 9), - FIELDOF_OPT(krb5_cred_info, ptr_seqof_host_addresses, caddrs, 10, 0, 10), +DEFFIELD(cred_info_0, krb5_cred_info, session, 0, ptr_encryption_key); +DEFFIELD(cred_info_1, krb5_cred_info, client, 1, realm_of_principal); +DEFFIELD(cred_info_2, krb5_cred_info, client, 2, principal); +DEFFIELD(cred_info_3, krb5_cred_info, flags, 3, krb5_flags); +DEFFIELD(cred_info_4, krb5_cred_info, times.authtime, 4, kerberos_time); +DEFFIELD(cred_info_5, krb5_cred_info, times.starttime, 5, kerberos_time); +DEFFIELD(cred_info_6, krb5_cred_info, times.endtime, 6, kerberos_time); +DEFFIELD(cred_info_7, krb5_cred_info, times.renew_till, 7, kerberos_time); +DEFFIELD(cred_info_8, krb5_cred_info, server, 8, realm_of_principal); +DEFFIELD(cred_info_9, krb5_cred_info, server, 9, principal); +DEFFIELD(cred_info_10, krb5_cred_info, caddrs, 10, ptr_seqof_host_addresses); +static const struct atype_info *krb_cred_info_fields[] = { + &k5_atype_cred_info_0, &k5_atype_cred_info_1, &k5_atype_cred_info_2, + &k5_atype_cred_info_3, &k5_atype_cred_info_4, &k5_atype_cred_info_5, + &k5_atype_cred_info_6, &k5_atype_cred_info_7, &k5_atype_cred_info_8, + &k5_atype_cred_info_9, &k5_atype_cred_info_10 }; static unsigned int optional_krb_cred_info(const void *p) { const krb5_cred_info *val = p; - unsigned int optional = 0; - - if (val->caddrs != NULL && val->caddrs[0] != NULL) - optional |= (1u << 10); - if (val->server != NULL) { - optional |= (1u << 9); - optional |= (1u << 8); - } - if (val->times.renew_till) - optional |= (1u << 7); - if (val->times.endtime) - optional |= (1u << 6); - if (val->times.starttime) - optional |= (1u << 5); - if (val->times.authtime) - optional |= (1u << 4); - if (val->flags) - optional |= (1u << 3); - if (val->client != NULL) { - optional |= (1u << 2); - optional |= (1u << 1); - } - - return optional; + unsigned int not_present = 0; + if (val->caddrs == NULL || val->caddrs[0] == NULL) + not_present |= (1u << 10); + if (val->server == NULL) + not_present |= (1u << 9) | (1u << 8); + if (val->times.renew_till == 0) + not_present |= (1u << 7); + if (val->times.endtime == 0) + not_present |= (1u << 6); + if (val->times.starttime == 0) + not_present |= (1u << 5); + if (val->times.authtime == 0) + not_present |= (1u << 4); + if (val->flags == 0) + not_present |= (1u << 3); + if (val->client == NULL) + not_present |= (1u << 2) | (1u << 1); + return not_present; } DEFSEQTYPE(cred_info, krb5_cred_info, krb_cred_info_fields, optional_krb_cred_info); DEFPTRTYPE(cred_info_ptr, cred_info); -DEFNULLTERMSEQOFTYPE(seq_of_cred_info, cred_info_ptr); - -DEFPTRTYPE(ptrseqof_cred_info, seq_of_cred_info); - +DEFNULLTERMSEQOFTYPE(seqof_cred_info, cred_info_ptr); +DEFPTRTYPE(ptrseqof_cred_info, seqof_cred_info); +DEFFIELD(etype_info_0, krb5_etype_info_entry, etype, 0, int32); +DEFCNFIELD(etype_info_1, krb5_etype_info_entry, salt, length, 1, octetstring); +static const struct atype_info *etype_info_entry_fields[] = { + &k5_atype_etype_info_0, &k5_atype_etype_info_1 +}; static unsigned int optional_etype_info_entry(const void *vptr) { const krb5_etype_info_entry *val = vptr; - unsigned int optional = 0; - - if (val->length != KRB5_ETYPE_NO_SALT) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->length == KRB5_ETYPE_NO_SALT) + not_present |= (1u << 1); + return not_present; } -static const struct field_info etype_info_entry_fields[] = { - FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0, 0), - FIELDOF_OPTSTRING(krb5_etype_info_entry, octetstring, salt, length, - 1, 0, 1), -}; DEFSEQTYPE(etype_info_entry, krb5_etype_info_entry, etype_info_entry_fields, optional_etype_info_entry); +/* First field is the same as etype-info. */ +DEFCNFIELD(etype_info2_1, krb5_etype_info_entry, salt, length, 1, + u_generalstring); +DEFFIELD(etype_info2_2, krb5_etype_info_entry, s2kparams, 2, ostring_data); +static const struct atype_info *etype_info2_entry_fields[] = { + &k5_atype_etype_info_0, &k5_atype_etype_info2_1, &k5_atype_etype_info2_2 +}; static unsigned int optional_etype_info2_entry(const void *vptr) { const krb5_etype_info_entry *val = vptr; - unsigned int optional = 0; - - if (val->length != KRB5_ETYPE_NO_SALT) - optional |= (1u << 1); - if (val->s2kparams.data) - optional |= (1u << 2); - - return optional; + unsigned int not_present = 0; + if (val->length == KRB5_ETYPE_NO_SALT) + not_present |= (1u << 1); + if (val->s2kparams.data == NULL) + not_present |= (1u << 2); + return not_present; } - -static const struct field_info etype_info2_entry_fields[] = { - FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0, 0), - FIELDOF_OPTSTRING(krb5_etype_info_entry, u_generalstring, salt, length, - 1, 0, 1), - FIELDOF_OPT(krb5_etype_info_entry, ostring_data, s2kparams, 2, 0, 2), -}; DEFSEQTYPE(etype_info2_entry, krb5_etype_info_entry, etype_info2_entry_fields, optional_etype_info2_entry); @@ -452,174 +432,160 @@ DEFNULLTERMSEQOFTYPE(etype_info, etype_info_entry_ptr); DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry); DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr); -static const struct field_info sam_challenge_2_fields[] = { - FIELDOF_NORM(krb5_sam_challenge_2, der_data, sam_challenge_2_body, 0, 0), - FIELDOF_NORM(krb5_sam_challenge_2, ptr_seqof_checksum, sam_cksum, 1, 0), -}; -DEFSEQTYPE(sam_challenge_2, krb5_sam_challenge_2, sam_challenge_2_fields, 0); - -static const struct field_info sam_challenge_2_body_fields[] = { - FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0, 0), - FIELDOF_NORM(krb5_sam_challenge_2_body, krb5_flags, sam_flags, 1, 0), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_type_name, - 2, 0, 2), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_track_id, - 3, 0, 3), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge_label, - 4, 0, 4), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge, - 5, 0, 5), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_response_prompt, - 6, 0, 6), - FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_pk_for_sad, - 7, 0, 7), - FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_nonce, 8, 0), - FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_etype, 9, 0), +DEFFIELD(sch_0, krb5_sam_challenge_2, sam_challenge_2_body, 0, der_data); +DEFFIELD(sch_1, krb5_sam_challenge_2, sam_cksum, 1, ptr_seqof_checksum); +static const struct atype_info *sam_challenge_2_fields[] = { + &k5_atype_sch_0, &k5_atype_sch_1 +}; +DEFSEQTYPE(sam_challenge_2, krb5_sam_challenge_2, sam_challenge_2_fields, + NULL); + +DEFFIELD(schb_0, krb5_sam_challenge_2_body, sam_type, 0, int32); +DEFFIELD(schb_1, krb5_sam_challenge_2_body, sam_flags, 1, krb5_flags); +DEFFIELD(schb_2, krb5_sam_challenge_2_body, sam_type_name, 2, ostring_data); +DEFFIELD(schb_3, krb5_sam_challenge_2_body, sam_track_id, 3, ostring_data); +DEFFIELD(schb_4, krb5_sam_challenge_2_body, sam_challenge_label, 4, + ostring_data); +DEFFIELD(schb_5, krb5_sam_challenge_2_body, sam_challenge, 5, ostring_data); +DEFFIELD(schb_6, krb5_sam_challenge_2_body, sam_response_prompt, 6, + ostring_data); +DEFFIELD(schb_7, krb5_sam_challenge_2_body, sam_pk_for_sad, 7, ostring_data); +DEFFIELD(schb_8, krb5_sam_challenge_2_body, sam_nonce, 8, int32); +DEFFIELD(schb_9, krb5_sam_challenge_2_body, sam_etype, 9, int32); +static const struct atype_info *sam_challenge_2_body_fields[] = { + &k5_atype_schb_0, &k5_atype_schb_1, &k5_atype_schb_2, &k5_atype_schb_3, + &k5_atype_schb_4, &k5_atype_schb_5, &k5_atype_schb_6, &k5_atype_schb_7, + &k5_atype_schb_8, &k5_atype_schb_9 }; static unsigned int optional_sam_challenge_2_body(const void *p) { const krb5_sam_challenge_2_body *val = p; - unsigned int optional = 0; - - if (val->sam_pk_for_sad.length > 0) optional |= (1u << 7); - if (val->sam_response_prompt.length > 0) optional |= (1u << 6); - if (val->sam_challenge.length > 0) optional |= (1u << 5); - if (val->sam_challenge_label.length > 0) optional |= (1u << 4); - if (val->sam_track_id.length > 0) optional |= (1u << 3); - if (val->sam_type_name.length > 0) optional |= (1u << 2); - - return optional; + unsigned int not_present = 0; + if (val->sam_pk_for_sad.length == 0) + not_present |= (1u << 7); + if (val->sam_response_prompt.length == 0) + not_present |= (1u << 6); + if (val->sam_challenge.length == 0) + not_present |= (1u << 5); + if (val->sam_challenge_label.length == 0) + not_present |= (1u << 4); + if (val->sam_track_id.length == 0) + not_present |= (1u << 3); + if (val->sam_type_name.length == 0) + not_present |= (1u << 2); + return not_present; } -DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body,sam_challenge_2_body_fields, +DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body, + sam_challenge_2_body_fields, optional_sam_challenge_2_body); -static const struct field_info enc_sam_response_enc_2_fields[] = { - FIELDOF_NORM(krb5_enc_sam_response_enc_2, int32, sam_nonce, 0, 0), - FIELDOF_OPT(krb5_enc_sam_response_enc_2, ostring_data, sam_sad, 1, 0, 1), +DEFFIELD(esre_0, krb5_enc_sam_response_enc_2, sam_nonce, 0, int32); +DEFFIELD(esre_1, krb5_enc_sam_response_enc_2, sam_sad, 1, ostring_data); +static const struct atype_info *enc_sam_response_enc_2_fields[] = { + &k5_atype_esre_0, &k5_atype_esre_1 }; static unsigned int optional_enc_sam_response_enc_2(const void *p) { const krb5_enc_sam_response_enc_2 *val = p; - unsigned int optional = 0; - - if (val->sam_sad.length > 0) optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->sam_sad.length == 0) + not_present |= (1u << 1); + return not_present; } DEFSEQTYPE(enc_sam_response_enc_2, krb5_enc_sam_response_enc_2, enc_sam_response_enc_2_fields, optional_enc_sam_response_enc_2); -static const struct field_info sam_response_2_fields[] = { - FIELDOF_NORM(krb5_sam_response_2, int32, sam_type, 0, 0), - FIELDOF_NORM(krb5_sam_response_2, krb5_flags, sam_flags, 1, 0), - FIELDOF_OPT(krb5_sam_response_2, ostring_data, sam_track_id, 2, 0, 2), - FIELDOF_NORM(krb5_sam_response_2, encrypted_data, sam_enc_nonce_or_sad, - 3, 0), - FIELDOF_NORM(krb5_sam_response_2, int32, sam_nonce, 4, 0), +DEFFIELD(sam_resp_0, krb5_sam_response_2, sam_type, 0, int32); +DEFFIELD(sam_resp_1, krb5_sam_response_2, sam_flags, 1, krb5_flags); +DEFFIELD(sam_resp_2, krb5_sam_response_2, sam_track_id, 2, ostring_data); +DEFFIELD(sam_resp_3, krb5_sam_response_2, sam_enc_nonce_or_sad, 3, + encrypted_data); +DEFFIELD(sam_resp_4, krb5_sam_response_2, sam_nonce, 4, int32); +static const struct atype_info *sam_response_2_fields[] = { + &k5_atype_sam_resp_0, &k5_atype_sam_resp_1, &k5_atype_sam_resp_2, + &k5_atype_sam_resp_3, &k5_atype_sam_resp_4 }; static unsigned int optional_sam_response_2(const void *p) { const krb5_sam_response_2 *val = p; - unsigned int optional = 0; - - if (val->sam_track_id.length > 0) optional |= (1u << 2); - - return optional; + unsigned int not_present = 0; + if (val->sam_track_id.length == 0) + not_present |= (1u << 2); + return not_present; } DEFSEQTYPE(sam_response_2, krb5_sam_response_2, sam_response_2_fields, optional_sam_response_2); -static const struct field_info krb5_authenticator_fields[] = { - /* Authenticator ::= [APPLICATION 2] SEQUENCE */ - /* authenticator-vno[0] INTEGER */ - FIELD_INT_IMM(KVNO, 0, 0), - /* crealm[1] Realm */ - FIELDOF_NORM(krb5_authenticator, realm_of_principal, client, 1, 0), - /* cname[2] PrincipalName */ - FIELDOF_NORM(krb5_authenticator, principal, client, 2, 0), - /* cksum[3] Checksum OPTIONAL */ - FIELDOF_OPT(krb5_authenticator, checksum_ptr, checksum, 3, 0, 3), - /* cusec[4] INTEGER */ - FIELDOF_NORM(krb5_authenticator, int32, cusec, 4, 0), - /* ctime[5] KerberosTime */ - FIELDOF_NORM(krb5_authenticator, kerberos_time, ctime, 5, 0), - /* subkey[6] EncryptionKey OPTIONAL */ - FIELDOF_OPT(krb5_authenticator, ptr_encryption_key, subkey, 6, 0, 6), - /* seq-number[7] INTEGER OPTIONAL */ - FIELDOF_OPT(krb5_authenticator, uint, seq_number, 7, 0, 7), - /* authorization-data[8] AuthorizationData OPTIONAL */ - FIELDOF_OPT(krb5_authenticator, auth_data_ptr, authorization_data, - 8, 0, 8), +DEFCTAGGEDTYPE(authenticator_0, 0, krb5_version); +DEFFIELD(authenticator_1, krb5_authenticator, client, 1, realm_of_principal); +DEFFIELD(authenticator_2, krb5_authenticator, client, 2, principal); +DEFFIELD(authenticator_3, krb5_authenticator, checksum, 3, checksum_ptr); +DEFFIELD(authenticator_4, krb5_authenticator, cusec, 4, int32); +DEFFIELD(authenticator_5, krb5_authenticator, ctime, 5, kerberos_time); +DEFFIELD(authenticator_6, krb5_authenticator, subkey, 6, ptr_encryption_key); +DEFFIELD(authenticator_7, krb5_authenticator, seq_number, 7, uint); +DEFFIELD(authenticator_8, krb5_authenticator, authorization_data, 8, + auth_data_ptr); +static const struct atype_info *krb5_authenticator_fields[] = { + &k5_atype_authenticator_0, &k5_atype_authenticator_1, + &k5_atype_authenticator_2, &k5_atype_authenticator_3, + &k5_atype_authenticator_4, &k5_atype_authenticator_5, + &k5_atype_authenticator_6, &k5_atype_authenticator_7, + &k5_atype_authenticator_8 }; static unsigned int optional_krb5_authenticator(const void *p) { const krb5_authenticator *val = p; - unsigned int optional = 0; - - if (val->authorization_data != NULL && val->authorization_data[0] != NULL) - optional |= (1u << 8); - - if (val->seq_number != 0) - optional |= (1u << 7); - - if (val->subkey != NULL) - optional |= (1u << 6); - - if (val->checksum != NULL) - optional |= (1u << 3); - - return optional; + unsigned int not_present = 0; + if (val->authorization_data == NULL || val->authorization_data[0] == NULL) + not_present |= (1u << 8); + if (val->seq_number == 0) + not_present |= (1u << 7); + if (val->subkey == NULL) + not_present |= (1u << 6); + if (val->checksum == NULL) + not_present |= (1u << 3); + return not_present; } -DEFSEQTYPE(untagged_krb5_authenticator, krb5_authenticator, krb5_authenticator_fields, - optional_krb5_authenticator); +DEFSEQTYPE(untagged_krb5_authenticator, krb5_authenticator, + krb5_authenticator_fields, optional_krb5_authenticator); DEFAPPTAGGEDTYPE(krb5_authenticator, 2, untagged_krb5_authenticator); -static const struct field_info enc_tkt_part_fields[] = { - /* EncTicketPart ::= [APPLICATION 3] SEQUENCE */ - /* flags[0] TicketFlags */ - FIELDOF_NORM(krb5_enc_tkt_part, krb5_flags, flags, 0, 0), - /* key[1] EncryptionKey */ - FIELDOF_NORM(krb5_enc_tkt_part, ptr_encryption_key, session, 1, 0), - /* crealm[2] Realm */ - FIELDOF_NORM(krb5_enc_tkt_part, realm_of_principal, client, 2, 0), - /* cname[3] PrincipalName */ - FIELDOF_NORM(krb5_enc_tkt_part, principal, client, 3, 0), - /* transited[4] TransitedEncoding */ - FIELDOF_NORM(krb5_enc_tkt_part, transited, transited, 4, 0), - /* authtime[5] KerberosTime */ - FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.authtime, 5, 0), - /* starttime[6] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.starttime, 6, 0, 6), - /* endtime[7] KerberosTime */ - FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.endtime, 7, 0), - /* renew-till[8] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.renew_till, 8, 0, 8), - /* caddr[9] HostAddresses OPTIONAL */ - FIELDOF_OPT(krb5_enc_tkt_part, ptr_seqof_host_addresses, caddrs, 9, 0, 9), - /* authorization-data[10] AuthorizationData OPTIONAL */ - FIELDOF_OPT(krb5_enc_tkt_part, auth_data_ptr, authorization_data, - 10, 0, 10), +DEFFIELD(enc_tkt_0, krb5_enc_tkt_part, flags, 0, krb5_flags); +DEFFIELD(enc_tkt_1, krb5_enc_tkt_part, session, 1, ptr_encryption_key); +DEFFIELD(enc_tkt_2, krb5_enc_tkt_part, client, 2, realm_of_principal); +DEFFIELD(enc_tkt_3, krb5_enc_tkt_part, client, 3, principal); +DEFFIELD(enc_tkt_4, krb5_enc_tkt_part, transited, 4, transited); +DEFFIELD(enc_tkt_5, krb5_enc_tkt_part, times.authtime, 5, kerberos_time); +DEFFIELD(enc_tkt_6, krb5_enc_tkt_part, times.starttime, 6, kerberos_time); +DEFFIELD(enc_tkt_7, krb5_enc_tkt_part, times.endtime, 7, kerberos_time); +DEFFIELD(enc_tkt_8, krb5_enc_tkt_part, times.renew_till, 8, kerberos_time); +DEFFIELD(enc_tkt_9, krb5_enc_tkt_part, caddrs, 9, ptr_seqof_host_addresses); +DEFFIELD(enc_tkt_10, krb5_enc_tkt_part, authorization_data, 10, auth_data_ptr); +static const struct atype_info *enc_tkt_part_fields[] = { + &k5_atype_enc_tkt_0, &k5_atype_enc_tkt_1, &k5_atype_enc_tkt_2, + &k5_atype_enc_tkt_3, &k5_atype_enc_tkt_4, &k5_atype_enc_tkt_5, + &k5_atype_enc_tkt_6, &k5_atype_enc_tkt_7, &k5_atype_enc_tkt_8, + &k5_atype_enc_tkt_9, &k5_atype_enc_tkt_10 }; static unsigned int optional_enc_tkt_part(const void *p) { const krb5_enc_tkt_part *val = p; - unsigned int optional = 0; - - if (val->authorization_data != NULL && val->authorization_data[0] != NULL) - optional |= (1u << 10); - if (val->caddrs != NULL && val->caddrs[0] != NULL) - optional |= (1u << 9); - if (val->times.renew_till) - optional |= (1u << 8); - if (val->times.starttime) - optional |= (1u << 6); - - return optional; + unsigned int not_present = 0; + if (val->authorization_data == NULL || val->authorization_data[0] == NULL) + not_present |= (1u << 10); + if (val->caddrs == NULL || val->caddrs[0] == NULL) + not_present |= (1u << 9); + if (val->times.renew_till == 0) + not_present |= (1u << 8); + if (val->times.starttime == 0) + not_present |= (1u << 6); + return not_present; } DEFSEQTYPE(untagged_enc_tkt_part, krb5_enc_tkt_part, enc_tkt_part_fields, optional_enc_tkt_part); @@ -627,427 +593,371 @@ DEFAPPTAGGEDTYPE(enc_tkt_part, 3, untagged_enc_tkt_part); DEFAPPTAGGEDTYPE(enc_tgs_rep_part, 26, enc_kdc_rep_part); -static const struct field_info as_rep_fields[] = { - /* AS-REP ::= [APPLICATION 11] KDC-REP */ - /* But KDC-REP needs to know what type it's being encapsulated - in, so expand each version. */ - FIELD_INT_IMM(KVNO, 0, 0), - FIELD_INT_IMM(KRB5_AS_REP, 1, 0), - FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 0, 2), - FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3, 0), - FIELDOF_NORM(krb5_kdc_rep, principal, client, 4, 0), - FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5, 0), - FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6, 0), +DEFINT_IMMEDIATE(as_rep_msg_type, KRB5_AS_REP); +DEFCTAGGEDTYPE(kdc_rep_0, 0, krb5_version); +DEFCTAGGEDTYPE(as_rep_1, 1, as_rep_msg_type); +DEFFIELD(kdc_rep_2, krb5_kdc_rep, padata, 2, ptr_seqof_pa_data); +DEFFIELD(kdc_rep_3, krb5_kdc_rep, client, 3, realm_of_principal); +DEFFIELD(kdc_rep_4, krb5_kdc_rep, client, 4, principal); +DEFFIELD(kdc_rep_5, krb5_kdc_rep, ticket, 5, ticket_ptr); +DEFFIELD(kdc_rep_6, krb5_kdc_rep, enc_part, 6, encrypted_data); +static const struct atype_info *as_rep_fields[] = { + &k5_atype_kdc_rep_0, &k5_atype_as_rep_1, &k5_atype_kdc_rep_2, + &k5_atype_kdc_rep_3, &k5_atype_kdc_rep_4, &k5_atype_kdc_rep_5, + &k5_atype_kdc_rep_6 }; static unsigned int -optional_as_rep(const void *p) +optional_kdc_rep(const void *p) { const krb5_kdc_rep *val = p; - unsigned int optional = 0; - - if (val->padata != NULL && val->padata[0] != NULL) - optional |= (1u << 2); - - return optional; + unsigned int not_present = 0; + if (val->padata == NULL || val->padata[0] == NULL) + not_present |= (1u << 2); + return not_present; } -DEFSEQTYPE(untagged_as_rep, krb5_kdc_rep, as_rep_fields, optional_as_rep); +DEFSEQTYPE(untagged_as_rep, krb5_kdc_rep, as_rep_fields, optional_kdc_rep); DEFAPPTAGGEDTYPE(as_rep, 11, untagged_as_rep); -static const struct field_info tgs_rep_fields[] = { - /* TGS-REP ::= [APPLICATION 13] KDC-REP */ - /* But KDC-REP needs to know what type it's being encapsulated - in, so expand each version. */ - FIELD_INT_IMM(KVNO, 0, 0), - FIELD_INT_IMM(KRB5_TGS_REP, 1, 0), - FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 0, 2), - FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3, 0), - FIELDOF_NORM(krb5_kdc_rep, principal, client, 4, 0), - FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5, 0), - FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6, 0), -}; -static unsigned int -optional_tgs_rep(const void *p) -{ - const krb5_kdc_rep *val = p; - unsigned int optional = 0; - - if (val->padata != NULL && val->padata[0] != NULL) - optional |= (1u << 2); - - return optional; -} -DEFSEQTYPE(untagged_tgs_rep, krb5_kdc_rep, tgs_rep_fields, optional_tgs_rep); +/* TGS-REP ::= [APPLICATION 13] KDC-REP */ +/* But KDC-REP needs to know what type it's being encapsulated in, so use a + * separate atype. Most fields are the same. */ +DEFINT_IMMEDIATE(tgs_rep_msg_type, KRB5_TGS_REP); +DEFCTAGGEDTYPE(tgs_rep_1, 1, tgs_rep_msg_type); +static const struct atype_info *tgs_rep_fields[] = { + &k5_atype_kdc_rep_0, &k5_atype_tgs_rep_1, &k5_atype_kdc_rep_2, + &k5_atype_kdc_rep_3, &k5_atype_kdc_rep_4, &k5_atype_kdc_rep_5, + &k5_atype_kdc_rep_6 +}; +DEFSEQTYPE(untagged_tgs_rep, krb5_kdc_rep, tgs_rep_fields, optional_kdc_rep); DEFAPPTAGGEDTYPE(tgs_rep, 13, untagged_tgs_rep); -static const struct field_info ap_req_fields[] = { - /* AP-REQ ::= [APPLICATION 14] SEQUENCE */ - /* pvno[0] INTEGER */ - FIELD_INT_IMM(KVNO, 0, 0), - /* msg-type[1] INTEGER */ - FIELD_INT_IMM(ASN1_KRB_AP_REQ, 1, 0), - /* ap-options[2] APOptions */ - FIELDOF_NORM(krb5_ap_req, krb5_flags, ap_options, 2, 0), - /* ticket[3] Ticket */ - FIELDOF_NORM(krb5_ap_req, ticket_ptr, ticket, 3, 0), - /* authenticator[4] EncryptedData */ - FIELDOF_NORM(krb5_ap_req, encrypted_data, authenticator, 4, 0), -}; -DEFSEQTYPE(untagged_ap_req, krb5_ap_req, ap_req_fields, 0); +DEFINT_IMMEDIATE(ap_req_msg_type, ASN1_KRB_AP_REQ); +DEFCTAGGEDTYPE(ap_req_0, 0, krb5_version); +DEFCTAGGEDTYPE(ap_req_1, 1, ap_req_msg_type); +DEFFIELD(ap_req_2, krb5_ap_req, ap_options, 2, krb5_flags); +DEFFIELD(ap_req_3, krb5_ap_req, ticket, 3, ticket_ptr); +DEFFIELD(ap_req_4, krb5_ap_req, authenticator, 4, encrypted_data); +static const struct atype_info *ap_req_fields[] = { + &k5_atype_ap_req_0, &k5_atype_ap_req_1, &k5_atype_ap_req_2, + &k5_atype_ap_req_3, &k5_atype_ap_req_4 +}; +DEFSEQTYPE(untagged_ap_req, krb5_ap_req, ap_req_fields, NULL); DEFAPPTAGGEDTYPE(ap_req, 14, untagged_ap_req); -static const struct field_info ap_rep_fields[] = { - /* AP-REP ::= [APPLICATION 15] SEQUENCE */ - /* pvno[0] INTEGER */ - FIELD_INT_IMM(KVNO, 0, 0), - /* msg-type[1] INTEGER */ - FIELD_INT_IMM(ASN1_KRB_AP_REP, 1, 0), - /* enc-part[2] EncryptedData */ - FIELDOF_NORM(krb5_ap_rep, encrypted_data, enc_part, 2, 0), +DEFINT_IMMEDIATE(ap_rep_msg_type, ASN1_KRB_AP_REP); +DEFCTAGGEDTYPE(ap_rep_0, 0, krb5_version); +DEFCTAGGEDTYPE(ap_rep_1, 1, ap_rep_msg_type); +DEFFIELD(ap_rep_2, krb5_ap_rep, enc_part, 2, encrypted_data); +static const struct atype_info *ap_rep_fields[] = { + &k5_atype_ap_rep_0, &k5_atype_ap_rep_1, &k5_atype_ap_rep_2 }; -DEFSEQTYPE(untagged_ap_rep, krb5_ap_rep, ap_rep_fields, 0); +DEFSEQTYPE(untagged_ap_rep, krb5_ap_rep, ap_rep_fields, NULL); DEFAPPTAGGEDTYPE(ap_rep, 15, untagged_ap_rep); -static const struct field_info ap_rep_enc_part_fields[] = { - /* EncAPRepPart ::= [APPLICATION 27] SEQUENCE */ - /* ctime[0] KerberosTime */ - FIELDOF_NORM(krb5_ap_rep_enc_part, kerberos_time, ctime, 0, 0), - /* cusec[1] INTEGER */ - FIELDOF_NORM(krb5_ap_rep_enc_part, int32, cusec, 1, 0), - /* subkey[2] EncryptionKey OPTIONAL */ - FIELDOF_OPT(krb5_ap_rep_enc_part, ptr_encryption_key, subkey, 2, 0, 2), - /* seq-number[3] INTEGER OPTIONAL */ - FIELDOF_OPT(krb5_ap_rep_enc_part, uint, seq_number, 3, 0, 3), +DEFFIELD(ap_rep_enc_part_0, krb5_ap_rep_enc_part, ctime, 0, kerberos_time); +DEFFIELD(ap_rep_enc_part_1, krb5_ap_rep_enc_part, cusec, 1, int32); +DEFFIELD(ap_rep_enc_part_2, krb5_ap_rep_enc_part, subkey, 2, + ptr_encryption_key); +DEFFIELD(ap_rep_enc_part_3, krb5_ap_rep_enc_part, seq_number, 3, uint); +static const struct atype_info *ap_rep_enc_part_fields[] = { + &k5_atype_ap_rep_enc_part_0, &k5_atype_ap_rep_enc_part_1, + &k5_atype_ap_rep_enc_part_2, &k5_atype_ap_rep_enc_part_3 }; static unsigned int optional_ap_rep_enc_part(const void *p) { const krb5_ap_rep_enc_part *val = p; - unsigned int optional = 0; - - if (val->seq_number) - optional |= (1u << 3); - if (val->subkey != NULL) - optional |= (1u << 2); - - return optional; + unsigned int not_present = 0; + if (val->seq_number == 0) + not_present |= (1u << 3); + if (val->subkey == NULL) + not_present |= (1u << 2); + return not_present; } DEFSEQTYPE(untagged_ap_rep_enc_part, krb5_ap_rep_enc_part, ap_rep_enc_part_fields, optional_ap_rep_enc_part); DEFAPPTAGGEDTYPE(ap_rep_enc_part, 27, untagged_ap_rep_enc_part); -static const struct field_info as_req_fields[] = { - /* AS-REQ ::= [APPLICATION 10] KDC-REQ */ - FIELD_INT_IMM(KVNO, 1, 0), - FIELD_INT_IMM(KRB5_AS_REQ, 2, 0), - FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 0, 3), - FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4, 0), +/* First context tag is 1. Fourth field is the encoding of the krb5_kdc_req + * structure as a KDC-REQ-BODY. */ +DEFINT_IMMEDIATE(as_req_msg_type, KRB5_AS_REQ); +DEFCTAGGEDTYPE(as_req_1, 1, krb5_version); +DEFCTAGGEDTYPE(as_req_2, 2, as_req_msg_type); +DEFFIELD(as_req_3, krb5_kdc_req, padata, 3, ptr_seqof_pa_data); +DEFCTAGGEDTYPE(as_req_4, 4, kdc_req_body); +static const struct atype_info *as_req_fields[] = { + &k5_atype_as_req_1, &k5_atype_as_req_2, &k5_atype_as_req_3, + &k5_atype_as_req_4 }; static unsigned int optional_as_req(const void *p) { const krb5_kdc_req *val = p; - unsigned int optional = 0; - - if (val->padata != NULL && val->padata[0] != NULL) - optional |= (1u << 3); - - return optional; + unsigned int not_present = 0; + if (val->padata == NULL || val->padata[0] == NULL) + not_present |= (1u << 2); + return not_present; } DEFSEQTYPE(untagged_as_req, krb5_kdc_req, as_req_fields, optional_as_req); DEFAPPTAGGEDTYPE(as_req, 10, untagged_as_req); -static const struct field_info tgs_req_fields[] = { - /* TGS-REQ ::= [APPLICATION 12] KDC-REQ */ - FIELD_INT_IMM(KVNO, 1, 0), - FIELD_INT_IMM(KRB5_TGS_REQ, 2, 0), - FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 0, 3), - FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4, 0), +/* Most fields are the same as as_req. */ +DEFINT_IMMEDIATE(tgs_req_msg_type, KRB5_TGS_REQ); +DEFCTAGGEDTYPE(tgs_req_2, 2, tgs_req_msg_type); +static const struct atype_info *tgs_req_fields[] = { + &k5_atype_as_req_1, &k5_atype_tgs_req_2, &k5_atype_as_req_3, + &k5_atype_as_req_4 }; -static unsigned int -optional_tgs_req(const void *p) -{ - const krb5_kdc_req *val = p; - unsigned int optional = 0; - - if (val->padata != NULL && val->padata[0] != NULL) - optional |= (1u << 3); - - return optional; -} DEFSEQTYPE(untagged_tgs_req, krb5_kdc_req, tgs_req_fields, - optional_tgs_req); + optional_as_req); DEFAPPTAGGEDTYPE(tgs_req, 12, untagged_tgs_req); -static const struct field_info krb5_safe_fields[] = { - FIELD_INT_IMM(KVNO, 0, 0), - FIELD_INT_IMM(ASN1_KRB_SAFE, 1, 0), - FIELD_SELF(krb_safe_body, 2, 0), - FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, 3, 0), +DEFINT_IMMEDIATE(safe_msg_type, ASN1_KRB_SAFE); +DEFCTAGGEDTYPE(safe_0, 0, krb5_version); +DEFCTAGGEDTYPE(safe_1, 1, safe_msg_type); +DEFCTAGGEDTYPE(safe_2, 2, krb_safe_body); +DEFFIELD(safe_3, krb5_safe, checksum, 3, checksum_ptr); +static const struct atype_info *krb5_safe_fields[] = { + &k5_atype_safe_0, &k5_atype_safe_1, &k5_atype_safe_2, &k5_atype_safe_3 }; -DEFSEQTYPE(untagged_krb5_safe, krb5_safe, krb5_safe_fields, 0); +DEFSEQTYPE(untagged_krb5_safe, krb5_safe, krb5_safe_fields, NULL); DEFAPPTAGGEDTYPE(krb5_safe, 20, untagged_krb5_safe); +/* Hack to encode a KRB-SAFE with a pre-specified body encoding. The integer- + * immediate fields are borrowed from krb5_safe_fields above. */ DEFPTRTYPE(krb_saved_safe_body_ptr, der_data); -DEFFIELDTYPE(krb5_safe_checksum_only, krb5_safe, - FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, -1, 0)); +DEFOFFSETTYPE(krb5_safe_checksum_only, krb5_safe, checksum, checksum_ptr); DEFPTRTYPE(krb5_safe_checksum_only_ptr, krb5_safe_checksum_only); -static const struct field_info krb5_safe_with_body_fields[] = { - FIELD_INT_IMM(KVNO, 0, 0), - FIELD_INT_IMM(ASN1_KRB_SAFE, 1, 0), - FIELDOF_NORM(struct krb5_safe_with_body, krb_saved_safe_body_ptr, body, - 2, 0), - FIELDOF_NORM(struct krb5_safe_with_body, krb5_safe_checksum_only_ptr, - safe, 3, 0), +DEFFIELD(safe_with_body_2, struct krb5_safe_with_body, body, 2, + krb_saved_safe_body_ptr); +DEFFIELD(safe_with_body_3, struct krb5_safe_with_body, safe, 3, + krb5_safe_checksum_only_ptr); +static const struct atype_info *krb5_safe_with_body_fields[] = { + &k5_atype_safe_0, &k5_atype_safe_1, &k5_atype_safe_with_body_2, + &k5_atype_safe_with_body_3 }; DEFSEQTYPE(untagged_krb5_safe_with_body, struct krb5_safe_with_body, - krb5_safe_with_body_fields, 0); + krb5_safe_with_body_fields, NULL); DEFAPPTAGGEDTYPE(krb5_safe_with_body, 20, untagged_krb5_safe_with_body); -static const struct field_info priv_fields[] = { - FIELD_INT_IMM(KVNO, 0, 0), - FIELD_INT_IMM(ASN1_KRB_PRIV, 1, 0), - FIELDOF_NORM(krb5_priv, encrypted_data, enc_part, 3, 0), +/* Third tag is [3] instead of [2]. */ +DEFINT_IMMEDIATE(priv_msg_type, ASN1_KRB_PRIV); +DEFCTAGGEDTYPE(priv_0, 0, krb5_version); +DEFCTAGGEDTYPE(priv_1, 1, priv_msg_type); +DEFFIELD(priv_3, krb5_priv, enc_part, 3, encrypted_data); +static const struct atype_info *priv_fields[] = { + &k5_atype_priv_0, &k5_atype_priv_1, &k5_atype_priv_3 }; -DEFSEQTYPE(untagged_priv, krb5_priv, priv_fields, 0); +DEFSEQTYPE(untagged_priv, krb5_priv, priv_fields, NULL); DEFAPPTAGGEDTYPE(krb5_priv, 21, untagged_priv); -static const struct field_info priv_enc_part_fields[] = { - FIELDOF_NORM(krb5_priv_enc_part, ostring_data, user_data, 0, 0), - FIELDOF_OPT(krb5_priv_enc_part, kerberos_time, timestamp, 1, 0, 1), - FIELDOF_OPT(krb5_priv_enc_part, int32, usec, 2, 0, 2), - FIELDOF_OPT(krb5_priv_enc_part, uint, seq_number, 3, 0, 3), - FIELDOF_NORM(krb5_priv_enc_part, address_ptr, s_address, 4, 0), - FIELDOF_OPT(krb5_priv_enc_part, address_ptr, r_address, 5, 0, 5), +DEFFIELD(priv_enc_part_0, krb5_priv_enc_part, user_data, 0, ostring_data); +DEFFIELD(priv_enc_part_1, krb5_priv_enc_part, timestamp, 1, kerberos_time); +DEFFIELD(priv_enc_part_2, krb5_priv_enc_part, usec, 2, int32); +DEFFIELD(priv_enc_part_3, krb5_priv_enc_part, seq_number, 3, uint); +DEFFIELD(priv_enc_part_4, krb5_priv_enc_part, s_address, 4, address_ptr); +DEFFIELD(priv_enc_part_5, krb5_priv_enc_part, r_address, 5, address_ptr); +static const struct atype_info *priv_enc_part_fields[] = { + &k5_atype_priv_enc_part_0, &k5_atype_priv_enc_part_1, + &k5_atype_priv_enc_part_2, &k5_atype_priv_enc_part_3, + &k5_atype_priv_enc_part_4, &k5_atype_priv_enc_part_5 }; static unsigned int optional_priv_enc_part(const void *p) { const krb5_priv_enc_part *val = p; - unsigned int optional = 0; - - if (val->timestamp) { - optional |= (1u << 2); - optional |= (1u << 1); - } - if (val->seq_number) - optional |= (1u << 3); - if (val->r_address) - optional |= (1u << 5); - - return optional; + unsigned int not_present = 0; + if (val->timestamp == 0) + not_present |= (1u << 2) | (1u << 1); + if (val->seq_number == 0) + not_present |= (1u << 3); + if (val->r_address == NULL) + not_present |= (1u << 5); + return not_present; } DEFSEQTYPE(untagged_priv_enc_part, krb5_priv_enc_part, priv_enc_part_fields, optional_priv_enc_part); DEFAPPTAGGEDTYPE(priv_enc_part, 28, untagged_priv_enc_part); -static const struct field_info cred_fields[] = { - /* KRB-CRED ::= [APPLICATION 22] SEQUENCE */ - /* pvno[0] INTEGER */ - FIELD_INT_IMM(KVNO, 0, 0), - /* msg-type[1] INTEGER, -- KRB_CRED */ - FIELD_INT_IMM(ASN1_KRB_CRED, 1, 0), - /* tickets[2] SEQUENCE OF Ticket */ - FIELDOF_NORM(krb5_cred, ptr_seqof_ticket, tickets, 2, 0), - /* enc-part[3] EncryptedData */ - FIELDOF_NORM(krb5_cred, encrypted_data, enc_part, 3, 0), -}; -DEFSEQTYPE(untagged_cred, krb5_cred, cred_fields, 0); +DEFINT_IMMEDIATE(cred_msg_type, ASN1_KRB_CRED); +DEFCTAGGEDTYPE(cred_0, 0, krb5_version); +DEFCTAGGEDTYPE(cred_1, 1, cred_msg_type); +DEFFIELD(cred_2, krb5_cred, tickets, 2, ptr_seqof_ticket); +DEFFIELD(cred_3, krb5_cred, enc_part, 3, encrypted_data); +static const struct atype_info *cred_fields[] = { + &k5_atype_cred_0, &k5_atype_cred_1, &k5_atype_cred_2, &k5_atype_cred_3 +}; +DEFSEQTYPE(untagged_cred, krb5_cred, cred_fields, NULL); DEFAPPTAGGEDTYPE(krb5_cred, 22, untagged_cred); -static const struct field_info enc_cred_part_fields[] = { - /* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE */ - /* ticket-info[0] SEQUENCE OF KrbCredInfo */ - FIELDOF_NORM(krb5_cred_enc_part, ptrseqof_cred_info, ticket_info, 0, 0), - /* nonce[1] INTEGER OPTIONAL */ - FIELDOF_OPT(krb5_cred_enc_part, int32, nonce, 1, 0, 1), - /* timestamp[2] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_cred_enc_part, kerberos_time, timestamp, 2, 0, 2), - /* usec[3] INTEGER OPTIONAL */ - FIELDOF_OPT(krb5_cred_enc_part, int32, usec, 3, 0, 3), - /* s-address[4] HostAddress OPTIONAL */ - FIELDOF_OPT(krb5_cred_enc_part, address_ptr, s_address, 4, 0, 4), - /* r-address[5] HostAddress OPTIONAL */ - FIELDOF_OPT(krb5_cred_enc_part, address_ptr, r_address, 5, 0, 5), +DEFFIELD(enc_cred_part_0, krb5_cred_enc_part, ticket_info, 0, + ptrseqof_cred_info); +DEFFIELD(enc_cred_part_1, krb5_cred_enc_part, nonce, 1, int32); +DEFFIELD(enc_cred_part_2, krb5_cred_enc_part, timestamp, 2, kerberos_time); +DEFFIELD(enc_cred_part_3, krb5_cred_enc_part, usec, 3, int32); +DEFFIELD(enc_cred_part_4, krb5_cred_enc_part, s_address, 4, address_ptr); +DEFFIELD(enc_cred_part_5, krb5_cred_enc_part, r_address, 5, address_ptr); +static const struct atype_info *enc_cred_part_fields[] = { + &k5_atype_enc_cred_part_0, &k5_atype_enc_cred_part_1, + &k5_atype_enc_cred_part_2, &k5_atype_enc_cred_part_3, + &k5_atype_enc_cred_part_4, &k5_atype_enc_cred_part_5 }; static unsigned int optional_enc_cred_part(const void *p) { const krb5_cred_enc_part *val = p; - unsigned int optional = 0; - - if (val->r_address != NULL) - optional |= (1u << 5); - - if (val->s_address != NULL) - optional |= (1u << 4); - - if (val->timestamp) { - optional |= (1u << 2); - optional |= (1u << 3); - } - - if (val->nonce) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->r_address == NULL) + not_present |= (1u << 5); + if (val->s_address == NULL) + not_present |= (1u << 4); + if (val->timestamp == 0) + not_present |= (1u << 2) | (1u << 3); + if (val->nonce == 0) + not_present |= (1u << 1); + return not_present; } DEFSEQTYPE(untagged_enc_cred_part, krb5_cred_enc_part, enc_cred_part_fields, optional_enc_cred_part); DEFAPPTAGGEDTYPE(enc_cred_part, 29, untagged_enc_cred_part); -static const struct field_info error_fields[] = { - /* KRB-ERROR ::= [APPLICATION 30] SEQUENCE */ - /* pvno[0] INTEGER */ - FIELD_INT_IMM(KVNO, 0, 0), - /* msg-type[1] INTEGER */ - FIELD_INT_IMM(ASN1_KRB_ERROR, 1, 0), - /* ctime[2] KerberosTime OPTIONAL */ - FIELDOF_OPT(krb5_error, kerberos_time, ctime, 2, 0, 2), - /* cusec[3] INTEGER OPTIONAL */ - FIELDOF_OPT(krb5_error, int32, cusec, 3, 0, 3), - /* stime[4] KerberosTime */ - FIELDOF_NORM(krb5_error, kerberos_time, stime, 4, 0), - /* susec[5] INTEGER */ - FIELDOF_NORM(krb5_error, int32, susec, 5, 0), - /* error-code[6] INTEGER */ - FIELDOF_NORM(krb5_error, ui_4, error, 6, 0), - /* crealm[7] Realm OPTIONAL */ - FIELDOF_OPT(krb5_error, realm_of_principal, client, 7, 0, 7), - /* cname[8] PrincipalName OPTIONAL */ - FIELDOF_OPT(krb5_error, principal, client, 8, 0, 8), - /* realm[9] Realm -- Correct realm */ - FIELDOF_NORM(krb5_error, realm_of_principal, server, 9, 0), - /* sname[10] PrincipalName -- Correct name */ - FIELDOF_NORM(krb5_error, principal, server, 10, 0), - /* e-text[11] GeneralString OPTIONAL */ - FIELDOF_OPT(krb5_error, gstring_data, text, 11, 0, 11), - /* e-data[12] OCTET STRING OPTIONAL */ - FIELDOF_OPT(krb5_error, ostring_data, e_data, 12, 0, 12), +DEFINT_IMMEDIATE(error_msg_type, ASN1_KRB_ERROR); +DEFCTAGGEDTYPE(error_0, 0, krb5_version); +DEFCTAGGEDTYPE(error_1, 1, error_msg_type); +DEFFIELD(error_2, krb5_error, ctime, 2, kerberos_time); +DEFFIELD(error_3, krb5_error, cusec, 3, int32); +DEFFIELD(error_4, krb5_error, stime, 4, kerberos_time); +DEFFIELD(error_5, krb5_error, susec, 5, int32); +DEFFIELD(error_6, krb5_error, error, 6, ui_4); +DEFFIELD(error_7, krb5_error, client, 7, realm_of_principal); +DEFFIELD(error_8, krb5_error, client, 8, principal); +DEFFIELD(error_9, krb5_error, server, 9, realm_of_principal); +DEFFIELD(error_10, krb5_error, server, 10, principal); +DEFFIELD(error_11, krb5_error, text, 11, gstring_data); +DEFFIELD(error_12, krb5_error, e_data, 12, ostring_data); +static const struct atype_info *error_fields[] = { + &k5_atype_error_0, &k5_atype_error_1, &k5_atype_error_2, &k5_atype_error_3, + &k5_atype_error_4, &k5_atype_error_5, &k5_atype_error_6, &k5_atype_error_7, + &k5_atype_error_8, &k5_atype_error_9, &k5_atype_error_10, + &k5_atype_error_11, &k5_atype_error_12 }; static unsigned int optional_error(const void *p) { const krb5_error *val = p; - unsigned int optional = 0; - - if (val->ctime) - optional |= (1u << 2); - if (val->cusec) - optional |= (1u << 3); - if (val->client) { - optional |= (1u << 7); - optional |= (1u << 8); - } - if (val->text.data != NULL && val->text.length > 0) - optional |= (1u << 11); - if (val->e_data.data != NULL && val->e_data.length > 0) - optional |= (1u << 12); - - return optional; + unsigned int not_present = 0; + if (val->ctime == 0) + not_present |= (1u << 2); + if (val->cusec == 0) + not_present |= (1u << 3); + if (val->client == NULL) + not_present |= (1u << 7) | (1u << 8); + if (val->text.data == NULL || val->text.length == 0) + not_present |= (1u << 11); + if (val->e_data.data == NULL || val->e_data.length == 0) + not_present |= (1u << 12); + return not_present; } DEFSEQTYPE(untagged_krb5_error, krb5_error, error_fields, optional_error); DEFAPPTAGGEDTYPE(krb5_error, 30, untagged_krb5_error); -static const struct field_info pa_enc_ts_fields[] = { - FIELDOF_NORM(krb5_pa_enc_ts, kerberos_time, patimestamp, 0, 0), - FIELDOF_OPT(krb5_pa_enc_ts, int32, pausec, 1, 0, 1), +DEFFIELD(pa_enc_ts_0, krb5_pa_enc_ts, patimestamp, 0, kerberos_time); +DEFFIELD(pa_enc_ts_1, krb5_pa_enc_ts, pausec, 1, int32); +static const struct atype_info *pa_enc_ts_fields[] = { + &k5_atype_pa_enc_ts_0, &k5_atype_pa_enc_ts_1 }; static unsigned int optional_pa_enc_ts(const void *p) { const krb5_pa_enc_ts *val = p; - unsigned int optional = 0; - - if (val->pausec) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (val->pausec == 0) + not_present |= (1u << 1); + return not_present; } DEFSEQTYPE(pa_enc_ts, krb5_pa_enc_ts, pa_enc_ts_fields, optional_pa_enc_ts); -static const struct field_info setpw_req_fields[] = { - FIELDOF_NORM(struct krb5_setpw_req, ostring_data, password, 0, 0), - FIELDOF_NORM(struct krb5_setpw_req, principal, target, 1, 0), - FIELDOF_NORM(struct krb5_setpw_req, realm_of_principal, target, 2, 0), +DEFFIELD(setpw_0, struct krb5_setpw_req, password, 0, ostring_data); +DEFFIELD(setpw_1, struct krb5_setpw_req, target, 1, principal); +DEFFIELD(setpw_2, struct krb5_setpw_req, target, 2, realm_of_principal); +static const struct atype_info *setpw_req_fields[] = { + &k5_atype_setpw_0, &k5_atype_setpw_1, &k5_atype_setpw_2 }; - -DEFSEQTYPE(setpw_req, struct krb5_setpw_req, setpw_req_fields, 0); +DEFSEQTYPE(setpw_req, struct krb5_setpw_req, setpw_req_fields, NULL); /* [MS-SFU] Section 2.2.1. */ -static const struct field_info pa_for_user_fields[] = { - FIELDOF_NORM(krb5_pa_for_user, principal, user, 0, 0), - FIELDOF_NORM(krb5_pa_for_user, realm_of_principal, user, 1, 0), - FIELDOF_NORM(krb5_pa_for_user, checksum, cksum, 2, 0), - FIELDOF_NORM(krb5_pa_for_user, gstring_data, auth_package, 3, 0), +DEFFIELD(pa_for_user_0, krb5_pa_for_user, user, 0, principal); +DEFFIELD(pa_for_user_1, krb5_pa_for_user, user, 1, realm_of_principal); +DEFFIELD(pa_for_user_2, krb5_pa_for_user, cksum, 2, checksum); +DEFFIELD(pa_for_user_3, krb5_pa_for_user, auth_package, 3, gstring_data); +static const struct atype_info *pa_for_user_fields[] = { + &k5_atype_pa_for_user_0, &k5_atype_pa_for_user_1, &k5_atype_pa_for_user_2, + &k5_atype_pa_for_user_3, }; - -DEFSEQTYPE(pa_for_user, krb5_pa_for_user, pa_for_user_fields, 0); +DEFSEQTYPE(pa_for_user, krb5_pa_for_user, pa_for_user_fields, NULL); /* [MS-SFU] Section 2.2.2. */ -static const struct field_info s4u_userid_fields[] = { - FIELDOF_NORM(krb5_s4u_userid, int32, nonce, 0, 0), - FIELDOF_OPT(krb5_s4u_userid, principal, user, 1, 0, 1), - FIELDOF_NORM(krb5_s4u_userid, realm_of_principal, user, 2, 0), - FIELDOF_OPT(krb5_s4u_userid, ostring_data, subject_cert, 3, 0, 3), - FIELDOF_OPT(krb5_s4u_userid, krb5_flags, options, 4, 0, 4), +DEFFIELD(s4u_userid_0, krb5_s4u_userid, nonce, 0, int32); +DEFFIELD(s4u_userid_1, krb5_s4u_userid, user, 1, principal); +DEFFIELD(s4u_userid_2, krb5_s4u_userid, user, 2, realm_of_principal); +DEFFIELD(s4u_userid_3, krb5_s4u_userid, subject_cert, 3, ostring_data); +DEFFIELD(s4u_userid_4, krb5_s4u_userid, options, 4, krb5_flags); +static const struct atype_info *s4u_userid_fields[] = { + &k5_atype_s4u_userid_0, &k5_atype_s4u_userid_1, &k5_atype_s4u_userid_2, + &k5_atype_s4u_userid_3, &k5_atype_s4u_userid_4 }; - -static unsigned int s4u_userid_optional (const void *p) { +static unsigned int +s4u_userid_optional(const void *p) +{ const krb5_s4u_userid *val = p; - unsigned int optional = 0; - if (val->user != NULL && val->user->length != 0) - optional |= (1u)<<1; - if (val->subject_cert.length != 0) - optional |= (1u)<<3; - if (val->options != 0) - optional |= (1u)<<4; - return optional; + unsigned int not_present = 0; + if (val->user == NULL || val->user->length == 0) + not_present |= (1u << 1); + if (val->subject_cert.length == 0) + not_present |= (1u << 3); + if (val->options == 0) + not_present |= (1u << 4); + return not_present; } +DEFSEQTYPE(s4u_userid, krb5_s4u_userid, s4u_userid_fields, + s4u_userid_optional); -DEFSEQTYPE(s4u_userid, krb5_s4u_userid, s4u_userid_fields, s4u_userid_optional); - -static const struct field_info pa_s4u_x509_user_fields[] = { - FIELDOF_NORM(krb5_pa_s4u_x509_user, s4u_userid, user_id, 0, 0), - FIELDOF_NORM(krb5_pa_s4u_x509_user, checksum, cksum, 1, 0), +DEFFIELD(pa_s4u_x509_user_0, krb5_pa_s4u_x509_user, user_id, 0, s4u_userid); +DEFFIELD(pa_s4u_x509_user_1, krb5_pa_s4u_x509_user, cksum, 1, checksum); +static const struct atype_info *pa_s4u_x509_user_fields[] = { + &k5_atype_pa_s4u_x509_user_0, &k5_atype_pa_s4u_x509_user_1 }; - -DEFSEQTYPE(pa_s4u_x509_user, krb5_pa_s4u_x509_user, pa_s4u_x509_user_fields, 0); - -#if 0 -/* draft-brezak-win2k-krb-authz Section 6. */ -static const struct field_info pa_pac_request_fields[] = { - FIELDOF_NORM(krb5_pa_pac_req, boolean, include_pac, 0, 0), -}; - -DEFSEQTYPE(pa_pac_request, krb5_pa_pac_req, pa_pac_request_fields, 0); -#endif +DEFSEQTYPE(pa_s4u_x509_user, krb5_pa_s4u_x509_user, pa_s4u_x509_user_fields, + NULL); /* RFC 4537 */ -DEFFIELDTYPE(etype_list, krb5_etype_list, - FIELDOF_SEQOF_INT32(krb5_etype_list, int32_ptr, etypes, length, - -1, 0)); +DEFCOUNTEDTYPE(etype_list, krb5_etype_list, etypes, length, cseqof_int32); /* draft-ietf-krb-wg-preauth-framework-09 */ -static const struct field_info fast_armor_fields[] = { - FIELDOF_NORM(krb5_fast_armor, int32, armor_type, 0, 0), - FIELDOF_NORM(krb5_fast_armor, ostring_data, armor_value, 1, 0), +DEFFIELD(fast_armor_0, krb5_fast_armor, armor_type, 0, int32); +DEFFIELD(fast_armor_1, krb5_fast_armor, armor_value, 1, ostring_data); +static const struct atype_info *fast_armor_fields[] = { + &k5_atype_fast_armor_0, &k5_atype_fast_armor_1 +}; +DEFSEQTYPE(fast_armor, krb5_fast_armor, fast_armor_fields, NULL); +DEFPTRTYPE(ptr_fast_armor, fast_armor); + +DEFFIELD(fast_armored_req_0, krb5_fast_armored_req, armor, 0, ptr_fast_armor); +DEFFIELD(fast_armored_req_1, krb5_fast_armored_req, req_checksum, 1, checksum); +DEFFIELD(fast_armored_req_2, krb5_fast_armored_req, enc_part, 2, + encrypted_data); +static const struct atype_info *fast_armored_req_fields[] = { + &k5_atype_fast_armored_req_0, &k5_atype_fast_armored_req_1, + &k5_atype_fast_armored_req_2 }; - -DEFSEQTYPE( fast_armor, krb5_fast_armor, fast_armor_fields, 0); -DEFPTRTYPE( ptr_fast_armor, fast_armor); - -static const struct field_info fast_armored_req_fields[] = { - FIELDOF_OPT(krb5_fast_armored_req, ptr_fast_armor, armor, 0, 0, 0), - FIELDOF_NORM(krb5_fast_armored_req, checksum, req_checksum, 1, 0), - FIELDOF_NORM(krb5_fast_armored_req, encrypted_data, enc_part, 2, 0), -}; - -static unsigned int fast_armored_req_optional (const void *p) { +static unsigned int +fast_armored_req_optional(const void *p) +{ const krb5_fast_armored_req *val = p; - unsigned int optional = 0; - if (val->armor) - optional |= (1u)<<0; - return optional; + unsigned int not_present = 0; + if (val->armor == NULL) + not_present |= (1u << 0); + return not_present; } DEFSEQTYPE(fast_armored_req, krb5_fast_armored_req, fast_armored_req_fields, fast_armored_req_optional); @@ -1057,167 +967,171 @@ DEFSEQTYPE(fast_armored_req, krb5_fast_armored_req, fast_armored_req_fields, DEFTAGGEDTYPE(pa_fx_fast_request, CONTEXT_SPECIFIC, CONSTRUCTED, 0, 0, fast_armored_req); -DEFFIELDTYPE(fast_req_padata, krb5_kdc_req, - FIELDOF_NORM(krb5_kdc_req, ptr_seqof_pa_data, padata, -1, 0)); +DEFOFFSETTYPE(fast_req_padata, krb5_kdc_req, padata, ptr_seqof_pa_data); DEFPTRTYPE(ptr_fast_req_padata, fast_req_padata); - -static const struct field_info fast_req_fields[] = { - FIELDOF_NORM(krb5_fast_req, krb5_flags, fast_options, 0, 0), - FIELDOF_NORM( krb5_fast_req, ptr_fast_req_padata, req_body, 1, 0), - FIELDOF_NORM( krb5_fast_req, ptr_kdc_req_body, req_body, 2, 0), -}; - -DEFSEQTYPE(fast_req, krb5_fast_req, fast_req_fields, 0); - - -static const struct field_info fast_finished_fields[] = { - FIELDOF_NORM( krb5_fast_finished, kerberos_time, timestamp, 0, 0), - FIELDOF_NORM( krb5_fast_finished, int32, usec, 1, 0), - FIELDOF_NORM( krb5_fast_finished, realm_of_principal, client, 2, 0), - FIELDOF_NORM(krb5_fast_finished, principal, client, 3, 0), - FIELDOF_NORM( krb5_fast_finished, checksum, ticket_checksum, 4, 0), -}; - -DEFSEQTYPE( fast_finished, krb5_fast_finished, fast_finished_fields, 0); - -DEFPTRTYPE( ptr_fast_finished, fast_finished); - -static const struct field_info fast_response_fields[] = { - FIELDOF_NORM(krb5_fast_response, ptr_seqof_pa_data, padata, 0, 0), - FIELDOF_OPT(krb5_fast_response, ptr_encryption_key, strengthen_key, - 1, 0, 1), - FIELDOF_OPT(krb5_fast_response, ptr_fast_finished, finished, 2, 0, 2), - FIELDOF_NORM(krb5_fast_response, int32, nonce, 3, 0), +DEFPTRTYPE(ptr_kdc_req_body, kdc_req_body); +DEFFIELD(fast_req_0, krb5_fast_req, fast_options, 0, krb5_flags); +DEFFIELD(fast_req_1, krb5_fast_req, req_body, 1, ptr_fast_req_padata); +DEFFIELD(fast_req_2, krb5_fast_req, req_body, 2, ptr_kdc_req_body); +static const struct atype_info *fast_req_fields[] = { + &k5_atype_fast_req_0, &k5_atype_fast_req_1, &k5_atype_fast_req_2 +}; +DEFSEQTYPE(fast_req, krb5_fast_req, fast_req_fields, NULL); + +DEFFIELD(fast_finished_0, krb5_fast_finished, timestamp, 0, kerberos_time); +DEFFIELD(fast_finished_1, krb5_fast_finished, usec, 1, int32); +DEFFIELD(fast_finished_2, krb5_fast_finished, client, 2, realm_of_principal); +DEFFIELD(fast_finished_3, krb5_fast_finished, client, 3, principal); +DEFFIELD(fast_finished_4, krb5_fast_finished, ticket_checksum, 4, checksum); +static const struct atype_info *fast_finished_fields[] = { + &k5_atype_fast_finished_0, &k5_atype_fast_finished_1, + &k5_atype_fast_finished_2, &k5_atype_fast_finished_3, + &k5_atype_fast_finished_4 +}; +DEFSEQTYPE(fast_finished, krb5_fast_finished, fast_finished_fields, NULL); +DEFPTRTYPE(ptr_fast_finished, fast_finished); + +DEFFIELD(fast_response_0, krb5_fast_response, padata, 0, ptr_seqof_pa_data); +DEFFIELD(fast_response_1, krb5_fast_response, strengthen_key, 1, + ptr_encryption_key); +DEFFIELD(fast_response_2, krb5_fast_response, finished, 2, ptr_fast_finished); +DEFFIELD(fast_response_3, krb5_fast_response, nonce, 3, int32); +static const struct atype_info *fast_response_fields[] = { + &k5_atype_fast_response_0, &k5_atype_fast_response_1, + &k5_atype_fast_response_2, &k5_atype_fast_response_3 }; - static unsigned int -fast_response_optional (const void *p) +fast_response_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_fast_response *val = p; - if (val->strengthen_key) - optional |= (1u <<1); - if (val->finished) - optional |= (1u<<2); - return optional; + if (val->strengthen_key == NULL) + not_present |= (1u <<1); + if (val->finished == NULL) + not_present |= (1u<<2); + return not_present; } -DEFSEQTYPE( fast_response, krb5_fast_response, fast_response_fields, fast_response_optional); +DEFSEQTYPE(fast_response, krb5_fast_response, fast_response_fields, + fast_response_optional); -static const struct field_info fast_rep_fields[] = { - FIELDOF_ENCODEAS(krb5_enc_data, encrypted_data, 0, 0), +DEFCTAGGEDTYPE(fast_rep_0, 0, encrypted_data); +static const struct atype_info *fast_rep_fields[] = { + &k5_atype_fast_rep_0 }; -DEFSEQTYPE(fast_rep, krb5_enc_data, fast_rep_fields, 0); +DEFSEQTYPE(fast_rep, krb5_enc_data, fast_rep_fields, NULL); /* This is a CHOICE type with only one choice (so far) and we're not using a * distinguisher/union for it. */ DEFTAGGEDTYPE(pa_fx_fast_reply, CONTEXT_SPECIFIC, CONSTRUCTED, 0, 0, fast_rep); -static const struct field_info ad_kdcissued_fields[] = { - FIELDOF_NORM(krb5_ad_kdcissued, checksum, ad_checksum, 0, 0), - FIELDOF_OPT(krb5_ad_kdcissued, realm_of_principal, i_principal, 1, 0, 1), - FIELDOF_OPT(krb5_ad_kdcissued, principal, i_principal, 2, 0, 1), - FIELDOF_NORM(krb5_ad_kdcissued, auth_data_ptr, elements, 3, 0), +DEFFIELD(ad_kdcissued_0, krb5_ad_kdcissued, ad_checksum, 0, checksum); +DEFFIELD(ad_kdcissued_1, krb5_ad_kdcissued, i_principal, 1, + realm_of_principal); +DEFFIELD(ad_kdcissued_2, krb5_ad_kdcissued, i_principal, 2, principal); +DEFFIELD(ad_kdcissued_3, krb5_ad_kdcissued, elements, 3, auth_data_ptr); +static const struct atype_info *ad_kdcissued_fields[] = { + &k5_atype_ad_kdcissued_0, &k5_atype_ad_kdcissued_1, + &k5_atype_ad_kdcissued_2, &k5_atype_ad_kdcissued_3 }; - static unsigned int ad_kdcissued_optional(const void *p) { unsigned int optional = 0; const krb5_ad_kdcissued *val = p; - if (val->i_principal) - optional |= (1u << 1); + if (val->i_principal == NULL) + optional |= (1u << 1) | (1u << 2); return optional; } +DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields, + ad_kdcissued_optional); -DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields, ad_kdcissued_optional); - -static const struct field_info princ_plus_realm_fields[] = { - FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 0, 0), - FIELDOF_ENCODEAS(krb5_principal_data, realm_of_principal_data, 1, 0), +DEFCTAGGEDTYPE(princ_plus_realm_0, 0, principal_data); +DEFCTAGGEDTYPE(princ_plus_realm_1, 1, realm_of_principal_data); +static const struct atype_info *princ_plus_realm_fields[] = { + &k5_atype_princ_plus_realm_0, &k5_atype_princ_plus_realm_1 }; - -DEFSEQTYPE(princ_plus_realm_data, krb5_principal_data, princ_plus_realm_fields, 0); +DEFSEQTYPE(princ_plus_realm_data, krb5_principal_data, princ_plus_realm_fields, + NULL); DEFPTRTYPE(princ_plus_realm, princ_plus_realm_data); - -DEFNULLTERMSEQOFTYPE(seq_of_princ_plus_realm, princ_plus_realm); -DEFPTRTYPE(ptr_seq_of_princ_plus_realm, seq_of_princ_plus_realm); - -static const struct field_info ad_signedpath_data_fields[] = { - FIELDOF_NORM(krb5_ad_signedpath_data, princ_plus_realm, client, 0, 0), - FIELDOF_NORM(krb5_ad_signedpath_data, kerberos_time, authtime, 1, 0), - FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seq_of_princ_plus_realm, - delegated, 2, 0, 2), - FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seqof_pa_data, method_data, - 3, 0, 3), - FIELDOF_OPT(krb5_ad_signedpath_data, auth_data_ptr, authorization_data, - 4, 0, 4), +DEFNULLTERMSEQOFTYPE(seqof_princ_plus_realm, princ_plus_realm); +DEFPTRTYPE(ptr_seqof_princ_plus_realm, seqof_princ_plus_realm); + +DEFFIELD(spdata_0, krb5_ad_signedpath_data, client, 0, princ_plus_realm); +DEFFIELD(spdata_1, krb5_ad_signedpath_data, authtime, 1, kerberos_time); +DEFFIELD(spdata_2, krb5_ad_signedpath_data, delegated, 2, + ptr_seqof_princ_plus_realm); +DEFFIELD(spdata_3, krb5_ad_signedpath_data, method_data, 3, ptr_seqof_pa_data); +DEFFIELD(spdata_4, krb5_ad_signedpath_data, authorization_data, 4, + auth_data_ptr); +static const struct atype_info *ad_signedpath_data_fields[] = { + &k5_atype_spdata_0, &k5_atype_spdata_1, &k5_atype_spdata_2, + &k5_atype_spdata_3, &k5_atype_spdata_4 }; - -static unsigned int ad_signedpath_data_optional(const void *p) +static unsigned int +ad_signedpath_data_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_ad_signedpath_data *val = p; - if (val->delegated && val->delegated[0]) - optional |= (1u << 2); - if (val->method_data && val->method_data[0]) - optional |= (1u << 3); - if (val->authorization_data && val->authorization_data[0]) - optional |= (1u << 4); - return optional; + if (val->delegated == NULL || val->delegated[0] == NULL) + not_present |= (1u << 2); + if (val->method_data == NULL || val->method_data[0] == NULL) + not_present |= (1u << 3); + if (val->authorization_data == NULL || val->authorization_data[0] == NULL) + not_present |= (1u << 4); + return not_present; } - -DEFSEQTYPE(ad_signedpath_data, krb5_ad_signedpath_data, ad_signedpath_data_fields, ad_signedpath_data_optional); - -static const struct field_info ad_signedpath_fields[] = { - FIELDOF_NORM(krb5_ad_signedpath, int32, enctype, 0, 0), - FIELDOF_NORM(krb5_ad_signedpath, checksum, checksum, 1, 0), - FIELDOF_OPT(krb5_ad_signedpath, ptr_seq_of_princ_plus_realm, delegated, - 2, 0, 2), - FIELDOF_OPT(krb5_ad_signedpath, ptr_seqof_pa_data, method_data, 3, 0, 3), +DEFSEQTYPE(ad_signedpath_data, krb5_ad_signedpath_data, + ad_signedpath_data_fields, ad_signedpath_data_optional); + +DEFFIELD(signedpath_0, krb5_ad_signedpath, enctype, 0, int32); +DEFFIELD(signedpath_1, krb5_ad_signedpath, checksum, 1, checksum); +DEFFIELD(signedpath_2, krb5_ad_signedpath, delegated, 2, + ptr_seqof_princ_plus_realm); +DEFFIELD(signedpath_3, krb5_ad_signedpath, method_data, 3, ptr_seqof_pa_data); +static const struct atype_info *ad_signedpath_fields[] = { + &k5_atype_signedpath_0, &k5_atype_signedpath_1, &k5_atype_signedpath_2, + &k5_atype_signedpath_3 }; - -static unsigned int ad_signedpath_optional(const void *p) +static unsigned int +ad_signedpath_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_ad_signedpath *val = p; - if (val->delegated && val->delegated[0]) - optional |= (1u << 2); - if (val->method_data && val->method_data[0]) - optional |= (1u << 3); - return optional; + if (val->delegated == NULL || val->delegated[0] == NULL) + not_present |= (1u << 2); + if (val->method_data == NULL || val->method_data[0] == NULL) + not_present |= (1u << 3); + return not_present; } +DEFSEQTYPE(ad_signedpath, krb5_ad_signedpath, ad_signedpath_fields, + ad_signedpath_optional); -DEFSEQTYPE(ad_signedpath, krb5_ad_signedpath, ad_signedpath_fields, ad_signedpath_optional); - -static const struct field_info iakerb_header_fields[] = { - FIELDOF_NORM(krb5_iakerb_header, ostring_data, target_realm, 1, 0), - FIELDOF_OPT(krb5_iakerb_header, ostring_data_ptr, cookie, 2, 0, 2), +/* First context tag is 1, not 0. */ +DEFFIELD(iakerb_header_1, krb5_iakerb_header, target_realm, 1, ostring_data); +DEFFIELD(iakerb_header_2, krb5_iakerb_header, cookie, 2, ostring_data_ptr); +static const struct atype_info *iakerb_header_fields[] = { + &k5_atype_iakerb_header_1, &k5_atype_iakerb_header_2 }; - -static unsigned int iakerb_header_optional(const void *p) +static unsigned int +iakerb_header_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_iakerb_header *val = p; - if (val->cookie && val->cookie->data) - optional |= (1u << 2); - return optional; + if (val->cookie == NULL || val->cookie->data == NULL) + not_present |= (1u << 1); + return not_present; } +DEFSEQTYPE(iakerb_header, krb5_iakerb_header, iakerb_header_fields, + iakerb_header_optional); -DEFSEQTYPE(iakerb_header, krb5_iakerb_header, iakerb_header_fields, iakerb_header_optional); - -static const struct field_info iakerb_finished_fields[] = { - FIELDOF_NORM(krb5_iakerb_finished, checksum, checksum, 1, 0), +/* First context tag is 1, not 0. */ +DEFFIELD(iakerb_finished_0, krb5_iakerb_finished, checksum, 1, checksum); +static const struct atype_info *iakerb_finished_fields[] = { + &k5_atype_iakerb_finished_0 }; - -static unsigned int iakerb_finished_optional(const void *p) -{ - unsigned int optional = 0; - return optional; -} - DEFSEQTYPE(iakerb_finished, krb5_iakerb_finished, iakerb_finished_fields, - iakerb_finished_optional); + NULL); /* Exported complete encoders -- these produce a krb5_data with the encoding in the correct byte order. */ @@ -1259,7 +1173,7 @@ MAKE_FULL_ENCODER(encode_krb5_etype_info, etype_info); MAKE_FULL_ENCODER(encode_krb5_etype_info2, etype_info2); MAKE_FULL_ENCODER(encode_krb5_enc_data, encrypted_data); MAKE_FULL_ENCODER(encode_krb5_pa_enc_ts, pa_enc_ts); -MAKE_FULL_ENCODER(encode_krb5_padata_sequence, seq_of_pa_data); +MAKE_FULL_ENCODER(encode_krb5_padata_sequence, seqof_pa_data); /* sam preauth additions */ MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2, sam_challenge_2); MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2_body, @@ -1290,214 +1204,222 @@ MAKE_FULL_ENCODER(encode_krb5_iakerb_finished, iakerb_finished); #ifndef DISABLE_PKINIT -DEFSTRINGTYPE(object_identifier, char *, asn1_encode_bytestring, - ASN1_OBJECTIDENTIFIER); -DEFFIELDTYPE(oid_data, krb5_data, - FIELDOF_STRING(krb5_data, object_identifier, data, length, - -1, 0)); +DEFCOUNTEDSTRINGTYPE(object_identifier, char *, unsigned int, + asn1_encode_bytestring, ASN1_OBJECTIDENTIFIER); +DEFCOUNTEDTYPE(oid_data, krb5_data, data, length, object_identifier); DEFPTRTYPE(oid_data_ptr, oid_data); +/* RFC 3280. No context tags. */ +DEFOFFSETTYPE(algid_0, krb5_algorithm_identifier, algorithm, oid_data); +DEFOFFSETTYPE(algid_1, krb5_algorithm_identifier, parameters, der_data); +static const struct atype_info *algorithm_identifier_fields[] = { + &k5_atype_algid_0, &k5_atype_algid_1 +}; static unsigned int algorithm_identifier_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_algorithm_identifier *val = p; - if (val->parameters.length > 0) - optional |= (1u << 1); - return optional; + if (val->parameters.length == 0) + not_present |= (1u << 1); + return not_present; } - -static const struct field_info algorithm_identifier_fields[] = { - FIELDOF_NORM(krb5_algorithm_identifier, oid_data, algorithm, -1, 0), - FIELDOF_OPT(krb5_algorithm_identifier, der_data, parameters, -1, 0, 1), -}; DEFSEQTYPE(algorithm_identifier, krb5_algorithm_identifier, algorithm_identifier_fields, algorithm_identifier_optional); DEFPTRTYPE(algorithm_identifier_ptr, algorithm_identifier); -static const struct field_info kdf_alg_id_fields[] = { - FIELDOF_ENCODEAS(krb5_data, oid_data, 0, 0) +DEFCTAGGEDTYPE(kdf_alg_id_0, 0, oid_data); +static const struct atype_info *kdf_alg_id_fields[] = { + &k5_atype_kdf_alg_id_0 }; DEFSEQTYPE(kdf_alg_id, krb5_data, kdf_alg_id_fields, NULL); DEFPTRTYPE(kdf_alg_id_ptr, kdf_alg_id); DEFNONEMPTYNULLTERMSEQOFTYPE(supported_kdfs, kdf_alg_id_ptr); DEFPTRTYPE(supported_kdfs_ptr, supported_kdfs); -/* Krb5PrincipalName is defined in RFC 4556 and is *not* PrincipalName from RFC 4120*/ -static const struct field_info pkinit_krb5_principal_name_fields[] = { - FIELDOF_NORM(krb5_principal_data, gstring_data, realm, 0, 0), - FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 1, 0) +/* KRB5PrincipalName from RFC 4556 (*not* PrincipalName from RFC 4120) */ +DEFCTAGGEDTYPE(pkinit_princ_0, 0, realm_of_principal_data); +DEFCTAGGEDTYPE(pkinit_princ_1, 1, principal_data); +static const struct atype_info *pkinit_krb5_principal_name_fields[] = { + &k5_atype_pkinit_princ_0, &k5_atype_pkinit_princ_1 }; - - -DEFSEQTYPE(pkinit_krb5_principal_name_data, krb5_principal_data, pkinit_krb5_principal_name_fields, NULL); +DEFSEQTYPE(pkinit_krb5_principal_name_data, krb5_principal_data, + pkinit_krb5_principal_name_fields, NULL); DEFPTRTYPE(pkinit_krb5_principal_name, pkinit_krb5_principal_name_data); -DEFOCTETWRAPTYPE(pkinit_krb5_principal_name_wrapped, pkinit_krb5_principal_name); - -/* For SP80056A OtherInfo, for pkinit agility */ -static const struct field_info sp80056a_other_info_fields[] = { - FIELDOF_NORM(krb5_sp80056a_other_info, algorithm_identifier, - algorithm_identifier, -1, 0), - FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, - party_u_info, 0, 0), - FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, - party_v_info, 1, 0), - FIELDOF_STRING(krb5_sp80056a_other_info, s_octetstring, - supp_pub_info.data, supp_pub_info.length, 2, 0), -}; - -DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, sp80056a_other_info_fields, NULL); +/* SP80056A OtherInfo, for pkinit agility. No context tag on first field. */ +DEFTAGGEDTYPE(pkinit_krb5_principal_name_wrapped, UNIVERSAL, PRIMITIVE, + ASN1_OCTETSTRING, 0, pkinit_krb5_principal_name); +DEFOFFSETTYPE(oinfo_notag, krb5_sp80056a_other_info, algorithm_identifier, + algorithm_identifier); +DEFFIELD(oinfo_0, krb5_sp80056a_other_info, party_u_info, 0, + pkinit_krb5_principal_name_wrapped); +DEFFIELD(oinfo_1, krb5_sp80056a_other_info, party_v_info, 1, + pkinit_krb5_principal_name_wrapped); +DEFFIELD(oinfo_2, krb5_sp80056a_other_info, supp_pub_info, 2, ostring_data); +static const struct atype_info *sp80056a_other_info_fields[] = { + &k5_atype_oinfo_notag, &k5_atype_oinfo_0, &k5_atype_oinfo_1, + &k5_atype_oinfo_2 +}; +DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, + sp80056a_other_info_fields, NULL); /* For PkinitSuppPubInfo, for pkinit agility */ -static const struct field_info pkinit_supp_pub_info_fields[] = { - FIELDOF_NORM(krb5_pkinit_supp_pub_info, int32, enctype, 0, 0), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, as_req.data, - as_req.length, 1, 0), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, pk_as_rep.data, - pk_as_rep.length, 2, 0), +DEFFIELD(supp_pub_0, krb5_pkinit_supp_pub_info, enctype, 0, int32); +DEFFIELD(supp_pub_1, krb5_pkinit_supp_pub_info, as_req, 1, ostring_data); +DEFFIELD(supp_pub_2, krb5_pkinit_supp_pub_info, pk_as_rep, 2, ostring_data); +static const struct atype_info *pkinit_supp_pub_info_fields[] = { + &k5_atype_supp_pub_0, &k5_atype_supp_pub_1, &k5_atype_supp_pub_2 }; - -DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, pkinit_supp_pub_info_fields, NULL); +DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, + pkinit_supp_pub_info_fields, NULL); MAKE_FULL_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info); MAKE_FULL_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info); /* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */ -DEFFIELDTYPE(ostring_checksum, krb5_checksum, - FIELDOF_STRING(krb5_checksum, octetstring, contents, length, - -1, 0)); +DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring); -static const struct field_info pk_authenticator_fields[] = { - FIELDOF_NORM(krb5_pk_authenticator, int32, cusec, 0, 0), - FIELDOF_NORM(krb5_pk_authenticator, kerberos_time, ctime, 1, 0), - FIELDOF_NORM(krb5_pk_authenticator, int32, nonce, 2, 0), - FIELDOF_NORM(krb5_pk_authenticator, ostring_checksum, paChecksum, 3, 0), +DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32); +DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time); +DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32); +DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3, + ostring_checksum); +static const struct atype_info *pk_authenticator_fields[] = { + &k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1, + &k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3 }; DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields, - 0); - -static const struct field_info pk_authenticator_draft9_fields[] = { - FIELDOF_NORM(krb5_pk_authenticator_draft9, principal, kdcName, 0, 0), - FIELDOF_NORM(krb5_pk_authenticator_draft9, realm_of_principal, kdcName, - 1, 0), - FIELDOF_NORM(krb5_pk_authenticator_draft9, int32, cusec, 2, 0), - FIELDOF_NORM(krb5_pk_authenticator_draft9, kerberos_time, ctime, 3, 0), - FIELDOF_NORM(krb5_pk_authenticator_draft9, int32, nonce, 4, 0), + NULL); + +DEFFIELD(pkauth9_0, krb5_pk_authenticator_draft9, kdcName, 0, principal); +DEFFIELD(pkauth9_1, krb5_pk_authenticator_draft9, kdcName, 1, + realm_of_principal); +DEFFIELD(pkauth9_2, krb5_pk_authenticator_draft9, cusec, 2, int32); +DEFFIELD(pkauth9_3, krb5_pk_authenticator_draft9, ctime, 3, kerberos_time); +DEFFIELD(pkauth9_4, krb5_pk_authenticator_draft9, nonce, 4, int32); +static const struct atype_info *pk_authenticator_draft9_fields[] = { + &k5_atype_pkauth9_0, &k5_atype_pkauth9_1, &k5_atype_pkauth9_2, + &k5_atype_pkauth9_3, &k5_atype_pkauth9_4 }; DEFSEQTYPE(pk_authenticator_draft9, krb5_pk_authenticator_draft9, - pk_authenticator_draft9_fields, 0); + pk_authenticator_draft9_fields, NULL); -DEFSTRINGTYPE(s_bitstring, char *, asn1_encode_bitstring, ASN1_BITSTRING); -DEFFIELDTYPE(bitstring_data, krb5_data, - FIELDOF_STRING(krb5_data, s_bitstring, data, length, -1, 0)); +DEFCOUNTEDSTRINGTYPE(s_bitstring, char *, unsigned int, asn1_encode_bitstring, + ASN1_BITSTRING); +DEFCOUNTEDTYPE(bitstring_data, krb5_data, data, length, s_bitstring); -static const struct field_info subject_pk_info_fields[] = { - FIELDOF_NORM(krb5_subject_pk_info, algorithm_identifier, algorithm, -1, 0), - FIELDOF_NORM(krb5_subject_pk_info, bitstring_data, subjectPublicKey, -1, 0) +/* RFC 3280. No context tags. */ +DEFOFFSETTYPE(spki_0, krb5_subject_pk_info, algorithm, algorithm_identifier); +DEFOFFSETTYPE(spki_1, krb5_subject_pk_info, subjectPublicKey, bitstring_data); +static const struct atype_info *subject_pk_info_fields[] = { + &k5_atype_spki_0, &k5_atype_spki_1 }; -DEFSEQTYPE(subject_pk_info, krb5_subject_pk_info, subject_pk_info_fields, 0); +DEFSEQTYPE(subject_pk_info, krb5_subject_pk_info, subject_pk_info_fields, + NULL); DEFPTRTYPE(subject_pk_info_ptr, subject_pk_info); -DEFNULLTERMSEQOFTYPE(seq_of_algorithm_identifier, algorithm_identifier_ptr); -DEFPTRTYPE(ptr_seqof_algorithm_identifier, seq_of_algorithm_identifier); - +DEFNULLTERMSEQOFTYPE(seqof_algorithm_identifier, algorithm_identifier_ptr); +DEFPTRTYPE(ptr_seqof_algorithm_identifier, seqof_algorithm_identifier); +DEFFIELD(auth_pack_0, krb5_auth_pack, pkAuthenticator, 0, pk_authenticator); +DEFFIELD(auth_pack_1, krb5_auth_pack, clientPublicValue, 1, + subject_pk_info_ptr); +DEFFIELD(auth_pack_2, krb5_auth_pack, supportedCMSTypes, 2, + ptr_seqof_algorithm_identifier); +DEFFIELD(auth_pack_3, krb5_auth_pack, clientDHNonce, 3, ostring_data); +DEFFIELD(auth_pack_4, krb5_auth_pack, supportedKDFs, 4, supported_kdfs_ptr); +static const struct atype_info *auth_pack_fields[] = { + &k5_atype_auth_pack_0, &k5_atype_auth_pack_1, &k5_atype_auth_pack_2, + &k5_atype_auth_pack_3, &k5_atype_auth_pack_4 +}; static unsigned int auth_pack_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_auth_pack *val = p; - if (val->clientPublicValue != NULL) - optional |= (1u << 1); - if (val->supportedCMSTypes != NULL) - optional |= (1u << 2); - if (val->clientDHNonce.length != 0) - optional |= (1u << 3); - if (val->supportedKDFs != NULL) - optional |= (1u << 4); - return optional; + if (val->clientPublicValue == NULL) + not_present |= (1u << 1); + if (val->supportedCMSTypes == NULL) + not_present |= (1u << 2); + if (val->clientDHNonce.length == 0) + not_present |= (1u << 3); + if (val->supportedKDFs == NULL) + not_present |= (1u << 4); + return not_present; } - -static const struct field_info auth_pack_fields[] = { - FIELDOF_NORM(krb5_auth_pack, pk_authenticator, pkAuthenticator, 0, 0), - FIELDOF_OPT(krb5_auth_pack, subject_pk_info_ptr, clientPublicValue, - 1, 0, 1), - FIELDOF_OPT(krb5_auth_pack, ptr_seqof_algorithm_identifier, - supportedCMSTypes, 2, 0, 2), - FIELDOF_OPT(krb5_auth_pack, ostring_data, clientDHNonce, 3, 0, 3), - FIELDOF_OPT(krb5_auth_pack, supported_kdfs_ptr, supportedKDFs, 4, 0, 4), -}; DEFSEQTYPE(auth_pack, krb5_auth_pack, auth_pack_fields, auth_pack_optional); +DEFFIELD(auth_pack9_0, krb5_auth_pack_draft9, pkAuthenticator, 0, + pk_authenticator_draft9); +DEFFIELD(auth_pack9_1, krb5_auth_pack_draft9, clientPublicValue, 1, + subject_pk_info_ptr); +static const struct atype_info *auth_pack_draft9_fields[] = { + &k5_atype_auth_pack9_0, &k5_atype_auth_pack9_1 +}; static unsigned int auth_pack_draft9_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_auth_pack_draft9 *val = p; - if (val->clientPublicValue != NULL) - optional |= (1u << 1); - return optional; + if (val->clientPublicValue == NULL) + not_present |= (1u << 1); + return not_present; } - -static const struct field_info auth_pack_draft9_fields[] = { - FIELDOF_NORM(krb5_auth_pack_draft9, pk_authenticator_draft9, - pkAuthenticator, 0, 0), - FIELDOF_OPT(krb5_auth_pack_draft9, subject_pk_info_ptr, - clientPublicValue, 1, 0, 1), -}; DEFSEQTYPE(auth_pack_draft9, krb5_auth_pack_draft9, auth_pack_draft9_fields, auth_pack_draft9_optional); +DEFFIELD_IMPLICIT(extprinc_0, krb5_external_principal_identifier, + subjectName, 0, ostring_data); +DEFFIELD_IMPLICIT(extprinc_1, krb5_external_principal_identifier, + issuerAndSerialNumber, 1, ostring_data); +DEFFIELD_IMPLICIT(extprinc_2, krb5_external_principal_identifier, + subjectKeyIdentifier, 2, ostring_data); +static const struct atype_info *external_principal_identifier_fields[] = { + &k5_atype_extprinc_0, &k5_atype_extprinc_1, &k5_atype_extprinc_2 +}; static unsigned int external_principal_identifier_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_external_principal_identifier *val = p; - if (val->subjectName.length > 0) - optional |= (1u << 0); - if (val->issuerAndSerialNumber.length > 0) - optional |= (1u << 1); - if (val->subjectKeyIdentifier.length > 0) - optional |= (1u << 2); - return optional; + if (val->subjectName.length == 0) + not_present |= (1u << 0); + if (val->issuerAndSerialNumber.length == 0) + not_present |= (1u << 1); + if (val->subjectKeyIdentifier.length == 0) + not_present |= (1u << 2); + return not_present; } - -static const struct field_info external_principal_identifier_fields[] = { - FIELDOF_OPT(krb5_external_principal_identifier, ostring_data, subjectName, - 0, 1, 0), - FIELDOF_OPT(krb5_external_principal_identifier, ostring_data, - issuerAndSerialNumber, 1, 1, 1), - FIELDOF_OPT(krb5_external_principal_identifier, ostring_data, - subjectKeyIdentifier, 2, 1, 2), -}; DEFSEQTYPE(external_principal_identifier, krb5_external_principal_identifier, external_principal_identifier_fields, external_principal_identifier_optional); DEFPTRTYPE(external_principal_identifier_ptr, external_principal_identifier); -DEFNULLTERMSEQOFTYPE(seq_of_external_principal_identifier, +DEFNULLTERMSEQOFTYPE(seqof_external_principal_identifier, external_principal_identifier_ptr); DEFPTRTYPE(ptr_seqof_external_principal_identifier, - seq_of_external_principal_identifier); + seqof_external_principal_identifier); +DEFFIELD_IMPLICIT(pa_pk_as_req_0, krb5_pa_pk_as_req, signedAuthPack, 0, + ostring_data); +DEFFIELD(pa_pk_as_req_1, krb5_pa_pk_as_req, trustedCertifiers, 1, + ptr_seqof_external_principal_identifier); +DEFFIELD_IMPLICIT(pa_pk_as_req_2, krb5_pa_pk_as_req, kdcPkId, 2, ostring_data); +static const struct atype_info *pa_pk_as_req_fields[] = { + &k5_atype_pa_pk_as_req_0, &k5_atype_pa_pk_as_req_1, + &k5_atype_pa_pk_as_req_2 +}; static unsigned int pa_pk_as_req_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_pa_pk_as_req *val = p; - if (val->trustedCertifiers != NULL) - optional |= (1u << 1); - if (val->kdcPkId.length > 0) - optional |= (1u << 2); - return optional; + if (val->trustedCertifiers == NULL) + not_present |= (1u << 1); + if (val->kdcPkId.length == 0) + not_present |= (1u << 2); + return not_present; } - -static const struct field_info pa_pk_as_req_fields[] = { - FIELDOF_NORM(krb5_pa_pk_as_req, ostring_data, signedAuthPack, 0, 1), - FIELDOF_OPT(krb5_pa_pk_as_req, ptr_seqof_external_principal_identifier, - trustedCertifiers, 1, 0, 1), - FIELDOF_OPT(krb5_pa_pk_as_req, ostring_data, kdcPkId, 2, 1, 2), -}; DEFSEQTYPE(pa_pk_as_req, krb5_pa_pk_as_req, pa_pk_as_req_fields, pa_pk_as_req_optional); @@ -1512,39 +1434,25 @@ DEFSEQTYPE(pa_pk_as_req, krb5_pa_pk_as_req, pa_pk_as_req_fields, * krb5_data object; pretend that they are wrapped in IMPLICIT OCTET STRING in * order to wrap them in primitive [1] and [2] tags. */ -DEFTAGGEDTYPE(princ_0_primitive, CONTEXT_SPECIFIC, PRIMITIVE, 0, 0, principal); -typedef union krb5_trusted_ca_choices krb5_trusted_ca_choices; -typedef enum krb5_trusted_ca_selection krb5_trusted_ca_selection; -static const struct field_info trusted_ca_alternatives[] = { - FIELDOF_NORM(krb5_trusted_ca_choices, princ_0_primitive, principalName, - -1, 0), - FIELDOF_NORM(krb5_trusted_ca_choices, ostring_data, caName, 1, 1), - FIELDOF_NORM(krb5_trusted_ca_choices, ostring_data, issuerAndSerial, 2, 1), -}; -DEFCHOICETYPE(trusted_ca_choice, krb5_trusted_ca_choices, - trusted_ca_alternatives); -DEFINTTYPE(trusted_ca_selection, krb5_trusted_ca_selection); -DEFFIELDTYPE(trusted_ca, krb5_trusted_ca, - FIELDOF_CHOICE(krb5_trusted_ca, trusted_ca_choice, u, choice, - trusted_ca_selection, -1)); +DEFOFFSETTYPE(trusted_ca_0_untagged, union krb5_trusted_ca_choices, + principalName, principal); +DEFTAGGEDTYPE(trusted_ca_0, CONTEXT_SPECIFIC, PRIMITIVE, 0, 0, + trusted_ca_0_untagged); +DEFFIELD_IMPLICIT(trusted_ca_1, union krb5_trusted_ca_choices, caName, 1, + ostring_data); +DEFFIELD_IMPLICIT(trusted_ca_2, union krb5_trusted_ca_choices, + issuerAndSerial, 2, ostring_data); +static const struct atype_info *trusted_ca_alternatives[] = { + &k5_atype_trusted_ca_0, &k5_atype_trusted_ca_1, &k5_atype_trusted_ca_2 +}; +DEFCHOICETYPE(trusted_ca_choice, union krb5_trusted_ca_choices, + enum krb5_trusted_ca_selection, trusted_ca_alternatives); +DEFCOUNTEDTYPE_SIGNED(trusted_ca, krb5_trusted_ca, u, choice, + trusted_ca_choice); DEFPTRTYPE(trusted_ca_ptr, trusted_ca); -DEFNULLTERMSEQOFTYPE(seq_of_trusted_ca, trusted_ca_ptr); -DEFPTRTYPE(ptr_seqof_trusted_ca, seq_of_trusted_ca); - -static unsigned int -pa_pk_as_req_draft9_optional(const void *p) -{ - unsigned int optional = 0; - const krb5_pa_pk_as_req_draft9 *val = p; - if (val->trustedCertifiers != NULL) - optional |= (1u << 1); - if (val->kdcCert.length > 0) - optional |= (1u << 2); - if (val->encryptionCert.length > 0) - optional |= (1u << 3); - return optional; -} +DEFNULLTERMSEQOFTYPE(seqof_trusted_ca, trusted_ca_ptr); +DEFPTRTYPE(ptr_seqof_trusted_ca, seqof_trusted_ca); /* * draft-ietf-cat-kerberos-pk-init-09 specifies signedAuthPack, kdcCert, and @@ -1556,81 +1464,99 @@ pa_pk_as_req_draft9_optional(const void *p) * wrapped in IMPLICIT OCTET STRING in order to generate primitive context * tags. */ -static const struct field_info pa_pk_as_req_draft9_fields[] = { - FIELDOF_NORM(krb5_pa_pk_as_req_draft9, ostring_data, signedAuthPack, 0, 1), - FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ptr_seqof_trusted_ca, - trustedCertifiers, 1, 0, 1), - FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ostring_data, kdcCert, 2, 1, 2), - FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ostring_data, encryptionCert, - 3, 1, 3), +DEFFIELD_IMPLICIT(pa_pk_as_req9_0, krb5_pa_pk_as_req_draft9, signedAuthPack, 0, + ostring_data); +DEFFIELD(pa_pk_as_req9_1, krb5_pa_pk_as_req_draft9, trustedCertifiers, 1, + ptr_seqof_trusted_ca); +DEFFIELD_IMPLICIT(pa_pk_as_req9_2, krb5_pa_pk_as_req_draft9, kdcCert, 2, + ostring_data); +DEFFIELD_IMPLICIT(pa_pk_as_req9_3, krb5_pa_pk_as_req_draft9, encryptionCert, 3, + ostring_data); +static const struct atype_info *pa_pk_as_req_draft9_fields[] = { + &k5_atype_pa_pk_as_req9_0, &k5_atype_pa_pk_as_req9_1, + &k5_atype_pa_pk_as_req9_2, &k5_atype_pa_pk_as_req9_3 }; +static unsigned int +pa_pk_as_req_draft9_optional(const void *p) +{ + unsigned int not_present = 0; + const krb5_pa_pk_as_req_draft9 *val = p; + if (val->trustedCertifiers == NULL) + not_present |= (1u << 1); + if (val->kdcCert.length == 0) + not_present |= (1u << 2); + if (val->encryptionCert.length == 0) + not_present |= (1u << 3); + return not_present; +} DEFSEQTYPE(pa_pk_as_req_draft9, krb5_pa_pk_as_req_draft9, pa_pk_as_req_draft9_fields, pa_pk_as_req_draft9_optional); +DEFFIELD_IMPLICIT(dh_rep_info_0, krb5_dh_rep_info, dhSignedData, 0, + ostring_data); +DEFFIELD(dh_rep_info_1, krb5_dh_rep_info, serverDHNonce, 1, ostring_data); +DEFFIELD(dh_rep_info_2, krb5_dh_rep_info, kdfID, 2, kdf_alg_id_ptr); +static const struct atype_info *dh_rep_info_fields[] = { + &k5_atype_dh_rep_info_0, &k5_atype_dh_rep_info_1, &k5_atype_dh_rep_info_2 +}; static unsigned int dh_rep_info_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_dh_rep_info *val = p; - if (val->serverDHNonce.length > 0) - optional |= (1u << 1); - if (val->kdfID != NULL) - optional |= (1u << 2); - return optional; + if (val->serverDHNonce.length == 0) + not_present |= (1u << 1); + if (val->kdfID == NULL) + not_present |= (1u << 2); + return not_present; } +DEFSEQTYPE(dh_rep_info, krb5_dh_rep_info, dh_rep_info_fields, + dh_rep_info_optional); -static const struct field_info dh_rep_info_fields[] = { - FIELDOF_NORM(krb5_dh_rep_info, ostring_data, dhSignedData, 0, 1), - FIELDOF_OPT(krb5_dh_rep_info, ostring_data, serverDHNonce, 1, 0, 1), - FIELDOF_OPT(krb5_dh_rep_info, kdf_alg_id_ptr, kdfID, 2, 0, 2), +DEFFIELD(dh_key_0, krb5_kdc_dh_key_info, subjectPublicKey, 0, bitstring_data); +DEFFIELD(dh_key_1, krb5_kdc_dh_key_info, nonce, 1, int32); +DEFFIELD(dh_key_2, krb5_kdc_dh_key_info, dhKeyExpiration, 2, kerberos_time); +static const struct atype_info *kdc_dh_key_info_fields[] = { + &k5_atype_dh_key_0, &k5_atype_dh_key_1, &k5_atype_dh_key_2 }; -DEFSEQTYPE(dh_rep_info, krb5_dh_rep_info, - dh_rep_info_fields, dh_rep_info_optional); - static unsigned int kdc_dh_key_info_optional(const void *p) { - unsigned int optional = 0; + unsigned int not_present = 0; const krb5_kdc_dh_key_info *val = p; - if (val->dhKeyExpiration != 0) - optional |= (1u << 2); - return optional; + if (val->dhKeyExpiration == 0) + not_present |= (1u << 2); + return not_present; } - -static const struct field_info kdc_dh_key_info_fields[] = { - FIELDOF_NORM(krb5_kdc_dh_key_info, bitstring_data, subjectPublicKey, 0, 0), - FIELDOF_NORM(krb5_kdc_dh_key_info, int32, nonce, 1, 0), - FIELDOF_OPT(krb5_kdc_dh_key_info, kerberos_time, dhKeyExpiration, 2, 0, 2), -}; DEFSEQTYPE(kdc_dh_key_info, krb5_kdc_dh_key_info, kdc_dh_key_info_fields, kdc_dh_key_info_optional); - -static const struct field_info reply_key_pack_fields[] = { - FIELDOF_NORM(krb5_reply_key_pack, encryption_key, replyKey, 0, 0), - FIELDOF_NORM(krb5_reply_key_pack, checksum, asChecksum, 1, 0), +DEFFIELD(reply_key_pack_0, krb5_reply_key_pack, replyKey, 0, encryption_key); +DEFFIELD(reply_key_pack_1, krb5_reply_key_pack, asChecksum, 1, checksum); +static const struct atype_info *reply_key_pack_fields[] = { + &k5_atype_reply_key_pack_0, &k5_atype_reply_key_pack_1 }; -DEFSEQTYPE(reply_key_pack, krb5_reply_key_pack, reply_key_pack_fields, 0); +DEFSEQTYPE(reply_key_pack, krb5_reply_key_pack, reply_key_pack_fields, NULL); -static const struct field_info reply_key_pack_draft9_fields[] = { - FIELDOF_NORM(krb5_reply_key_pack_draft9, encryption_key, replyKey, 0, 0), - FIELDOF_NORM(krb5_reply_key_pack_draft9, int32, nonce, 1, 0), +DEFFIELD(key_pack9_0, krb5_reply_key_pack_draft9, replyKey, 0, encryption_key); +DEFFIELD(key_pack9_1, krb5_reply_key_pack_draft9, nonce, 1, int32); +static const struct atype_info *reply_key_pack_draft9_fields[] = { + &k5_atype_key_pack9_0, &k5_atype_key_pack9_1 }; DEFSEQTYPE(reply_key_pack_draft9, krb5_reply_key_pack_draft9, - reply_key_pack_draft9_fields, 0); + reply_key_pack_draft9_fields, NULL); -typedef union krb5_pa_pk_as_rep_choices krb5_pa_pk_as_rep_choices; -typedef enum krb5_pa_pk_as_rep_selection krb5_pa_pk_as_rep_selection; -static const struct field_info pa_pk_as_rep_alternatives[] = { - FIELDOF_NORM(krb5_pa_pk_as_rep_choices, dh_rep_info, dh_Info, 0, 0), - FIELDOF_NORM(krb5_pa_pk_as_rep_choices, ostring_data, encKeyPack, 1, 1), +DEFFIELD(pa_pk_as_rep_0, union krb5_pa_pk_as_rep_choices, dh_Info, 0, + dh_rep_info); +DEFFIELD_IMPLICIT(pa_pk_as_rep_1, union krb5_pa_pk_as_rep_choices, encKeyPack, + 1, ostring_data); +static const struct atype_info *pa_pk_as_rep_alternatives[] = { + &k5_atype_pa_pk_as_rep_0, &k5_atype_pa_pk_as_rep_1 }; -DEFCHOICETYPE(pa_pk_as_rep_choice, krb5_pa_pk_as_rep_choices, - pa_pk_as_rep_alternatives); -DEFINTTYPE(pa_pk_as_rep_selection, krb5_pa_pk_as_rep_selection); -DEFFIELDTYPE(pa_pk_as_rep, krb5_pa_pk_as_rep, - FIELDOF_CHOICE(krb5_pa_pk_as_rep, pa_pk_as_rep_choice, u, choice, - pa_pk_as_rep_selection, -1)); +DEFCHOICETYPE(pa_pk_as_rep_choice, union krb5_pa_pk_as_rep_choices, + enum krb5_pa_pk_as_rep_selection, pa_pk_as_rep_alternatives); +DEFCOUNTEDTYPE_SIGNED(pa_pk_as_rep, krb5_pa_pk_as_rep, u, choice, + pa_pk_as_rep_choice); /* * draft-ietf-cat-kerberos-pk-init-09 specifies these alternatives as @@ -1641,23 +1567,19 @@ DEFFIELDTYPE(pa_pk_as_rep, krb5_pa_pk_as_rep, * krb5_data object; pretend that they are wrapped in IMPLICIT OCTET STRING in * order to wrap them in primitive [0] and [1] tags. */ -typedef union krb5_pa_pk_as_rep_draft9_choices -krb5_pa_pk_as_rep_draft9_choices; -typedef enum krb5_pa_pk_as_rep_draft9_selection -krb5_pa_pk_as_rep_draft9_selection; -static const struct field_info pa_pk_as_rep_draft9_alternatives[] = { - FIELDOF_NORM(krb5_pa_pk_as_rep_draft9_choices, ostring_data, dhSignedData, - 0, 1), - FIELDOF_NORM(krb5_pa_pk_as_rep_draft9_choices, ostring_data, encKeyPack, - 1, 1), -}; -DEFCHOICETYPE(pa_pk_as_rep_draft9_choice, krb5_pa_pk_as_rep_draft9_choices, +DEFFIELD_IMPLICIT(pa_pk_as_rep9_0, union krb5_pa_pk_as_rep_draft9_choices, + dhSignedData, 0, ostring_data); +DEFFIELD_IMPLICIT(pa_pk_as_rep9_1, union krb5_pa_pk_as_rep_draft9_choices, + encKeyPack, 1, ostring_data); +static const struct atype_info *pa_pk_as_rep_draft9_alternatives[] = { + &k5_atype_pa_pk_as_rep9_0, &k5_atype_pa_pk_as_rep9_1 +}; +DEFCHOICETYPE(pa_pk_as_rep_draft9_choice, + union krb5_pa_pk_as_rep_draft9_choices, + enum krb5_pa_pk_as_rep_draft9_selection, pa_pk_as_rep_draft9_alternatives); -DEFINTTYPE(pa_pk_as_rep_draft9_selection, krb5_pa_pk_as_rep_draft9_selection); -DEFFIELDTYPE(pa_pk_as_rep_draft9, krb5_pa_pk_as_rep_draft9, - FIELDOF_CHOICE(krb5_pa_pk_as_rep_draft9, - pa_pk_as_rep_draft9_choice, u, choice, - pa_pk_as_rep_draft9_selection, -1)); +DEFCOUNTEDTYPE_SIGNED(pa_pk_as_rep_draft9, krb5_pa_pk_as_rep_draft9, u, choice, + pa_pk_as_rep_draft9_choice); MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_req, pa_pk_as_req); MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_req_draft9, pa_pk_as_req_draft9); @@ -1669,8 +1591,8 @@ MAKE_FULL_ENCODER(encode_krb5_kdc_dh_key_info, kdc_dh_key_info); MAKE_FULL_ENCODER(encode_krb5_reply_key_pack, reply_key_pack); MAKE_FULL_ENCODER(encode_krb5_reply_key_pack_draft9, reply_key_pack_draft9); MAKE_FULL_ENCODER(encode_krb5_td_trusted_certifiers, - seq_of_external_principal_identifier); -MAKE_FULL_ENCODER(encode_krb5_td_dh_parameters, seq_of_algorithm_identifier); + seqof_external_principal_identifier); +MAKE_FULL_ENCODER(encode_krb5_td_dh_parameters, seqof_algorithm_identifier); #else /* DISABLE_PKINIT */ @@ -1692,12 +1614,13 @@ encode_krb5_pkinit_supp_pub_info(const krb5_pkinit_supp_pub_info *rep, #endif /* not DISABLE_PKINIT */ -static const struct field_info typed_data_fields[] = { - FIELDOF_NORM(krb5_pa_data, int32, pa_type, 0, 0), - FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 1, 0), +DEFFIELD(typed_data_0, krb5_pa_data, pa_type, 0, int32); +DEFCNFIELD(typed_data_1, krb5_pa_data, contents, length, 1, octetstring); +static const struct atype_info *typed_data_fields[] = { + &k5_atype_typed_data_0, &k5_atype_typed_data_1 }; -DEFSEQTYPE(typed_data, krb5_pa_data, typed_data_fields, 0); +DEFSEQTYPE(typed_data, krb5_pa_data, typed_data_fields, NULL); DEFPTRTYPE(typed_data_ptr, typed_data); -DEFNULLTERMSEQOFTYPE(seq_of_typed_data, typed_data_ptr); -MAKE_FULL_ENCODER(encode_krb5_typed_data, seq_of_typed_data); +DEFNULLTERMSEQOFTYPE(seqof_typed_data, typed_data_ptr); +MAKE_FULL_ENCODER(encode_krb5_typed_data, seqof_typed_data); diff --git a/src/lib/krb5/asn.1/ldap_key_seq.c b/src/lib/krb5/asn.1/ldap_key_seq.c index 1a7c9558d..6c0de20cc 100644 --- a/src/lib/krb5/asn.1/ldap_key_seq.c +++ b/src/lib/krb5/asn.1/ldap_key_seq.c @@ -51,59 +51,66 @@ * Imports from asn1_k_encode.c. * XXX Must be manually synchronized for now. */ -IMPORT_TYPE(octetstring, unsigned char *); IMPORT_TYPE(int32, krb5_int32); DEFINTTYPE(int16, krb5_int16); -DEFINTTYPE(ui_2, krb5_ui_2); -static const struct field_info krbsalt_fields[] = { - FIELDOF_NORM(krb5_key_data, int16, key_data_type[1], 0, 0), - FIELDOF_OPTSTRINGL(krb5_key_data, octetstring, key_data_contents[1], - ui_2, key_data_length[1], 1, 0, 1), +DEFCOUNTEDSTRINGTYPE(ui2_octetstring, unsigned char *, krb5_ui_2, + asn1_encode_bytestring, ASN1_OCTETSTRING); + +DEFFIELD(krbsalt_0, krb5_key_data, key_data_type[1], 0, int16); +DEFCNFIELD(krbsalt_1, krb5_key_data, key_data_contents[1], key_data_length[1], + 1, ui2_octetstring); +static const struct atype_info *krbsalt_fields[] = { + &k5_atype_krbsalt_0, &k5_atype_krbsalt_1 }; static unsigned int optional_krbsalt (const void *p) { const krb5_key_data *k = p; - unsigned int optional = 0; - - if (k->key_data_length[1] > 0) - optional |= (1u << 1); - - return optional; + unsigned int not_present = 0; + if (k->key_data_length[1] == 0) + not_present |= (1u << 1); + return not_present; } DEFSEQTYPE(krbsalt, krb5_key_data, krbsalt_fields, optional_krbsalt); -static const struct field_info encryptionkey_fields[] = { - FIELDOF_NORM(krb5_key_data, int16, key_data_type[0], 0, 0), - FIELDOF_STRINGL(krb5_key_data, octetstring, key_data_contents[0], - ui_2, key_data_length[0], 1, 0), + +DEFFIELD(encryptionkey_0, krb5_key_data, key_data_type[0], 0, int16); +DEFCNFIELD(encryptionkey_1, krb5_key_data, key_data_contents[0], + key_data_length[0], 1, ui2_octetstring); +static const struct atype_info *encryptionkey_fields[] = { + &k5_atype_encryptionkey_0, &k5_atype_encryptionkey_1 }; -DEFSEQTYPE(encryptionkey, krb5_key_data, encryptionkey_fields, 0); +DEFSEQTYPE(encryptionkey, krb5_key_data, encryptionkey_fields, NULL); -static const struct field_info key_data_fields[] = { - FIELDOF_ENCODEAS(krb5_key_data, krbsalt, 0, 0), - FIELDOF_ENCODEAS(krb5_key_data, encryptionkey, 1, 0), +DEFCTAGGEDTYPE(key_data_0, 0, krbsalt); +DEFCTAGGEDTYPE(key_data_1, 1, encryptionkey); #if 0 /* We don't support this field currently. */ - FIELDOF_blah(krb5_key_data, s2kparams, ...), +DEFCTAGGEDTYPE(key_data_2, 2, s2kparams), #endif +static const struct atype_info *key_data_fields[] = { + &k5_atype_key_data_0, &k5_atype_key_data_1 }; DEFSEQTYPE(key_data, krb5_key_data, key_data_fields, 0); DEFPTRTYPE(ptr_key_data, key_data); +DEFCOUNTEDSEQOFTYPE(cseqof_key_data, krb5_int16, ptr_key_data); -DEFFIELDTYPE(key_data_kvno, krb5_key_data, - FIELDOF_NORM(krb5_key_data, int16, key_data_kvno, -1, 0)); +DEFOFFSETTYPE(key_data_kvno, krb5_key_data, key_data_kvno, int16); DEFPTRTYPE(ptr_key_data_kvno, key_data_kvno); -static const struct field_info ldap_key_seq_fields[] = { - FIELD_INT_IMM(1, 0, 0), - FIELD_INT_IMM(1, 1, 0), - FIELDOF_NORM(ldap_seqof_key_data, ptr_key_data_kvno, key_data, 2, 0), - FIELDOF_NORM(ldap_seqof_key_data, int32, mkvno, 3, 0), /* mkvno */ - FIELDOF_SEQOF_LEN(ldap_seqof_key_data, ptr_key_data, key_data, n_key_data, - int16, 4, 0), +DEFINT_IMMEDIATE(one, 1); +DEFCTAGGEDTYPE(ldap_key_seq_0, 0, one); +DEFCTAGGEDTYPE(ldap_key_seq_1, 1, one); +DEFFIELD(ldap_key_seq_2, ldap_seqof_key_data, key_data, 2, ptr_key_data_kvno); +DEFFIELD(ldap_key_seq_3, ldap_seqof_key_data, mkvno, 3, int32); +DEFCNFIELD(ldap_key_seq_4, ldap_seqof_key_data, key_data, n_key_data, 4, + cseqof_key_data); +static const struct atype_info *ldap_key_seq_fields[] = { + &k5_atype_ldap_key_seq_0, &k5_atype_ldap_key_seq_1, + &k5_atype_ldap_key_seq_2, &k5_atype_ldap_key_seq_3, + &k5_atype_ldap_key_seq_4 }; -DEFSEQTYPE(ldap_key_seq, ldap_seqof_key_data, ldap_key_seq_fields, 0); +DEFSEQTYPE(ldap_key_seq, ldap_seqof_key_data, ldap_key_seq_fields, NULL); /* Export a function to do the whole encoding. */ MAKE_FULL_ENCODER(krb5int_ldap_encode_sequence_of_keys, ldap_key_seq); -- 2.26.2