xref: /titanic_52/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * src/lib/krb5/asn.1/asn1_k_decode.c
8  *
9  * Copyright 1994 by the Massachusetts Institute of Technology.
10  * All Rights Reserved.
11  *
12  * Export of this software from the United States of America may
13  *   require a specific license from the United States Government.
14  *   It is the responsibility of any person or organization contemplating
15  *   export to obtain such a license before exporting.
16  *
17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18  * distribute this software and its documentation for any purpose and
19  * without fee is hereby granted, provided that the above copyright
20  * notice appear in all copies and that both that copyright notice and
21  * this permission notice appear in supporting documentation, and that
22  * the name of M.I.T. not be used in advertising or publicity pertaining
23  * to distribution of the software without specific, written prior
24  * permission.  Furthermore if you modify this software you must label
25  * your software as modified software and not distribute it in such a
26  * fashion that it might be confused with the original M.I.T. software.
27  * M.I.T. makes no representations about the suitability of
28  * this software for any purpose.  It is provided "as is" without express
29  * or implied warranty.
30  */
31 
32 #include "asn1_k_decode.h"
33 #include "asn1_decode.h"
34 #include "asn1_get.h"
35 #include "asn1_misc.h"
36 
37 /* Declare useful decoder variables. */
38 #define setup()					\
39   asn1_error_code retval;			\
40   asn1_class asn1class;				\
41   asn1_construction construction;		\
42   asn1_tagnum tagnum;				\
43   unsigned int length, taglen
44 
45 #define unused_var(x) if (0) { x = 0; x = x - x; }
46 
47 /* This is used for prefetch of next tag in sequence. */
48 #define next_tag()								\
49 { taginfo t2;									\
50   retval = asn1_get_tag_2(&subbuf, &t2);					\
51   if (retval) return retval;							\
52   /* Copy out to match previous functionality, until better integrated.  */	\
53   asn1class = t2.asn1class;							\
54   construction = t2.construction;						\
55   tagnum = t2.tagnum;								\
56   taglen = t2.length;								\
57   indef = t2.indef;								\
58 }
59 
60 /* Force check for EOC tag. */
61 #define get_eoc()									\
62     {											\
63 	taginfo t3;									\
64 	retval = asn1_get_tag_2(&subbuf, &t3);						\
65 	if(retval) return retval;							\
66         if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
67 	    return ASN1_MISSING_EOC;							\
68         /* Copy out to match previous functionality, until better integrated.  */	\
69 	asn1class = t3.asn1class;							\
70 	construction = t3.construction;							\
71 	tagnum = t3.tagnum;								\
72 	taglen = t3.length;								\
73 	indef = t3.indef;								\
74     }
75 
76 #define alloc_field(var, type)			\
77   var = (type*)calloc(1, sizeof(type));		\
78   if ((var) == NULL) return ENOMEM
79 
80 /* Fetch an expected APPLICATION class tag and verify. */
81 #define apptag(tagexpect)								\
82   {											\
83       taginfo t1;									\
84       retval = asn1_get_tag_2(buf, &t1);						\
85       if (retval) return retval;						   	\
86       if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
87 	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
88       /* Copy out to match previous functionality, until better integrated.  */		\
89       asn1class = t1.asn1class;								\
90       construction = t1.construction;							\
91       tagnum = t1.tagnum;								\
92       applen = t1.length;								\
93   }
94 
95 /**** normal fields ****/
96 
97 /*
98  * get_field_body
99  *
100  * Get bare field.  This also prefetches the next tag.  The call to
101  * get_eoc() assumes that any values fetched by this macro are
102  * enclosed in a context-specific tag.
103  */
104 #define get_field_body(var, decoder)		\
105   retval = decoder(&subbuf, &(var));		\
106   if (retval) return retval;			\
107   if (!taglen && indef) { get_eoc(); }		\
108   next_tag()
109 
110 /*
111  * get_field
112  *
113  * Get field having an expected context specific tag.  This assumes
114  * that context-specific tags are monotonically increasing in its
115  * verification of tag numbers.
116  */
117 #define get_field(var, tagexpect, decoder)				\
118   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
119   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
120   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
121       && (tagnum || taglen || asn1class != UNIVERSAL))			\
122     return ASN1_BAD_ID;							\
123   get_field_body(var,decoder)
124 
125 /*
126  * opt_field
127  *
128  * Get an optional field with an expected context specific tag.
129  * Assumes that OPTVAL will have the default value, thus failing to
130  * distinguish between absent optional values and present optional
131  * values that happen to have the value of OPTVAL.
132  */
133 #define opt_field(var, tagexpect, decoder, optvalue)			\
134   if (asn1buf_remains(&subbuf, seqindef)) {				\
135     if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
136 	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
137       return ASN1_BAD_ID;						\
138     if (tagnum == (tagexpect)) {					\
139       get_field_body(var, decoder);					\
140     } else var = optvalue;						\
141   }
142 
143 /**** fields w/ length ****/
144 
145 /* similar to get_field_body */
146 #define get_lenfield_body(len, var, decoder)	\
147   retval = decoder(&subbuf, &(len), &(var));	\
148   if (retval) return retval;			\
149   if (!taglen && indef) { get_eoc(); }		\
150   next_tag()
151 
152 /* similar to get_field_body */
153 #define get_lenfield(len, var, tagexpect, decoder)			\
154   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
155   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
156   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
157       && (tagnum || taglen || asn1class != UNIVERSAL))			\
158     return ASN1_BAD_ID;							\
159   get_lenfield_body(len, var, decoder)
160 
161 /* similar to opt_field */
162 #define opt_lenfield(len, var, tagexpect, decoder)	\
163   if (tagnum == (tagexpect)) {				\
164     get_lenfield_body(len, var, decoder);		\
165   } else { len = 0; var = 0; }
166 
167 /*
168  * Deal with implicitly tagged fields
169  */
170 #define get_implicit_octet_string(len, var, tagexpect)		    \
171   if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD;		    \
172   if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE)   \
173      return ASN1_BAD_ID;					    \
174   retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));	    \
175   if (retval) return retval;					    \
176   (len) = taglen;						    \
177   next_tag()
178 
179 #define opt_implicit_octet_string(len, var, tagexpect)		    \
180   if (tagnum == (tagexpect)) {					    \
181     if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
182 	return ASN1_BAD_ID;					    \
183     retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));   \
184     if (retval) return retval;					    \
185     (len) = taglen;						    \
186     next_tag();							    \
187   } else { (len) = 0; (var) = NULL; }
188 
189 /*
190  * begin_structure
191  *
192  * Declares some variables for decoding SEQUENCE types.  This is meant
193  * to be called in an inner block that ends with a call to
194  * end_structure().
195  */
196 #define begin_structure()					\
197   asn1buf subbuf;						\
198   int seqindef;							\
199   int indef;							\
200   retval = asn1_get_sequence(buf, &length, &seqindef);		\
201   if (retval) return retval;					\
202   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
203   if (retval) return retval;					\
204   next_tag()
205 
206 /*
207  * This is used for structures which have no tagging.
208  * It is the same as begin_structure() except next_tag()
209  * is not called.
210  */
211 #define begin_structure_no_tag()				\
212   asn1buf subbuf;						\
213   int seqindef;							\
214   int indef;							\
215   retval = asn1_get_sequence(buf, &length, &seqindef);		\
216   if (retval) return retval;					\
217   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
218   if (retval) return retval
219 
220 /* skip trailing garbage */
221 #define end_structure()						\
222   retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
223 			length, indef, seqindef);		\
224   if (retval) return retval
225 
226 /*
227  * begin_choice
228  *
229  * Declares some variables for decoding CHOICE types.  This is meant
230  * to be called in an inner block that ends with a call to
231  * end_choice().
232  */
233 #define begin_choice()						\
234   asn1buf subbuf;						\
235   int seqindef;							\
236   int indef;							\
237   taginfo t;							\
238   retval = asn1_get_tag_2(buf, &t);				\
239   if (retval) return retval;					\
240   tagnum = t.tagnum;                                            \
241   taglen = t.length;                                            \
242   indef = t.indef;                                              \
243   length = t.length;                                            \
244   seqindef = t.indef;                                           \
245   asn1class = t.asn1class;					\
246   construction = t.construction;				\
247   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
248   if (retval) return retval
249 
250 /* skip trailing garbage */
251 #define end_choice()						\
252   length -= t.length;						\
253   retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum,	\
254 			length, t.indef, seqindef);		\
255   if (retval) return retval
256 
257 /*
258  * sequence_of
259  *
260  * Declares some variables for decoding SEQUENCE OF types.  This is
261  * meant to be called in an inner block that ends with a call to
262  * end_sequence_of().
263  */
264 #define sequence_of(buf)			\
265   unsigned int length, taglen;			\
266   asn1_class asn1class;				\
267   asn1_construction construction;		\
268   asn1_tagnum tagnum;				\
269   int indef;					\
270   sequence_of_common(buf)
271 
272 /*
273  * sequence_of_no_tagvars
274  *
275  * This is meant for use inside decoder functions that have an outer
276  * sequence structure and thus declares variables of different names
277  * than does sequence_of() to avoid shadowing.
278  */
279 #define sequence_of_no_tagvars(buf)		\
280   asn1_class eseqclass;				\
281   asn1_construction eseqconstr;			\
282   asn1_tagnum eseqnum;				\
283   unsigned int eseqlen;				\
284   int eseqindef;				\
285   sequence_of_common(buf)
286 
287 /*
288  * sequence_of_common
289  *
290  * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
291  * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
292  * does not prefetch the next tag.
293  */
294 #define sequence_of_common(buf)					\
295   int size = 0;							\
296   asn1buf seqbuf;						\
297   int seqofindef;						\
298   retval = asn1_get_sequence(buf, &length, &seqofindef);	\
299   if (retval) return retval;					\
300   retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
301   if (retval) return retval
302 
303 /*
304  * end_sequence_of
305  *
306  * Attempts to fetch an EOC tag, if any, and to sync over trailing
307  * garbage, if any.
308  */
309 #define end_sequence_of(buf)							\
310   {										\
311       taginfo t4;								\
312       retval = asn1_get_tag_2(&seqbuf, &t4);					\
313       if (retval) return retval;						\
314       /* Copy out to match previous functionality, until better integrated.  */	\
315       asn1class = t4.asn1class;							\
316       construction = t4.construction;						\
317       tagnum = t4.tagnum;							\
318       taglen = t4.length;							\
319       indef = t4.indef;								\
320   }										\
321   retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
322 			length, indef, seqofindef);				\
323   if (retval) return retval;
324 
325 /*
326  * end_sequence_of_no_tagvars
327  *
328  * Like end_sequence_of(), but uses the different (non-shadowing)
329  * variable names.
330  */
331 #define end_sequence_of_no_tagvars(buf)						\
332   {										\
333       taginfo t5;								\
334       retval = asn1_get_tag_2(&seqbuf, &t5);					\
335       if (retval) return retval;						\
336       /* Copy out to match previous functionality, until better integrated.  */	\
337       eseqclass = t5.asn1class;							\
338       eseqconstr = t5.construction;						\
339       eseqnum = t5.tagnum;							\
340       eseqlen = t5.length;							\
341       eseqindef = t5.indef;							\
342   }										\
343   retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
344 			eseqlen, eseqindef, seqofindef);			\
345   if (retval) return retval;
346 
347 #define cleanup()				\
348   return 0
349 
350 /* scalars */
351 asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
352 {
353     time_t	t;
354     asn1_error_code retval;
355 
356     retval =  asn1_decode_generaltime(buf,&t);
357     if (retval)
358 	return retval;
359 
360     *val = t;
361     return 0;
362 }
363 
364 #define integer_convert(fname,ktype)\
365 asn1_error_code fname(asn1buf * buf, ktype * val)\
366 {\
367   asn1_error_code retval;\
368   long n;\
369   retval = asn1_decode_integer(buf,&n);\
370   if(retval) return retval;\
371   *val = (ktype)n;\
372   return 0;\
373 }
374 #define unsigned_integer_convert(fname,ktype)\
375 asn1_error_code fname(asn1buf * buf, ktype * val)\
376 {\
377   asn1_error_code retval;\
378   unsigned long n;\
379   retval = asn1_decode_unsigned_integer(buf,&n);\
380   if(retval) return retval;\
381   *val = (ktype)n;\
382   return 0;\
383 }
384 integer_convert(asn1_decode_int,int)
385 integer_convert(asn1_decode_int32,krb5_int32)
386 integer_convert(asn1_decode_kvno,krb5_kvno)
387 integer_convert(asn1_decode_enctype,krb5_enctype)
388 integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
389 integer_convert(asn1_decode_octet,krb5_octet)
390 integer_convert(asn1_decode_addrtype,krb5_addrtype)
391 integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
392 unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
393 unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
394 
395 asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
396 {
397   asn1_error_code retval;
398   unsigned long n;
399 
400   retval = asn1_decode_maybe_unsigned(buf, &n);
401   if (retval) return retval;
402   *val = (krb5_ui_4)n & 0xffffffff;
403   return 0;
404 }
405 
406 asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
407 {
408   asn1_error_code retval;
409   unsigned long n;
410 
411   retval = asn1_decode_unsigned_integer(buf,&n);
412   if(retval) return retval;
413 
414   *val = (krb5_msgtype) n;
415   return 0;
416 }
417 
418 
419 /* structures */
420 asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
421 {
422   return asn1_decode_generalstring(buf,
423 				   &((*val)->realm.length),
424 				   &((*val)->realm.data));
425 }
426 
427 asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
428 {
429   setup();
430   { begin_structure();
431     get_field((*val)->type,0,asn1_decode_int32);
432 
433     { sequence_of_no_tagvars(&subbuf);
434       while(asn1buf_remains(&seqbuf,seqofindef) > 0){
435 	size++;
436 	if ((*val)->data == NULL)
437 	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
438 	else
439 	  (*val)->data = (krb5_data*)realloc((*val)->data,
440 					     size*sizeof(krb5_data));
441 	if((*val)->data == NULL) return ENOMEM;
442 	retval = asn1_decode_generalstring(&seqbuf,
443 					   &((*val)->data[size-1].length),
444 					   &((*val)->data[size-1].data));
445 	if(retval) return retval;
446       }
447       (*val)->length = size;
448       end_sequence_of_no_tagvars(&subbuf);
449     }
450     if (indef) {
451 	get_eoc();
452     }
453     next_tag();
454     end_structure();
455     (*val)->magic = KV5M_PRINCIPAL;
456   }
457   cleanup();
458 }
459 
460 asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
461 {
462   setup();
463   { begin_structure();
464     get_field(val->checksum_type,0,asn1_decode_cksumtype);
465     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
466     end_structure();
467     val->magic = KV5M_CHECKSUM;
468   }
469   cleanup();
470 }
471 
472 asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
473 {
474   setup();
475   { begin_structure();
476     get_field(val->enctype,0,asn1_decode_enctype);
477     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
478     end_structure();
479     val->magic = KV5M_KEYBLOCK;
480   }
481   cleanup();
482 }
483 
484 asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
485 {
486   setup();
487   { begin_structure();
488     get_field(val->enctype,0,asn1_decode_enctype);
489     opt_field(val->kvno,1,asn1_decode_kvno,0);
490     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
491     end_structure();
492     val->magic = KV5M_ENC_DATA;
493   }
494   cleanup();
495 }
496 
497 asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
498 {
499   asn1_error_code retval;
500   asn1_octet unused, o;
501   taginfo t;
502   int i;
503   krb5_flags f=0;
504   unsigned int length;
505 
506   retval = asn1_get_tag_2(buf, &t);
507   if (retval) return retval;
508   if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
509       t.tagnum != ASN1_BITSTRING)
510       return ASN1_BAD_ID;
511   length = t.length;
512 
513   retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
514   if(retval) return retval;
515 
516   /* Number of unused bits must be between 0 and 7. */
517   if (unused > 7) return ASN1_BAD_FORMAT;
518   length--;
519 
520   for(i = 0; i < length; i++) {
521     retval = asn1buf_remove_octet(buf,&o);
522     if(retval) return retval;
523     /* ignore bits past number 31 */
524     if (i < 4)
525       f = (f<<8) | ((krb5_flags)o&0xFF);
526   }
527   if (length <= 4) {
528     /* Mask out unused bits, but only if necessary. */
529     f &= ~(krb5_flags)0 << unused;
530   }
531   /* left-justify */
532   if (length < 4)
533     f <<= (4 - length) * 8;
534   *val = f;
535   return 0;
536 }
537 
538 asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
539 { return asn1_decode_krb5_flags(buf,val); }
540 
541 asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
542 { return asn1_decode_krb5_flags(buf,val); }
543 
544 asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
545 { return asn1_decode_krb5_flags(buf,val); }
546 
547 asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
548 {
549   setup();
550   { begin_structure();
551     get_field(val->tr_type,0,asn1_decode_octet);
552     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
553     end_structure();
554     val->magic = KV5M_TRANSITED;
555   }
556   cleanup();
557 }
558 
559 asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
560 {
561   setup();
562   { begin_structure();
563     alloc_field(val->session,krb5_keyblock);
564     get_field(*(val->session),0,asn1_decode_encryption_key);
565     get_field(val->last_req,1,asn1_decode_last_req);
566     get_field(val->nonce,2,asn1_decode_int32);
567     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
568     get_field(val->flags,4,asn1_decode_ticket_flags);
569     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
570     /* Set to authtime if missing */
571     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
572     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
573     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
574     alloc_field(val->server,krb5_principal_data);
575     get_field(val->server,9,asn1_decode_realm);
576     get_field(val->server,10,asn1_decode_principal_name);
577     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
578     end_structure();
579     val->magic = KV5M_ENC_KDC_REP_PART;
580   }
581   cleanup();
582 }
583 
584 asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
585 {
586   setup();
587   unsigned int applen;
588   apptag(1);
589   { begin_structure();
590     { krb5_kvno vno;
591       get_field(vno,0,asn1_decode_kvno);
592       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
593     alloc_field(val->server,krb5_principal_data);
594     get_field(val->server,1,asn1_decode_realm);
595     get_field(val->server,2,asn1_decode_principal_name);
596     get_field(val->enc_part,3,asn1_decode_encrypted_data);
597     end_structure();
598     val->magic = KV5M_TICKET;
599   }
600   if (!applen) {
601       taginfo t;
602       retval = asn1_get_tag_2(buf, &t);
603       if (retval) return retval;
604   }
605   cleanup();
606 }
607 
608 asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
609 {
610   setup();
611   { begin_structure();
612     { krb5_kvno kvno;
613       get_field(kvno,1,asn1_decode_kvno);
614       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
615     get_field(val->msg_type,2,asn1_decode_msgtype);
616     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
617     get_field(*val,4,asn1_decode_kdc_req_body);
618     end_structure();
619     val->magic = KV5M_KDC_REQ;
620   }
621   cleanup();
622 }
623 
624 asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
625 {
626   setup();
627   {
628     krb5_principal psave;
629     begin_structure();
630     get_field(val->kdc_options,0,asn1_decode_kdc_options);
631     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
632     opt_field(val->client,1,asn1_decode_principal_name,NULL);
633     alloc_field(val->server,krb5_principal_data);
634     get_field(val->server,2,asn1_decode_realm);
635     if(val->client != NULL){
636       retval = asn1_krb5_realm_copy(val->client,val->server);
637       if(retval) return retval; }
638 
639     /* If opt_field server is missing, memory reference to server is
640        lost and results in memory leak */
641     psave = val->server;
642     opt_field(val->server,3,asn1_decode_principal_name,NULL);
643     if(val->server == NULL){
644       if(psave->realm.data) {
645 	free(psave->realm.data);
646 	psave->realm.data = NULL;
647 	psave->realm.length=0;
648       }
649       free(psave);
650     }
651     opt_field(val->from,4,asn1_decode_kerberos_time,0);
652     get_field(val->till,5,asn1_decode_kerberos_time);
653     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
654     get_field(val->nonce,7,asn1_decode_int32);
655     get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
656     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
657     if(tagnum == 10){
658       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
659     else{
660       val->authorization_data.magic = KV5M_ENC_DATA;
661       val->authorization_data.enctype = 0;
662       val->authorization_data.kvno = 0;
663       val->authorization_data.ciphertext.data = NULL;
664       val->authorization_data.ciphertext.length = 0;
665     }
666     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
667     end_structure();
668     val->magic = KV5M_KDC_REQ;
669   }
670   cleanup();
671 }
672 
673 asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
674 {
675   setup();
676   { begin_structure();
677     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
678     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
679     opt_field(val->usec,2,asn1_decode_int32,0);
680     opt_field(val->seq_number,3,asn1_decode_seqnum,0);
681     alloc_field(val->s_address,krb5_address);
682     get_field(*(val->s_address),4,asn1_decode_host_address);
683     if(tagnum == 5){
684       alloc_field(val->r_address,krb5_address);
685       get_field(*(val->r_address),5,asn1_decode_host_address);
686     } else val->r_address = NULL;
687     end_structure();
688     val->magic = KV5M_SAFE;
689   }
690   cleanup();
691 }
692 
693 asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
694 {
695   setup();
696   { begin_structure();
697     get_field(val->addrtype,0,asn1_decode_addrtype);
698     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
699     end_structure();
700     val->magic = KV5M_ADDRESS;
701   }
702   cleanup();
703 }
704 
705 asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
706 {
707   setup();
708   { begin_structure();
709     { krb5_kvno pvno;
710       get_field(pvno,0,asn1_decode_kvno);
711       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
712     get_field(val->msg_type,1,asn1_decode_msgtype);
713     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
714     alloc_field(val->client,krb5_principal_data);
715     get_field(val->client,3,asn1_decode_realm);
716     get_field(val->client,4,asn1_decode_principal_name);
717     alloc_field(val->ticket,krb5_ticket);
718     get_field(*(val->ticket),5,asn1_decode_ticket);
719     get_field(val->enc_part,6,asn1_decode_encrypted_data);
720     end_structure();
721     val->magic = KV5M_KDC_REP;
722   }
723   cleanup();
724 }
725 
726 
727 /* arrays */
728 #define get_element(element,decoder)\
729 retval = decoder(&seqbuf,element);\
730 if(retval) return retval
731 
732 #define array_append(array,size,element,type)\
733 size++;\
734 if (*(array) == NULL)\
735      *(array) = (type**)malloc((size+1)*sizeof(type*));\
736 else\
737   *(array) = (type**)realloc(*(array),\
738 			     (size+1)*sizeof(type*));\
739 if(*(array) == NULL) return ENOMEM;\
740 (*(array))[(size)-1] = elt
741 
742 #define decode_array_body(type,decoder)\
743   asn1_error_code retval;\
744   type *elt;\
745 \
746   { sequence_of(buf);\
747     while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
748       alloc_field(elt,type);\
749       get_element(elt,decoder);\
750       array_append(val,size,elt,type);\
751     }\
752     if (*val == NULL)\
753 	*val = (type **)malloc(sizeof(type*));\
754     (*val)[size] = NULL;\
755     end_sequence_of(buf);\
756   }\
757   cleanup()
758 
759 
760 asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
761 {
762   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
763 }
764 
765 asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
766 {
767   setup();
768   { begin_structure();
769     get_field(val->ad_type,0,asn1_decode_authdatatype);
770     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
771     end_structure();
772     val->magic = KV5M_AUTHDATA;
773   }
774   cleanup();
775 }
776 
777 asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
778 {
779   decode_array_body(krb5_address,asn1_decode_host_address);
780 }
781 
782 asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
783 {
784   decode_array_body(krb5_ticket,asn1_decode_ticket);
785 }
786 
787 asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
788 {
789   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
790 }
791 
792 asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
793 {
794   setup();
795   { begin_structure();
796     alloc_field(val->session,krb5_keyblock);
797     get_field(*(val->session),0,asn1_decode_encryption_key);
798     if(tagnum == 1){
799       alloc_field(val->client,krb5_principal_data);
800       opt_field(val->client,1,asn1_decode_realm,NULL);
801       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
802     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
803     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
804     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
805     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
806     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
807     if(tagnum == 8){
808       alloc_field(val->server,krb5_principal_data);
809       opt_field(val->server,8,asn1_decode_realm,NULL);
810       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
811     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
812     end_structure();
813     val->magic = KV5M_CRED_INFO;
814   }
815   cleanup();
816 }
817 
818 asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
819 {
820   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
821 }
822 
823 asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
824 {
825   setup();
826   { begin_structure();
827     get_field(val->pa_type,1,asn1_decode_int32);
828     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
829     end_structure();
830     val->magic = KV5M_PA_DATA;
831   }
832   cleanup();
833 }
834 
835 asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
836 {
837   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
838 }
839 
840 asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
841 {
842   setup();
843   { begin_structure();
844     get_field(val->lr_type,0,asn1_decode_int32);
845     get_field(val->value,1,asn1_decode_kerberos_time);
846     end_structure();
847     val->magic = KV5M_LAST_REQ_ENTRY;
848 #ifdef KRB5_GENEROUS_LR_TYPE
849     /* If we are only a single byte wide and negative - fill in the
850        other bits */
851     if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
852 #endif
853   }
854   cleanup();
855 }
856 
857 asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
858 {
859   asn1_error_code retval;
860   { sequence_of(buf);
861     while(asn1buf_remains(&seqbuf,seqofindef) > 0){
862       size++;
863       if (*val == NULL)
864         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
865       else
866         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
867       if(*val == NULL) return ENOMEM;
868       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
869       if(retval) return retval;
870     }
871     *num = size;
872     end_sequence_of(buf);
873   }
874   cleanup();
875 }
876 
877 asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
878 {
879   decode_array_body(krb5_checksum, asn1_decode_checksum);
880 }
881 
882 static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
883 {
884   /*
885    * Solaris Kerberos:
886    * Use a temporary char* (tmpp) in place of val->salt when calling
887    * get_lenfield(). val->salt cannot be cast to a char* as casting will not
888    * produce an lvalue. Use the new value pointed to by tmpp as the value for
889    * val->salt.
890    */
891   char *tmpp;
892   setup();
893   { begin_structure();
894     get_field(val->etype,0,asn1_decode_enctype);
895     if (tagnum == 1) {
896       get_lenfield(val->length,tmpp,1,asn1_decode_generalstring);
897       val->salt = (krb5_octet*)tmpp;	/* SUNW14resync hack */
898     } else {
899 	    val->length = KRB5_ETYPE_NO_SALT;
900 	    val->salt = 0;
901     }
902     if ( tagnum ==2) {
903       krb5_octet *params ;
904       get_lenfield( val->s2kparams.length, params,
905 		      2, asn1_decode_octetstring);
906       val->s2kparams.data = ( char *) params;
907     } else {
908 	val->s2kparams.data = NULL;
909 	val->s2kparams.length = 0;
910     }
911     end_structure();
912     val->magic = KV5M_ETYPE_INFO_ENTRY;
913   }
914   cleanup();
915 }
916 
917 static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
918 {
919   setup();
920   { begin_structure();
921     get_field(val->etype,0,asn1_decode_enctype);
922     if (tagnum == 1) {
923 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
924     } else {
925 	    val->length = KRB5_ETYPE_NO_SALT;
926 	    val->salt = 0;
927     }
928     if ( tagnum ==2) {
929       krb5_octet *params ;
930       get_lenfield( val->s2kparams.length, params,
931 		      2, asn1_decode_octetstring);
932       val->s2kparams.data = ( char *) params;
933     } else {
934 	val->s2kparams.data = NULL;
935 	val->s2kparams.length = 0;
936     }
937     end_structure();
938     val->magic = KV5M_ETYPE_INFO_ENTRY;
939   }
940   cleanup();
941 }
942 
943 
944 static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
945 {
946   setup();
947   { begin_structure();
948     get_field(val->etype,0,asn1_decode_enctype);
949     if (tagnum == 1) {
950 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
951     } else {
952 	    val->length = KRB5_ETYPE_NO_SALT;
953 	    val->salt = 0;
954     }
955     val->s2kparams.data = NULL;
956     val->s2kparams.length = 0;
957 
958     end_structure();
959     val->magic = KV5M_ETYPE_INFO_ENTRY;
960   }
961   cleanup();
962 }
963 
964 asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
965 {
966   decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
967 }
968 
969 asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
970 					krb5_boolean v1_3_behavior)
971 {
972     if (v1_3_behavior) {
973 	decode_array_body(krb5_etype_info_entry,
974 			  asn1_decode_etype_info2_entry_1_3);
975     } else {
976 	decode_array_body(krb5_etype_info_entry,
977 			  asn1_decode_etype_info2_entry);
978     }
979 }
980 
981 asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
982 {
983   setup();
984   { begin_structure();
985     alloc_field(val->passwd,krb5_data);
986     get_lenfield(val->passwd->length,val->passwd->data,
987 		 0,asn1_decode_charstring);
988     val->passwd->magic = KV5M_DATA;
989     alloc_field(val->phrase,krb5_data);
990     get_lenfield(val->phrase->length,val->phrase->data,
991 		 1,asn1_decode_charstring);
992     val->phrase->magic = KV5M_DATA;
993     end_structure();
994     val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
995   }
996   cleanup();
997 }
998 
999 asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
1000 {
1001   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
1002 }
1003 
1004 asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
1005 { return asn1_decode_krb5_flags(buf,val); }
1006 
1007 #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
1008 #define opt_cksum(var,tagexpect,decoder)\
1009 if(tagnum == (tagexpect)){\
1010   get_field_body(var,decoder); }\
1011 else var.length = 0
1012 
1013 asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
1014 {
1015   setup();
1016   { begin_structure();
1017     get_field(val->sam_type,0,asn1_decode_int32);
1018     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1019     opt_string(val->sam_type_name,2,asn1_decode_charstring);
1020     opt_string(val->sam_track_id,3,asn1_decode_charstring);
1021     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
1022     opt_string(val->sam_challenge,5,asn1_decode_charstring);
1023     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
1024     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
1025     opt_field(val->sam_nonce,8,asn1_decode_int32,0);
1026     opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
1027     end_structure();
1028     val->magic = KV5M_SAM_CHALLENGE;
1029   }
1030   cleanup();
1031 }
1032 asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
1033 {
1034   setup();
1035   { char *save, *end;
1036     size_t alloclen;
1037     begin_structure();
1038     if (tagnum != 0) return ASN1_MISSING_FIELD;
1039     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
1040       return ASN1_BAD_ID;
1041     save = subbuf.next;
1042     { sequence_of_no_tagvars(&subbuf);
1043       unused_var(size);
1044       end_sequence_of_no_tagvars(&subbuf);
1045     }
1046     end = subbuf.next;
1047     alloclen = end - save;
1048     if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
1049       return ENOMEM;
1050     val->sam_challenge_2_body.length = alloclen;
1051     memcpy(val->sam_challenge_2_body.data, save, alloclen);
1052     next_tag();
1053     get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
1054     end_structure();
1055   }
1056   cleanup();
1057 }
1058 asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
1059 {
1060   setup();
1061   { begin_structure();
1062     get_field(val->sam_type,0,asn1_decode_int32);
1063     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1064     opt_string(val->sam_type_name,2,asn1_decode_charstring);
1065     opt_string(val->sam_track_id,3,asn1_decode_charstring);
1066     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
1067     opt_string(val->sam_challenge,5,asn1_decode_charstring);
1068     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
1069     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
1070     get_field(val->sam_nonce,8,asn1_decode_int32);
1071     get_field(val->sam_etype, 9, asn1_decode_int32);
1072     end_structure();
1073     val->magic = KV5M_SAM_CHALLENGE;
1074   }
1075   cleanup();
1076 }
1077 asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
1078 {
1079   setup();
1080   { begin_structure();
1081     /* alloc_field(val->sam_key,krb5_keyblock); */
1082     get_field(val->sam_key,0,asn1_decode_encryption_key);
1083     end_structure();
1084     val->magic = KV5M_SAM_KEY;
1085   }
1086   cleanup();
1087 }
1088 
1089 asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
1090 {
1091   setup();
1092   { begin_structure();
1093     opt_field(val->sam_nonce,0,asn1_decode_int32,0);
1094     opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
1095     opt_field(val->sam_usec,2,asn1_decode_int32,0);
1096     opt_string(val->sam_sad,3,asn1_decode_charstring);
1097     end_structure();
1098     val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
1099   }
1100   cleanup();
1101 }
1102 
1103 asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
1104 {
1105   setup();
1106   { begin_structure();
1107     get_field(val->sam_nonce,0,asn1_decode_int32);
1108     opt_string(val->sam_sad,1,asn1_decode_charstring);
1109     end_structure();
1110     val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
1111   }
1112   cleanup();
1113 }
1114 
1115 #define opt_encfield(fld,tag,fn) \
1116     if(tagnum == tag){ \
1117       get_field(fld,tag,fn); } \
1118     else{\
1119       fld.magic = 0;\
1120       fld.enctype = 0;\
1121       fld.kvno = 0;\
1122       fld.ciphertext.data = NULL;\
1123       fld.ciphertext.length = 0;\
1124     }
1125 
1126 asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
1127 {
1128   setup();
1129   { begin_structure();
1130     get_field(val->sam_type,0,asn1_decode_int32);
1131     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1132     opt_string(val->sam_track_id,2,asn1_decode_charstring);
1133     opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
1134     get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
1135     opt_field(val->sam_nonce,5,asn1_decode_int32,0);
1136     opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
1137     end_structure();
1138     val->magic = KV5M_SAM_RESPONSE;
1139   }
1140   cleanup();
1141 }
1142 
1143 asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
1144 {
1145   setup();
1146   { begin_structure();
1147     get_field(val->sam_type,0,asn1_decode_int32);
1148     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1149     opt_string(val->sam_track_id,2,asn1_decode_charstring);
1150     get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
1151     get_field(val->sam_nonce,4,asn1_decode_int32);
1152     end_structure();
1153     val->magic = KV5M_SAM_RESPONSE;
1154   }
1155   cleanup();
1156 }
1157 
1158 
1159 asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
1160 {
1161   setup();
1162   { begin_structure();
1163     get_field(val->sam_key,0,asn1_decode_encryption_key);
1164     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1165     get_field(val->stime,2,asn1_decode_kerberos_time);
1166     get_field(val->susec,3,asn1_decode_int32);
1167     alloc_field(val->client,krb5_principal_data);
1168     get_field(val->client,4,asn1_decode_realm);
1169     get_field(val->client,5,asn1_decode_principal_name);
1170     opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
1171     end_structure();
1172     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
1173   }
1174   cleanup();
1175 }
1176 
1177 /* PKINIT */
1178 
1179 asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val)
1180 {
1181     setup();
1182     {
1183       begin_structure();
1184       opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0);
1185       opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1);
1186       opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2);
1187       end_structure();
1188     }
1189     cleanup();
1190 }
1191 
1192 asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val)
1193 {
1194     decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier);
1195 }
1196 
1197 asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val)
1198 {
1199   setup();
1200   {
1201     begin_structure();
1202     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1203     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL);
1204     opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2);
1205     end_structure();
1206   }
1207   cleanup();
1208 }
1209 
1210 #if 0	/* XXX   This needs to be tested!!! XXX */
1211 asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1212 {
1213     setup();
1214     {
1215       char *start, *end;
1216       size_t alloclen;
1217 
1218       begin_explicit_choice();
1219       if (t.tagnum == choice_trusted_cas_principalName) {
1220 	val->choice = choice_trusted_cas_principalName;
1221       } else if (t.tagnum == choice_trusted_cas_caName) {
1222 	val->choice = choice_trusted_cas_caName;
1223 	start = subbuf.next;
1224 	{
1225 	  sequence_of_no_tagvars(&subbuf);
1226 	  unused_var(size);
1227 	  end_sequence_of_no_tagvars(&subbuf);
1228 	}
1229 	end = subbuf.next;
1230 	alloclen = end - start;
1231 	val->u.caName.data = malloc(alloclen);
1232 	if (val->u.caName.data == NULL)
1233 	  return ENOMEM;
1234 	memcpy(val->u.caName.data, start, alloclen);
1235 	val->u.caName.length = alloclen;
1236 	next_tag();
1237       } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
1238 	val->choice = choice_trusted_cas_issuerAndSerial;
1239 	start = subbuf.next;
1240 	{
1241 	  sequence_of_no_tagvars(&subbuf);
1242 	  unused_var(size);
1243 	  end_sequence_of_no_tagvars(&subbuf);
1244 	}
1245 	end = subbuf.next;
1246 	alloclen = end - start;
1247 	val->u.issuerAndSerial.data = malloc(alloclen);
1248 	if (val->u.issuerAndSerial.data == NULL)
1249 	  return ENOMEM;
1250 	memcpy(val->u.issuerAndSerial.data, start, alloclen);
1251 	val->u.issuerAndSerial.length = alloclen;
1252 	next_tag();
1253       } else return ASN1_BAD_ID;
1254       end_explicit_choice();
1255     }
1256     cleanup();
1257 }
1258 #else
1259 asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1260 {
1261     setup();
1262     { begin_choice();
1263       if (tagnum == choice_trusted_cas_principalName) {
1264 	val->choice = choice_trusted_cas_principalName;
1265 	asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName));
1266       } else if (tagnum == choice_trusted_cas_caName) {
1267 	val->choice = choice_trusted_cas_caName;
1268 	get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName);
1269       } else if (tagnum == choice_trusted_cas_issuerAndSerial) {
1270 	val->choice = choice_trusted_cas_issuerAndSerial;
1271 	get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data,
1272 				  choice_trusted_cas_issuerAndSerial);
1273       } else return ASN1_BAD_ID;
1274       end_choice();
1275     }
1276     cleanup();
1277 }
1278 #endif
1279 
1280 asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val)
1281 {
1282     decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca);
1283 }
1284 
1285 asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val)
1286 {
1287   setup();
1288   { begin_structure();
1289     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1290     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL);
1291     opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring);
1292     opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring);
1293     end_structure();
1294   }
1295   cleanup();
1296 }
1297 
1298 asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val)
1299 {
1300     setup();
1301     { begin_structure();
1302       get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0);
1303 
1304       opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring);
1305       end_structure();
1306     }
1307     cleanup();
1308 }
1309 
1310 asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val)
1311 {
1312     setup();
1313     { begin_structure();
1314       get_field(val->cusec, 0, asn1_decode_int32);
1315       get_field(val->ctime, 1, asn1_decode_kerberos_time);
1316       get_field(val->nonce, 2, asn1_decode_int32);
1317       opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring);
1318       end_structure();
1319     }
1320     cleanup();
1321 }
1322 
1323 asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val)
1324 {
1325     setup();
1326     { begin_structure();
1327       alloc_field(val->kdcName,krb5_principal_data);
1328       get_field(val->kdcName, 0, asn1_decode_principal_name);
1329       get_field(val->kdcName, 1, asn1_decode_realm);
1330       get_field(val->cusec, 2, asn1_decode_int32);
1331       get_field(val->ctime, 3, asn1_decode_kerberos_time);
1332       get_field(val->nonce, 4, asn1_decode_int32);
1333       end_structure();
1334     }
1335     cleanup();
1336 }
1337 
1338 asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf,  krb5_algorithm_identifier *val) {
1339 
1340   setup();
1341   { begin_structure_no_tag();
1342     /*
1343      * Forbid indefinite encoding because we don't read enough tag
1344      * information from the trailing octets ("ANY DEFINED BY") to
1345      * synchronize EOC tags, etc.
1346      */
1347     if (seqindef) return ASN1_BAD_FORMAT;
1348     /*
1349      * Set up tag variables because we don't actually call anything
1350      * that fetches tag info for us; it's all buried in the decoder
1351      * primitives.
1352      */
1353     tagnum = ASN1_TAGNUM_CEILING;
1354     asn1class = UNIVERSAL;
1355     construction = PRIMITIVE;
1356     taglen = 0;
1357     indef = 0;
1358     retval = asn1_decode_oid(&subbuf, &val->algorithm.length,
1359 			     &val->algorithm.data);
1360     if(retval) return retval;
1361     val->parameters.length = 0;
1362     val->parameters.data = NULL;
1363 
1364     if(length > subbuf.next - subbuf.base) {
1365       unsigned int size = length - (subbuf.next - subbuf.base);
1366       retval = asn1buf_remove_octetstring(&subbuf, size,
1367 					  &val->parameters.data);
1368       if(retval) return retval;
1369       val->parameters.length = size;
1370     }
1371 
1372     end_structure();
1373   }
1374   cleanup();
1375 }
1376 
1377 asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val)
1378 {
1379     asn1_octet unused;
1380     setup();
1381     { begin_structure_no_tag();
1382 
1383       retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm);
1384       if (retval) return retval;
1385 
1386       /* SubjectPublicKey encoded as a BIT STRING */
1387       next_tag();
1388       if (asn1class != UNIVERSAL || construction != PRIMITIVE ||
1389           tagnum != ASN1_BITSTRING)
1390         return ASN1_BAD_ID;
1391 
1392       retval = asn1buf_remove_octet(&subbuf, &unused);
1393       if(retval) return retval;
1394 
1395       /* Number of unused bits must be between 0 and 7. */
1396       /* What to do if unused is not zero? */
1397       if (unused > 7) return ASN1_BAD_FORMAT;
1398       taglen--;
1399 
1400       val->subjectPublicKey.length = 0;
1401       val->subjectPublicKey.data = NULL;
1402       retval = asn1buf_remove_octetstring(&subbuf, taglen,
1403 					  &val->subjectPublicKey.data);
1404       if(retval) return retval;
1405       val->subjectPublicKey.length = taglen;
1406       /*
1407        * We didn't call any macro that does next_tag(); do so now to
1408        * preload tag of any trailing encodings.
1409        */
1410       next_tag();
1411       end_structure();
1412     }
1413     cleanup();
1414 }
1415 
1416 asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val)
1417 {
1418     decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier);
1419 }
1420 
1421 asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val)
1422 {
1423     setup();
1424     { begin_structure();
1425       retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data);
1426       if(retval) return retval;
1427       val->subjectPublicKey.length = taglen;
1428       next_tag();
1429       get_field(val->nonce, 1, asn1_decode_int32);
1430       opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0);
1431       end_structure();
1432     }
1433     cleanup();
1434 }
1435 
1436 asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val)
1437 {
1438     setup();
1439     { begin_structure();
1440       get_field(val->replyKey, 0, asn1_decode_encryption_key);
1441       get_field(val->asChecksum, 1, asn1_decode_checksum);
1442       end_structure();
1443     }
1444     cleanup();
1445 }
1446 
1447 asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val)
1448 {
1449     setup();
1450     { begin_structure();
1451       get_field(val->replyKey, 0, asn1_decode_encryption_key);
1452       get_field(val->nonce, 1, asn1_decode_int32);
1453       end_structure();
1454     }
1455     cleanup();
1456 }
1457 
1458 
1459 asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val)
1460 {
1461     setup();
1462     { begin_structure();
1463       get_field(*val, 0, asn1_decode_realm);
1464       get_field(*val, 1, asn1_decode_principal_name);
1465       end_structure();
1466     }
1467     cleanup();
1468 }
1469 
1470 asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val)
1471 {
1472     setup();
1473     { begin_structure();
1474       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator);
1475       if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); }
1476       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
1477       if (asn1buf_remains(&subbuf, seqindef)) {
1478 	if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
1479 	    && (tagnum || taglen || asn1class != UNIVERSAL))
1480 	  return ASN1_BAD_ID;
1481 	if (tagnum == 1) {
1482 	  retval = asn1_decode_subject_pk_info(&subbuf,
1483 					       val->clientPublicValue);
1484 	  if (!taglen && indef) { get_eoc(); }
1485 	  next_tag();
1486 	} else val->clientPublicValue = NULL;
1487       }
1488       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
1489       if (asn1buf_remains(&subbuf, seqindef)) {
1490         if (tagnum == 2) {
1491 	  asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes);
1492 	  if (!taglen && indef) { get_eoc(); }
1493 	  next_tag();
1494 	} else val->supportedCMSTypes = NULL;
1495       }
1496       opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring);
1497       end_structure();
1498     }
1499     cleanup();
1500 }
1501 
1502 asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val)
1503 {
1504     setup();
1505     { begin_structure();
1506       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9);
1507       if (tagnum == 1) {
1508 	alloc_field(val->clientPublicValue, krb5_subject_pk_info);
1509 	/* can't call opt_field because it does decoder(&subbuf, &(val)); */
1510 	if (asn1buf_remains(&subbuf, seqindef)) {
1511 	  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
1512 	    && (tagnum || taglen || asn1class != UNIVERSAL))
1513 	    return ASN1_BAD_ID;
1514 	  if (tagnum == 1) {
1515 	    retval = asn1_decode_subject_pk_info(&subbuf,
1516 					         val->clientPublicValue);
1517 	    if (!taglen && indef) { get_eoc(); }
1518 	    next_tag();
1519 	  } else val->clientPublicValue = NULL;
1520 	}
1521       }
1522       end_structure();
1523     }
1524     cleanup();
1525 }
1526 
1527 asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val)
1528 {
1529   setup();
1530   { begin_choice();
1531     if (tagnum == choice_pa_pk_as_rep_dhInfo) {
1532       val->choice = choice_pa_pk_as_rep_dhInfo;
1533       get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info);
1534     } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
1535       val->choice = choice_pa_pk_as_rep_encKeyPack;
1536       get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data,
1537 				choice_pa_pk_as_rep_encKeyPack);
1538     } else {
1539       val->choice = choice_pa_pk_as_rep_UNKNOWN;
1540     }
1541     end_choice();
1542   }
1543   cleanup();
1544 }
1545 
1546 asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val)
1547 {
1548   setup();
1549   { begin_structure();
1550     if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) {
1551       val->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
1552       get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data,
1553 		    choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring);
1554     } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
1555       val->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
1556       get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data,
1557 		    choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring);
1558     } else {
1559       val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN;
1560     }
1561     end_structure();
1562   }
1563   cleanup();
1564 }
1565 
1566 asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val)
1567 {
1568     decode_array_body(krb5_typed_data,asn1_decode_typed_data);
1569 }
1570 
1571 asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val)
1572 {
1573   setup();
1574   { begin_structure();
1575     get_field(val->type,0,asn1_decode_int32);
1576     get_lenfield(val->length,val->data,1,asn1_decode_octetstring);
1577     end_structure();
1578   }
1579   cleanup();
1580 }
1581