2 * src/lib/krb5/asn.1/krb5_decode.c
4 * Copyright 1994 by the Massachusetts Institute of Technology.
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.
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.
26 #include "asn1_k_decode.h"
27 #include "asn1_decode.h"
30 /* setup *********************************************************/
31 /* set up variables */
33 asn1_error_code retval;\
36 asn1_construction construction;\
40 retval = asn1buf_wrap_data(&buf,code);\
41 if(retval) return retval
43 #define setup_no_length()\
44 asn1_error_code retval;\
47 asn1_construction construction;\
50 retval = asn1buf_wrap_data(&buf,code);\
51 if(retval) return retval
53 #define setup_no_tagnum()\
54 asn1_error_code retval;\
57 asn1_construction construction;\
59 retval = asn1buf_wrap_data(&buf,code);\
60 if(retval) return retval
62 #define alloc_field(var,type)\
63 var = (type*)calloc(1,sizeof(type));\
64 if((var) == NULL) return ENOMEM
66 #define setup_buf_only()\
67 asn1_error_code retval;\
69 retval = asn1buf_wrap_data(&buf,code);\
70 if(retval) return retval
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
83 /* process a structure *******************************************/
85 /* decode an explicit tag and place the number in tagnum */
87 retval = asn1_get_tag(&subbuf,&class,&construction,&tagnum,NULL);\
88 if(retval) return retval;\
89 if(class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
92 /* decode sequence header and initialize tagnum with the first field */
93 #define begin_structure()\
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;\
103 #define end_structure()\
104 asn1buf_sync(&buf,&subbuf)
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;\
113 /* decode a field (<[UNIVERSAL id]> <length> <contents>)
114 check that the id number == tagexpect then
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)
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); }
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;\
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)
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);\
145 /* clean up ******************************************************/
150 krb5_error_code decode_krb5_authenticator(code, rep)
151 const krb5_data * code;
152 krb5_authenticator ** rep;
155 alloc_field(*rep,krb5_authenticator);
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);
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);
179 krb5_error_code decode_krb5_ticket(code, rep)
180 const krb5_data * code;
184 alloc_field(*rep,krb5_ticket);
189 get_field(kvno,0,asn1_decode_kvno);
190 if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO;
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);
201 krb5_error_code decode_krb5_encryption_key(code, rep)
202 const krb5_data * code;
203 krb5_keyblock ** rep;
206 alloc_field(*rep,krb5_keyblock);
209 get_field((*rep)->keytype,0,asn1_decode_keytype);
210 get_lenfield((*rep)->length,(*rep)->contents,1,asn1_decode_octetstring);
212 (*rep)->magic = KV5M_KEYBLOCK;
213 (*rep)->etype = ETYPE_UNKNOWN;
218 krb5_error_code decode_krb5_enc_tkt_part(code, rep)
219 const krb5_data * code;
220 krb5_enc_tkt_part ** rep;
223 alloc_field(*rep,krb5_enc_tkt_part);
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);
245 krb5_error_code decode_krb5_enc_kdc_rep_part(code, rep)
246 const krb5_data * code;
247 krb5_enc_kdc_rep_part ** rep;
250 alloc_field(*rep,krb5_enc_kdc_rep_part);
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;
259 retval = asn1_decode_enc_kdc_rep_part(&buf,*rep);
260 if(retval) return (krb5_error_code)retval;
265 krb5_error_code decode_krb5_as_rep(code, rep)
266 const krb5_data * code;
270 alloc_field(*rep,krb5_kdc_rep);
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;
283 krb5_error_code decode_krb5_tgs_rep(code, rep)
284 const krb5_data * code;
288 alloc_field(*rep,krb5_kdc_rep);
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;
300 krb5_error_code decode_krb5_ap_req(code, rep)
301 const krb5_data * code;
305 alloc_field(*rep,krb5_ap_req);
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;
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);
327 krb5_error_code decode_krb5_ap_rep(code, rep)
328 const krb5_data * code;
332 alloc_field(*rep,krb5_ap_rep);
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;
345 get_field((*rep)->enc_part,2,asn1_decode_encrypted_data);
351 krb5_error_code decode_krb5_ap_rep_enc_part(code, rep)
352 const krb5_data * code;
353 krb5_ap_rep_enc_part ** rep;
356 alloc_field(*rep,krb5_ap_rep_enc_part);
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);
370 krb5_error_code decode_krb5_as_req(code, rep)
371 const krb5_data * code;
375 alloc_field(*rep,krb5_kdc_req);
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;
387 krb5_error_code decode_krb5_tgs_req(code, rep)
388 const krb5_data * code;
392 alloc_field(*rep,krb5_kdc_req);
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;
404 krb5_error_code decode_krb5_kdc_req_body(code, rep)
405 const krb5_data * code;
409 alloc_field(*rep,krb5_kdc_req);
411 retval = asn1_decode_kdc_req_body(&buf,*rep);
412 if(retval) return (krb5_error_code)retval;
417 krb5_error_code decode_krb5_safe(code, rep)
418 const krb5_data * code;
422 alloc_field(*rep,krb5_safe);
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;
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);
443 krb5_error_code decode_krb5_priv(code, rep)
444 const krb5_data * code;
448 alloc_field(*rep,krb5_priv);
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;
461 get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
467 krb5_error_code decode_krb5_enc_priv_part(code, rep)
468 const krb5_data * code;
469 krb5_priv_enc_part ** rep;
472 alloc_field(*rep,krb5_priv_enc_part);
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);
489 krb5_error_code decode_krb5_cred(code, rep)
490 const krb5_data * code;
494 alloc_field(*rep,krb5_cred);
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;
507 get_field((*rep)->tickets,2,asn1_decode_sequence_of_ticket);
508 get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
514 krb5_error_code decode_krb5_enc_cred_part(code, rep)
515 const krb5_data * code;
516 krb5_cred_enc_part ** rep;
519 alloc_field(*rep,krb5_cred_enc_part);
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);
536 krb5_error_code decode_krb5_error(code, rep)
537 const krb5_data * code;
541 alloc_field(*rep,krb5_error);
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;
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);
572 krb5_error_code decode_krb5_authdata(code, rep)
573 const krb5_data * code;
574 krb5_authdata *** rep;
578 retval = asn1_decode_authorization_data(&buf,rep);
579 if(retval) return (krb5_error_code)retval;
583 krb5_error_code decode_krb5_pwd_sequence(code, rep)
584 const krb5_data * code;
585 passwd_phrase_element ** rep;
588 alloc_field(*rep,passwd_phrase_element);
589 retval = asn1_decode_passwdsequence(&buf,*rep);
590 if(retval) return retval;
594 krb5_error_code decode_krb5_pwd_data(code, rep)
595 const krb5_data * code;
596 krb5_pwd_data ** rep;
599 alloc_field(*rep,krb5_pwd_data);
601 get_field((*rep)->sequence_count,0,asn1_decode_int);
602 get_field((*rep)->element,1,asn1_decode_sequence_of_passwdsequence);