1*68591Sdab /* 2*68591Sdab * $Source: /mit/krb5/.cvsroot/src/appl/bsd/forward.c,v $ 3*68591Sdab * $Id: forward.c,v 1.4 1993/10/15 16:41:29 tytso Exp $ 4*68591Sdab */ 5*68591Sdab 6*68591Sdab #ifndef lint 7*68591Sdab static char *rcsid_forward_c = 8*68591Sdab "$Id: forward.c,v 1.4 1993/10/15 16:41:29 tytso Exp $"; 9*68591Sdab #endif /* lint */ 10*68591Sdab #define LIBC_SCCS 11*68591Sdab 12*68591Sdab /*- 13*68591Sdab * Copyright (c) 1993 14*68591Sdab * The Regents of the University of California. All rights reserved. 15*68591Sdab * 16*68591Sdab * %sccs.include.redist.c% 17*68591Sdab */ 18*68591Sdab 19*68591Sdab #ifndef lint 20*68591Sdab static char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 03/24/95"; 21*68591Sdab #endif /* not lint */ 22*68591Sdab 23*68591Sdab 24*68591Sdab /* General-purpose forwarding routines. These routines may be put into */ 25*68591Sdab /* libkrb5.a to allow widespread use */ 26*68591Sdab 27*68591Sdab #if defined(KRB5) && defined(FORWARD) 28*68591Sdab #include <stdio.h> 29*68591Sdab #include <pwd.h> 30*68591Sdab #include <netdb.h> 31*68591Sdab 32*68591Sdab #include <krb5/krb5.h> 33*68591Sdab #include <krb5/asn1.h> 34*68591Sdab #include <krb5/crc-32.h> 35*68591Sdab #include <krb5/los-proto.h> 36*68591Sdab #include <krb5/ext-proto.h> 37*68591Sdab 38*68591Sdab #define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */ 39*68591Sdab /* helper function: convert flags to necessary KDC options */ 40*68591Sdab #define flags2options(flags) (flags & KDC_TKT_COMMON_MASK) 41*68591Sdab 42*68591Sdab 43*68591Sdab 44*68591Sdab /* Get a TGT for use at the remote host */ 45*68591Sdab krb5_error_code 46*68591Sdab get_for_creds(etype, sumtype, rhost, client, enc_key, forwardable, outbuf) 47*68591Sdab const krb5_enctype etype; 48*68591Sdab const krb5_cksumtype sumtype; 49*68591Sdab char *rhost; 50*68591Sdab krb5_principal client; 51*68591Sdab krb5_keyblock *enc_key; 52*68591Sdab int forwardable; /* Should forwarded TGT also be forwardable? */ 53*68591Sdab krb5_data *outbuf; 54*68591Sdab { 55*68591Sdab struct hostent *hp; 56*68591Sdab krb5_address **addrs; 57*68591Sdab krb5_error_code retval; 58*68591Sdab krb5_data *scratch; 59*68591Sdab krb5_kdc_rep *dec_rep; 60*68591Sdab krb5_error *err_reply; 61*68591Sdab krb5_response tgsrep; 62*68591Sdab krb5_creds creds, tgt; 63*68591Sdab krb5_ccache cc; 64*68591Sdab krb5_flags kdcoptions; 65*68591Sdab krb5_timestamp now; 66*68591Sdab char *remote_host; 67*68591Sdab char **hrealms; 68*68591Sdab int i; 69*68591Sdab 70*68591Sdab if (!rhost || !(hp = gethostbyname(rhost))) 71*68591Sdab return KRB5_ERR_BAD_HOSTNAME; 72*68591Sdab 73*68591Sdab remote_host = (char *) malloc(strlen(hp->h_name)+1); 74*68591Sdab if (!remote_host) 75*68591Sdab return ENOMEM; 76*68591Sdab strcpy(remote_host, hp->h_name); 77*68591Sdab 78*68591Sdab if (retval = krb5_get_host_realm(remote_host, &hrealms)) { 79*68591Sdab free(remote_host); 80*68591Sdab return retval; 81*68591Sdab } 82*68591Sdab if (!hrealms[0]) { 83*68591Sdab free(remote_host); 84*68591Sdab krb5_xfree(hrealms); 85*68591Sdab return KRB5_ERR_HOST_REALM_UNKNOWN; 86*68591Sdab } 87*68591Sdab 88*68591Sdab /* Count elements */ 89*68591Sdab for(i=0; hp->h_addr_list[i]; i++); 90*68591Sdab 91*68591Sdab addrs = (krb5_address **) malloc ((i+1)*sizeof(*addrs)); 92*68591Sdab if (!addrs) 93*68591Sdab return ENOMEM; 94*68591Sdab 95*68591Sdab for(i=0; hp->h_addr_list[i]; i++) { 96*68591Sdab addrs[i] = (krb5_address *) malloc(sizeof(krb5_address)); 97*68591Sdab if (addrs[i]) { 98*68591Sdab addrs[i]->addrtype = hp->h_addrtype; 99*68591Sdab addrs[i]->length = hp->h_length; 100*68591Sdab addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length); 101*68591Sdab if (!addrs[i]->contents) { 102*68591Sdab krb5_free_addresses(addrs); 103*68591Sdab return ENOMEM; 104*68591Sdab } 105*68591Sdab else 106*68591Sdab memcpy ((char *)addrs[i]->contents, hp->h_addr_list[i], 107*68591Sdab addrs[i]->length); 108*68591Sdab } 109*68591Sdab else { 110*68591Sdab return ENOMEM; 111*68591Sdab } 112*68591Sdab } 113*68591Sdab addrs[i] = 0; 114*68591Sdab 115*68591Sdab memset((char *)&creds, 0, sizeof(creds)); 116*68591Sdab if (retval = krb5_copy_principal(client, &creds.client)) 117*68591Sdab return retval; 118*68591Sdab 119*68591Sdab if (retval = krb5_build_principal_ext(&creds.server, 120*68591Sdab strlen(hrealms[0]), 121*68591Sdab hrealms[0], 122*68591Sdab KRB5_TGS_NAME_SIZE, 123*68591Sdab KRB5_TGS_NAME, 124*68591Sdab client->realm.length, 125*68591Sdab client->realm.data, 126*68591Sdab 0)) 127*68591Sdab return retval; 128*68591Sdab 129*68591Sdab creds.times.starttime = 0; 130*68591Sdab if (retval = krb5_timeofday(&now)) { 131*68591Sdab return retval; 132*68591Sdab } 133*68591Sdab creds.times.endtime = now + KRB5_DEFAULT_LIFE; 134*68591Sdab creds.times.renew_till = 0; 135*68591Sdab 136*68591Sdab if (retval = krb5_cc_default(&cc)) { 137*68591Sdab return retval; 138*68591Sdab } 139*68591Sdab 140*68591Sdab /* fetch tgt directly from cache */ 141*68591Sdab if (retval = krb5_cc_retrieve_cred (cc, 142*68591Sdab KRB5_TC_MATCH_SRV_NAMEONLY, 143*68591Sdab &creds, 144*68591Sdab &tgt)) { 145*68591Sdab return retval; 146*68591Sdab } 147*68591Sdab 148*68591Sdab /* tgt->client must be equal to creds.client */ 149*68591Sdab if (!krb5_principal_compare(tgt.client, creds.client)) 150*68591Sdab return KRB5_PRINC_NOMATCH; 151*68591Sdab 152*68591Sdab if (!tgt.ticket.length) 153*68591Sdab return(KRB5_NO_TKT_SUPPLIED); 154*68591Sdab 155*68591Sdab kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; 156*68591Sdab 157*68591Sdab if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */ 158*68591Sdab kdcoptions &= ~(KDC_OPT_FORWARDABLE); 159*68591Sdab 160*68591Sdab if (retval = krb5_send_tgs(kdcoptions, &creds.times, etype, sumtype, 161*68591Sdab creds.server, 162*68591Sdab addrs, 163*68591Sdab creds.authdata, 164*68591Sdab 0, /* no padata */ 165*68591Sdab 0, /* no second ticket */ 166*68591Sdab &tgt, &tgsrep)) 167*68591Sdab return retval; 168*68591Sdab 169*68591Sdab #undef cleanup 170*68591Sdab #define cleanup() free(tgsrep.response.data) 171*68591Sdab 172*68591Sdab switch (tgsrep.message_type) { 173*68591Sdab case KRB5_TGS_REP: 174*68591Sdab break; 175*68591Sdab case KRB5_ERROR: 176*68591Sdab default: 177*68591Sdab if (!krb5_is_krb_error(&tgsrep.response)) { 178*68591Sdab retval = KRB5KRB_AP_ERR_MSG_TYPE; 179*68591Sdab } else 180*68591Sdab retval = decode_krb5_error(&tgsrep.response, &err_reply); 181*68591Sdab if (retval) { 182*68591Sdab cleanup(); 183*68591Sdab return retval; /* neither proper reply nor error! */ 184*68591Sdab } 185*68591Sdab 186*68591Sdab retval = err_reply->error + ERROR_TABLE_BASE_krb5; 187*68591Sdab 188*68591Sdab krb5_free_error(err_reply); 189*68591Sdab cleanup(); 190*68591Sdab return retval; 191*68591Sdab } 192*68591Sdab retval = krb5_decode_kdc_rep(&tgsrep.response, 193*68591Sdab &tgt.keyblock, 194*68591Sdab etype, /* enctype */ 195*68591Sdab &dec_rep); 196*68591Sdab 197*68591Sdab cleanup(); 198*68591Sdab if (retval) 199*68591Sdab return retval; 200*68591Sdab #undef cleanup 201*68591Sdab #define cleanup() {\ 202*68591Sdab memset((char *)dec_rep->enc_part2->session->contents, 0,\ 203*68591Sdab dec_rep->enc_part2->session->length);\ 204*68591Sdab krb5_free_kdc_rep(dec_rep); } 205*68591Sdab 206*68591Sdab if (dec_rep->msg_type != KRB5_TGS_REP) { 207*68591Sdab retval = KRB5KRB_AP_ERR_MSG_TYPE; 208*68591Sdab cleanup(); 209*68591Sdab return retval; 210*68591Sdab } 211*68591Sdab 212*68591Sdab /* now it's decrypted and ready for prime time */ 213*68591Sdab 214*68591Sdab if (!krb5_principal_compare(dec_rep->client, tgt.client)) { 215*68591Sdab cleanup(); 216*68591Sdab return KRB5_KDCREP_MODIFIED; 217*68591Sdab } 218*68591Sdab 219*68591Sdab if (retval = mk_cred(dec_rep, 220*68591Sdab etype, 221*68591Sdab enc_key, 222*68591Sdab 0, 223*68591Sdab 0, 224*68591Sdab outbuf)) 225*68591Sdab return retval; 226*68591Sdab 227*68591Sdab krb5_free_kdc_rep(dec_rep); 228*68591Sdab 229*68591Sdab return retval; 230*68591Sdab #undef cleanup 231*68591Sdab } 232*68591Sdab 233*68591Sdab 234*68591Sdab 235*68591Sdab /* Create asn.1 encoded KRB-CRED message from the kdc reply. */ 236*68591Sdab krb5_error_code 237*68591Sdab mk_cred(dec_rep, etype, key, sender_addr, recv_addr, outbuf) 238*68591Sdab krb5_kdc_rep *dec_rep; 239*68591Sdab krb5_enctype etype; 240*68591Sdab krb5_keyblock *key; 241*68591Sdab krb5_address *sender_addr; 242*68591Sdab krb5_address *recv_addr; 243*68591Sdab krb5_data *outbuf; 244*68591Sdab { 245*68591Sdab krb5_error_code retval; 246*68591Sdab krb5_encrypt_block eblock; 247*68591Sdab krb5_cred ret_cred; 248*68591Sdab krb5_cred_enc_part cred_enc_part; 249*68591Sdab krb5_data *scratch; 250*68591Sdab 251*68591Sdab if (!valid_etype(etype)) 252*68591Sdab return KRB5_PROG_ETYPE_NOSUPP; 253*68591Sdab 254*68591Sdab ret_cred.tickets = (krb5_ticket **) calloc(2, sizeof(*ret_cred.tickets)); 255*68591Sdab if (!ret_cred.tickets) 256*68591Sdab return ENOMEM; 257*68591Sdab ret_cred.tickets[0] = dec_rep->ticket; 258*68591Sdab ret_cred.tickets[1] = 0; 259*68591Sdab 260*68591Sdab ret_cred.enc_part.etype = etype; 261*68591Sdab ret_cred.enc_part.kvno = 0; 262*68591Sdab 263*68591Sdab cred_enc_part.ticket_info = (krb5_cred_info **) 264*68591Sdab calloc(2, sizeof(*cred_enc_part.ticket_info)); 265*68591Sdab if (!cred_enc_part.ticket_info) { 266*68591Sdab krb5_free_tickets(ret_cred.tickets); 267*68591Sdab return ENOMEM; 268*68591Sdab } 269*68591Sdab cred_enc_part.ticket_info[0] = (krb5_cred_info *) 270*68591Sdab malloc(sizeof(*cred_enc_part.ticket_info[0])); 271*68591Sdab if (!cred_enc_part.ticket_info[0]) { 272*68591Sdab krb5_free_tickets(ret_cred.tickets); 273*68591Sdab krb5_free_cred_enc_part(cred_enc_part); 274*68591Sdab return ENOMEM; 275*68591Sdab } 276*68591Sdab cred_enc_part.nonce = 0; 277*68591Sdab 278*68591Sdab if (retval = krb5_us_timeofday(&cred_enc_part.timestamp, 279*68591Sdab &cred_enc_part.usec)) 280*68591Sdab return retval; 281*68591Sdab 282*68591Sdab cred_enc_part.s_address = (krb5_address *)sender_addr; 283*68591Sdab cred_enc_part.r_address = (krb5_address *)recv_addr; 284*68591Sdab 285*68591Sdab cred_enc_part.ticket_info[0]->session = dec_rep->enc_part2->session; 286*68591Sdab cred_enc_part.ticket_info[0]->client = dec_rep->client; 287*68591Sdab cred_enc_part.ticket_info[0]->server = dec_rep->enc_part2->server; 288*68591Sdab cred_enc_part.ticket_info[0]->flags = dec_rep->enc_part2->flags; 289*68591Sdab cred_enc_part.ticket_info[0]->times = dec_rep->enc_part2->times; 290*68591Sdab cred_enc_part.ticket_info[0]->caddrs = dec_rep->enc_part2->caddrs; 291*68591Sdab 292*68591Sdab cred_enc_part.ticket_info[1] = 0; 293*68591Sdab 294*68591Sdab /* start by encoding to-be-encrypted part of the message */ 295*68591Sdab 296*68591Sdab if (retval = encode_krb5_enc_cred_part(&cred_enc_part, &scratch)) 297*68591Sdab return retval; 298*68591Sdab 299*68591Sdab #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); krb5_free_data(scratch); } 300*68591Sdab 301*68591Sdab /* put together an eblock for this encryption */ 302*68591Sdab 303*68591Sdab krb5_use_cstype(&eblock, etype); 304*68591Sdab ret_cred.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length, 305*68591Sdab eblock.crypto_entry); 306*68591Sdab /* add padding area, and zero it */ 307*68591Sdab if (!(scratch->data = realloc(scratch->data, 308*68591Sdab ret_cred.enc_part.ciphertext.length))) { 309*68591Sdab /* may destroy scratch->data */ 310*68591Sdab krb5_xfree(scratch); 311*68591Sdab return ENOMEM; 312*68591Sdab } 313*68591Sdab memset(scratch->data + scratch->length, 0, 314*68591Sdab ret_cred.enc_part.ciphertext.length - scratch->length); 315*68591Sdab if (!(ret_cred.enc_part.ciphertext.data = 316*68591Sdab malloc(ret_cred.enc_part.ciphertext.length))) { 317*68591Sdab retval = ENOMEM; 318*68591Sdab goto clean_scratch; 319*68591Sdab } 320*68591Sdab 321*68591Sdab #define cleanup_encpart() {\ 322*68591Sdab (void) memset(ret_cred.enc_part.ciphertext.data, 0, \ 323*68591Sdab ret_cred.enc_part.ciphertext.length); \ 324*68591Sdab free(ret_cred.enc_part.ciphertext.data); \ 325*68591Sdab ret_cred.enc_part.ciphertext.length = 0; \ 326*68591Sdab ret_cred.enc_part.ciphertext.data = 0;} 327*68591Sdab 328*68591Sdab /* do any necessary key pre-processing */ 329*68591Sdab if (retval = krb5_process_key(&eblock, key)) { 330*68591Sdab goto clean_encpart; 331*68591Sdab } 332*68591Sdab 333*68591Sdab #define cleanup_prockey() {(void) krb5_finish_key(&eblock);} 334*68591Sdab 335*68591Sdab /* call the encryption routine */ 336*68591Sdab if (retval = krb5_encrypt((krb5_pointer) scratch->data, 337*68591Sdab (krb5_pointer) 338*68591Sdab ret_cred.enc_part.ciphertext.data, 339*68591Sdab scratch->length, &eblock, 340*68591Sdab 0)) { 341*68591Sdab goto clean_prockey; 342*68591Sdab } 343*68591Sdab 344*68591Sdab /* private message is now assembled-- do some cleanup */ 345*68591Sdab cleanup_scratch(); 346*68591Sdab 347*68591Sdab if (retval = krb5_finish_key(&eblock)) { 348*68591Sdab cleanup_encpart(); 349*68591Sdab return retval; 350*68591Sdab } 351*68591Sdab /* encode private message */ 352*68591Sdab if (retval = encode_krb5_cred(&ret_cred, &scratch)) { 353*68591Sdab cleanup_encpart(); 354*68591Sdab return retval; 355*68591Sdab } 356*68591Sdab 357*68591Sdab cleanup_encpart(); 358*68591Sdab 359*68591Sdab *outbuf = *scratch; 360*68591Sdab krb5_xfree(scratch); 361*68591Sdab return 0; 362*68591Sdab 363*68591Sdab clean_prockey: 364*68591Sdab cleanup_prockey(); 365*68591Sdab clean_encpart: 366*68591Sdab cleanup_encpart(); 367*68591Sdab clean_scratch: 368*68591Sdab cleanup_scratch(); 369*68591Sdab 370*68591Sdab return retval; 371*68591Sdab #undef cleanup_prockey 372*68591Sdab #undef cleanup_encpart 373*68591Sdab #undef cleanup_scratch 374*68591Sdab } 375*68591Sdab 376*68591Sdab 377*68591Sdab 378*68591Sdab /* Decode, decrypt and store the forwarded creds in the local ccache. */ 379*68591Sdab krb5_error_code 380*68591Sdab rd_and_store_for_creds(inbuf, ticket, lusername) 381*68591Sdab krb5_data *inbuf; 382*68591Sdab krb5_ticket *ticket; 383*68591Sdab char *lusername; 384*68591Sdab { 385*68591Sdab krb5_encrypt_block eblock; 386*68591Sdab krb5_creds creds; 387*68591Sdab krb5_error_code retval; 388*68591Sdab char ccname[35]; 389*68591Sdab krb5_ccache ccache = NULL; 390*68591Sdab struct passwd *pwd; 391*68591Sdab 392*68591Sdab if (retval = rd_cred(inbuf, ticket->enc_part2->session, 393*68591Sdab &creds, 0, 0)) { 394*68591Sdab return(retval); 395*68591Sdab } 396*68591Sdab 397*68591Sdab if (!(pwd = (struct passwd *) getpwnam(lusername))) { 398*68591Sdab return -1; 399*68591Sdab } 400*68591Sdab 401*68591Sdab sprintf(ccname, "FILE:/tmp/krb5cc_%d", pwd->pw_uid); 402*68591Sdab 403*68591Sdab if (retval = krb5_cc_resolve(ccname, &ccache)) { 404*68591Sdab return(retval); 405*68591Sdab } 406*68591Sdab 407*68591Sdab if (retval = krb5_cc_initialize(ccache, 408*68591Sdab ticket->enc_part2->client)) { 409*68591Sdab return(retval); 410*68591Sdab } 411*68591Sdab 412*68591Sdab if (retval = krb5_cc_store_cred(ccache, &creds)) { 413*68591Sdab return(retval); 414*68591Sdab } 415*68591Sdab 416*68591Sdab if (retval = chown(ccname+5, pwd->pw_uid, -1)) { 417*68591Sdab return(retval); 418*68591Sdab } 419*68591Sdab 420*68591Sdab return retval; 421*68591Sdab } 422*68591Sdab 423*68591Sdab 424*68591Sdab 425*68591Sdab extern krb5_deltat krb5_clockskew; 426*68591Sdab #define in_clock_skew(date) (abs((date)-currenttime) < krb5_clockskew) 427*68591Sdab 428*68591Sdab /* Decode the KRB-CRED message, and return creds */ 429*68591Sdab krb5_error_code 430*68591Sdab rd_cred(inbuf, key, creds, sender_addr, recv_addr) 431*68591Sdab const krb5_data *inbuf; 432*68591Sdab const krb5_keyblock *key; 433*68591Sdab krb5_creds *creds; /* Filled in */ 434*68591Sdab const krb5_address *sender_addr; /* optional */ 435*68591Sdab const krb5_address *recv_addr; /* optional */ 436*68591Sdab { 437*68591Sdab krb5_error_code retval; 438*68591Sdab krb5_encrypt_block eblock; 439*68591Sdab krb5_cred *credmsg; 440*68591Sdab krb5_cred_enc_part *credmsg_enc_part; 441*68591Sdab krb5_data *scratch; 442*68591Sdab krb5_timestamp currenttime; 443*68591Sdab 444*68591Sdab if (!krb5_is_krb_cred(inbuf)) 445*68591Sdab return KRB5KRB_AP_ERR_MSG_TYPE; 446*68591Sdab 447*68591Sdab /* decode private message */ 448*68591Sdab if (retval = decode_krb5_cred(inbuf, &credmsg)) { 449*68591Sdab return retval; 450*68591Sdab } 451*68591Sdab 452*68591Sdab #define cleanup_credmsg() {(void)krb5_xfree(credmsg->enc_part.ciphertext.data); (void)krb5_xfree(credmsg);} 453*68591Sdab 454*68591Sdab if (!(scratch = (krb5_data *) malloc(sizeof(*scratch)))) { 455*68591Sdab cleanup_credmsg(); 456*68591Sdab return ENOMEM; 457*68591Sdab } 458*68591Sdab 459*68591Sdab #define cleanup_scratch() {(void)memset(scratch->data, 0, scratch->length); (void)krb5_xfree(scratch->data);} 460*68591Sdab 461*68591Sdab if (retval = encode_krb5_ticket(credmsg->tickets[0], &scratch)) { 462*68591Sdab cleanup_credmsg(); 463*68591Sdab cleanup_scratch(); 464*68591Sdab return(retval); 465*68591Sdab } 466*68591Sdab 467*68591Sdab creds->ticket = *scratch; 468*68591Sdab if (!(creds->ticket.data = malloc(scratch->length))) { 469*68591Sdab krb5_xfree(creds->ticket.data); 470*68591Sdab return ENOMEM; 471*68591Sdab } 472*68591Sdab memcpy((char *)creds->ticket.data, (char *) scratch->data, scratch->length); 473*68591Sdab 474*68591Sdab cleanup_scratch(); 475*68591Sdab 476*68591Sdab if (!valid_etype(credmsg->enc_part.etype)) { 477*68591Sdab cleanup_credmsg(); 478*68591Sdab return KRB5_PROG_ETYPE_NOSUPP; 479*68591Sdab } 480*68591Sdab 481*68591Sdab /* put together an eblock for this decryption */ 482*68591Sdab 483*68591Sdab krb5_use_cstype(&eblock, credmsg->enc_part.etype); 484*68591Sdab scratch->length = credmsg->enc_part.ciphertext.length; 485*68591Sdab 486*68591Sdab if (!(scratch->data = malloc(scratch->length))) { 487*68591Sdab cleanup_credmsg(); 488*68591Sdab return ENOMEM; 489*68591Sdab } 490*68591Sdab 491*68591Sdab /* do any necessary key pre-processing */ 492*68591Sdab if (retval = krb5_process_key(&eblock, key)) { 493*68591Sdab cleanup_credmsg(); 494*68591Sdab cleanup_scratch(); 495*68591Sdab return retval; 496*68591Sdab } 497*68591Sdab 498*68591Sdab #define cleanup_prockey() {(void) krb5_finish_key(&eblock);} 499*68591Sdab 500*68591Sdab /* call the decryption routine */ 501*68591Sdab if (retval = krb5_decrypt((krb5_pointer) credmsg->enc_part.ciphertext.data, 502*68591Sdab (krb5_pointer) scratch->data, 503*68591Sdab scratch->length, &eblock, 504*68591Sdab 0)) { 505*68591Sdab cleanup_credmsg(); 506*68591Sdab cleanup_scratch(); 507*68591Sdab cleanup_prockey(); 508*68591Sdab return retval; 509*68591Sdab } 510*68591Sdab 511*68591Sdab /* cred message is now decrypted -- do some cleanup */ 512*68591Sdab 513*68591Sdab cleanup_credmsg(); 514*68591Sdab 515*68591Sdab if (retval = krb5_finish_key(&eblock)) { 516*68591Sdab cleanup_scratch(); 517*68591Sdab return retval; 518*68591Sdab } 519*68591Sdab 520*68591Sdab /* now decode the decrypted stuff */ 521*68591Sdab if (retval = decode_krb5_enc_cred_part(scratch, &credmsg_enc_part)) { 522*68591Sdab cleanup_scratch(); 523*68591Sdab return retval; 524*68591Sdab } 525*68591Sdab cleanup_scratch(); 526*68591Sdab 527*68591Sdab #define cleanup_mesg() {(void)krb5_xfree(credmsg_enc_part);} 528*68591Sdab 529*68591Sdab if (retval = krb5_timeofday(¤ttime)) { 530*68591Sdab cleanup_mesg(); 531*68591Sdab return retval; 532*68591Sdab } 533*68591Sdab if (!in_clock_skew(credmsg_enc_part->timestamp)) { 534*68591Sdab cleanup_mesg(); 535*68591Sdab return KRB5KRB_AP_ERR_SKEW; 536*68591Sdab } 537*68591Sdab 538*68591Sdab if (sender_addr && credmsg_enc_part->s_address && 539*68591Sdab !krb5_address_compare(sender_addr, 540*68591Sdab credmsg_enc_part->s_address)) { 541*68591Sdab cleanup_mesg(); 542*68591Sdab return KRB5KRB_AP_ERR_BADADDR; 543*68591Sdab } 544*68591Sdab if (recv_addr && credmsg_enc_part->r_address && 545*68591Sdab !krb5_address_compare(recv_addr, 546*68591Sdab credmsg_enc_part->r_address)) { 547*68591Sdab cleanup_mesg(); 548*68591Sdab return KRB5KRB_AP_ERR_BADADDR; 549*68591Sdab } 550*68591Sdab 551*68591Sdab if (credmsg_enc_part->r_address) { 552*68591Sdab krb5_address **our_addrs; 553*68591Sdab 554*68591Sdab if (retval = krb5_os_localaddr(&our_addrs)) { 555*68591Sdab cleanup_mesg(); 556*68591Sdab return retval; 557*68591Sdab } 558*68591Sdab if (!krb5_address_search(credmsg_enc_part->r_address, 559*68591Sdab our_addrs)) { 560*68591Sdab krb5_free_addresses(our_addrs); 561*68591Sdab cleanup_mesg(); 562*68591Sdab return KRB5KRB_AP_ERR_BADADDR; 563*68591Sdab } 564*68591Sdab krb5_free_addresses(our_addrs); 565*68591Sdab } 566*68591Sdab 567*68591Sdab if (retval = krb5_copy_principal(credmsg_enc_part->ticket_info[0]->client, 568*68591Sdab &creds->client)) { 569*68591Sdab return(retval); 570*68591Sdab } 571*68591Sdab 572*68591Sdab if (retval = krb5_copy_principal(credmsg_enc_part->ticket_info[0]->server, 573*68591Sdab &creds->server)) { 574*68591Sdab return(retval); 575*68591Sdab } 576*68591Sdab 577*68591Sdab if (retval = 578*68591Sdab krb5_copy_keyblock_contents(credmsg_enc_part->ticket_info[0]->session, 579*68591Sdab &creds->keyblock)) { 580*68591Sdab return(retval); 581*68591Sdab } 582*68591Sdab 583*68591Sdab #undef clean 584*68591Sdab #define clean() {\ 585*68591Sdab memset((char *)creds->keyblock.contents, 0, creds->keyblock.length);} 586*68591Sdab 587*68591Sdab creds->times = credmsg_enc_part->ticket_info[0]->times; 588*68591Sdab creds->is_skey = FALSE; 589*68591Sdab creds->ticket_flags = credmsg_enc_part->ticket_info[0]->flags; 590*68591Sdab 591*68591Sdab if (retval = krb5_copy_addresses(credmsg_enc_part->ticket_info[0]->caddrs, 592*68591Sdab &creds->addresses)) { 593*68591Sdab clean(); 594*68591Sdab return(retval); 595*68591Sdab } 596*68591Sdab 597*68591Sdab creds->second_ticket.length = 0; 598*68591Sdab 599*68591Sdab creds->authdata = 0; 600*68591Sdab 601*68591Sdab cleanup_mesg(); 602*68591Sdab return 0; 603*68591Sdab #undef clean 604*68591Sdab #undef cleanup_credmsg 605*68591Sdab #undef cleanup_scratch 606*68591Sdab #undef cleanup_prockey 607*68591Sdab #undef cleanup_mesg 608*68591Sdab } 609*68591Sdab 610*68591Sdab #endif /* defined(KRB5) && defined(FORWARD) */ 611