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 * Copyright 2000 by the Massachusetts Institute of Technology. 10*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 13*7c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 14*7c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 15*7c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 16*7c478bd9Sstevel@tonic-gate * 17*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 18*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 19*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 20*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 21*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 22*7c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 23*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 24*7c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 25*7c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 26*7c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 27*7c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 28*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 29*7c478bd9Sstevel@tonic-gate * or implied warranty. 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, distribute, and sell this software 36*7c478bd9Sstevel@tonic-gate * and its documentation for any purpose is hereby granted without fee, 37*7c478bd9Sstevel@tonic-gate * provided that the above copyright notice appears in all copies and 38*7c478bd9Sstevel@tonic-gate * that both that copyright notice and this permission notice appear in 39*7c478bd9Sstevel@tonic-gate * supporting documentation, and that the name of OpenVision not be used 40*7c478bd9Sstevel@tonic-gate * in advertising or publicity pertaining to distribution of the software 41*7c478bd9Sstevel@tonic-gate * without specific, written prior permission. OpenVision makes no 42*7c478bd9Sstevel@tonic-gate * representations about the suitability of this software for any 43*7c478bd9Sstevel@tonic-gate * purpose. It is provided "as is" without express or implied warranty. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 46*7c478bd9Sstevel@tonic-gate * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 47*7c478bd9Sstevel@tonic-gate * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 48*7c478bd9Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 49*7c478bd9Sstevel@tonic-gate * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 50*7c478bd9Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 51*7c478bd9Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* 55*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC. 56*7c478bd9Sstevel@tonic-gate * 57*7c478bd9Sstevel@tonic-gate * All rights reserved. 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require 60*7c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the 61*7c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to 62*7c478bd9Sstevel@tonic-gate * obtain such a license before exporting. 63*7c478bd9Sstevel@tonic-gate * 64*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 65*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 66*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 67*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 68*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 69*7c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining 70*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 71*7c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of 72*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 73*7c478bd9Sstevel@tonic-gate * or implied warranty. 74*7c478bd9Sstevel@tonic-gate * 75*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 76*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 77*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #include <gssapiP_krb5.h> 81*7c478bd9Sstevel@tonic-gate #include <k5-int.h> 82*7c478bd9Sstevel@tonic-gate #include <memory.h> 83*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 84*7c478bd9Sstevel@tonic-gate #include <syslog.h> 85*7c478bd9Sstevel@tonic-gate #include <assert.h> 86*7c478bd9Sstevel@tonic-gate #define ROOT_UID 0 87*7c478bd9Sstevel@tonic-gate #define KRB5_DEFAULT_LIFE 60*60*10 88*7c478bd9Sstevel@tonic-gate #define CACHE_FILENAME_LEN 35 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* 91*7c478bd9Sstevel@tonic-gate * $Id: init_sec_context.c,v 1.51.2.7 2000/06/28 02:48:22 tlyu Exp $ 92*7c478bd9Sstevel@tonic-gate */ 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate extern int 95*7c478bd9Sstevel@tonic-gate safechown(const char *src, uid_t uid, gid_t gid, int mode); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * XXX This is for debugging only!!! Should become a real bitfield 99*7c478bd9Sstevel@tonic-gate * at some point 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate int krb5_gss_dbg_client_expcreds = 0; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Common code which fetches the correct krb5 credentials from the 105*7c478bd9Sstevel@tonic-gate * ccache. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate static krb5_error_code get_credentials(context, cred, server, now, 108*7c478bd9Sstevel@tonic-gate endtime, out_creds) 109*7c478bd9Sstevel@tonic-gate krb5_context context; 110*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 111*7c478bd9Sstevel@tonic-gate krb5_principal server; 112*7c478bd9Sstevel@tonic-gate krb5_timestamp now; 113*7c478bd9Sstevel@tonic-gate krb5_timestamp endtime; 114*7c478bd9Sstevel@tonic-gate krb5_creds **out_creds; 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate krb5_error_code code; 117*7c478bd9Sstevel@tonic-gate krb5_creds in_creds; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "get_credentials() start\n"); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate memset((char *) &in_creds, 0, sizeof(krb5_creds)); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client))) 124*7c478bd9Sstevel@tonic-gate goto cleanup; 125*7c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, server, &in_creds.server))) 126*7c478bd9Sstevel@tonic-gate goto cleanup; 127*7c478bd9Sstevel@tonic-gate in_creds.times.endtime = endtime; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate in_creds.keyblock.enctype = 0; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate code = krb5_get_credentials(context, 0, cred->ccache, 132*7c478bd9Sstevel@tonic-gate &in_creds, out_creds); 133*7c478bd9Sstevel@tonic-gate if (code) 134*7c478bd9Sstevel@tonic-gate goto cleanup; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate * Enforce a stricter limit (without timeskew forgiveness at the 138*7c478bd9Sstevel@tonic-gate * boundaries) because accept_sec_context code is also similarly 139*7c478bd9Sstevel@tonic-gate * non-forgiving. 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL && 142*7c478bd9Sstevel@tonic-gate (*out_creds)->times.endtime < now) { 143*7c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_TKT_EXPIRED; 144*7c478bd9Sstevel@tonic-gate goto cleanup; 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate cleanup: 148*7c478bd9Sstevel@tonic-gate if (in_creds.client) 149*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.client); 150*7c478bd9Sstevel@tonic-gate if (in_creds.server) 151*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.server); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_INFO, "get_credentials() end, code = %d\n", code); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate return code; 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate struct gss_checksum_data { 159*7c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx; 160*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 161*7c478bd9Sstevel@tonic-gate krb5_checksum md5; 162*7c478bd9Sstevel@tonic-gate krb5_data checksum_data; 163*7c478bd9Sstevel@tonic-gate }; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate static krb5_error_code KRB5_CALLCONV 166*7c478bd9Sstevel@tonic-gate make_gss_checksum (krb5_context context, krb5_auth_context auth_context, 167*7c478bd9Sstevel@tonic-gate void *cksum_data, krb5_data **out) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate krb5_error_code code; 170*7c478bd9Sstevel@tonic-gate krb5_int32 con_flags; 171*7c478bd9Sstevel@tonic-gate unsigned char *ptr; 172*7c478bd9Sstevel@tonic-gate struct gss_checksum_data *data = cksum_data; 173*7c478bd9Sstevel@tonic-gate krb5_data credmsg; 174*7c478bd9Sstevel@tonic-gate int junk; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate data->checksum_data.data = 0; 177*7c478bd9Sstevel@tonic-gate credmsg.data = 0; 178*7c478bd9Sstevel@tonic-gate /* build the checksum field */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate if (data->ctx->gss_flags & GSS_C_DELEG_FLAG) { 181*7c478bd9Sstevel@tonic-gate /* first get KRB_CRED message, so we know its length */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* clear the time check flag that was set in krb5_auth_con_init() */ 184*7c478bd9Sstevel@tonic-gate krb5_auth_con_getflags(context, auth_context, &con_flags); 185*7c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context, 186*7c478bd9Sstevel@tonic-gate con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate code = krb5_fwd_tgt_creds(context, auth_context, 0, 189*7c478bd9Sstevel@tonic-gate data->cred->princ, data->ctx->there, 190*7c478bd9Sstevel@tonic-gate data->cred->ccache, 1, 191*7c478bd9Sstevel@tonic-gate &credmsg); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */ 194*7c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context, con_flags); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate if (code) { 197*7c478bd9Sstevel@tonic-gate /* don't fail here; just don't accept/do the delegation 198*7c478bd9Sstevel@tonic-gate request */ 199*7c478bd9Sstevel@tonic-gate data->ctx->gss_flags &= ~GSS_C_DELEG_FLAG; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate data->checksum_data.length = 24; 202*7c478bd9Sstevel@tonic-gate } else { 203*7c478bd9Sstevel@tonic-gate if (credmsg.length+28 > KRB5_INT16_MAX) { 204*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg); 205*7c478bd9Sstevel@tonic-gate return(KRB5KRB_ERR_FIELD_TOOLONG); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate data->checksum_data.length = 28+credmsg.length; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate } else { 211*7c478bd9Sstevel@tonic-gate data->checksum_data.length = 24; 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate #ifdef CFX_EXERCISE 214*7c478bd9Sstevel@tonic-gate if (data->ctx->auth_context->keyblock->enctype == 18) { 215*7c478bd9Sstevel@tonic-gate srand(time(0) ^ getpid()); 216*7c478bd9Sstevel@tonic-gate /* Our ftp client code stupidly assumes a base64-encoded 217*7c478bd9Sstevel@tonic-gate version of the token will fit in 10K, so don't make this 218*7c478bd9Sstevel@tonic-gate too big. */ 219*7c478bd9Sstevel@tonic-gate junk = rand() & 0xff; 220*7c478bd9Sstevel@tonic-gate } else 221*7c478bd9Sstevel@tonic-gate junk = 0; 222*7c478bd9Sstevel@tonic-gate #else 223*7c478bd9Sstevel@tonic-gate junk = 0; 224*7c478bd9Sstevel@tonic-gate #endif 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate data->checksum_data.length += junk; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* now allocate a buffer to hold the checksum data and 229*7c478bd9Sstevel@tonic-gate (maybe) KRB_CRED msg */ 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if ((data->checksum_data.data = 232*7c478bd9Sstevel@tonic-gate (char *) xmalloc(data->checksum_data.length)) == NULL) { 233*7c478bd9Sstevel@tonic-gate if (credmsg.data) 234*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg); 235*7c478bd9Sstevel@tonic-gate return(ENOMEM); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate ptr = (uchar_t *)data->checksum_data.data; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->md5.length, 0); 241*7c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) data->md5.contents, data->md5.length); 242*7c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->ctx->gss_flags, 0); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* done with this, free it */ 245*7c478bd9Sstevel@tonic-gate xfree(data->md5.contents); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate if (credmsg.data) { 248*7c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, KRB5_GSS_FOR_CREDS_OPTION, 0); 249*7c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, credmsg.length, 0); 250*7c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) credmsg.data, credmsg.length); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate /* free credmsg data */ 253*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate if (junk) 256*7c478bd9Sstevel@tonic-gate memset(ptr, 'i', junk); 257*7c478bd9Sstevel@tonic-gate *out = &data->checksum_data; 258*7c478bd9Sstevel@tonic-gate return 0; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate static krb5_error_code 262*7c478bd9Sstevel@tonic-gate make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token) 263*7c478bd9Sstevel@tonic-gate krb5_context context; 264*7c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx; 265*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 266*7c478bd9Sstevel@tonic-gate krb5_creds *k_cred; 267*7c478bd9Sstevel@tonic-gate gss_channel_bindings_t chan_bindings; 268*7c478bd9Sstevel@tonic-gate gss_OID mech_type; 269*7c478bd9Sstevel@tonic-gate gss_buffer_t token; 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate krb5_flags mk_req_flags = 0; 272*7c478bd9Sstevel@tonic-gate krb5_error_code code; 273*7c478bd9Sstevel@tonic-gate struct gss_checksum_data cksum_struct; 274*7c478bd9Sstevel@tonic-gate krb5_checksum md5; 275*7c478bd9Sstevel@tonic-gate krb5_data ap_req; 276*7c478bd9Sstevel@tonic-gate krb5_data *checksum_data = NULL; 277*7c478bd9Sstevel@tonic-gate unsigned char *ptr; 278*7c478bd9Sstevel@tonic-gate unsigned char *t; 279*7c478bd9Sstevel@tonic-gate int tlen; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate ap_req.data = 0; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* build the checksum buffer */ 284*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "make_ap_req_v1() start\n"); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate /* compute the hash of the channel bindings */ 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5, 0))) 289*7c478bd9Sstevel@tonic-gate return(code); 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate krb5_auth_con_set_req_cksumtype(context, ctx->auth_context, 292*7c478bd9Sstevel@tonic-gate CKSUMTYPE_KG_CB); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate cksum_struct.md5 = md5; 295*7c478bd9Sstevel@tonic-gate cksum_struct.ctx = ctx; 296*7c478bd9Sstevel@tonic-gate cksum_struct.cred = cred; 297*7c478bd9Sstevel@tonic-gate cksum_struct.checksum_data.data = NULL; 298*7c478bd9Sstevel@tonic-gate switch (k_cred->keyblock.enctype) { 299*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_CRC: 300*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD4: 301*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD5: 302*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES3_CBC_SHA1: 303*7c478bd9Sstevel@tonic-gate code = make_gss_checksum(context, ctx->auth_context, &cksum_struct, 304*7c478bd9Sstevel@tonic-gate &checksum_data); 305*7c478bd9Sstevel@tonic-gate if (code) 306*7c478bd9Sstevel@tonic-gate goto cleanup; 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate default: 309*7c478bd9Sstevel@tonic-gate krb5_auth_con_set_checksum_func(context, ctx->auth_context, 310*7c478bd9Sstevel@tonic-gate make_gss_checksum, &cksum_struct); 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* call mk_req. subkey and ap_req need to be used or destroyed */ 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate mk_req_flags = AP_OPTS_USE_SUBKEY; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) 319*7c478bd9Sstevel@tonic-gate mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if ((code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, 322*7c478bd9Sstevel@tonic-gate checksum_data, k_cred, &ap_req))) 323*7c478bd9Sstevel@tonic-gate goto cleanup; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* store the interesting stuff from creds and authent */ 326*7c478bd9Sstevel@tonic-gate ctx->endtime = k_cred->times.endtime; 327*7c478bd9Sstevel@tonic-gate ctx->krb_flags = k_cred->ticket_flags; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* build up the token */ 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* allocate space for the token */ 332*7c478bd9Sstevel@tonic-gate tlen = g_token_size((gss_OID) mech_type, ap_req.length); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate if ((t = (unsigned char *) xmalloc(tlen)) == NULL) { 335*7c478bd9Sstevel@tonic-gate code = ENOMEM; 336*7c478bd9Sstevel@tonic-gate goto cleanup; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* fill in the buffer */ 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate ptr = t; 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate g_make_token_header((gss_OID) mech_type, ap_req.length, 344*7c478bd9Sstevel@tonic-gate &ptr, KG_TOK_CTX_AP_REQ); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) ap_req.data, ap_req.length); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* pass it back */ 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate token->length = tlen; 351*7c478bd9Sstevel@tonic-gate token->value = (void *) t; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate code = 0; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate cleanup: 356*7c478bd9Sstevel@tonic-gate /* 357*7c478bd9Sstevel@tonic-gate * We only free cksum_struct.checksum_data here, because checksum_data 358*7c478bd9Sstevel@tonic-gate * could point to cksum_struct.checksum_data or NULL. 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate if (cksum_struct.checksum_data.data) 361*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &cksum_struct.checksum_data); 362*7c478bd9Sstevel@tonic-gate if (ap_req.data) 363*7c478bd9Sstevel@tonic-gate xfree(ap_req.data); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_INFO, "make_ap_req_v1() end, code = %d\n", code); 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate return (code); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate static krb5_boolean 373*7c478bd9Sstevel@tonic-gate principal_ignore_inst_compare(context, princ1, princ2) 374*7c478bd9Sstevel@tonic-gate krb5_context context; 375*7c478bd9Sstevel@tonic-gate krb5_const_principal princ1; 376*7c478bd9Sstevel@tonic-gate krb5_const_principal princ2; 377*7c478bd9Sstevel@tonic-gate { 378*7c478bd9Sstevel@tonic-gate krb5_int32 nelem; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate nelem = krb5_princ_size(context, princ1); 381*7c478bd9Sstevel@tonic-gate if (nelem != krb5_princ_size(context, princ2)) 382*7c478bd9Sstevel@tonic-gate return FALSE; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate if (! krb5_realm_compare(context, princ1, princ2)) 385*7c478bd9Sstevel@tonic-gate return FALSE; 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * Solaris Kerberos 389*7c478bd9Sstevel@tonic-gate * If princ1 is elem1/metachar@REALM, compare just elem1 (and REALM). 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate if (nelem == 2) { 392*7c478bd9Sstevel@tonic-gate const krb5_data *p = krb5_princ_component(context, princ1, 1); 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate if (p->length == 1) { 395*7c478bd9Sstevel@tonic-gate const char *s = p->data; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (s[0] == '*') { 398*7c478bd9Sstevel@tonic-gate const krb5_data *p1 = krb5_princ_component(context, princ1, 0); 399*7c478bd9Sstevel@tonic-gate const krb5_data *p2 = krb5_princ_component(context, princ2, 0); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate if (p1->length != p2->length || 402*7c478bd9Sstevel@tonic-gate memcmp(p1->data, p2->data, p1->length)) 403*7c478bd9Sstevel@tonic-gate return FALSE; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate return TRUE; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate return FALSE; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* 414*7c478bd9Sstevel@tonic-gate * Solaris Kerberos 415*7c478bd9Sstevel@tonic-gate * This is a dup of krb5_ktfile_get_entry (sigh) but is necessary to 416*7c478bd9Sstevel@tonic-gate * to get a custom princ compare above (principal_ignore_inst_compare) 417*7c478bd9Sstevel@tonic-gate * and thus avoid mucking w/important krb5 internal 418*7c478bd9Sstevel@tonic-gate * api (krb5_principal_compare) 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate #include "../krb5/keytab/file/ktfile.h" 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate static krb5_error_code KRB5_CALLCONV 423*7c478bd9Sstevel@tonic-gate ktfile_get_entry(context, id, principal, kvno, enctype, entry) 424*7c478bd9Sstevel@tonic-gate krb5_context context; 425*7c478bd9Sstevel@tonic-gate krb5_keytab id; 426*7c478bd9Sstevel@tonic-gate krb5_const_principal principal; 427*7c478bd9Sstevel@tonic-gate krb5_kvno kvno; 428*7c478bd9Sstevel@tonic-gate krb5_enctype enctype; 429*7c478bd9Sstevel@tonic-gate krb5_keytab_entry * entry; 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate krb5_keytab_entry cur_entry, new_entry; 432*7c478bd9Sstevel@tonic-gate krb5_error_code kerror = 0; 433*7c478bd9Sstevel@tonic-gate int found_wrong_kvno = 0; 434*7c478bd9Sstevel@tonic-gate krb5_boolean similar; 435*7c478bd9Sstevel@tonic-gate int kvno_offset = 0; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() start\n"); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* Open the keyfile for reading */ 440*7c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_openr(context, id))){ 441*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "ktfile_get_entry() end, ktfileint_openr() " 442*7c478bd9Sstevel@tonic-gate "kerror= %d\n", kerror); 443*7c478bd9Sstevel@tonic-gate return(kerror); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * For efficiency and simplicity, we'll use a while true that 448*7c478bd9Sstevel@tonic-gate * is exited with a break statement. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate cur_entry.principal = 0; 451*7c478bd9Sstevel@tonic-gate cur_entry.vno = 0; 452*7c478bd9Sstevel@tonic-gate cur_entry.key.contents = 0; 453*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 454*7c478bd9Sstevel@tonic-gate while (TRUE) { 455*7c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry))) 456*7c478bd9Sstevel@tonic-gate break; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * by the time this loop exits, it must either free cur_entry, 460*7c478bd9Sstevel@tonic-gate * and copy new_entry there, or free new_entry. Otherwise, it 461*7c478bd9Sstevel@tonic-gate * leaks. 462*7c478bd9Sstevel@tonic-gate */ 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate /* 465*7c478bd9Sstevel@tonic-gate * if the principal isn't the one requested, free new_entry 466*7c478bd9Sstevel@tonic-gate * and continue to the next. 467*7c478bd9Sstevel@tonic-gate */ 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (!principal_ignore_inst_compare(context, principal, 470*7c478bd9Sstevel@tonic-gate new_entry.principal)) { 471*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry); 472*7c478bd9Sstevel@tonic-gate continue; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * if the enctype is not ignored and doesn't match, free new_entry 477*7c478bd9Sstevel@tonic-gate * and continue to the next 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate if (enctype != IGNORE_ENCTYPE) { 481*7c478bd9Sstevel@tonic-gate if ((kerror = krb5_c_enctype_compare(context, enctype, 482*7c478bd9Sstevel@tonic-gate new_entry.key.enctype, 483*7c478bd9Sstevel@tonic-gate &similar))) { 484*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry); 485*7c478bd9Sstevel@tonic-gate break; 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate if (!similar) { 489*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry); 490*7c478bd9Sstevel@tonic-gate continue; 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate /* 493*7c478bd9Sstevel@tonic-gate * Coerce the enctype of the output keyblock in case we 494*7c478bd9Sstevel@tonic-gate * got an inexact match on the enctype. 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate new_entry.key.enctype = enctype; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (kvno == IGNORE_VNO) { 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * if this is the first match, or if the new vno is 502*7c478bd9Sstevel@tonic-gate * bigger, free the current and keep the new. Otherwise, 503*7c478bd9Sstevel@tonic-gate * free the new. 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate /* 506*7c478bd9Sstevel@tonic-gate * A 1.2.x keytab contains only the low 8 bits of the key 507*7c478bd9Sstevel@tonic-gate * version number. Since it can be much bigger, and thus 508*7c478bd9Sstevel@tonic-gate * the 8-bit value can wrap, we need some heuristics to 509*7c478bd9Sstevel@tonic-gate * figure out the "highest" numbered key if some numbers 510*7c478bd9Sstevel@tonic-gate * close to 255 and some near 0 are used. 511*7c478bd9Sstevel@tonic-gate * 512*7c478bd9Sstevel@tonic-gate * The heuristic here: 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate * If we have any keys with versions over 240, then assume 515*7c478bd9Sstevel@tonic-gate * that all version numbers 0-127 refer to 256+N instead. 516*7c478bd9Sstevel@tonic-gate * Not perfect, but maybe good enough? 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate #define M(VNO) (((VNO) - kvno_offset + 256) % 256) 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate if (new_entry.vno > 240) 522*7c478bd9Sstevel@tonic-gate kvno_offset = 128; 523*7c478bd9Sstevel@tonic-gate if (! cur_entry.principal || 524*7c478bd9Sstevel@tonic-gate M(new_entry.vno) > M(cur_entry.vno)) { 525*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry); 526*7c478bd9Sstevel@tonic-gate cur_entry = new_entry; 527*7c478bd9Sstevel@tonic-gate } else { 528*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate } else { 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * if this kvno matches, free the current (will there ever 533*7c478bd9Sstevel@tonic-gate * be one?), keep the new, and break out. Otherwise, remember 534*7c478bd9Sstevel@tonic-gate * that we were here so we can return the right error, and 535*7c478bd9Sstevel@tonic-gate * free the new 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * Yuck. The krb5-1.2.x keytab format only stores one byte 539*7c478bd9Sstevel@tonic-gate * for the kvno, so we're toast if the kvno requested is 540*7c478bd9Sstevel@tonic-gate * higher than that. Short-term workaround: only compare 541*7c478bd9Sstevel@tonic-gate * the low 8 bits. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate if (new_entry.vno == (kvno & 0xff)) { 545*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry); 546*7c478bd9Sstevel@tonic-gate cur_entry = new_entry; 547*7c478bd9Sstevel@tonic-gate break; 548*7c478bd9Sstevel@tonic-gate } else { 549*7c478bd9Sstevel@tonic-gate found_wrong_kvno++; 550*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (kerror == KRB5_KT_END) { 556*7c478bd9Sstevel@tonic-gate if (cur_entry.principal) 557*7c478bd9Sstevel@tonic-gate kerror = 0; 558*7c478bd9Sstevel@tonic-gate else if (found_wrong_kvno) 559*7c478bd9Sstevel@tonic-gate kerror = KRB5_KT_KVNONOTFOUND; 560*7c478bd9Sstevel@tonic-gate else 561*7c478bd9Sstevel@tonic-gate kerror = KRB5_KT_NOTFOUND; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate if (kerror) { 564*7c478bd9Sstevel@tonic-gate (void) krb5_ktfileint_close(context, id); 565*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry); 566*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, kerror=" 567*7c478bd9Sstevel@tonic-gate "%d\n", kerror); 568*7c478bd9Sstevel@tonic-gate return kerror; 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_close(context, id)) != 0) { 571*7c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry); 572*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, ktfileint_close() " 573*7c478bd9Sstevel@tonic-gate "kerror= %d\n", kerror); 574*7c478bd9Sstevel@tonic-gate return kerror; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate *entry = cur_entry; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* Let us close the file before we leave */ 579*7c478bd9Sstevel@tonic-gate (void) krb5_ktfileint_close(context, id); 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() end"); 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate return 0; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate /* 588*7c478bd9Sstevel@tonic-gate * Solaris Kerberos 589*7c478bd9Sstevel@tonic-gate * Given a princ of name/instance@LOCALREALM, search the keytab 590*7c478bd9Sstevel@tonic-gate * for a match of name and LOCALREALM and if found, return instance 591*7c478bd9Sstevel@tonic-gate * as a string. 592*7c478bd9Sstevel@tonic-gate * 593*7c478bd9Sstevel@tonic-gate * Caller must free returned string. 594*7c478bd9Sstevel@tonic-gate */ 595*7c478bd9Sstevel@tonic-gate static krb5_error_code 596*7c478bd9Sstevel@tonic-gate get_instance_keytab( 597*7c478bd9Sstevel@tonic-gate krb5_context context, 598*7c478bd9Sstevel@tonic-gate const char *sname, 599*7c478bd9Sstevel@tonic-gate krb5_keytab keytab, 600*7c478bd9Sstevel@tonic-gate char **instance) /* out */ 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate krb5_error_code ret=0; 603*7c478bd9Sstevel@tonic-gate krb5_keytab_entry kt_ent; 604*7c478bd9Sstevel@tonic-gate krb5_int32 nelem, free_kt_ent=0; 605*7c478bd9Sstevel@tonic-gate register const krb5_data *p; 606*7c478bd9Sstevel@tonic-gate char *realm=NULL, *s=NULL; 607*7c478bd9Sstevel@tonic-gate krb5_principal client=NULL, princ=NULL; 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate if (!keytab) 610*7c478bd9Sstevel@tonic-gate return EINVAL; 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate if (ret = krb5_get_default_realm(context, &realm)) 613*7c478bd9Sstevel@tonic-gate return ret; 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate ret = krb5_build_principal(context, &client, strlen(realm), 616*7c478bd9Sstevel@tonic-gate realm, sname, "*", 617*7c478bd9Sstevel@tonic-gate (char *)0); 618*7c478bd9Sstevel@tonic-gate if (ret) 619*7c478bd9Sstevel@tonic-gate goto out; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate ret = ktfile_get_entry(context, keytab, client, 622*7c478bd9Sstevel@tonic-gate 0, /* don't have vno available */ 623*7c478bd9Sstevel@tonic-gate 0, &kt_ent); 624*7c478bd9Sstevel@tonic-gate if (ret) 625*7c478bd9Sstevel@tonic-gate goto out; 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate free_kt_ent++; /* kt_ent is not a ptr */ 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate princ = kt_ent.principal; 630*7c478bd9Sstevel@tonic-gate nelem = krb5_princ_size(context, princ); 631*7c478bd9Sstevel@tonic-gate if (nelem != 2) { 632*7c478bd9Sstevel@tonic-gate ret = KRB5_PRINC_NOMATCH; 633*7c478bd9Sstevel@tonic-gate goto out; 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate p = krb5_princ_component(context, princ, 1); 637*7c478bd9Sstevel@tonic-gate s = calloc(p->length + sizeof(char), sizeof(char)); 638*7c478bd9Sstevel@tonic-gate if (!s) { 639*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 640*7c478bd9Sstevel@tonic-gate goto out; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate (void) memcpy(s, p->data, p->length); 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate out: 647*7c478bd9Sstevel@tonic-gate free(realm); 648*7c478bd9Sstevel@tonic-gate if (client) 649*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, client); 650*7c478bd9Sstevel@tonic-gate if (free_kt_ent) 651*7c478bd9Sstevel@tonic-gate (void) krb5_kt_free_entry(context, &kt_ent); 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (ret == 0) 654*7c478bd9Sstevel@tonic-gate *instance = s; 655*7c478bd9Sstevel@tonic-gate return ret; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate static OM_uint32 659*7c478bd9Sstevel@tonic-gate load_root_cred_using_keytab( 660*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status, 661*7c478bd9Sstevel@tonic-gate krb5_context context, 662*7c478bd9Sstevel@tonic-gate const char *sname, 663*7c478bd9Sstevel@tonic-gate int use_nodename) 664*7c478bd9Sstevel@tonic-gate { 665*7c478bd9Sstevel@tonic-gate krb5_creds my_creds; 666*7c478bd9Sstevel@tonic-gate krb5_principal me; 667*7c478bd9Sstevel@tonic-gate krb5_principal server; 668*7c478bd9Sstevel@tonic-gate krb5_error_code code; 669*7c478bd9Sstevel@tonic-gate krb5_ccache ccache = NULL; 670*7c478bd9Sstevel@tonic-gate krb5_keytab keytab = NULL; 671*7c478bd9Sstevel@tonic-gate krb5_timestamp now; 672*7c478bd9Sstevel@tonic-gate krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */ 673*7c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opt; 674*7c478bd9Sstevel@tonic-gate krb5_data tgtname = { 675*7c478bd9Sstevel@tonic-gate 0, 676*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 677*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 678*7c478bd9Sstevel@tonic-gate }; 679*7c478bd9Sstevel@tonic-gate char *svcname = NULL; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() start \n"); 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate if (!sname) 684*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate memset((char *)&my_creds, 0, sizeof(my_creds)); 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate if (code = krb5_kt_default(context, &keytab)) { 689*7c478bd9Sstevel@tonic-gate *minor_status = code; 690*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate if (!use_nodename) { 694*7c478bd9Sstevel@tonic-gate char *instance = NULL; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate code = get_instance_keytab(context, sname, keytab, &instance); 697*7c478bd9Sstevel@tonic-gate if (code == 0) { 698*7c478bd9Sstevel@tonic-gate code = krb5_sname_to_principal(context, 699*7c478bd9Sstevel@tonic-gate instance, sname, 700*7c478bd9Sstevel@tonic-gate KRB5_NT_UNKNOWN, &me); 701*7c478bd9Sstevel@tonic-gate free(instance); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate } else { 704*7c478bd9Sstevel@tonic-gate code = krb5_sname_to_principal(context, NULL, sname, 705*7c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &me); 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate if (code) { 708*7c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab); 709*7c478bd9Sstevel@tonic-gate *minor_status = code; 710*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate my_creds.client = me; 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate if((code = krb5_build_principal_ext(context, &server, 715*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length, 716*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data, 717*7c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 718*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length, 719*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data, 720*7c478bd9Sstevel@tonic-gate 0))) { 721*7c478bd9Sstevel@tonic-gate *minor_status = code; 722*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 723*7c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab); 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate my_creds.server = server; 729*7c478bd9Sstevel@tonic-gate my_creds.times.starttime = 0; /* start timer 730*7c478bd9Sstevel@tonic-gate * when request 731*7c478bd9Sstevel@tonic-gate * gets to KDC 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) { 734*7c478bd9Sstevel@tonic-gate *minor_status = code; 735*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 736*7c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab); 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate my_creds.times.endtime = now + lifetime; 741*7c478bd9Sstevel@tonic-gate my_creds.times.renew_till = 0; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate memset(&opt, 0, sizeof (opt)); 744*7c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opt); 745*7c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opt, lifetime); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate code = krb5_unparse_name(context, server, &svcname); 748*7c478bd9Sstevel@tonic-gate if (code != 0) { 749*7c478bd9Sstevel@tonic-gate *minor_status = code; 750*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 751*7c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab); 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate code = krb5_get_init_creds_keytab(context, 756*7c478bd9Sstevel@tonic-gate &my_creds, me, keytab, 757*7c478bd9Sstevel@tonic-gate 0, svcname, &opt); 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab); 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate if (svcname != NULL) 762*7c478bd9Sstevel@tonic-gate free(svcname); 763*7c478bd9Sstevel@tonic-gate if (code) { 764*7c478bd9Sstevel@tonic-gate *minor_status = code; 765*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate code = krb5_cc_resolve (context, 770*7c478bd9Sstevel@tonic-gate krb5_cc_default_name(context), 771*7c478bd9Sstevel@tonic-gate &ccache); 772*7c478bd9Sstevel@tonic-gate if (code != 0) { 773*7c478bd9Sstevel@tonic-gate *minor_status = code; 774*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate code = krb5_cc_initialize (context, ccache, me); 779*7c478bd9Sstevel@tonic-gate if (code != 0) { 780*7c478bd9Sstevel@tonic-gate *minor_status = code; 781*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 782*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate code = krb5_cc_store_cred(context, ccache, 788*7c478bd9Sstevel@tonic-gate &my_creds); 789*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds); 790*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate if (code) { 793*7c478bd9Sstevel@tonic-gate *minor_status = code; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "load_root_cred_using_keytab() end, error " 796*7c478bd9Sstevel@tonic-gate "code = %d\n", code); 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() end \n"); 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate static OM_uint32 807*7c478bd9Sstevel@tonic-gate renew_ccache(OM_uint32 *minor_status, krb5_context context, uid_t uid) 808*7c478bd9Sstevel@tonic-gate { 809*7c478bd9Sstevel@tonic-gate krb5_principal me; 810*7c478bd9Sstevel@tonic-gate krb5_principal server; 811*7c478bd9Sstevel@tonic-gate krb5_creds creds; 812*7c478bd9Sstevel@tonic-gate krb5_creds tmpcreds; 813*7c478bd9Sstevel@tonic-gate krb5_creds *out_creds; 814*7c478bd9Sstevel@tonic-gate krb5_error_code code; 815*7c478bd9Sstevel@tonic-gate krb5_ccache ccache = NULL; 816*7c478bd9Sstevel@tonic-gate static char ccache_name_buf[CACHE_FILENAME_LEN]; 817*7c478bd9Sstevel@tonic-gate int options = 0; 818*7c478bd9Sstevel@tonic-gate krb5_data tgtname = { 819*7c478bd9Sstevel@tonic-gate 0, 820*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 821*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 822*7c478bd9Sstevel@tonic-gate }; 823*7c478bd9Sstevel@tonic-gate gid_t gid = getgid(); 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate memset((char *)&creds, 0, sizeof(creds)); 826*7c478bd9Sstevel@tonic-gate memset((char *)&tmpcreds, 0, sizeof(creds)); 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate if ((code = krb5_cc_default(context, &ccache))) { 829*7c478bd9Sstevel@tonic-gate *minor_status = code; 830*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 831*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if ((code = krb5_cc_get_principal(context, ccache, &me)) != 0) { 835*7c478bd9Sstevel@tonic-gate *minor_status = code; 836*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 837*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate creds.client = me; 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate if((code = krb5_build_principal_ext(context, &server, 843*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length, 844*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data, 845*7c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 846*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length, 847*7c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data, 848*7c478bd9Sstevel@tonic-gate 0))) { 849*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, me); 850*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 851*7c478bd9Sstevel@tonic-gate *minor_status = code; 852*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate creds.server = server; 856*7c478bd9Sstevel@tonic-gate creds.ticket_flags = TKT_FLG_RENEWABLE; 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate if ((krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_FLAGS, 859*7c478bd9Sstevel@tonic-gate &creds, &tmpcreds))) { 860*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 861*7c478bd9Sstevel@tonic-gate return (KDC_ERR_BADOPTION); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate creds.ticket_flags = 0; 865*7c478bd9Sstevel@tonic-gate code = krb5_get_credentials_renew(context, options, ccache, 866*7c478bd9Sstevel@tonic-gate &creds, &out_creds); 867*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &creds); 868*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &tmpcreds); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate if (code) { 871*7c478bd9Sstevel@tonic-gate *minor_status = code; 872*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate krb5_free_creds(context, out_creds); 876*7c478bd9Sstevel@tonic-gate snprintf(ccache_name_buf, CACHE_FILENAME_LEN, "/tmp/krb5cc_%d", 877*7c478bd9Sstevel@tonic-gate uid, -1); 878*7c478bd9Sstevel@tonic-gate code = safechown(ccache_name_buf, uid, gid, -1); 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate if (code == -1) { 881*7c478bd9Sstevel@tonic-gate (void) krb5_cc_destroy(context, ccache); 882*7c478bd9Sstevel@tonic-gate *minor_status = code; 883*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache); 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate /* 893*7c478bd9Sstevel@tonic-gate * Solaris Kerberos: 894*7c478bd9Sstevel@tonic-gate * We enforce a minimum refresh time on the root cred. This avoids problems for 895*7c478bd9Sstevel@tonic-gate * the higher level communication protocol for having valid creds and 896*7c478bd9Sstevel@tonic-gate * setting up a valid context, only to have it expire before or while 897*7c478bd9Sstevel@tonic-gate * it is being used. For non root users we don't care since we do not refresh 898*7c478bd9Sstevel@tonic-gate * there creds, they get what they can get. 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate #define MIN_REFRESH_TIME 300 901*7c478bd9Sstevel@tonic-gate #define MIN_RENEW_TIME 1500 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate /* get_default_cred() must be called with the krb5_mutex lock held */ 904*7c478bd9Sstevel@tonic-gate static OM_uint32 905*7c478bd9Sstevel@tonic-gate get_default_cred(OM_uint32 *minor_status, void *ct, gss_cred_id_t *cred_handle) 906*7c478bd9Sstevel@tonic-gate { 907*7c478bd9Sstevel@tonic-gate krb5_timestamp now; 908*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 909*7c478bd9Sstevel@tonic-gate OM_uint32 major; 910*7c478bd9Sstevel@tonic-gate OM_uint32 mntmp; 911*7c478bd9Sstevel@tonic-gate uid_t uid = getuid(); 912*7c478bd9Sstevel@tonic-gate krb5_context context = (krb5_context)ct; 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "get_default_cred() start\n"); 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate /* Get the default cred for user */ 917*7c478bd9Sstevel@tonic-gate if (((major = kg_get_defcred(minor_status, cred_handle)) != NULL) && 918*7c478bd9Sstevel@tonic-gate GSS_ERROR(major)) { 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate /* If we're not root we're done */ 921*7c478bd9Sstevel@tonic-gate if (uid != ROOT_UID) 922*7c478bd9Sstevel@tonic-gate return (major); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate /* 925*7c478bd9Sstevel@tonic-gate * Try and get root's cred in the cache using keytab. 926*7c478bd9Sstevel@tonic-gate * 927*7c478bd9Sstevel@tonic-gate * First try "root" and then try "host" - this allows 928*7c478bd9Sstevel@tonic-gate * Secure NFS to use the host principal for mounting if 929*7c478bd9Sstevel@tonic-gate * there is no root principal. 930*7c478bd9Sstevel@tonic-gate * 931*7c478bd9Sstevel@tonic-gate * Then try "host/<anything>" to match any instance (needed 932*7c478bd9Sstevel@tonic-gate * for DHCP clients). 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 935*7c478bd9Sstevel@tonic-gate context, "root", 1); 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 938*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 939*7c478bd9Sstevel@tonic-gate context, "host", 1); 940*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 941*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 942*7c478bd9Sstevel@tonic-gate context, "host", 0); 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 945*7c478bd9Sstevel@tonic-gate return (major); 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate /* We should have valid tgt now in the cache, so get it. */ 948*7c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle); 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate return (major); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate /* We've got a gss cred handle that is a kerberos cred handle. */ 954*7c478bd9Sstevel@tonic-gate cred = (krb5_gss_cred_id_t)*cred_handle; 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate /* If we can't get the time, assume the worst. */ 957*7c478bd9Sstevel@tonic-gate if (krb5_timeofday(context, &now)) { 958*7c478bd9Sstevel@tonic-gate (void) krb5_gss_release_cred_no_lock(ct, &mntmp, cred_handle); 959*7c478bd9Sstevel@tonic-gate return (GSS_S_CREDENTIALS_EXPIRED); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate /* If root's cred has expired re-get it */ 963*7c478bd9Sstevel@tonic-gate if (cred->tgt_expire < now + MIN_REFRESH_TIME && uid == ROOT_UID) { 964*7c478bd9Sstevel@tonic-gate (void) krb5_gss_release_cred_no_lock(ct, &mntmp, cred_handle); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 967*7c478bd9Sstevel@tonic-gate context, "root", 1); 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 970*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 971*7c478bd9Sstevel@tonic-gate context, "host", 1); 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 974*7c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status, 975*7c478bd9Sstevel@tonic-gate context, "host", 0); 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 978*7c478bd9Sstevel@tonic-gate return (major); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle); 981*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 982*7c478bd9Sstevel@tonic-gate return (major); 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate /* Any body else is SOL unless we can renew their credential cache */ 985*7c478bd9Sstevel@tonic-gate } else if ((cred->tgt_expire < now + MIN_RENEW_TIME) && 986*7c478bd9Sstevel@tonic-gate (cred->tgt_expire > now)) { 987*7c478bd9Sstevel@tonic-gate (void) krb5_gss_release_cred_no_lock(ct, &mntmp, cred_handle); 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate major = renew_ccache(minor_status, context, uid); 990*7c478bd9Sstevel@tonic-gate if ((major != GSS_S_COMPLETE) && 991*7c478bd9Sstevel@tonic-gate (major != KDC_ERR_BADOPTION)) 992*7c478bd9Sstevel@tonic-gate return (major); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle); 995*7c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 996*7c478bd9Sstevel@tonic-gate return (major); 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate /* Otherwise we got non expired creds */ 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "get_default_cred() end\n"); 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 1005*7c478bd9Sstevel@tonic-gate } 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate /* 1008*7c478bd9Sstevel@tonic-gate * setup_enc 1009*7c478bd9Sstevel@tonic-gate * 1010*7c478bd9Sstevel@tonic-gate * Fill in the encryption descriptors. Called after AP-REQ is made. 1011*7c478bd9Sstevel@tonic-gate */ 1012*7c478bd9Sstevel@tonic-gate static OM_uint32 1013*7c478bd9Sstevel@tonic-gate setup_enc( 1014*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status, 1015*7c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx, 1016*7c478bd9Sstevel@tonic-gate krb5_context context) 1017*7c478bd9Sstevel@tonic-gate { 1018*7c478bd9Sstevel@tonic-gate krb5_error_code code; 1019*7c478bd9Sstevel@tonic-gate OM_uint32 ret = GSS_S_COMPLETE; 1020*7c478bd9Sstevel@tonic-gate int i; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate ctx->have_acceptor_subkey = 0; 1023*7c478bd9Sstevel@tonic-gate ctx->proto = 0; 1024*7c478bd9Sstevel@tonic-gate ctx->cksumtype = 0; 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "setup_enc() enctype = %d\n", 1027*7c478bd9Sstevel@tonic-gate ctx->subkey->enctype); 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate switch(ctx->subkey->enctype) { 1030*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD5: 1031*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD4: 1032*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_CRC: 1033*7c478bd9Sstevel@tonic-gate ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; 1034*7c478bd9Sstevel@tonic-gate ctx->signalg = SGN_ALG_DES_MAC_MD5; 1035*7c478bd9Sstevel@tonic-gate ctx->cksum_size = 8; 1036*7c478bd9Sstevel@tonic-gate ctx->sealalg = SEAL_ALG_DES; 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /* The encryption key is the session key XOR 1039*7c478bd9Sstevel@tonic-gate 0xf0f0f0f0f0f0f0f0. */ 1040*7c478bd9Sstevel@tonic-gate if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) 1041*7c478bd9Sstevel@tonic-gate goto fail; 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate for (i=0; i<ctx->enc->length; i++) 1044*7c478bd9Sstevel@tonic-gate ctx->enc->contents[i] ^= 0xf0; 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate goto copy_subkey_to_seq; 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate case ENCTYPE_DES3_CBC_SHA1: 1049*7c478bd9Sstevel@tonic-gate /* MIT extension */ 1050*7c478bd9Sstevel@tonic-gate ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; 1051*7c478bd9Sstevel@tonic-gate ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; 1052*7c478bd9Sstevel@tonic-gate ctx->cksum_size = 20; 1053*7c478bd9Sstevel@tonic-gate ctx->sealalg = SEAL_ALG_DES3KD; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate copy_subkey: 1056*7c478bd9Sstevel@tonic-gate code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc); 1057*7c478bd9Sstevel@tonic-gate if (code) 1058*7c478bd9Sstevel@tonic-gate goto fail; 1059*7c478bd9Sstevel@tonic-gate copy_subkey_to_seq: 1060*7c478bd9Sstevel@tonic-gate code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq); 1061*7c478bd9Sstevel@tonic-gate if (code) { 1062*7c478bd9Sstevel@tonic-gate krb5_free_keyblock (context, ctx->enc); 1063*7c478bd9Sstevel@tonic-gate goto fail; 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate break; 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate case ENCTYPE_ARCFOUR_HMAC: 1068*7c478bd9Sstevel@tonic-gate /* Microsoft extension */ 1069*7c478bd9Sstevel@tonic-gate ctx->signalg = SGN_ALG_HMAC_MD5 ; 1070*7c478bd9Sstevel@tonic-gate ctx->cksum_size = 8; 1071*7c478bd9Sstevel@tonic-gate ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate goto copy_subkey; 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate default: 1076*7c478bd9Sstevel@tonic-gate /* Fill some fields we shouldn't be using on this path 1077*7c478bd9Sstevel@tonic-gate with garbage. */ 1078*7c478bd9Sstevel@tonic-gate ctx->signalg = -10; 1079*7c478bd9Sstevel@tonic-gate ctx->sealalg = -10; 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate ctx->proto = 1; 1082*7c478bd9Sstevel@tonic-gate code = krb5int_c_mandatory_cksumtype(context, ctx->subkey->enctype, 1083*7c478bd9Sstevel@tonic-gate &ctx->cksumtype); 1084*7c478bd9Sstevel@tonic-gate if (code) 1085*7c478bd9Sstevel@tonic-gate goto fail; 1086*7c478bd9Sstevel@tonic-gate code = krb5_c_checksum_length(context, ctx->cksumtype, 1087*7c478bd9Sstevel@tonic-gate (size_t *)&ctx->cksum_size); 1088*7c478bd9Sstevel@tonic-gate if (code) 1089*7c478bd9Sstevel@tonic-gate goto fail; 1090*7c478bd9Sstevel@tonic-gate goto copy_subkey; 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate fail: 1093*7c478bd9Sstevel@tonic-gate if (code) { 1094*7c478bd9Sstevel@tonic-gate *minor_status = code; 1095*7c478bd9Sstevel@tonic-gate ret = GSS_S_FAILURE; 1096*7c478bd9Sstevel@tonic-gate } 1097*7c478bd9Sstevel@tonic-gate success: 1098*7c478bd9Sstevel@tonic-gate return (ret); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate /* 1102*7c478bd9Sstevel@tonic-gate * new_connection 1103*7c478bd9Sstevel@tonic-gate * 1104*7c478bd9Sstevel@tonic-gate * Do the grunt work of setting up a new context. 1105*7c478bd9Sstevel@tonic-gate */ 1106*7c478bd9Sstevel@tonic-gate static OM_uint32 1107*7c478bd9Sstevel@tonic-gate new_connection( 1108*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status, 1109*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred, 1110*7c478bd9Sstevel@tonic-gate gss_ctx_id_t *context_handle, 1111*7c478bd9Sstevel@tonic-gate gss_name_t target_name, 1112*7c478bd9Sstevel@tonic-gate gss_OID mech_type, 1113*7c478bd9Sstevel@tonic-gate OM_uint32 req_flags, 1114*7c478bd9Sstevel@tonic-gate OM_uint32 time_req, 1115*7c478bd9Sstevel@tonic-gate gss_channel_bindings_t input_chan_bindings, 1116*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, 1117*7c478bd9Sstevel@tonic-gate gss_OID *actual_mech_type, 1118*7c478bd9Sstevel@tonic-gate gss_buffer_t output_token, 1119*7c478bd9Sstevel@tonic-gate OM_uint32 *ret_flags, 1120*7c478bd9Sstevel@tonic-gate OM_uint32 *time_rec, 1121*7c478bd9Sstevel@tonic-gate krb5_context context, 1122*7c478bd9Sstevel@tonic-gate int default_mech) 1123*7c478bd9Sstevel@tonic-gate { 1124*7c478bd9Sstevel@tonic-gate OM_uint32 major_status; 1125*7c478bd9Sstevel@tonic-gate krb5_error_code code; 1126*7c478bd9Sstevel@tonic-gate krb5_creds *k_cred; 1127*7c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx, *ctx_free; 1128*7c478bd9Sstevel@tonic-gate krb5_timestamp now; 1129*7c478bd9Sstevel@tonic-gate gss_buffer_desc token; 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate major_status = GSS_S_FAILURE; 1132*7c478bd9Sstevel@tonic-gate token.length = 0; 1133*7c478bd9Sstevel@tonic-gate token.value = NULL; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate /* make sure the cred is usable for init */ 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate if ((cred->usage != GSS_C_INITIATE) && 1138*7c478bd9Sstevel@tonic-gate (cred->usage != GSS_C_BOTH)) { 1139*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1140*7c478bd9Sstevel@tonic-gate return(GSS_S_NO_CRED); 1141*7c478bd9Sstevel@tonic-gate } 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate /* complain if the input token is non-null */ 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) { 1146*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1147*7c478bd9Sstevel@tonic-gate return(GSS_S_DEFECTIVE_TOKEN); 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate /* create the ctx */ 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec))) 1153*7c478bd9Sstevel@tonic-gate == NULL) { 1154*7c478bd9Sstevel@tonic-gate *minor_status = ENOMEM; 1155*7c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate 1158*7c478bd9Sstevel@tonic-gate /* fill in the ctx */ 1159*7c478bd9Sstevel@tonic-gate memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); 1160*7c478bd9Sstevel@tonic-gate ctx_free = ctx; 1161*7c478bd9Sstevel@tonic-gate if ((code = krb5_auth_con_init(context, &ctx->auth_context))) 1162*7c478bd9Sstevel@tonic-gate goto fail; 1163*7c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, ctx->auth_context, 1164*7c478bd9Sstevel@tonic-gate KRB5_AUTH_CONTEXT_DO_SEQUENCE); 1165*7c478bd9Sstevel@tonic-gate ctx->initiate = 1; 1166*7c478bd9Sstevel@tonic-gate ctx->gss_flags = (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | 1167*7c478bd9Sstevel@tonic-gate GSS_C_TRANS_FLAG | GSS_C_PROT_READY_FLAG | 1168*7c478bd9Sstevel@tonic-gate ((req_flags) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | 1169*7c478bd9Sstevel@tonic-gate GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG))); 1170*7c478bd9Sstevel@tonic-gate ctx->seed_init = 0; 1171*7c478bd9Sstevel@tonic-gate ctx->big_endian = 0; /* all initiators do little-endian, as per spec */ 1172*7c478bd9Sstevel@tonic-gate ctx->seqstate = 0; 1173*7c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) 1174*7c478bd9Sstevel@tonic-gate goto fail; 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate if (time_req == 0 || time_req == GSS_C_INDEFINITE) { 1177*7c478bd9Sstevel@tonic-gate ctx->endtime = 0; 1178*7c478bd9Sstevel@tonic-gate } else { 1179*7c478bd9Sstevel@tonic-gate ctx->endtime = now + time_req; 1180*7c478bd9Sstevel@tonic-gate } 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) 1183*7c478bd9Sstevel@tonic-gate goto fail; 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, (krb5_principal) target_name, 1186*7c478bd9Sstevel@tonic-gate &ctx->there))) 1187*7c478bd9Sstevel@tonic-gate goto fail; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate code = get_credentials(context, cred, ctx->there, now, 1190*7c478bd9Sstevel@tonic-gate ctx->endtime, &k_cred); 1191*7c478bd9Sstevel@tonic-gate if (code) 1192*7c478bd9Sstevel@tonic-gate goto fail; 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate if (default_mech) { 1195*7c478bd9Sstevel@tonic-gate mech_type = (gss_OID) gss_mech_krb5; 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: we allocate the memory for mech_used here 1198*7c478bd9Sstevel@tonic-gate * because we store mech_used as a gss_OID and not a (gss_OID *) 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate ctx->mech_used.elements = malloc(mech_type->length); 1201*7c478bd9Sstevel@tonic-gate if ( (ctx->mech_used.elements) == NULL ) { 1202*7c478bd9Sstevel@tonic-gate code = ENOMEM; 1203*7c478bd9Sstevel@tonic-gate major_status = GSS_S_FAILURE; 1204*7c478bd9Sstevel@tonic-gate goto fail; 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate ctx->mech_used.length = mech_type->length; 1207*7c478bd9Sstevel@tonic-gate memcpy(ctx->mech_used.elements, mech_type->elements, mech_type->length); 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate /* 1210*7c478bd9Sstevel@tonic-gate * Now try to make it static if at all possible.... 1211*7c478bd9Sstevel@tonic-gate */ 1212*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: our mech_used is part of the ctx structure */ 1213*7c478bd9Sstevel@tonic-gate /* ctx->mech_used = krb5_gss_convert_static_mech_oid(&(ctx->mech_used)); */ 1214*7c478bd9Sstevel@tonic-gate { 1215*7c478bd9Sstevel@tonic-gate /* gsskrb5 v1 */ 1216*7c478bd9Sstevel@tonic-gate krb5_ui_4 seq_temp; 1217*7c478bd9Sstevel@tonic-gate if ((code = make_ap_req_v1(context, ctx, 1218*7c478bd9Sstevel@tonic-gate cred, k_cred, input_chan_bindings, 1219*7c478bd9Sstevel@tonic-gate mech_type, &token))) { 1220*7c478bd9Sstevel@tonic-gate if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || 1221*7c478bd9Sstevel@tonic-gate (code == KG_EMPTY_CCACHE)) 1222*7c478bd9Sstevel@tonic-gate major_status = GSS_S_NO_CRED; 1223*7c478bd9Sstevel@tonic-gate if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) 1224*7c478bd9Sstevel@tonic-gate major_status = GSS_S_CREDENTIALS_EXPIRED; 1225*7c478bd9Sstevel@tonic-gate goto fail; 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, 1229*7c478bd9Sstevel@tonic-gate (krb5_int32 *)&seq_temp); 1230*7c478bd9Sstevel@tonic-gate ctx->seq_send = seq_temp; 1231*7c478bd9Sstevel@tonic-gate krb5_auth_con_getsendsubkey(context, ctx->auth_context, 1232*7c478bd9Sstevel@tonic-gate &ctx->subkey); 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate major_status = setup_enc(minor_status, ctx, context); 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate if (k_cred) { 1238*7c478bd9Sstevel@tonic-gate krb5_free_creds(context, k_cred); 1239*7c478bd9Sstevel@tonic-gate k_cred = 0; 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* at this point, the context is constructed and valid, 1243*7c478bd9Sstevel@tonic-gate hence, releaseable */ 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate /* intern the context handle */ 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) { 1248*7c478bd9Sstevel@tonic-gate code = G_VALIDATE_FAILED; 1249*7c478bd9Sstevel@tonic-gate goto fail; 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate *context_handle = (gss_ctx_id_t) ctx; 1252*7c478bd9Sstevel@tonic-gate ctx_free = 0; 1253*7c478bd9Sstevel@tonic-gate /* compute time_rec */ 1254*7c478bd9Sstevel@tonic-gate if (time_rec) { 1255*7c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) 1256*7c478bd9Sstevel@tonic-gate goto fail; 1257*7c478bd9Sstevel@tonic-gate *time_rec = ctx->endtime - now; 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate /* set the other returns */ 1261*7c478bd9Sstevel@tonic-gate *output_token = token; 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate if (ret_flags) 1264*7c478bd9Sstevel@tonic-gate *ret_flags = ctx->gss_flags; 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate if (actual_mech_type) 1267*7c478bd9Sstevel@tonic-gate *actual_mech_type = mech_type; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate /* return successfully */ 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1272*7c478bd9Sstevel@tonic-gate if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) { 1273*7c478bd9Sstevel@tonic-gate ctx->established = 0; 1274*7c478bd9Sstevel@tonic-gate return(GSS_S_CONTINUE_NEEDED); 1275*7c478bd9Sstevel@tonic-gate } else { 1276*7c478bd9Sstevel@tonic-gate ctx->seq_recv = ctx->seq_send; 1277*7c478bd9Sstevel@tonic-gate g_order_init(&(ctx->seqstate), ctx->seq_recv, 1278*7c478bd9Sstevel@tonic-gate (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 1279*7c478bd9Sstevel@tonic-gate (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto); 1280*7c478bd9Sstevel@tonic-gate ctx->gss_flags |= GSS_C_PROT_READY_FLAG; 1281*7c478bd9Sstevel@tonic-gate ctx->established = 1; 1282*7c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE); 1283*7c478bd9Sstevel@tonic-gate } 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate fail: 1286*7c478bd9Sstevel@tonic-gate if (ctx_free) { 1287*7c478bd9Sstevel@tonic-gate if (ctx_free->auth_context) 1288*7c478bd9Sstevel@tonic-gate krb5_auth_con_free(context, ctx_free->auth_context); 1289*7c478bd9Sstevel@tonic-gate if (ctx_free->here) 1290*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, ctx_free->here); 1291*7c478bd9Sstevel@tonic-gate if (ctx_free->there) 1292*7c478bd9Sstevel@tonic-gate krb5_free_principal(context, ctx_free->there); 1293*7c478bd9Sstevel@tonic-gate if (ctx_free->subkey) 1294*7c478bd9Sstevel@tonic-gate krb5_free_keyblock(context, ctx_free->subkey); 1295*7c478bd9Sstevel@tonic-gate xfree(ctx_free); 1296*7c478bd9Sstevel@tonic-gate } else 1297*7c478bd9Sstevel@tonic-gate (void)krb5_gss_delete_sec_context(context, minor_status, context_handle, NULL); 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate *minor_status = code; 1300*7c478bd9Sstevel@tonic-gate return (major_status); 1301*7c478bd9Sstevel@tonic-gate } 1302*7c478bd9Sstevel@tonic-gate 1303*7c478bd9Sstevel@tonic-gate /* 1304*7c478bd9Sstevel@tonic-gate * mutual_auth 1305*7c478bd9Sstevel@tonic-gate * 1306*7c478bd9Sstevel@tonic-gate * Handle the reply from the acceptor, if we're doing mutual auth. 1307*7c478bd9Sstevel@tonic-gate */ 1308*7c478bd9Sstevel@tonic-gate static OM_uint32 1309*7c478bd9Sstevel@tonic-gate mutual_auth( 1310*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status, 1311*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred, 1312*7c478bd9Sstevel@tonic-gate gss_ctx_id_t *context_handle, 1313*7c478bd9Sstevel@tonic-gate gss_name_t target_name, 1314*7c478bd9Sstevel@tonic-gate gss_OID mech_type, 1315*7c478bd9Sstevel@tonic-gate OM_uint32 req_flags, 1316*7c478bd9Sstevel@tonic-gate OM_uint32 time_req, 1317*7c478bd9Sstevel@tonic-gate gss_channel_bindings_t input_chan_bindings, 1318*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, 1319*7c478bd9Sstevel@tonic-gate gss_OID *actual_mech_type, 1320*7c478bd9Sstevel@tonic-gate gss_buffer_t output_token, 1321*7c478bd9Sstevel@tonic-gate OM_uint32 *ret_flags, 1322*7c478bd9Sstevel@tonic-gate OM_uint32 *time_rec, 1323*7c478bd9Sstevel@tonic-gate krb5_context context) 1324*7c478bd9Sstevel@tonic-gate { 1325*7c478bd9Sstevel@tonic-gate OM_uint32 major_status; 1326*7c478bd9Sstevel@tonic-gate unsigned char *ptr; 1327*7c478bd9Sstevel@tonic-gate char *sptr; 1328*7c478bd9Sstevel@tonic-gate krb5_data ap_rep; 1329*7c478bd9Sstevel@tonic-gate krb5_ap_rep_enc_part *ap_rep_data; 1330*7c478bd9Sstevel@tonic-gate krb5_timestamp now; 1331*7c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx; 1332*7c478bd9Sstevel@tonic-gate krb5_error *krb_error; 1333*7c478bd9Sstevel@tonic-gate krb5_error_code code; 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate major_status = GSS_S_FAILURE; 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate /* validate the context handle */ 1338*7c478bd9Sstevel@tonic-gate /*SUPPRESS 29*/ 1339*7c478bd9Sstevel@tonic-gate if (! kg_validate_ctx_id(*context_handle)) { 1340*7c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_VALIDATE_FAILED; 1341*7c478bd9Sstevel@tonic-gate return(GSS_S_NO_CONTEXT); 1342*7c478bd9Sstevel@tonic-gate } 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate ctx = (krb5_gss_ctx_id_rec *) *context_handle; 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate /* make sure the context is non-established, and that certain 1347*7c478bd9Sstevel@tonic-gate arguments are unchanged */ 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate if ((ctx->established) || 1350*7c478bd9Sstevel@tonic-gate ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) { 1351*7c478bd9Sstevel@tonic-gate code = KG_CONTEXT_ESTABLISHED; 1352*7c478bd9Sstevel@tonic-gate goto fail; 1353*7c478bd9Sstevel@tonic-gate } 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate if (! krb5_principal_compare(context, ctx->there, 1356*7c478bd9Sstevel@tonic-gate (krb5_principal) target_name)) { 1357*7c478bd9Sstevel@tonic-gate (void)krb5_gss_delete_sec_context(context, minor_status, 1358*7c478bd9Sstevel@tonic-gate context_handle, NULL); 1359*7c478bd9Sstevel@tonic-gate code = 0; 1360*7c478bd9Sstevel@tonic-gate major_status = GSS_S_BAD_NAME; 1361*7c478bd9Sstevel@tonic-gate goto fail; 1362*7c478bd9Sstevel@tonic-gate } 1363*7c478bd9Sstevel@tonic-gate 1364*7c478bd9Sstevel@tonic-gate /* verify the token and leave the AP_REP message in ap_rep */ 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate if (input_token == GSS_C_NO_BUFFER) { 1367*7c478bd9Sstevel@tonic-gate (void)krb5_gss_delete_sec_context(context, minor_status, 1368*7c478bd9Sstevel@tonic-gate context_handle, NULL); 1369*7c478bd9Sstevel@tonic-gate code = 0; 1370*7c478bd9Sstevel@tonic-gate major_status = GSS_S_DEFECTIVE_TOKEN; 1371*7c478bd9Sstevel@tonic-gate goto fail; 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate ptr = (unsigned char *) input_token->value; 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate if (g_verify_token_header(&ctx->mech_used, 1377*7c478bd9Sstevel@tonic-gate (uint32_t *)&(ap_rep.length), 1378*7c478bd9Sstevel@tonic-gate &ptr, KG_TOK_CTX_AP_REP, 1379*7c478bd9Sstevel@tonic-gate input_token->length, 1)) { 1380*7c478bd9Sstevel@tonic-gate if (g_verify_token_header(&ctx->mech_used, 1381*7c478bd9Sstevel@tonic-gate (uint32_t *)&(ap_rep.length), 1382*7c478bd9Sstevel@tonic-gate &ptr, KG_TOK_CTX_ERROR, 1383*7c478bd9Sstevel@tonic-gate input_token->length, 1) == 0) { 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate /* Handle a KRB_ERROR message from the server */ 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate sptr = (char *) ptr; /* PC compiler bug */ 1388*7c478bd9Sstevel@tonic-gate TREAD_STR(sptr, ap_rep.data, ap_rep.length); 1389*7c478bd9Sstevel@tonic-gate 1390*7c478bd9Sstevel@tonic-gate code = krb5_rd_error(context, &ap_rep, &krb_error); 1391*7c478bd9Sstevel@tonic-gate if (code) 1392*7c478bd9Sstevel@tonic-gate goto fail; 1393*7c478bd9Sstevel@tonic-gate if (krb_error->error) 1394*7c478bd9Sstevel@tonic-gate code = krb_error->error + ERROR_TABLE_BASE_krb5; 1395*7c478bd9Sstevel@tonic-gate else 1396*7c478bd9Sstevel@tonic-gate code = 0; 1397*7c478bd9Sstevel@tonic-gate krb5_free_error(context, krb_error); 1398*7c478bd9Sstevel@tonic-gate goto fail; 1399*7c478bd9Sstevel@tonic-gate } else { 1400*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1401*7c478bd9Sstevel@tonic-gate return(GSS_S_DEFECTIVE_TOKEN); 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate } 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate sptr = (char *) ptr; /* PC compiler bug */ 1406*7c478bd9Sstevel@tonic-gate TREAD_STR(sptr, ap_rep.data, ap_rep.length); 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate /* decode the ap_rep */ 1409*7c478bd9Sstevel@tonic-gate if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep, 1410*7c478bd9Sstevel@tonic-gate &ap_rep_data))) { 1411*7c478bd9Sstevel@tonic-gate /* 1412*7c478bd9Sstevel@tonic-gate * XXX A hack for backwards compatiblity. 1413*7c478bd9Sstevel@tonic-gate * To be removed in 1999 -- proven 1414*7c478bd9Sstevel@tonic-gate */ 1415*7c478bd9Sstevel@tonic-gate krb5_auth_con_setuseruserkey(context, ctx->auth_context, 1416*7c478bd9Sstevel@tonic-gate ctx->subkey); 1417*7c478bd9Sstevel@tonic-gate if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep, 1418*7c478bd9Sstevel@tonic-gate &ap_rep_data))) 1419*7c478bd9Sstevel@tonic-gate goto fail; 1420*7c478bd9Sstevel@tonic-gate } 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate /* store away the sequence number */ 1423*7c478bd9Sstevel@tonic-gate ctx->seq_recv = ap_rep_data->seq_number; 1424*7c478bd9Sstevel@tonic-gate g_order_init(&(ctx->seqstate), ctx->seq_recv, 1425*7c478bd9Sstevel@tonic-gate (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 1426*7c478bd9Sstevel@tonic-gate (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0, ctx->proto); 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate if (ctx->proto == 1 && ap_rep_data->subkey) { 1429*7c478bd9Sstevel@tonic-gate /* Keep acceptor's subkey. */ 1430*7c478bd9Sstevel@tonic-gate ctx->have_acceptor_subkey = 1; 1431*7c478bd9Sstevel@tonic-gate code = krb5_copy_keyblock(context, ap_rep_data->subkey, 1432*7c478bd9Sstevel@tonic-gate &ctx->acceptor_subkey); 1433*7c478bd9Sstevel@tonic-gate if (code) 1434*7c478bd9Sstevel@tonic-gate goto fail; 1435*7c478bd9Sstevel@tonic-gate code = krb5int_c_mandatory_cksumtype(context, 1436*7c478bd9Sstevel@tonic-gate ctx->acceptor_subkey->enctype, 1437*7c478bd9Sstevel@tonic-gate &ctx->acceptor_subkey_cksumtype); 1438*7c478bd9Sstevel@tonic-gate if (code) 1439*7c478bd9Sstevel@tonic-gate goto fail; 1440*7c478bd9Sstevel@tonic-gate } 1441*7c478bd9Sstevel@tonic-gate 1442*7c478bd9Sstevel@tonic-gate /* free the ap_rep_data */ 1443*7c478bd9Sstevel@tonic-gate krb5_free_ap_rep_enc_part(context, ap_rep_data); 1444*7c478bd9Sstevel@tonic-gate 1445*7c478bd9Sstevel@tonic-gate /* set established */ 1446*7c478bd9Sstevel@tonic-gate ctx->established = 1; 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate /* set returns */ 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate if (time_rec) { 1451*7c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) 1452*7c478bd9Sstevel@tonic-gate goto fail; 1453*7c478bd9Sstevel@tonic-gate *time_rec = ctx->endtime - now; 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate if (ret_flags) 1456*7c478bd9Sstevel@tonic-gate *ret_flags = ctx->gss_flags; 1457*7c478bd9Sstevel@tonic-gate 1458*7c478bd9Sstevel@tonic-gate if (actual_mech_type) 1459*7c478bd9Sstevel@tonic-gate *actual_mech_type = mech_type; 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate /* success */ 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1464*7c478bd9Sstevel@tonic-gate return GSS_S_COMPLETE; 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate fail: 1467*7c478bd9Sstevel@tonic-gate (void)krb5_gss_delete_sec_context(context, minor_status, context_handle, NULL); 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate *minor_status = code; 1470*7c478bd9Sstevel@tonic-gate return (major_status); 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate /* 1474*7c478bd9Sstevel@tonic-gate * krb5_gss_init_sec_context 1475*7c478bd9Sstevel@tonic-gate * This has been broken up into smaller chunks for CFX support. 1476*7c478bd9Sstevel@tonic-gate * MIT KRB5 1.3.2 1477*7c478bd9Sstevel@tonic-gate */ 1478*7c478bd9Sstevel@tonic-gate OM_uint32 1479*7c478bd9Sstevel@tonic-gate krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle, 1480*7c478bd9Sstevel@tonic-gate context_handle, target_name, mech_type, 1481*7c478bd9Sstevel@tonic-gate req_flags, time_req, input_chan_bindings, 1482*7c478bd9Sstevel@tonic-gate input_token, actual_mech_type, output_token, 1483*7c478bd9Sstevel@tonic-gate ret_flags, time_rec) 1484*7c478bd9Sstevel@tonic-gate void *ct; 1485*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status; 1486*7c478bd9Sstevel@tonic-gate gss_cred_id_t claimant_cred_handle; 1487*7c478bd9Sstevel@tonic-gate gss_ctx_id_t *context_handle; 1488*7c478bd9Sstevel@tonic-gate gss_name_t target_name; 1489*7c478bd9Sstevel@tonic-gate gss_OID mech_type; 1490*7c478bd9Sstevel@tonic-gate OM_uint32 req_flags; 1491*7c478bd9Sstevel@tonic-gate OM_uint32 time_req; 1492*7c478bd9Sstevel@tonic-gate gss_channel_bindings_t input_chan_bindings; 1493*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token; 1494*7c478bd9Sstevel@tonic-gate gss_OID *actual_mech_type; 1495*7c478bd9Sstevel@tonic-gate gss_buffer_t output_token; 1496*7c478bd9Sstevel@tonic-gate OM_uint32 *ret_flags; 1497*7c478bd9Sstevel@tonic-gate OM_uint32 *time_rec; 1498*7c478bd9Sstevel@tonic-gate { 1499*7c478bd9Sstevel@tonic-gate krb5_context context; 1500*7c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred = NULL; 1501*7c478bd9Sstevel@tonic-gate int err; 1502*7c478bd9Sstevel@tonic-gate int default_mech = 0; 1503*7c478bd9Sstevel@tonic-gate OM_uint32 major_status; 1504*7c478bd9Sstevel@tonic-gate OM_uint32 tmp_min_stat; 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: for MT safety, we avoid the use of a default 1507*7c478bd9Sstevel@tonic-gate * context via kg_get_context() */ 1508*7c478bd9Sstevel@tonic-gate #if 0 1509*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(kg_get_context(minor_status, &context))) 1510*7c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 1511*7c478bd9Sstevel@tonic-gate #endif 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "krb5_gss_init_sec_context() start\n"); 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate mutex_lock(&krb5_mutex); 1516*7c478bd9Sstevel@tonic-gate context = ct; 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate /* set up return values so they can be "freed" successfully */ 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate major_status = GSS_S_FAILURE; /* Default major code */ 1521*7c478bd9Sstevel@tonic-gate output_token->length = 0; 1522*7c478bd9Sstevel@tonic-gate output_token->value = NULL; 1523*7c478bd9Sstevel@tonic-gate if (actual_mech_type) 1524*7c478bd9Sstevel@tonic-gate *actual_mech_type = NULL; 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate /* verify that the target_name is valid and usable */ 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate if (! kg_validate_name(target_name)) { 1529*7c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_VALIDATE_FAILED; 1530*7c478bd9Sstevel@tonic-gate major_status = (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); 1531*7c478bd9Sstevel@tonic-gate goto unlock; 1532*7c478bd9Sstevel@tonic-gate } 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate /* verify the credential, or use the default */ 1535*7c478bd9Sstevel@tonic-gate /*SUPPRESS 29*/ 1536*7c478bd9Sstevel@tonic-gate if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) { 1537*7c478bd9Sstevel@tonic-gate /* 1538*7c478bd9Sstevel@tonic-gate * Solaris Kerberos: here we are using the Solaris specific 1539*7c478bd9Sstevel@tonic-gate * function get_default_cred() to handle the special case of a 1540*7c478bd9Sstevel@tonic-gate * root principal 1541*7c478bd9Sstevel@tonic-gate */ 1542*7c478bd9Sstevel@tonic-gate major_status = get_default_cred(minor_status, ct, (gss_cred_id_t *)&cred); 1543*7c478bd9Sstevel@tonic-gate if (major_status && GSS_ERROR(major_status)) { 1544*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "krb5_gss_init_sec_context() end, error " 1545*7c478bd9Sstevel@tonic-gate "major_status = %d\n", major_status); 1546*7c478bd9Sstevel@tonic-gate goto unlock; 1547*7c478bd9Sstevel@tonic-gate } 1548*7c478bd9Sstevel@tonic-gate } else { 1549*7c478bd9Sstevel@tonic-gate major_status = krb5_gss_validate_cred_no_lock(ct, minor_status, 1550*7c478bd9Sstevel@tonic-gate claimant_cred_handle); 1551*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(major_status)) { 1552*7c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "krb5_gss_init_sec_context() end, error " 1553*7c478bd9Sstevel@tonic-gate "major_status = %d\n", major_status); 1554*7c478bd9Sstevel@tonic-gate goto unlock; 1555*7c478bd9Sstevel@tonic-gate } 1556*7c478bd9Sstevel@tonic-gate cred = (krb5_gss_cred_id_t) claimant_cred_handle; 1557*7c478bd9Sstevel@tonic-gate } 1558*7c478bd9Sstevel@tonic-gate 1559*7c478bd9Sstevel@tonic-gate /* verify the mech_type */ 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate err = 0; 1562*7c478bd9Sstevel@tonic-gate if (mech_type == GSS_C_NULL_OID) { 1563*7c478bd9Sstevel@tonic-gate default_mech = 1; 1564*7c478bd9Sstevel@tonic-gate if (cred->rfc_mech) { 1565*7c478bd9Sstevel@tonic-gate mech_type = (gss_OID) gss_mech_krb5; 1566*7c478bd9Sstevel@tonic-gate } else if (cred->prerfc_mech) { 1567*7c478bd9Sstevel@tonic-gate mech_type = (gss_OID) gss_mech_krb5_old; 1568*7c478bd9Sstevel@tonic-gate } else { 1569*7c478bd9Sstevel@tonic-gate err = 1; 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate } else if (g_OID_equal(mech_type, gss_mech_krb5)) { 1572*7c478bd9Sstevel@tonic-gate if (!cred->rfc_mech) 1573*7c478bd9Sstevel@tonic-gate err = 1; 1574*7c478bd9Sstevel@tonic-gate } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) { 1575*7c478bd9Sstevel@tonic-gate if (!cred->prerfc_mech) 1576*7c478bd9Sstevel@tonic-gate err = 1; 1577*7c478bd9Sstevel@tonic-gate } else { 1578*7c478bd9Sstevel@tonic-gate err = 1; 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate if (err) { 1582*7c478bd9Sstevel@tonic-gate *minor_status = 0; 1583*7c478bd9Sstevel@tonic-gate major_status = GSS_S_BAD_MECH; 1584*7c478bd9Sstevel@tonic-gate goto unlock; 1585*7c478bd9Sstevel@tonic-gate } 1586*7c478bd9Sstevel@tonic-gate 1587*7c478bd9Sstevel@tonic-gate /* is this a new connection or not? */ 1588*7c478bd9Sstevel@tonic-gate 1589*7c478bd9Sstevel@tonic-gate /*SUPPRESS 29*/ 1590*7c478bd9Sstevel@tonic-gate if (*context_handle == GSS_C_NO_CONTEXT) { 1591*7c478bd9Sstevel@tonic-gate major_status = new_connection(minor_status, cred, context_handle, 1592*7c478bd9Sstevel@tonic-gate target_name, mech_type, req_flags, 1593*7c478bd9Sstevel@tonic-gate time_req, input_chan_bindings, 1594*7c478bd9Sstevel@tonic-gate input_token, actual_mech_type, 1595*7c478bd9Sstevel@tonic-gate output_token, ret_flags, time_rec, 1596*7c478bd9Sstevel@tonic-gate context, default_mech); 1597*7c478bd9Sstevel@tonic-gate } else { 1598*7c478bd9Sstevel@tonic-gate major_status = mutual_auth(minor_status, cred, context_handle, 1599*7c478bd9Sstevel@tonic-gate target_name, mech_type, req_flags, 1600*7c478bd9Sstevel@tonic-gate time_req, input_chan_bindings, 1601*7c478bd9Sstevel@tonic-gate input_token, actual_mech_type, 1602*7c478bd9Sstevel@tonic-gate output_token, ret_flags, time_rec, 1603*7c478bd9Sstevel@tonic-gate context); 1604*7c478bd9Sstevel@tonic-gate } 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate unlock: 1607*7c478bd9Sstevel@tonic-gate if (claimant_cred_handle == GSS_C_NO_CREDENTIAL && cred != NULL) 1608*7c478bd9Sstevel@tonic-gate krb5_gss_release_cred_no_lock(context, &tmp_min_stat, (gss_cred_id_t *)cred); 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate mutex_unlock(&krb5_mutex); 1611*7c478bd9Sstevel@tonic-gate 1612*7c478bd9Sstevel@tonic-gate KRB5_LOG1(KRB5_ERR, "krb5_gss_init_sec_context() end, error " 1613*7c478bd9Sstevel@tonic-gate "major_status = %d, minor_status = %d\n", 1614*7c478bd9Sstevel@tonic-gate major_status, *minor_status); 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate return (major_status); 1617*7c478bd9Sstevel@tonic-gate } 1618