Windows global stuff:
[krb5.git] / src / lib / krb5 / asn.1 / krb5_decode.c
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.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  */
23
24 #include "krb5.h"
25 #include "krbasn1.h"
26 #include "asn1_k_decode.h"
27 #include "asn1_decode.h"
28 #include "asn1_get.h"
29
30 /* setup *********************************************************/
31 /* set up variables */
32 #define setup()\
33 asn1_error_code retval;\
34 asn1buf buf;\
35 asn1_class class;\
36 asn1_construction construction;\
37 asn1_tagnum tagnum;\
38 int length;\
39 \
40 retval = asn1buf_wrap_data(&buf,code);\
41 if(retval) return retval
42
43 #define setup_no_length()\
44 asn1_error_code retval;\
45 asn1buf buf;\
46 asn1_class class;\
47 asn1_construction construction;\
48 asn1_tagnum tagnum;\
49 \
50 retval = asn1buf_wrap_data(&buf,code);\
51 if(retval) return retval
52
53 #define setup_no_tagnum()\
54 asn1_error_code retval;\
55 asn1buf buf;\
56 asn1_class class;\
57 asn1_construction construction;\
58 \
59 retval = asn1buf_wrap_data(&buf,code);\
60 if(retval) return retval
61
62 #define alloc_field(var,type)\
63 var = (type*)calloc(1,sizeof(type));\
64 if((var) == NULL) return ENOMEM
65
66 #define setup_buf_only()\
67 asn1_error_code retval;\
68 asn1buf buf;\
69 retval = asn1buf_wrap_data(&buf,code);\
70 if(retval) return retval
71
72
73 /* process encoding header ***************************************/
74 /* decode tag and check that it == [APPLICATION tagnum] */
75 #define check_apptag(tagexpect)\
76 retval = asn1_get_tag(&buf,&class,&construction,&tagnum,NULL);\
77 if(retval) return retval;\
78 if(class != APPLICATION || construction != CONSTRUCTED) return ASN1_BAD_ID;\
79 if(tagnum != (tagexpect)) return KRB5_BADMSGTYPE
80
81
82
83 /* process a structure *******************************************/
84
85 /* decode an explicit tag and place the number in tagnum */
86 #define next_tag()\
87 retval = asn1_get_tag(&subbuf,&class,&construction,&tagnum,NULL);\
88 if(retval) return retval;\
89 if(class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
90   return ASN1_BAD_ID
91
92 /* decode sequence header and initialize tagnum with the first field */
93 #define begin_structure()\
94 asn1buf subbuf;\
95 retval = asn1_get_tag(&buf,&class,&construction,&tagnum,&length);\
96 if(retval) return retval;\
97 if(class != UNIVERSAL || construction != CONSTRUCTED ||\
98    tagnum != ASN1_SEQUENCE) return ASN1_BAD_ID;\
99 retval = asn1buf_imbed(&subbuf,&buf,length);\
100 if(retval) return retval;\
101 next_tag()
102
103 #define end_structure()\
104 asn1buf_sync(&buf,&subbuf)
105
106 /* process fields *******************************************/
107 /* normal fields ************************/
108 #define get_field_body(var,decoder)\
109 retval = decoder(&subbuf,&(var));\
110 if(retval) return (krb5_error_code)retval;\
111 next_tag()
112
113 /* decode a field (<[UNIVERSAL id]> <length> <contents>)
114     check that the id number == tagexpect then
115     decode into var
116     get the next tag */
117 #define get_field(var,tagexpect,decoder)\
118 if(tagnum > (tagexpect)) return ASN1_MISSING_FIELD;\
119 if(tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;\
120 get_field_body(var,decoder)
121
122 /* decode (or skip, if not present) an optional field */
123 #define opt_field(var,tagexpect,decoder)\
124 if(tagnum == (tagexpect)){ get_field_body(var,decoder); }
125
126 /* field w/ accompanying length *********/
127 #define get_lenfield_body(len,var,decoder)\
128 retval = decoder(&subbuf,&(len),&(var));\
129 if(retval) return (krb5_error_code)retval;\
130 next_tag()
131
132 /* decode a field w/ its length (for string types) */
133 #define get_lenfield(len,var,tagexpect,decoder)\
134 if(tagnum > (tagexpect)) return ASN1_MISSING_FIELD;\
135 if(tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;\
136 get_lenfield_body(len,var,decoder)
137
138 /* decode an optional field w/ length */
139 #define opt_lenfield(len,var,tagexpect,decoder)\
140 if(tagnum == (tagexpect)){\
141   get_lenfield_body(len,var,decoder);\
142 }
143
144
145 /* clean up ******************************************************/
146 /* finish up */
147 #define cleanup()\
148 return 0
149
150 krb5_error_code decode_krb5_authenticator(code, rep)
151      const krb5_data * code;
152      krb5_authenticator ** rep;
153 {
154   setup();
155   alloc_field(*rep,krb5_authenticator);
156
157   check_apptag(2);
158   { begin_structure();
159     { krb5_kvno kvno;
160       get_field(kvno,0,asn1_decode_kvno);
161       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
162     alloc_field((*rep)->client,krb5_principal_data);
163     get_field((*rep)->client,1,asn1_decode_realm);
164     get_field((*rep)->client,2,asn1_decode_principal_name);
165     if(tagnum == 3){
166       alloc_field((*rep)->checksum,krb5_checksum);
167       get_field(*((*rep)->checksum),3,asn1_decode_checksum); }
168     get_field((*rep)->cusec,4,asn1_decode_int32);
169     get_field((*rep)->ctime,5,asn1_decode_kerberos_time);
170     if(tagnum == 6){ alloc_field((*rep)->subkey,krb5_keyblock); }
171     opt_field(*((*rep)->subkey),6,asn1_decode_encryption_key);
172     opt_field((*rep)->seq_number,7,asn1_decode_int32);
173     opt_field((*rep)->authorization_data,8,asn1_decode_authorization_data);
174     end_structure();
175   }
176   cleanup();
177 }
178
179 krb5_error_code decode_krb5_ticket(code, rep)
180      const krb5_data * code;
181      krb5_ticket ** rep;
182 {
183   setup();
184   alloc_field(*rep,krb5_ticket);
185   
186   check_apptag(1);
187   { begin_structure();
188     { krb5_kvno kvno;
189       get_field(kvno,0,asn1_decode_kvno);
190       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO;
191     }
192     alloc_field((*rep)->server,krb5_principal_data);
193     get_field((*rep)->server,1,asn1_decode_realm);
194     get_field((*rep)->server,2,asn1_decode_principal_name);
195     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
196     end_structure();
197   }
198   cleanup();
199 }
200
201 krb5_error_code decode_krb5_encryption_key(code, rep)
202      const krb5_data * code;
203      krb5_keyblock ** rep;
204 {
205   setup();
206   alloc_field(*rep,krb5_keyblock);
207
208   { begin_structure();
209     get_field((*rep)->keytype,0,asn1_decode_keytype);
210     get_lenfield((*rep)->length,(*rep)->contents,1,asn1_decode_octetstring);
211     end_structure();
212     (*rep)->magic = KV5M_KEYBLOCK;
213     (*rep)->etype = ETYPE_UNKNOWN;
214   }
215   cleanup();
216 }
217
218 krb5_error_code decode_krb5_enc_tkt_part(code, rep)
219      const krb5_data * code;
220      krb5_enc_tkt_part ** rep;
221 {
222   setup();
223   alloc_field(*rep,krb5_enc_tkt_part);
224
225   check_apptag(3);
226   { begin_structure();
227     get_field((*rep)->flags,0,asn1_decode_ticket_flags);
228     alloc_field((*rep)->session,krb5_keyblock);
229     get_field(*((*rep)->session),1,asn1_decode_encryption_key);
230     alloc_field((*rep)->client,krb5_principal_data);
231     get_field((*rep)->client,2,asn1_decode_realm);
232     get_field((*rep)->client,3,asn1_decode_principal_name);
233     get_field((*rep)->transited,4,asn1_decode_transited_encoding);
234     get_field((*rep)->times.authtime,5,asn1_decode_kerberos_time);
235     opt_field((*rep)->times.starttime,6,asn1_decode_kerberos_time);
236     get_field((*rep)->times.endtime,7,asn1_decode_kerberos_time);
237     opt_field((*rep)->times.renew_till,8,asn1_decode_kerberos_time);
238     opt_field((*rep)->caddrs,9,asn1_decode_host_addresses);
239     opt_field((*rep)->authorization_data,10,asn1_decode_authorization_data);
240     end_structure();
241   }
242   cleanup();
243 }
244
245 krb5_error_code decode_krb5_enc_kdc_rep_part(code, rep)
246      const krb5_data * code;
247      krb5_enc_kdc_rep_part ** rep;
248 {
249   setup_no_length();
250   alloc_field(*rep,krb5_enc_kdc_rep_part);
251
252   retval = asn1_get_tag(&buf,&class,&construction,&tagnum,NULL);
253   if(retval) return retval;
254   if(class != APPLICATION || construction != CONSTRUCTED) return ASN1_BAD_ID;
255   if(tagnum == 25) (*rep)->msg_type = KRB5_AS_REP;
256   else if(tagnum == 26) (*rep)->msg_type = KRB5_TGS_REP;
257   else return KRB5_BADMSGTYPE;
258
259   retval = asn1_decode_enc_kdc_rep_part(&buf,*rep);
260   if(retval) return (krb5_error_code)retval;
261
262   cleanup();
263 }
264
265 krb5_error_code decode_krb5_as_rep(code, rep)
266      const krb5_data * code;
267      krb5_kdc_rep ** rep;
268 {
269   setup_no_length();
270   alloc_field(*rep,krb5_kdc_rep);
271
272   check_apptag(11);
273   retval = asn1_decode_kdc_rep(&buf,*rep);
274   if(retval) return (krb5_error_code)retval;
275 #ifdef KRB5_MSGTYPE_STRICT
276   if((*rep)->msg_type != KRB5_AS_REP)
277       return KRB5_BADMSGTYPE;
278 #endif
279
280   cleanup();
281 }
282
283 krb5_error_code decode_krb5_tgs_rep(code, rep)
284      const krb5_data * code;
285      krb5_kdc_rep ** rep;
286 {
287   setup_no_length();
288   alloc_field(*rep,krb5_kdc_rep);
289
290   check_apptag(13);
291   retval = asn1_decode_kdc_rep(&buf,*rep);
292   if(retval) return (krb5_error_code)retval;
293 #ifdef KRB5_MSGTYPE_STRICT
294   if((*rep)->msg_type != KRB5_TGS_REP) return KRB5_BADMSGTYPE;
295 #endif
296
297   cleanup();
298 }
299
300 krb5_error_code decode_krb5_ap_req(code, rep)
301      const krb5_data * code;
302      krb5_ap_req ** rep;
303 {
304   setup();
305   alloc_field(*rep,krb5_ap_req);
306
307   check_apptag(14);
308   { begin_structure();
309     { krb5_kvno kvno;
310       get_field(kvno,0,asn1_decode_kvno);
311       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
312     { krb5_msgtype msg_type;
313       get_field(msg_type,1,asn1_decode_msgtype);
314 #ifdef KRB5_MSGTYPE_STRICT
315       if(msg_type != KRB5_AP_REQ) return KRB5_BADMSGTYPE;
316 #endif
317     }
318     get_field((*rep)->ap_options,2,asn1_decode_ap_options);
319     alloc_field((*rep)->ticket,krb5_ticket);
320     get_field(*((*rep)->ticket),3,asn1_decode_ticket);
321     get_field((*rep)->authenticator,4,asn1_decode_encrypted_data);
322     end_structure();
323   }
324   cleanup();
325 }
326
327 krb5_error_code decode_krb5_ap_rep(code, rep)
328      const krb5_data * code;
329      krb5_ap_rep ** rep;
330 {
331   setup();
332   alloc_field(*rep,krb5_ap_rep);
333
334   check_apptag(15);
335   { begin_structure();
336     { krb5_kvno kvno;
337       get_field(kvno,0,asn1_decode_kvno);
338       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
339     { krb5_msgtype msg_type;
340       get_field(msg_type,1,asn1_decode_msgtype);
341 #ifdef KRB5_MSGTYPE_STRICT
342       if(msg_type != KRB5_AP_REP) return KRB5_BADMSGTYPE;
343 #endif
344     }
345     get_field((*rep)->enc_part,2,asn1_decode_encrypted_data);
346     end_structure();
347   }
348   cleanup();
349 }
350
351 krb5_error_code decode_krb5_ap_rep_enc_part(code, rep)
352      const krb5_data * code;
353      krb5_ap_rep_enc_part ** rep;
354 {
355   setup();
356   alloc_field(*rep,krb5_ap_rep_enc_part);
357
358   check_apptag(27);
359   { begin_structure();
360     get_field((*rep)->ctime,0,asn1_decode_kerberos_time);
361     get_field((*rep)->cusec,1,asn1_decode_int32);
362     if(tagnum == 2){ alloc_field((*rep)->subkey,krb5_keyblock); }
363     opt_field(*((*rep)->subkey),2,asn1_decode_encryption_key);
364     opt_field((*rep)->seq_number,3,asn1_decode_int32);
365     end_structure();
366   }
367   cleanup();
368 }
369
370 krb5_error_code decode_krb5_as_req(code, rep)
371      const krb5_data * code;
372      krb5_kdc_req ** rep;
373 {
374   setup_no_length();
375   alloc_field(*rep,krb5_kdc_req);
376
377   check_apptag(10);
378   retval = asn1_decode_kdc_req(&buf,*rep);
379   if(retval) return (krb5_error_code)retval;
380 #ifdef KRB5_MSGTYPE_STRICT
381   if((*rep)->msg_type != KRB5_AS_REQ) return KRB5_BADMSGTYPE;
382 #endif
383   
384   cleanup();
385 }
386
387 krb5_error_code decode_krb5_tgs_req(code, rep)
388      const krb5_data * code;
389      krb5_kdc_req ** rep;
390 {
391   setup_no_length();
392   alloc_field(*rep,krb5_kdc_req);
393
394   check_apptag(12);
395   retval = asn1_decode_kdc_req(&buf,*rep);
396   if(retval) return (krb5_error_code)retval;
397 #ifdef KRB5_MSGTYPE_STRICT
398   if((*rep)->msg_type != KRB5_TGS_REQ) return KRB5_BADMSGTYPE;
399 #endif
400   
401   cleanup();
402 }
403
404 krb5_error_code decode_krb5_kdc_req_body(code, rep)
405      const krb5_data * code;
406      krb5_kdc_req ** rep;
407 {
408   setup_buf_only();
409   alloc_field(*rep,krb5_kdc_req);
410
411   retval = asn1_decode_kdc_req_body(&buf,*rep);
412   if(retval) return (krb5_error_code)retval;
413
414   cleanup();
415 }
416
417 krb5_error_code decode_krb5_safe(code, rep)
418      const krb5_data * code;
419      krb5_safe ** rep;
420 {
421   setup();
422   alloc_field(*rep,krb5_safe);
423
424   check_apptag(20);
425   { begin_structure();
426     { krb5_kvno kvno;
427       get_field(kvno,0,asn1_decode_kvno);
428       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
429     { krb5_msgtype msg_type;
430       get_field(msg_type,1,asn1_decode_msgtype);
431 #ifdef KRB5_MSGTYPE_STRICT
432       if(msg_type != KRB5_SAFE) return KRB5_BADMSGTYPE;
433 #endif
434     }
435     get_field(**rep,2,asn1_decode_krb_safe_body);
436     alloc_field((*rep)->checksum,krb5_checksum);
437     get_field(*((*rep)->checksum),3,asn1_decode_checksum);
438     end_structure();
439   }
440   cleanup();
441 }
442
443 krb5_error_code decode_krb5_priv(code, rep)
444      const krb5_data * code;
445      krb5_priv ** rep;
446 {
447   setup();
448   alloc_field(*rep,krb5_priv);
449
450   check_apptag(21);
451   { begin_structure();
452     { krb5_kvno kvno;
453       get_field(kvno,0,asn1_decode_kvno);
454       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
455     { krb5_msgtype msg_type;
456       get_field(msg_type,1,asn1_decode_msgtype);
457 #ifdef KRB5_MSGTYPE_STRICT
458       if(msg_type != KRB5_PRIV) return KRB5_BADMSGTYPE;
459 #endif
460     }
461     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
462     end_structure();
463   }
464   cleanup();
465 }
466
467 krb5_error_code decode_krb5_enc_priv_part(code, rep)
468      const krb5_data * code;
469      krb5_priv_enc_part ** rep;
470 {
471   setup();
472   alloc_field(*rep,krb5_priv_enc_part);
473
474   check_apptag(28);
475   { begin_structure();
476     get_lenfield((*rep)->user_data.length,(*rep)->user_data.data,0,asn1_decode_charstring);
477     opt_field((*rep)->timestamp,1,asn1_decode_kerberos_time);
478     opt_field((*rep)->usec,2,asn1_decode_int32);
479     opt_field((*rep)->seq_number,3,asn1_decode_int32);
480     alloc_field((*rep)->s_address,krb5_address);
481     get_field(*((*rep)->s_address),4,asn1_decode_host_address);
482     if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
483     opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
484     end_structure();
485   }
486   cleanup();
487 }
488
489 krb5_error_code decode_krb5_cred(code, rep)
490      const krb5_data * code;
491      krb5_cred ** rep;
492 {
493   setup();
494   alloc_field(*rep,krb5_cred);
495
496   check_apptag(22);
497   { begin_structure();
498     { krb5_kvno kvno;
499       get_field(kvno,0,asn1_decode_kvno);
500       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
501     { krb5_msgtype msg_type;
502       get_field(msg_type,1,asn1_decode_msgtype);
503 #ifdef KRB5_MSGTYPE_STRICT
504       if(msg_type != KRB5_CRED) return KRB5_BADMSGTYPE;
505 #endif
506     }
507     get_field((*rep)->tickets,2,asn1_decode_sequence_of_ticket);
508     get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
509     end_structure();
510   }
511   cleanup();
512 }
513
514 krb5_error_code decode_krb5_enc_cred_part(code, rep)
515      const krb5_data * code;
516      krb5_cred_enc_part ** rep;
517 {
518   setup();
519   alloc_field(*rep,krb5_cred_enc_part);
520
521   check_apptag(29);
522   { begin_structure();
523     get_field((*rep)->ticket_info,0,asn1_decode_sequence_of_krb_cred_info);
524     opt_field((*rep)->nonce,1,asn1_decode_int32);
525     opt_field((*rep)->timestamp,2,asn1_decode_kerberos_time);
526     opt_field((*rep)->usec,3,asn1_decode_int32);
527     if(tagnum == 4){ alloc_field((*rep)->s_address,krb5_address); }
528     opt_field(*((*rep)->s_address),4,asn1_decode_host_address);
529     if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
530     opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
531     end_structure();
532   }
533   cleanup();
534 }
535
536 krb5_error_code decode_krb5_error(code, rep)
537      const krb5_data * code;
538      krb5_error ** rep;
539 {
540   setup();
541   alloc_field(*rep,krb5_error);
542   
543   check_apptag(30);
544   { begin_structure();
545     { krb5_kvno kvno;
546       get_field(kvno,0,asn1_decode_kvno);
547       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
548     { krb5_msgtype msg_type;
549       get_field(msg_type,1,asn1_decode_msgtype);
550 #ifdef KRB5_MSGTYPE_STRICT
551       if(msg_type != KRB5_ERROR) return KRB5_BADMSGTYPE;
552 #endif
553     }
554     opt_field((*rep)->ctime,2,asn1_decode_kerberos_time);
555     opt_field((*rep)->cusec,3,asn1_decode_int32);
556     get_field((*rep)->stime,4,asn1_decode_kerberos_time);
557     get_field((*rep)->susec,5,asn1_decode_int32);
558     get_field((*rep)->error,6,asn1_decode_ui_4);
559     if(tagnum == 7){ alloc_field((*rep)->client,krb5_principal_data); }
560     opt_field((*rep)->client,7,asn1_decode_realm);
561     opt_field((*rep)->client,8,asn1_decode_principal_name);
562     alloc_field((*rep)->server,krb5_principal_data);
563     get_field((*rep)->server,9,asn1_decode_realm);
564     get_field((*rep)->server,10,asn1_decode_principal_name);
565     opt_lenfield((*rep)->text.length,(*rep)->text.data,11,asn1_decode_generalstring);
566     opt_lenfield((*rep)->e_data.length,(*rep)->e_data.data,12,asn1_decode_charstring);
567     end_structure();
568   }
569   cleanup();
570 }
571
572 krb5_error_code decode_krb5_authdata(code, rep)
573      const krb5_data * code;
574      krb5_authdata *** rep;
575 {
576   setup_buf_only();
577   *rep = 0;
578   retval = asn1_decode_authorization_data(&buf,rep);
579   if(retval) return (krb5_error_code)retval;
580   cleanup();
581 }
582
583 krb5_error_code decode_krb5_pwd_sequence(code, rep)
584      const krb5_data * code;
585      passwd_phrase_element ** rep;
586 {
587   setup_buf_only();
588   alloc_field(*rep,passwd_phrase_element);
589   retval = asn1_decode_passwdsequence(&buf,*rep);
590   if(retval) return retval;
591   cleanup();
592 }
593
594 krb5_error_code decode_krb5_pwd_data(code, rep)
595      const krb5_data * code;
596      krb5_pwd_data ** rep;
597 {
598   setup();
599   alloc_field(*rep,krb5_pwd_data);
600   { begin_structure();
601     get_field((*rep)->sequence_count,0,asn1_decode_int);
602     get_field((*rep)->element,1,asn1_decode_sequence_of_passwdsequence);
603     end_structure (); }
604   cleanup();
605 }