1 /*
2  * src/lib/krb5/asn.1/krb5_decode.c
3  *
4  * Copyright 1994 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 #include "k5-int.h"
28 #include "krbasn1.h"
29 #include "asn1_k_decode.h"
30 #include "asn1_decode.h"
31 #include "asn1_get.h"
32 
33 /* setup *********************************************************/
34 /* set up variables */
35 /* the setup* macros can return, but are always used at function start
36    and thus need no malloc cleanup */
37 #define setup_buf_only()\
38 asn1_error_code retval;\
39 asn1buf buf;\
40 \
41 retval = asn1buf_wrap_data(&buf,code);\
42 if(retval) return retval
43 
44 #define setup_no_tagnum()\
45 asn1_class asn1class;\
46 asn1_construction construction;\
47 setup_buf_only()
48 
49 #define setup_no_length()\
50 asn1_tagnum tagnum;\
51 setup_no_tagnum()
52 
53 #define setup()\
54 unsigned int length;\
55 setup_no_length()
56 
57 /* helper macros for cleanup */
58 #define clean_return(val) { retval = val; goto error_out; }
59 
60 /* alloc_field is the first thing to allocate storage that may need cleanup */
61 #define alloc_field(var,type)\
62 var = (type*)calloc(1,sizeof(type));\
63 if((var) == NULL) clean_return(ENOMEM)
64 
65 /* process encoding header ***************************************/
66 /* decode tag and check that it == [APPLICATION tagnum] */
67 #define check_apptag(tagexpect)						\
68 {									\
69     taginfo t1;								\
70     retval = asn1_get_tag_2(&buf, &t1);					\
71     if (retval) clean_return (retval);					\
72     if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED)	\
73 	clean_return(ASN1_BAD_ID);					\
74     if (t1.tagnum != (tagexpect)) clean_return(KRB5_BADMSGTYPE);	\
75     asn1class = t1.asn1class;						\
76     construction = t1.construction;					\
77     tagnum = t1.tagnum;							\
78 }
79 
80 
81 
82 /* process a structure *******************************************/
83 
84 /* decode an explicit tag and place the number in tagnum */
85 #define next_tag()				\
86 { taginfo t2;					\
87   retval = asn1_get_tag_2(&subbuf, &t2);	\
88   if(retval) clean_return(retval);		\
89   asn1class = t2.asn1class;			\
90   construction = t2.construction;		\
91   tagnum = t2.tagnum;				\
92   indef = t2.indef;				\
93   taglen = t2.length;				\
94 }
95 
96 #define get_eoc()						\
97 {								\
98     taginfo t3;							\
99     retval = asn1_get_tag_2(&subbuf, &t3);			\
100     if (retval) return retval;					\
101     if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)	\
102         return ASN1_MISSING_EOC;				\
103     asn1class = t3.asn1class;					\
104     construction = t3.construction;				\
105     tagnum = t3.tagnum;						\
106     indef = t3.indef;						\
107 }
108 
109 /* decode sequence header and initialize tagnum with the first field */
110 #define begin_structure()\
111 unsigned int taglen;\
112 asn1buf subbuf;\
113 int seqindef;\
114 int indef;\
115 retval = asn1_get_sequence(&buf,&length,&seqindef);\
116 if(retval) clean_return(retval);\
117 retval = asn1buf_imbed(&subbuf,&buf,length,seqindef);\
118 if(retval) clean_return(retval);\
119 next_tag()
120 
121 #define end_structure()\
122 retval = asn1buf_sync(&buf,&subbuf,asn1class,tagnum,length,indef,seqindef);\
123 if (retval) clean_return(retval)
124 
125 /* process fields *******************************************/
126 /* normal fields ************************/
127 #define get_field_body(var,decoder)\
128 retval = decoder(&subbuf,&(var));\
129 if(retval) clean_return(retval);\
130 if (indef) { get_eoc(); }\
131 next_tag()
132 
133 /* decode a field (<[UNIVERSAL id]> <length> <contents>)
134     check that the id number == tagexpect then
135     decode into var
136     get the next tag */
137 #define get_field(var,tagexpect,decoder)\
138 if(tagnum > (tagexpect)) clean_return(ASN1_MISSING_FIELD);\
139 if(tagnum < (tagexpect)) clean_return(ASN1_MISPLACED_FIELD);\
140 if(asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
141   clean_return(ASN1_BAD_ID);\
142 get_field_body(var,decoder)
143 
144 /* decode (or skip, if not present) an optional field */
145 #define opt_field(var,tagexpect,decoder)				\
146   if (asn1buf_remains(&subbuf, seqindef)) {				\
147     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
148       clean_return(ASN1_BAD_ID);					\
149     if (tagnum == (tagexpect)) {					\
150       get_field_body(var,decoder);					\
151     }									\
152   }
153 
154 /* field w/ accompanying length *********/
155 #define get_lenfield_body(len,var,decoder)\
156 retval = decoder(&subbuf,&(len),&(var));\
157 if(retval) clean_return(retval);\
158 if (indef) { get_eoc(); }\
159 next_tag()
160 
161 /* decode a field w/ its length (for string types) */
162 #define get_lenfield(len,var,tagexpect,decoder)\
163 if(tagnum > (tagexpect)) clean_return(ASN1_MISSING_FIELD);\
164 if(tagnum < (tagexpect)) clean_return(ASN1_MISPLACED_FIELD);\
165 if(asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
166   clean_return(ASN1_BAD_ID);\
167 get_lenfield_body(len,var,decoder)
168 
169 /* decode an optional field w/ length */
170 #define opt_lenfield(len,var,tagexpect,decoder)				\
171   if (asn1buf_remains(&subbuf, seqindef)) {				\
172     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
173       clean_return(ASN1_BAD_ID);					\
174     if (tagnum == (tagexpect)) {					\
175       get_lenfield_body(len,var,decoder);				\
176     }									\
177   }
178 
179 
180 /* clean up ******************************************************/
181 /* finish up */
182 /* to make things less painful, assume the cleanup is passed rep */
183 #define cleanup(cleanup_routine)\
184    return 0; \
185 error_out: \
186    if (rep && *rep) { \
187 	cleanup_routine(*rep); \
188 	*rep = NULL; \
189    } \
190    return retval;
191 
192 #define cleanup_none()\
193    return 0; \
194 error_out: \
195    return retval;
196 
197 #define cleanup_manual()\
198    return 0;
199 
200 #define free_field(rep,f) if ((rep)->f) free((rep)->f)
201 #define clear_field(rep,f) (*(rep))->f = 0
202 
decode_krb5_authenticator(const krb5_data * code,krb5_authenticator ** rep)203 krb5_error_code decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **rep)
204 {
205   setup();
206   alloc_field(*rep,krb5_authenticator);
207   clear_field(rep,subkey);
208   clear_field(rep,checksum);
209   clear_field(rep,client);
210 
211   check_apptag(2);
212   { begin_structure();
213     { krb5_kvno kvno;
214       get_field(kvno,0,asn1_decode_kvno);
215       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
216     alloc_field((*rep)->client,krb5_principal_data);
217     get_field((*rep)->client,1,asn1_decode_realm);
218     get_field((*rep)->client,2,asn1_decode_principal_name);
219     if(tagnum == 3){
220       alloc_field((*rep)->checksum,krb5_checksum);
221       get_field(*((*rep)->checksum),3,asn1_decode_checksum); }
222     get_field((*rep)->cusec,4,asn1_decode_int32);
223     get_field((*rep)->ctime,5,asn1_decode_kerberos_time);
224     if(tagnum == 6){ alloc_field((*rep)->subkey,krb5_keyblock); }
225     opt_field(*((*rep)->subkey),6,asn1_decode_encryption_key);
226     opt_field((*rep)->seq_number,7,asn1_decode_seqnum);
227     opt_field((*rep)->authorization_data,8,asn1_decode_authorization_data);
228     (*rep)->magic = KV5M_AUTHENTICATOR;
229     end_structure();
230   }
231   cleanup_manual();
232 error_out:
233   if (rep && *rep) {
234       free_field(*rep,subkey);
235       free_field(*rep,checksum);
236       free_field(*rep,client);
237       free(*rep);
238       *rep = NULL;
239   }
240   return retval;
241 }
242 
243 krb5_error_code
244 KRB5_CALLCONV
krb5_decode_ticket(const krb5_data * code,krb5_ticket ** rep)245 krb5_decode_ticket(const krb5_data *code, krb5_ticket **rep)
246 {
247     return decode_krb5_ticket(code, rep);
248 }
249 
decode_krb5_ticket(const krb5_data * code,krb5_ticket ** rep)250 krb5_error_code decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep)
251 {
252   setup();
253   alloc_field(*rep,krb5_ticket);
254   clear_field(rep,server);
255 
256   check_apptag(1);
257   { begin_structure();
258     { krb5_kvno kvno;
259       get_field(kvno,0,asn1_decode_kvno);
260       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO);
261     }
262     alloc_field((*rep)->server,krb5_principal_data);
263     get_field((*rep)->server,1,asn1_decode_realm);
264     get_field((*rep)->server,2,asn1_decode_principal_name);
265     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
266     (*rep)->magic = KV5M_TICKET;
267     end_structure();
268   }
269   cleanup_manual();
270 error_out:
271   if (rep && *rep) {
272       free_field(*rep,server);
273       free(*rep);
274       *rep = NULL;
275   }
276   return retval;
277 }
278 
decode_krb5_encryption_key(const krb5_data * code,krb5_keyblock ** rep)279 krb5_error_code decode_krb5_encryption_key(const krb5_data *code, krb5_keyblock **rep)
280 {
281   setup();
282   alloc_field(*rep,krb5_keyblock);
283 
284   { begin_structure();
285     get_field((*rep)->enctype,0,asn1_decode_enctype);
286     get_lenfield((*rep)->length,(*rep)->contents,1,asn1_decode_octetstring);
287     end_structure();
288     (*rep)->magic = KV5M_KEYBLOCK;
289   }
290   cleanup(free);
291 }
292 
decode_krb5_enc_tkt_part(const krb5_data * code,krb5_enc_tkt_part ** rep)293 krb5_error_code decode_krb5_enc_tkt_part(const krb5_data *code, krb5_enc_tkt_part **rep)
294 {
295   setup();
296   alloc_field(*rep,krb5_enc_tkt_part);
297   clear_field(rep,session);
298   clear_field(rep,client);
299 
300   check_apptag(3);
301   { begin_structure();
302     get_field((*rep)->flags,0,asn1_decode_ticket_flags);
303     alloc_field((*rep)->session,krb5_keyblock);
304     get_field(*((*rep)->session),1,asn1_decode_encryption_key);
305     alloc_field((*rep)->client,krb5_principal_data);
306     get_field((*rep)->client,2,asn1_decode_realm);
307     get_field((*rep)->client,3,asn1_decode_principal_name);
308     get_field((*rep)->transited,4,asn1_decode_transited_encoding);
309     get_field((*rep)->times.authtime,5,asn1_decode_kerberos_time);
310     if (tagnum == 6)
311       { get_field((*rep)->times.starttime,6,asn1_decode_kerberos_time); }
312     else
313       (*rep)->times.starttime=(*rep)->times.authtime;
314     get_field((*rep)->times.endtime,7,asn1_decode_kerberos_time);
315     opt_field((*rep)->times.renew_till,8,asn1_decode_kerberos_time);
316     opt_field((*rep)->caddrs,9,asn1_decode_host_addresses);
317     opt_field((*rep)->authorization_data,10,asn1_decode_authorization_data);
318     (*rep)->magic = KV5M_ENC_TKT_PART;
319     end_structure();
320   }
321   cleanup_manual();
322 error_out:
323   if (rep && *rep) {
324       free_field(*rep,session);
325       free_field(*rep,client);
326       free(*rep);
327       *rep = NULL;
328   }
329   return retval;
330 }
331 
decode_krb5_enc_kdc_rep_part(const krb5_data * code,krb5_enc_kdc_rep_part ** rep)332 krb5_error_code decode_krb5_enc_kdc_rep_part(const krb5_data *code, krb5_enc_kdc_rep_part **rep)
333 {
334   taginfo t4;
335   setup_buf_only();
336   alloc_field(*rep,krb5_enc_kdc_rep_part);
337 
338   retval = asn1_get_tag_2(&buf, &t4);
339   if (retval) clean_return(retval);
340   if (t4.asn1class != APPLICATION || t4.construction != CONSTRUCTED) clean_return(ASN1_BAD_ID);
341   if (t4.tagnum == 25) (*rep)->msg_type = KRB5_AS_REP;
342   else if(t4.tagnum == 26) (*rep)->msg_type = KRB5_TGS_REP;
343   else clean_return(KRB5_BADMSGTYPE);
344 
345   retval = asn1_decode_enc_kdc_rep_part(&buf,*rep);
346   if(retval) clean_return(retval);
347 
348   cleanup(free);
349 }
350 
decode_krb5_as_rep(const krb5_data * code,krb5_kdc_rep ** rep)351 krb5_error_code decode_krb5_as_rep(const krb5_data *code, krb5_kdc_rep **rep)
352 {
353   setup_no_length();
354   alloc_field(*rep,krb5_kdc_rep);
355 
356   check_apptag(11);
357   retval = asn1_decode_kdc_rep(&buf,*rep);
358   if(retval) clean_return(retval);
359 #ifdef KRB5_MSGTYPE_STRICT
360   if((*rep)->msg_type != KRB5_AS_REP)
361     clean_return(KRB5_BADMSGTYPE);
362 #endif
363 
364   cleanup(free);
365 }
366 
decode_krb5_tgs_rep(const krb5_data * code,krb5_kdc_rep ** rep)367 krb5_error_code decode_krb5_tgs_rep(const krb5_data *code, krb5_kdc_rep **rep)
368 {
369   setup_no_length();
370   alloc_field(*rep,krb5_kdc_rep);
371 
372   check_apptag(13);
373   retval = asn1_decode_kdc_rep(&buf,*rep);
374   if(retval) clean_return(retval);
375 #ifdef KRB5_MSGTYPE_STRICT
376   if((*rep)->msg_type != KRB5_TGS_REP) clean_return(KRB5_BADMSGTYPE);
377 #endif
378 
379   cleanup(free);
380 }
381 
decode_krb5_ap_req(const krb5_data * code,krb5_ap_req ** rep)382 krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep)
383 {
384   setup();
385   alloc_field(*rep,krb5_ap_req);
386   clear_field(rep,ticket);
387 
388   check_apptag(14);
389   { begin_structure();
390     { krb5_kvno kvno;
391       get_field(kvno,0,asn1_decode_kvno);
392       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
393     { krb5_msgtype msg_type;
394       get_field(msg_type,1,asn1_decode_msgtype);
395 #ifdef KRB5_MSGTYPE_STRICT
396       if(msg_type != KRB5_AP_REQ) clean_return(KRB5_BADMSGTYPE);
397 #endif
398     }
399     get_field((*rep)->ap_options,2,asn1_decode_ap_options);
400     alloc_field((*rep)->ticket,krb5_ticket);
401     get_field(*((*rep)->ticket),3,asn1_decode_ticket);
402     get_field((*rep)->authenticator,4,asn1_decode_encrypted_data);
403     end_structure();
404     (*rep)->magic = KV5M_AP_REQ;
405   }
406   cleanup_manual();
407 error_out:
408   if (rep && *rep) {
409       free_field(*rep,ticket);
410       free(*rep);
411       *rep = NULL;
412   }
413   return retval;
414 }
415 
decode_krb5_ap_rep(const krb5_data * code,krb5_ap_rep ** rep)416 krb5_error_code decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **rep)
417 {
418   setup();
419   alloc_field(*rep,krb5_ap_rep);
420 
421   check_apptag(15);
422   { begin_structure();
423     { krb5_kvno kvno;
424       get_field(kvno,0,asn1_decode_kvno);
425       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
426     { krb5_msgtype msg_type;
427       get_field(msg_type,1,asn1_decode_msgtype);
428 #ifdef KRB5_MSGTYPE_STRICT
429       if(msg_type != KRB5_AP_REP) clean_return(KRB5_BADMSGTYPE);
430 #endif
431     }
432     get_field((*rep)->enc_part,2,asn1_decode_encrypted_data);
433     end_structure();
434     (*rep)->magic = KV5M_AP_REP;
435   }
436   cleanup(free);
437 }
438 
decode_krb5_ap_rep_enc_part(const krb5_data * code,krb5_ap_rep_enc_part ** rep)439 krb5_error_code decode_krb5_ap_rep_enc_part(const krb5_data *code, krb5_ap_rep_enc_part **rep)
440 {
441   setup();
442   alloc_field(*rep,krb5_ap_rep_enc_part);
443   clear_field(rep,subkey);
444 
445   check_apptag(27);
446   { begin_structure();
447     get_field((*rep)->ctime,0,asn1_decode_kerberos_time);
448     get_field((*rep)->cusec,1,asn1_decode_int32);
449     if(tagnum == 2){ alloc_field((*rep)->subkey,krb5_keyblock); }
450     opt_field(*((*rep)->subkey),2,asn1_decode_encryption_key);
451     opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
452     end_structure();
453     (*rep)->magic = KV5M_AP_REP_ENC_PART;
454   }
455   cleanup_manual();
456 error_out:
457   if (rep && *rep) {
458       free_field(*rep,subkey);
459       free(*rep);
460       *rep = NULL;
461   }
462   return retval;
463 }
464 
decode_krb5_as_req(const krb5_data * code,krb5_kdc_req ** rep)465 krb5_error_code decode_krb5_as_req(const krb5_data *code, krb5_kdc_req **rep)
466 {
467   setup_no_length();
468   alloc_field(*rep,krb5_kdc_req);
469 
470   check_apptag(10);
471   retval = asn1_decode_kdc_req(&buf,*rep);
472   if(retval) clean_return(retval);
473 #ifdef KRB5_MSGTYPE_STRICT
474   if((*rep)->msg_type != KRB5_AS_REQ) clean_return(KRB5_BADMSGTYPE);
475 #endif
476 
477   cleanup(free);
478 }
479 
decode_krb5_tgs_req(const krb5_data * code,krb5_kdc_req ** rep)480 krb5_error_code decode_krb5_tgs_req(const krb5_data *code, krb5_kdc_req **rep)
481 {
482   setup_no_length();
483   alloc_field(*rep,krb5_kdc_req);
484 
485   check_apptag(12);
486   retval = asn1_decode_kdc_req(&buf,*rep);
487   if(retval) clean_return(retval);
488 #ifdef KRB5_MSGTYPE_STRICT
489   if((*rep)->msg_type != KRB5_TGS_REQ) clean_return(KRB5_BADMSGTYPE);
490 #endif
491 
492   cleanup(free);
493 }
494 
decode_krb5_kdc_req_body(const krb5_data * code,krb5_kdc_req ** rep)495 krb5_error_code decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **rep)
496 {
497   setup_buf_only();
498   alloc_field(*rep,krb5_kdc_req);
499 
500   retval = asn1_decode_kdc_req_body(&buf,*rep);
501   if(retval) clean_return(retval);
502 
503   cleanup(free);
504 }
505 
506 /*
507  * decode_krb5_safe_with_body
508  *
509  * Like decode_krb5_safe(), but grabs the encoding of the
510  * KRB-SAFE-BODY as well, in case re-encoding would produce a
511  * different encoding.  (Yes, we're using DER, but there's this
512  * annoying problem with pre-1.3.x code using signed sequence numbers,
513  * which we permissively decode and cram into unsigned 32-bit numbers.
514  * When they're re-encoded, they're no longer negative if they started
515  * out negative, so checksum verification fails.)
516  *
517  * This does *not* perform any copying; the returned pointer to the
518  * encoded KRB-SAFE-BODY points into the input buffer.
519  */
decode_krb5_safe_with_body(const krb5_data * code,krb5_safe ** rep,krb5_data * body)520 krb5_error_code decode_krb5_safe_with_body(
521   const krb5_data *code,
522   krb5_safe **rep,
523   krb5_data *body)
524 {
525   krb5_data tmpbody;
526   setup();
527   alloc_field(*rep,krb5_safe);
528   clear_field(rep,checksum);
529   tmpbody.magic = 0;
530 
531   check_apptag(20);
532   { begin_structure();
533     { krb5_kvno kvno;
534       get_field(kvno,0,asn1_decode_kvno);
535       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
536     { krb5_msgtype msg_type;
537       get_field(msg_type,1,asn1_decode_msgtype);
538 #ifdef KRB5_MSGTYPE_STRICT
539       if(msg_type != KRB5_SAFE) clean_return(KRB5_BADMSGTYPE);
540 #endif
541     }
542     /*
543      * Gross kludge to extract pointer to encoded safe-body.  Relies
544      * on tag prefetch done by next_tag().  Don't handle indefinite
545      * encoding, as it's too much work.
546      */
547     if (!indef) {
548       tmpbody.length = taglen;
549       tmpbody.data = subbuf.next;
550     } else {
551       tmpbody.length = 0;
552       tmpbody.data = NULL;
553     }
554     get_field(**rep,2,asn1_decode_krb_safe_body);
555     alloc_field((*rep)->checksum,krb5_checksum);
556     get_field(*((*rep)->checksum),3,asn1_decode_checksum);
557   (*rep)->magic = KV5M_SAFE;
558     end_structure();
559   }
560   if (body != NULL)
561     *body = tmpbody;
562   cleanup_manual();
563 error_out:
564   if (rep && *rep) {
565       free_field(*rep,checksum);
566       free(*rep);
567       *rep = NULL;
568   }
569   return retval;
570 }
571 
decode_krb5_safe(const krb5_data * code,krb5_safe ** rep)572 krb5_error_code decode_krb5_safe(const krb5_data *code, krb5_safe **rep)
573 {
574   return decode_krb5_safe_with_body(code, rep, NULL);
575 }
576 
decode_krb5_priv(const krb5_data * code,krb5_priv ** rep)577 krb5_error_code decode_krb5_priv(const krb5_data *code, krb5_priv **rep)
578 {
579   setup();
580   alloc_field(*rep,krb5_priv);
581 
582   check_apptag(21);
583   { begin_structure();
584     { krb5_kvno kvno;
585       get_field(kvno,0,asn1_decode_kvno);
586       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
587     { krb5_msgtype msg_type;
588       get_field(msg_type,1,asn1_decode_msgtype);
589 #ifdef KRB5_MSGTYPE_STRICT
590       if(msg_type != KRB5_PRIV) clean_return(KRB5_BADMSGTYPE);
591 #endif
592     }
593     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
594     (*rep)->magic = KV5M_PRIV;
595     end_structure();
596   }
597   cleanup(free);
598 }
599 
decode_krb5_enc_priv_part(const krb5_data * code,krb5_priv_enc_part ** rep)600 krb5_error_code decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_part **rep)
601 {
602   setup();
603   alloc_field(*rep,krb5_priv_enc_part);
604   clear_field(rep,r_address);
605   clear_field(rep,s_address);
606 
607   check_apptag(28);
608   { begin_structure();
609     get_lenfield((*rep)->user_data.length,(*rep)->user_data.data,0,asn1_decode_charstring);
610     opt_field((*rep)->timestamp,1,asn1_decode_kerberos_time);
611     opt_field((*rep)->usec,2,asn1_decode_int32);
612     opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
613     alloc_field((*rep)->s_address,krb5_address);
614     get_field(*((*rep)->s_address),4,asn1_decode_host_address);
615     if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
616     opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
617     (*rep)->magic = KV5M_PRIV_ENC_PART;
618     end_structure();
619   }
620   cleanup_manual();
621 error_out:
622   if (rep && *rep) {
623       free_field(*rep,r_address);
624       free_field(*rep,s_address);
625       free(*rep);
626       *rep = NULL;
627   }
628   return retval;
629 }
630 
decode_krb5_cred(const krb5_data * code,krb5_cred ** rep)631 krb5_error_code decode_krb5_cred(const krb5_data *code, krb5_cred **rep)
632 {
633   setup();
634   alloc_field(*rep,krb5_cred);
635 
636   check_apptag(22);
637   { begin_structure();
638     { krb5_kvno kvno;
639       get_field(kvno,0,asn1_decode_kvno);
640       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
641     { krb5_msgtype msg_type;
642       get_field(msg_type,1,asn1_decode_msgtype);
643 #ifdef KRB5_MSGTYPE_STRICT
644       if(msg_type != KRB5_CRED) clean_return(KRB5_BADMSGTYPE);
645 #endif
646     }
647     get_field((*rep)->tickets,2,asn1_decode_sequence_of_ticket);
648     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
649     (*rep)->magic = KV5M_CRED;
650     end_structure();
651   }
652   cleanup(free);
653 }
654 
decode_krb5_enc_cred_part(const krb5_data * code,krb5_cred_enc_part ** rep)655 krb5_error_code decode_krb5_enc_cred_part(const krb5_data *code, krb5_cred_enc_part **rep)
656 {
657   setup();
658   alloc_field(*rep,krb5_cred_enc_part);
659   clear_field(rep,r_address);
660   clear_field(rep,s_address);
661 
662   check_apptag(29);
663   { begin_structure();
664     get_field((*rep)->ticket_info,0,asn1_decode_sequence_of_krb_cred_info);
665     opt_field((*rep)->nonce,1,asn1_decode_int32);
666     opt_field((*rep)->timestamp,2,asn1_decode_kerberos_time);
667     opt_field((*rep)->usec,3,asn1_decode_int32);
668     if(tagnum == 4){ alloc_field((*rep)->s_address,krb5_address); }
669     opt_field(*((*rep)->s_address),4,asn1_decode_host_address);
670     if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
671     opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
672     (*rep)->magic = KV5M_CRED_ENC_PART;
673     end_structure();
674   }
675   cleanup_manual();
676 error_out:
677   if (rep && *rep) {
678       free_field(*rep,r_address);
679       free_field(*rep,s_address);
680       free(*rep);
681       *rep = NULL;
682   }
683   return retval;
684 }
685 
686 
decode_krb5_error(const krb5_data * code,krb5_error ** rep)687 krb5_error_code decode_krb5_error(const krb5_data *code, krb5_error **rep)
688 {
689   setup();
690   alloc_field(*rep,krb5_error);
691   clear_field(rep,server);
692   clear_field(rep,client);
693 
694   check_apptag(30);
695   { begin_structure();
696     { krb5_kvno kvno;
697       get_field(kvno,0,asn1_decode_kvno);
698       if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
699     { krb5_msgtype msg_type;
700       get_field(msg_type,1,asn1_decode_msgtype);
701 #ifdef KRB5_MSGTYPE_STRICT
702       if(msg_type != KRB5_ERROR) clean_return(KRB5_BADMSGTYPE);
703 #endif
704     }
705     opt_field((*rep)->ctime,2,asn1_decode_kerberos_time);
706     opt_field((*rep)->cusec,3,asn1_decode_int32);
707     get_field((*rep)->stime,4,asn1_decode_kerberos_time);
708     get_field((*rep)->susec,5,asn1_decode_int32);
709     get_field((*rep)->error,6,asn1_decode_ui_4);
710     if(tagnum == 7){ alloc_field((*rep)->client,krb5_principal_data); }
711     opt_field((*rep)->client,7,asn1_decode_realm);
712     opt_field((*rep)->client,8,asn1_decode_principal_name);
713     alloc_field((*rep)->server,krb5_principal_data);
714     get_field((*rep)->server,9,asn1_decode_realm);
715     get_field((*rep)->server,10,asn1_decode_principal_name);
716     opt_lenfield((*rep)->text.length,(*rep)->text.data,11,asn1_decode_generalstring);
717     opt_lenfield((*rep)->e_data.length,(*rep)->e_data.data,12,asn1_decode_charstring);
718     (*rep)->magic = KV5M_ERROR;
719     end_structure();
720   }
721   cleanup_manual();
722 error_out:
723   if (rep && *rep) {
724       free_field(*rep,server);
725       free_field(*rep,client);
726       free(*rep);
727       *rep = NULL;
728   }
729   return retval;
730 }
731 
decode_krb5_authdata(const krb5_data * code,krb5_authdata *** rep)732 krb5_error_code decode_krb5_authdata(const krb5_data *code, krb5_authdata ***rep)
733 {
734   setup_buf_only();
735   *rep = 0;
736   retval = asn1_decode_authorization_data(&buf,rep);
737   if(retval) clean_return(retval);
738   cleanup_none();		/* we're not allocating anything here... */
739 }
740 
decode_krb5_pwd_sequence(const krb5_data * code,passwd_phrase_element ** rep)741 krb5_error_code decode_krb5_pwd_sequence(const krb5_data *code, passwd_phrase_element **rep)
742 {
743   setup_buf_only();
744   alloc_field(*rep,passwd_phrase_element);
745   retval = asn1_decode_passwdsequence(&buf,*rep);
746   if(retval) clean_return(retval);
747   cleanup(free);
748 }
749 
decode_krb5_pwd_data(const krb5_data * code,krb5_pwd_data ** rep)750 krb5_error_code decode_krb5_pwd_data(const krb5_data *code, krb5_pwd_data **rep)
751 {
752   setup();
753   alloc_field(*rep,krb5_pwd_data);
754   { begin_structure();
755     get_field((*rep)->sequence_count,0,asn1_decode_int);
756     get_field((*rep)->element,1,asn1_decode_sequence_of_passwdsequence);
757     (*rep)->magic = KV5M_PWD_DATA;
758     end_structure (); }
759   cleanup(free);
760 }
761 
decode_krb5_padata_sequence(const krb5_data * code,krb5_pa_data *** rep)762 krb5_error_code decode_krb5_padata_sequence(const krb5_data *code, krb5_pa_data ***rep)
763 {
764   setup_buf_only();
765   *rep = 0;
766   retval = asn1_decode_sequence_of_pa_data(&buf,rep);
767   if(retval) clean_return(retval);
768   cleanup_none();		/* we're not allocating anything here */
769 }
770 
decode_krb5_alt_method(const krb5_data * code,krb5_alt_method ** rep)771 krb5_error_code decode_krb5_alt_method(const krb5_data *code, krb5_alt_method **rep)
772 {
773   setup();
774   alloc_field(*rep,krb5_alt_method);
775   { begin_structure();
776     get_field((*rep)->method,0,asn1_decode_int32);
777     if (tagnum == 1) {
778 	get_lenfield((*rep)->length,(*rep)->data,1,asn1_decode_octetstring);
779     } else {
780 	(*rep)->length = 0;
781 	(*rep)->data = 0;
782     }
783     (*rep)->magic = KV5M_ALT_METHOD;
784     end_structure();
785   }
786   cleanup(free);
787 }
788 
decode_krb5_etype_info(const krb5_data * code,krb5_etype_info_entry *** rep)789 krb5_error_code decode_krb5_etype_info(const krb5_data *code, krb5_etype_info_entry ***rep)
790 {
791   setup_buf_only();
792   *rep = 0;
793   retval = asn1_decode_etype_info(&buf,rep);
794   if(retval) clean_return(retval);
795   cleanup_none();		/* we're not allocating anything here */
796 }
797 
decode_krb5_etype_info2(const krb5_data * code,krb5_etype_info_entry *** rep)798 krb5_error_code decode_krb5_etype_info2(const krb5_data *code, krb5_etype_info_entry ***rep)
799 {
800     setup_buf_only();
801     *rep = 0;
802     retval = asn1_decode_etype_info2(&buf,rep, 0);
803     if (retval == ASN1_BAD_ID) {
804 	retval = asn1buf_wrap_data(&buf,code);
805 	if(retval) clean_return(retval);
806 	retval = asn1_decode_etype_info2(&buf, rep, 1);
807     }
808     if(retval) clean_return(retval);
809     cleanup_none();		/* we're not allocating anything here */
810 }
811 
812 
decode_krb5_enc_data(const krb5_data * code,krb5_enc_data ** rep)813 krb5_error_code decode_krb5_enc_data(const krb5_data *code, krb5_enc_data **rep)
814 {
815   setup_buf_only();
816   alloc_field(*rep,krb5_enc_data);
817 
818   retval = asn1_decode_encrypted_data(&buf,*rep);
819   if(retval) clean_return(retval);
820 
821   cleanup(free);
822 }
823 
decode_krb5_pa_enc_ts(const krb5_data * code,krb5_pa_enc_ts ** rep)824 krb5_error_code decode_krb5_pa_enc_ts(const krb5_data *code, krb5_pa_enc_ts **rep)
825 {
826   setup();
827   alloc_field(*rep,krb5_pa_enc_ts);
828   { begin_structure();
829     get_field((*rep)->patimestamp,0,asn1_decode_kerberos_time);
830     if (tagnum == 1) {
831 	get_field((*rep)->pausec,1,asn1_decode_int32);
832     } else
833 	(*rep)->pausec = 0;
834     end_structure (); }
835   cleanup(free);
836 }
837 
decode_krb5_sam_challenge(const krb5_data * code,krb5_sam_challenge ** rep)838 krb5_error_code decode_krb5_sam_challenge(const krb5_data *code, krb5_sam_challenge **rep)
839 {
840   setup_buf_only();
841   alloc_field(*rep,krb5_sam_challenge);
842 
843   retval = asn1_decode_sam_challenge(&buf,*rep);
844   if(retval) clean_return(retval);
845 
846   cleanup(free);
847 }
848 
decode_krb5_sam_challenge_2(const krb5_data * code,krb5_sam_challenge_2 ** rep)849 krb5_error_code decode_krb5_sam_challenge_2(const krb5_data *code, krb5_sam_challenge_2 **rep)
850 {
851   setup_buf_only();
852   alloc_field(*rep,krb5_sam_challenge_2);
853 
854   retval = asn1_decode_sam_challenge_2(&buf,*rep);
855   if(retval) clean_return(retval);
856 
857   cleanup(free);
858 }
859 
decode_krb5_sam_challenge_2_body(const krb5_data * code,krb5_sam_challenge_2_body ** rep)860 krb5_error_code decode_krb5_sam_challenge_2_body(const krb5_data *code, krb5_sam_challenge_2_body **rep)
861 {
862   setup_buf_only();
863   alloc_field(*rep, krb5_sam_challenge_2_body);
864 
865   retval = asn1_decode_sam_challenge_2_body(&buf, *rep);
866   if(retval) clean_return(retval);
867 
868   cleanup(free);
869 }
870 
decode_krb5_enc_sam_key(const krb5_data * code,krb5_sam_key ** rep)871 krb5_error_code decode_krb5_enc_sam_key(const krb5_data *code, krb5_sam_key **rep)
872 {
873   setup_buf_only();
874   alloc_field(*rep,krb5_sam_key);
875 
876   retval = asn1_decode_enc_sam_key(&buf,*rep);
877   if(retval) clean_return(retval);
878 
879   cleanup(free);
880 }
881 
decode_krb5_enc_sam_response_enc(const krb5_data * code,krb5_enc_sam_response_enc ** rep)882 krb5_error_code decode_krb5_enc_sam_response_enc(const krb5_data *code, krb5_enc_sam_response_enc **rep)
883 {
884   setup_buf_only();
885   alloc_field(*rep,krb5_enc_sam_response_enc);
886 
887   retval = asn1_decode_enc_sam_response_enc(&buf,*rep);
888   if(retval) clean_return(retval);
889 
890   cleanup(free);
891 }
892 
decode_krb5_enc_sam_response_enc_2(const krb5_data * code,krb5_enc_sam_response_enc_2 ** rep)893 krb5_error_code decode_krb5_enc_sam_response_enc_2(const krb5_data *code, krb5_enc_sam_response_enc_2 **rep)
894 {
895   setup_buf_only();
896   alloc_field(*rep,krb5_enc_sam_response_enc_2);
897 
898   retval = asn1_decode_enc_sam_response_enc_2(&buf,*rep);
899   if(retval) clean_return(retval);
900 
901   cleanup(free);
902 }
903 
decode_krb5_sam_response(const krb5_data * code,krb5_sam_response ** rep)904 krb5_error_code decode_krb5_sam_response(const krb5_data *code, krb5_sam_response **rep)
905 {
906   setup_buf_only();
907   alloc_field(*rep,krb5_sam_response);
908 
909   retval = asn1_decode_sam_response(&buf,*rep);
910   if(retval) clean_return(retval);
911 
912   cleanup(free);
913 }
914 
decode_krb5_sam_response_2(const krb5_data * code,krb5_sam_response_2 ** rep)915 krb5_error_code decode_krb5_sam_response_2(const krb5_data *code, krb5_sam_response_2 **rep)
916 {
917   setup_buf_only();
918   alloc_field(*rep,krb5_sam_response_2);
919 
920   retval = asn1_decode_sam_response_2(&buf,*rep);
921   if(retval) clean_return(retval);
922 
923   cleanup(free);
924 }
925 
decode_krb5_predicted_sam_response(const krb5_data * code,krb5_predicted_sam_response ** rep)926 krb5_error_code decode_krb5_predicted_sam_response(const krb5_data *code, krb5_predicted_sam_response **rep)
927 {
928   setup_buf_only();		/* preallocated */
929   alloc_field(*rep,krb5_predicted_sam_response);
930 
931   retval = asn1_decode_predicted_sam_response(&buf,*rep);
932   if(retval) clean_return(retval);
933 
934   cleanup(free);
935 }
936 
decode_krb5_pa_pk_as_req(const krb5_data * code,krb5_pa_pk_as_req ** rep)937 krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **rep)
938 {
939   setup_buf_only();
940   alloc_field(*rep, krb5_pa_pk_as_req);
941 
942   retval = asn1_decode_pa_pk_as_req(&buf, *rep);
943   if (retval) clean_return(retval);
944 
945   cleanup(free);
946 }
947 
decode_krb5_pa_pk_as_req_draft9(const krb5_data * code,krb5_pa_pk_as_req_draft9 ** rep)948 krb5_error_code decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, krb5_pa_pk_as_req_draft9 **rep)
949 {
950   setup_buf_only();
951   alloc_field(*rep, krb5_pa_pk_as_req_draft9);
952 
953   retval = asn1_decode_pa_pk_as_req_draft9(&buf, *rep);
954   if (retval) clean_return(retval);
955 
956   cleanup(free);
957 }
958 
decode_krb5_pa_pk_as_rep(const krb5_data * code,krb5_pa_pk_as_rep ** rep)959 krb5_error_code decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **rep)
960 {
961   setup_buf_only();
962   alloc_field(*rep, krb5_pa_pk_as_rep);
963 
964   retval = asn1_decode_pa_pk_as_rep(&buf, *rep);
965   if (retval) clean_return(retval);
966 
967   cleanup(free);
968 }
969 
decode_krb5_pa_pk_as_rep_draft9(const krb5_data * code,krb5_pa_pk_as_rep_draft9 ** rep)970 krb5_error_code decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, krb5_pa_pk_as_rep_draft9 **rep)
971 {
972   setup_buf_only();
973   alloc_field(*rep, krb5_pa_pk_as_rep_draft9);
974 
975   retval = asn1_decode_pa_pk_as_rep_draft9(&buf, *rep);
976   if (retval) clean_return(retval);
977 
978   cleanup(free);
979 }
980 
decode_krb5_auth_pack(const krb5_data * code,krb5_auth_pack ** rep)981 krb5_error_code decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **rep)
982 {
983   setup_buf_only();
984   alloc_field(*rep, krb5_auth_pack);
985 
986   retval = asn1_decode_auth_pack(&buf, *rep);
987   if (retval) clean_return(retval);
988 
989   cleanup(free);
990 }
991 
decode_krb5_auth_pack_draft9(const krb5_data * code,krb5_auth_pack_draft9 ** rep)992 krb5_error_code decode_krb5_auth_pack_draft9(const krb5_data *code, krb5_auth_pack_draft9 **rep)
993 {
994   setup_buf_only();
995   alloc_field(*rep, krb5_auth_pack_draft9);
996 
997   retval = asn1_decode_auth_pack_draft9(&buf, *rep);
998   if (retval) clean_return(retval);
999 
1000   cleanup(free);
1001 }
1002 
decode_krb5_kdc_dh_key_info(const krb5_data * code,krb5_kdc_dh_key_info ** rep)1003 krb5_error_code decode_krb5_kdc_dh_key_info(const krb5_data *code, krb5_kdc_dh_key_info **rep)
1004 {
1005   setup_buf_only();
1006   alloc_field(*rep, krb5_kdc_dh_key_info);
1007 
1008   retval = asn1_decode_kdc_dh_key_info(&buf, *rep);
1009   if (retval) clean_return(retval);
1010 
1011   cleanup(free);
1012 }
1013 
decode_krb5_principal_name(const krb5_data * code,krb5_principal_data ** rep)1014 krb5_error_code decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **rep)
1015 {
1016   setup_buf_only();
1017   alloc_field(*rep, krb5_principal_data);
1018 
1019   retval = asn1_decode_krb5_principal_name(&buf, rep);
1020   if (retval) clean_return(retval);
1021 
1022   cleanup(free);
1023 }
1024 
decode_krb5_reply_key_pack(const krb5_data * code,krb5_reply_key_pack ** rep)1025 krb5_error_code decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **rep)
1026 {
1027   setup_buf_only();
1028   alloc_field(*rep, krb5_reply_key_pack);
1029 
1030   retval = asn1_decode_reply_key_pack(&buf, *rep);
1031   if (retval)
1032     goto error_out;
1033 
1034   cleanup_manual();
1035 error_out:
1036   if (rep && *rep) {
1037     if ((*rep)->replyKey.contents)
1038 	free((*rep)->replyKey.contents);
1039     if ((*rep)->asChecksum.contents)
1040       free((*rep)->asChecksum.contents);
1041     free(*rep);
1042     *rep = NULL;
1043   }
1044   return retval;
1045 }
1046 
decode_krb5_reply_key_pack_draft9(const krb5_data * code,krb5_reply_key_pack_draft9 ** rep)1047 krb5_error_code decode_krb5_reply_key_pack_draft9(const krb5_data *code, krb5_reply_key_pack_draft9 **rep)
1048 {
1049   setup_buf_only();
1050   alloc_field(*rep, krb5_reply_key_pack_draft9);
1051 
1052   retval = asn1_decode_reply_key_pack_draft9(&buf, *rep);
1053   if (retval) clean_return(retval);
1054 
1055   cleanup(free);
1056 }
1057 
decode_krb5_typed_data(const krb5_data * code,krb5_typed_data *** rep)1058 krb5_error_code decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***rep)
1059 {
1060   setup_buf_only();
1061   retval = asn1_decode_sequence_of_typed_data(&buf, rep);
1062   if (retval) clean_return(retval);
1063 
1064   cleanup(free);
1065 }
1066 
decode_krb5_td_trusted_certifiers(const krb5_data * code,krb5_external_principal_identifier *** rep)1067 krb5_error_code decode_krb5_td_trusted_certifiers(const krb5_data *code, krb5_external_principal_identifier ***rep)
1068 {
1069   setup_buf_only();
1070   retval = asn1_decode_sequence_of_external_principal_identifier(&buf, rep);
1071   if (retval) clean_return(retval);
1072 
1073   cleanup(free);
1074 }
1075 
decode_krb5_td_dh_parameters(const krb5_data * code,krb5_algorithm_identifier *** rep)1076 krb5_error_code decode_krb5_td_dh_parameters(const krb5_data *code, krb5_algorithm_identifier ***rep)
1077 {
1078   setup_buf_only();
1079   retval = asn1_decode_sequence_of_algorithm_identifier(&buf, rep);
1080   if (retval) clean_return(retval);
1081 
1082   cleanup(free);
1083 }
1084