1505d05c7Sgtb /*
2*86aa8097Smp  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3505d05c7Sgtb  * Use is subject to license terms.
4505d05c7Sgtb  */
5505d05c7Sgtb 
67c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * src/lib/krb5/asn.1/asn1_k_decode.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 1994 by the Massachusetts Institute of Technology.
117c478bd9Sstevel@tonic-gate  * All Rights Reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "asn1_k_decode.h"
347c478bd9Sstevel@tonic-gate #include "asn1_decode.h"
357c478bd9Sstevel@tonic-gate #include "asn1_get.h"
367c478bd9Sstevel@tonic-gate #include "asn1_misc.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* Declare useful decoder variables. */
397c478bd9Sstevel@tonic-gate #define setup()					\
407c478bd9Sstevel@tonic-gate   asn1_error_code retval;			\
417c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
427c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
437c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
447c478bd9Sstevel@tonic-gate   unsigned int length, taglen
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #define unused_var(x) if (0) { x = 0; x = x - x; }
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /* This is used for prefetch of next tag in sequence. */
497c478bd9Sstevel@tonic-gate #define next_tag()								\
507c478bd9Sstevel@tonic-gate { taginfo t2;									\
517c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(&subbuf, &t2);					\
527c478bd9Sstevel@tonic-gate   if (retval) return retval;							\
537c478bd9Sstevel@tonic-gate   /* Copy out to match previous functionality, until better integrated.  */	\
547c478bd9Sstevel@tonic-gate   asn1class = t2.asn1class;							\
557c478bd9Sstevel@tonic-gate   construction = t2.construction;						\
567c478bd9Sstevel@tonic-gate   tagnum = t2.tagnum;								\
577c478bd9Sstevel@tonic-gate   taglen = t2.length;								\
587c478bd9Sstevel@tonic-gate   indef = t2.indef;								\
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /* Force check for EOC tag. */
627c478bd9Sstevel@tonic-gate #define get_eoc()									\
637c478bd9Sstevel@tonic-gate     {											\
647c478bd9Sstevel@tonic-gate 	taginfo t3;									\
657c478bd9Sstevel@tonic-gate 	retval = asn1_get_tag_2(&subbuf, &t3);						\
667c478bd9Sstevel@tonic-gate 	if(retval) return retval;							\
677c478bd9Sstevel@tonic-gate         if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
687c478bd9Sstevel@tonic-gate 	    return ASN1_MISSING_EOC;							\
697c478bd9Sstevel@tonic-gate         /* Copy out to match previous functionality, until better integrated.  */	\
707c478bd9Sstevel@tonic-gate 	asn1class = t3.asn1class;							\
717c478bd9Sstevel@tonic-gate 	construction = t3.construction;							\
727c478bd9Sstevel@tonic-gate 	tagnum = t3.tagnum;								\
737c478bd9Sstevel@tonic-gate 	taglen = t3.length;								\
747c478bd9Sstevel@tonic-gate 	indef = t3.indef;								\
757c478bd9Sstevel@tonic-gate     }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate #define alloc_field(var, type)			\
787c478bd9Sstevel@tonic-gate   var = (type*)calloc(1, sizeof(type));		\
797c478bd9Sstevel@tonic-gate   if ((var) == NULL) return ENOMEM
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /* Fetch an expected APPLICATION class tag and verify. */
827c478bd9Sstevel@tonic-gate #define apptag(tagexpect)								\
837c478bd9Sstevel@tonic-gate   {											\
847c478bd9Sstevel@tonic-gate       taginfo t1;									\
857c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t1);						\
867c478bd9Sstevel@tonic-gate       if (retval) return retval;						   	\
877c478bd9Sstevel@tonic-gate       if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
887c478bd9Sstevel@tonic-gate 	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
897c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */		\
907c478bd9Sstevel@tonic-gate       asn1class = t1.asn1class;								\
917c478bd9Sstevel@tonic-gate       construction = t1.construction;							\
927c478bd9Sstevel@tonic-gate       tagnum = t1.tagnum;								\
937c478bd9Sstevel@tonic-gate       applen = t1.length;								\
947c478bd9Sstevel@tonic-gate   }
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /**** normal fields ****/
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * get_field_body
1007c478bd9Sstevel@tonic-gate  *
1017c478bd9Sstevel@tonic-gate  * Get bare field.  This also prefetches the next tag.  The call to
1027c478bd9Sstevel@tonic-gate  * get_eoc() assumes that any values fetched by this macro are
1037c478bd9Sstevel@tonic-gate  * enclosed in a context-specific tag.
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate #define get_field_body(var, decoder)		\
1067c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(var));		\
1077c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1087c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1097c478bd9Sstevel@tonic-gate   next_tag()
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate  * get_field
1137c478bd9Sstevel@tonic-gate  *
1147c478bd9Sstevel@tonic-gate  * Get field having an expected context specific tag.  This assumes
1157c478bd9Sstevel@tonic-gate  * that context-specific tags are monotonically increasing in its
1167c478bd9Sstevel@tonic-gate  * verification of tag numbers.
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate #define get_field(var, tagexpect, decoder)				\
1197c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1207c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1217c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1227c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1237c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1247c478bd9Sstevel@tonic-gate   get_field_body(var,decoder)
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate  * opt_field
1287c478bd9Sstevel@tonic-gate  *
1297c478bd9Sstevel@tonic-gate  * Get an optional field with an expected context specific tag.
1307c478bd9Sstevel@tonic-gate  * Assumes that OPTVAL will have the default value, thus failing to
1317c478bd9Sstevel@tonic-gate  * distinguish between absent optional values and present optional
1327c478bd9Sstevel@tonic-gate  * values that happen to have the value of OPTVAL.
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate #define opt_field(var, tagexpect, decoder, optvalue)			\
1357c478bd9Sstevel@tonic-gate   if (asn1buf_remains(&subbuf, seqindef)) {				\
1367c478bd9Sstevel@tonic-gate     if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1377c478bd9Sstevel@tonic-gate 	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
1387c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;						\
1397c478bd9Sstevel@tonic-gate     if (tagnum == (tagexpect)) {					\
1407c478bd9Sstevel@tonic-gate       get_field_body(var, decoder);					\
1417c478bd9Sstevel@tonic-gate     } else var = optvalue;						\
1427c478bd9Sstevel@tonic-gate   }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /**** fields w/ length ****/
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1477c478bd9Sstevel@tonic-gate #define get_lenfield_body(len, var, decoder)	\
1487c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(len), &(var));	\
1497c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1507c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1517c478bd9Sstevel@tonic-gate   next_tag()
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1547c478bd9Sstevel@tonic-gate #define get_lenfield(len, var, tagexpect, decoder)			\
1557c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1567c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1577c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1587c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1597c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1607c478bd9Sstevel@tonic-gate   get_lenfield_body(len, var, decoder)
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /* similar to opt_field */
1637c478bd9Sstevel@tonic-gate #define opt_lenfield(len, var, tagexpect, decoder)	\
1647c478bd9Sstevel@tonic-gate   if (tagnum == (tagexpect)) {				\
1657c478bd9Sstevel@tonic-gate     get_lenfield_body(len, var, decoder);		\
1667c478bd9Sstevel@tonic-gate   } else { len = 0; var = 0; }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * begin_structure
1707c478bd9Sstevel@tonic-gate  *
1717c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE types.  This is meant
1727c478bd9Sstevel@tonic-gate  * to be called in an inner block that ends with a call to
1737c478bd9Sstevel@tonic-gate  * end_structure().
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate #define begin_structure()					\
1767c478bd9Sstevel@tonic-gate   asn1buf subbuf;						\
1777c478bd9Sstevel@tonic-gate   int seqindef;							\
1787c478bd9Sstevel@tonic-gate   int indef;							\
1797c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqindef);		\
1807c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
1817c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
1827c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
1837c478bd9Sstevel@tonic-gate   next_tag()
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /* skip trailing garbage */
1867c478bd9Sstevel@tonic-gate #define end_structure()						\
1877c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
1887c478bd9Sstevel@tonic-gate 			length, indef, seqindef);		\
1897c478bd9Sstevel@tonic-gate   if (retval) return retval
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * sequence_of
1937c478bd9Sstevel@tonic-gate  *
1947c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE OF types.  This is
1957c478bd9Sstevel@tonic-gate  * meant to be called in an inner block that ends with a call to
1967c478bd9Sstevel@tonic-gate  * end_sequence_of().
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate #define sequence_of(buf)			\
1997c478bd9Sstevel@tonic-gate   unsigned int length, taglen;			\
2007c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
2017c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
2027c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
2037c478bd9Sstevel@tonic-gate   int indef;					\
2047c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * sequence_of_no_tagvars
2087c478bd9Sstevel@tonic-gate  *
2097c478bd9Sstevel@tonic-gate  * This is meant for use inside decoder functions that have an outer
2107c478bd9Sstevel@tonic-gate  * sequence structure and thus declares variables of different names
2117c478bd9Sstevel@tonic-gate  * than does sequence_of() to avoid shadowing.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate #define sequence_of_no_tagvars(buf)		\
2147c478bd9Sstevel@tonic-gate   asn1_class eseqclass;				\
2157c478bd9Sstevel@tonic-gate   asn1_construction eseqconstr;			\
2167c478bd9Sstevel@tonic-gate   asn1_tagnum eseqnum;				\
2177c478bd9Sstevel@tonic-gate   unsigned int eseqlen;				\
2187c478bd9Sstevel@tonic-gate   int eseqindef;				\
2197c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate /*
2227c478bd9Sstevel@tonic-gate  * sequence_of_common
2237c478bd9Sstevel@tonic-gate  *
2247c478bd9Sstevel@tonic-gate  * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
2257c478bd9Sstevel@tonic-gate  * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
2267c478bd9Sstevel@tonic-gate  * does not prefetch the next tag.
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate #define sequence_of_common(buf)					\
2297c478bd9Sstevel@tonic-gate   int size = 0;							\
2307c478bd9Sstevel@tonic-gate   asn1buf seqbuf;						\
2317c478bd9Sstevel@tonic-gate   int seqofindef;						\
2327c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqofindef);	\
2337c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
2347c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
2357c478bd9Sstevel@tonic-gate   if (retval) return retval
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  * end_sequence_of
2397c478bd9Sstevel@tonic-gate  *
2407c478bd9Sstevel@tonic-gate  * Attempts to fetch an EOC tag, if any, and to sync over trailing
2417c478bd9Sstevel@tonic-gate  * garbage, if any.
2427c478bd9Sstevel@tonic-gate  */
2437c478bd9Sstevel@tonic-gate #define end_sequence_of(buf)							\
2447c478bd9Sstevel@tonic-gate   {										\
2457c478bd9Sstevel@tonic-gate       taginfo t4;								\
2467c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t4);					\
2477c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
2487c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
2497c478bd9Sstevel@tonic-gate       asn1class = t4.asn1class;							\
2507c478bd9Sstevel@tonic-gate       construction = t4.construction;						\
2517c478bd9Sstevel@tonic-gate       tagnum = t4.tagnum;							\
2527c478bd9Sstevel@tonic-gate       taglen = t4.length;							\
2537c478bd9Sstevel@tonic-gate       indef = t4.indef;								\
2547c478bd9Sstevel@tonic-gate   }										\
2557c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
2567c478bd9Sstevel@tonic-gate 			length, indef, seqofindef);				\
2577c478bd9Sstevel@tonic-gate   if (retval) return retval;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate /*
2607c478bd9Sstevel@tonic-gate  * end_sequence_of_no_tagvars
2617c478bd9Sstevel@tonic-gate  *
2627c478bd9Sstevel@tonic-gate  * Like end_sequence_of(), but uses the different (non-shadowing)
2637c478bd9Sstevel@tonic-gate  * variable names.
2647c478bd9Sstevel@tonic-gate  */
2657c478bd9Sstevel@tonic-gate #define end_sequence_of_no_tagvars(buf)						\
2667c478bd9Sstevel@tonic-gate   {										\
2677c478bd9Sstevel@tonic-gate       taginfo t5;								\
2687c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t5);					\
2697c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
2707c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
2717c478bd9Sstevel@tonic-gate       eseqclass = t5.asn1class;							\
2727c478bd9Sstevel@tonic-gate       eseqconstr = t5.construction;						\
2737c478bd9Sstevel@tonic-gate       eseqnum = t5.tagnum;							\
2747c478bd9Sstevel@tonic-gate       eseqlen = t5.length;							\
2757c478bd9Sstevel@tonic-gate       eseqindef = t5.indef;							\
2767c478bd9Sstevel@tonic-gate   }										\
2777c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
2787c478bd9Sstevel@tonic-gate 			eseqlen, eseqindef, seqofindef);			\
2797c478bd9Sstevel@tonic-gate   if (retval) return retval;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate #define cleanup()				\
2827c478bd9Sstevel@tonic-gate   return 0
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /* scalars */
2857c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate     time_t	t;
2887c478bd9Sstevel@tonic-gate     asn1_error_code retval;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate     retval =  asn1_decode_generaltime(buf,&t);
2917c478bd9Sstevel@tonic-gate     if (retval)
2927c478bd9Sstevel@tonic-gate 	return retval;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate     *val = t;
2957c478bd9Sstevel@tonic-gate     return 0;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #define integer_convert(fname,ktype)\
2997c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3007c478bd9Sstevel@tonic-gate {\
3017c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3027c478bd9Sstevel@tonic-gate   long n;\
3037c478bd9Sstevel@tonic-gate   retval = asn1_decode_integer(buf,&n);\
3047c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3057c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3067c478bd9Sstevel@tonic-gate   return 0;\
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate #define unsigned_integer_convert(fname,ktype)\
3097c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3107c478bd9Sstevel@tonic-gate {\
3117c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3127c478bd9Sstevel@tonic-gate   unsigned long n;\
3137c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);\
3147c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3157c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3167c478bd9Sstevel@tonic-gate   return 0;\
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int,int)
3197c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int32,krb5_int32)
3207c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_kvno,krb5_kvno)
3217c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_enctype,krb5_enctype)
3227c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
3237c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_octet,krb5_octet)
3247c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_addrtype,krb5_addrtype)
3257c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
3267c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
3277c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate   asn1_error_code retval;
3327c478bd9Sstevel@tonic-gate   unsigned long n;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate   retval = asn1_decode_maybe_unsigned(buf, &n);
3357c478bd9Sstevel@tonic-gate   if (retval) return retval;
3367c478bd9Sstevel@tonic-gate   *val = (krb5_ui_4)n & 0xffffffff;
3377c478bd9Sstevel@tonic-gate   return 0;
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate   asn1_error_code retval;
3437c478bd9Sstevel@tonic-gate   unsigned long n;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);
3467c478bd9Sstevel@tonic-gate   if(retval) return retval;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate   *val = (krb5_msgtype) n;
3497c478bd9Sstevel@tonic-gate   return 0;
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate /* structures */
3547c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate   return asn1_decode_generalstring(buf,
357505d05c7Sgtb 				   &((*val)->realm.length),
3587c478bd9Sstevel@tonic-gate 				   &((*val)->realm.data));
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate   setup();
3647c478bd9Sstevel@tonic-gate   { begin_structure();
3657c478bd9Sstevel@tonic-gate     get_field((*val)->type,0,asn1_decode_int32);
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
3687c478bd9Sstevel@tonic-gate       while(asn1buf_remains(&seqbuf,seqofindef) > 0){
3697c478bd9Sstevel@tonic-gate 	size++;
3707c478bd9Sstevel@tonic-gate 	if ((*val)->data == NULL)
3717c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
3727c478bd9Sstevel@tonic-gate 	else
3737c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)realloc((*val)->data,
3747c478bd9Sstevel@tonic-gate 					     size*sizeof(krb5_data));
3757c478bd9Sstevel@tonic-gate 	if((*val)->data == NULL) return ENOMEM;
3767c478bd9Sstevel@tonic-gate 	retval = asn1_decode_generalstring(&seqbuf,
377505d05c7Sgtb 					   &((*val)->data[size-1].length),
3787c478bd9Sstevel@tonic-gate 			   &((*val)->data[size-1].data));
3797c478bd9Sstevel@tonic-gate 	if(retval) return retval;
3807c478bd9Sstevel@tonic-gate       }
3817c478bd9Sstevel@tonic-gate       (*val)->length = size;
3827c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
3837c478bd9Sstevel@tonic-gate     }
3847c478bd9Sstevel@tonic-gate     if (indef) {
3857c478bd9Sstevel@tonic-gate 	get_eoc();
3867c478bd9Sstevel@tonic-gate     }
3877c478bd9Sstevel@tonic-gate     next_tag();
3887c478bd9Sstevel@tonic-gate     end_structure();
3897c478bd9Sstevel@tonic-gate     (*val)->magic = KV5M_PRINCIPAL;
3907c478bd9Sstevel@tonic-gate   }
3917c478bd9Sstevel@tonic-gate   cleanup();
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate   setup();
3977c478bd9Sstevel@tonic-gate   { begin_structure();
3987c478bd9Sstevel@tonic-gate     get_field(val->checksum_type,0,asn1_decode_cksumtype);
3997c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4007c478bd9Sstevel@tonic-gate     end_structure();
4017c478bd9Sstevel@tonic-gate     val->magic = KV5M_CHECKSUM;
4027c478bd9Sstevel@tonic-gate   }
4037c478bd9Sstevel@tonic-gate   cleanup();
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate   setup();
4097c478bd9Sstevel@tonic-gate   { begin_structure();
4107c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4117c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4127c478bd9Sstevel@tonic-gate     end_structure();
4137c478bd9Sstevel@tonic-gate     val->magic = KV5M_KEYBLOCK;
4147c478bd9Sstevel@tonic-gate   }
4157c478bd9Sstevel@tonic-gate   cleanup();
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
4197c478bd9Sstevel@tonic-gate {
4207c478bd9Sstevel@tonic-gate   setup();
4217c478bd9Sstevel@tonic-gate   { begin_structure();
4227c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4237c478bd9Sstevel@tonic-gate     opt_field(val->kvno,1,asn1_decode_kvno,0);
4247c478bd9Sstevel@tonic-gate     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
4257c478bd9Sstevel@tonic-gate     end_structure();
4267c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_DATA;
4277c478bd9Sstevel@tonic-gate   }
4287c478bd9Sstevel@tonic-gate   cleanup();
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
4327c478bd9Sstevel@tonic-gate {
4337c478bd9Sstevel@tonic-gate   asn1_error_code retval;
4347c478bd9Sstevel@tonic-gate   asn1_octet unused, o;
4357c478bd9Sstevel@tonic-gate   taginfo t;
4367c478bd9Sstevel@tonic-gate   int i;
4377c478bd9Sstevel@tonic-gate   krb5_flags f=0;
4387c478bd9Sstevel@tonic-gate   unsigned int length;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(buf, &t);
4417c478bd9Sstevel@tonic-gate   if (retval) return retval;
4427c478bd9Sstevel@tonic-gate   if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
4437c478bd9Sstevel@tonic-gate       t.tagnum != ASN1_BITSTRING)
4447c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
4457c478bd9Sstevel@tonic-gate   length = t.length;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate   retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
4487c478bd9Sstevel@tonic-gate   if(retval) return retval;
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate   /* Number of unused bits must be between 0 and 7. */
4517c478bd9Sstevel@tonic-gate   if (unused > 7) return ASN1_BAD_FORMAT;
4527c478bd9Sstevel@tonic-gate   length--;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate   for(i = 0; i < length; i++) {
4557c478bd9Sstevel@tonic-gate     retval = asn1buf_remove_octet(buf,&o);
4567c478bd9Sstevel@tonic-gate     if(retval) return retval;
4577c478bd9Sstevel@tonic-gate     /* ignore bits past number 31 */
4587c478bd9Sstevel@tonic-gate     if (i < 4)
4597c478bd9Sstevel@tonic-gate       f = (f<<8) | ((krb5_flags)o&0xFF);
4607c478bd9Sstevel@tonic-gate   }
4617c478bd9Sstevel@tonic-gate   if (length <= 4) {
4627c478bd9Sstevel@tonic-gate     /* Mask out unused bits, but only if necessary. */
4637c478bd9Sstevel@tonic-gate     f &= ~(krb5_flags)0 << unused;
4647c478bd9Sstevel@tonic-gate   }
4657c478bd9Sstevel@tonic-gate   /* left-justify */
4667c478bd9Sstevel@tonic-gate   if (length < 4)
4677c478bd9Sstevel@tonic-gate     f <<= (4 - length) * 8;
4687c478bd9Sstevel@tonic-gate   *val = f;
4697c478bd9Sstevel@tonic-gate   return 0;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
4737c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
4767c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
4797c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate   setup();
4847c478bd9Sstevel@tonic-gate   { begin_structure();
4857c478bd9Sstevel@tonic-gate     get_field(val->tr_type,0,asn1_decode_octet);
4867c478bd9Sstevel@tonic-gate     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
4877c478bd9Sstevel@tonic-gate     end_structure();
4887c478bd9Sstevel@tonic-gate     val->magic = KV5M_TRANSITED;
4897c478bd9Sstevel@tonic-gate   }
4907c478bd9Sstevel@tonic-gate   cleanup();
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate   setup();
4967c478bd9Sstevel@tonic-gate   { begin_structure();
4977c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
4987c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
4997c478bd9Sstevel@tonic-gate     get_field(val->last_req,1,asn1_decode_last_req);
5007c478bd9Sstevel@tonic-gate     get_field(val->nonce,2,asn1_decode_int32);
5017c478bd9Sstevel@tonic-gate     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
5027c478bd9Sstevel@tonic-gate     get_field(val->flags,4,asn1_decode_ticket_flags);
5037c478bd9Sstevel@tonic-gate     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
5047c478bd9Sstevel@tonic-gate     /* Set to authtime if missing */
5057c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
5067c478bd9Sstevel@tonic-gate     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
5077c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
5087c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5097c478bd9Sstevel@tonic-gate     get_field(val->server,9,asn1_decode_realm);
5107c478bd9Sstevel@tonic-gate     get_field(val->server,10,asn1_decode_principal_name);
5117c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
5127c478bd9Sstevel@tonic-gate     end_structure();
5137c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_KDC_REP_PART;
5147c478bd9Sstevel@tonic-gate   }
5157c478bd9Sstevel@tonic-gate   cleanup();
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
5197c478bd9Sstevel@tonic-gate {
5207c478bd9Sstevel@tonic-gate   setup();
5217c478bd9Sstevel@tonic-gate   unsigned int applen;
5227c478bd9Sstevel@tonic-gate   apptag(1);
5237c478bd9Sstevel@tonic-gate   { begin_structure();
5247c478bd9Sstevel@tonic-gate     { krb5_kvno vno;
5257c478bd9Sstevel@tonic-gate       get_field(vno,0,asn1_decode_kvno);
5267c478bd9Sstevel@tonic-gate       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
5277c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5287c478bd9Sstevel@tonic-gate     get_field(val->server,1,asn1_decode_realm);
5297c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_principal_name);
5307c478bd9Sstevel@tonic-gate     get_field(val->enc_part,3,asn1_decode_encrypted_data);
5317c478bd9Sstevel@tonic-gate     end_structure();
5327c478bd9Sstevel@tonic-gate     val->magic = KV5M_TICKET;
5337c478bd9Sstevel@tonic-gate   }
5347c478bd9Sstevel@tonic-gate   if (!applen) {
5357c478bd9Sstevel@tonic-gate       taginfo t;
5367c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t);
537505d05c7Sgtb       if (retval) return retval;
5387c478bd9Sstevel@tonic-gate       }
5397c478bd9Sstevel@tonic-gate   cleanup();
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate   setup();
5457c478bd9Sstevel@tonic-gate   { begin_structure();
5467c478bd9Sstevel@tonic-gate     { krb5_kvno kvno;
5477c478bd9Sstevel@tonic-gate       get_field(kvno,1,asn1_decode_kvno);
5487c478bd9Sstevel@tonic-gate       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
5497c478bd9Sstevel@tonic-gate     get_field(val->msg_type,2,asn1_decode_msgtype);
5507c478bd9Sstevel@tonic-gate     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
5517c478bd9Sstevel@tonic-gate     get_field(*val,4,asn1_decode_kdc_req_body);
5527c478bd9Sstevel@tonic-gate     end_structure();
5537c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
5547c478bd9Sstevel@tonic-gate   }
5557c478bd9Sstevel@tonic-gate   cleanup();
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate   setup();
5617c478bd9Sstevel@tonic-gate   {
5627c478bd9Sstevel@tonic-gate     krb5_principal psave;
5637c478bd9Sstevel@tonic-gate     begin_structure();
5647c478bd9Sstevel@tonic-gate     get_field(val->kdc_options,0,asn1_decode_kdc_options);
5657c478bd9Sstevel@tonic-gate     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
5667c478bd9Sstevel@tonic-gate     opt_field(val->client,1,asn1_decode_principal_name,NULL);
5677c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5687c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_realm);
5697c478bd9Sstevel@tonic-gate     if(val->client != NULL){
5707c478bd9Sstevel@tonic-gate       retval = asn1_krb5_realm_copy(val->client,val->server);
571505d05c7Sgtb       if(retval) return retval; }
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate     /* If opt_field server is missing, memory reference to server is
5747c478bd9Sstevel@tonic-gate        lost and results in memory leak */
5757c478bd9Sstevel@tonic-gate     psave = val->server;
5767c478bd9Sstevel@tonic-gate     opt_field(val->server,3,asn1_decode_principal_name,NULL);
5777c478bd9Sstevel@tonic-gate     if(val->server == NULL){
5787c478bd9Sstevel@tonic-gate       if(psave->realm.data) {
5797c478bd9Sstevel@tonic-gate 	free(psave->realm.data);
5807c478bd9Sstevel@tonic-gate 	psave->realm.data = NULL;
5817c478bd9Sstevel@tonic-gate 	psave->realm.length=0;
5827c478bd9Sstevel@tonic-gate       }
5837c478bd9Sstevel@tonic-gate       free(psave);
5847c478bd9Sstevel@tonic-gate     }
5857c478bd9Sstevel@tonic-gate     opt_field(val->from,4,asn1_decode_kerberos_time,0);
5867c478bd9Sstevel@tonic-gate     get_field(val->till,5,asn1_decode_kerberos_time);
5877c478bd9Sstevel@tonic-gate     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
5887c478bd9Sstevel@tonic-gate     get_field(val->nonce,7,asn1_decode_int32);
5897c478bd9Sstevel@tonic-gate     get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
5907c478bd9Sstevel@tonic-gate     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
5917c478bd9Sstevel@tonic-gate     if(tagnum == 10){
5927c478bd9Sstevel@tonic-gate       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
5937c478bd9Sstevel@tonic-gate     else{
5947c478bd9Sstevel@tonic-gate       val->authorization_data.magic = KV5M_ENC_DATA;
5957c478bd9Sstevel@tonic-gate       val->authorization_data.enctype = 0;
5967c478bd9Sstevel@tonic-gate       val->authorization_data.kvno = 0;
5977c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.data = NULL;
5987c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.length = 0;
5997c478bd9Sstevel@tonic-gate     }
6007c478bd9Sstevel@tonic-gate     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
6017c478bd9Sstevel@tonic-gate     end_structure();
6027c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
6037c478bd9Sstevel@tonic-gate   }
6047c478bd9Sstevel@tonic-gate   cleanup();
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate   setup();
6107c478bd9Sstevel@tonic-gate   { begin_structure();
6117c478bd9Sstevel@tonic-gate     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
6127c478bd9Sstevel@tonic-gate     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
6137c478bd9Sstevel@tonic-gate     opt_field(val->usec,2,asn1_decode_int32,0);
6147c478bd9Sstevel@tonic-gate     opt_field(val->seq_number,3,asn1_decode_seqnum,0);
6157c478bd9Sstevel@tonic-gate     alloc_field(val->s_address,krb5_address);
6167c478bd9Sstevel@tonic-gate     get_field(*(val->s_address),4,asn1_decode_host_address);
6177c478bd9Sstevel@tonic-gate     if(tagnum == 5){
6187c478bd9Sstevel@tonic-gate       alloc_field(val->r_address,krb5_address);
6197c478bd9Sstevel@tonic-gate       get_field(*(val->r_address),5,asn1_decode_host_address);
6207c478bd9Sstevel@tonic-gate     } else val->r_address = NULL;
6217c478bd9Sstevel@tonic-gate     end_structure();
6227c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAFE;
6237c478bd9Sstevel@tonic-gate   }
6247c478bd9Sstevel@tonic-gate   cleanup();
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate   setup();
6307c478bd9Sstevel@tonic-gate   { begin_structure();
6317c478bd9Sstevel@tonic-gate     get_field(val->addrtype,0,asn1_decode_addrtype);
6327c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
6337c478bd9Sstevel@tonic-gate     end_structure();
6347c478bd9Sstevel@tonic-gate     val->magic = KV5M_ADDRESS;
6357c478bd9Sstevel@tonic-gate   }
6367c478bd9Sstevel@tonic-gate   cleanup();
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate   setup();
6427c478bd9Sstevel@tonic-gate   { begin_structure();
6437c478bd9Sstevel@tonic-gate     { krb5_kvno pvno;
6447c478bd9Sstevel@tonic-gate       get_field(pvno,0,asn1_decode_kvno);
6457c478bd9Sstevel@tonic-gate       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
6467c478bd9Sstevel@tonic-gate     get_field(val->msg_type,1,asn1_decode_msgtype);
6477c478bd9Sstevel@tonic-gate     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
6487c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
6497c478bd9Sstevel@tonic-gate     get_field(val->client,3,asn1_decode_realm);
6507c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_principal_name);
6517c478bd9Sstevel@tonic-gate     alloc_field(val->ticket,krb5_ticket);
6527c478bd9Sstevel@tonic-gate     get_field(*(val->ticket),5,asn1_decode_ticket);
6537c478bd9Sstevel@tonic-gate     get_field(val->enc_part,6,asn1_decode_encrypted_data);
6547c478bd9Sstevel@tonic-gate     end_structure();
6557c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REP;
6567c478bd9Sstevel@tonic-gate   }
6577c478bd9Sstevel@tonic-gate   cleanup();
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate /* arrays */
6627c478bd9Sstevel@tonic-gate #define get_element(element,decoder)\
6637c478bd9Sstevel@tonic-gate retval = decoder(&seqbuf,element);\
6647c478bd9Sstevel@tonic-gate if(retval) return retval
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate #define array_append(array,size,element,type)\
6677c478bd9Sstevel@tonic-gate size++;\
6687c478bd9Sstevel@tonic-gate if (*(array) == NULL)\
6697c478bd9Sstevel@tonic-gate      *(array) = (type**)malloc((size+1)*sizeof(type*));\
6707c478bd9Sstevel@tonic-gate else\
6717c478bd9Sstevel@tonic-gate   *(array) = (type**)realloc(*(array),\
6727c478bd9Sstevel@tonic-gate 			     (size+1)*sizeof(type*));\
6737c478bd9Sstevel@tonic-gate if(*(array) == NULL) return ENOMEM;\
6747c478bd9Sstevel@tonic-gate (*(array))[(size)-1] = elt
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate #define decode_array_body(type,decoder)\
6777c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
6787c478bd9Sstevel@tonic-gate   type *elt;\
6797c478bd9Sstevel@tonic-gate \
6807c478bd9Sstevel@tonic-gate   { sequence_of(buf);\
6817c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
6827c478bd9Sstevel@tonic-gate       alloc_field(elt,type);\
6837c478bd9Sstevel@tonic-gate       get_element(elt,decoder);\
6847c478bd9Sstevel@tonic-gate       array_append(val,size,elt,type);\
6857c478bd9Sstevel@tonic-gate     }\
6867c478bd9Sstevel@tonic-gate     if (*val == NULL)\
6877c478bd9Sstevel@tonic-gate 	*val = (type **)malloc(sizeof(type*));\
6887c478bd9Sstevel@tonic-gate     (*val)[size] = NULL;\
6897c478bd9Sstevel@tonic-gate     end_sequence_of(buf);\
6907c478bd9Sstevel@tonic-gate   }\
6917c478bd9Sstevel@tonic-gate   cleanup()
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
7007c478bd9Sstevel@tonic-gate {
7017c478bd9Sstevel@tonic-gate   setup();
7027c478bd9Sstevel@tonic-gate   { begin_structure();
7037c478bd9Sstevel@tonic-gate     get_field(val->ad_type,0,asn1_decode_authdatatype);
7047c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
7057c478bd9Sstevel@tonic-gate     end_structure();
7067c478bd9Sstevel@tonic-gate     val->magic = KV5M_AUTHDATA;
7077c478bd9Sstevel@tonic-gate   }
7087c478bd9Sstevel@tonic-gate   cleanup();
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
7127c478bd9Sstevel@tonic-gate {
7137c478bd9Sstevel@tonic-gate   decode_array_body(krb5_address,asn1_decode_host_address);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate   decode_array_body(krb5_ticket,asn1_decode_ticket);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate   setup();
7297c478bd9Sstevel@tonic-gate   { begin_structure();
7307c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
7317c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
7327c478bd9Sstevel@tonic-gate     if(tagnum == 1){
7337c478bd9Sstevel@tonic-gate       alloc_field(val->client,krb5_principal_data);
7347c478bd9Sstevel@tonic-gate       opt_field(val->client,1,asn1_decode_realm,NULL);
7357c478bd9Sstevel@tonic-gate       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
7367c478bd9Sstevel@tonic-gate     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
7377c478bd9Sstevel@tonic-gate     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
7387c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
7397c478bd9Sstevel@tonic-gate     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
7407c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
7417c478bd9Sstevel@tonic-gate     if(tagnum == 8){
7427c478bd9Sstevel@tonic-gate       alloc_field(val->server,krb5_principal_data);
7437c478bd9Sstevel@tonic-gate       opt_field(val->server,8,asn1_decode_realm,NULL);
7447c478bd9Sstevel@tonic-gate       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
7457c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
7467c478bd9Sstevel@tonic-gate     end_structure();
7477c478bd9Sstevel@tonic-gate     val->magic = KV5M_CRED_INFO;
7487c478bd9Sstevel@tonic-gate   }
7497c478bd9Sstevel@tonic-gate   cleanup();
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
7537c478bd9Sstevel@tonic-gate {
7547c478bd9Sstevel@tonic-gate   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate   setup();
7607c478bd9Sstevel@tonic-gate   { begin_structure();
7617c478bd9Sstevel@tonic-gate     get_field(val->pa_type,1,asn1_decode_int32);
7627c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
7637c478bd9Sstevel@tonic-gate     end_structure();
7647c478bd9Sstevel@tonic-gate     val->magic = KV5M_PA_DATA;
7657c478bd9Sstevel@tonic-gate   }
7667c478bd9Sstevel@tonic-gate   cleanup();
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate   setup();
7777c478bd9Sstevel@tonic-gate   { begin_structure();
7787c478bd9Sstevel@tonic-gate     get_field(val->lr_type,0,asn1_decode_int32);
7797c478bd9Sstevel@tonic-gate     get_field(val->value,1,asn1_decode_kerberos_time);
7807c478bd9Sstevel@tonic-gate     end_structure();
7817c478bd9Sstevel@tonic-gate     val->magic = KV5M_LAST_REQ_ENTRY;
7827c478bd9Sstevel@tonic-gate #ifdef KRB5_GENEROUS_LR_TYPE
7837c478bd9Sstevel@tonic-gate     /* If we are only a single byte wide and negative - fill in the
7847c478bd9Sstevel@tonic-gate        other bits */
7857c478bd9Sstevel@tonic-gate     if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
7867c478bd9Sstevel@tonic-gate #endif
7877c478bd9Sstevel@tonic-gate   }
7887c478bd9Sstevel@tonic-gate   cleanup();
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate   asn1_error_code retval;
7947c478bd9Sstevel@tonic-gate   { sequence_of(buf);
7957c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){
7967c478bd9Sstevel@tonic-gate       size++;
7977c478bd9Sstevel@tonic-gate       if (*val == NULL)
7987c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
7997c478bd9Sstevel@tonic-gate       else
8007c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
8017c478bd9Sstevel@tonic-gate       if(*val == NULL) return ENOMEM;
8027c478bd9Sstevel@tonic-gate       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
8037c478bd9Sstevel@tonic-gate       if(retval) return retval;
8047c478bd9Sstevel@tonic-gate     }
8057c478bd9Sstevel@tonic-gate     *num = size;
8067c478bd9Sstevel@tonic-gate     end_sequence_of(buf);
8077c478bd9Sstevel@tonic-gate   }
8087c478bd9Sstevel@tonic-gate   cleanup();
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate   decode_array_body(krb5_checksum, asn1_decode_checksum);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
8177c478bd9Sstevel@tonic-gate {
818*86aa8097Smp   /*
819*86aa8097Smp    * Solaris Kerberos:
820*86aa8097Smp    * Use a temporary char* (tmpp) in place of val->salt when calling
821*86aa8097Smp    * get_lenfield(). val->salt cannot be cast to a char* as casting will not
822*86aa8097Smp    * produce an lvalue. Use the new value pointed to by tmpp as the value for
823*86aa8097Smp    * val->salt.
824*86aa8097Smp    */
825505d05c7Sgtb   char *tmpp;
8267c478bd9Sstevel@tonic-gate   setup();
8277c478bd9Sstevel@tonic-gate   { begin_structure();
8287c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
8297c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
830505d05c7Sgtb       get_lenfield(val->length,tmpp,1,asn1_decode_generalstring);
831*86aa8097Smp       val->salt = (krb5_octet*)tmpp;	/* SUNW14resync hack */
8327c478bd9Sstevel@tonic-gate     } else {
8337c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
8347c478bd9Sstevel@tonic-gate 	    val->salt = 0;
8357c478bd9Sstevel@tonic-gate     }
8367c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
8377c478bd9Sstevel@tonic-gate       krb5_octet *params ;
8387c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
8397c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
8407c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
8417c478bd9Sstevel@tonic-gate     } else {
8427c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
8437c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
8447c478bd9Sstevel@tonic-gate     }
8457c478bd9Sstevel@tonic-gate     end_structure();
8467c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
8477c478bd9Sstevel@tonic-gate   }
8487c478bd9Sstevel@tonic-gate   cleanup();
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
8527c478bd9Sstevel@tonic-gate {
8537c478bd9Sstevel@tonic-gate   setup();
8547c478bd9Sstevel@tonic-gate   { begin_structure();
8557c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
8567c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
8577c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
8587c478bd9Sstevel@tonic-gate     } else {
8597c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
8607c478bd9Sstevel@tonic-gate 	    val->salt = 0;
8617c478bd9Sstevel@tonic-gate     }
8627c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
8637c478bd9Sstevel@tonic-gate       krb5_octet *params ;
8647c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
8657c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
8667c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
8677c478bd9Sstevel@tonic-gate     } else {
8687c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
8697c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
8707c478bd9Sstevel@tonic-gate     }
8717c478bd9Sstevel@tonic-gate     end_structure();
8727c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
8737c478bd9Sstevel@tonic-gate   }
8747c478bd9Sstevel@tonic-gate   cleanup();
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
877505d05c7Sgtb 
878505d05c7Sgtb static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate   setup();
8817c478bd9Sstevel@tonic-gate   { begin_structure();
8827c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
8837c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
8847c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
8857c478bd9Sstevel@tonic-gate     } else {
8867c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
8877c478bd9Sstevel@tonic-gate 	    val->salt = 0;
8887c478bd9Sstevel@tonic-gate     }
8897c478bd9Sstevel@tonic-gate     val->s2kparams.data = NULL;
8907c478bd9Sstevel@tonic-gate     val->s2kparams.length = 0;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate     end_structure();
8937c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
8947c478bd9Sstevel@tonic-gate   }
8957c478bd9Sstevel@tonic-gate   cleanup();
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
8997c478bd9Sstevel@tonic-gate {
9007c478bd9Sstevel@tonic-gate   decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
9047c478bd9Sstevel@tonic-gate 					krb5_boolean v1_3_behavior)
9057c478bd9Sstevel@tonic-gate {
9067c478bd9Sstevel@tonic-gate     if (v1_3_behavior) {
9077c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9087c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry_1_3);
9097c478bd9Sstevel@tonic-gate     } else {
9107c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9117c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry);
9127c478bd9Sstevel@tonic-gate     }
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate   setup();
9187c478bd9Sstevel@tonic-gate   { begin_structure();
9197c478bd9Sstevel@tonic-gate     alloc_field(val->passwd,krb5_data);
9207c478bd9Sstevel@tonic-gate     get_lenfield(val->passwd->length,val->passwd->data,
9217c478bd9Sstevel@tonic-gate 		 0,asn1_decode_charstring);
9227c478bd9Sstevel@tonic-gate     val->passwd->magic = KV5M_DATA;
9237c478bd9Sstevel@tonic-gate     alloc_field(val->phrase,krb5_data);
9247c478bd9Sstevel@tonic-gate     get_lenfield(val->phrase->length,val->phrase->data,
9257c478bd9Sstevel@tonic-gate 		 1,asn1_decode_charstring);
9267c478bd9Sstevel@tonic-gate     val->phrase->magic = KV5M_DATA;
9277c478bd9Sstevel@tonic-gate     end_structure();
9287c478bd9Sstevel@tonic-gate     val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
9297c478bd9Sstevel@tonic-gate   }
9307c478bd9Sstevel@tonic-gate   cleanup();
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
9347c478bd9Sstevel@tonic-gate {
9357c478bd9Sstevel@tonic-gate   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
9397c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
9427c478bd9Sstevel@tonic-gate #define opt_cksum(var,tagexpect,decoder)\
9437c478bd9Sstevel@tonic-gate if(tagnum == (tagexpect)){\
9447c478bd9Sstevel@tonic-gate   get_field_body(var,decoder); }\
9457c478bd9Sstevel@tonic-gate else var.length = 0
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
9487c478bd9Sstevel@tonic-gate {
9497c478bd9Sstevel@tonic-gate   setup();
9507c478bd9Sstevel@tonic-gate   { begin_structure();
9517c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
9527c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
9537c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
9547c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
9557c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
9567c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
9577c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
9587c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
9597c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,8,asn1_decode_int32,0);
9607c478bd9Sstevel@tonic-gate     opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
9617c478bd9Sstevel@tonic-gate     end_structure();
9627c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
9637c478bd9Sstevel@tonic-gate   }
9647c478bd9Sstevel@tonic-gate   cleanup();
9657c478bd9Sstevel@tonic-gate }
9667c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
9677c478bd9Sstevel@tonic-gate {
9687c478bd9Sstevel@tonic-gate   setup();
9697c478bd9Sstevel@tonic-gate   { char *save, *end;
9707c478bd9Sstevel@tonic-gate     size_t alloclen;
9717c478bd9Sstevel@tonic-gate     begin_structure();
9727c478bd9Sstevel@tonic-gate     if (tagnum != 0) return ASN1_MISSING_FIELD;
9737c478bd9Sstevel@tonic-gate     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
9747c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
9757c478bd9Sstevel@tonic-gate     save = subbuf.next;
9767c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
9777c478bd9Sstevel@tonic-gate       unused_var(size);
9787c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
9797c478bd9Sstevel@tonic-gate     }
9807c478bd9Sstevel@tonic-gate     end = subbuf.next;
9817c478bd9Sstevel@tonic-gate     alloclen = end - save;
9827c478bd9Sstevel@tonic-gate     if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
9837c478bd9Sstevel@tonic-gate       return ENOMEM;
9847c478bd9Sstevel@tonic-gate     val->sam_challenge_2_body.length = alloclen;
9857c478bd9Sstevel@tonic-gate     memcpy(val->sam_challenge_2_body.data, save, alloclen);
9867c478bd9Sstevel@tonic-gate     next_tag();
9877c478bd9Sstevel@tonic-gate     get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
9887c478bd9Sstevel@tonic-gate     end_structure();
9897c478bd9Sstevel@tonic-gate   }
9907c478bd9Sstevel@tonic-gate   cleanup();
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate   setup();
9957c478bd9Sstevel@tonic-gate   { begin_structure();
9967c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
9977c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
9987c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
9997c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
10007c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
10017c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
10027c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
10037c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
10047c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,8,asn1_decode_int32);
10057c478bd9Sstevel@tonic-gate     get_field(val->sam_etype, 9, asn1_decode_int32);
10067c478bd9Sstevel@tonic-gate     end_structure();
10077c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
10087c478bd9Sstevel@tonic-gate   }
10097c478bd9Sstevel@tonic-gate   cleanup();
10107c478bd9Sstevel@tonic-gate }
10117c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
10127c478bd9Sstevel@tonic-gate {
10137c478bd9Sstevel@tonic-gate   setup();
10147c478bd9Sstevel@tonic-gate   { begin_structure();
10157c478bd9Sstevel@tonic-gate     /* alloc_field(val->sam_key,krb5_keyblock); */
10167c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
10177c478bd9Sstevel@tonic-gate     end_structure();
10187c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_KEY;
10197c478bd9Sstevel@tonic-gate   }
10207c478bd9Sstevel@tonic-gate   cleanup();
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
10247c478bd9Sstevel@tonic-gate {
10257c478bd9Sstevel@tonic-gate   setup();
10267c478bd9Sstevel@tonic-gate   { begin_structure();
10277c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,0,asn1_decode_int32,0);
10287c478bd9Sstevel@tonic-gate     opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
10297c478bd9Sstevel@tonic-gate     opt_field(val->sam_usec,2,asn1_decode_int32,0);
10307c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,3,asn1_decode_charstring);
10317c478bd9Sstevel@tonic-gate     end_structure();
10327c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
10337c478bd9Sstevel@tonic-gate   }
10347c478bd9Sstevel@tonic-gate   cleanup();
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate   setup();
10407c478bd9Sstevel@tonic-gate   { begin_structure();
10417c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,0,asn1_decode_int32);
10427c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,1,asn1_decode_charstring);
10437c478bd9Sstevel@tonic-gate     end_structure();
10447c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
10457c478bd9Sstevel@tonic-gate   }
10467c478bd9Sstevel@tonic-gate   cleanup();
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate #define opt_encfield(fld,tag,fn) \
10507c478bd9Sstevel@tonic-gate     if(tagnum == tag){ \
10517c478bd9Sstevel@tonic-gate       get_field(fld,tag,fn); } \
10527c478bd9Sstevel@tonic-gate     else{\
10537c478bd9Sstevel@tonic-gate       fld.magic = 0;\
10547c478bd9Sstevel@tonic-gate       fld.enctype = 0;\
10557c478bd9Sstevel@tonic-gate       fld.kvno = 0;\
10567c478bd9Sstevel@tonic-gate       fld.ciphertext.data = NULL;\
10577c478bd9Sstevel@tonic-gate       fld.ciphertext.length = 0;\
10587c478bd9Sstevel@tonic-gate     }
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
10617c478bd9Sstevel@tonic-gate {
10627c478bd9Sstevel@tonic-gate   setup();
10637c478bd9Sstevel@tonic-gate   { begin_structure();
10647c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10657c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10667c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
10677c478bd9Sstevel@tonic-gate     opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
10687c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
10697c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,5,asn1_decode_int32,0);
10707c478bd9Sstevel@tonic-gate     opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
10717c478bd9Sstevel@tonic-gate     end_structure();
10727c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
10737c478bd9Sstevel@tonic-gate   }
10747c478bd9Sstevel@tonic-gate   cleanup();
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
10787c478bd9Sstevel@tonic-gate {
10797c478bd9Sstevel@tonic-gate   setup();
10807c478bd9Sstevel@tonic-gate   { begin_structure();
10817c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10827c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10837c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
10847c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
10857c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,4,asn1_decode_int32);
10867c478bd9Sstevel@tonic-gate     end_structure();
10877c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
10887c478bd9Sstevel@tonic-gate   }
10897c478bd9Sstevel@tonic-gate   cleanup();
10907c478bd9Sstevel@tonic-gate }
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate   setup();
10967c478bd9Sstevel@tonic-gate   { begin_structure();
10977c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
10987c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10997c478bd9Sstevel@tonic-gate     get_field(val->stime,2,asn1_decode_kerberos_time);
11007c478bd9Sstevel@tonic-gate     get_field(val->susec,3,asn1_decode_int32);
11017c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
11027c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_realm);
11037c478bd9Sstevel@tonic-gate     get_field(val->client,5,asn1_decode_principal_name);
11047c478bd9Sstevel@tonic-gate     opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
11057c478bd9Sstevel@tonic-gate     end_structure();
11067c478bd9Sstevel@tonic-gate     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
11077c478bd9Sstevel@tonic-gate   }
11087c478bd9Sstevel@tonic-gate   cleanup();
11097c478bd9Sstevel@tonic-gate }
1110