1 #pragma ident "%Z%%M% %I% %E% SMI" 2 3 /* 4 * src/lib/krb5/asn.1/asn1_k_encode.c 5 * 6 * Copyright 1994 by the Massachusetts Institute of Technology. 7 * All Rights Reserved. 8 * 9 * Export of this software from the United States of America may 10 * require a specific license from the United States Government. 11 * It is the responsibility of any person or organization contemplating 12 * export to obtain such a license before exporting. 13 * 14 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 15 * distribute this software and its documentation for any purpose and 16 * without fee is hereby granted, provided that the above copyright 17 * notice appear in all copies and that both that copyright notice and 18 * this permission notice appear in supporting documentation, and that 19 * the name of M.I.T. not be used in advertising or publicity pertaining 20 * to distribution of the software without specific, written prior 21 * permission. Furthermore if you modify this software you must label 22 * your software as modified software and not distribute it in such a 23 * fashion that it might be confused with the original M.I.T. software. 24 * M.I.T. makes no representations about the suitability of 25 * this software for any purpose. It is provided "as is" without express 26 * or implied warranty. 27 */ 28 29 #include "asn1_k_encode.h" 30 #include "asn1_make.h" 31 #include "asn1_encode.h" 32 #include <assert.h> 33 34 /**** asn1 macros ****/ 35 #if 0 36 How to write an asn1 encoder function using these macros: 37 38 asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, 39 const krb5_type *val, 40 int *retlen) 41 { 42 asn1_setup(); 43 44 asn1_addfield(val->last_field, n, asn1_type); 45 asn1_addfield(rep->next_to_last_field, n-1, asn1_type); 46 ... 47 48 /* for OPTIONAL fields */ 49 if(rep->field_i == should_not_be_omitted) 50 asn1_addfield(rep->field_i, i, asn1_type); 51 52 /* for string fields (these encoders take an additional argument, 53 the length of the string) */ 54 addlenfield(rep->field_length, rep->field, i-1, asn1_type); 55 56 /* if you really have to do things yourself... */ 57 retval = asn1_encode_asn1_type(buf,rep->field,&length); 58 if(retval) return retval; 59 sum += length; 60 retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length, 61 &length); 62 if(retval) return retval; 63 sum += length; 64 65 ... 66 asn1_addfield(rep->second_field, 1, asn1_type); 67 asn1_addfield(rep->first_field, 0, asn1_type); 68 asn1_makeseq(); 69 70 asn1_cleanup(); 71 } 72 #endif 73 74 /* setup() -- create and initialize bookkeeping variables 75 retval: stores error codes returned from subroutines 76 length: length of the most-recently produced encoding 77 sum: cumulative length of the entire encoding */ 78 #define asn1_setup()\ 79 asn1_error_code retval;\ 80 unsigned int length, sum=0 81 82 /* asn1_addfield -- add a field, or component, to the encoding */ 83 #define asn1_addfield(value,tag,encoder)\ 84 { retval = encoder(buf,value,&length);\ 85 if(retval){\ 86 asn1buf_destroy(&buf);\ 87 return retval; }\ 88 sum += length;\ 89 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ 90 if(retval){\ 91 asn1buf_destroy(&buf);\ 92 return retval; }\ 93 sum += length; } 94 95 /* asn1_addlenfield -- add a field whose length must be separately specified */ 96 #define asn1_addlenfield(len,value,tag,encoder)\ 97 { retval = encoder(buf,len,value,&length);\ 98 if(retval){\ 99 asn1buf_destroy(&buf);\ 100 return retval; }\ 101 sum += length;\ 102 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\ 103 if(retval){\ 104 asn1buf_destroy(&buf);\ 105 return retval; }\ 106 sum += length; } 107 108 /* form a sequence (by adding a sequence header to the current encoding) */ 109 #define asn1_makeseq()\ 110 retval = asn1_make_sequence(buf,sum,&length);\ 111 if(retval){\ 112 asn1buf_destroy(&buf);\ 113 return retval; }\ 114 sum += length 115 116 /* add an APPLICATION class tag to the current encoding */ 117 #define asn1_apptag(num)\ 118 retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\ 119 if(retval){\ 120 asn1buf_destroy(&buf);\ 121 return retval; }\ 122 sum += length 123 124 /* produce the final output and clean up the workspace */ 125 #define asn1_cleanup()\ 126 *retlen = sum;\ 127 return 0 128 129 asn1_error_code asn1_encode_ui_4(asn1buf *buf, const krb5_ui_4 val, unsigned int *retlen) 130 { 131 return asn1_encode_unsigned_integer(buf,val,retlen); 132 } 133 134 135 asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val, unsigned int *retlen) 136 { 137 if (val == NULL || 138 (val->realm.length && val->realm.data == NULL)) 139 return ASN1_MISSING_FIELD; 140 return asn1_encode_generalstring(buf,val->realm.length,val->realm.data, 141 retlen); 142 } 143 144 asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen) 145 { 146 asn1_setup(); 147 int n; 148 149 if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD; 150 151 for(n = (int) ((val->length)-1); n >= 0; n--){ 152 if (val->data[n].length && 153 val->data[n].data == NULL) 154 return ASN1_MISSING_FIELD; 155 retval = asn1_encode_generalstring(buf, 156 (val->data)[n].length, 157 (val->data)[n].data, 158 &length); 159 if(retval) return retval; 160 sum += length; 161 } 162 asn1_makeseq(); 163 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length); 164 if(retval) return retval; 165 sum += length; 166 167 asn1_addfield(val->type,0,asn1_encode_integer); 168 169 asn1_makeseq(); 170 171 asn1_cleanup(); 172 } 173 174 asn1_error_code asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen) 175 { 176 return asn1_encode_generaltime(buf,val,retlen); 177 } 178 179 asn1_error_code asn1_encode_host_address(asn1buf *buf, const krb5_address *val, unsigned int *retlen) 180 { 181 asn1_setup(); 182 183 if (val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD; 184 185 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); 186 asn1_addfield(val->addrtype,0,asn1_encode_integer); 187 asn1_makeseq(); 188 189 asn1_cleanup(); 190 } 191 192 asn1_error_code asn1_encode_host_addresses(asn1buf *buf, const krb5_address **val, unsigned int *retlen) 193 { 194 asn1_setup(); 195 int i; 196 197 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; 198 199 for(i=0; val[i] != NULL; i++); /* go to end of array */ 200 for(i--; i>=0; i--){ 201 retval = asn1_encode_host_address(buf,val[i],&length); 202 if(retval) return retval; 203 sum += length; 204 } 205 asn1_makeseq(); 206 207 asn1_cleanup(); 208 } 209 210 asn1_error_code asn1_encode_encrypted_data(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen) 211 { 212 asn1_setup(); 213 214 if(val == NULL || 215 (val->ciphertext.length && val->ciphertext.data == NULL)) 216 return ASN1_MISSING_FIELD; 217 218 asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring); 219 /* krb5_kvno should be int */ 220 if(val->kvno) 221 asn1_addfield((int) val->kvno,1,asn1_encode_integer); 222 asn1_addfield(val->enctype,0,asn1_encode_integer); 223 224 asn1_makeseq(); 225 226 asn1_cleanup(); 227 } 228 229 asn1_error_code asn1_encode_krb5_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) 230 { 231 asn1_setup(); 232 krb5_flags valcopy = val; 233 int i; 234 235 for(i=0; i<4; i++){ 236 retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF)); 237 if(retval) return retval; 238 valcopy >>= 8; 239 } 240 retval = asn1buf_insert_octet(buf,0); /* 0 padding bits */ 241 if(retval) return retval; 242 sum = 5; 243 244 retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum, 245 &length); 246 if(retval) return retval; 247 sum += length; 248 249 *retlen = sum; 250 return 0; 251 } 252 253 asn1_error_code asn1_encode_ap_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) 254 { 255 return asn1_encode_krb5_flags(buf,val,retlen); 256 } 257 258 asn1_error_code asn1_encode_ticket_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) 259 { 260 return asn1_encode_krb5_flags(buf,val,retlen); 261 } 262 263 asn1_error_code asn1_encode_kdc_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) 264 { 265 return asn1_encode_krb5_flags(buf,val,retlen); 266 } 267 268 asn1_error_code asn1_encode_authorization_data(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen) 269 { 270 asn1_setup(); 271 int i; 272 273 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; 274 275 for(i=0; val[i] != NULL; i++); /* get to the end of the array */ 276 for(i--; i>=0; i--){ 277 retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length); 278 if(retval) return retval; 279 sum += length; 280 } 281 asn1_makeseq(); 282 283 asn1_cleanup(); 284 } 285 286 asn1_error_code asn1_encode_krb5_authdata_elt(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen) 287 { 288 asn1_setup(); 289 290 if (val == NULL || 291 (val->length && val->contents == NULL)) 292 return ASN1_MISSING_FIELD; 293 294 /* ad-data[1] OCTET STRING */ 295 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); 296 /* ad-type[0] INTEGER */ 297 asn1_addfield(val->ad_type,0,asn1_encode_integer); 298 /* SEQUENCE */ 299 asn1_makeseq(); 300 301 asn1_cleanup(); 302 } 303 304 asn1_error_code asn1_encode_kdc_rep(int msg_type, asn1buf *buf, const krb5_kdc_rep *val, unsigned int *retlen) 305 { 306 asn1_setup(); 307 308 if(val == NULL) return ASN1_MISSING_FIELD; 309 310 asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data); 311 asn1_addfield(val->ticket,5,asn1_encode_ticket); 312 asn1_addfield(val->client,4,asn1_encode_principal_name); 313 asn1_addfield(val->client,3,asn1_encode_realm); 314 if(val->padata != NULL && val->padata[0] != NULL) 315 asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data); 316 if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP) 317 return KRB5_BADMSGTYPE; 318 asn1_addfield(msg_type,1,asn1_encode_integer); 319 asn1_addfield(KVNO,0,asn1_encode_integer); 320 asn1_makeseq(); 321 322 asn1_cleanup(); 323 } 324 325 asn1_error_code asn1_encode_enc_kdc_rep_part(asn1buf *buf, const krb5_enc_kdc_rep_part *val, unsigned int *retlen) 326 { 327 asn1_setup(); 328 329 if(val == NULL) return ASN1_MISSING_FIELD; 330 331 /* caddr[11] HostAddresses OPTIONAL */ 332 if(val->caddrs != NULL && val->caddrs[0] != NULL) 333 asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses); 334 335 /* sname[10] PrincipalName */ 336 asn1_addfield(val->server,10,asn1_encode_principal_name); 337 338 /* srealm[9] Realm */ 339 asn1_addfield(val->server,9,asn1_encode_realm); 340 341 /* renew-till[8] KerberosTime OPTIONAL */ 342 if(val->flags & TKT_FLG_RENEWABLE) 343 asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time); 344 345 /* endtime[7] KerberosTime */ 346 asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time); 347 348 /* starttime[6] KerberosTime OPTIONAL */ 349 if(val->times.starttime) 350 asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time); 351 352 /* authtime[5] KerberosTime */ 353 asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time); 354 355 /* flags[4] TicketFlags */ 356 asn1_addfield(val->flags,4,asn1_encode_ticket_flags); 357 358 /* key-expiration[3] KerberosTime OPTIONAL */ 359 if(val->key_exp) 360 asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time); 361 362 /* nonce[2] INTEGER */ 363 asn1_addfield(val->nonce,2,asn1_encode_integer); 364 365 /* last-req[1] LastReq */ 366 asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req); 367 368 /* key[0] EncryptionKey */ 369 asn1_addfield(val->session,0,asn1_encode_encryption_key); 370 371 /* EncKDCRepPart ::= SEQUENCE */ 372 asn1_makeseq(); 373 374 asn1_cleanup(); 375 } 376 377 asn1_error_code asn1_encode_sequence_of_checksum(asn1buf *buf, const krb5_checksum ** val, unsigned int *retlen) 378 { 379 asn1_setup(); 380 int i; 381 382 if(val == NULL) return ASN1_MISSING_FIELD; 383 384 for (i=0; val[i] != NULL; i++); 385 for (i--; i>=0; i--){ 386 retval = asn1_encode_checksum(buf,val[i],&length); 387 if(retval) return retval; 388 sum += length; 389 } 390 asn1_makeseq(); 391 392 asn1_cleanup(); 393 } 394 395 asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *rep, unsigned int *retlen) 396 { 397 asn1_setup(); 398 399 if(rep == NULL) return ASN1_MISSING_FIELD; 400 401 /* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */ 402 if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL) 403 asn1_addfield((const krb5_ticket**)rep->second_ticket, 404 11,asn1_encode_sequence_of_ticket); 405 406 /* enc-authorization-data[10] EncryptedData OPTIONAL, */ 407 /* -- Encrypted AuthorizationData encoding */ 408 if(rep->authorization_data.ciphertext.data != NULL) 409 asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data); 410 411 /* addresses[9] HostAddresses OPTIONAL, */ 412 if(rep->addresses != NULL && rep->addresses[0] != NULL) 413 asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses); 414 415 /* etype[8] SEQUENCE OF INTEGER, -- EncryptionType, */ 416 /* -- in preference order */ 417 asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype); 418 419 /* nonce[7] INTEGER, */ 420 asn1_addfield(rep->nonce,7,asn1_encode_integer); 421 422 /* rtime[6] KerberosTime OPTIONAL, */ 423 if(rep->rtime) 424 asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time); 425 426 /* till[5] KerberosTime, */ 427 asn1_addfield(rep->till,5,asn1_encode_kerberos_time); 428 429 /* from[4] KerberosTime OPTIONAL, */ 430 if(rep->from) 431 asn1_addfield(rep->from,4,asn1_encode_kerberos_time); 432 433 /* sname[3] PrincipalName OPTIONAL, */ 434 if(rep->server != NULL) 435 asn1_addfield(rep->server,3,asn1_encode_principal_name); 436 437 /* realm[2] Realm, -- Server's realm */ 438 /* -- Also client's in AS-REQ */ 439 if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){ 440 if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){ 441 asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm) 442 } else return ASN1_MISSING_FIELD; 443 }else if(rep->server != NULL){ 444 asn1_addfield(rep->server,2,asn1_encode_realm); 445 }else return ASN1_MISSING_FIELD; 446 447 /* cname[1] PrincipalName OPTIONAL, */ 448 /* -- Used only in AS-REQ */ 449 if(rep->client != NULL) 450 asn1_addfield(rep->client,1,asn1_encode_principal_name); 451 452 /* kdc-options[0] KDCOptions, */ 453 asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options); 454 455 /* KDC-REQ-BODY ::= SEQUENCE */ 456 asn1_makeseq(); 457 458 asn1_cleanup(); 459 } 460 461 asn1_error_code asn1_encode_encryption_key(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen) 462 { 463 asn1_setup(); 464 465 if (val == NULL || 466 (val->length && val->contents == NULL)) 467 return ASN1_MISSING_FIELD; 468 469 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); 470 asn1_addfield(val->enctype,0,asn1_encode_integer); 471 asn1_makeseq(); 472 473 asn1_cleanup(); 474 } 475 476 asn1_error_code asn1_encode_checksum(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen) 477 { 478 asn1_setup(); 479 480 if (val == NULL || 481 (val->length && val->contents == NULL)) 482 return ASN1_MISSING_FIELD; 483 484 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); 485 asn1_addfield(val->checksum_type,0,asn1_encode_integer); 486 asn1_makeseq(); 487 488 asn1_cleanup(); 489 } 490 491 asn1_error_code asn1_encode_transited_encoding(asn1buf *buf, const krb5_transited *val, unsigned int *retlen) 492 { 493 asn1_setup(); 494 495 if(val == NULL || 496 (val->tr_contents.length != 0 && val->tr_contents.data == NULL)) 497 return ASN1_MISSING_FIELD; 498 499 asn1_addlenfield(val->tr_contents.length,val->tr_contents.data, 500 1,asn1_encode_charstring); 501 asn1_addfield(val->tr_type,0,asn1_encode_integer); 502 asn1_makeseq(); 503 504 asn1_cleanup(); 505 } 506 507 asn1_error_code asn1_encode_last_req(asn1buf *buf, const krb5_last_req_entry **val, unsigned int *retlen) 508 { 509 asn1_setup(); 510 int i; 511 512 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; 513 514 for(i=0; val[i] != NULL; i++); /* go to end of array */ 515 for(i--; i>=0; i--){ 516 retval = asn1_encode_last_req_entry(buf,val[i],&length); 517 if(retval) return retval; 518 sum += length; 519 } 520 asn1_makeseq(); 521 522 asn1_cleanup(); 523 } 524 525 asn1_error_code asn1_encode_last_req_entry(asn1buf *buf, const krb5_last_req_entry *val, unsigned int *retlen) 526 { 527 asn1_setup(); 528 529 if(val == NULL) return ASN1_MISSING_FIELD; 530 531 asn1_addfield(val->value,1,asn1_encode_kerberos_time); 532 asn1_addfield(val->lr_type,0,asn1_encode_integer); 533 asn1_makeseq(); 534 535 asn1_cleanup(); 536 } 537 538 asn1_error_code asn1_encode_sequence_of_pa_data(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen) 539 { 540 asn1_setup(); 541 int i; 542 543 if (val == NULL) return ASN1_MISSING_FIELD; 544 545 for(i=0; val[i] != NULL; i++); 546 for(i--; i>=0; i--){ 547 retval = asn1_encode_pa_data(buf,val[i],&length); 548 if(retval) return retval; 549 sum += length; 550 } 551 asn1_makeseq(); 552 553 asn1_cleanup(); 554 } 555 556 asn1_error_code asn1_encode_pa_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen) 557 { 558 asn1_setup(); 559 560 if(val == NULL || (val->length != 0 && val->contents == NULL)) 561 return ASN1_MISSING_FIELD; 562 563 asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring); 564 asn1_addfield(val->pa_type,1,asn1_encode_integer); 565 asn1_makeseq(); 566 567 asn1_cleanup(); 568 } 569 570 asn1_error_code asn1_encode_sequence_of_ticket(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen) 571 { 572 asn1_setup(); 573 int i; 574 575 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; 576 577 for(i=0; val[i] != NULL; i++); 578 for(i--; i>=0; i--){ 579 retval = asn1_encode_ticket(buf,val[i],&length); 580 if(retval) return retval; 581 sum += length; 582 } 583 asn1_makeseq(); 584 585 asn1_cleanup(); 586 } 587 588 asn1_error_code asn1_encode_ticket(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen) 589 { 590 asn1_setup(); 591 592 if(val == NULL) return ASN1_MISSING_FIELD; 593 594 asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data); 595 asn1_addfield(val->server,2,asn1_encode_principal_name); 596 asn1_addfield(val->server,1,asn1_encode_realm); 597 asn1_addfield(KVNO,0,asn1_encode_integer); 598 asn1_makeseq(); 599 asn1_apptag(1); 600 601 asn1_cleanup(); 602 } 603 604 asn1_error_code asn1_encode_sequence_of_enctype(asn1buf *buf, const int len, const krb5_enctype *val, unsigned int *retlen) 605 { 606 asn1_setup(); 607 int i; 608 609 if(val == NULL) return ASN1_MISSING_FIELD; 610 611 for(i=len-1; i>=0; i--){ 612 retval = asn1_encode_integer(buf,val[i],&length); 613 if(retval) return retval; 614 sum += length; 615 } 616 asn1_makeseq(); 617 618 asn1_cleanup(); 619 } 620 621 asn1_error_code asn1_encode_kdc_req(int msg_type, asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen) 622 { 623 asn1_setup(); 624 625 if(val == NULL) return ASN1_MISSING_FIELD; 626 627 asn1_addfield(val,4,asn1_encode_kdc_req_body); 628 if(val->padata != NULL && val->padata[0] != NULL) 629 asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data); 630 if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ) 631 return KRB5_BADMSGTYPE; 632 asn1_addfield(msg_type,2,asn1_encode_integer); 633 asn1_addfield(KVNO,1,asn1_encode_integer); 634 asn1_makeseq(); 635 636 asn1_cleanup(); 637 } 638 639 asn1_error_code asn1_encode_krb_safe_body(asn1buf *buf, const krb5_safe *val, unsigned int *retlen) 640 { 641 asn1_setup(); 642 643 if(val == NULL) return ASN1_MISSING_FIELD; 644 645 if(val->r_address != NULL) 646 asn1_addfield(val->r_address,5,asn1_encode_host_address); 647 asn1_addfield(val->s_address,4,asn1_encode_host_address); 648 if(val->seq_number) 649 asn1_addfield(val->seq_number,3,asn1_encode_unsigned_integer); 650 if(val->timestamp){ 651 asn1_addfield(val->usec,2,asn1_encode_integer); 652 asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time); 653 } 654 if (val->user_data.length && val->user_data.data == NULL) 655 return ASN1_MISSING_FIELD; 656 asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring) 657 ; 658 659 asn1_makeseq(); 660 asn1_cleanup(); 661 } 662 663 asn1_error_code asn1_encode_sequence_of_krb_cred_info(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen) 664 { 665 asn1_setup(); 666 int i; 667 668 if(val == NULL) return ASN1_MISSING_FIELD; 669 670 for(i=0; val[i] != NULL; i++); 671 for(i--; i>=0; i--){ 672 retval = asn1_encode_krb_cred_info(buf,val[i],&length); 673 if(retval) return retval; 674 sum += length; 675 } 676 asn1_makeseq(); 677 678 asn1_cleanup(); 679 } 680 681 asn1_error_code asn1_encode_krb_cred_info(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen) 682 { 683 asn1_setup(); 684 685 if(val == NULL) return ASN1_MISSING_FIELD; 686 687 if(val->caddrs != NULL && val->caddrs[0] != NULL) 688 asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses); 689 if(val->server != NULL){ 690 asn1_addfield(val->server,9,asn1_encode_principal_name); 691 asn1_addfield(val->server,8,asn1_encode_realm); 692 } 693 if(val->times.renew_till) 694 asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time); 695 if(val->times.endtime) 696 asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time); 697 if(val->times.starttime) 698 asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time); 699 if(val->times.authtime) 700 asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time); 701 if(val->flags) 702 asn1_addfield(val->flags,3,asn1_encode_ticket_flags); 703 if(val->client != NULL){ 704 asn1_addfield(val->client,2,asn1_encode_principal_name); 705 asn1_addfield(val->client,1,asn1_encode_realm); 706 } 707 asn1_addfield(val->session,0,asn1_encode_encryption_key); 708 709 asn1_makeseq(); 710 711 asn1_cleanup(); 712 } 713 714 asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info_entry *val, 715 unsigned int *retlen, int etype_info2) 716 { 717 asn1_setup(); 718 719 assert(val->s2kparams.data == NULL || etype_info2); 720 if(val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT && 721 val->salt == NULL)) 722 return ASN1_MISSING_FIELD; 723 if(val->s2kparams.data != NULL) 724 asn1_addlenfield(val->s2kparams.length, (const uchar_t *)val->s2kparams.data, 2, 725 asn1_encode_octetstring); 726 if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT){ 727 if (etype_info2) 728 asn1_addlenfield(val->length, (const char *)val->salt,1, 729 asn1_encode_generalstring) 730 else asn1_addlenfield(val->length,val->salt,1, 731 asn1_encode_octetstring); 732 } 733 asn1_addfield(val->etype,0,asn1_encode_integer); 734 asn1_makeseq(); 735 736 asn1_cleanup(); 737 } 738 739 asn1_error_code asn1_encode_etype_info(asn1buf *buf, const krb5_etype_info_entry **val, 740 unsigned int *retlen, int etype_info2) 741 { 742 asn1_setup(); 743 int i; 744 745 if (val == NULL) return ASN1_MISSING_FIELD; 746 747 for(i=0; val[i] != NULL; i++); /* get to the end of the array */ 748 for(i--; i>=0; i--){ 749 retval = asn1_encode_etype_info_entry(buf,val[i],&length, etype_info2); 750 if(retval) return retval; 751 sum += length; 752 } 753 asn1_makeseq(); 754 asn1_cleanup(); 755 } 756 757 asn1_error_code asn1_encode_sequence_of_passwdsequence(asn1buf *buf, const passwd_phrase_element **val, unsigned int *retlen) 758 { 759 asn1_setup(); 760 int i; 761 762 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; 763 764 for(i=0; val[i] != NULL; i++); /* get to the end of the array */ 765 for(i--; i>=0; i--){ 766 retval = asn1_encode_passwdsequence(buf,val[i],&length); 767 if(retval) return retval; 768 sum += length; 769 } 770 asn1_makeseq(); 771 asn1_cleanup(); 772 } 773 774 asn1_error_code asn1_encode_passwdsequence(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen) 775 { 776 asn1_setup(); 777 asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring); 778 asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring); 779 asn1_makeseq(); 780 asn1_cleanup(); 781 } 782 783 asn1_error_code asn1_encode_sam_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) 784 { 785 return asn1_encode_krb5_flags(buf,val,retlen); 786 } 787 788 #define add_optstring(val,n,fn) \ 789 if ((val).length > 0) {asn1_addlenfield((val).length,(val).data,n,fn);} 790 791 asn1_error_code asn1_encode_sam_challenge(asn1buf *buf, const krb5_sam_challenge *val, unsigned int *retlen) 792 { 793 asn1_setup(); 794 /* possibly wrong */ 795 if (val->sam_cksum.length) 796 asn1_addfield(&(val->sam_cksum),9,asn1_encode_checksum); 797 798 if (val->sam_nonce) 799 asn1_addfield(val->sam_nonce,8,asn1_encode_integer); 800 801 add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); 802 add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); 803 add_optstring(val->sam_challenge,5,asn1_encode_charstring); 804 add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); 805 add_optstring(val->sam_track_id,3,asn1_encode_charstring); 806 add_optstring(val->sam_type_name,2,asn1_encode_charstring); 807 808 asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); 809 asn1_addfield(val->sam_type,0,asn1_encode_integer); 810 811 asn1_makeseq(); 812 asn1_cleanup(); 813 } 814 815 asn1_error_code asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, unsigned int *retlen) 816 { 817 asn1_setup(); 818 if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0])) 819 return ASN1_MISSING_FIELD; 820 821 asn1_addfield((const krb5_checksum **) val->sam_cksum, 1, asn1_encode_sequence_of_checksum); 822 retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length, 823 (unsigned char *)val->sam_challenge_2_body.data); 824 if(retval){ 825 asn1buf_destroy(&buf); 826 return retval; 827 } 828 sum += val->sam_challenge_2_body.length; 829 retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, 830 val->sam_challenge_2_body.length, &length); 831 if(retval) { 832 asn1buf_destroy(&buf); 833 return retval; 834 } 835 sum += length; 836 837 asn1_makeseq(); 838 asn1_cleanup(); 839 } 840 841 asn1_error_code asn1_encode_sam_challenge_2_body(asn1buf *buf, const krb5_sam_challenge_2_body *val, unsigned int *retlen) 842 { 843 asn1_setup(); 844 845 asn1_addfield(val->sam_etype, 9, asn1_encode_integer); 846 asn1_addfield(val->sam_nonce,8,asn1_encode_integer); 847 add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); 848 add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); 849 add_optstring(val->sam_challenge,5,asn1_encode_charstring); 850 add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); 851 add_optstring(val->sam_track_id,3,asn1_encode_charstring); 852 add_optstring(val->sam_type_name,2,asn1_encode_charstring); 853 854 asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); 855 asn1_addfield(val->sam_type,0,asn1_encode_integer); 856 857 asn1_makeseq(); 858 asn1_cleanup(); 859 } 860 861 asn1_error_code asn1_encode_sam_key(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen) 862 { 863 asn1_setup(); 864 asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); 865 866 asn1_makeseq(); 867 868 asn1_cleanup(); 869 } 870 871 872 asn1_error_code asn1_encode_enc_sam_response_enc(asn1buf *buf, const krb5_enc_sam_response_enc *val, unsigned int *retlen) 873 { 874 asn1_setup(); 875 add_optstring(val->sam_sad,3,asn1_encode_charstring); 876 asn1_addfield(val->sam_usec,2,asn1_encode_integer); 877 asn1_addfield(val->sam_timestamp,1,asn1_encode_kerberos_time); 878 asn1_addfield(val->sam_nonce,0,asn1_encode_integer); 879 880 asn1_makeseq(); 881 882 asn1_cleanup(); 883 } 884 885 asn1_error_code asn1_encode_enc_sam_response_enc_2(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val, unsigned int *retlen) 886 { 887 asn1_setup(); 888 add_optstring(val->sam_sad,1,asn1_encode_charstring); 889 asn1_addfield(val->sam_nonce,0,asn1_encode_integer); 890 891 asn1_makeseq(); 892 893 asn1_cleanup(); 894 } 895 896 asn1_error_code asn1_encode_sam_response(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen) 897 { 898 asn1_setup(); 899 900 if (val->sam_patimestamp) 901 asn1_addfield(val->sam_patimestamp,6,asn1_encode_kerberos_time); 902 if (val->sam_nonce) 903 asn1_addfield(val->sam_nonce,5,asn1_encode_integer); 904 asn1_addfield(&(val->sam_enc_nonce_or_ts),4,asn1_encode_encrypted_data); 905 if (val->sam_enc_key.ciphertext.length) 906 asn1_addfield(&(val->sam_enc_key),3,asn1_encode_encrypted_data); 907 add_optstring(val->sam_track_id,2,asn1_encode_charstring); 908 asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); 909 asn1_addfield(val->sam_type,0,asn1_encode_integer); 910 911 asn1_makeseq(); 912 913 asn1_cleanup(); 914 } 915 916 asn1_error_code asn1_encode_sam_response_2(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen) 917 { 918 asn1_setup(); 919 920 asn1_addfield(val->sam_nonce,4,asn1_encode_integer); 921 asn1_addfield(&(val->sam_enc_nonce_or_sad),3,asn1_encode_encrypted_data); 922 add_optstring(val->sam_track_id,2,asn1_encode_charstring); 923 asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); 924 asn1_addfield(val->sam_type,0,asn1_encode_integer); 925 926 asn1_makeseq(); 927 928 asn1_cleanup(); 929 } 930 931 asn1_error_code asn1_encode_predicted_sam_response(asn1buf *buf, const krb5_predicted_sam_response *val, unsigned int *retlen) 932 { 933 asn1_setup(); 934 935 add_optstring(val->msd,6,asn1_encode_charstring); 936 asn1_addfield(val->client,5,asn1_encode_principal_name); 937 asn1_addfield(val->client,4,asn1_encode_realm); 938 asn1_addfield(val->susec,3,asn1_encode_integer); 939 asn1_addfield(val->stime,2,asn1_encode_kerberos_time); 940 asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); 941 asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); 942 943 asn1_makeseq(); 944 945 asn1_cleanup(); 946 } 947 948 /* 949 * Do some ugliness to insert a raw pre-encoded KRB-SAFE-BODY. 950 */ 951 asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *body, unsigned int *retlen) 952 { 953 asn1_error_code retval; 954 955 retval = asn1buf_insert_octetstring(buf, body->length, 956 (krb5_octet *)body->data); 957 if (retval){ 958 asn1buf_destroy(&buf); 959 return retval; 960 } 961 *retlen = body->length; 962 return 0; 963 } 964