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