1*ba7b222eSGlenn Barry /*
2*ba7b222eSGlenn Barry  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3*ba7b222eSGlenn Barry  * Use is subject to license terms.
4*ba7b222eSGlenn Barry  */
5*ba7b222eSGlenn Barry /* -*- mode: c; indent-tabs-mode: nil -*- */
6*ba7b222eSGlenn Barry /*
7*ba7b222eSGlenn Barry  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
8*ba7b222eSGlenn Barry  * Use is subject to license terms.
9*ba7b222eSGlenn Barry  */
107c478bd9Sstevel@tonic-gate /*
117c478bd9Sstevel@tonic-gate  * src/lib/krb5/asn.1/asn1_k_encode.c
12*ba7b222eSGlenn Barry  *
13*ba7b222eSGlenn Barry  * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
147c478bd9Sstevel@tonic-gate  * All Rights Reserved.
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
177c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
187c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
197c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
20*ba7b222eSGlenn Barry  *
217c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
227c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
237c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
247c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
257c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
267c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
277c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
287c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
297c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
307c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
317c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
327c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
337c478bd9Sstevel@tonic-gate  * or implied warranty.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include "asn1_k_encode.h"
377c478bd9Sstevel@tonic-gate #include "asn1_make.h"
387c478bd9Sstevel@tonic-gate #include "asn1_encode.h"
397c478bd9Sstevel@tonic-gate #include <assert.h>
40*ba7b222eSGlenn Barry #include "k5-platform-store_32.h" /* Solaris Kerberos */
417c478bd9Sstevel@tonic-gate 
42*ba7b222eSGlenn Barry /* helper macros
437c478bd9Sstevel@tonic-gate 
44*ba7b222eSGlenn Barry    These are mostly only needed for PKINIT, but there are three
45*ba7b222eSGlenn Barry    basic-krb5 encoders not converted yet.  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /* setup() -- create and initialize bookkeeping variables
487c478bd9Sstevel@tonic-gate      retval: stores error codes returned from subroutines
497c478bd9Sstevel@tonic-gate      length: length of the most-recently produced encoding
507c478bd9Sstevel@tonic-gate      sum: cumulative length of the entire encoding */
517c478bd9Sstevel@tonic-gate #define asn1_setup()\
527c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
53*ba7b222eSGlenn Barry   unsigned int sum=0
54159d09a2SMark Phalan 
557c478bd9Sstevel@tonic-gate /* form a sequence (by adding a sequence header to the current encoding) */
567c478bd9Sstevel@tonic-gate #define asn1_makeseq()\
57*ba7b222eSGlenn Barry { unsigned int length;\
587c478bd9Sstevel@tonic-gate   retval = asn1_make_sequence(buf,sum,&length);\
59*ba7b222eSGlenn Barry   if (retval) {\
607c478bd9Sstevel@tonic-gate     return retval; }\
61*ba7b222eSGlenn Barry   sum += length; }
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /* produce the final output and clean up the workspace */
647c478bd9Sstevel@tonic-gate #define asn1_cleanup()\
657c478bd9Sstevel@tonic-gate   *retlen = sum;\
667c478bd9Sstevel@tonic-gate   return 0
677c478bd9Sstevel@tonic-gate 
68*ba7b222eSGlenn Barry /* asn1_addfield -- add a field, or component, to the encoding */
69*ba7b222eSGlenn Barry #define asn1_addfield(value,tag,encoder)\
70*ba7b222eSGlenn Barry { unsigned int length; \
71*ba7b222eSGlenn Barry   retval = encoder(buf,value,&length);  \
72*ba7b222eSGlenn Barry   if (retval) {\
73*ba7b222eSGlenn Barry     return retval; }\
74*ba7b222eSGlenn Barry   sum += length;\
75*ba7b222eSGlenn Barry   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
76*ba7b222eSGlenn Barry   if (retval) {\
77*ba7b222eSGlenn Barry     return retval; }\
78*ba7b222eSGlenn Barry   sum += length; }
797c478bd9Sstevel@tonic-gate 
80*ba7b222eSGlenn Barry DEFINTTYPE(int32, krb5_int32);
81*ba7b222eSGlenn Barry DEFPTRTYPE(int32_ptr, int32);
82*ba7b222eSGlenn Barry 
83*ba7b222eSGlenn Barry DEFUINTTYPE(uint, unsigned int);
84*ba7b222eSGlenn Barry DEFUINTTYPE(octet, krb5_octet);
85*ba7b222eSGlenn Barry DEFUINTTYPE(ui_4, krb5_ui_4);
86*ba7b222eSGlenn Barry 
87*ba7b222eSGlenn Barry DEFFNLENTYPE(octetstring, unsigned char *, asn1_encode_octetstring);
88*ba7b222eSGlenn Barry DEFFNLENTYPE(s_octetstring, char *, asn1_encode_octetstring);
89*ba7b222eSGlenn Barry DEFFNLENTYPE(charstring, char *, asn1_encode_charstring);
90*ba7b222eSGlenn Barry DEFFNLENTYPE(generalstring, char *, asn1_encode_generalstring);
91*ba7b222eSGlenn Barry DEFFNLENTYPE(u_generalstring, unsigned char *, asn1_encode_generalstring);
92*ba7b222eSGlenn Barry DEFFNLENTYPE(opaque, char *, asn1_encode_opaque);
93*ba7b222eSGlenn Barry 
94*ba7b222eSGlenn Barry DEFFIELDTYPE(gstring_data, krb5_data,
95*ba7b222eSGlenn Barry              FIELDOF_STRING(krb5_data, generalstring, data, length, -1));
96*ba7b222eSGlenn Barry DEFPTRTYPE(gstring_data_ptr,gstring_data);
97*ba7b222eSGlenn Barry 
98*ba7b222eSGlenn Barry DEFFIELDTYPE(ostring_data, krb5_data,
99*ba7b222eSGlenn Barry              FIELDOF_STRING(krb5_data, s_octetstring, data, length, -1));
100*ba7b222eSGlenn Barry DEFPTRTYPE(ostring_data_ptr,ostring_data);
101*ba7b222eSGlenn Barry 
102*ba7b222eSGlenn Barry DEFFIELDTYPE(opaque_data, krb5_data,
103*ba7b222eSGlenn Barry              FIELDOF_STRING(krb5_data, opaque, data, length, -1));
104*ba7b222eSGlenn Barry 
105*ba7b222eSGlenn Barry DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data,
106*ba7b222eSGlenn Barry              FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1));
107*ba7b222eSGlenn Barry DEFPTRTYPE(realm_of_principal, realm_of_principal_data);
108*ba7b222eSGlenn Barry 
109*ba7b222eSGlenn Barry 
110*ba7b222eSGlenn Barry static const struct field_info princname_fields[] = {
111*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_principal_data, int32, type, 0),
112*ba7b222eSGlenn Barry     FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, 1),
113*ba7b222eSGlenn Barry };
114*ba7b222eSGlenn Barry /* krb5_principal is a typedef for krb5_principal_data*, so this is
115*ba7b222eSGlenn Barry    effectively "encode_principal_data_at" with an address arg.  */
116*ba7b222eSGlenn Barry DEFSEQTYPE(principal_data, krb5_principal_data, princname_fields, 0);
117*ba7b222eSGlenn Barry DEFPTRTYPE(principal, principal_data);
118*ba7b222eSGlenn Barry 
119*ba7b222eSGlenn Barry static asn1_error_code
asn1_encode_kerberos_time_at(asn1buf * buf,const krb5_timestamp * val,unsigned int * retlen)120*ba7b222eSGlenn Barry asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val,
121*ba7b222eSGlenn Barry                              unsigned int *retlen)
122*ba7b222eSGlenn Barry {
123*ba7b222eSGlenn Barry     /* Range checking for time_t vs krb5_timestamp?  */
124*ba7b222eSGlenn Barry     time_t tval = *val;
125*ba7b222eSGlenn Barry     return asn1_encode_generaltime(buf, tval, retlen);
126*ba7b222eSGlenn Barry }
127*ba7b222eSGlenn Barry DEFFNXTYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at);
128*ba7b222eSGlenn Barry 
129*ba7b222eSGlenn Barry static const struct field_info address_fields[] = {
130*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_address, int32, addrtype, 0),
131*ba7b222eSGlenn Barry     FIELDOF_STRING(krb5_address, octetstring, contents, length, 1),
132*ba7b222eSGlenn Barry };
133*ba7b222eSGlenn Barry DEFSEQTYPE(address, krb5_address, address_fields, 0);
134*ba7b222eSGlenn Barry DEFPTRTYPE(address_ptr, address);
135*ba7b222eSGlenn Barry 
136*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(seq_of_host_addresses, address_ptr);
137*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_seqof_host_addresses, seq_of_host_addresses);
138*ba7b222eSGlenn Barry 
139*ba7b222eSGlenn Barry static unsigned int
optional_encrypted_data(const void * vptr)140*ba7b222eSGlenn Barry optional_encrypted_data (const void *vptr)
141*ba7b222eSGlenn Barry {
142*ba7b222eSGlenn Barry     const krb5_enc_data *val = vptr;
143*ba7b222eSGlenn Barry     unsigned int optional = 0;
144*ba7b222eSGlenn Barry 
145*ba7b222eSGlenn Barry     if (val->kvno != 0)
146*ba7b222eSGlenn Barry         optional |= (1u << 1);
147*ba7b222eSGlenn Barry 
148*ba7b222eSGlenn Barry     return optional;
149*ba7b222eSGlenn Barry }
150*ba7b222eSGlenn Barry 
151*ba7b222eSGlenn Barry static const struct field_info encrypted_data_fields[] = {
152*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_data, int32, enctype, 0),
153*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_data, uint, kvno, 1, 1),
154*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_data, ostring_data, ciphertext, 2),
155*ba7b222eSGlenn Barry };
156*ba7b222eSGlenn Barry DEFSEQTYPE(encrypted_data, krb5_enc_data, encrypted_data_fields,
157*ba7b222eSGlenn Barry            optional_encrypted_data);
158*ba7b222eSGlenn Barry 
159*ba7b222eSGlenn Barry /* The encode_bitstring function wants an array of bytes (since PKINIT
160*ba7b222eSGlenn Barry    may provide something that isn't 32 bits), but krb5_flags is stored
161*ba7b222eSGlenn Barry    as a 32-bit integer in host order.  */
162*ba7b222eSGlenn Barry static asn1_error_code
asn1_encode_krb5_flags_at(asn1buf * buf,const krb5_flags * val,unsigned int * retlen)163*ba7b222eSGlenn Barry asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val,
164*ba7b222eSGlenn Barry                           unsigned int *retlen)
165*ba7b222eSGlenn Barry {
166*ba7b222eSGlenn Barry     unsigned char cbuf[4];
167*ba7b222eSGlenn Barry     store_32_be((krb5_ui_4) *val, cbuf);
168*ba7b222eSGlenn Barry     return asn1_encode_bitstring(buf, 4, cbuf, retlen);
169*ba7b222eSGlenn Barry }
170*ba7b222eSGlenn Barry DEFFNXTYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at);
171*ba7b222eSGlenn Barry 
172*ba7b222eSGlenn Barry static const struct field_info authdata_elt_fields[] = {
173*ba7b222eSGlenn Barry     /* ad-type[0]               INTEGER */
174*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_authdata, int32, ad_type, 0),
175*ba7b222eSGlenn Barry     /* ad-data[1]               OCTET STRING */
176*ba7b222eSGlenn Barry     FIELDOF_STRING(krb5_authdata, octetstring, contents, length, 1),
177*ba7b222eSGlenn Barry };
178*ba7b222eSGlenn Barry DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields, 0);
179*ba7b222eSGlenn Barry DEFPTRTYPE(authdata_elt_ptr, authdata_elt);
180*ba7b222eSGlenn Barry DEFNONEMPTYNULLTERMSEQOFTYPE(auth_data, authdata_elt_ptr);
181*ba7b222eSGlenn Barry DEFPTRTYPE(auth_data_ptr, auth_data);
182*ba7b222eSGlenn Barry 
183*ba7b222eSGlenn Barry static const struct field_info encryption_key_fields[] = {
184*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_keyblock, int32, enctype, 0),
185*ba7b222eSGlenn Barry     FIELDOF_STRING(krb5_keyblock, octetstring, contents, length, 1),
186*ba7b222eSGlenn Barry };
187*ba7b222eSGlenn Barry DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields, 0);
188*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_encryption_key, encryption_key);
189*ba7b222eSGlenn Barry 
190*ba7b222eSGlenn Barry static const struct field_info checksum_fields[] = {
191*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_checksum, int32, checksum_type, 0),
192*ba7b222eSGlenn Barry     FIELDOF_STRING(krb5_checksum, octetstring, contents, length, 1),
193*ba7b222eSGlenn Barry };
194*ba7b222eSGlenn Barry DEFSEQTYPE(checksum, krb5_checksum, checksum_fields, 0);
195*ba7b222eSGlenn Barry DEFPTRTYPE(checksum_ptr, checksum);
196*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(seq_of_checksum, checksum_ptr);
197*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_seqof_checksum, seq_of_checksum);
198*ba7b222eSGlenn Barry 
199*ba7b222eSGlenn Barry static const struct field_info lr_fields[] = {
200*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_last_req_entry, int32, lr_type, 0),
201*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_last_req_entry, kerberos_time, value, 1),
202*ba7b222eSGlenn Barry };
203*ba7b222eSGlenn Barry DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields, 0);
204*ba7b222eSGlenn Barry 
205*ba7b222eSGlenn Barry DEFPTRTYPE(last_req_ent_ptr, last_req_ent);
206*ba7b222eSGlenn Barry DEFNONEMPTYNULLTERMSEQOFTYPE(last_req, last_req_ent_ptr);
207*ba7b222eSGlenn Barry DEFPTRTYPE(last_req_ptr, last_req);
208*ba7b222eSGlenn Barry 
209*ba7b222eSGlenn Barry static const struct field_info ticket_fields[] = {
210*ba7b222eSGlenn Barry     FIELD_INT_IMM(KVNO, 0),
211*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_ticket, realm_of_principal, server, 1),
212*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_ticket, principal, server, 2),
213*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_ticket, encrypted_data, enc_part, 3),
214*ba7b222eSGlenn Barry };
215*ba7b222eSGlenn Barry DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields, 0);
216*ba7b222eSGlenn Barry DEFAPPTAGGEDTYPE(ticket, 1, untagged_ticket);
217*ba7b222eSGlenn Barry 
218*ba7b222eSGlenn Barry static const struct field_info pa_data_fields[] = {
219*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_pa_data, int32, pa_type, 1),
220*ba7b222eSGlenn Barry     FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 2),
221*ba7b222eSGlenn Barry };
222*ba7b222eSGlenn Barry DEFSEQTYPE(pa_data, krb5_pa_data, pa_data_fields, 0);
223*ba7b222eSGlenn Barry DEFPTRTYPE(pa_data_ptr, pa_data);
224*ba7b222eSGlenn Barry 
225*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(seq_of_pa_data, pa_data_ptr);
226*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_seqof_pa_data, seq_of_pa_data);
227*ba7b222eSGlenn Barry 
228*ba7b222eSGlenn Barry DEFPTRTYPE(ticket_ptr, ticket);
229*ba7b222eSGlenn Barry DEFNONEMPTYNULLTERMSEQOFTYPE(seq_of_ticket,ticket_ptr);
230*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_seqof_ticket, seq_of_ticket);
231*ba7b222eSGlenn Barry 
232*ba7b222eSGlenn Barry /* EncKDCRepPart ::= SEQUENCE */
233*ba7b222eSGlenn Barry static const struct field_info enc_kdc_rep_part_fields[] = {
234*ba7b222eSGlenn Barry     /* key[0]           EncryptionKey */
235*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, ptr_encryption_key, session, 0),
236*ba7b222eSGlenn Barry     /* last-req[1]      LastReq */
237*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, last_req_ptr, last_req, 1),
238*ba7b222eSGlenn Barry     /* nonce[2]         INTEGER */
239*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, int32, nonce, 2),
240*ba7b222eSGlenn Barry     /* key-expiration[3]        KerberosTime OPTIONAL */
241*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, key_exp, 3, 3),
242*ba7b222eSGlenn Barry     /* flags[4]         TicketFlags */
243*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, krb5_flags, flags, 4),
244*ba7b222eSGlenn Barry     /* authtime[5]      KerberosTime */
245*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.authtime, 5),
246*ba7b222eSGlenn Barry     /* starttime[6]     KerberosTime OPTIONAL */
247*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.starttime, 6, 6),
248*ba7b222eSGlenn Barry     /* endtime[7]               KerberosTime */
249*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, kerberos_time, times.endtime, 7),
250*ba7b222eSGlenn Barry     /* renew-till[8]    KerberosTime OPTIONAL */
251*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_kdc_rep_part, kerberos_time, times.renew_till, 8, 8),
252*ba7b222eSGlenn Barry     /* srealm[9]                Realm */
253*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, realm_of_principal, server, 9),
254*ba7b222eSGlenn Barry     /* sname[10]                PrincipalName */
255*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_kdc_rep_part, principal, server, 10),
256*ba7b222eSGlenn Barry     /* caddr[11]                HostAddresses OPTIONAL */
257*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_host_addresses, caddrs,
258*ba7b222eSGlenn Barry                 11, 11),
259*ba7b222eSGlenn Barry     /* encrypted-pa-data[12]    SEQUENCE OF PA-DATA OPTIONAL */
260*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_kdc_rep_part, ptr_seqof_pa_data, enc_padata, 12, 12),
261*ba7b222eSGlenn Barry };
optional_enc_kdc_rep_part(const void * p)262*ba7b222eSGlenn Barry static unsigned int optional_enc_kdc_rep_part(const void *p)
263*ba7b222eSGlenn Barry {
264*ba7b222eSGlenn Barry     const krb5_enc_kdc_rep_part *val = p;
265*ba7b222eSGlenn Barry     unsigned int optional = 0;
266*ba7b222eSGlenn Barry 
267*ba7b222eSGlenn Barry     if (val->key_exp)
268*ba7b222eSGlenn Barry         optional |= (1u << 3);
269*ba7b222eSGlenn Barry     if (val->times.starttime)
270*ba7b222eSGlenn Barry         optional |= (1u << 6);
271*ba7b222eSGlenn Barry     if (val->flags & TKT_FLG_RENEWABLE)
272*ba7b222eSGlenn Barry         optional |= (1u << 8);
273*ba7b222eSGlenn Barry     if (val->caddrs != NULL && val->caddrs[0] != NULL)
274*ba7b222eSGlenn Barry         optional |= (1u << 11);
275*ba7b222eSGlenn Barry 
276*ba7b222eSGlenn Barry     return optional;
277*ba7b222eSGlenn Barry }
278*ba7b222eSGlenn Barry DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields,
279*ba7b222eSGlenn Barry            optional_enc_kdc_rep_part);
280*ba7b222eSGlenn Barry 
281*ba7b222eSGlenn Barry /* Yuck!  Eventually push this *up* above the encoder API and make the
282*ba7b222eSGlenn Barry    rest of the library put the realm name in one consistent place.  At
283*ba7b222eSGlenn Barry    the same time, might as well add the msg-type field and encode both
284*ba7b222eSGlenn Barry    AS-REQ and TGS-REQ through the same descriptor.  */
285*ba7b222eSGlenn Barry struct kdc_req_hack {
286*ba7b222eSGlenn Barry     krb5_kdc_req v;
287*ba7b222eSGlenn Barry     krb5_data *server_realm;
288*ba7b222eSGlenn Barry };
289*ba7b222eSGlenn Barry static const struct field_info kdc_req_hack_fields[] = {
290*ba7b222eSGlenn Barry     FIELDOF_NORM(struct kdc_req_hack, krb5_flags, v.kdc_options, 0),
291*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, principal, v.client, 1, 1),
292*ba7b222eSGlenn Barry     FIELDOF_NORM(struct kdc_req_hack, gstring_data_ptr, server_realm, 2),
293*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, principal, v.server, 3, 3),
294*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.from, 4, 4),
295*ba7b222eSGlenn Barry     FIELDOF_NORM(struct kdc_req_hack, kerberos_time, v.till, 5),
296*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, kerberos_time, v.rtime, 6, 6),
297*ba7b222eSGlenn Barry     FIELDOF_NORM(struct kdc_req_hack, int32, v.nonce, 7),
298*ba7b222eSGlenn Barry     FIELDOF_SEQOF_INT32(struct kdc_req_hack, int32_ptr, v.ktype, v.nktypes, 8),
299*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_host_addresses, v.addresses, 9, 9),
300*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, encrypted_data, v.authorization_data, 10, 10),
301*ba7b222eSGlenn Barry     FIELDOF_OPT(struct kdc_req_hack, ptr_seqof_ticket, v.second_ticket, 11, 11),
302*ba7b222eSGlenn Barry };
optional_kdc_req_hack(const void * p)303*ba7b222eSGlenn Barry static unsigned int optional_kdc_req_hack(const void *p)
304*ba7b222eSGlenn Barry {
305*ba7b222eSGlenn Barry     const struct kdc_req_hack *val2 = p;
306*ba7b222eSGlenn Barry     const krb5_kdc_req *val = &val2->v;
307*ba7b222eSGlenn Barry     unsigned int optional = 0;
308*ba7b222eSGlenn Barry 
309*ba7b222eSGlenn Barry     if (val->second_ticket != NULL && val->second_ticket[0] != NULL)
310*ba7b222eSGlenn Barry         optional |= (1u << 11);
311*ba7b222eSGlenn Barry     if (val->authorization_data.ciphertext.data != NULL)
312*ba7b222eSGlenn Barry         optional |= (1u << 10);
313*ba7b222eSGlenn Barry     if (val->addresses != NULL && val->addresses[0] != NULL)
314*ba7b222eSGlenn Barry         optional |= (1u << 9);
315*ba7b222eSGlenn Barry     if (val->rtime)
316*ba7b222eSGlenn Barry         optional |= (1u << 6);
317*ba7b222eSGlenn Barry     if (val->from)
318*ba7b222eSGlenn Barry         optional |= (1u << 4);
319*ba7b222eSGlenn Barry     if (val->server != NULL)
320*ba7b222eSGlenn Barry         optional |= (1u << 3);
321*ba7b222eSGlenn Barry     if (val->client != NULL)
322*ba7b222eSGlenn Barry         optional |= (1u << 1);
323*ba7b222eSGlenn Barry 
324*ba7b222eSGlenn Barry     return optional;
325*ba7b222eSGlenn Barry }
326*ba7b222eSGlenn Barry DEFSEQTYPE(kdc_req_body_hack, struct kdc_req_hack, kdc_req_hack_fields,
327*ba7b222eSGlenn Barry            optional_kdc_req_hack);
328*ba7b222eSGlenn Barry static asn1_error_code
329*ba7b222eSGlenn Barry asn1_encode_kdc_req_hack(asn1buf *, const struct kdc_req_hack *,
330*ba7b222eSGlenn Barry                          unsigned int *);
331*ba7b222eSGlenn Barry MAKE_ENCFN(asn1_encode_kdc_req_hack, kdc_req_body_hack);
332*ba7b222eSGlenn Barry static asn1_error_code
asn1_encode_kdc_req_body(asn1buf * buf,const krb5_kdc_req * val,unsigned int * retlen)333*ba7b222eSGlenn Barry asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val,
334*ba7b222eSGlenn Barry                          unsigned int *retlen)
335*ba7b222eSGlenn Barry {
336*ba7b222eSGlenn Barry     struct kdc_req_hack val2;
337*ba7b222eSGlenn Barry     val2.v = *val;
338*ba7b222eSGlenn Barry     if (val->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) {
339*ba7b222eSGlenn Barry         if (val->second_ticket != NULL && val->second_ticket[0] != NULL) {
340*ba7b222eSGlenn Barry             val2.server_realm = &val->second_ticket[0]->server->realm;
341*ba7b222eSGlenn Barry         } else return ASN1_MISSING_FIELD;
342*ba7b222eSGlenn Barry     } else if (val->server != NULL) {
343*ba7b222eSGlenn Barry         val2.server_realm = &val->server->realm;
344*ba7b222eSGlenn Barry     } else return ASN1_MISSING_FIELD;
345*ba7b222eSGlenn Barry     return asn1_encode_kdc_req_hack(buf, &val2, retlen);
346*ba7b222eSGlenn Barry }
347*ba7b222eSGlenn Barry DEFFNXTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body);
348*ba7b222eSGlenn Barry /* end ugly hack */
349*ba7b222eSGlenn Barry 
350*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_kdc_req_body,kdc_req_body);
351*ba7b222eSGlenn Barry 
352*ba7b222eSGlenn Barry static const struct field_info transited_fields[] = {
353*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_transited, octet, tr_type, 0),
354*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_transited, ostring_data, tr_contents, 1),
355*ba7b222eSGlenn Barry };
356*ba7b222eSGlenn Barry DEFSEQTYPE(transited, krb5_transited, transited_fields, 0);
357*ba7b222eSGlenn Barry 
358*ba7b222eSGlenn Barry static const struct field_info krb_safe_body_fields[] = {
359*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_safe, ostring_data, user_data, 0),
360*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_safe, kerberos_time, timestamp, 1, 1),
361*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_safe, int32, usec, 2, 2),
362*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_safe, uint, seq_number, 3, 3),
363*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_safe, address_ptr, s_address, 4),
364*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_safe, address_ptr, r_address, 5, 5),
365*ba7b222eSGlenn Barry };
optional_krb_safe_body(const void * p)366*ba7b222eSGlenn Barry static unsigned int optional_krb_safe_body(const void *p)
367*ba7b222eSGlenn Barry {
368*ba7b222eSGlenn Barry     const krb5_safe *val = p;
369*ba7b222eSGlenn Barry     unsigned int optional = 0;
370*ba7b222eSGlenn Barry 
371*ba7b222eSGlenn Barry     if (val->timestamp) {
372*ba7b222eSGlenn Barry         optional |= (1u << 1);
373*ba7b222eSGlenn Barry         optional |= (1u << 2);
374*ba7b222eSGlenn Barry     }
375*ba7b222eSGlenn Barry     if (val->seq_number)
376*ba7b222eSGlenn Barry         optional |= (1u << 3);
377*ba7b222eSGlenn Barry     if (val->r_address != NULL)
378*ba7b222eSGlenn Barry         optional |= (1u << 5);
379*ba7b222eSGlenn Barry 
380*ba7b222eSGlenn Barry     return optional;
381*ba7b222eSGlenn Barry }
382*ba7b222eSGlenn Barry DEFSEQTYPE(krb_safe_body, krb5_safe, krb_safe_body_fields,
383*ba7b222eSGlenn Barry            optional_krb_safe_body);
384*ba7b222eSGlenn Barry 
385*ba7b222eSGlenn Barry static const struct field_info krb_cred_info_fields[] = {
386*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_cred_info, ptr_encryption_key, session, 0),
387*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, realm_of_principal, client, 1, 1),
388*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, principal, client, 2, 2),
389*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, krb5_flags, flags, 3, 3),
390*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, kerberos_time, times.authtime, 4, 4),
391*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, kerberos_time, times.starttime, 5, 5),
392*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, kerberos_time, times.endtime, 6, 6),
393*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, kerberos_time, times.renew_till, 7, 7),
394*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, realm_of_principal, server, 8, 8),
395*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, principal, server, 9, 9),
396*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_cred_info, ptr_seqof_host_addresses, caddrs, 10, 10),
397*ba7b222eSGlenn Barry };
optional_krb_cred_info(const void * p)398*ba7b222eSGlenn Barry static unsigned int optional_krb_cred_info(const void *p)
399*ba7b222eSGlenn Barry {
400*ba7b222eSGlenn Barry     const krb5_cred_info *val = p;
401*ba7b222eSGlenn Barry     unsigned int optional = 0;
402*ba7b222eSGlenn Barry 
403*ba7b222eSGlenn Barry     if (val->caddrs != NULL && val->caddrs[0] != NULL)
404*ba7b222eSGlenn Barry         optional |= (1u << 10);
405*ba7b222eSGlenn Barry     if (val->server != NULL) {
406*ba7b222eSGlenn Barry         optional |= (1u << 9);
407*ba7b222eSGlenn Barry         optional |= (1u << 8);
408*ba7b222eSGlenn Barry     }
409*ba7b222eSGlenn Barry     if (val->times.renew_till)
410*ba7b222eSGlenn Barry         optional |= (1u << 7);
411*ba7b222eSGlenn Barry     if (val->times.endtime)
412*ba7b222eSGlenn Barry         optional |= (1u << 6);
413*ba7b222eSGlenn Barry     if (val->times.starttime)
414*ba7b222eSGlenn Barry         optional |= (1u << 5);
415*ba7b222eSGlenn Barry     if (val->times.authtime)
416*ba7b222eSGlenn Barry         optional |= (1u << 4);
417*ba7b222eSGlenn Barry     if (val->flags)
418*ba7b222eSGlenn Barry         optional |= (1u << 3);
419*ba7b222eSGlenn Barry     if (val->client != NULL) {
420*ba7b222eSGlenn Barry         optional |= (1u << 2);
421*ba7b222eSGlenn Barry         optional |= (1u << 1);
422*ba7b222eSGlenn Barry     }
4237c478bd9Sstevel@tonic-gate 
424*ba7b222eSGlenn Barry     return optional;
4257c478bd9Sstevel@tonic-gate }
426*ba7b222eSGlenn Barry DEFSEQTYPE(cred_info, krb5_cred_info, krb_cred_info_fields,
427*ba7b222eSGlenn Barry            optional_krb_cred_info);
428*ba7b222eSGlenn Barry DEFPTRTYPE(cred_info_ptr, cred_info);
429*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(seq_of_cred_info, cred_info_ptr);
4307c478bd9Sstevel@tonic-gate 
431*ba7b222eSGlenn Barry DEFPTRTYPE(ptrseqof_cred_info, seq_of_cred_info);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 
435*ba7b222eSGlenn Barry static unsigned int
optional_etype_info_entry(const void * vptr)436*ba7b222eSGlenn Barry optional_etype_info_entry(const void *vptr)
4377c478bd9Sstevel@tonic-gate {
438*ba7b222eSGlenn Barry     const krb5_etype_info_entry *val = vptr;
439*ba7b222eSGlenn Barry     unsigned int optional = 0;
4407c478bd9Sstevel@tonic-gate 
441*ba7b222eSGlenn Barry     if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT)
442*ba7b222eSGlenn Barry         optional |= (1u << 1);
4437c478bd9Sstevel@tonic-gate 
444*ba7b222eSGlenn Barry     return optional;
4457c478bd9Sstevel@tonic-gate }
446*ba7b222eSGlenn Barry static const struct field_info etype_info_entry_fields[] = {
447*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0),
448*ba7b222eSGlenn Barry     FIELDOF_OPTSTRING(krb5_etype_info_entry, octetstring, salt, length, 1, 1),
449*ba7b222eSGlenn Barry };
450*ba7b222eSGlenn Barry DEFSEQTYPE(etype_info_entry, krb5_etype_info_entry, etype_info_entry_fields,
451*ba7b222eSGlenn Barry            optional_etype_info_entry);
4527c478bd9Sstevel@tonic-gate 
453*ba7b222eSGlenn Barry static unsigned int
optional_etype_info2_entry(const void * vptr)454*ba7b222eSGlenn Barry optional_etype_info2_entry(const void *vptr)
4557c478bd9Sstevel@tonic-gate {
456*ba7b222eSGlenn Barry     const krb5_etype_info_entry *val = vptr;
457*ba7b222eSGlenn Barry     unsigned int optional = 0;
4587c478bd9Sstevel@tonic-gate 
459*ba7b222eSGlenn Barry     if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT)
460*ba7b222eSGlenn Barry         optional |= (1u << 1);
461*ba7b222eSGlenn Barry     if (val->s2kparams.data)
462*ba7b222eSGlenn Barry         optional |= (1u << 2);
4637c478bd9Sstevel@tonic-gate 
464*ba7b222eSGlenn Barry     return optional;
465*ba7b222eSGlenn Barry }
4667c478bd9Sstevel@tonic-gate 
467*ba7b222eSGlenn Barry static const struct field_info etype_info2_entry_fields[] = {
468*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_etype_info_entry, int32, etype, 0),
469*ba7b222eSGlenn Barry     FIELDOF_OPTSTRING(krb5_etype_info_entry, u_generalstring, salt, length,
470*ba7b222eSGlenn Barry                       1, 1),
471*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_etype_info_entry, ostring_data, s2kparams, 2, 2),
472*ba7b222eSGlenn Barry };
473*ba7b222eSGlenn Barry DEFSEQTYPE(etype_info2_entry, krb5_etype_info_entry, etype_info2_entry_fields,
474*ba7b222eSGlenn Barry            optional_etype_info2_entry);
4757c478bd9Sstevel@tonic-gate 
476*ba7b222eSGlenn Barry DEFPTRTYPE(etype_info_entry_ptr, etype_info_entry);
477*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(etype_info, etype_info_entry_ptr);
4787c478bd9Sstevel@tonic-gate 
479*ba7b222eSGlenn Barry DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry);
480*ba7b222eSGlenn Barry DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr);
4817c478bd9Sstevel@tonic-gate 
482*ba7b222eSGlenn Barry static const struct field_info passwdsequence_fields[] = {
483*ba7b222eSGlenn Barry     FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, passwd, 0),
484*ba7b222eSGlenn Barry     FIELDOF_NORM(passwd_phrase_element, ostring_data_ptr, phrase, 1),
485*ba7b222eSGlenn Barry };
486*ba7b222eSGlenn Barry DEFSEQTYPE(passwdsequence, passwd_phrase_element, passwdsequence_fields, 0);
4877c478bd9Sstevel@tonic-gate 
488*ba7b222eSGlenn Barry DEFPTRTYPE(passwdsequence_ptr, passwdsequence);
489*ba7b222eSGlenn Barry DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_passwdsequence, passwdsequence_ptr);
490*ba7b222eSGlenn Barry DEFPTRTYPE(ptr_seqof_passwdsequence, seqof_passwdsequence);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 
493*ba7b222eSGlenn Barry static const struct field_info sam_challenge_fields[] = {
494*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge, int32, sam_type, 0),
495*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge, krb5_flags, sam_flags, 1),
496*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_type_name, 2, 2),
497*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_track_id,3, 3),
498*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge_label,4, 4),
499*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_challenge,5, 5),
500*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_response_prompt,6, 6),
501*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, ostring_data, sam_pk_for_sad,7, 7),
502*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, int32, sam_nonce, 8, 8),
503*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge, checksum, sam_cksum, 9, 9),
504*ba7b222eSGlenn Barry };
optional_sam_challenge(const void * p)505*ba7b222eSGlenn Barry static unsigned int optional_sam_challenge(const void *p)
5067c478bd9Sstevel@tonic-gate {
507*ba7b222eSGlenn Barry     const krb5_sam_challenge *val = p;
508*ba7b222eSGlenn Barry     unsigned int optional = 0;
5097c478bd9Sstevel@tonic-gate 
510*ba7b222eSGlenn Barry     if (val->sam_cksum.length)
511*ba7b222eSGlenn Barry         optional |= (1u << 9);
5127c478bd9Sstevel@tonic-gate 
513*ba7b222eSGlenn Barry     if (val->sam_nonce)
514*ba7b222eSGlenn Barry         optional |= (1u << 8);
5157c478bd9Sstevel@tonic-gate 
516*ba7b222eSGlenn Barry     if (val->sam_pk_for_sad.length > 0) optional |= (1u << 7);
517*ba7b222eSGlenn Barry     if (val->sam_response_prompt.length > 0) optional |= (1u << 6);
518*ba7b222eSGlenn Barry     if (val->sam_challenge.length > 0) optional |= (1u << 5);
519*ba7b222eSGlenn Barry     if (val->sam_challenge_label.length > 0) optional |= (1u << 4);
520*ba7b222eSGlenn Barry     if (val->sam_track_id.length > 0) optional |= (1u << 3);
521*ba7b222eSGlenn Barry     if (val->sam_type_name.length > 0) optional |= (1u << 2);
5227c478bd9Sstevel@tonic-gate 
523*ba7b222eSGlenn Barry     return optional;
5247c478bd9Sstevel@tonic-gate }
525*ba7b222eSGlenn Barry DEFSEQTYPE(sam_challenge,krb5_sam_challenge,sam_challenge_fields,
526*ba7b222eSGlenn Barry            optional_sam_challenge);
5277c478bd9Sstevel@tonic-gate 
528*ba7b222eSGlenn Barry #if 0 /* encoders not used! */
529*ba7b222eSGlenn Barry MAKE_ENCFN(asn1_encode_sequence_of_checksum, seq_of_checksum);
530*ba7b222eSGlenn Barry static asn1_error_code
531*ba7b222eSGlenn Barry asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val,
532*ba7b222eSGlenn Barry                             unsigned int *retlen)
5337c478bd9Sstevel@tonic-gate {
534*ba7b222eSGlenn Barry     asn1_setup();
535*ba7b222eSGlenn Barry     if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0]))
536*ba7b222eSGlenn Barry         return ASN1_MISSING_FIELD;
537*ba7b222eSGlenn Barry 
538*ba7b222eSGlenn Barry     asn1_addfield(val->sam_cksum, 1, asn1_encode_sequence_of_checksum);
539*ba7b222eSGlenn Barry 
540*ba7b222eSGlenn Barry     {
541*ba7b222eSGlenn Barry         unsigned int length;
542*ba7b222eSGlenn Barry 
543*ba7b222eSGlenn Barry         retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length,
544*ba7b222eSGlenn Barry                                             (unsigned char *)val->sam_challenge_2_body.data);
545*ba7b222eSGlenn Barry         if (retval) {
546*ba7b222eSGlenn Barry             return retval;
547*ba7b222eSGlenn Barry         }
548*ba7b222eSGlenn Barry         sum += val->sam_challenge_2_body.length;
549*ba7b222eSGlenn Barry         retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
550*ba7b222eSGlenn Barry                                 val->sam_challenge_2_body.length, &length);
551*ba7b222eSGlenn Barry         if (retval) {
552*ba7b222eSGlenn Barry             return retval;
553*ba7b222eSGlenn Barry         }
554*ba7b222eSGlenn Barry         sum += length;
555*ba7b222eSGlenn Barry     }
5567c478bd9Sstevel@tonic-gate 
557*ba7b222eSGlenn Barry     asn1_makeseq();
558*ba7b222eSGlenn Barry     asn1_cleanup();
559*ba7b222eSGlenn Barry }
560*ba7b222eSGlenn Barry DEFFNXTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2);
561*ba7b222eSGlenn Barry 
562*ba7b222eSGlenn Barry static const struct field_info sam_challenge_2_body_fields[] = {
563*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0),
564*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge_2_body, krb5_flags, sam_flags, 1),
565*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_type_name, 2, 2),
566*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_track_id,3, 3),
567*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge_label,4, 4),
568*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_challenge,5, 5),
569*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_response_prompt,6, 6),
570*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_challenge_2_body, ostring_data, sam_pk_for_sad,7, 7),
571*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_nonce, 8),
572*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_etype, 9),
573*ba7b222eSGlenn Barry };
574*ba7b222eSGlenn Barry static unsigned int optional_sam_challenge_2_body(const void *p)
575*ba7b222eSGlenn Barry {
576*ba7b222eSGlenn Barry     const krb5_sam_challenge_2_body *val = p;
577*ba7b222eSGlenn Barry     unsigned int optional = 0;
578*ba7b222eSGlenn Barry 
579*ba7b222eSGlenn Barry     if (val->sam_pk_for_sad.length > 0) optional |= (1u << 7);
580*ba7b222eSGlenn Barry     if (val->sam_response_prompt.length > 0) optional |= (1u << 6);
581*ba7b222eSGlenn Barry     if (val->sam_challenge.length > 0) optional |= (1u << 5);
582*ba7b222eSGlenn Barry     if (val->sam_challenge_label.length > 0) optional |= (1u << 4);
583*ba7b222eSGlenn Barry     if (val->sam_track_id.length > 0) optional |= (1u << 3);
584*ba7b222eSGlenn Barry     if (val->sam_type_name.length > 0) optional |= (1u << 2);
585*ba7b222eSGlenn Barry 
586*ba7b222eSGlenn Barry     return optional;
587*ba7b222eSGlenn Barry }
588*ba7b222eSGlenn Barry DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body,sam_challenge_2_body_fields,
589*ba7b222eSGlenn Barry            optional_sam_challenge_2_body);
590*ba7b222eSGlenn Barry #endif
5917c478bd9Sstevel@tonic-gate 
592*ba7b222eSGlenn Barry static const struct field_info sam_key_fields[] = {
593*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_key, encryption_key, sam_key, 0),
594*ba7b222eSGlenn Barry };
595*ba7b222eSGlenn Barry DEFSEQTYPE(sam_key, krb5_sam_key, sam_key_fields, 0);
5967c478bd9Sstevel@tonic-gate 
597*ba7b222eSGlenn Barry static const struct field_info enc_sam_response_enc_fields[] = {
598*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_nonce, 0),
599*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_sam_response_enc, kerberos_time, sam_timestamp, 1),
600*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_sam_response_enc, int32, sam_usec, 2),
601*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_sam_response_enc, ostring_data, sam_sad, 3, 3),
602*ba7b222eSGlenn Barry };
optional_enc_sam_response_enc(const void * p)603*ba7b222eSGlenn Barry static unsigned int optional_enc_sam_response_enc(const void *p)
604*ba7b222eSGlenn Barry {
605*ba7b222eSGlenn Barry     const krb5_enc_sam_response_enc *val = p;
606*ba7b222eSGlenn Barry     unsigned int optional = 0;
607*ba7b222eSGlenn Barry 
608*ba7b222eSGlenn Barry     if (val->sam_sad.length > 0) optional |= (1u << 3);
609*ba7b222eSGlenn Barry 
610*ba7b222eSGlenn Barry     return optional;
611*ba7b222eSGlenn Barry }
612*ba7b222eSGlenn Barry DEFSEQTYPE(enc_sam_response_enc, krb5_enc_sam_response_enc,
613*ba7b222eSGlenn Barry            enc_sam_response_enc_fields, optional_enc_sam_response_enc);
614*ba7b222eSGlenn Barry 
615*ba7b222eSGlenn Barry static const struct field_info enc_sam_response_enc_2_fields[] = {
616*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_enc_sam_response_enc_2, int32, sam_nonce, 0),
617*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_enc_sam_response_enc_2, ostring_data, sam_sad, 1, 1),
618*ba7b222eSGlenn Barry };
optional_enc_sam_response_enc_2(const void * p)619*ba7b222eSGlenn Barry static unsigned int optional_enc_sam_response_enc_2(const void *p)
620*ba7b222eSGlenn Barry {
621*ba7b222eSGlenn Barry     const krb5_enc_sam_response_enc_2 *val = p;
622*ba7b222eSGlenn Barry     unsigned int optional = 0;
623*ba7b222eSGlenn Barry 
624*ba7b222eSGlenn Barry     if (val->sam_sad.length > 0) optional |= (1u << 1);
625*ba7b222eSGlenn Barry 
626*ba7b222eSGlenn Barry     return optional;
627*ba7b222eSGlenn Barry }
628*ba7b222eSGlenn Barry DEFSEQTYPE(enc_sam_response_enc_2, krb5_enc_sam_response_enc_2,
629*ba7b222eSGlenn Barry            enc_sam_response_enc_2_fields, optional_enc_sam_response_enc_2);
630*ba7b222eSGlenn Barry 
631*ba7b222eSGlenn Barry static const struct field_info sam_response_fields[] = {
632*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response, int32, sam_type, 0),
633*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response, krb5_flags, sam_flags, 1),
634*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_response, ostring_data, sam_track_id, 2, 2),
635*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_response, encrypted_data, sam_enc_key, 3, 3),
636*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response, encrypted_data, sam_enc_nonce_or_ts, 4),
637*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_response, int32, sam_nonce, 5, 5),
638*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_response, kerberos_time, sam_patimestamp, 6, 6),
639*ba7b222eSGlenn Barry };
optional_sam_response(const void * p)640*ba7b222eSGlenn Barry static unsigned int optional_sam_response(const void *p)
641*ba7b222eSGlenn Barry {
642*ba7b222eSGlenn Barry     const krb5_sam_response *val = p;
643*ba7b222eSGlenn Barry     unsigned int optional = 0;
644*ba7b222eSGlenn Barry 
645*ba7b222eSGlenn Barry     if (val->sam_patimestamp)
646*ba7b222eSGlenn Barry         optional |= (1u << 6);
647*ba7b222eSGlenn Barry     if (val->sam_nonce)
648*ba7b222eSGlenn Barry         optional |= (1u << 5);
649*ba7b222eSGlenn Barry     if (val->sam_enc_key.ciphertext.length)
650*ba7b222eSGlenn Barry         optional |= (1u << 3);
651*ba7b222eSGlenn Barry     if (val->sam_track_id.length > 0) optional |= (1u << 2);
652*ba7b222eSGlenn Barry 
653*ba7b222eSGlenn Barry     return optional;
654*ba7b222eSGlenn Barry }
655*ba7b222eSGlenn Barry DEFSEQTYPE(sam_response, krb5_sam_response, sam_response_fields,
656*ba7b222eSGlenn Barry            optional_sam_response);
657*ba7b222eSGlenn Barry 
658*ba7b222eSGlenn Barry static const struct field_info sam_response_2_fields[] = {
659*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response_2, int32, sam_type, 0),
660*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response_2, krb5_flags, sam_flags, 1),
661*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_sam_response_2, ostring_data, sam_track_id, 2, 2),
662*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response_2, encrypted_data, sam_enc_nonce_or_sad, 3),
663*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_sam_response_2, int32, sam_nonce, 4),
664*ba7b222eSGlenn Barry };
optional_sam_response_2(const void * p)665*ba7b222eSGlenn Barry static unsigned int optional_sam_response_2(const void *p)
666*ba7b222eSGlenn Barry {
667*ba7b222eSGlenn Barry     const krb5_sam_response_2 *val = p;
668*ba7b222eSGlenn Barry     unsigned int optional = 0;
669*ba7b222eSGlenn Barry 
670*ba7b222eSGlenn Barry     if (val->sam_track_id.length > 0) optional |= (1u << 2);
671*ba7b222eSGlenn Barry 
672*ba7b222eSGlenn Barry     return optional;
673*ba7b222eSGlenn Barry }
674*ba7b222eSGlenn Barry DEFSEQTYPE(sam_response_2, krb5_sam_response_2, sam_response_2_fields,
675*ba7b222eSGlenn Barry            optional_sam_response_2);
676*ba7b222eSGlenn Barry 
677*ba7b222eSGlenn Barry static const struct field_info predicted_sam_response_fields[] = {
678*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, encryption_key, sam_key, 0),
679*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, krb5_flags, sam_flags, 1),
680*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, kerberos_time, stime, 2),
681*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, int32, susec, 3),
682*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, realm_of_principal, client, 4),
683*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_predicted_sam_response, principal, client, 5),
684*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_predicted_sam_response, ostring_data, msd, 6, 6),
685*ba7b222eSGlenn Barry };
optional_predicted_sam_response(const void * p)686*ba7b222eSGlenn Barry static unsigned int optional_predicted_sam_response(const void *p)
687*ba7b222eSGlenn Barry {
688*ba7b222eSGlenn Barry     const krb5_predicted_sam_response *val = p;
689*ba7b222eSGlenn Barry     unsigned int optional = 0;
690*ba7b222eSGlenn Barry 
691*ba7b222eSGlenn Barry     if (val->msd.length > 0) optional |= (1u << 6);
692*ba7b222eSGlenn Barry 
693*ba7b222eSGlenn Barry     return optional;
694*ba7b222eSGlenn Barry }
695*ba7b222eSGlenn Barry DEFSEQTYPE(predicted_sam_response, krb5_predicted_sam_response,
696*ba7b222eSGlenn Barry            predicted_sam_response_fields,
697*ba7b222eSGlenn Barry            optional_predicted_sam_response);
698*ba7b222eSGlenn Barry 
699*ba7b222eSGlenn Barry static const struct field_info krb5_authenticator_fields[] = {
700*ba7b222eSGlenn Barry     /* Authenticator ::= [APPLICATION 2] SEQUENCE */
701*ba7b222eSGlenn Barry     /* authenticator-vno[0]     INTEGER */
702*ba7b222eSGlenn Barry     FIELD_INT_IMM(KVNO, 0),
703*ba7b222eSGlenn Barry     /* crealm[1]                        Realm */
704*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_authenticator, realm_of_principal, client, 1),
705*ba7b222eSGlenn Barry     /* cname[2]                 PrincipalName */
706*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_authenticator, principal, client, 2),
707*ba7b222eSGlenn Barry     /* cksum[3]                 Checksum OPTIONAL */
708*ba7b222eSGlenn Barry     FIELDOF_OPT(krb5_authenticator, checksum_ptr, checksum, 3, 3),
709*ba7b222eSGlenn Barry     /* cusec[4]                 INTEGER */
710*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_authenticator, int32, cusec, 4),
711*ba7b222eSGlenn Barry     /* ctime[5]                 KerberosTime */
712*ba7b222eSGlenn Barry     FIELDOF_NORM(krb5_authenticator,