1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate /* 9*7c478bd9Sstevel@tonic-gate * lib/krb5/krb/get_in_tkt.c 10*7c478bd9Sstevel@tonic-gate * 11*7c478bd9Sstevel@tonic-gate * Copyright 1990,1991, 2003 by the Massachusetts Institute of Technology. 12*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 15*7c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 16*7c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 17*7c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 18*7c478bd9Sstevel@tonic-gate * 19*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 20*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 21*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 22*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 23*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 24*7c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 25*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 26*7c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 27*7c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 28*7c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 29*7c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 30*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 31*7c478bd9Sstevel@tonic-gate * or implied warranty. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * krb5_get_in_tkt() 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <k5-int.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate All-purpose initial ticket routine, usually called via 43*7c478bd9Sstevel@tonic-gate krb5_get_in_tkt_with_password or krb5_get_in_tkt_with_skey. 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate Attempts to get an initial ticket for creds->client to use server 46*7c478bd9Sstevel@tonic-gate creds->server, (realm is taken from creds->client), with options 47*7c478bd9Sstevel@tonic-gate options, and using creds->times.starttime, creds->times.endtime, 48*7c478bd9Sstevel@tonic-gate creds->times.renew_till as from, till, and rtime. 49*7c478bd9Sstevel@tonic-gate creds->times.renew_till is ignored unless the RENEWABLE option is requested. 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate key_proc is called to fill in the key to be used for decryption. 52*7c478bd9Sstevel@tonic-gate keyseed is passed on to key_proc. 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate decrypt_proc is called to perform the decryption of the response (the 55*7c478bd9Sstevel@tonic-gate encrypted part is in dec_rep->enc_part; the decrypted part should be 56*7c478bd9Sstevel@tonic-gate allocated and filled into dec_rep->enc_part2 57*7c478bd9Sstevel@tonic-gate arg is passed on to decrypt_proc. 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate If addrs is non-NULL, it is used for the addresses requested. If it is 60*7c478bd9Sstevel@tonic-gate null, the system standard addresses are used. 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate A succesful call will place the ticket in the credentials cache ccache 63*7c478bd9Sstevel@tonic-gate and fill in creds with the ticket information used/returned.. 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate returns system errors, encryption errors 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* some typedef's for the function args to make things look a bit cleaner */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate typedef krb5_error_code (*git_key_proc) PROTOTYPE((krb5_context, 73*7c478bd9Sstevel@tonic-gate const krb5_enctype, 74*7c478bd9Sstevel@tonic-gate krb5_data *, 75*7c478bd9Sstevel@tonic-gate krb5_const_pointer, 76*7c478bd9Sstevel@tonic-gate krb5_keyblock **)); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate typedef krb5_error_code (*git_decrypt_proc) PROTOTYPE((krb5_context, 79*7c478bd9Sstevel@tonic-gate const krb5_keyblock *, 80*7c478bd9Sstevel@tonic-gate krb5_const_pointer, 81*7c478bd9Sstevel@tonic-gate krb5_kdc_rep * )); 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static krb5_error_code make_preauth_list PROTOTYPE((krb5_context, 84*7c478bd9Sstevel@tonic-gate krb5_preauthtype *, 85*7c478bd9Sstevel@tonic-gate int, krb5_pa_data ***)); 86*7c478bd9Sstevel@tonic-gate /* 87*7c478bd9Sstevel@tonic-gate * This function sends a request to the KDC, and gets back a response; 88*7c478bd9Sstevel@tonic-gate * the response is parsed into ret_err_reply or ret_as_reply if the 89*7c478bd9Sstevel@tonic-gate * reponse is a KRB_ERROR or a KRB_AS_REP packet. If it is some other 90*7c478bd9Sstevel@tonic-gate * unexpected response, an error is returned. 91*7c478bd9Sstevel@tonic-gate */ 92*7c478bd9Sstevel@tonic-gate static krb5_error_code 93*7c478bd9Sstevel@tonic-gate send_as_request(context, request, time_now, ret_err_reply, ret_as_reply, 94*7c478bd9Sstevel@tonic-gate use_master) 95*7c478bd9Sstevel@tonic-gate krb5_context context; 96*7c478bd9Sstevel@tonic-gate krb5_kdc_req *request; 97*7c478bd9Sstevel@tonic-gate krb5_timestamp *time_now; 98*7c478bd9Sstevel@tonic-gate krb5_error ** ret_err_reply; 99*7c478bd9Sstevel@tonic-gate krb5_kdc_rep ** ret_as_reply; 100*7c478bd9Sstevel@tonic-gate int use_master; 101*7c478bd9Sstevel@tonic-gate { 102*7c478bd9Sstevel@tonic-gate krb5_kdc_rep *as_reply = 0; 103*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 104*7c478bd9Sstevel@tonic-gate krb5_data *packet = 0; 105*7c478bd9Sstevel@tonic-gate krb5_data reply; 106*7c478bd9Sstevel@tonic-gate char k4_version; /* same type as *(krb5_data::data) */ 107*7c478bd9Sstevel@tonic-gate int tcp_only = 0; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate reply.data = 0; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if ((retval = krb5_timeofday(context, time_now))) 112*7c478bd9Sstevel@tonic-gate goto cleanup; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * XXX we know they are the same size... and we should do 116*7c478bd9Sstevel@tonic-gate * something better than just the current time 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate request->nonce = (krb5_int32) *time_now; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* encode & send to KDC */ 121*7c478bd9Sstevel@tonic-gate if ((retval = encode_krb5_as_req(request, &packet)) != 0) 122*7c478bd9Sstevel@tonic-gate goto cleanup; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate k4_version = packet->data[0]; 125*7c478bd9Sstevel@tonic-gate send_again: 126*7c478bd9Sstevel@tonic-gate retval = krb5_sendto_kdc(context, packet, 127*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, request->client), 128*7c478bd9Sstevel@tonic-gate &reply, use_master, tcp_only); 129*7c478bd9Sstevel@tonic-gate if (retval) 130*7c478bd9Sstevel@tonic-gate goto cleanup; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* now decode the reply...could be error or as_rep */ 133*7c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&reply)) { 134*7c478bd9Sstevel@tonic-gate krb5_error *err_reply; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate if ((retval = decode_krb5_error(&reply, &err_reply))) 137*7c478bd9Sstevel@tonic-gate /* some other error code--??? */ 138*7c478bd9Sstevel@tonic-gate goto cleanup; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (ret_err_reply) { 141*7c478bd9Sstevel@tonic-gate if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG 142*7c478bd9Sstevel@tonic-gate && tcp_only == 0) { 143*7c478bd9Sstevel@tonic-gate tcp_only = 1; 144*7c478bd9Sstevel@tonic-gate krb5_free_error(context, err_reply); 145*7c478bd9Sstevel@tonic-gate free(reply.data); 146*7c478bd9Sstevel@tonic-gate reply.data = 0; 147*7c478bd9Sstevel@tonic-gate goto send_again; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate *ret_err_reply = err_reply; 150*7c478bd9Sstevel@tonic-gate } else 151*7c478bd9Sstevel@tonic-gate krb5_free_error(context, err_reply); 152*7c478bd9Sstevel@tonic-gate goto cleanup; 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * Check to make sure it isn't a V4 reply. 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate if (!krb5_is_as_rep(&reply)) { 159*7c478bd9Sstevel@tonic-gate /* these are in <kerberosIV/prot.h> as well but it isn't worth including. */ 160*7c478bd9Sstevel@tonic-gate #define V4_KRB_PROT_VERSION 4 161*7c478bd9Sstevel@tonic-gate #define V4_AUTH_MSG_ERR_REPLY (5<<1) 162*7c478bd9Sstevel@tonic-gate /* check here for V4 reply */ 163*7c478bd9Sstevel@tonic-gate unsigned int t_switch; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* From v4 g_in_tkt.c: This used to be 166*7c478bd9Sstevel@tonic-gate switch (pkt_msg_type(rpkt) & ~1) { 167*7c478bd9Sstevel@tonic-gate but SCO 3.2v4 cc compiled that incorrectly. */ 168*7c478bd9Sstevel@tonic-gate t_switch = reply.data[1]; 169*7c478bd9Sstevel@tonic-gate t_switch &= ~1; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate if (t_switch == V4_AUTH_MSG_ERR_REPLY 172*7c478bd9Sstevel@tonic-gate && (reply.data[0] == V4_KRB_PROT_VERSION 173*7c478bd9Sstevel@tonic-gate || reply.data[0] == k4_version)) { 174*7c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_V4_REPLY; 175*7c478bd9Sstevel@tonic-gate } else { 176*7c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_MSG_TYPE; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate goto cleanup; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* It must be a KRB_AS_REP message, or an bad returned packet */ 182*7c478bd9Sstevel@tonic-gate if ((retval = decode_krb5_as_rep(&reply, &as_reply))) 183*7c478bd9Sstevel@tonic-gate /* some other error code ??? */ 184*7c478bd9Sstevel@tonic-gate goto cleanup; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate if (as_reply->msg_type != KRB5_AS_REP) { 187*7c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_MSG_TYPE; 188*7c478bd9Sstevel@tonic-gate krb5_free_kdc_rep(context, as_reply); 189*7c478bd9Sstevel@tonic-gate goto cleanup; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (ret_as_reply) 193*7c478bd9Sstevel@tonic-gate *ret_as_reply = as_reply; 194*7c478bd9Sstevel@tonic-gate else 195*7c478bd9Sstevel@tonic-gate krb5_free_kdc_rep(context, as_reply); 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate cleanup: 198*7c478bd9Sstevel@tonic-gate if (packet) 199*7c478bd9Sstevel@tonic-gate krb5_free_data(context, packet); 200*7c478bd9Sstevel@tonic-gate if (reply.data) 201*7c478bd9Sstevel@tonic-gate free(reply.data); 202*7c478bd9Sstevel@tonic-gate return retval; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate static krb5_error_code 206*7c478bd9Sstevel@tonic-gate decrypt_as_reply(context, request, as_reply, key_proc, keyseed, key, 207*7c478bd9Sstevel@tonic-gate decrypt_proc, decryptarg) 208*7c478bd9Sstevel@tonic-gate krb5_context context; 209*7c478bd9Sstevel@tonic-gate krb5_kdc_req *request; 210*7c478bd9Sstevel@tonic-gate krb5_kdc_rep *as_reply; 211*7c478bd9Sstevel@tonic-gate git_key_proc key_proc; 212*7c478bd9Sstevel@tonic-gate krb5_const_pointer keyseed; 213*7c478bd9Sstevel@tonic-gate krb5_keyblock * key; 214*7c478bd9Sstevel@tonic-gate git_decrypt_proc decrypt_proc; 215*7c478bd9Sstevel@tonic-gate krb5_const_pointer decryptarg; 216*7c478bd9Sstevel@tonic-gate { 217*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 218*7c478bd9Sstevel@tonic-gate krb5_keyblock * decrypt_key = 0; 219*7c478bd9Sstevel@tonic-gate krb5_data salt; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "decrypt_as_reply() start"); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (as_reply->enc_part2) 224*7c478bd9Sstevel@tonic-gate return 0; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate if (key) 227*7c478bd9Sstevel@tonic-gate decrypt_key = key; 228*7c478bd9Sstevel@tonic-gate else if (request != NULL) { 229*7c478bd9Sstevel@tonic-gate if ((retval = krb5_principal2salt(context, request->client, &salt))) 230*7c478bd9Sstevel@tonic-gate return(retval); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate retval = (*key_proc)(context, as_reply->enc_part.enctype, 233*7c478bd9Sstevel@tonic-gate &salt, keyseed, &decrypt_key); 234*7c478bd9Sstevel@tonic-gate krb5_xfree(salt.data); 235*7c478bd9Sstevel@tonic-gate if (retval) 236*7c478bd9Sstevel@tonic-gate goto cleanup; 237*7c478bd9Sstevel@tonic-gate } else { 238*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_ERR, "decrypt_as_reply() end, " 239*7c478bd9Sstevel@tonic-gate "error key == NULL and request == NULL"); 240*7c478bd9Sstevel@tonic-gate return (EINVAL); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* Solaris kerberos: Overwriting the decrypt_key->enctype because the 244*7c478bd9Sstevel@tonic-gate * decrypt key's enctype may not be an exact match with the enctype that the 245*7c478bd9Sstevel@tonic-gate * KDC used to encrypt this part of the AS reply. This assumes the 246*7c478bd9Sstevel@tonic-gate * as_reply->enc_part.enctype has been validated which is done by checking 247*7c478bd9Sstevel@tonic-gate * to see if the enctype that the KDC sent back in the as_reply is one of 248*7c478bd9Sstevel@tonic-gate * the enctypes originally requested. Note, if request is NULL then the 249*7c478bd9Sstevel@tonic-gate * as_reply->enc_part.enctype could not be validated. 250*7c478bd9Sstevel@tonic-gate */ 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if (request != NULL) { 253*7c478bd9Sstevel@tonic-gate if (is_in_keytype(request->ktype, request->nktypes, 254*7c478bd9Sstevel@tonic-gate as_reply->enc_part.enctype)) { 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate decrypt_key->enctype = as_reply->enc_part.enctype; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate } else { 259*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_ERR, "decrypt_as_reply() end, " 260*7c478bd9Sstevel@tonic-gate "error is_in_keytype() returned false"); 261*7c478bd9Sstevel@tonic-gate retval = KRB5_BAD_ENCTYPE; 262*7c478bd9Sstevel@tonic-gate goto cleanup; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if ((retval = (*decrypt_proc)(context, decrypt_key, decryptarg, as_reply))){ 267*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "decrypt_as_reply() error (*decrypt_proc)() retval " 268*7c478bd9Sstevel@tonic-gate "= %d", retval); 269*7c478bd9Sstevel@tonic-gate goto cleanup; 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate cleanup: 273*7c478bd9Sstevel@tonic-gate if (!key && decrypt_key) 274*7c478bd9Sstevel@tonic-gate krb5_free_keyblock(context, decrypt_key); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_INFO, "decrypt_as_reply() end, retval = %d", retval); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate return (retval); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate static krb5_error_code 282*7c478bd9Sstevel@tonic-gate verify_as_reply(context, time_now, request, as_reply) 283*7c478bd9Sstevel@tonic-gate krb5_context context; 284*7c478bd9Sstevel@tonic-gate krb5_timestamp time_now; 285*7c478bd9Sstevel@tonic-gate krb5_kdc_req *request; 286*7c478bd9Sstevel@tonic-gate krb5_kdc_rep *as_reply; 287*7c478bd9Sstevel@tonic-gate { 288*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate /* check the contents for sanity: */ 291*7c478bd9Sstevel@tonic-gate if (!as_reply->enc_part2->times.starttime) 292*7c478bd9Sstevel@tonic-gate as_reply->enc_part2->times.starttime = 293*7c478bd9Sstevel@tonic-gate as_reply->enc_part2->times.authtime; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (!krb5_principal_compare(context, as_reply->client, request->client) 296*7c478bd9Sstevel@tonic-gate || !krb5_principal_compare(context, as_reply->enc_part2->server, request->server) 297*7c478bd9Sstevel@tonic-gate || !krb5_principal_compare(context, as_reply->ticket->server, request->server) 298*7c478bd9Sstevel@tonic-gate || (request->nonce != as_reply->enc_part2->nonce) 299*7c478bd9Sstevel@tonic-gate /* XXX check for extraneous flags */ 300*7c478bd9Sstevel@tonic-gate /* XXX || (!krb5_addresses_compare(context, addrs, as_reply->enc_part2->caddrs)) */ 301*7c478bd9Sstevel@tonic-gate || ((request->kdc_options & KDC_OPT_POSTDATED) && 302*7c478bd9Sstevel@tonic-gate (request->from != 0) && 303*7c478bd9Sstevel@tonic-gate (request->from != as_reply->enc_part2->times.starttime)) 304*7c478bd9Sstevel@tonic-gate || ((request->till != 0) && 305*7c478bd9Sstevel@tonic-gate (as_reply->enc_part2->times.endtime > request->till)) 306*7c478bd9Sstevel@tonic-gate || ((request->kdc_options & KDC_OPT_RENEWABLE) && 307*7c478bd9Sstevel@tonic-gate (request->rtime != 0) && 308*7c478bd9Sstevel@tonic-gate (as_reply->enc_part2->times.renew_till > request->rtime)) 309*7c478bd9Sstevel@tonic-gate || ((request->kdc_options & KDC_OPT_RENEWABLE_OK) && 310*7c478bd9Sstevel@tonic-gate !(request->kdc_options & KDC_OPT_RENEWABLE) && 311*7c478bd9Sstevel@tonic-gate (as_reply->enc_part2->flags & KDC_OPT_RENEWABLE) && 312*7c478bd9Sstevel@tonic-gate (request->till != 0) && 313*7c478bd9Sstevel@tonic-gate (as_reply->enc_part2->times.renew_till > request->till)) 314*7c478bd9Sstevel@tonic-gate ) 315*7c478bd9Sstevel@tonic-gate return KRB5_KDCREP_MODIFIED; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) { 318*7c478bd9Sstevel@tonic-gate retval = krb5_set_real_time(context, 319*7c478bd9Sstevel@tonic-gate as_reply->enc_part2->times.authtime, 0); 320*7c478bd9Sstevel@tonic-gate if (retval) 321*7c478bd9Sstevel@tonic-gate return retval; 322*7c478bd9Sstevel@tonic-gate } else { 323*7c478bd9Sstevel@tonic-gate if ((request->from == 0) && 324*7c478bd9Sstevel@tonic-gate (labs(as_reply->enc_part2->times.starttime - time_now) 325*7c478bd9Sstevel@tonic-gate > context->clockskew)) 326*7c478bd9Sstevel@tonic-gate return (KRB5_KDCREP_SKEW); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate return 0; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 332*7c478bd9Sstevel@tonic-gate static krb5_error_code 333*7c478bd9Sstevel@tonic-gate stash_as_reply(context, time_now, request, as_reply, creds, ccache) 334*7c478bd9Sstevel@tonic-gate krb5_context context; 335*7c478bd9Sstevel@tonic-gate krb5_timestamp time_now; 336*7c478bd9Sstevel@tonic-gate krb5_kdc_req *request; 337*7c478bd9Sstevel@tonic-gate krb5_kdc_rep *as_reply; 338*7c478bd9Sstevel@tonic-gate krb5_creds * creds; 339*7c478bd9Sstevel@tonic-gate krb5_ccache ccache; 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 342*7c478bd9Sstevel@tonic-gate krb5_data * packet; 343*7c478bd9Sstevel@tonic-gate krb5_principal client; 344*7c478bd9Sstevel@tonic-gate krb5_principal server; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate client = NULL; 347*7c478bd9Sstevel@tonic-gate server = NULL; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate if (!creds->client) 350*7c478bd9Sstevel@tonic-gate if (retval = krb5_copy_principal(context, as_reply->client, &client)) 351*7c478bd9Sstevel@tonic-gate goto cleanup; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate if (!creds->server) 354*7c478bd9Sstevel@tonic-gate if (retval = krb5_copy_principal(context, as_reply->enc_part2->server, 355*7c478bd9Sstevel@tonic-gate &server)) 356*7c478bd9Sstevel@tonic-gate goto cleanup; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* fill in the credentials */ 359*7c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_keyblock_contents(context, 360*7c478bd9Sstevel@tonic-gate as_reply->enc_part2->session, 361*7c478bd9Sstevel@tonic-gate &creds->keyblock))) 362*7c478bd9Sstevel@tonic-gate goto cleanup; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate creds->times = as_reply->enc_part2->times; 365*7c478bd9Sstevel@tonic-gate creds->is_skey = FALSE; /* this is an AS_REQ, so cannot 366*7c478bd9Sstevel@tonic-gate be encrypted in skey */ 367*7c478bd9Sstevel@tonic-gate creds->ticket_flags = as_reply->enc_part2->flags; 368*7c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_addresses(context, as_reply->enc_part2->caddrs, 369*7c478bd9Sstevel@tonic-gate &creds->addresses))) 370*7c478bd9Sstevel@tonic-gate goto cleanup; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate creds->second_ticket.length = 0; 373*7c478bd9Sstevel@tonic-gate creds->second_ticket.data = 0; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if ((retval = encode_krb5_ticket(as_reply->ticket, &packet))) 376*7c478bd9Sstevel@tonic-gate goto cleanup; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate creds->ticket = *packet; 379*7c478bd9Sstevel@tonic-gate krb5_xfree(packet); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* store it in the ccache! */ 382*7c478bd9Sstevel@tonic-gate if (ccache) 383*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_store_cred(context, ccache, creds)) !=0) 384*7c478bd9Sstevel@tonic-gate goto cleanup; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if (!creds->client) 387*7c478bd9Sstevel@tonic-gate creds->client = client; 388*7c478bd9Sstevel@tonic-gate if (!creds->server) 389*7c478bd9Sstevel@tonic-gate creds->server = server; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate cleanup: 392*7c478bd9Sstevel@tonic-gate if (retval) { 393*7c478bd9Sstevel@tonic-gate if (client) 394*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, client); 395*7c478bd9Sstevel@tonic-gate if (server) 396*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, server); 397*7c478bd9Sstevel@tonic-gate if (creds->keyblock.contents) { 398*7c478bd9Sstevel@tonic-gate memset((char *)creds->keyblock.contents, 0, 399*7c478bd9Sstevel@tonic-gate creds->keyblock.length); 400*7c478bd9Sstevel@tonic-gate krb5_xfree(creds->keyblock.contents); 401*7c478bd9Sstevel@tonic-gate creds->keyblock.contents = 0; 402*7c478bd9Sstevel@tonic-gate creds->keyblock.length = 0; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate if (creds->ticket.data) { 405*7c478bd9Sstevel@tonic-gate krb5_xfree(creds->ticket.data); 406*7c478bd9Sstevel@tonic-gate creds->ticket.data = 0; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate if (creds->addresses) { 409*7c478bd9Sstevel@tonic-gate krb5_free_addresses(context, creds->addresses); 410*7c478bd9Sstevel@tonic-gate creds->addresses = 0; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate return (retval); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 417*7c478bd9Sstevel@tonic-gate static krb5_error_code 418*7c478bd9Sstevel@tonic-gate make_preauth_list(context, ptypes, nptypes, ret_list) 419*7c478bd9Sstevel@tonic-gate krb5_context context; 420*7c478bd9Sstevel@tonic-gate krb5_preauthtype * ptypes; 421*7c478bd9Sstevel@tonic-gate int nptypes; 422*7c478bd9Sstevel@tonic-gate krb5_pa_data *** ret_list; 423*7c478bd9Sstevel@tonic-gate { 424*7c478bd9Sstevel@tonic-gate krb5_preauthtype * ptypep; 425*7c478bd9Sstevel@tonic-gate krb5_pa_data ** preauthp; 426*7c478bd9Sstevel@tonic-gate int i; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate if (nptypes < 0) { 429*7c478bd9Sstevel@tonic-gate for (nptypes=0, ptypep = ptypes; *ptypep; ptypep++, nptypes++) 430*7c478bd9Sstevel@tonic-gate ; 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* allocate space for a NULL to terminate the list */ 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if ((preauthp = 436*7c478bd9Sstevel@tonic-gate (krb5_pa_data **) malloc((nptypes+1)*sizeof(krb5_pa_data *))) == NULL) 437*7c478bd9Sstevel@tonic-gate return(ENOMEM); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate for (i=0; i<nptypes; i++) { 440*7c478bd9Sstevel@tonic-gate if ((preauthp[i] = 441*7c478bd9Sstevel@tonic-gate (krb5_pa_data *) malloc(sizeof(krb5_pa_data))) == NULL) { 442*7c478bd9Sstevel@tonic-gate for (; i>=0; i++) 443*7c478bd9Sstevel@tonic-gate free(preauthp[i]); 444*7c478bd9Sstevel@tonic-gate free(preauthp); 445*7c478bd9Sstevel@tonic-gate return (ENOMEM); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate preauthp[i]->magic = KV5M_PA_DATA; 448*7c478bd9Sstevel@tonic-gate preauthp[i]->pa_type = ptypes[i]; 449*7c478bd9Sstevel@tonic-gate preauthp[i]->length = 0; 450*7c478bd9Sstevel@tonic-gate preauthp[i]->contents = 0; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* fill in the terminating NULL */ 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate preauthp[nptypes] = NULL; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate *ret_list = preauthp; 458*7c478bd9Sstevel@tonic-gate return 0; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate #define MAX_IN_TKT_LOOPS 16 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* begin libdefaults parsing code. This should almost certainly move 464*7c478bd9Sstevel@tonic-gate somewhere else, but I don't know where the correct somewhere else 465*7c478bd9Sstevel@tonic-gate is yet. */ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* XXX Duplicating this is annoying; try to work on a better way.*/ 468*7c478bd9Sstevel@tonic-gate static char *conf_yes[] = { 469*7c478bd9Sstevel@tonic-gate "y", "yes", "true", "t", "1", "on", 470*7c478bd9Sstevel@tonic-gate 0, 471*7c478bd9Sstevel@tonic-gate }; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate static char *conf_no[] = { 474*7c478bd9Sstevel@tonic-gate "n", "no", "false", "nil", "0", "off", 475*7c478bd9Sstevel@tonic-gate 0, 476*7c478bd9Sstevel@tonic-gate }; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate int 479*7c478bd9Sstevel@tonic-gate _krb5_conf_boolean(s) 480*7c478bd9Sstevel@tonic-gate char *s; 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate char **p; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate for(p=conf_yes; *p; p++) { 485*7c478bd9Sstevel@tonic-gate if (!strcasecmp(*p,s)) 486*7c478bd9Sstevel@tonic-gate return 1; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate for(p=conf_no; *p; p++) { 490*7c478bd9Sstevel@tonic-gate if (!strcasecmp(*p,s)) 491*7c478bd9Sstevel@tonic-gate return 0; 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate /* Default to "no" */ 495*7c478bd9Sstevel@tonic-gate return 0; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate static krb5_error_code 499*7c478bd9Sstevel@tonic-gate krb5_libdefault_string(context, realm, option, ret_value) 500*7c478bd9Sstevel@tonic-gate krb5_context context; 501*7c478bd9Sstevel@tonic-gate const krb5_data *realm; 502*7c478bd9Sstevel@tonic-gate const char *option; 503*7c478bd9Sstevel@tonic-gate char **ret_value; 504*7c478bd9Sstevel@tonic-gate { 505*7c478bd9Sstevel@tonic-gate profile_t profile; 506*7c478bd9Sstevel@tonic-gate const char *names[5]; 507*7c478bd9Sstevel@tonic-gate char **nameval = NULL; 508*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 509*7c478bd9Sstevel@tonic-gate char realmstr[1024]; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate if (realm->length > sizeof(realmstr)-1) 512*7c478bd9Sstevel@tonic-gate return(EINVAL); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate strncpy(realmstr, realm->data, realm->length); 515*7c478bd9Sstevel@tonic-gate realmstr[realm->length] = '\0'; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (!context || (context->magic != KV5M_CONTEXT)) 518*7c478bd9Sstevel@tonic-gate return KV5M_CONTEXT; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate profile = context->profile; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate names[0] = "realms"; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate /* 525*7c478bd9Sstevel@tonic-gate * Try number one: 526*7c478bd9Sstevel@tonic-gate * 527*7c478bd9Sstevel@tonic-gate * [realms] 528*7c478bd9Sstevel@tonic-gate * REALM = { 529*7c478bd9Sstevel@tonic-gate * option = <boolean> 530*7c478bd9Sstevel@tonic-gate * } 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate names[1] = realmstr; 534*7c478bd9Sstevel@tonic-gate names[2] = option; 535*7c478bd9Sstevel@tonic-gate names[3] = 0; 536*7c478bd9Sstevel@tonic-gate retval = profile_get_values(profile, names, &nameval); 537*7c478bd9Sstevel@tonic-gate if (retval == 0 && nameval && nameval[0]) 538*7c478bd9Sstevel@tonic-gate goto goodbye; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * Try number two: 542*7c478bd9Sstevel@tonic-gate * 543*7c478bd9Sstevel@tonic-gate * [libdefaults] 544*7c478bd9Sstevel@tonic-gate * option = <boolean> 545*7c478bd9Sstevel@tonic-gate */ 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate names[0] = "libdefaults"; 548*7c478bd9Sstevel@tonic-gate names[1] = option; 549*7c478bd9Sstevel@tonic-gate names[2] = 0; 550*7c478bd9Sstevel@tonic-gate retval = profile_get_values(profile, names, &nameval); 551*7c478bd9Sstevel@tonic-gate if (retval == 0 && nameval && nameval[0]) 552*7c478bd9Sstevel@tonic-gate goto goodbye; 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate goodbye: 555*7c478bd9Sstevel@tonic-gate if (!nameval) 556*7c478bd9Sstevel@tonic-gate return(ENOENT); 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate if (!nameval[0]) { 559*7c478bd9Sstevel@tonic-gate retval = ENOENT; 560*7c478bd9Sstevel@tonic-gate } else { 561*7c478bd9Sstevel@tonic-gate *ret_value = malloc(strlen(nameval[0]) + 1); 562*7c478bd9Sstevel@tonic-gate if (!*ret_value) 563*7c478bd9Sstevel@tonic-gate retval = ENOMEM; 564*7c478bd9Sstevel@tonic-gate else 565*7c478bd9Sstevel@tonic-gate strcpy(*ret_value, nameval[0]); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate profile_free_list(nameval); 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate return retval; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate /* not static so verify_init_creds() can call it */ 574*7c478bd9Sstevel@tonic-gate /* as well as the DNS code */ 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate krb5_error_code 577*7c478bd9Sstevel@tonic-gate krb5_libdefault_boolean(context, realm, option, ret_value) 578*7c478bd9Sstevel@tonic-gate krb5_context context; 579*7c478bd9Sstevel@tonic-gate const char *option; 580*7c478bd9Sstevel@tonic-gate const krb5_data *realm; 581*7c478bd9Sstevel@tonic-gate int *ret_value; 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate char *string = NULL; 584*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate retval = krb5_libdefault_string(context, realm, option, &string); 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate if (retval) 589*7c478bd9Sstevel@tonic-gate return(retval); 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate *ret_value = _krb5_conf_boolean(string); 592*7c478bd9Sstevel@tonic-gate free(string); 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate return(0); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate KRB5_DLLIMP krb5_error_code KRB5_CALLCONV 598*7c478bd9Sstevel@tonic-gate krb5_get_init_creds(context, creds, client, prompter, prompter_data, 599*7c478bd9Sstevel@tonic-gate start_time, in_tkt_service, options, gak_fct, gak_data, 600*7c478bd9Sstevel@tonic-gate use_master, as_reply) 601*7c478bd9Sstevel@tonic-gate krb5_context context; 602*7c478bd9Sstevel@tonic-gate krb5_creds *creds; 603*7c478bd9Sstevel@tonic-gate krb5_principal client; 604*7c478bd9Sstevel@tonic-gate krb5_prompter_fct prompter; 605*7c478bd9Sstevel@tonic-gate void *prompter_data; 606*7c478bd9Sstevel@tonic-gate krb5_deltat start_time; 607*7c478bd9Sstevel@tonic-gate char *in_tkt_service; 608*7c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt *options; 609*7c478bd9Sstevel@tonic-gate krb5_gic_get_as_key_fct gak_fct; 610*7c478bd9Sstevel@tonic-gate void *gak_data; 611*7c478bd9Sstevel@tonic-gate int use_master; 612*7c478bd9Sstevel@tonic-gate krb5_kdc_rep **as_reply; 613*7c478bd9Sstevel@tonic-gate { 614*7c478bd9Sstevel@tonic-gate krb5_error_code ret; 615*7c478bd9Sstevel@tonic-gate krb5_kdc_req request; 616*7c478bd9Sstevel@tonic-gate krb5_pa_data **padata; 617*7c478bd9Sstevel@tonic-gate int tempint; 618*7c478bd9Sstevel@tonic-gate char *tempstr; 619*7c478bd9Sstevel@tonic-gate krb5_deltat renew_life; 620*7c478bd9Sstevel@tonic-gate krb5_deltat max_life; 621*7c478bd9Sstevel@tonic-gate int loopcount; 622*7c478bd9Sstevel@tonic-gate krb5_data salt; 623*7c478bd9Sstevel@tonic-gate krb5_data s2kparams; 624*7c478bd9Sstevel@tonic-gate krb5_keyblock as_key; 625*7c478bd9Sstevel@tonic-gate krb5_error *err_reply; 626*7c478bd9Sstevel@tonic-gate krb5_kdc_rep *local_as_reply; 627*7c478bd9Sstevel@tonic-gate krb5_timestamp time_now; 628*7c478bd9Sstevel@tonic-gate krb5_enctype etype = 0; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate /* initialize everything which will be freed at cleanup */ 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate s2kparams.data = NULL; 633*7c478bd9Sstevel@tonic-gate s2kparams.length = 0; 634*7c478bd9Sstevel@tonic-gate request.server = NULL; 635*7c478bd9Sstevel@tonic-gate request.ktype = NULL; 636*7c478bd9Sstevel@tonic-gate request.addresses = NULL; 637*7c478bd9Sstevel@tonic-gate request.padata = NULL; 638*7c478bd9Sstevel@tonic-gate padata = NULL; 639*7c478bd9Sstevel@tonic-gate salt.length = 0; 640*7c478bd9Sstevel@tonic-gate salt.data = NULL; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate (void) memset(&as_key, 0, sizeof(as_key)); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate local_as_reply = 0; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Set up the basic request structure 648*7c478bd9Sstevel@tonic-gate */ 649*7c478bd9Sstevel@tonic-gate request.magic = KV5M_KDC_REQ; 650*7c478bd9Sstevel@tonic-gate request.msg_type = KRB5_AS_REQ; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate /* request.padata is filled in later */ 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate request.kdc_options = context->kdc_default_options; 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* forwardable */ 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)) 659*7c478bd9Sstevel@tonic-gate tempint = options->forwardable; 660*7c478bd9Sstevel@tonic-gate else if ((ret = krb5_libdefault_boolean(context, &client->realm, 661*7c478bd9Sstevel@tonic-gate "forwardable", &tempint)) == 0) 662*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 663*7c478bd9Sstevel@tonic-gate ; 664*7c478bd9Sstevel@tonic-gate else 665*7c478bd9Sstevel@tonic-gate tempint = 0; 666*7c478bd9Sstevel@tonic-gate if (tempint) 667*7c478bd9Sstevel@tonic-gate request.kdc_options |= KDC_OPT_FORWARDABLE; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* proxiable */ 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)) 672*7c478bd9Sstevel@tonic-gate tempint = options->proxiable; 673*7c478bd9Sstevel@tonic-gate else if ((ret = krb5_libdefault_boolean(context, &client->realm, 674*7c478bd9Sstevel@tonic-gate "proxiable", &tempint)) == 0) 675*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 676*7c478bd9Sstevel@tonic-gate ; 677*7c478bd9Sstevel@tonic-gate else 678*7c478bd9Sstevel@tonic-gate tempint = 0; 679*7c478bd9Sstevel@tonic-gate if (tempint) 680*7c478bd9Sstevel@tonic-gate request.kdc_options |= KDC_OPT_PROXIABLE; 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate /* renewable */ 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)) { 685*7c478bd9Sstevel@tonic-gate renew_life = options->renew_life; 686*7c478bd9Sstevel@tonic-gate } else if ((ret = krb5_libdefault_string(context, &client->realm, 687*7c478bd9Sstevel@tonic-gate "renew_lifetime", &tempstr)) 688*7c478bd9Sstevel@tonic-gate == 0) { 689*7c478bd9Sstevel@tonic-gate if (ret = krb5_string_to_deltat(tempstr, &renew_life)) { 690*7c478bd9Sstevel@tonic-gate free(tempstr); 691*7c478bd9Sstevel@tonic-gate goto cleanup; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate } else { 694*7c478bd9Sstevel@tonic-gate renew_life = 0; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate if (renew_life > 0) 697*7c478bd9Sstevel@tonic-gate request.kdc_options |= KDC_OPT_RENEWABLE; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* allow_postdate */ 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate if (start_time > 0) 702*7c478bd9Sstevel@tonic-gate request.kdc_options |= (KDC_OPT_ALLOW_POSTDATE|KDC_OPT_POSTDATED); 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate /* client */ 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate request.client = client; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate if (in_tkt_service) { 709*7c478bd9Sstevel@tonic-gate /* this is ugly, because so are the data structures involved. I'm 710*7c478bd9Sstevel@tonic-gate in the library, so I'm going to manipulate the data structures 711*7c478bd9Sstevel@tonic-gate directly, otherwise, it will be worse. */ 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate if (ret = krb5_parse_name(context, in_tkt_service, &request.server)) 714*7c478bd9Sstevel@tonic-gate goto cleanup; 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate /* stuff the client realm into the server principal. 717*7c478bd9Sstevel@tonic-gate realloc if necessary */ 718*7c478bd9Sstevel@tonic-gate if (request.server->realm.length < request.client->realm.length) 719*7c478bd9Sstevel@tonic-gate if ((request.server->realm.data = 720*7c478bd9Sstevel@tonic-gate (char *) realloc(request.server->realm.data, 721*7c478bd9Sstevel@tonic-gate request.client->realm.length)) == NULL) { 722*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 723*7c478bd9Sstevel@tonic-gate goto cleanup; 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate request.server->realm.length = request.client->realm.length; 727*7c478bd9Sstevel@tonic-gate memcpy(request.server->realm.data, request.client->realm.data, 728*7c478bd9Sstevel@tonic-gate request.client->realm.length); 729*7c478bd9Sstevel@tonic-gate } else { 730*7c478bd9Sstevel@tonic-gate if (ret = krb5_build_principal_ext(context, &request.server, 731*7c478bd9Sstevel@tonic-gate request.client->realm.length, 732*7c478bd9Sstevel@tonic-gate request.client->realm.data, 733*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 734*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME, 735*7c478bd9Sstevel@tonic-gate request.client->realm.length, 736*7c478bd9Sstevel@tonic-gate request.client->realm.data, 737*7c478bd9Sstevel@tonic-gate 0)) 738*7c478bd9Sstevel@tonic-gate goto cleanup; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate if (ret = krb5_timeofday(context, &request.from)) 742*7c478bd9Sstevel@tonic-gate goto cleanup; 743*7c478bd9Sstevel@tonic-gate request.from += start_time; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate request.till = request.from; 746*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)) 747*7c478bd9Sstevel@tonic-gate request.till += options->tkt_life; 748*7c478bd9Sstevel@tonic-gate else if ((ret = krb5_libdefault_string(context, &client->realm, 749*7c478bd9Sstevel@tonic-gate "max_lifetime", &tempstr)) == 0) { 750*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: max_lifetime parameter support (tkt lifetime) */ 751*7c478bd9Sstevel@tonic-gate if (ret = krb5_string_to_deltat(tempstr, &max_life)) { 752*7c478bd9Sstevel@tonic-gate free(tempstr); 753*7c478bd9Sstevel@tonic-gate goto cleanup; 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate request.till += max_life; 756*7c478bd9Sstevel@tonic-gate } else { 757*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: defaulting to infinity. Note 0 == infinity (ASN1 758*7c478bd9Sstevel@tonic-gate * encoding will do the right thing). 759*7c478bd9Sstevel@tonic-gate */ 760*7c478bd9Sstevel@tonic-gate request.till = 0; 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate if (renew_life > 0) { 764*7c478bd9Sstevel@tonic-gate request.rtime = request.from; 765*7c478bd9Sstevel@tonic-gate request.rtime += renew_life; 766*7c478bd9Sstevel@tonic-gate } else { 767*7c478bd9Sstevel@tonic-gate request.rtime = 0; 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate /* nonce is filled in by send_as_request */ 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)) { 773*7c478bd9Sstevel@tonic-gate request.ktype = options->etype_list; 774*7c478bd9Sstevel@tonic-gate request.nktypes = options->etype_list_length; 775*7c478bd9Sstevel@tonic-gate } else if ((ret = krb5_get_default_in_tkt_ktypes(context, 776*7c478bd9Sstevel@tonic-gate &request.ktype)) == 0) { 777*7c478bd9Sstevel@tonic-gate for (request.nktypes = 0; 778*7c478bd9Sstevel@tonic-gate request.ktype[request.nktypes]; 779*7c478bd9Sstevel@tonic-gate request.nktypes++) 780*7c478bd9Sstevel@tonic-gate ; 781*7c478bd9Sstevel@tonic-gate } else { 782*7c478bd9Sstevel@tonic-gate /* there isn't any useful default here. ret is set from above */ 783*7c478bd9Sstevel@tonic-gate goto cleanup; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST)) { 787*7c478bd9Sstevel@tonic-gate request.addresses = options->address_list; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate /* it would be nice if this parsed out an address list, but 790*7c478bd9Sstevel@tonic-gate that would be work. */ 791*7c478bd9Sstevel@tonic-gate else if (((ret = krb5_libdefault_boolean(context, &client->realm, 792*7c478bd9Sstevel@tonic-gate "no_addresses", &tempint)) == 0) 793*7c478bd9Sstevel@tonic-gate && tempint) { 794*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 795*7c478bd9Sstevel@tonic-gate ; 796*7c478bd9Sstevel@tonic-gate } else if (((ret = krb5_libdefault_boolean(context, &client->realm, 797*7c478bd9Sstevel@tonic-gate "noaddresses", &tempint)) == 0) 798*7c478bd9Sstevel@tonic-gate && tempint) { 799*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 800*7c478bd9Sstevel@tonic-gate ; 801*7c478bd9Sstevel@tonic-gate } else { 802*7c478bd9Sstevel@tonic-gate if ((ret = krb5_os_localaddr(context, &request.addresses))) 803*7c478bd9Sstevel@tonic-gate goto cleanup; 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate request.authorization_data.ciphertext.length = 0; 807*7c478bd9Sstevel@tonic-gate request.authorization_data.ciphertext.data = 0; 808*7c478bd9Sstevel@tonic-gate request.unenc_authdata = 0; 809*7c478bd9Sstevel@tonic-gate request.second_ticket = 0; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* set up the other state. */ 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)) { 814*7c478bd9Sstevel@tonic-gate if (ret = make_preauth_list(context, options->preauth_list, 815*7c478bd9Sstevel@tonic-gate options->preauth_list_length, 816*7c478bd9Sstevel@tonic-gate &padata)) 817*7c478bd9Sstevel@tonic-gate goto cleanup; 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate /* the salt is allocated from somewhere, unless it is from the caller, 821*7c478bd9Sstevel@tonic-gate then it is a reference */ 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)) { 824*7c478bd9Sstevel@tonic-gate salt = *options->salt; 825*7c478bd9Sstevel@tonic-gate } else { 826*7c478bd9Sstevel@tonic-gate salt.length = (unsigned int)-1; 827*7c478bd9Sstevel@tonic-gate salt.data = NULL; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* now, loop processing preauth data and talking to the kdc */ 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate for (loopcount = 0; loopcount < MAX_IN_TKT_LOOPS; loopcount++) { 833*7c478bd9Sstevel@tonic-gate if (request.padata) { 834*7c478bd9Sstevel@tonic-gate krb5_free_pa_data(context, request.padata); 835*7c478bd9Sstevel@tonic-gate request.padata = NULL; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (ret = krb5_do_preauth(context, &request, 839*7c478bd9Sstevel@tonic-gate padata, &request.padata, 840*7c478bd9Sstevel@tonic-gate &salt, &s2kparams, &etype, &as_key, prompter, 841*7c478bd9Sstevel@tonic-gate prompter_data, gak_fct, gak_data)) 842*7c478bd9Sstevel@tonic-gate goto cleanup; 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate if (padata) { 845*7c478bd9Sstevel@tonic-gate krb5_free_pa_data(context, padata); 846*7c478bd9Sstevel@tonic-gate padata = 0; 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate err_reply = 0; 850*7c478bd9Sstevel@tonic-gate local_as_reply = 0; 851*7c478bd9Sstevel@tonic-gate if ((ret = send_as_request(context, &request, &time_now, &err_reply, 852*7c478bd9Sstevel@tonic-gate &local_as_reply, use_master))) 853*7c478bd9Sstevel@tonic-gate goto cleanup; 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate if (err_reply) { 856*7c478bd9Sstevel@tonic-gate if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED && 857*7c478bd9Sstevel@tonic-gate err_reply->e_data.length > 0) { 858*7c478bd9Sstevel@tonic-gate ret = decode_krb5_padata_sequence(&err_reply->e_data, 859*7c478bd9Sstevel@tonic-gate &padata); 860*7c478bd9Sstevel@tonic-gate krb5_free_error(context, err_reply); 861*7c478bd9Sstevel@tonic-gate if (ret) 862*7c478bd9Sstevel@tonic-gate goto cleanup; 863*7c478bd9Sstevel@tonic-gate } else { 864*7c478bd9Sstevel@tonic-gate ret = err_reply->error + ERROR_TABLE_BASE_krb5; 865*7c478bd9Sstevel@tonic-gate krb5_free_error(context, err_reply); 866*7c478bd9Sstevel@tonic-gate goto cleanup; 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate } else if (local_as_reply) { 869*7c478bd9Sstevel@tonic-gate break; 870*7c478bd9Sstevel@tonic-gate } else { 871*7c478bd9Sstevel@tonic-gate ret = KRB5KRB_AP_ERR_MSG_TYPE; 872*7c478bd9Sstevel@tonic-gate goto cleanup; 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if (loopcount == MAX_IN_TKT_LOOPS) { 877*7c478bd9Sstevel@tonic-gate ret = KRB5_GET_IN_TKT_LOOP; 878*7c478bd9Sstevel@tonic-gate goto cleanup; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* process any preauth data in the as_reply */ 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate if (ret = krb5_do_preauth(context, &request, 884*7c478bd9Sstevel@tonic-gate local_as_reply->padata, &padata, 885*7c478bd9Sstevel@tonic-gate &salt, &s2kparams, &etype, &as_key, prompter, 886*7c478bd9Sstevel@tonic-gate prompter_data, gak_fct, gak_data)) 887*7c478bd9Sstevel@tonic-gate goto cleanup; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate /* XXX if there's padata on output, something is wrong, but it's 890*7c478bd9Sstevel@tonic-gate not obviously an error */ 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate /* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY, 893*7c478bd9Sstevel@tonic-gate the AS_REP comes back encrypted in the user's longterm key 894*7c478bd9Sstevel@tonic-gate instead of in the SAD. If there was a SAM preauth, there 895*7c478bd9Sstevel@tonic-gate will be an as_key here which will be the SAD. If that fails, 896*7c478bd9Sstevel@tonic-gate use the gak_fct to get the password, and try again. */ 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /* XXX because etypes are handled poorly (particularly wrt SAM, 899*7c478bd9Sstevel@tonic-gate where the etype is fixed by the kdc), we may want to try 900*7c478bd9Sstevel@tonic-gate decrypt_as_reply twice. If there's an as_key available, try 901*7c478bd9Sstevel@tonic-gate it. If decrypting the as_rep fails, or if there isn't an 902*7c478bd9Sstevel@tonic-gate as_key at all yet, then use the gak_fct to get one, and try 903*7c478bd9Sstevel@tonic-gate again. */ 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate if (as_key.length) 906*7c478bd9Sstevel@tonic-gate ret = decrypt_as_reply(context, (krb5_kdc_req *)NULL, local_as_reply, 907*7c478bd9Sstevel@tonic-gate (git_key_proc)NULL, (krb5_const_pointer)NULL, 908*7c478bd9Sstevel@tonic-gate &as_key, krb5_kdc_rep_decrypt_proc, 909*7c478bd9Sstevel@tonic-gate (krb5_const_pointer)NULL); 910*7c478bd9Sstevel@tonic-gate else 911*7c478bd9Sstevel@tonic-gate ret = -1; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate if (ret) { 914*7c478bd9Sstevel@tonic-gate /* if we haven't get gotten a key, get it now */ 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate if (ret = ((*gak_fct)(context, request.client, 917*7c478bd9Sstevel@tonic-gate local_as_reply->enc_part.enctype, 918*7c478bd9Sstevel@tonic-gate prompter, prompter_data, &salt, &s2kparams, 919*7c478bd9Sstevel@tonic-gate &as_key, gak_data))) 920*7c478bd9Sstevel@tonic-gate goto cleanup; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (ret=decrypt_as_reply(context, (krb5_kdc_req *)NULL, local_as_reply, 923*7c478bd9Sstevel@tonic-gate (git_key_proc)NULL, (krb5_const_pointer)NULL, 924*7c478bd9Sstevel@tonic-gate &as_key, krb5_kdc_rep_decrypt_proc, 925*7c478bd9Sstevel@tonic-gate (krb5_const_pointer)NULL)) 926*7c478bd9Sstevel@tonic-gate goto cleanup; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate if (ret = verify_as_reply(context, time_now, &request, local_as_reply)) 930*7c478bd9Sstevel@tonic-gate goto cleanup; 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * XXX this should be inside stash_as_reply, but as long as 934*7c478bd9Sstevel@tonic-gate * get_in_tkt is still around using that arg as an in/out, I can't 935*7c478bd9Sstevel@tonic-gate * do that 936*7c478bd9Sstevel@tonic-gate */ 937*7c478bd9Sstevel@tonic-gate (void) memset(creds, 0, sizeof(*creds)); 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (ret = stash_as_reply(context, time_now, &request, local_as_reply, 940*7c478bd9Sstevel@tonic-gate creds, (krb5_ccache)NULL)) 941*7c478bd9Sstevel@tonic-gate goto cleanup; 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* success */ 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate ret = 0; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate cleanup: 948*7c478bd9Sstevel@tonic-gate if (request.server) 949*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, request.server); 950*7c478bd9Sstevel@tonic-gate if (request.ktype && 951*7c478bd9Sstevel@tonic-gate (!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)))) 952*7c478bd9Sstevel@tonic-gate free(request.ktype); 953*7c478bd9Sstevel@tonic-gate if (request.addresses && 954*7c478bd9Sstevel@tonic-gate (!(options && 955*7c478bd9Sstevel@tonic-gate (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST)))) 956*7c478bd9Sstevel@tonic-gate krb5_free_addresses(context, request.addresses); 957*7c478bd9Sstevel@tonic-gate if (padata) 958*7c478bd9Sstevel@tonic-gate krb5_free_pa_data(context, padata); 959*7c478bd9Sstevel@tonic-gate if (request.padata) 960*7c478bd9Sstevel@tonic-gate krb5_free_pa_data(context, request.padata); 961*7c478bd9Sstevel@tonic-gate if (as_key.length) 962*7c478bd9Sstevel@tonic-gate krb5_free_keyblock_contents(context, &as_key); 963*7c478bd9Sstevel@tonic-gate if (salt.data && 964*7c478bd9Sstevel@tonic-gate (!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)))) 965*7c478bd9Sstevel@tonic-gate krb5_xfree(salt.data); 966*7c478bd9Sstevel@tonic-gate if (as_reply) 967*7c478bd9Sstevel@tonic-gate *as_reply = local_as_reply; 968*7c478bd9Sstevel@tonic-gate else if (local_as_reply) 969*7c478bd9Sstevel@tonic-gate krb5_free_kdc_rep(context, local_as_reply); 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate return(ret); 972*7c478bd9Sstevel@tonic-gate } 973