1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 /* 8 * src/lib/krb5/asn.1/asn1_k_decode.c 9 * 10 * Copyright 1994 by the Massachusetts Institute of Technology. 11 * All Rights Reserved. 12 * 13 * Export of this software from the United States of America may 14 * require a specific license from the United States Government. 15 * It is the responsibility of any person or organization contemplating 16 * export to obtain such a license before exporting. 17 * 18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 19 * distribute this software and its documentation for any purpose and 20 * without fee is hereby granted, provided that the above copyright 21 * notice appear in all copies and that both that copyright notice and 22 * this permission notice appear in supporting documentation, and that 23 * the name of M.I.T. not be used in advertising or publicity pertaining 24 * to distribution of the software without specific, written prior 25 * permission. Furthermore if you modify this software you must label 26 * your software as modified software and not distribute it in such a 27 * fashion that it might be confused with the original M.I.T. software. 28 * M.I.T. makes no representations about the suitability of 29 * this software for any purpose. It is provided "as is" without express 30 * or implied warranty. 31 */ 32 33 #include "asn1_k_decode.h" 34 #include "asn1_decode.h" 35 #include "asn1_get.h" 36 #include "asn1_misc.h" 37 38 /* Declare useful decoder variables. */ 39 #define setup() \ 40 asn1_error_code retval; \ 41 asn1_class asn1class; \ 42 asn1_construction construction; \ 43 asn1_tagnum tagnum; \ 44 unsigned int length, taglen 45 46 #define unused_var(x) if (0) { x = 0; x = x - x; } 47 48 /* This is used for prefetch of next tag in sequence. */ 49 #define next_tag() \ 50 { taginfo t2; \ 51 retval = asn1_get_tag_2(&subbuf, &t2); \ 52 if (retval) return retval; \ 53 /* Copy out to match previous functionality, until better integrated. */ \ 54 asn1class = t2.asn1class; \ 55 construction = t2.construction; \ 56 tagnum = t2.tagnum; \ 57 taglen = t2.length; \ 58 indef = t2.indef; \ 59 } 60 61 /* Force check for EOC tag. */ 62 #define get_eoc() \ 63 { \ 64 taginfo t3; \ 65 retval = asn1_get_tag_2(&subbuf, &t3); \ 66 if(retval) return retval; \ 67 if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef) \ 68 return ASN1_MISSING_EOC; \ 69 /* Copy out to match previous functionality, until better integrated. */ \ 70 asn1class = t3.asn1class; \ 71 construction = t3.construction; \ 72 tagnum = t3.tagnum; \ 73 taglen = t3.length; \ 74 indef = t3.indef; \ 75 } 76 77 #define alloc_field(var, type) \ 78 var = (type*)calloc(1, sizeof(type)); \ 79 if ((var) == NULL) return ENOMEM 80 81 /* Fetch an expected APPLICATION class tag and verify. */ 82 #define apptag(tagexpect) \ 83 { \ 84 taginfo t1; \ 85 retval = asn1_get_tag_2(buf, &t1); \ 86 if (retval) return retval; \ 87 if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED || \ 88 t1.tagnum != (tagexpect)) return ASN1_BAD_ID; \ 89 /* Copy out to match previous functionality, until better integrated. */ \ 90 asn1class = t1.asn1class; \ 91 construction = t1.construction; \ 92 tagnum = t1.tagnum; \ 93 applen = t1.length; \ 94 } 95 96 /**** normal fields ****/ 97 98 /* 99 * get_field_body 100 * 101 * Get bare field. This also prefetches the next tag. The call to 102 * get_eoc() assumes that any values fetched by this macro are 103 * enclosed in a context-specific tag. 104 */ 105 #define get_field_body(var, decoder) \ 106 retval = decoder(&subbuf, &(var)); \ 107 if (retval) return retval; \ 108 if (!taglen && indef) { get_eoc(); } \ 109 next_tag() 110 111 /* 112 * get_field 113 * 114 * Get field having an expected context specific tag. This assumes 115 * that context-specific tags are monotonically increasing in its 116 * verification of tag numbers. 117 */ 118 #define get_field(var, tagexpect, decoder) \ 119 if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD; \ 120 if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD; \ 121 if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ 122 && (tagnum || taglen || asn1class != UNIVERSAL)) \ 123 return ASN1_BAD_ID; \ 124 get_field_body(var,decoder) 125 126 /* 127 * opt_field 128 * 129 * Get an optional field with an expected context specific tag. 130 * Assumes that OPTVAL will have the default value, thus failing to 131 * distinguish between absent optional values and present optional 132 * values that happen to have the value of OPTVAL. 133 */ 134 #define opt_field(var, tagexpect, decoder, optvalue) \ 135 if (asn1buf_remains(&subbuf, seqindef)) { \ 136 if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ 137 && (tagnum || taglen || asn1class != UNIVERSAL)) \ 138 return ASN1_BAD_ID; \ 139 if (tagnum == (tagexpect)) { \ 140 get_field_body(var, decoder); \ 141 } else var = optvalue; \ 142 } 143 144 /**** fields w/ length ****/ 145 146 /* similar to get_field_body */ 147 #define get_lenfield_body(len, var, decoder) \ 148 retval = decoder(&subbuf, &(len), &(var)); \ 149 if (retval) return retval; \ 150 if (!taglen && indef) { get_eoc(); } \ 151 next_tag() 152 153 /* similar to get_field_body */ 154 #define get_lenfield(len, var, tagexpect, decoder) \ 155 if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD; \ 156 if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD; \ 157 if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ 158 && (tagnum || taglen || asn1class != UNIVERSAL)) \ 159 return ASN1_BAD_ID; \ 160 get_lenfield_body(len, var, decoder) 161 162 /* similar to opt_field */ 163 #define opt_lenfield(len, var, tagexpect, decoder) \ 164 if (tagnum == (tagexpect)) { \ 165 get_lenfield_body(len, var, decoder); \ 166 } else { len = 0; var = 0; } 167 168 /* 169 * begin_structure 170 * 171 * Declares some variables for decoding SEQUENCE types. This is meant 172 * to be called in an inner block that ends with a call to 173 * end_structure(). 174 */ 175 #define begin_structure() \ 176 asn1buf subbuf; \ 177 int seqindef; \ 178 int indef; \ 179 retval = asn1_get_sequence(buf, &length, &seqindef); \ 180 if (retval) return retval; \ 181 retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ 182 if (retval) return retval; \ 183 next_tag() 184 185 /* skip trailing garbage */ 186 #define end_structure() \ 187 retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum, \ 188 length, indef, seqindef); \ 189 if (retval) return retval 190 191 /* 192 * sequence_of 193 * 194 * Declares some variables for decoding SEQUENCE OF types. This is 195 * meant to be called in an inner block that ends with a call to 196 * end_sequence_of(). 197 */ 198 #define sequence_of(buf) \ 199 unsigned int length, taglen; \ 200 asn1_class asn1class; \ 201 asn1_construction construction; \ 202 asn1_tagnum tagnum; \ 203 int indef; \ 204 sequence_of_common(buf) 205 206 /* 207 * sequence_of_no_tagvars 208 * 209 * This is meant for use inside decoder functions that have an outer 210 * sequence structure and thus declares variables of different names 211 * than does sequence_of() to avoid shadowing. 212 */ 213 #define sequence_of_no_tagvars(buf) \ 214 asn1_class eseqclass; \ 215 asn1_construction eseqconstr; \ 216 asn1_tagnum eseqnum; \ 217 unsigned int eseqlen; \ 218 int eseqindef; \ 219 sequence_of_common(buf) 220 221 /* 222 * sequence_of_common 223 * 224 * Fetches the outer SEQUENCE OF length info into {length,seqofindef} 225 * and imbeds an inner buffer seqbuf. Unlike begin_structure(), it 226 * does not prefetch the next tag. 227 */ 228 #define sequence_of_common(buf) \ 229 int size = 0; \ 230 asn1buf seqbuf; \ 231 int seqofindef; \ 232 retval = asn1_get_sequence(buf, &length, &seqofindef); \ 233 if (retval) return retval; \ 234 retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef); \ 235 if (retval) return retval 236 237 /* 238 * end_sequence_of 239 * 240 * Attempts to fetch an EOC tag, if any, and to sync over trailing 241 * garbage, if any. 242 */ 243 #define end_sequence_of(buf) \ 244 { \ 245 taginfo t4; \ 246 retval = asn1_get_tag_2(&seqbuf, &t4); \ 247 if (retval) return retval; \ 248 /* Copy out to match previous functionality, until better integrated. */ \ 249 asn1class = t4.asn1class; \ 250 construction = t4.construction; \ 251 tagnum = t4.tagnum; \ 252 taglen = t4.length; \ 253 indef = t4.indef; \ 254 } \ 255 retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum, \ 256 length, indef, seqofindef); \ 257 if (retval) return retval; 258 259 /* 260 * end_sequence_of_no_tagvars 261 * 262 * Like end_sequence_of(), but uses the different (non-shadowing) 263 * variable names. 264 */ 265 #define end_sequence_of_no_tagvars(buf) \ 266 { \ 267 taginfo t5; \ 268 retval = asn1_get_tag_2(&seqbuf, &t5); \ 269 if (retval) return retval; \ 270 /* Copy out to match previous functionality, until better integrated. */ \ 271 eseqclass = t5.asn1class; \ 272 eseqconstr = t5.construction; \ 273 eseqnum = t5.tagnum; \ 274 eseqlen = t5.length; \ 275 eseqindef = t5.indef; \ 276 } \ 277 retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum, \ 278 eseqlen, eseqindef, seqofindef); \ 279 if (retval) return retval; 280 281 #define cleanup() \ 282 return 0 283 284 /* scalars */ 285 asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val) 286 { 287 time_t t; 288 asn1_error_code retval; 289 290 retval = asn1_decode_generaltime(buf,&t); 291 if (retval) 292 return retval; 293 294 *val = t; 295 return 0; 296 } 297 298 #define integer_convert(fname,ktype)\ 299 asn1_error_code fname(asn1buf * buf, ktype * val)\ 300 {\ 301 asn1_error_code retval;\ 302 long n;\ 303 retval = asn1_decode_integer(buf,&n);\ 304 if(retval) return retval;\ 305 *val = (ktype)n;\ 306 return 0;\ 307 } 308 #define unsigned_integer_convert(fname,ktype)\ 309 asn1_error_code fname(asn1buf * buf, ktype * val)\ 310 {\ 311 asn1_error_code retval;\ 312 unsigned long n;\ 313 retval = asn1_decode_unsigned_integer(buf,&n);\ 314 if(retval) return retval;\ 315 *val = (ktype)n;\ 316 return 0;\ 317 } 318 integer_convert(asn1_decode_int,int) 319 integer_convert(asn1_decode_int32,krb5_int32) 320 integer_convert(asn1_decode_kvno,krb5_kvno) 321 integer_convert(asn1_decode_enctype,krb5_enctype) 322 integer_convert(asn1_decode_cksumtype,krb5_cksumtype) 323 integer_convert(asn1_decode_octet,krb5_octet) 324 integer_convert(asn1_decode_addrtype,krb5_addrtype) 325 integer_convert(asn1_decode_authdatatype,krb5_authdatatype) 326 unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2) 327 unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4) 328 329 asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val) 330 { 331 asn1_error_code retval; 332 unsigned long n; 333 334 retval = asn1_decode_maybe_unsigned(buf, &n); 335 if (retval) return retval; 336 *val = (krb5_ui_4)n & 0xffffffff; 337 return 0; 338 } 339 340 asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val) 341 { 342 asn1_error_code retval; 343 unsigned long n; 344 345 retval = asn1_decode_unsigned_integer(buf,&n); 346 if(retval) return retval; 347 348 *val = (krb5_msgtype) n; 349 return 0; 350 } 351 352 353 /* structures */ 354 asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val) 355 { 356 return asn1_decode_generalstring(buf, 357 &((*val)->realm.length), 358 &((*val)->realm.data)); 359 } 360 361 asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val) 362 { 363 setup(); 364 { begin_structure(); 365 get_field((*val)->type,0,asn1_decode_int32); 366 367 { sequence_of_no_tagvars(&subbuf); 368 while(asn1buf_remains(&seqbuf,seqofindef) > 0){ 369 size++; 370 if ((*val)->data == NULL) 371 (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data)); 372 else 373 (*val)->data = (krb5_data*)realloc((*val)->data, 374 size*sizeof(krb5_data)); 375 if((*val)->data == NULL) return ENOMEM; 376 retval = asn1_decode_generalstring(&seqbuf, 377 &((*val)->data[size-1].length), 378 &((*val)->data[size-1].data)); 379 if(retval) return retval; 380 } 381 (*val)->length = size; 382 end_sequence_of_no_tagvars(&subbuf); 383 } 384 if (indef) { 385 get_eoc(); 386 } 387 next_tag(); 388 end_structure(); 389 (*val)->magic = KV5M_PRINCIPAL; 390 } 391 cleanup(); 392 } 393 394 asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val) 395 { 396 setup(); 397 { begin_structure(); 398 get_field(val->checksum_type,0,asn1_decode_cksumtype); 399 get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); 400 end_structure(); 401 val->magic = KV5M_CHECKSUM; 402 } 403 cleanup(); 404 } 405 406 asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val) 407 { 408 setup(); 409 { begin_structure(); 410 get_field(val->enctype,0,asn1_decode_enctype); 411 get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); 412 end_structure(); 413 val->magic = KV5M_KEYBLOCK; 414 } 415 cleanup(); 416 } 417 418 asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val) 419 { 420 setup(); 421 { begin_structure(); 422 get_field(val->enctype,0,asn1_decode_enctype); 423 opt_field(val->kvno,1,asn1_decode_kvno,0); 424 get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring); 425 end_structure(); 426 val->magic = KV5M_ENC_DATA; 427 } 428 cleanup(); 429 } 430 431 asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val) 432 { 433 asn1_error_code retval; 434 asn1_octet unused, o; 435 taginfo t; 436 int i; 437 krb5_flags f=0; 438 unsigned int length; 439 440 retval = asn1_get_tag_2(buf, &t); 441 if (retval) return retval; 442 if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE || 443 t.tagnum != ASN1_BITSTRING) 444 return ASN1_BAD_ID; 445 length = t.length; 446 447 retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */ 448 if(retval) return retval; 449 450 /* Number of unused bits must be between 0 and 7. */ 451 if (unused > 7) return ASN1_BAD_FORMAT; 452 length--; 453 454 for(i = 0; i < length; i++) { 455 retval = asn1buf_remove_octet(buf,&o); 456 if(retval) return retval; 457 /* ignore bits past number 31 */ 458 if (i < 4) 459 f = (f<<8) | ((krb5_flags)o&0xFF); 460 } 461 if (length <= 4) { 462 /* Mask out unused bits, but only if necessary. */ 463 f &= ~(krb5_flags)0 << unused; 464 } 465 /* left-justify */ 466 if (length < 4) 467 f <<= (4 - length) * 8; 468 *val = f; 469 return 0; 470 } 471 472 asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val) 473 { return asn1_decode_krb5_flags(buf,val); } 474 475 asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val) 476 { return asn1_decode_krb5_flags(buf,val); } 477 478 asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val) 479 { return asn1_decode_krb5_flags(buf,val); } 480 481 asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val) 482 { 483 setup(); 484 { begin_structure(); 485 get_field(val->tr_type,0,asn1_decode_octet); 486 get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring); 487 end_structure(); 488 val->magic = KV5M_TRANSITED; 489 } 490 cleanup(); 491 } 492 493 asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val) 494 { 495 setup(); 496 { begin_structure(); 497 alloc_field(val->session,krb5_keyblock); 498 get_field(*(val->session),0,asn1_decode_encryption_key); 499 get_field(val->last_req,1,asn1_decode_last_req); 500 get_field(val->nonce,2,asn1_decode_int32); 501 opt_field(val->key_exp,3,asn1_decode_kerberos_time,0); 502 get_field(val->flags,4,asn1_decode_ticket_flags); 503 get_field(val->times.authtime,5,asn1_decode_kerberos_time); 504 /* Set to authtime if missing */ 505 opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime); 506 get_field(val->times.endtime,7,asn1_decode_kerberos_time); 507 opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0); 508 alloc_field(val->server,krb5_principal_data); 509 get_field(val->server,9,asn1_decode_realm); 510 get_field(val->server,10,asn1_decode_principal_name); 511 opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL); 512 end_structure(); 513 val->magic = KV5M_ENC_KDC_REP_PART; 514 } 515 cleanup(); 516 } 517 518 asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val) 519 { 520 setup(); 521 unsigned int applen; 522 apptag(1); 523 { begin_structure(); 524 { krb5_kvno vno; 525 get_field(vno,0,asn1_decode_kvno); 526 if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } 527 alloc_field(val->server,krb5_principal_data); 528 get_field(val->server,1,asn1_decode_realm); 529 get_field(val->server,2,asn1_decode_principal_name); 530 get_field(val->enc_part,3,asn1_decode_encrypted_data); 531 end_structure(); 532 val->magic = KV5M_TICKET; 533 } 534 if (!applen) { 535 taginfo t; 536 retval = asn1_get_tag_2(buf, &t); 537 if (retval) return retval; 538 } 539 cleanup(); 540 } 541 542 asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val) 543 { 544 setup(); 545 { begin_structure(); 546 { krb5_kvno kvno; 547 get_field(kvno,1,asn1_decode_kvno); 548 if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } 549 get_field(val->msg_type,2,asn1_decode_msgtype); 550 opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL); 551 get_field(*val,4,asn1_decode_kdc_req_body); 552 end_structure(); 553 val->magic = KV5M_KDC_REQ; 554 } 555 cleanup(); 556 } 557 558 asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val) 559 { 560 setup(); 561 { 562 krb5_principal psave; 563 begin_structure(); 564 get_field(val->kdc_options,0,asn1_decode_kdc_options); 565 if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); } 566 opt_field(val->client,1,asn1_decode_principal_name,NULL); 567 alloc_field(val->server,krb5_principal_data); 568 get_field(val->server,2,asn1_decode_realm); 569 if(val->client != NULL){ 570 retval = asn1_krb5_realm_copy(val->client,val->server); 571 if(retval) return retval; } 572 573 /* If opt_field server is missing, memory reference to server is 574 lost and results in memory leak */ 575 psave = val->server; 576 opt_field(val->server,3,asn1_decode_principal_name,NULL); 577 if(val->server == NULL){ 578 if(psave->realm.data) { 579 free(psave->realm.data); 580 psave->realm.data = NULL; 581 psave->realm.length=0; 582 } 583 free(psave); 584 } 585 opt_field(val->from,4,asn1_decode_kerberos_time,0); 586 get_field(val->till,5,asn1_decode_kerberos_time); 587 opt_field(val->rtime,6,asn1_decode_kerberos_time,0); 588 get_field(val->nonce,7,asn1_decode_int32); 589 get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype); 590 opt_field(val->addresses,9,asn1_decode_host_addresses,0); 591 if(tagnum == 10){ 592 get_field(val->authorization_data,10,asn1_decode_encrypted_data); } 593 else{ 594 val->authorization_data.magic = KV5M_ENC_DATA; 595 val->authorization_data.enctype = 0; 596 val->authorization_data.kvno = 0; 597 val->authorization_data.ciphertext.data = NULL; 598 val->authorization_data.ciphertext.length = 0; 599 } 600 opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL); 601 end_structure(); 602 val->magic = KV5M_KDC_REQ; 603 } 604 cleanup(); 605 } 606 607 asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val) 608 { 609 setup(); 610 { begin_structure(); 611 get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring); 612 opt_field(val->timestamp,1,asn1_decode_kerberos_time,0); 613 opt_field(val->usec,2,asn1_decode_int32,0); 614 opt_field(val->seq_number,3,asn1_decode_seqnum,0); 615 alloc_field(val->s_address,krb5_address); 616 get_field(*(val->s_address),4,asn1_decode_host_address); 617 if(tagnum == 5){ 618 alloc_field(val->r_address,krb5_address); 619 get_field(*(val->r_address),5,asn1_decode_host_address); 620 } else val->r_address = NULL; 621 end_structure(); 622 val->magic = KV5M_SAFE; 623 } 624 cleanup(); 625 } 626 627 asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val) 628 { 629 setup(); 630 { begin_structure(); 631 get_field(val->addrtype,0,asn1_decode_addrtype); 632 get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); 633 end_structure(); 634 val->magic = KV5M_ADDRESS; 635 } 636 cleanup(); 637 } 638 639 asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val) 640 { 641 setup(); 642 { begin_structure(); 643 { krb5_kvno pvno; 644 get_field(pvno,0,asn1_decode_kvno); 645 if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } 646 get_field(val->msg_type,1,asn1_decode_msgtype); 647 opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL); 648 alloc_field(val->client,krb5_principal_data); 649 get_field(val->client,3,asn1_decode_realm); 650 get_field(val->client,4,asn1_decode_principal_name); 651 alloc_field(val->ticket,krb5_ticket); 652 get_field(*(val->ticket),5,asn1_decode_ticket); 653 get_field(val->enc_part,6,asn1_decode_encrypted_data); 654 end_structure(); 655 val->magic = KV5M_KDC_REP; 656 } 657 cleanup(); 658 } 659 660 661 /* arrays */ 662 #define get_element(element,decoder)\ 663 retval = decoder(&seqbuf,element);\ 664 if(retval) return retval 665 666 #define array_append(array,size,element,type)\ 667 size++;\ 668 if (*(array) == NULL)\ 669 *(array) = (type**)malloc((size+1)*sizeof(type*));\ 670 else\ 671 *(array) = (type**)realloc(*(array),\ 672 (size+1)*sizeof(type*));\ 673 if(*(array) == NULL) return ENOMEM;\ 674 (*(array))[(size)-1] = elt 675 676 #define decode_array_body(type,decoder)\ 677 asn1_error_code retval;\ 678 type *elt;\ 679 \ 680 { sequence_of(buf);\ 681 while(asn1buf_remains(&seqbuf,seqofindef) > 0){\ 682 alloc_field(elt,type);\ 683 get_element(elt,decoder);\ 684 array_append(val,size,elt,type);\ 685 }\ 686 if (*val == NULL)\ 687 *val = (type **)malloc(sizeof(type*));\ 688 (*val)[size] = NULL;\ 689 end_sequence_of(buf);\ 690 }\ 691 cleanup() 692 693 694 asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val) 695 { 696 decode_array_body(krb5_authdata,asn1_decode_authdata_elt); 697 } 698 699 asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val) 700 { 701 setup(); 702 { begin_structure(); 703 get_field(val->ad_type,0,asn1_decode_authdatatype); 704 get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); 705 end_structure(); 706 val->magic = KV5M_AUTHDATA; 707 } 708 cleanup(); 709 } 710 711 asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val) 712 { 713 decode_array_body(krb5_address,asn1_decode_host_address); 714 } 715 716 asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val) 717 { 718 decode_array_body(krb5_ticket,asn1_decode_ticket); 719 } 720 721 asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val) 722 { 723 decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info); 724 } 725 726 asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val) 727 { 728 setup(); 729 { begin_structure(); 730 alloc_field(val->session,krb5_keyblock); 731 get_field(*(val->session),0,asn1_decode_encryption_key); 732 if(tagnum == 1){ 733 alloc_field(val->client,krb5_principal_data); 734 opt_field(val->client,1,asn1_decode_realm,NULL); 735 opt_field(val->client,2,asn1_decode_principal_name,NULL); } 736 opt_field(val->flags,3,asn1_decode_ticket_flags,0); 737 opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0); 738 opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0); 739 opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0); 740 opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0); 741 if(tagnum == 8){ 742 alloc_field(val->server,krb5_principal_data); 743 opt_field(val->server,8,asn1_decode_realm,NULL); 744 opt_field(val->server,9,asn1_decode_principal_name,NULL); } 745 opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL); 746 end_structure(); 747 val->magic = KV5M_CRED_INFO; 748 } 749 cleanup(); 750 } 751 752 asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val) 753 { 754 decode_array_body(krb5_pa_data,asn1_decode_pa_data); 755 } 756 757 asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val) 758 { 759 setup(); 760 { begin_structure(); 761 get_field(val->pa_type,1,asn1_decode_int32); 762 get_lenfield(val->length,val->contents,2,asn1_decode_octetstring); 763 end_structure(); 764 val->magic = KV5M_PA_DATA; 765 } 766 cleanup(); 767 } 768 769 asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val) 770 { 771 decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry); 772 } 773 774 asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val) 775 { 776 setup(); 777 { begin_structure(); 778 get_field(val->lr_type,0,asn1_decode_int32); 779 get_field(val->value,1,asn1_decode_kerberos_time); 780 end_structure(); 781 val->magic = KV5M_LAST_REQ_ENTRY; 782 #ifdef KRB5_GENEROUS_LR_TYPE 783 /* If we are only a single byte wide and negative - fill in the 784 other bits */ 785 if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U; 786 #endif 787 } 788 cleanup(); 789 } 790 791 asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val) 792 { 793 asn1_error_code retval; 794 { sequence_of(buf); 795 while(asn1buf_remains(&seqbuf,seqofindef) > 0){ 796 size++; 797 if (*val == NULL) 798 *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype)); 799 else 800 *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype)); 801 if(*val == NULL) return ENOMEM; 802 retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1])); 803 if(retval) return retval; 804 } 805 *num = size; 806 end_sequence_of(buf); 807 } 808 cleanup(); 809 } 810 811 asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val) 812 { 813 decode_array_body(krb5_checksum, asn1_decode_checksum); 814 } 815 816 static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val ) 817 { 818 /* 819 * Solaris Kerberos: 820 * Use a temporary char* (tmpp) in place of val->salt when calling 821 * get_lenfield(). val->salt cannot be cast to a char* as casting will not 822 * produce an lvalue. Use the new value pointed to by tmpp as the value for 823 * val->salt. 824 */ 825 char *tmpp; 826 setup(); 827 { begin_structure(); 828 get_field(val->etype,0,asn1_decode_enctype); 829 if (tagnum == 1) { 830 get_lenfield(val->length,tmpp,1,asn1_decode_generalstring); 831 val->salt = (krb5_octet*)tmpp; /* SUNW14resync hack */ 832 } else { 833 val->length = KRB5_ETYPE_NO_SALT; 834 val->salt = 0; 835 } 836 if ( tagnum ==2) { 837 krb5_octet *params ; 838 get_lenfield( val->s2kparams.length, params, 839 2, asn1_decode_octetstring); 840 val->s2kparams.data = ( char *) params; 841 } else { 842 val->s2kparams.data = NULL; 843 val->s2kparams.length = 0; 844 } 845 end_structure(); 846 val->magic = KV5M_ETYPE_INFO_ENTRY; 847 } 848 cleanup(); 849 } 850 851 static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val ) 852 { 853 setup(); 854 { begin_structure(); 855 get_field(val->etype,0,asn1_decode_enctype); 856 if (tagnum == 1) { 857 get_lenfield(val->length,val->salt,1,asn1_decode_octetstring); 858 } else { 859 val->length = KRB5_ETYPE_NO_SALT; 860 val->salt = 0; 861 } 862 if ( tagnum ==2) { 863 krb5_octet *params ; 864 get_lenfield( val->s2kparams.length, params, 865 2, asn1_decode_octetstring); 866 val->s2kparams.data = ( char *) params; 867 } else { 868 val->s2kparams.data = NULL; 869 val->s2kparams.length = 0; 870 } 871 end_structure(); 872 val->magic = KV5M_ETYPE_INFO_ENTRY; 873 } 874 cleanup(); 875 } 876 877 878 static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val ) 879 { 880 setup(); 881 { begin_structure(); 882 get_field(val->etype,0,asn1_decode_enctype); 883 if (tagnum == 1) { 884 get_lenfield(val->length,val->salt,1,asn1_decode_octetstring); 885 } else { 886 val->length = KRB5_ETYPE_NO_SALT; 887 val->salt = 0; 888 } 889 val->s2kparams.data = NULL; 890 val->s2kparams.length = 0; 891 892 end_structure(); 893 val->magic = KV5M_ETYPE_INFO_ENTRY; 894 } 895 cleanup(); 896 } 897 898 asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val ) 899 { 900 decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry); 901 } 902 903 asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val , 904 krb5_boolean v1_3_behavior) 905 { 906 if (v1_3_behavior) { 907 decode_array_body(krb5_etype_info_entry, 908 asn1_decode_etype_info2_entry_1_3); 909 } else { 910 decode_array_body(krb5_etype_info_entry, 911 asn1_decode_etype_info2_entry); 912 } 913 } 914 915 asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val) 916 { 917 setup(); 918 { begin_structure(); 919 alloc_field(val->passwd,krb5_data); 920 get_lenfield(val->passwd->length,val->passwd->data, 921 0,asn1_decode_charstring); 922 val->passwd->magic = KV5M_DATA; 923 alloc_field(val->phrase,krb5_data); 924 get_lenfield(val->phrase->length,val->phrase->data, 925 1,asn1_decode_charstring); 926 val->phrase->magic = KV5M_DATA; 927 end_structure(); 928 val->magic = KV5M_PASSWD_PHRASE_ELEMENT; 929 } 930 cleanup(); 931 } 932 933 asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val) 934 { 935 decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence); 936 } 937 938 asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val) 939 { return asn1_decode_krb5_flags(buf,val); } 940 941 #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn) 942 #define opt_cksum(var,tagexpect,decoder)\ 943 if(tagnum == (tagexpect)){\ 944 get_field_body(var,decoder); }\ 945 else var.length = 0 946 947 asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val) 948 { 949 setup(); 950 { begin_structure(); 951 get_field(val->sam_type,0,asn1_decode_int32); 952 get_field(val->sam_flags,1,asn1_decode_sam_flags); 953 opt_string(val->sam_type_name,2,asn1_decode_charstring); 954 opt_string(val->sam_track_id,3,asn1_decode_charstring); 955 opt_string(val->sam_challenge_label,4,asn1_decode_charstring); 956 opt_string(val->sam_challenge,5,asn1_decode_charstring); 957 opt_string(val->sam_response_prompt,6,asn1_decode_charstring); 958 opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring); 959 opt_field(val->sam_nonce,8,asn1_decode_int32,0); 960 opt_cksum(val->sam_cksum,9,asn1_decode_checksum); 961 end_structure(); 962 val->magic = KV5M_SAM_CHALLENGE; 963 } 964 cleanup(); 965 } 966 asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val) 967 { 968 setup(); 969 { char *save, *end; 970 size_t alloclen; 971 begin_structure(); 972 if (tagnum != 0) return ASN1_MISSING_FIELD; 973 if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) 974 return ASN1_BAD_ID; 975 save = subbuf.next; 976 { sequence_of_no_tagvars(&subbuf); 977 unused_var(size); 978 end_sequence_of_no_tagvars(&subbuf); 979 } 980 end = subbuf.next; 981 alloclen = end - save; 982 if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL) 983 return ENOMEM; 984 val->sam_challenge_2_body.length = alloclen; 985 memcpy(val->sam_challenge_2_body.data, save, alloclen); 986 next_tag(); 987 get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum); 988 end_structure(); 989 } 990 cleanup(); 991 } 992 asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val) 993 { 994 setup(); 995 { begin_structure(); 996 get_field(val->sam_type,0,asn1_decode_int32); 997 get_field(val->sam_flags,1,asn1_decode_sam_flags); 998 opt_string(val->sam_type_name,2,asn1_decode_charstring); 999 opt_string(val->sam_track_id,3,asn1_decode_charstring); 1000 opt_string(val->sam_challenge_label,4,asn1_decode_charstring); 1001 opt_string(val->sam_challenge,5,asn1_decode_charstring); 1002 opt_string(val->sam_response_prompt,6,asn1_decode_charstring); 1003 opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring); 1004 get_field(val->sam_nonce,8,asn1_decode_int32); 1005 get_field(val->sam_etype, 9, asn1_decode_int32); 1006 end_structure(); 1007 val->magic = KV5M_SAM_CHALLENGE; 1008 } 1009 cleanup(); 1010 } 1011 asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val) 1012 { 1013 setup(); 1014 { begin_structure(); 1015 /* alloc_field(val->sam_key,krb5_keyblock); */ 1016 get_field(val->sam_key,0,asn1_decode_encryption_key); 1017 end_structure(); 1018 val->magic = KV5M_SAM_KEY; 1019 } 1020 cleanup(); 1021 } 1022 1023 asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val) 1024 { 1025 setup(); 1026 { begin_structure(); 1027 opt_field(val->sam_nonce,0,asn1_decode_int32,0); 1028 opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0); 1029 opt_field(val->sam_usec,2,asn1_decode_int32,0); 1030 opt_string(val->sam_sad,3,asn1_decode_charstring); 1031 end_structure(); 1032 val->magic = KV5M_ENC_SAM_RESPONSE_ENC; 1033 } 1034 cleanup(); 1035 } 1036 1037 asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val) 1038 { 1039 setup(); 1040 { begin_structure(); 1041 get_field(val->sam_nonce,0,asn1_decode_int32); 1042 opt_string(val->sam_sad,1,asn1_decode_charstring); 1043 end_structure(); 1044 val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2; 1045 } 1046 cleanup(); 1047 } 1048 1049 #define opt_encfield(fld,tag,fn) \ 1050 if(tagnum == tag){ \ 1051 get_field(fld,tag,fn); } \ 1052 else{\ 1053 fld.magic = 0;\ 1054 fld.enctype = 0;\ 1055 fld.kvno = 0;\ 1056 fld.ciphertext.data = NULL;\ 1057 fld.ciphertext.length = 0;\ 1058 } 1059 1060 asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val) 1061 { 1062 setup(); 1063 { begin_structure(); 1064 get_field(val->sam_type,0,asn1_decode_int32); 1065 get_field(val->sam_flags,1,asn1_decode_sam_flags); 1066 opt_string(val->sam_track_id,2,asn1_decode_charstring); 1067 opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data); 1068 get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data); 1069 opt_field(val->sam_nonce,5,asn1_decode_int32,0); 1070 opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0); 1071 end_structure(); 1072 val->magic = KV5M_SAM_RESPONSE; 1073 } 1074 cleanup(); 1075 } 1076 1077 asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val) 1078 { 1079 setup(); 1080 { begin_structure(); 1081 get_field(val->sam_type,0,asn1_decode_int32); 1082 get_field(val->sam_flags,1,asn1_decode_sam_flags); 1083 opt_string(val->sam_track_id,2,asn1_decode_charstring); 1084 get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data); 1085 get_field(val->sam_nonce,4,asn1_decode_int32); 1086 end_structure(); 1087 val->magic = KV5M_SAM_RESPONSE; 1088 } 1089 cleanup(); 1090 } 1091 1092 1093 asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val) 1094 { 1095 setup(); 1096 { begin_structure(); 1097 get_field(val->sam_key,0,asn1_decode_encryption_key); 1098 get_field(val->sam_flags,1,asn1_decode_sam_flags); 1099 get_field(val->stime,2,asn1_decode_kerberos_time); 1100 get_field(val->susec,3,asn1_decode_int32); 1101 alloc_field(val->client,krb5_principal_data); 1102 get_field(val->client,4,asn1_decode_realm); 1103 get_field(val->client,5,asn1_decode_principal_name); 1104 opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */ 1105 end_structure(); 1106 val->magic = KV5M_PREDICTED_SAM_RESPONSE; 1107 } 1108 cleanup(); 1109 } 1110