diff options
Diffstat (limited to 'src/lib/krb5/asn.1/asn1_k_encode.c')
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.c | 2003 |
1 files changed, 1169 insertions, 834 deletions
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index e2577d8..a94ac3c 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -30,45 +30,10 @@ #include "asn1_encode.h" #include <assert.h> -/**** asn1 macros ****/ -#if 0 - How to write an asn1 encoder function using these macros: +/* helper macros - asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, - const krb5_type *val, - int *retlen) - { - asn1_setup(); - - asn1_addfield(val->last_field, n, asn1_type); - asn1_addfield(rep->next_to_last_field, n-1, asn1_type); - ... - - /* for OPTIONAL fields */ - if (rep->field_i == should_not_be_omitted) - asn1_addfield(rep->field_i, i, asn1_type); - - /* for string fields (these encoders take an additional argument, - the length of the string) */ - addlenfield(rep->field_length, rep->field, i-1, asn1_type); - - /* if you really have to do things yourself... */ - retval = asn1_encode_asn1_type(buf,rep->field,&length); - if (retval) return retval; - sum += length; - retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length, - &length); - if (retval) return retval; - sum += length; - - ... - asn1_addfield(rep->second_field, 1, asn1_type); - asn1_addfield(rep->first_field, 0, asn1_type); - asn1_makeseq(); - - asn1_cleanup(); - } -#endif + These are mostly only needed for PKINIT, but there are three + basic-krb5 encoders not converted yet. */ /* setup() -- create and initialize bookkeeping variables retval: stores error codes returned from subroutines @@ -76,942 +41,1290 @@ sum: cumulative length of the entire encoding */ #define asn1_setup()\ asn1_error_code retval;\ - unsigned int length, sum=0 - -/* asn1_addfield -- add a field, or component, to the encoding */ -#define asn1_addfield(value,tag,encoder)\ -{ retval = encoder(buf,value,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length;\ - retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length; } - -/* asn1_addlenfield -- add a field whose length must be separately specified */ -#define asn1_addlenfield(len,value,tag,encoder)\ -{ retval = encoder(buf,len,value,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length;\ - retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length; } - -/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */ -#define asn1_addfield_implicit(value,tag,encoder)\ -{ retval = encoder(buf,value,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length;\ - retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length; } - -/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */ -#define asn1_insert_implicit_octetstring(len,value,tag)\ -{ retval = asn1buf_insert_octetstring(buf,len,value);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += len;\ - retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length; } - -/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */ -#define asn1_insert_implicit_bitstring(len,value,tag)\ -{ retval = asn1buf_insert_octetstring(buf,len,value);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += len;\ - retval = asn1buf_insert_octet(buf, 0);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum++;\ - retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length; } + unsigned int sum=0 /* form a sequence (by adding a sequence header to the current encoding) */ #define asn1_makeseq()\ +{ unsigned int length;\ retval = asn1_make_sequence(buf,sum,&length);\ if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - sum += length - -/* add an APPLICATION class tag to the current encoding */ -#define asn1_apptag(num)\ - retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\ - if (retval) {\ - asn1buf_destroy(&buf);\ return retval; }\ - sum += length + sum += length; } /* produce the final output and clean up the workspace */ #define asn1_cleanup()\ *retlen = sum;\ return 0 -asn1_error_code asn1_encode_ui_4(asn1buf *buf, const krb5_ui_4 val, unsigned int *retlen) -{ - return asn1_encode_unsigned_integer(buf,val,retlen); -} - - -asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val, unsigned int *retlen) -{ - if (val == NULL || - (val->realm.length && val->realm.data == NULL)) - return ASN1_MISSING_FIELD; - return asn1_encode_generalstring(buf,val->realm.length,val->realm.data, - retlen); -} +/* asn1_addfield -- add a field, or component, to the encoding */ +#define asn1_addfield(value,tag,encoder)\ +{ unsigned int length; \ + retval = encoder(buf,value,&length); \ + if (retval) {\ + return retval; }\ + sum += length;\ + retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ + if (retval) {\ + return retval; }\ + sum += length; } -asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen) -{ - asn1_setup(); - int n; - - if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD; - - for (n = (int) ((val->length)-1); n >= 0; n--) { - if (val->data[n].length && - val->data[n].data == NULL) - return ASN1_MISSING_FIELD; - retval = asn1_encode_generalstring(buf, - (val->data)[n].length, - (val->data)[n].data, - &length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length); - if (retval) return retval; - sum += length; +DEFINTTYPE(int32, krb5_int32); +DEFPTRTYPE(int32_ptr, int32); - asn1_addfield(val->type,0,asn1_encode_integer); +DEFUINTTYPE(uint, unsigned int); +DEFUINTTYPE(octet, krb5_octet); +DEFUINTTYPE(ui_4, krb5_ui_4); - asn1_makeseq(); +DEFFNLENTYPE(octetstring, unsigned char *, asn1_encode_octetstring); +DEFFNLENTYPE(s_octetstring, char *, asn1_encode_octetstring); +DEFFNLENTYPE(charstring, char *, asn1_encode_charstring); +DEFFNLENTYPE(generalstring, char *, asn1_encode_generalstring); +DEFFNLENTYPE(u_generalstring, unsigned char *, asn1_encode_generalstring); +DEFFNLENTYPE(opaque, char *, asn1_encode_opaque); - asn1_cleanup(); -} +DEFFIELDTYPE(gstring_data, krb5_data, + FIELDOF_STRING(krb5_data, generalstring, data, length, -1)); +DEFPTRTYPE(gstring_data_ptr,gstring_data); -asn1_error_code asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen) -{ - return asn1_encode_generaltime(buf,val,retlen); -} +DEFFIELDTYPE(ostring_data, krb5_data, + FIELDOF_STRING(krb5_data, s_octetstring, data, length, -1)); +DEFPTRTYPE(ostring_data_ptr,ostring_data); -asn1_error_code asn1_encode_host_address(asn1buf *buf, const krb5_address *val, unsigned int *retlen) -{ - asn1_setup(); +DEFFIELDTYPE(opaque_data, krb5_data, + FIELDOF_STRING(krb5_data, opaque, data, length, -1)); - if (val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD; +DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, + FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1)); +DEFPTRTYPE(realm_of_principal, realm_of_principal_data); - asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); - asn1_addfield(val->addrtype,0,asn1_encode_integer); - asn1_makeseq(); - asn1_cleanup(); -} +static const struct field_info princname_fields[] = { + FIELDOF_NORM(krb5_principal_data, int32, type, 0), + FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, 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); +DEFPTRTYPE(principal, principal_data); -asn1_error_code asn1_encode_host_addresses(asn1buf *buf, const krb5_address **val, unsigned int *retlen) +static asn1_error_code +asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val, + unsigned int *retlen) { - asn1_setup(); - int i; - - if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; - - for (i=0; val[i] != NULL; i++); /* go to end of array */ - for (i--; i>=0; i--) { - retval = asn1_encode_host_address(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - - asn1_cleanup(); + /* Range checking for time_t vs krb5_timestamp? */ + time_t tval = *val; + return asn1_encode_generaltime(buf, tval, retlen); } +DEFFNXTYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at); -asn1_error_code asn1_encode_encrypted_data(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen) -{ - asn1_setup(); - - if (val == NULL || - (val->ciphertext.length && val->ciphertext.data == NULL)) - return ASN1_MISSING_FIELD; - - asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring); - /* krb5_kvno should be int */ - if (val->kvno) - asn1_addfield((int) val->kvno,1,asn1_encode_integer); - asn1_addfield(val->enctype,0,asn1_encode_integer); +const static struct field_info address_fields[] = { + FIELDOF_NORM(krb5_address, int32, addrtype, 0), + FIELDOF_STRING(krb5_address, octetstring, contents, length, 1), +}; +DEFSEQTYPE(address, krb5_address, address_fields, 0); +DEFPTRTYPE(address_ptr, address); - asn1_makeseq(); - - asn1_cleanup(); -} +DEFNULLTERMSEQOFTYPE(seq_of_host_addresses, address_ptr); +DEFPTRTYPE(ptr_seqof_host_addresses, seq_of_host_addresses); -asn1_error_code asn1_encode_krb5_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) +static unsigned int +optional_encrypted_data (const void *vptr) { - asn1_setup(); - krb5_flags valcopy = val; - int i; - - for (i=0; i<4; i++) { - retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF)); - if (retval) return retval; - valcopy >>= 8; - } - retval = asn1buf_insert_octet(buf,0); /* 0 padding bits */ - if (retval) return retval; - sum = 5; + const krb5_enc_data *val = vptr; + unsigned int optional = 0; - retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum, - &length); - if (retval) return retval; - sum += length; + if (val->kvno != 0) + optional |= (1u << 1); - *retlen = sum; - return 0; + return optional; } -asn1_error_code asn1_encode_ap_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) -{ - return asn1_encode_krb5_flags(buf,val,retlen); -} - -asn1_error_code asn1_encode_ticket_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) -{ - return asn1_encode_krb5_flags(buf,val,retlen); -} +static const struct field_info encrypted_data_fields[] = { + FIELDOF_NORM(krb5_enc_data, int32, enctype, 0), + FIELDOF_OPT(krb5_enc_data, uint, kvno, 1, 1), + FIELDOF_NORM(krb5_enc_data, ostring_data, ciphertext, 2), +}; +DEFSEQTYPE(encrypted_data, krb5_enc_data, encrypted_data_fields, + optional_encrypted_data); -asn1_error_code asn1_encode_kdc_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) +/* The encode_bitstring function wants an array of bytes (since PKINIT + may provide something that isn't 32 bits), but krb5_flags is stored + as a 32-bit integer in host order. */ +static asn1_error_code +asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val, + unsigned int *retlen) { - return asn1_encode_krb5_flags(buf,val,retlen); + unsigned char cbuf[4]; + store_32_be(*val, cbuf); + return asn1_encode_bitstring(buf, 4, cbuf, retlen); } +DEFFNXTYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at); -asn1_error_code asn1_encode_authorization_data(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen) -{ - asn1_setup(); - int i; - - if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; - - for (i=0; val[i] != NULL; i++); /* get to the end of the array */ - for (i--; i>=0; i--) { - retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - - asn1_cleanup(); -} - -asn1_error_code asn1_encode_krb5_authdata_elt(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen) -{ - asn1_setup(); - - if (val == NULL || - (val->length && val->contents == NULL)) - return ASN1_MISSING_FIELD; - - /* ad-data[1] OCTET STRING */ - asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); +const static struct field_info authdata_elt_fields[] = { /* ad-type[0] INTEGER */ - asn1_addfield(val->ad_type,0,asn1_encode_integer); - /* SEQUENCE */ - asn1_makeseq(); + FIELDOF_NORM(krb5_authdata, int32, ad_type, 0), + /* ad-data[1] OCTET STRING */ + FIELDOF_STRING(krb5_authdata, octetstring, contents, length, 1), +}; +DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields, 0); +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), + FIELDOF_STRING(krb5_keyblock, octetstring, contents, length, 1), +}; +DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields, 0); +DEFPTRTYPE(ptr_encryption_key, encryption_key); + +static const struct field_info checksum_fields[] = { + FIELDOF_NORM(krb5_checksum, int32, checksum_type, 0), + FIELDOF_STRING(krb5_checksum, octetstring, contents, length, 1), +}; +DEFSEQTYPE(checksum, krb5_checksum, checksum_fields, 0); +DEFPTRTYPE(checksum_ptr, checksum); +DEFNULLTERMSEQOFTYPE(seq_of_checksum, checksum_ptr); +DEFPTRTYPE(ptr_seqof_checksum, seq_of_checksum); + +static const struct field_info lr_fields[] = { + FIELDOF_NORM(krb5_last_req_entry, int32, lr_type, 0), + FIELDOF_NORM(krb5_last_req_entry, kerberos_time, value, 1), +}; +DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields, 0); + +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), + FIELDOF_NORM(krb5_ticket, realm_of_principal, server, 1), + FIELDOF_NORM(krb5_ticket, principal, server, 2), + FIELDOF_NORM(krb5_ticket, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields, 0); +DEFAPPTAGGEDTYPE(ticket, 1, untagged_ticket); + +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), + /* last-req[1] LastReq */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, last_req_ptr, last_req, 1), + /* nonce[2] INTEGER */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, int32, nonce, 2), + /* key-expiration[3] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, key_exp, 3, 3), + /* flags[4] TicketFlags */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, krb5_flags, flags, 4), + /* authtime[5] KerberosTime */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.authtime, 5), + /* starttime[6] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.starttime, 6, 6), + /* endtime[7] KerberosTime */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.endtime, 7), + /* renew-till[8] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.renew_till, 8, 8), + /* srealm[9] Realm */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, realm_of_principal, server, 9), + /* sname[10] PrincipalName */ + FIELDOF_NORM(krb5_enc_kdc_rep_part, principal, server, 10), + /* caddr[11] HostAddresses OPTIONAL */ + FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_host_addresses, caddrs, + 11, 11), +}; +static unsigned int optional_enc_kdc_rep_part(const void *p) +{ + const krb5_enc_kdc_rep_part *val = p; + unsigned int optional = 0; - asn1_cleanup(); + 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); + + return optional; +} +DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields, + optional_enc_kdc_rep_part); + +/* Yuck! Eventually push this *up* above the encoder API and make the + rest of the library put the realm name in one consistent place. At + 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 { + 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), + FIELDOF_OPT(struct kdc_req_hack, principal, v.client, 1, 1), + FIELDOF_NORM(struct kdc_req_hack, gstring_data_ptr, server_realm, 2), + FIELDOF_OPT(struct kdc_req_hack, principal, v.server, 3, 3), + FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.from, 4, 4), + FIELDOF_NORM(struct kdc_req_hack, kerberos_time, v.till, 5), + FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.rtime, 6, 6), + FIELDOF_NORM(struct kdc_req_hack, int32, v.nonce, 7), + FIELDOF_SEQOF_INT32(struct kdc_req_hack, int32_ptr, v.ktype, v.nktypes, 8), + FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_host_addresses, v.addresses, 9, 9), + FIELDOF_OPT(struct kdc_req_hack, encrypted_data, v.authorization_data, 10, 10), + FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_ticket, v.second_ticket, 11, 11), +}; +static unsigned int optional_kdc_req_hack(const void *p) +{ + const struct 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; +} +DEFSEQTYPE(kdc_req_body_hack, struct kdc_req_hack, kdc_req_hack_fields, + optional_kdc_req_hack); +static asn1_error_code +asn1_encode_kdc_req_hack(asn1buf *, const struct kdc_req_hack *, + unsigned int *); +MAKE_ENCFN(asn1_encode_kdc_req_hack, kdc_req_body_hack); +static asn1_error_code +asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val, + unsigned int *retlen) +{ + struct 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) { + val2.server_realm = &val->second_ticket[0]->server->realm; + } else return ASN1_MISSING_FIELD; + } else if (val->server != NULL) { + val2.server_realm = &val->server->realm; + } else return ASN1_MISSING_FIELD; + return asn1_encode_kdc_req_hack(buf, &val2, retlen); } +DEFFNXTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); +/* end ugly hack */ -asn1_error_code asn1_encode_kdc_rep(int msg_type, asn1buf *buf, const krb5_kdc_rep *val, unsigned int *retlen) -{ - asn1_setup(); +static const struct field_info transited_fields[] = { + FIELDOF_NORM(krb5_transited, octet, tr_type, 0), + FIELDOF_NORM(krb5_transited, ostring_data, tr_contents, 1), +}; +DEFSEQTYPE(transited, krb5_transited, transited_fields, 0); - if (val == NULL) return ASN1_MISSING_FIELD; +static const struct field_info pa_data_fields[] = { + FIELDOF_NORM(krb5_pa_data, int32, pa_type, 1), + FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 2), +}; +DEFSEQTYPE(pa_data, krb5_pa_data, pa_data_fields, 0); +DEFPTRTYPE(pa_data_ptr, pa_data); - asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data); - asn1_addfield(val->ticket,5,asn1_encode_ticket); - asn1_addfield(val->client,4,asn1_encode_principal_name); - asn1_addfield(val->client,3,asn1_encode_realm); - if (val->padata != NULL && val->padata[0] != NULL) - asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data); - if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP) - return KRB5_BADMSGTYPE; - asn1_addfield(msg_type,1,asn1_encode_integer); - asn1_addfield(KVNO,0,asn1_encode_integer); - asn1_makeseq(); +DEFNULLTERMSEQOFTYPE(seq_of_pa_data, pa_data_ptr); +DEFPTRTYPE(ptr_seqof_pa_data, seq_of_pa_data); - asn1_cleanup(); -} -asn1_error_code asn1_encode_enc_kdc_rep_part(asn1buf *buf, const krb5_enc_kdc_rep_part *val, unsigned int *retlen) +static const struct field_info krb_safe_body_fields[] = { + FIELDOF_NORM(krb5_safe, ostring_data, user_data, 0), + FIELDOF_OPT(krb5_safe, kerberos_time, timestamp, 1, 1), + FIELDOF_OPT(krb5_safe, int32, usec, 2, 2), + FIELDOF_OPT(krb5_safe, uint, seq_number, 3, 3), + FIELDOF_NORM(krb5_safe, address_ptr, s_address, 4), + FIELDOF_OPT(krb5_safe, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_krb_safe_body(const void *p) { - asn1_setup(); + const krb5_safe *val = p; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; + 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; +} +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), + FIELDOF_OPT(krb5_cred_info, realm_of_principal, client, 1, 1), + FIELDOF_OPT(krb5_cred_info, principal, client, 2, 2), + FIELDOF_OPT(krb5_cred_info, krb5_flags, flags, 3, 3), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.authtime, 4, 4), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.starttime, 5, 5), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.endtime, 6, 6), + FIELDOF_OPT(krb5_cred_info, kerberos_time, times.renew_till, 7, 7), + FIELDOF_OPT(krb5_cred_info, realm_of_principal, server, 8, 8), + FIELDOF_OPT(krb5_cred_info, principal, server, 9, 9), + FIELDOF_OPT(krb5_cred_info, ptr_seqof_host_addresses, caddrs, 10, 10), +}; +static unsigned int optional_krb_cred_info(const void *p) +{ + const krb5_cred_info *val = p; + unsigned int optional = 0; - /* caddr[11] HostAddresses OPTIONAL */ if (val->caddrs != NULL && val->caddrs[0] != NULL) - asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses); - - /* sname[10] PrincipalName */ - asn1_addfield(val->server,10,asn1_encode_principal_name); - - /* srealm[9] Realm */ - asn1_addfield(val->server,9,asn1_encode_realm); - - /* renew-till[8] KerberosTime OPTIONAL */ - if (val->flags & TKT_FLG_RENEWABLE) - asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time); - - /* endtime[7] KerberosTime */ - asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time); - - /* starttime[6] KerberosTime OPTIONAL */ + 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) - asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time); - - /* authtime[5] KerberosTime */ - asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time); - - /* flags[4] TicketFlags */ - asn1_addfield(val->flags,4,asn1_encode_ticket_flags); - - /* key-expiration[3] KerberosTime OPTIONAL */ - if (val->key_exp) - asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time); - - /* nonce[2] INTEGER */ - asn1_addfield(val->nonce,2,asn1_encode_integer); + 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); + } - /* last-req[1] LastReq */ - asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req); + return optional; +} +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); - /* key[0] EncryptionKey */ - asn1_addfield(val->session,0,asn1_encode_encryption_key); +DEFPTRTYPE(ptrseqof_cred_info, seq_of_cred_info); - /* EncKDCRepPart ::= SEQUENCE */ - asn1_makeseq(); - asn1_cleanup(); -} -asn1_error_code asn1_encode_sequence_of_checksum(asn1buf *buf, const krb5_checksum ** val, unsigned int *retlen) +static unsigned int +optional_etype_info_entry(const void *vptr) { - asn1_setup(); - int i; + const krb5_etype_info_entry *val = vptr; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; + if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT) + optional |= (1u << 1); - for (i=0; val[i] != NULL; i++); - for (i--; i>=0; i--) { - retval = asn1_encode_checksum(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - - asn1_cleanup(); + return optional; } +static const struct field_info etype_info_entry_fields[] = { + FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0), + FIELDOF_OPTSTRING(krb5_etype_info_entry, octetstring, salt, length, 1, 1), +}; +DEFSEQTYPE(etype_info_entry, krb5_etype_info_entry, etype_info_entry_fields, + optional_etype_info_entry); -asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *rep, unsigned int *retlen) +static unsigned int +optional_etype_info2_entry(const void *vptr) { - asn1_setup(); - - if (rep == NULL) return ASN1_MISSING_FIELD; + const krb5_etype_info_entry *val = vptr; + unsigned int optional = 0; - /* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */ - if (rep->second_ticket != NULL && rep->second_ticket[0] != NULL) - asn1_addfield((const krb5_ticket**)rep->second_ticket, - 11,asn1_encode_sequence_of_ticket); + if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT) + optional |= (1u << 1); + if (val->s2kparams.data) + optional |= (1u << 2); - /* enc-authorization-data[10] EncryptedData OPTIONAL, */ - /* -- Encrypted AuthorizationData encoding */ - if (rep->authorization_data.ciphertext.data != NULL) - asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data); - - /* addresses[9] HostAddresses OPTIONAL, */ - if (rep->addresses != NULL && rep->addresses[0] != NULL) - asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses); - - /* etype[8] SEQUENCE OF INTEGER, -- EncryptionType, */ - /* -- in preference order */ - asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype); - - /* nonce[7] INTEGER, */ - asn1_addfield(rep->nonce,7,asn1_encode_integer); - - /* rtime[6] KerberosTime OPTIONAL, */ - if (rep->rtime) - asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time); - - /* till[5] KerberosTime, */ - asn1_addfield(rep->till,5,asn1_encode_kerberos_time); + return optional; +} - /* from[4] KerberosTime OPTIONAL, */ - if (rep->from) - asn1_addfield(rep->from,4,asn1_encode_kerberos_time); +static const struct field_info etype_info2_entry_fields[] = { + FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0), + FIELDOF_OPTSTRING(krb5_etype_info_entry, u_generalstring, salt, length, + 1, 1), + FIELDOF_OPT(krb5_etype_info_entry, ostring_data, s2kparams, 2, 2), +}; +DEFSEQTYPE(etype_info2_entry, krb5_etype_info_entry, etype_info2_entry_fields, + optional_etype_info2_entry); - /* sname[3] PrincipalName OPTIONAL, */ - if (rep->server != NULL) - asn1_addfield(rep->server,3,asn1_encode_principal_name); +DEFPTRTYPE(etype_info_entry_ptr, etype_info_entry); +DEFNULLTERMSEQOFTYPE(etype_info, etype_info_entry_ptr); - /* realm[2] Realm, -- Server's realm */ - /* -- Also client's in AS-REQ */ - if (rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { - if (rep->second_ticket != NULL && rep->second_ticket[0] != NULL) { - asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm) - } else return ASN1_MISSING_FIELD; - } else if (rep->server != NULL) { - asn1_addfield(rep->server,2,asn1_encode_realm); - } else return ASN1_MISSING_FIELD; +DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry); +DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr); - /* cname[1] PrincipalName OPTIONAL, */ - /* -- Used only in AS-REQ */ - if (rep->client != NULL) - asn1_addfield(rep->client,1,asn1_encode_principal_name); +static const struct field_info passwdsequence_fields[] = { + FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, passwd, 0), + FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, phrase, 1), +}; +DEFSEQTYPE(passwdsequence, passwd_phrase_element, passwdsequence_fields, 0); - /* kdc-options[0] KDCOptions, */ - asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options); +DEFPTRTYPE(passwdsequence_ptr, passwdsequence); +DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_passwdsequence, passwdsequence_ptr); +DEFPTRTYPE(ptr_seqof_passwdsequence, seqof_passwdsequence); - /* KDC-REQ-BODY ::= SEQUENCE */ - asn1_makeseq(); - - asn1_cleanup(); -} -asn1_error_code asn1_encode_encryption_key(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen) +static const struct field_info sam_challenge_fields[] = { + FIELDOF_NORM(krb5_sam_challenge, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_challenge, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_type_name, 2, 2), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_track_id,3, 3), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge_label,4, 4), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge,5, 5), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_response_prompt,6, 6), + FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_pk_for_sad,7, 7), + FIELDOF_OPT(krb5_sam_challenge, int32, sam_nonce, 8, 8), + FIELDOF_OPT(krb5_sam_challenge, checksum, sam_cksum, 9, 9), +}; +static unsigned int optional_sam_challenge(const void *p) { - asn1_setup(); - - if (val == NULL || - (val->length && val->contents == NULL)) - return ASN1_MISSING_FIELD; - - asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); - asn1_addfield(val->enctype,0,asn1_encode_integer); - asn1_makeseq(); + const krb5_sam_challenge *val = p; + unsigned int optional = 0; - asn1_cleanup(); -} - -asn1_error_code asn1_encode_checksum(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen) -{ - asn1_setup(); + if (val->sam_cksum.length) + optional |= (1u << 9); - if (val == NULL || - (val->length && val->contents == NULL)) - return ASN1_MISSING_FIELD; + if (val->sam_nonce) + optional |= (1u << 8); - asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); - asn1_addfield(val->checksum_type,0,asn1_encode_integer); - asn1_makeseq(); + 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); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(sam_challenge,krb5_sam_challenge,sam_challenge_fields, + optional_sam_challenge); -asn1_error_code asn1_encode_transited_encoding(asn1buf *buf, const krb5_transited *val, unsigned int *retlen) +#if 0 /* encoders not used! */ +MAKE_ENCFN(asn1_encode_sequence_of_checksum, seq_of_checksum); +static asn1_error_code +asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, + unsigned int *retlen) { asn1_setup(); - - if (val == NULL || - (val->tr_contents.length != 0 && val->tr_contents.data == NULL)) + if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0])) return ASN1_MISSING_FIELD; - asn1_addlenfield(val->tr_contents.length,val->tr_contents.data, - 1,asn1_encode_charstring); - asn1_addfield(val->tr_type,0,asn1_encode_integer); - asn1_makeseq(); - - asn1_cleanup(); -} - -asn1_error_code asn1_encode_last_req(asn1buf *buf, const krb5_last_req_entry **val, unsigned int *retlen) -{ - asn1_setup(); - int i; + asn1_addfield(val->sam_cksum, 1, asn1_encode_sequence_of_checksum); - if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + { + unsigned int length; - for (i=0; val[i] != NULL; i++); /* go to end of array */ - for (i--; i>=0; i--) { - retval = asn1_encode_last_req_entry(buf,val[i],&length); - if (retval) return retval; + retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length, + (unsigned char *)val->sam_challenge_2_body.data); + if (retval) { + return retval; + } + sum += val->sam_challenge_2_body.length; + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, + val->sam_challenge_2_body.length, &length); + if (retval) { + return retval; + } sum += length; } - asn1_makeseq(); - - asn1_cleanup(); -} -asn1_error_code asn1_encode_last_req_entry(asn1buf *buf, const krb5_last_req_entry *val, unsigned int *retlen) -{ - asn1_setup(); - - if (val == NULL) return ASN1_MISSING_FIELD; - - asn1_addfield(val->value,1,asn1_encode_kerberos_time); - asn1_addfield(val->lr_type,0,asn1_encode_integer); asn1_makeseq(); - asn1_cleanup(); } +DEFFNXTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2); + +static const struct field_info sam_challenge_2_body_fields[] = { + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_challenge_2_body, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_type_name, 2, 2), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_track_id,3, 3), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge_label,4, 4), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge,5, 5), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_response_prompt,6, 6), + FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_pk_for_sad,7, 7), + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_nonce, 8), + FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_etype, 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; +} +DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body,sam_challenge_2_body_fields, + optional_sam_challenge_2_body); +#endif -asn1_error_code asn1_encode_sequence_of_pa_data(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen) -{ - asn1_setup(); - int i; - - if (val == NULL) return ASN1_MISSING_FIELD; - - for (i=0; val[i] != NULL; i++); - for (i--; i>=0; i--) { - retval = asn1_encode_pa_data(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - - asn1_cleanup(); -} +static const struct field_info sam_key_fields[] = { + FIELDOF_NORM(krb5_sam_key, encryption_key, sam_key, 0), +}; +DEFSEQTYPE(sam_key, krb5_sam_key, sam_key_fields, 0); -asn1_error_code asn1_encode_pa_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen) +static const struct field_info enc_sam_response_enc_fields[] = { + FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_nonce, 0), + FIELDOF_NORM(krb5_enc_sam_response_enc, kerberos_time, sam_timestamp, 1), + FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_usec, 2), + FIELDOF_OPT(krb5_enc_sam_response_enc, ostring_data, sam_sad, 3, 3), +}; +static unsigned int optional_enc_sam_response_enc(const void *p) { - asn1_setup(); + const krb5_enc_sam_response_enc *val = p; + unsigned int optional = 0; - if (val == NULL || (val->length != 0 && val->contents == NULL)) - return ASN1_MISSING_FIELD; - - asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring); - asn1_addfield(val->pa_type,1,asn1_encode_integer); - asn1_makeseq(); + if (val->sam_sad.length > 0) optional |= (1u << 3); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(enc_sam_response_enc, krb5_enc_sam_response_enc, + enc_sam_response_enc_fields, optional_enc_sam_response_enc); -asn1_error_code asn1_encode_sequence_of_ticket(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen) +static const struct field_info enc_sam_response_enc_2_fields[] = { + FIELDOF_NORM(krb5_enc_sam_response_enc_2, int32, sam_nonce, 0), + FIELDOF_OPT(krb5_enc_sam_response_enc_2, ostring_data, sam_sad, 1, 1), +}; +static unsigned int optional_enc_sam_response_enc_2(const void *p) { - asn1_setup(); - int i; - - if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + const krb5_enc_sam_response_enc_2 *val = p; + unsigned int optional = 0; - for (i=0; val[i] != NULL; i++); - for (i--; i>=0; i--) { - retval = asn1_encode_ticket(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); + if (val->sam_sad.length > 0) optional |= (1u << 1); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(enc_sam_response_enc_2, krb5_enc_sam_response_enc_2, + enc_sam_response_enc_2_fields, optional_enc_sam_response_enc_2); -asn1_error_code asn1_encode_ticket(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen) +static const struct field_info sam_response_fields[] = { + FIELDOF_NORM(krb5_sam_response, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_response, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_response, ostring_data, sam_track_id, 2, 2), + FIELDOF_OPT(krb5_sam_response, encrypted_data, sam_enc_key, 3, 3), + FIELDOF_NORM(krb5_sam_response, encrypted_data, sam_enc_nonce_or_ts, 4), + FIELDOF_OPT(krb5_sam_response, int32, sam_nonce, 5, 5), + FIELDOF_OPT(krb5_sam_response, kerberos_time, sam_patimestamp, 6, 6), +}; +static unsigned int optional_sam_response(const void *p) { - asn1_setup(); - - if (val == NULL) return ASN1_MISSING_FIELD; + const krb5_sam_response *val = p; + unsigned int optional = 0; - asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data); - asn1_addfield(val->server,2,asn1_encode_principal_name); - asn1_addfield(val->server,1,asn1_encode_realm); - asn1_addfield(KVNO,0,asn1_encode_integer); - asn1_makeseq(); - asn1_apptag(1); + if (val->sam_patimestamp) + optional |= (1u << 6); + if (val->sam_nonce) + optional |= (1u << 5); + if (val->sam_enc_key.ciphertext.length) + optional |= (1u << 3); + if (val->sam_track_id.length > 0) optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(sam_response, krb5_sam_response, sam_response_fields, + optional_sam_response); + +static const struct field_info sam_response_2_fields[] = { + FIELDOF_NORM(krb5_sam_response_2, int32, sam_type, 0), + FIELDOF_NORM(krb5_sam_response_2, krb5_flags, sam_flags, 1), + FIELDOF_OPT(krb5_sam_response_2, ostring_data, sam_track_id, 2, 2), + FIELDOF_NORM(krb5_sam_response_2, encrypted_data, sam_enc_nonce_or_sad, 3), + FIELDOF_NORM(krb5_sam_response_2, int32, sam_nonce, 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; +} +DEFSEQTYPE(sam_response_2, krb5_sam_response_2, sam_response_2_fields, + optional_sam_response_2); + +static const struct field_info predicted_sam_response_fields[] = { + FIELDOF_NORM(krb5_predicted_sam_response, encryption_key, sam_key, 0), + FIELDOF_NORM(krb5_predicted_sam_response, krb5_flags, sam_flags, 1), + FIELDOF_NORM(krb5_predicted_sam_response, kerberos_time, stime, 2), + FIELDOF_NORM(krb5_predicted_sam_response, int32, susec, 3), + FIELDOF_NORM(krb5_predicted_sam_response, realm_of_principal, client, 4), + FIELDOF_NORM(krb5_predicted_sam_response, principal, client, 5), + FIELDOF_OPT(krb5_predicted_sam_response, ostring_data, msd, 6, 6), +}; +static unsigned int optional_predicted_sam_response(const void *p) +{ + const krb5_predicted_sam_response *val = p; + unsigned int optional = 0; + + if (val->msd.length > 0) optional |= (1u << 6); + + return optional; +} +DEFSEQTYPE(predicted_sam_response, krb5_predicted_sam_response, + predicted_sam_response_fields, + optional_predicted_sam_response); + +static const struct field_info krb5_authenticator_fields[] = { + /* Authenticator ::= [APPLICATION 2] SEQUENCE */ + /* authenticator-vno[0] INTEGER */ + FIELD_INT_IMM(KVNO, 0), + /* crealm[1] Realm */ + FIELDOF_NORM(krb5_authenticator, realm_of_principal, client, 1), + /* cname[2] PrincipalName */ + FIELDOF_NORM(krb5_authenticator, principal, client, 2), + /* cksum[3] Checksum OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, checksum_ptr, checksum, 3, 3), + /* cusec[4] INTEGER */ + FIELDOF_NORM(krb5_authenticator, int32, cusec, 4), + /* ctime[5] KerberosTime */ + FIELDOF_NORM(krb5_authenticator, kerberos_time, ctime, 5), + /* subkey[6] EncryptionKey OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, ptr_encryption_key, subkey, 6, 6), + /* seq-number[7] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, uint, seq_number, 7, 7), + /* authorization-data[8] AuthorizationData OPTIONAL */ + FIELDOF_OPT(krb5_authenticator, auth_data_ptr, authorization_data, 8, 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; +} +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), + /* key[1] EncryptionKey */ + FIELDOF_NORM(krb5_enc_tkt_part, ptr_encryption_key, session, 1), + /* crealm[2] Realm */ + FIELDOF_NORM(krb5_enc_tkt_part, realm_of_principal, client, 2), + /* cname[3] PrincipalName */ + FIELDOF_NORM(krb5_enc_tkt_part, principal, client, 3), + /* transited[4] TransitedEncoding */ + FIELDOF_NORM(krb5_enc_tkt_part, transited, transited, 4), + /* authtime[5] KerberosTime */ + FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.authtime, 5), + /* starttime[6] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.starttime, 6, 6), + /* endtime[7] KerberosTime */ + FIELDOF_NORM(krb5_enc_tkt_part, kerberos_time, times.endtime, 7), + /* renew-till[8] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, kerberos_time, times.renew_till, 8, 8), + /* caddr[9] HostAddresses OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, ptr_seqof_host_addresses, caddrs, 9, 9), + /* authorization-data[10] AuthorizationData OPTIONAL */ + FIELDOF_OPT(krb5_enc_tkt_part, auth_data_ptr, authorization_data, 10, 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); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(untagged_enc_tkt_part, krb5_enc_tkt_part, enc_tkt_part_fields, + optional_enc_tkt_part); +DEFAPPTAGGEDTYPE(enc_tkt_part, 3, untagged_enc_tkt_part); -asn1_error_code asn1_encode_sequence_of_enctype(asn1buf *buf, const int len, const krb5_enctype *val, unsigned int *retlen) -{ - asn1_setup(); - int i; - - if (val == NULL) return ASN1_MISSING_FIELD; - - for (i=len-1; i>=0; i--) { - retval = asn1_encode_integer(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - - asn1_cleanup(); -} +DEFAPPTAGGEDTYPE(enc_tgs_rep_part, 26, enc_kdc_rep_part); -asn1_error_code asn1_encode_kdc_req(int msg_type, asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen) +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), + FIELD_INT_IMM(KRB5_AS_REP, 1), + FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 2), + FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3), + FIELDOF_NORM(krb5_kdc_rep, principal, client, 4), + FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5), + FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6), +}; +static unsigned int optional_as_rep(const void *p) { - asn1_setup(); + const krb5_kdc_rep *val = p; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; - - asn1_addfield(val,4,asn1_encode_kdc_req_body); if (val->padata != NULL && val->padata[0] != NULL) - asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data); - if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ) - return KRB5_BADMSGTYPE; - asn1_addfield(msg_type,2,asn1_encode_integer); - asn1_addfield(KVNO,1,asn1_encode_integer); - asn1_makeseq(); + optional |= (1u << 2); + + return optional; +} +DEFSEQTYPE(untagged_as_rep, krb5_kdc_rep, as_rep_fields, optional_as_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), + FIELD_INT_IMM(KRB5_TGS_REP, 1), + FIELDOF_OPT(krb5_kdc_rep, ptr_seqof_pa_data, padata, 2, 2), + FIELDOF_NORM(krb5_kdc_rep, realm_of_principal, client, 3), + FIELDOF_NORM(krb5_kdc_rep, principal, client, 4), + FIELDOF_NORM(krb5_kdc_rep, ticket_ptr, ticket, 5), + FIELDOF_NORM(krb5_kdc_rep, encrypted_data, enc_part, 6), +}; +static unsigned int optional_tgs_rep(const void *p) +{ + const krb5_kdc_rep *val = p; + unsigned int optional = 0; - asn1_cleanup(); -} - -asn1_error_code asn1_encode_krb_safe_body(asn1buf *buf, const krb5_safe *val, unsigned int *retlen) -{ - asn1_setup(); - - if (val == NULL) return ASN1_MISSING_FIELD; + 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); +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), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_AP_REQ, 1), + /* ap-options[2] APOptions */ + FIELDOF_NORM(krb5_ap_req, krb5_flags, ap_options, 2), + /* ticket[3] Ticket */ + FIELDOF_NORM(krb5_ap_req, ticket_ptr, ticket, 3), + /* authenticator[4] EncryptedData */ + FIELDOF_NORM(krb5_ap_req, encrypted_data, authenticator, 4), +}; +DEFSEQTYPE(untagged_ap_req, krb5_ap_req, ap_req_fields, 0); +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), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_AP_REP, 1), + /* enc-part[2] EncryptedData */ + FIELDOF_NORM(krb5_ap_rep, encrypted_data, enc_part, 2), +}; +DEFSEQTYPE(untagged_ap_rep, krb5_ap_rep, ap_rep_fields, 0); +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), + /* cusec[1] INTEGER */ + FIELDOF_NORM(krb5_ap_rep_enc_part, int32, cusec, 1), + /* subkey[2] EncryptionKey OPTIONAL */ + FIELDOF_OPT(krb5_ap_rep_enc_part, ptr_encryption_key, subkey, 2, 2), + /* seq-number[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_ap_rep_enc_part, uint, seq_number, 3, 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->r_address != NULL) - asn1_addfield(val->r_address,5,asn1_encode_host_address); - asn1_addfield(val->s_address,4,asn1_encode_host_address); if (val->seq_number) - asn1_addfield(val->seq_number,3,asn1_encode_unsigned_integer); - if (val->timestamp) { - asn1_addfield(val->usec,2,asn1_encode_integer); - asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time); - } - if (val->user_data.length && val->user_data.data == NULL) - return ASN1_MISSING_FIELD; - asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring) - ; + optional |= (1u << 3); + if (val->subkey != NULL) + optional |= (1u << 2); - asn1_makeseq(); - asn1_cleanup(); + return optional; } +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); -asn1_error_code asn1_encode_sequence_of_krb_cred_info(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen) +static const struct field_info as_req_fields[] = { + /* AS-REQ ::= [APPLICATION 10] KDC-REQ */ + FIELD_INT_IMM(KVNO, 1), + FIELD_INT_IMM(KRB5_AS_REQ, 2), + FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 3), + FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4), +}; +static unsigned int optional_as_req(const void *p) { - asn1_setup(); - int i; + const krb5_kdc_req *val = p; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; - - for (i=0; val[i] != NULL; i++); - for (i--; i>=0; i--) { - retval = asn1_encode_krb_cred_info(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); + if (val->padata != NULL && val->padata[0] != NULL) + optional |= (1u << 3); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(untagged_as_req, krb5_kdc_req, as_req_fields, optional_as_req); +DEFAPPTAGGEDTYPE(as_req, 10, untagged_as_req); -asn1_error_code asn1_encode_krb_cred_info(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen) +static const struct field_info tgs_req_fields[] = { + /* TGS-REQ ::= [APPLICATION 12] KDC-REQ */ + FIELD_INT_IMM(KVNO, 1), + FIELD_INT_IMM(KRB5_TGS_REQ, 2), + FIELDOF_OPT(krb5_kdc_req, ptr_seqof_pa_data, padata, 3, 3), + FIELDOF_ENCODEAS(krb5_kdc_req, kdc_req_body, 4), +}; +static unsigned int optional_tgs_req(const void *p) { - asn1_setup(); + const krb5_kdc_req *val = p; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; + 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); +DEFAPPTAGGEDTYPE(tgs_req, 12, untagged_tgs_req); + +static const struct field_info krb5_safe_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(ASN1_KRB_SAFE,1), + FIELD_SELF(krb_safe_body, 2), + FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, 3), +}; +DEFSEQTYPE(untagged_krb5_safe, krb5_safe, krb5_safe_fields, 0); +DEFAPPTAGGEDTYPE(krb5_safe, 20, untagged_krb5_safe); + +DEFPTRTYPE(krb_saved_safe_body_ptr, opaque_data); +DEFFIELDTYPE(krb5_safe_checksum_only, krb5_safe, + FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, -1)); +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), + FIELD_INT_IMM(ASN1_KRB_SAFE,1), + FIELDOF_NORM(struct krb5_safe_with_body, krb_saved_safe_body_ptr, body, 2), + FIELDOF_NORM(struct krb5_safe_with_body, krb5_safe_checksum_only_ptr, safe, 3), +}; +DEFSEQTYPE(untagged_krb5_safe_with_body, struct krb5_safe_with_body, + krb5_safe_with_body_fields, 0); +DEFAPPTAGGEDTYPE(krb5_safe_with_body, 20, untagged_krb5_safe_with_body); + +static const struct field_info priv_fields[] = { + FIELD_INT_IMM(KVNO, 0), + FIELD_INT_IMM(ASN1_KRB_PRIV, 1), + FIELDOF_NORM(krb5_priv, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_priv, krb5_priv, priv_fields, 0); +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), + FIELDOF_OPT(krb5_priv_enc_part, kerberos_time, timestamp, 1, 1), + FIELDOF_OPT(krb5_priv_enc_part, int32, usec, 2, 2), + FIELDOF_OPT(krb5_priv_enc_part, uint, seq_number, 3, 3), + FIELDOF_NORM(krb5_priv_enc_part, address_ptr, s_address, 4), + FIELDOF_OPT(krb5_priv_enc_part, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_priv_enc_part(const void *p) +{ + const krb5_priv_enc_part *val = p; + unsigned int optional = 0; - if (val->caddrs != NULL && val->caddrs[0] != NULL) - asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses); - if (val->server != NULL) { - asn1_addfield(val->server,9,asn1_encode_principal_name); - asn1_addfield(val->server,8,asn1_encode_realm); - } - if (val->times.renew_till) - asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time); - if (val->times.endtime) - asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time); - if (val->times.starttime) - asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time); - if (val->times.authtime) - asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time); - if (val->flags) - asn1_addfield(val->flags,3,asn1_encode_ticket_flags); - if (val->client != NULL) { - asn1_addfield(val->client,2,asn1_encode_principal_name); - asn1_addfield(val->client,1,asn1_encode_realm); + if (val->timestamp) { + optional |= (1u << 2); + optional |= (1u << 1); } - asn1_addfield(val->session,0,asn1_encode_encryption_key); + if (val->seq_number) + optional |= (1u << 3); + if (val->r_address) + optional |= (1u << 5); + + return optional; +} +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), + /* msg-type[1] INTEGER, -- KRB_CRED */ + FIELD_INT_IMM(ASN1_KRB_CRED, 1), + /* tickets[2] SEQUENCE OF Ticket */ + FIELDOF_NORM(krb5_cred, ptr_seqof_ticket, tickets, 2), + /* enc-part[3] EncryptedData */ + FIELDOF_NORM(krb5_cred, encrypted_data, enc_part, 3), +}; +DEFSEQTYPE(untagged_cred, krb5_cred, cred_fields, 0); +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), + /* nonce[1] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, int32, nonce, 1, 1), + /* timestamp[2] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, kerberos_time, timestamp, 2, 2), + /* usec[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, int32, usec, 3, 3), + /* s-address[4] HostAddress OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, address_ptr, s_address, 4, 4), + /* r-address[5] HostAddress OPTIONAL */ + FIELDOF_OPT(krb5_cred_enc_part, address_ptr, r_address, 5, 5), +}; +static unsigned int optional_enc_cred_part(const void *p) +{ + const krb5_cred_enc_part *val = p; + unsigned int optional = 0; - asn1_makeseq(); + if (val->r_address != NULL) + optional |= (1u << 5); - asn1_cleanup(); -} + if (val->s_address != NULL) + optional |= (1u << 4); -asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info_entry *val, - unsigned int *retlen, int etype_info2) -{ - asn1_setup(); + if (val->timestamp) { + optional |= (1u << 2); + optional |= (1u << 3); + } - assert(val->s2kparams.data == NULL || etype_info2); - if (val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT && - val->salt == NULL)) - return ASN1_MISSING_FIELD; - if (val->s2kparams.data != NULL) - asn1_addlenfield(val->s2kparams.length, val->s2kparams.data, 2, - asn1_encode_octetstring); - if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT) { - if (etype_info2) { - asn1_addlenfield(val->length,val->salt,1, - asn1_encode_generalstring); - } else { - asn1_addlenfield(val->length,val->salt,1, - asn1_encode_octetstring); - } + if (val->nonce) + optional |= (1u << 1); + + return optional; +} +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), + /* msg-type[1] INTEGER */ + FIELD_INT_IMM(ASN1_KRB_ERROR, 1), + /* ctime[2] KerberosTime OPTIONAL */ + FIELDOF_OPT(krb5_error, kerberos_time, ctime, 2, 2), + /* cusec[3] INTEGER OPTIONAL */ + FIELDOF_OPT(krb5_error, int32, cusec, 3, 3), + /* stime[4] KerberosTime */ + FIELDOF_NORM(krb5_error, kerberos_time, stime, 4), + /* susec[5] INTEGER */ + FIELDOF_NORM(krb5_error, int32, susec, 5), + /* error-code[6] INTEGER */ + FIELDOF_NORM(krb5_error, ui_4, error, 6), + /* crealm[7] Realm OPTIONAL */ + FIELDOF_OPT(krb5_error, realm_of_principal, client, 7, 7), + /* cname[8] PrincipalName OPTIONAL */ + FIELDOF_OPT(krb5_error, principal, client, 8, 8), + /* realm[9] Realm -- Correct realm */ + FIELDOF_NORM(krb5_error, realm_of_principal, server, 9), + /* sname[10] PrincipalName -- Correct name */ + FIELDOF_NORM(krb5_error, principal, server, 10), + /* e-text[11] GeneralString OPTIONAL */ + FIELDOF_OPT(krb5_error, gstring_data, text, 11, 11), + /* e-data[12] OCTET STRING OPTIONAL */ + FIELDOF_OPT(krb5_error, ostring_data, e_data, 12, 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); } - asn1_addfield(val->etype,0,asn1_encode_integer); - asn1_makeseq(); + 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); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(untagged_krb5_error, krb5_error, error_fields, optional_error); +DEFAPPTAGGEDTYPE(krb5_error, 30, untagged_krb5_error); -asn1_error_code asn1_encode_etype_info(asn1buf *buf, const krb5_etype_info_entry **val, - unsigned int *retlen, int etype_info2) +static const struct field_info alt_method_fields[] = { + FIELDOF_NORM(krb5_alt_method, int32, method, 0), + FIELDOF_OPTSTRING(krb5_alt_method, octetstring, data, length, 1, 1), +}; +static unsigned int +optional_alt_method(const void *p) { - asn1_setup(); - int i; + const krb5_alt_method *a = p; + unsigned int optional = 0; - if (val == NULL) return ASN1_MISSING_FIELD; + if (a->data != NULL && a->length > 0) + optional |= (1u << 1); - for (i=0; val[i] != NULL; i++); /* get to the end of the array */ - for (i--; i>=0; i--) { - retval = asn1_encode_etype_info_entry(buf,val[i],&length, etype_info2); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - asn1_cleanup(); + return optional; } +DEFSEQTYPE(alt_method, krb5_alt_method, alt_method_fields, optional_alt_method); -asn1_error_code asn1_encode_sequence_of_passwdsequence(asn1buf *buf, const passwd_phrase_element **val, unsigned int *retlen) +static const struct field_info pa_enc_ts_fields[] = { + FIELDOF_NORM(krb5_pa_enc_ts, kerberos_time, patimestamp, 0), + FIELDOF_OPT(krb5_pa_enc_ts, int32, pausec, 1, 1), +}; +static unsigned int +optional_pa_enc_ts(const void *p) { - asn1_setup(); - int i; - - if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; - - for (i=0; val[i] != NULL; i++); /* get to the end of the array */ - for (i--; i>=0; i--) { - retval = asn1_encode_passwdsequence(buf,val[i],&length); - if (retval) return retval; - sum += length; - } - asn1_makeseq(); - asn1_cleanup(); -} + const krb5_pa_enc_ts *val = p; + unsigned int optional = 0; -asn1_error_code asn1_encode_passwdsequence(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen) -{ - asn1_setup(); - asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring); - asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring); - asn1_makeseq(); - asn1_cleanup(); -} + if (val->pausec) + optional |= (1u << 1); -asn1_error_code asn1_encode_sam_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) -{ - return asn1_encode_krb5_flags(buf,val,retlen); + return optional; } +DEFSEQTYPE(pa_enc_ts, krb5_pa_enc_ts, pa_enc_ts_fields, optional_pa_enc_ts); -#define add_optstring(val,n,fn) \ - if ((val).length > 0) {asn1_addlenfield((val).length,(val).data,n,fn);} - -asn1_error_code asn1_encode_sam_challenge(asn1buf *buf, const krb5_sam_challenge *val, unsigned int *retlen) -{ - asn1_setup(); - /* possibly wrong */ - if (val->sam_cksum.length) - asn1_addfield(&(val->sam_cksum),9,asn1_encode_checksum); - - if (val->sam_nonce) - asn1_addfield(val->sam_nonce,8,asn1_encode_integer); - - add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); - add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); - add_optstring(val->sam_challenge,5,asn1_encode_charstring); - add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); - add_optstring(val->sam_track_id,3,asn1_encode_charstring); - add_optstring(val->sam_type_name,2,asn1_encode_charstring); - - asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); - asn1_addfield(val->sam_type,0,asn1_encode_integer); +static const struct field_info pwd_data_fields[] = { + FIELDOF_NORM(krb5_pwd_data, int32, sequence_count, 0), + FIELDOF_NORM(krb5_pwd_data, ptr_seqof_passwdsequence, element, 1), +}; +DEFSEQTYPE(pwd_data, krb5_pwd_data, pwd_data_fields, 0); - asn1_makeseq(); - asn1_cleanup(); -} +static const struct field_info setpw_req_fields[] = { + FIELDOF_NORM(struct krb5_setpw_req, ostring_data, password, 0), + FIELDOF_NORM(struct krb5_setpw_req, principal, target, 1), + FIELDOF_NORM(struct krb5_setpw_req, realm_of_principal, target, 2), +}; -asn1_error_code asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, unsigned int *retlen) -{ - asn1_setup(); - if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0])) - return ASN1_MISSING_FIELD; +DEFSEQTYPE(setpw_req, struct krb5_setpw_req, setpw_req_fields, 0); - asn1_addfield((const krb5_checksum **) val->sam_cksum, 1, asn1_encode_sequence_of_checksum); - retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length, - (unsigned char *)val->sam_challenge_2_body.data); - if (retval) { - asn1buf_destroy(&buf); - return retval; - } - sum += val->sam_challenge_2_body.length; - retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, - val->sam_challenge_2_body.length, &length); - if (retval) { - asn1buf_destroy(&buf); - return retval; - } - sum += length; - asn1_makeseq(); - asn1_cleanup(); -} -asn1_error_code asn1_encode_sam_challenge_2_body(asn1buf *buf, const krb5_sam_challenge_2_body *val, unsigned int *retlen) -{ - asn1_setup(); +/* Exported complete encoders -- these produce a krb5_data with + the encoding in the correct byte order. */ - asn1_addfield(val->sam_etype, 9, asn1_encode_integer); - asn1_addfield(val->sam_nonce,8,asn1_encode_integer); - add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); - add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); - add_optstring(val->sam_challenge,5,asn1_encode_charstring); - add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); - add_optstring(val->sam_track_id,3,asn1_encode_charstring); - add_optstring(val->sam_type_name,2,asn1_encode_charstring); +MAKE_FULL_ENCODER(encode_krb5_authenticator, krb5_authenticator); +MAKE_FULL_ENCODER(encode_krb5_ticket, ticket); +MAKE_FULL_ENCODER(encode_krb5_encryption_key, encryption_key); +MAKE_FULL_ENCODER(encode_krb5_enc_tkt_part, enc_tkt_part); +/* XXX We currently (for backwards compatibility) encode both + EncASRepPart and EncTGSRepPart with application tag 26. */ +MAKE_FULL_ENCODER(encode_krb5_enc_kdc_rep_part, enc_tgs_rep_part); +MAKE_FULL_ENCODER(encode_krb5_as_rep, as_rep); +MAKE_FULL_ENCODER(encode_krb5_tgs_rep, tgs_rep); +MAKE_FULL_ENCODER(encode_krb5_ap_req, ap_req); +MAKE_FULL_ENCODER(encode_krb5_ap_rep, ap_rep); +MAKE_FULL_ENCODER(encode_krb5_ap_rep_enc_part, ap_rep_enc_part); +MAKE_FULL_ENCODER(encode_krb5_as_req, as_req); +MAKE_FULL_ENCODER(encode_krb5_tgs_req, tgs_req); +MAKE_FULL_ENCODER(encode_krb5_kdc_req_body, kdc_req_body); +MAKE_FULL_ENCODER(encode_krb5_safe, krb5_safe); - asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); - asn1_addfield(val->sam_type,0,asn1_encode_integer); +/* + * encode_krb5_safe_with_body + * + * Like encode_krb5_safe(), except takes a saved KRB-SAFE-BODY + * encoding to avoid problems with re-encoding. + */ +MAKE_FULL_ENCODER(encode_krb5_safe_with_body, krb5_safe_with_body); + +MAKE_FULL_ENCODER(encode_krb5_priv, krb5_priv); +MAKE_FULL_ENCODER(encode_krb5_enc_priv_part, priv_enc_part); +MAKE_FULL_ENCODER(encode_krb5_cred, krb5_cred); +MAKE_FULL_ENCODER(encode_krb5_enc_cred_part, enc_cred_part); +MAKE_FULL_ENCODER(encode_krb5_error, krb5_error); +MAKE_FULL_ENCODER(encode_krb5_authdata, auth_data); +MAKE_FULL_ENCODER(encode_krb5_authdata_elt, authdata_elt); +MAKE_FULL_ENCODER(encode_krb5_alt_method, alt_method); +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); +/* Sandia Additions */ +MAKE_FULL_ENCODER(encode_krb5_pwd_sequence, passwdsequence); +MAKE_FULL_ENCODER(encode_krb5_pwd_data, pwd_data); +MAKE_FULL_ENCODER(encode_krb5_padata_sequence, seq_of_pa_data); +/* sam preauth additions */ +MAKE_FULL_ENCODER(encode_krb5_sam_challenge, sam_challenge); +#if 0 /* encoders not used! */ +MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2, sam_challenge_2); +MAKE_FULL_ENCODER(encode_krb5_sam_challenge_2_body, + sam_challenge_2_body); +#endif +MAKE_FULL_ENCODER(encode_krb5_sam_key, sam_key); +MAKE_FULL_ENCODER(encode_krb5_enc_sam_response_enc, + enc_sam_response_enc); +MAKE_FULL_ENCODER(encode_krb5_enc_sam_response_enc_2, + enc_sam_response_enc_2); +MAKE_FULL_ENCODER(encode_krb5_sam_response, sam_response); +MAKE_FULL_ENCODER(encode_krb5_sam_response_2, sam_response_2); +MAKE_FULL_ENCODER(encode_krb5_predicted_sam_response, + predicted_sam_response); +MAKE_FULL_ENCODER(encode_krb5_setpw_req, setpw_req); - asn1_makeseq(); - asn1_cleanup(); -} -asn1_error_code asn1_encode_sam_key(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen) -{ - asn1_setup(); - asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); - asn1_makeseq(); - asn1_cleanup(); -} -asn1_error_code asn1_encode_enc_sam_response_enc(asn1buf *buf, const krb5_enc_sam_response_enc *val, unsigned int *retlen) -{ - asn1_setup(); - add_optstring(val->sam_sad,3,asn1_encode_charstring); - asn1_addfield(val->sam_usec,2,asn1_encode_integer); - asn1_addfield(val->sam_timestamp,1,asn1_encode_kerberos_time); - asn1_addfield(val->sam_nonce,0,asn1_encode_integer); - asn1_makeseq(); - asn1_cleanup(); -} -asn1_error_code asn1_encode_enc_sam_response_enc_2(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val, unsigned int *retlen) -{ - asn1_setup(); - add_optstring(val->sam_sad,1,asn1_encode_charstring); - asn1_addfield(val->sam_nonce,0,asn1_encode_integer); +#ifndef DISABLE_PKINIT +/* + * PKINIT + */ - asn1_makeseq(); +/* This code hasn't been converted to use the above framework yet, + because we currently have no test cases to validate the new + version. It *also* appears that some of the encodings may disagree + with the specifications, but that's a separate problem. */ - asn1_cleanup(); -} +/**** asn1 macros ****/ +#if 0 + How to write an asn1 encoder function using these macros: -asn1_error_code asn1_encode_sam_response(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen) -{ - asn1_setup(); + asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, + const krb5_type *val, + int *retlen) + { + asn1_setup(); - if (val->sam_patimestamp) - asn1_addfield(val->sam_patimestamp,6,asn1_encode_kerberos_time); - if (val->sam_nonce) - asn1_addfield(val->sam_nonce,5,asn1_encode_integer); - asn1_addfield(&(val->sam_enc_nonce_or_ts),4,asn1_encode_encrypted_data); - if (val->sam_enc_key.ciphertext.length) - asn1_addfield(&(val->sam_enc_key),3,asn1_encode_encrypted_data); - add_optstring(val->sam_track_id,2,asn1_encode_charstring); - asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); - asn1_addfield(val->sam_type,0,asn1_encode_integer); + asn1_addfield(val->last_field, n, asn1_type); + asn1_addfield(rep->next_to_last_field, n-1, asn1_type); + ... - asn1_makeseq(); + /* for OPTIONAL fields */ + if (rep->field_i == should_not_be_omitted) + asn1_addfield(rep->field_i, i, asn1_type); - asn1_cleanup(); -} + /* for string fields (these encoders take an additional argument, + the length of the string) */ + addlenfield(rep->field_length, rep->field, i-1, asn1_type); -asn1_error_code asn1_encode_sam_response_2(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen) -{ - asn1_setup(); + /* if you really have to do things yourself... */ + retval = asn1_encode_asn1_type(buf,rep->field,&length); + if (retval) return retval; + sum += length; + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length, + &length); + if (retval) return retval; + sum += length; - asn1_addfield(val->sam_nonce,4,asn1_encode_integer); - asn1_addfield(&(val->sam_enc_nonce_or_sad),3,asn1_encode_encrypted_data); - add_optstring(val->sam_track_id,2,asn1_encode_charstring); - asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); - asn1_addfield(val->sam_type,0,asn1_encode_integer); + ... + asn1_addfield(rep->second_field, 1, asn1_type); + asn1_addfield(rep->first_field, 0, asn1_type); + asn1_makeseq(); - asn1_makeseq(); + asn1_cleanup(); + } +#endif - asn1_cleanup(); -} +/* asn1_addlenfield -- add a field whose length must be separately specified */ +#define asn1_addlenfield(len,value,tag,encoder)\ +{ unsigned int length; \ + retval = encoder(buf,len,value,&length); \ + if (retval) {\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length;\ + retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ + if (retval) {\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length; } -asn1_error_code asn1_encode_predicted_sam_response(asn1buf *buf, const krb5_predicted_sam_response *val, unsigned int *retlen) -{ - asn1_setup(); +/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */ +#define asn1_addfield_implicit(value,tag,encoder)\ +{ unsigned int length;\ + retval = encoder(buf,value,&length);\ + if (retval) {\ + return retval; }\ + sum += length;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } - add_optstring(val->msd,6,asn1_encode_charstring); - asn1_addfield(val->client,5,asn1_encode_principal_name); - asn1_addfield(val->client,4,asn1_encode_realm); - asn1_addfield(val->susec,3,asn1_encode_integer); - asn1_addfield(val->stime,2,asn1_encode_kerberos_time); - asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); - asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); +/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */ +#define asn1_insert_implicit_octetstring(len,value,tag)\ +{ unsigned int length;\ + retval = asn1buf_insert_octetstring(buf,len,value);\ + if (retval) {\ + return retval; }\ + sum += len;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } - asn1_makeseq(); +/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */ +/* needs "length" declared in enclosing context */ +#define asn1_insert_implicit_bitstring(len,value,tag)\ +{ retval = asn1buf_insert_octetstring(buf,len,value); \ + if (retval) {\ + return retval; }\ + sum += len;\ + retval = asn1buf_insert_octet(buf, 0);\ + if (retval) {\ + return retval; }\ + sum++;\ + retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \ + if (retval) {\ + return retval; }\ + sum += length; } - asn1_cleanup(); -} +/* Callable encoders for the types defined above, until the PKINIT + encoders get converted. */ +MAKE_ENCFN(asn1_encode_realm, realm_of_principal_data); +MAKE_ENCFN(asn1_encode_principal_name, principal_data); +MAKE_ENCFN(asn1_encode_encryption_key, encryption_key); +MAKE_ENCFN(asn1_encode_checksum, checksum); -/* - * Do some ugliness to insert a raw pre-encoded KRB-SAFE-BODY. - */ -asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *body, unsigned int *retlen) +static asn1_error_code +asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, + unsigned int *retlen) { - asn1_error_code retval; - - retval = asn1buf_insert_octetstring(buf, body->length, - (krb5_octet *)body->data); - if (retval) { - asn1buf_destroy(&buf); - return retval; - } - *retlen = body->length; - return 0; + return asn1_encode_kerberos_time_at(buf,&val,retlen); } -#ifndef DISABLE_PKINIT -/* - * PKINIT - */ - +/* Now the real PKINIT encoder functions. */ asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen) { asn1_setup(); @@ -1053,15 +1366,18 @@ asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algori sum += val->parameters.length; } - retval = asn1_encode_oid(buf, val->algorithm.length, - val->algorithm.data, - &length); + { + unsigned int length; + retval = asn1_encode_oid(buf, val->algorithm.length, + val->algorithm.data, + &length); - if (retval) { - asn1buf_destroy(&buf); - return retval; + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; } - sum += length; asn1_makeseq(); asn1_cleanup(); @@ -1071,9 +1387,14 @@ asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_ { asn1_setup(); - asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING); + { + unsigned int length; + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING); + } if (val->algorithm.parameters.length != 0) { + unsigned int length; + retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length, val->algorithm.parameters.data); if (retval) { @@ -1081,27 +1402,28 @@ asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_ return retval; } sum += val->algorithm.parameters.length; - } - retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, - val->algorithm.algorithm.data, - &length); + retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, + val->algorithm.algorithm.data, + &length); + + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; - if (retval) { - asn1buf_destroy(&buf); - return retval; - } - sum += length; - retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, - val->algorithm.parameters.length + length, - &length); + retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, + val->algorithm.parameters.length + length, + &length); - if (retval) { - asn1buf_destroy(&buf); - return retval; + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; } - sum += length; asn1_makeseq(); asn1_cleanup(); @@ -1116,6 +1438,7 @@ asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const for (i=0; val[i] != NULL; i++); for (i--; i>=0; i--) { + unsigned int length; retval = asn1_encode_algorithm_identifier(buf,val[i],&length); if (retval) return retval; sum += length; @@ -1183,6 +1506,7 @@ asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *b for (i=0; val[i] != NULL; i++); for (i--; i>=0; i--) { + unsigned int length; retval = asn1_encode_external_principal_identifier(buf,val[i],&length); if (retval) return retval; sum += length; @@ -1238,6 +1562,7 @@ asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trus for (i=0; val[i] != NULL; i++); for (i--; i>=0; i--) { + unsigned int length; retval = asn1_encode_trusted_ca(buf,val[i],&length); if (retval) return retval; sum += length; @@ -1286,15 +1611,19 @@ asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_ asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time); asn1_addfield(val->nonce, 1, asn1_encode_integer); - asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3); - retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, - val->subjectPublicKey.length + 1 + length, - &length); - if (retval) { - asn1buf_destroy(&buf); - return retval; + { + unsigned int length; + + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3); + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, + val->subjectPublicKey.length + 1 + length, + &length); + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; } - sum += length; asn1_makeseq(); asn1_cleanup(); @@ -1363,10 +1692,14 @@ asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_a asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen) { asn1_setup(); - retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length); - if (retval) { - asn1buf_destroy(&buf); - return retval; + { + unsigned int length; + retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length); + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + /* length set but ignored? sum not updated? */ } asn1_cleanup(); } @@ -1380,6 +1713,8 @@ asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_type for (i=0; val[i] != NULL; i++); for (i--; i>=0; i--) { + unsigned int length; + retval = asn1_encode_typed_data(buf,val[i],&length); if (retval) return retval; sum += length; |