17c478bd9Sstevel@tonic-gate /* 2*159d09a2SMark Phalan * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate 77c478bd9Sstevel@tonic-gate /* 8ab9b2e15Sgtb * Copyright 2000,2002, 2003 by the Massachusetts Institute of Technology. 97c478bd9Sstevel@tonic-gate * All Rights Reserved. 107c478bd9Sstevel@tonic-gate * 117c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 127c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 137c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 147c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 15ab9b2e15Sgtb * 167c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 177c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 187c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 197c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 207c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 217c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 227c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 237c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 247c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 257c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 267c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 277c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 287c478bd9Sstevel@tonic-gate * or implied warranty. 29ab9b2e15Sgtb * 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc. 33ab9b2e15Sgtb * 347c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, distribute, and sell this software 357c478bd9Sstevel@tonic-gate * and its documentation for any purpose is hereby granted without fee, 367c478bd9Sstevel@tonic-gate * provided that the above copyright notice appears in all copies and 377c478bd9Sstevel@tonic-gate * that both that copyright notice and this permission notice appear in 387c478bd9Sstevel@tonic-gate * supporting documentation, and that the name of OpenVision not be used 397c478bd9Sstevel@tonic-gate * in advertising or publicity pertaining to distribution of the software 407c478bd9Sstevel@tonic-gate * without specific, written prior permission. OpenVision makes no 417c478bd9Sstevel@tonic-gate * representations about the suitability of this software for any 427c478bd9Sstevel@tonic-gate * purpose. It is provided "as is" without express or implied warranty. 43ab9b2e15Sgtb * 447c478bd9Sstevel@tonic-gate * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 457c478bd9Sstevel@tonic-gate * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 467c478bd9Sstevel@tonic-gate * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 477c478bd9Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 487c478bd9Sstevel@tonic-gate * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 497c478bd9Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 507c478bd9Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC. 55ab9b2e15Sgtb * 567c478bd9Sstevel@tonic-gate * All rights reserved. 57ab9b2e15Sgtb * 587c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require 597c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the 607c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to 617c478bd9Sstevel@tonic-gate * obtain such a license before exporting. 62ab9b2e15Sgtb * 637c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 647c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 657c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 667c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 677c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 687c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining 697c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 707c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of 717c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 727c478bd9Sstevel@tonic-gate * or implied warranty. 73ab9b2e15Sgtb * 747c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 757c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 767c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate 79ab9b2e15Sgtb #include "k5-int.h" 80ab9b2e15Sgtb #include "gss_libinit.h" 81*159d09a2SMark Phalan #include "gssapiP_krb5.h" 82ab9b2e15Sgtb #include "mglueP.h" 83ab9b2e15Sgtb #ifdef HAVE_MEMORY_H 847c478bd9Sstevel@tonic-gate #include <memory.h> 85ab9b2e15Sgtb #endif 867c478bd9Sstevel@tonic-gate #include <stdlib.h> 877c478bd9Sstevel@tonic-gate #include <assert.h> 887c478bd9Sstevel@tonic-gate 89ab9b2e15Sgtb /* Solaris Kerberos start */ 90ab9b2e15Sgtb static OM_uint32 get_default_cred(OM_uint32 *, void *, gss_cred_id_t *); 91ab9b2e15Sgtb /* Solaris Kerberos end */ 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 94*159d09a2SMark Phalan * $Id: init_sec_context.c 18721 2006-10-16 16:18:29Z epeisach $ 957c478bd9Sstevel@tonic-gate */ 96ab9b2e15Sgtb 97ab9b2e15Sgtb /* XXX This is for debugging only!!! Should become a real bitfield 98ab9b2e15Sgtb at some point */ 997c478bd9Sstevel@tonic-gate int krb5_gss_dbg_client_expcreds = 0; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * Common code which fetches the correct krb5 credentials from the 1037c478bd9Sstevel@tonic-gate * ccache. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate static krb5_error_code get_credentials(context, cred, server, now, 1067c478bd9Sstevel@tonic-gate endtime, out_creds) 1077c478bd9Sstevel@tonic-gate krb5_context context; 1087c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 1097c478bd9Sstevel@tonic-gate krb5_principal server; 1107c478bd9Sstevel@tonic-gate krb5_timestamp now; 1117c478bd9Sstevel@tonic-gate krb5_timestamp endtime; 1127c478bd9Sstevel@tonic-gate krb5_creds **out_creds; 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate krb5_error_code code; 1157c478bd9Sstevel@tonic-gate krb5_creds in_creds; 1167c478bd9Sstevel@tonic-gate 117ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock); 1187c478bd9Sstevel@tonic-gate memset((char *) &in_creds, 0, sizeof(krb5_creds)); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client))) 1217c478bd9Sstevel@tonic-gate goto cleanup; 1227c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, server, &in_creds.server))) 1237c478bd9Sstevel@tonic-gate goto cleanup; 1247c478bd9Sstevel@tonic-gate in_creds.times.endtime = endtime; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate in_creds.keyblock.enctype = 0; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate code = krb5_get_credentials(context, 0, cred->ccache, 1297c478bd9Sstevel@tonic-gate &in_creds, out_creds); 1307c478bd9Sstevel@tonic-gate if (code) 1317c478bd9Sstevel@tonic-gate goto cleanup; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Enforce a stricter limit (without timeskew forgiveness at the 1357c478bd9Sstevel@tonic-gate * boundaries) because accept_sec_context code is also similarly 1367c478bd9Sstevel@tonic-gate * non-forgiving. 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL && 1397c478bd9Sstevel@tonic-gate (*out_creds)->times.endtime < now) { 1407c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_TKT_EXPIRED; 1417c478bd9Sstevel@tonic-gate goto cleanup; 1427c478bd9Sstevel@tonic-gate } 143ab9b2e15Sgtb 1447c478bd9Sstevel@tonic-gate cleanup: 1457c478bd9Sstevel@tonic-gate if (in_creds.client) 1467c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.client); 1477c478bd9Sstevel@tonic-gate if (in_creds.server) 1487c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.server); 1497c478bd9Sstevel@tonic-gate return code; 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate struct gss_checksum_data { 1527c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx; 1537c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 1547c478bd9Sstevel@tonic-gate krb5_checksum md5; 1557c478bd9Sstevel@tonic-gate krb5_data checksum_data; 1567c478bd9Sstevel@tonic-gate }; 1577c478bd9Sstevel@tonic-gate 158ab9b2e15Sgtb #ifdef CFX_EXERCISE 159ab9b2e15Sgtb #include "../../krb5/krb/auth_con.h" 160ab9b2e15Sgtb #endif 1617c478bd9Sstevel@tonic-gate static krb5_error_code KRB5_CALLCONV 1627c478bd9Sstevel@tonic-gate make_gss_checksum (krb5_context context, krb5_auth_context auth_context, 163ab9b2e15Sgtb void *cksum_data, krb5_data **out) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate krb5_error_code code; 1667c478bd9Sstevel@tonic-gate krb5_int32 con_flags; 1677c478bd9Sstevel@tonic-gate unsigned char *ptr; 1687c478bd9Sstevel@tonic-gate struct gss_checksum_data *data = cksum_data; 1697c478bd9Sstevel@tonic-gate krb5_data credmsg; 170ab9b2e15Sgtb unsigned int junk; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate data->checksum_data.data = 0; 1737c478bd9Sstevel@tonic-gate credmsg.data = 0; 1747c478bd9Sstevel@tonic-gate /* build the checksum field */ 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if (data->ctx->gss_flags & GSS_C_DELEG_FLAG) { 1777c478bd9Sstevel@tonic-gate /* first get KRB_CRED message, so we know its length */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* clear the time check flag that was set in krb5_auth_con_init() */ 1807c478bd9Sstevel@tonic-gate krb5_auth_con_getflags(context, auth_context, &con_flags); 1817c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context, 182ab9b2e15Sgtb con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate code = krb5_fwd_tgt_creds(context, auth_context, 0, 185ab9b2e15Sgtb data->cred->princ, data->ctx->there, 186ab9b2e15Sgtb data->cred->ccache, 1, 187ab9b2e15Sgtb &credmsg); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */ 1907c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context, con_flags); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (code) { 1937c478bd9Sstevel@tonic-gate /* don't fail here; just don't accept/do the delegation 194ab9b2e15Sgtb request */ 1957c478bd9Sstevel@tonic-gate data->ctx->gss_flags &= ~GSS_C_DELEG_FLAG; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate data->checksum_data.length = 24; 1987c478bd9Sstevel@tonic-gate } else { 1997c478bd9Sstevel@tonic-gate if (credmsg.length+28 > KRB5_INT16_MAX) { 2007c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg); 2017c478bd9Sstevel@tonic-gate return(KRB5KRB_ERR_FIELD_TOOLONG); 202ab9b2e15Sgtb } 2037c478bd9Sstevel@tonic-gate 204ab9b2e15Sgtb data->checksum_data.length = 28+credmsg.length; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate } else { 2077c478bd9Sstevel@tonic-gate data->checksum_data.length = 24; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate #ifdef CFX_EXERCISE 210ab9b2e15Sgtb if (data->ctx->auth_context->keyblock != NULL 211ab9b2e15Sgtb && data->ctx->auth_context->keyblock->enctype == 18) { 2127c478bd9Sstevel@tonic-gate srand(time(0) ^ getpid()); 2137c478bd9Sstevel@tonic-gate /* Our ftp client code stupidly assumes a base64-encoded 2147c478bd9Sstevel@tonic-gate version of the token will fit in 10K, so don't make this 2157c478bd9Sstevel@tonic-gate too big. */ 2167c478bd9Sstevel@tonic-gate junk = rand() & 0xff; 2177c478bd9Sstevel@tonic-gate } else 218ab9b2e15Sgtb junk = 0; 2197c478bd9Sstevel@tonic-gate #else 2207c478bd9Sstevel@tonic-gate junk = 0; 2217c478bd9Sstevel@tonic-gate #endif 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate data->checksum_data.length += junk; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* now allocate a buffer to hold the checksum data and 226ab9b2e15Sgtb (maybe) KRB_CRED msg */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if ((data->checksum_data.data = 2297c478bd9Sstevel@tonic-gate (char *) xmalloc(data->checksum_data.length)) == NULL) { 2307c478bd9Sstevel@tonic-gate if (credmsg.data) 231ab9b2e15Sgtb krb5_free_data_contents(context, &credmsg); 2327c478bd9Sstevel@tonic-gate return(ENOMEM); 2337c478bd9Sstevel@tonic-gate } 234*159d09a2SMark Phalan /* Solaris Kerberos */ 235ab9b2e15Sgtb ptr = (uchar_t *)data->checksum_data.data; /* SUNW15resync */ 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->md5.length, 0); 2387c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) data->md5.contents, data->md5.length); 2397c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->ctx->gss_flags, 0); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* done with this, free it */ 2427c478bd9Sstevel@tonic-gate xfree(data->md5.contents); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (credmsg.data) { 2457c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, KRB5_GSS_FOR_CREDS_OPTION, 0); 2467c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, credmsg.length, 0); 2477c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) credmsg.data, credmsg.length); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* free credmsg data */ 2507c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate if (junk) 2537c478bd9Sstevel@tonic-gate memset(ptr, 'i', junk); 2547c478bd9Sstevel@tonic-gate *out = &data->checksum_data; 2557c478bd9Sstevel@tonic-gate return 0; 2567c478bd9Sstevel@tonic-gate } 257ab9b2e15Sgtb 2587c478bd9Sstevel@tonic-gate static krb5_error_code 2597c478bd9Sstevel@tonic-gate make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token) 2607c478bd9Sstevel@tonic-gate krb5_context context; 2617c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx; 2627c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred; 2637c478bd9Sstevel@tonic-gate krb5_creds *k_cred; 2647c478bd9Sstevel@tonic-gate gss_channel_bindings_t chan_bindings; 2657c478bd9Sstevel@tonic-gate gss_OID mech_type; 2667c478bd9Sstevel@tonic-gate gss_buffer_t token; 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate krb5_flags mk_req_flags = 0; 2697c478bd9Sstevel@tonic-gate krb5_error_code code; 2707c478bd9Sstevel@tonic-gate struct gss_checksum_data cksum_struct; 2717c478bd9Sstevel@tonic-gate krb5_checksum md5; 2727c478bd9Sstevel@tonic-gate krb5_data ap_req; 2737c478bd9Sstevel@tonic-gate krb5_data *checksum_data = NULL; 2747c478bd9Sstevel@tonic-gate unsigned char *ptr; 2757c478bd9Sstevel@tonic-gate unsigned char *t; 276ab9b2e15Sgtb unsigned int tlen; 2777c478bd9Sstevel@tonic-gate 278ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock); 2797c478bd9Sstevel@tonic-gate ap_req.data = 0; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* compute the hash of the channel bindings */ 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5, 0))) 2847c478bd9Sstevel@tonic-gate return(code); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate krb5_auth_con_set_req_cksumtype(context, ctx->auth_context, 2877c478bd9Sstevel@tonic-gate CKSUMTYPE_KG_CB); 2887c478bd9Sstevel@tonic-gate cksum_struct.md5 = md5; 2897c478bd9Sstevel@tonic-gate cksum_struct.ctx = ctx; 2907c478bd9Sstevel@tonic-gate cksum_struct.cred = cred; 2917c478bd9Sstevel@tonic-gate cksum_struct.checksum_data.data = NULL; 2927c478bd9Sstevel@tonic-gate switch (k_cred->keyblock.enctype) { 2937c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_CRC: 2947c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD4: 2957c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD5: 2967c478bd9Sstevel@tonic-gate case ENCTYPE_DES3_CBC_SHA1: 297ab9b2e15Sgtb code = make_gss_checksum(context, ctx->auth_context, &cksum_struct, 298ab9b2e15Sgtb &checksum_data); 299ab9b2e15Sgtb if (code) 3007c478bd9Sstevel@tonic-gate goto cleanup; 301ab9b2e15Sgtb break; 3027c478bd9Sstevel@tonic-gate default: 3037c478bd9Sstevel@tonic-gate krb5_auth_con_set_checksum_func(context, ctx->auth_context, 304ab9b2e15Sgtb make_gss_checksum, &cksum_struct); 305ab9b2e15Sgtb break; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 308ab9b2e15Sgtb 3097c478bd9Sstevel@tonic-gate /* call mk_req. subkey and ap_req need to be used or destroyed */ 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate mk_req_flags = AP_OPTS_USE_SUBKEY; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) 3147c478bd9Sstevel@tonic-gate mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED; 3157c478bd9Sstevel@tonic-gate 316ab9b2e15Sgtb code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, 317ab9b2e15Sgtb checksum_data, k_cred, &ap_req); 318ab9b2e15Sgtb krb5_free_data_contents(context, &cksum_struct.checksum_data); 319ab9b2e15Sgtb if (code) 3207c478bd9Sstevel@tonic-gate goto cleanup; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* store the interesting stuff from creds and authent */ 3237c478bd9Sstevel@tonic-gate ctx->endtime = k_cred->times.endtime; 3247c478bd9Sstevel@tonic-gate ctx->krb_flags = k_cred->ticket_flags; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* build up the token */ 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* allocate space for the token */ 3297c478bd9Sstevel@tonic-gate tlen = g_token_size((gss_OID) mech_type, ap_req.length); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if ((t = (unsigned char *) xmalloc(tlen)) == NULL) { 3327c478bd9Sstevel@tonic-gate code = ENOMEM; 3337c478bd9Sstevel@tonic-gate goto cleanup; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* fill in the buffer */ 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate ptr = t; 3397c478bd9Sstevel@tonic-gate 340ab9b2e15Sgtb g_make_token_header(mech_type, ap_req.length, 3417c478bd9Sstevel@tonic-gate &ptr, KG_TOK_CTX_AP_REQ); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) ap_req.data, ap_req.length); 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* pass it back */ 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate token->length = tlen; 3487c478bd9Sstevel@tonic-gate token->value = (void *) t; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate code = 0; 351ab9b2e15Sgtb 352ab9b2e15Sgtb cleanup: 353ab9b2e15Sgtb if (checksum_data && checksum_data->data) 354ab9b2e15Sgtb krb5_free_data_contents(context, checksum_data); 3557c478bd9Sstevel@tonic-gate if (ap_req.data) 356ab9b2e15Sgtb krb5_free_data_contents(context, &ap_req); 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate return (code); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 361ab9b2e15Sgtb /* 362ab9b2e15Sgtb * setup_enc 363ab9b2e15Sgtb * 364ab9b2e15Sgtb * Fill in the encryption descriptors. Called after AP-REQ is made. 365ab9b2e15Sgtb */ 366ab9b2e15Sgtb static OM_uint32 367ab9b2e15Sgtb setup_enc( 368ab9b2e15Sgtb OM_uint32 *minor_status, 369ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx, 370ab9b2e15Sgtb krb5_context context) 371ab9b2e15Sgtb { 372ab9b2e15Sgtb krb5_error_code code; 373ab9b2e15Sgtb int i; 374ab9b2e15Sgtb krb5int_access kaccess; 3757c478bd9Sstevel@tonic-gate 376ab9b2e15Sgtb code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); 377ab9b2e15Sgtb if (code) 378ab9b2e15Sgtb goto fail; 3797c478bd9Sstevel@tonic-gate 380ab9b2e15Sgtb ctx->have_acceptor_subkey = 0; 381ab9b2e15Sgtb ctx->proto = 0; 382ab9b2e15Sgtb ctx->cksumtype = 0; 383ab9b2e15Sgtb switch(ctx->subkey->enctype) { 384ab9b2e15Sgtb case ENCTYPE_DES_CBC_MD5: 385ab9b2e15Sgtb case ENCTYPE_DES_CBC_MD4: 386ab9b2e15Sgtb case ENCTYPE_DES_CBC_CRC: 387ab9b2e15Sgtb ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; 388ab9b2e15Sgtb ctx->signalg = SGN_ALG_DES_MAC_MD5; 389ab9b2e15Sgtb ctx->cksum_size = 8; 390ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_DES; 3917c478bd9Sstevel@tonic-gate 392ab9b2e15Sgtb /* The encryption key is the session key XOR 393ab9b2e15Sgtb 0xf0f0f0f0f0f0f0f0. */ 394ab9b2e15Sgtb if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) 395ab9b2e15Sgtb goto fail; 3967c478bd9Sstevel@tonic-gate 397ab9b2e15Sgtb for (i=0; i<ctx->enc->length; i++) 398ab9b2e15Sgtb ctx->enc->contents[i] ^= 0xf0; 3997c478bd9Sstevel@tonic-gate 400ab9b2e15Sgtb goto copy_subkey_to_seq; 4017c478bd9Sstevel@tonic-gate 402ab9b2e15Sgtb case ENCTYPE_DES3_CBC_SHA1: 403ab9b2e15Sgtb /* MIT extension */ 404ab9b2e15Sgtb ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; 405ab9b2e15Sgtb ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; 406ab9b2e15Sgtb ctx->cksum_size = 20; 407ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_DES3KD; 408ab9b2e15Sgtb 409ab9b2e15Sgtb copy_subkey: 410ab9b2e15Sgtb code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc); 411ab9b2e15Sgtb if (code) 412ab9b2e15Sgtb goto fail; 413ab9b2e15Sgtb copy_subkey_to_seq: 414ab9b2e15Sgtb code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq); 415ab9b2e15Sgtb if (code) { 416ab9b2e15Sgtb krb5_free_keyblock (context, ctx->enc); 417ab9b2e15Sgtb goto fail; 418ab9b2e15Sgtb } 419ab9b2e15Sgtb goto success; 420ab9b2e15Sgtb 421ab9b2e15Sgtb case ENCTYPE_ARCFOUR_HMAC: 422ab9b2e15Sgtb /* Microsoft extension */ 423ab9b2e15Sgtb ctx->signalg = SGN_ALG_HMAC_MD5 ; 424ab9b2e15Sgtb ctx->cksum_size = 8; 425ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ; 426ab9b2e15Sgtb 427ab9b2e15Sgtb goto copy_subkey; 428ab9b2e15Sgtb 429ab9b2e15Sgtb default: 430ab9b2e15Sgtb /* Fill some fields we shouldn't be using on this path 431ab9b2e15Sgtb with garbage. */ 432ab9b2e15Sgtb ctx->signalg = -10; 433ab9b2e15Sgtb ctx->sealalg = -10; 434ab9b2e15Sgtb 435ab9b2e15Sgtb ctx->proto = 1; 436ab9b2e15Sgtb code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype, 437ab9b2e15Sgtb &ctx->cksumtype); 438ab9b2e15Sgtb if (code) 439ab9b2e15Sgtb goto fail; 440ab9b2e15Sgtb code = krb5_c_checksum_length(context, ctx->cksumtype, 441ab9b2e15Sgtb &ctx->cksum_size); 442ab9b2e15Sgtb if (code) 443ab9b2e15Sgtb goto fail; 444ab9b2e15Sgtb goto copy_subkey; 445ab9b2e15Sgtb } 446ab9b2e15Sgtb fail: 447ab9b2e15Sgtb /* SUNW15resync - (as in prev snv code) add if-code and success label fix */ 448ab9b2e15Sgtb if (code) { 449ab9b2e15Sgtb *minor_status = code; 450ab9b2e15Sgtb return GSS_S_FAILURE; 451ab9b2e15Sgtb } 452ab9b2e15Sgtb 453ab9b2e15Sgtb success: 454*159d09a2SMark Phalan return (GSS_S_COMPLETE); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* 458ab9b2e15Sgtb * new_connection 459ab9b2e15Sgtb * 460ab9b2e15Sgtb * Do the grunt work of setting up a new context. 4617c478bd9Sstevel@tonic-gate */ 462ab9b2e15Sgtb static OM_uint32 463ab9b2e15Sgtb new_connection( 464ab9b2e15Sgtb OM_uint32 *minor_status, 465ab9b2e15Sgtb krb5_gss_cred_id_t cred, 466ab9b2e15Sgtb gss_ctx_id_t *context_handle, 467ab9b2e15Sgtb gss_name_t target_name, 468ab9b2e15Sgtb gss_OID mech_type, 469ab9b2e15Sgtb OM_uint32 req_flags, 470ab9b2e15Sgtb OM_uint32 time_req, 471ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings, 472ab9b2e15Sgtb gss_buffer_t input_token, 473ab9b2e15Sgtb gss_OID *actual_mech_type, 474ab9b2e15Sgtb gss_buffer_t output_token, 475ab9b2e15Sgtb OM_uint32 *ret_flags, 476ab9b2e15Sgtb OM_uint32 *time_rec, 477ab9b2e15Sgtb krb5_context context, 478ab9b2e15Sgtb int default_mech) 4797c478bd9Sstevel@tonic-gate { 480ab9b2e15Sgtb OM_uint32 major_status; 481ab9b2e15Sgtb krb5_error_code code; 482ab9b2e15Sgtb krb5_creds *k_cred; 483ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx, *ctx_free; 484ab9b2e15Sgtb krb5_timestamp now; 485ab9b2e15Sgtb gss_buffer_desc token; 4867c478bd9Sstevel@tonic-gate 487ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock); 488ab9b2e15Sgtb major_status = GSS_S_FAILURE; 489ab9b2e15Sgtb token.length = 0; 490ab9b2e15Sgtb token.value = NULL; 4917c478bd9Sstevel@tonic-gate 492ab9b2e15Sgtb /* make sure the cred is usable for init */ 4937c478bd9Sstevel@tonic-gate 494ab9b2e15Sgtb if ((cred->usage != GSS_C_INITIATE) && 495ab9b2e15Sgtb (cred->usage != GSS_C_BOTH)) { 496ab9b2e15Sgtb *minor_status = 0; 497ab9b2e15Sgtb return(GSS_S_NO_CRED); 498ab9b2e15Sgtb } 4997c478bd9Sstevel@tonic-gate 500ab9b2e15Sgtb /* complain if the input token is non-null */ 5017c478bd9Sstevel@tonic-gate 502ab9b2e15Sgtb if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) { 503ab9b2e15Sgtb *minor_status = 0; 504ab9b2e15Sgtb return(GSS_S_DEFECTIVE_TOKEN); 505ab9b2e15Sgtb } 5067c478bd9Sstevel@tonic-gate 507ab9b2e15Sgtb /* create the ctx */ 5087c478bd9Sstevel@tonic-gate 509ab9b2e15Sgtb if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec))) 510ab9b2e15Sgtb == NULL) { 511ab9b2e15Sgtb *minor_status = ENOMEM; 512ab9b2e15Sgtb return(GSS_S_FAILURE); 513ab9b2e15Sgtb } 5147c478bd9Sstevel@tonic-gate 515ab9b2e15Sgtb /* fill in the ctx */ 516ab9b2e15Sgtb memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); 517ab9b2e15Sgtb ctx_free = ctx; 518ab9b2e15Sgtb if ((code = krb5_auth_con_init(context, &ctx->auth_context))) 519ab9b2e15Sgtb goto fail; 520ab9b2e15Sgtb krb5_auth_con_setflags(context, ctx->auth_context, 521ab9b2e15Sgtb KRB5_AUTH_CONTEXT_DO_SEQUENCE); 5227c478bd9Sstevel@tonic-gate 523ab9b2e15Sgtb /* limit the encryption types negotiated (if requested) */ 524ab9b2e15Sgtb if (cred->req_enctypes) { 525ab9b2e15Sgtb if ((code = krb5_set_default_tgs_enctypes(context, 526ab9b2e15Sgtb cred->req_enctypes))) { 527ab9b2e15Sgtb goto fail; 5287c478bd9Sstevel@tonic-gate } 529ab9b2e15Sgtb } 5307c478bd9Sstevel@tonic-gate 531ab9b2e15Sgtb ctx->initiate = 1; 532ab9b2e15Sgtb ctx->gss_flags = (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | 533ab9b2e15Sgtb GSS_C_TRANS_FLAG | 534ab9b2e15Sgtb ((req_flags) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | 535ab9b2e15Sgtb GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG))); 536ab9b2e15Sgtb ctx->seed_init = 0; 537ab9b2e15Sgtb ctx->big_endian = 0; /* all initiators do little-endian, as per spec */ 538ab9b2e15Sgtb ctx->seqstate = 0; 5397c478bd9Sstevel@tonic-gate 540ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now))) 541ab9b2e15Sgtb goto fail; 5427c478bd9Sstevel@tonic-gate 543ab9b2e15Sgtb if (time_req == 0 || time_req == GSS_C_INDEFINITE) { 544ab9b2e15Sgtb ctx->endtime = 0; 545ab9b2e15Sgtb } else { 546ab9b2e15Sgtb ctx->endtime = now + time_req; 547ab9b2e15Sgtb } 5487c478bd9Sstevel@tonic-gate 549ab9b2e15Sgtb if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) 550ab9b2e15Sgtb goto fail; 551ab9b2e15Sgtb 552ab9b2e15Sgtb if ((code = krb5_copy_principal(context, (krb5_principal) target_name, 553ab9b2e15Sgtb &ctx->there))) 554ab9b2e15Sgtb goto fail; 5557c478bd9Sstevel@tonic-gate 556ab9b2e15Sgtb code = get_credentials(context, cred, ctx->there, now, 557ab9b2e15Sgtb ctx->endtime, &k_cred); 558ab9b2e15Sgtb if (code) 559ab9b2e15Sgtb goto fail; 5607c478bd9Sstevel@tonic-gate 561ab9b2e15Sgtb if (default_mech) { 562ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5; 563ab9b2e15Sgtb } 5647c478bd9Sstevel@tonic-gate 565ab9b2e15Sgtb if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used) 566ab9b2e15Sgtb != GSS_S_COMPLETE) { 567ab9b2e15Sgtb code = *minor_status; 568ab9b2e15Sgtb goto fail; 569ab9b2e15Sgtb } 570ab9b2e15Sgtb /* 571ab9b2e15Sgtb * Now try to make it static if at all possible.... 572ab9b2e15Sgtb */ 573ab9b2e15Sgtb ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); 5747c478bd9Sstevel@tonic-gate 575ab9b2e15Sgtb { 576ab9b2e15Sgtb /* gsskrb5 v1 */ 577ab9b2e15Sgtb krb5_ui_4 seq_temp; 578ab9b2e15Sgtb if ((code = make_ap_req_v1(context, ctx, 579ab9b2e15Sgtb cred, k_cred, input_chan_bindings, 580ab9b2e15Sgtb mech_type, &token))) { 581ab9b2e15Sgtb if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || 582ab9b2e15Sgtb (code == KG_EMPTY_CCACHE)) 583ab9b2e15Sgtb major_status = GSS_S_NO_CRED; 584ab9b2e15Sgtb if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) 585ab9b2e15Sgtb major_status = GSS_S_CREDENTIALS_EXPIRED; 586ab9b2e15Sgtb goto fail; 587ab9b2e15Sgtb } 5887c478bd9Sstevel@tonic-gate 589ab9b2e15Sgtb krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, 590ab9b2e15Sgtb (krb5_int32 *)&seq_temp); /* SUNW15resync */ 591ab9b2e15Sgtb ctx->seq_send = seq_temp; 592ab9b2e15Sgtb krb5_auth_con_getsendsubkey(context, ctx->auth_context, 593ab9b2e15Sgtb &ctx->subkey); 594ab9b2e15Sgtb } 5957c478bd9Sstevel@tonic-gate 596ab9b2e15Sgtb major_status = setup_enc(minor_status, ctx, context); 5977c478bd9Sstevel@tonic-gate 598ab9b2e15Sgtb if (k_cred) { 599ab9b2e15Sgtb krb5_free_creds(context, k_cred); 600ab9b2e15Sgtb k_cred = 0; 601ab9b2e15Sgtb } 602ab9b2e15Sgtb 603ab9b2e15Sgtb /* at this point, the context is constructed and valid, 604ab9b2e15Sgtb hence, releaseable */ 6057c478bd9Sstevel@tonic-gate 606ab9b2e15Sgtb /* intern the context handle */ 6077c478bd9Sstevel@tonic-gate 608ab9b2e15Sgtb if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) { 609ab9b2e15Sgtb code = G_VALIDATE_FAILED; 610ab9b2e15Sgtb goto fail; 611ab9b2e15Sgtb } 612ab9b2e15Sgtb *context_handle = (gss_ctx_id_t) ctx; 613ab9b2e15Sgtb ctx_free = 0; 6147c478bd9Sstevel@tonic-gate 615ab9b2e15Sgtb /* compute time_rec */ 616ab9b2e15Sgtb if (time_rec) { 617ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now))) 618ab9b2e15Sgtb goto fail; 619ab9b2e15Sgtb *time_rec = ctx->endtime - now; 620ab9b2e15Sgtb } 6217c478bd9Sstevel@tonic-gate 622ab9b2e15Sgtb /* set the other returns */ 623ab9b2e15Sgtb *output_token = token; 6247c478bd9Sstevel@tonic-gate 625ab9b2e15Sgtb if (ret_flags) 626ab9b2e15Sgtb *ret_flags = ctx->gss_flags; 6277c478bd9Sstevel@tonic-gate 628ab9b2e15Sgtb if (actual_mech_type) 629ab9b2e15Sgtb *actual_mech_type = mech_type; 6307c478bd9Sstevel@tonic-gate 631ab9b2e15Sgtb /* return successfully */ 6327c478bd9Sstevel@tonic-gate 633ab9b2e15Sgtb *minor_status = 0; 634ab9b2e15Sgtb if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) { 635ab9b2e15Sgtb ctx->established = 0; 636ab9b2e15Sgtb return(GSS_S_CONTINUE_NEEDED); 637ab9b2e15Sgtb } else { 638ab9b2e15Sgtb ctx->seq_recv = ctx->seq_send; 639ab9b2e15Sgtb g_order_init(&(ctx->seqstate), ctx->seq_recv, 640ab9b2e15Sgtb (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 641ab9b2e15Sgtb (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto); 642ab9b2e15Sgtb ctx->gss_flags |= GSS_C_PROT_READY_FLAG; 643ab9b2e15Sgtb ctx->established = 1; 644ab9b2e15Sgtb return(GSS_S_COMPLETE); 645ab9b2e15Sgtb } 6467c478bd9Sstevel@tonic-gate 647ab9b2e15Sgtb fail: 648ab9b2e15Sgtb if (ctx_free) { 649ab9b2e15Sgtb if (ctx_free->auth_context) 650ab9b2e15Sgtb krb5_auth_con_free(context, ctx_free->auth_context); 651ab9b2e15Sgtb if (ctx_free->here) 652ab9b2e15Sgtb krb5_free_principal(context, ctx_free->here); 653ab9b2e15Sgtb if (ctx_free->there) 654ab9b2e15Sgtb krb5_free_principal(context, ctx_free->there); 655ab9b2e15Sgtb if (ctx_free->subkey) 656ab9b2e15Sgtb krb5_free_keyblock(context, ctx_free->subkey); 657ab9b2e15Sgtb xfree(ctx_free); 658ab9b2e15Sgtb } else 659ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL); 660ab9b2e15Sgtb 661ab9b2e15Sgtb *minor_status = code; 662ab9b2e15Sgtb return (major_status); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 665ab9b2e15Sgtb /* 666ab9b2e15Sgtb * mutual_auth 667ab9b2e15Sgtb * 668ab9b2e15Sgtb * Handle the reply from the acceptor, if we're doing mutual auth. 669ab9b2e15Sgtb */ 6707c478bd9Sstevel@tonic-gate static OM_uint32 671ab9b2e15Sgtb mutual_auth( 672ab9b2e15Sgtb OM_uint32 *minor_status, 673ab9b2e15Sgtb gss_ctx_id_t *context_handle, 674ab9b2e15Sgtb gss_name_t target_name, 675ab9b2e15Sgtb gss_OID mech_type, 676ab9b2e15Sgtb OM_uint32 req_flags, 677ab9b2e15Sgtb OM_uint32 time_req, 678ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings, 679ab9b2e15Sgtb gss_buffer_t input_token, 680ab9b2e15Sgtb gss_OID *actual_mech_type, 681ab9b2e15Sgtb gss_buffer_t output_token, 682ab9b2e15Sgtb OM_uint32 *ret_flags, 683ab9b2e15Sgtb OM_uint32 *time_rec, 684ab9b2e15Sgtb krb5_context context) 6857c478bd9Sstevel@tonic-gate { 686ab9b2e15Sgtb OM_uint32 major_status; 687ab9b2e15Sgtb unsigned char *ptr; 688ab9b2e15Sgtb char *sptr; 689ab9b2e15Sgtb krb5_data ap_rep; 690ab9b2e15Sgtb krb5_ap_rep_enc_part *ap_rep_data; 691ab9b2e15Sgtb krb5_timestamp now; 692ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx; 693ab9b2e15Sgtb krb5_error *krb_error; 694ab9b2e15Sgtb krb5_error_code code; 695ab9b2e15Sgtb krb5int_access kaccess; 6967c478bd9Sstevel@tonic-gate 697ab9b2e15Sgtb major_status = GSS_S_FAILURE; 6987c478bd9Sstevel@tonic-gate 699ab9b2e15Sgtb code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); 700ab9b2e15Sgtb if (code) 701ab9b2e15Sgtb goto fail; 7027c478bd9Sstevel@tonic-gate 703ab9b2e15Sgtb /* validate the context handle */ 704ab9b2e15Sgtb /*SUPPRESS 29*/ 705ab9b2e15Sgtb if (! kg_validate_ctx_id(*context_handle)) { 706ab9b2e15Sgtb *minor_status = (OM_uint32) G_VALIDATE_FAILED; 707ab9b2e15Sgtb return(GSS_S_NO_CONTEXT); 708ab9b2e15Sgtb } 7097c478bd9Sstevel@tonic-gate 710*159d09a2SMark Phalan ctx = (krb5_gss_ctx_id_t) *context_handle; 7117c478bd9Sstevel@tonic-gate 712ab9b2e15Sgtb /* make sure the context is non-established, and that certain 713ab9b2e15Sgtb arguments are unchanged */ 7147c478bd9Sstevel@tonic-gate 715ab9b2e15Sgtb if ((ctx->established) || 716ab9b2e15Sgtb ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) { 717ab9b2e15Sgtb code = KG_CONTEXT_ESTABLISHED; 718ab9b2e15Sgtb goto fail; 719ab9b2e15Sgtb } 720fe598cdcSmp 721ab9b2e15Sgtb if (! krb5_principal_compare(context, ctx->there, 722ab9b2e15Sgtb (krb5_principal) target_name)) { 723ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, 724ab9b2e15Sgtb context_handle, NULL); 725ab9b2e15Sgtb code = 0; 726ab9b2e15Sgtb major_status = GSS_S_BAD_NAME; 727ab9b2e15Sgtb goto fail; 728ab9b2e15Sgtb } 729fe598cdcSmp 730ab9b2e15Sgtb /* verify the token and leave the AP_REP message in ap_rep */ 731fe598cdcSmp 732ab9b2e15Sgtb if (input_token == GSS_C_NO_BUFFER) { 733ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, 734ab9b2e15Sgtb context_handle, NULL); 735ab9b2e15Sgtb code = 0; 736ab9b2e15Sgtb major_status = GSS_S_DEFECTIVE_TOKEN; 737ab9b2e15Sgtb goto fail; 738ab9b2e15Sgtb } 739fe598cdcSmp 740ab9b2e15Sgtb ptr = (unsigned char *) input_token->value; 7417c478bd9Sstevel@tonic-gate 742ab9b2e15Sgtb if (g_verify_token_header(ctx->mech_used, 743ab9b2e15Sgtb &(ap_rep.length), 744ab9b2e15Sgtb &ptr, KG_TOK_CTX_AP_REP, 745ab9b2e15Sgtb input_token->length, 1)) { 746ab9b2e15Sgtb if (g_verify_token_header((gss_OID) ctx->mech_used, 747ab9b2e15Sgtb &(ap_rep.length), 748ab9b2e15Sgtb &ptr, KG_TOK_CTX_ERROR, 749ab9b2e15Sgtb input_token->length, 1) == 0) { 7507c478bd9Sstevel@tonic-gate 751ab9b2e15Sgtb /* Handle a KRB_ERROR message from the server */ 7527c478bd9Sstevel@tonic-gate 753ab9b2e15Sgtb sptr = (char *) ptr; /* PC compiler bug */ 754ab9b2e15Sgtb TREAD_STR(sptr, ap_rep.data, ap_rep.length); 755ab9b2e15Sgtb 756ab9b2e15Sgtb code = krb5_rd_error(context, &ap_rep, &krb_error); 757ab9b2e15Sgtb if (code) 758ab9b2e15Sgtb goto fail; 759ab9b2e15Sgtb if (krb_error->error) 760ab9b2e15Sgtb code = krb_error->error + ERROR_TABLE_BASE_krb5; 761ab9b2e15Sgtb else 762ab9b2e15Sgtb code = 0; 763ab9b2e15Sgtb krb5_free_error(context, krb_error); 764ab9b2e15Sgtb goto fail; 765ab9b2e15Sgtb } else { 766ab9b2e15Sgtb *minor_status = 0; 767ab9b2e15Sgtb return(GSS_S_DEFECTIVE_TOKEN); 768ab9b2e15Sgtb } 769ab9b2e15Sgtb } 7707c478bd9Sstevel@tonic-gate 771ab9b2e15Sgtb sptr = (char *) ptr; /* PC compiler bug */ 772ab9b2e15Sgtb TREAD_STR(sptr, ap_rep.data, ap_rep.length); 7737c478bd9Sstevel@tonic-gate 774ab9b2e15Sgtb /* decode the ap_rep */ 775ab9b2e15Sgtb if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep, 776ab9b2e15Sgtb &ap_rep_data))) { 777ab9b2e15Sgtb /* 778ab9b2e15Sgtb * XXX A hack for backwards compatiblity. 779ab9b2e15Sgtb * To be removed in 1999 -- proven 780ab9b2e15Sgtb */ 781ab9b2e15Sgtb krb5_auth_con_setuseruserkey(context, ctx->auth_context, 782ab9b2e15Sgtb ctx->subkey); 783ab9b2e15Sgtb if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep, 784ab9b2e15Sgtb &ap_rep_data))) 785ab9b2e15Sgtb goto fail; 786ab9b2e15Sgtb } 7877c478bd9Sstevel@tonic-gate 788ab9b2e15Sgtb /* store away the sequence number */ 789ab9b2e15Sgtb ctx->seq_recv = ap_rep_data->seq_number; 790ab9b2e15Sgtb g_order_init(&(ctx->seqstate), ctx->seq_recv, 791ab9b2e15Sgtb (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 792ab9b2e15Sgtb (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0, ctx->proto); 7937c478bd9Sstevel@tonic-gate 794ab9b2e15Sgtb if (ctx->proto == 1 && ap_rep_data->subkey) { 795ab9b2e15Sgtb /* Keep acceptor's subkey. */ 796ab9b2e15Sgtb ctx->have_acceptor_subkey = 1; 797ab9b2e15Sgtb code = krb5_copy_keyblock(context, ap_rep_data->subkey, 798ab9b2e15Sgtb &ctx->acceptor_subkey); 799ab9b2e15Sgtb if (code) 800ab9b2e15Sgtb goto fail; 801ab9b2e15Sgtb code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, 802ab9b2e15Sgtb ctx->acceptor_subkey->enctype, 803ab9b2e15Sgtb &ctx->acceptor_subkey_cksumtype); 804ab9b2e15Sgtb if (code) 805ab9b2e15Sgtb goto fail; 806ab9b2e15Sgtb } 8077c478bd9Sstevel@tonic-gate 808ab9b2e15Sgtb /* free the ap_rep_data */ 809ab9b2e15Sgtb krb5_free_ap_rep_enc_part(context, ap_rep_data); 8107c478bd9Sstevel@tonic-gate 811ab9b2e15Sgtb /* set established */ 812ab9b2e15Sgtb ctx->established = 1; 8137c478bd9Sstevel@tonic-gate 814ab9b2e15Sgtb /* set returns */ 8157c478bd9Sstevel@tonic-gate 816ab9b2e15Sgtb if (time_rec) { 817ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now))) 818ab9b2e15Sgtb goto fail; 819ab9b2e15Sgtb *time_rec = ctx->endtime - now; 820ab9b2e15Sgtb } 8217c478bd9Sstevel@tonic-gate 822ab9b2e15Sgtb if (ret_flags) 823ab9b2e15Sgtb *ret_flags = ctx->gss_flags; 8247c478bd9Sstevel@tonic-gate 825ab9b2e15Sgtb if (actual_mech_type) 826ab9b2e15Sgtb *actual_mech_type = mech_type; 8277c478bd9Sstevel@tonic-gate 828ab9b2e15Sgtb /* success */ 8297c478bd9Sstevel@tonic-gate 830ab9b2e15Sgtb *minor_status = 0; 831ab9b2e15Sgtb return GSS_S_COMPLETE; 8327c478bd9Sstevel@tonic-gate 833ab9b2e15Sgtb fail: 834ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL); 8357c478bd9Sstevel@tonic-gate 836ab9b2e15Sgtb *minor_status = code; 837ab9b2e15Sgtb return (major_status); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 840ab9b2e15Sgtb OM_uint32 841ab9b2e15Sgtb krb5_gss_init_sec_context(minor_status, claimant_cred_handle, 842ab9b2e15Sgtb context_handle, target_name, mech_type, 843ab9b2e15Sgtb req_flags, time_req, input_chan_bindings, 844ab9b2e15Sgtb input_token, actual_mech_type, output_token, 845ab9b2e15Sgtb ret_flags, time_rec) 846ab9b2e15Sgtb OM_uint32 *minor_status; 847ab9b2e15Sgtb gss_cred_id_t claimant_cred_handle; 848ab9b2e15Sgtb gss_ctx_id_t *context_handle; 849ab9b2e15Sgtb gss_name_t target_name; 850ab9b2e15Sgtb gss_OID mech_type; 851ab9b2e15Sgtb OM_uint32 req_flags; 852ab9b2e15Sgtb OM_uint32 time_req; 853ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings; 854ab9b2e15Sgtb gss_buffer_t input_token; 855ab9b2e15Sgtb gss_OID *actual_mech_type; 856ab9b2e15Sgtb gss_buffer_t output_token; 857ab9b2e15Sgtb OM_uint32 *ret_flags; 858ab9b2e15Sgtb OM_uint32 *time_rec; 8597c478bd9Sstevel@tonic-gate { 860ab9b2e15Sgtb krb5_context context; 861ab9b2e15Sgtb krb5_gss_cred_id_t cred; 862ab9b2e15Sgtb int err; 863ab9b2e15Sgtb krb5_error_code kerr; 864ab9b2e15Sgtb int default_mech = 0; 865ab9b2e15Sgtb OM_uint32 major_status; 866ab9b2e15Sgtb OM_uint32 tmp_min_stat; 8677c478bd9Sstevel@tonic-gate 868ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) { 869ab9b2e15Sgtb kerr = krb5_gss_init_context(&context); 870ab9b2e15Sgtb if (kerr) { 871ab9b2e15Sgtb *minor_status = kerr; 872ab9b2e15Sgtb return GSS_S_FAILURE; 873ab9b2e15Sgtb } 874ab9b2e15Sgtb if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) 875ab9b2e15Sgtb return GSS_S_FAILURE; 876ab9b2e15Sgtb } else { 877ab9b2e15Sgtb context = ((krb5_gss_ctx_id_rec *)*context_handle)->k5_context; 878ab9b2e15Sgtb } 8797c478bd9Sstevel@tonic-gate 880ab9b2e15Sgtb /* set up return values so they can be "freed" successfully */ 8817c478bd9Sstevel@tonic-gate 882ab9b2e15Sgtb major_status = GSS_S_FAILURE; /* Default major code */ 883ab9b2e15Sgtb output_token->length = 0; 884ab9b2e15Sgtb output_token->value = NULL; 885ab9b2e15Sgtb if (actual_mech_type) 886ab9b2e15Sgtb *actual_mech_type = NULL; 8877c478bd9Sstevel@tonic-gate 888ab9b2e15Sgtb /* verify that the target_name is valid and usable */ 8897c478bd9Sstevel@tonic-gate 890ab9b2e15Sgtb if (! kg_validate_name(target_name)) { 891ab9b2e15Sgtb *minor_status = (OM_uint32) G_VALIDATE_FAILED; 892ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) 893ab9b2e15Sgtb krb5_free_context(context); 894ab9b2e15Sgtb return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); 895ab9b2e15Sgtb } 8967c478bd9Sstevel@tonic-gate 897ab9b2e15Sgtb /* verify the credential, or use the default */ 898ab9b2e15Sgtb /*SUPPRESS 29*/ 899ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) { 900ab9b2e15Sgtb /* 901ab9b2e15Sgtb * Solaris Kerberos: here we are using the Solaris specific 902ab9b2e15Sgtb * function get_default_cred() to handle the special case of a 903ab9b2e15Sgtb * root principal 904ab9b2e15Sgtb */ 905ab9b2e15Sgtb major_status = get_default_cred(minor_status, context, 906ab9b2e15Sgtb (gss_cred_id_t *)&cred); 907ab9b2e15Sgtb if (major_status && GSS_ERROR(major_status)) { 908ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) 909ab9b2e15Sgtb krb5_free_context(context); 910ab9b2e15Sgtb return(major_status); 911ab9b2e15Sgtb } 912ab9b2e15Sgtb } else { 913ab9b2e15Sgtb major_status = krb5_gss_validate_cred(minor_status, claimant_cred_handle); 914ab9b2e15Sgtb if (GSS_ERROR(major_status)) { 915ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) 916ab9b2e15Sgtb krb5_free_context(context); 917ab9b2e15Sgtb return(major_status); 918ab9b2e15Sgtb } 919ab9b2e15Sgtb cred = (krb5_gss_cred_id_t) claimant_cred_handle; 920ab9b2e15Sgtb } 921ab9b2e15Sgtb kerr = k5_mutex_lock(&cred->lock); 922ab9b2e15Sgtb if (kerr) { 923ab9b2e15Sgtb krb5_free_context(context); 924ab9b2e15Sgtb *minor_status = kerr; 925ab9b2e15Sgtb return GSS_S_FAILURE; 926ab9b2e15Sgtb } 9277c478bd9Sstevel@tonic-gate 928ab9b2e15Sgtb /* verify the mech_type */ 9297c478bd9Sstevel@tonic-gate 930ab9b2e15Sgtb err = 0; 931ab9b2e15Sgtb if (mech_type == GSS_C_NULL_OID) { 932ab9b2e15Sgtb default_mech = 1; 933ab9b2e15Sgtb if (cred->rfc_mech) { 934ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5; 935ab9b2e15Sgtb } else if (cred->prerfc_mech) { 936ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5_old; 937ab9b2e15Sgtb } else { 938ab9b2e15Sgtb err = 1; 939ab9b2e15Sgtb } 940ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5)) { 941ab9b2e15Sgtb if (!cred->rfc_mech) 942ab9b2e15Sgtb err = 1; 943ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) { 944ab9b2e15Sgtb if (!cred->prerfc_mech) 945ab9b2e15Sgtb err = 1; 946ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5_wrong)) { 947ab9b2e15Sgtb if (!cred->rfc_mech) 948ab9b2e15Sgtb err = 1; 949ab9b2e15Sgtb } else { 950ab9b2e15Sgtb err = 1; 951ab9b2e15Sgtb } 952ab9b2e15Sgtb 953ab9b2e15Sgtb if (err) { 954ab9b2e15Sgtb k5_mutex_unlock(&cred->lock); 955ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) 956ab9b2e15Sgtb krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred); 957ab9b2e15Sgtb *minor_status = 0; 958ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) 959ab9b2e15Sgtb krb5_free_context(context); 960ab9b2e15Sgtb return(GSS_S_BAD_MECH); 961ab9b2e15Sgtb } 9627c478bd9Sstevel@tonic-gate 963ab9b2e15Sgtb /* is this a new connection or not? */ 9647c478bd9Sstevel@tonic-gate 965ab9b2e15Sgtb /*SUPPRESS 29*/ 966ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) { 967ab9b2e15Sgtb major_status = new_connection(minor_status, cred, context_handle, 968ab9b2e15Sgtb target_name, mech_type, req_flags, 969ab9b2e15Sgtb time_req, input_chan_bindings, 970ab9b2e15Sgtb input_token, actual_mech_type, 971ab9b2e15Sgtb output_token, ret_flags, time_rec, 972ab9b2e15Sgtb context, default_mech); 973ab9b2e15Sgtb k5_mutex_unlock(&cred->lock); 974ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) 975ab9b2e15Sgtb krb5_free_context(context); 976ab9b2e15Sgtb else 977ab9b2e15Sgtb ((krb5_gss_ctx_id_rec *) *context_handle)->k5_context = context; 978ab9b2e15Sgtb } else { 979ab9b2e15Sgtb /* mutual_auth doesn't care about the credentials */ 980ab9b2e15Sgtb k5_mutex_unlock(&cred->lock); 981ab9b2e15Sgtb major_status = mutual_auth(minor_status, context_handle, 982ab9b2e15Sgtb target_name, mech_type, req_flags, 983ab9b2e15Sgtb time_req, input_chan_bindings, 984ab9b2e15Sgtb input_token, actual_mech_type, 985ab9b2e15Sgtb output_token, ret_flags, time_rec, 986ab9b2e15Sgtb context); 987ab9b2e15Sgtb /* If context_handle is now NO_CONTEXT, mutual_auth called 988ab9b2e15Sgtb delete_sec_context, which would've zapped the krb5 context 989ab9b2e15Sgtb too. */ 990ab9b2e15Sgtb } 9917c478bd9Sstevel@tonic-gate 992ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) 993ab9b2e15Sgtb krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t *)&cred); 9947c478bd9Sstevel@tonic-gate 995ab9b2e15Sgtb return(major_status); 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 998*159d09a2SMark Phalan #ifndef _WIN32 999ab9b2e15Sgtb k5_mutex_t kg_kdc_flag_mutex = K5_MUTEX_PARTIAL_INITIALIZER; 1000ab9b2e15Sgtb static int kdc_flag = 0; 1001ab9b2e15Sgtb #endif 10027c478bd9Sstevel@tonic-gate 1003ab9b2e15Sgtb krb5_error_code 1004ab9b2e15Sgtb krb5_gss_init_context (krb5_context *ctxp) 10057c478bd9Sstevel@tonic-gate { 1006ab9b2e15Sgtb krb5_error_code err; 1007*159d09a2SMark Phalan #ifndef _WIN32 1008ab9b2e15Sgtb int is_kdc; 1009*159d09a2SMark Phalan #endif 1010ab9b2e15Sgtb 1011ab9b2e15Sgtb err = gssint_initialize_library(); 1012ab9b2e15Sgtb if (err) 1013ab9b2e15Sgtb return err; 1014*159d09a2SMark Phalan #ifndef _WIN32 1015ab9b2e15Sgtb err = k5_mutex_lock(&kg_kdc_flag_mutex); 1016ab9b2e15Sgtb if (err) 1017ab9b2e15Sgtb return err; 1018ab9b2e15Sgtb is_kdc = kdc_flag; 1019ab9b2e15Sgtb k5_mutex_unlock(&kg_kdc_flag_mutex); 1020ab9b2e15Sgtb 1021ab9b2e15Sgtb if (is_kdc) 1022ab9b2e15Sgtb return krb5int_init_context_kdc(ctxp); 1023ab9b2e15Sgtb #endif 10247c478bd9Sstevel@tonic-gate 1025*159d09a2SMark Phalan return krb5_init_context(ctxp); 1026ab9b2e15Sgtb } 10277c478bd9Sstevel@tonic-gate 1028*159d09a2SMark Phalan #ifndef _WIN32 1029ab9b2e15Sgtb krb5_error_code 1030ab9b2e15Sgtb krb5_gss_use_kdc_context() 1031ab9b2e15Sgtb { 1032ab9b2e15Sgtb krb5_error_code err; 1033ab9b2e15Sgtb 1034ab9b2e15Sgtb err = gssint_initialize_library(); 1035ab9b2e15Sgtb if (err) 1036ab9b2e15Sgtb return err; 1037ab9b2e15Sgtb err = k5_mutex_lock(&kg_kdc_flag_mutex); 1038ab9b2e15Sgtb if (err) 1039ab9b2e15Sgtb return err; 1040ab9b2e15Sgtb kdc_flag = 1; 1041ab9b2e15Sgtb k5_mutex_unlock(&kg_kdc_flag_mutex); 1042ab9b2e15Sgtb return 0; 1043ab9b2e15Sgtb } 1044ab9b2e15Sgtb #endif 10457c478bd9Sstevel@tonic-gate 1046ab9b2e15Sgtb /* Solaris Kerberos specific routines start */ 10477c478bd9Sstevel@tonic-gate 1048ab9b2e15Sgtb #define ROOT_UID 0 1049ab9b2e15Sgtb #define KRB5_DEFAULT_LIFE 60*60*10 1050ab9b2e15Sgtb #define CACHE_FILENAME_LEN 35 10517c478bd9Sstevel@tonic-gate 1052ab9b2e15Sgtb extern int 1053ab9b2e15Sgtb safechown(const char *src, uid_t uid, gid_t gid, int mode); 10547c478bd9Sstevel@tonic-gate 1055ab9b2e15Sgtb static krb5_boolean 1056ab9b2e15Sgtb principal_ignore_inst_compare(context, princ1, princ2) 1057ab9b2e15Sgtb krb5_context context; 1058ab9b2e15Sgtb krb5_const_principal princ1; 1059ab9b2e15Sgtb krb5_const_principal princ2; 1060ab9b2e15Sgtb { 1061ab9b2e15Sgtb krb5_int32 nelem; 10627c478bd9Sstevel@tonic-gate 1063ab9b2e15Sgtb nelem = krb5_princ_size(context, princ1); 1064ab9b2e15Sgtb if (nelem != krb5_princ_size(context, princ2)) 1065ab9b2e15Sgtb return FALSE; 10667c478bd9Sstevel@tonic-gate 1067ab9b2e15Sgtb if (! krb5_realm_compare(context, princ1, princ2)) 1068ab9b2e15Sgtb return FALSE; 10697c478bd9Sstevel@tonic-gate 1070ab9b2e15Sgtb /* 1071ab9b2e15Sgtb * Solaris Kerberos 1072ab9b2e15Sgtb * If princ1 is elem1/metachar@REALM, compare just elem1 (and REALM). 1073ab9b2e15Sgtb */ 1074ab9b2e15Sgtb if (nelem == 2) { 1075ab9b2e15Sgtb const krb5_data *p = krb5_princ_component(context, princ1, 1); 1076ab9b2e15Sgtb 1077ab9b2e15Sgtb if (p->length == 1) { 1078ab9b2e15Sgtb const char *s = p->data; 10797c478bd9Sstevel@tonic-gate 1080ab9b2e15Sgtb if (s[0] == '*') { 1081ab9b2e15Sgtb const krb5_data *p1 = krb5_princ_component(context, princ1, 0); 1082ab9b2e15Sgtb const krb5_data *p2 = krb5_princ_component(context, princ2, 0); 10837c478bd9Sstevel@tonic-gate 1084ab9b2e15Sgtb if (p1->length != p2->length || 1085ab9b2e15Sgtb memcmp(p1->data, p2->data, p1->length)) 1086ab9b2e15Sgtb return FALSE; 1087ab9b2e15Sgtb 1088ab9b2e15Sgtb return TRUE; 1089ab9b2e15Sgtb } 1090ab9b2e15Sgtb } 1091ab9b2e15Sgtb } 1092ab9b2e15Sgtb 1093ab9b2e15Sgtb return FALSE; 1094ab9b2e15Sgtb } 10957c478bd9Sstevel@tonic-gate 1096ab9b2e15Sgtb /* 1097ab9b2e15Sgtb * Solaris Kerberos 1098ab9b2e15Sgtb * This is a dup of krb5_ktfile_get_entry (sigh) but is necessary to 1099ab9b2e15Sgtb * to get a custom princ compare above (principal_ignore_inst_compare) 1100ab9b2e15Sgtb * and thus avoid mucking w/important krb5 internal 1101ab9b2e15Sgtb * api (krb5_principal_compare) 1102ab9b2e15Sgtb */ 1103ab9b2e15Sgtb #include "../krb5/keytab/file/ktfile.h" 11047c478bd9Sstevel@tonic-gate 1105ab9b2e15Sgtb static krb5_error_code KRB5_CALLCONV 1106ab9b2e15Sgtb ktfile_get_entry(context, id, principal, kvno, enctype, entry) 1107ab9b2e15Sgtb krb5_context context; 1108ab9b2e15Sgtb krb5_keytab id; 1109ab9b2e15Sgtb krb5_const_principal principal; 1110ab9b2e15Sgtb krb5_kvno kvno; 1111ab9b2e15Sgtb krb5_enctype enctype; 1112ab9b2e15Sgtb krb5_keytab_entry * entry; 1113ab9b2e15Sgtb { 1114ab9b2e15Sgtb krb5_keytab_entry cur_entry, new_entry; 1115ab9b2e15Sgtb krb5_error_code kerror = 0; 1116ab9b2e15Sgtb int found_wrong_kvno = 0; 1117ab9b2e15Sgtb krb5_boolean similar; 1118ab9b2e15Sgtb int kvno_offset = 0; 11197c478bd9Sstevel@tonic-gate 1120ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() start\n"); 11217c478bd9Sstevel@tonic-gate 1122ab9b2e15Sgtb /* Open the keyfile for reading */ 1123ab9b2e15Sgtb if ((kerror = krb5_ktfileint_openr(context, id))){ 1124ab9b2e15Sgtb KRB5_LOG(KRB5_ERR, "ktfile_get_entry() end, ktfileint_openr() " 1125ab9b2e15Sgtb "kerror= %d\n", kerror); 1126ab9b2e15Sgtb return(kerror); 1127ab9b2e15Sgtb } 11287c478bd9Sstevel@tonic-gate 1129ab9b2e15Sgtb /* 1130ab9b2e15Sgtb * For efficiency and simplicity, we'll use a while true that 1131ab9b2e15Sgtb * is exited with a break statement. 1132ab9b2e15Sgtb */ 1133ab9b2e15Sgtb cur_entry.principal = 0; 1134ab9b2e15Sgtb cur_entry.vno = 0; 1135ab9b2e15Sgtb cur_entry.key.contents = 0; 1136ab9b2e15Sgtb /*CONSTCOND*/ 1137ab9b2e15Sgtb while (TRUE) { 1138ab9b2e15Sgtb if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry))) 1139ab9b2e15Sgtb break; 11407c478bd9Sstevel@tonic-gate 1141ab9b2e15Sgtb /* 1142ab9b2e15Sgtb * by the time this loop exits, it must either free cur_entry, 1143ab9b2e15Sgtb * and copy new_entry there, or free new_entry. Otherwise, it 1144ab9b2e15Sgtb * leaks. 1145ab9b2e15Sgtb */ 1146ab9b2e15Sgtb 1147ab9b2e15Sgtb /* 1148ab9b2e15Sgtb * if the principal isn't the one requested, free new_entry 1149ab9b2e15Sgtb * and continue to the next. 1150ab9b2e15Sgtb */ 11517c478bd9Sstevel@tonic-gate 1152ab9b2e15Sgtb if (!principal_ignore_inst_compare(context, principal, 1153ab9b2e15Sgtb new_entry.principal)) { 1154ab9b2e15Sgtb krb5_kt_free_entry(context, &new_entry); 1155ab9b2e15Sgtb continue; 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate 1158ab9b2e15Sgtb /* 1159ab9b2e15Sgtb * if the enctype is not ignored and doesn't match, free new_entry 1160ab9b2e15Sgtb * and continue to the next 1161ab9b2e15Sgtb */ 11627c478bd9Sstevel@tonic-gate 1163ab9b2e15Sgtb if (enctype != IGNORE_ENCTYPE) { 1164ab9b2e15Sgtb if ((kerror = krb5_c_enctype_compare(context, enctype, 1165ab9b2e15Sgtb new_entry.key.enctype, 1166ab9b2e15Sgtb &similar))) { 1167ab9b2e15Sgtb krb5_kt_free_entry(context, &new_entry); 1168ab9b2e15Sgtb break; 1169ab9b2e15Sgtb } 11707c478bd9Sstevel@tonic-gate 1171ab9b2e15Sgtb if (!similar) { 1172ab9b2e15Sgtb krb5_kt_free_entry(context, &new_entry); 1173ab9b2e15Sgtb continue; 1174ab9b2e15Sgtb } 1175ab9b2e15Sgtb /* 1176ab9b2e15Sgtb * Coerce the enctype of the output keyblock in case we 1177ab9b2e15Sgtb * got an inexact match on the enctype. 1178ab9b2e15Sgtb */ 1179ab9b2e15Sgtb new_entry.key.enctype = enctype; 1180ab9b2e15Sgtb } 11817c478bd9Sstevel@tonic-gate 1182ab9b2e15Sgtb if (kvno == IGNORE_VNO) { 1183ab9b2e15Sgtb /* 1184ab9b2e15Sgtb * if this is the first match, or if the new vno is 1185ab9b2e15Sgtb * bigger, free the current and keep the new. Otherwise, 1186ab9b2e15Sgtb * free the new. 1187ab9b2e15Sgtb */ 1188ab9b2e15Sgtb /* 1189ab9b2e15Sgtb * A 1.2.x keytab contains only the low 8 bits of the key 1190ab9b2e15Sgtb * version number. Since it can be much bigger, and thus 1191ab9b2e15Sgtb * the 8-bit value can wrap, we need some heuristics to 1192ab9b2e15Sgtb * figure out the "highest" numbered key if some numbers 1193ab9b2e15Sgtb * close to 255 and some near 0 are used. 1194ab9b2e15Sgtb * 1195ab9b2e15Sgtb * The heuristic here: 11967c478bd9Sstevel@tonic-gate 1197ab9b2e15Sgtb * If we have any keys with versions over 240, then assume 1198ab9b2e15Sgtb * that all version numbers 0-127 refer to 256+N instead. 1199ab9b2e15Sgtb * Not perfect, but maybe good enough? 1200ab9b2e15Sgtb */ 12017c478bd9Sstevel@tonic-gate 1202ab9b2e15Sgtb #define M(VNO) (((VNO) - kvno_offset + 256) % 256) 12037c478bd9Sstevel@tonic-gate 1204ab9b2e15Sgtb if (new_entry.vno > 240) 1205ab9b2e15Sgtb kvno_offset = 128; 1206ab9b2e15Sgtb if (! cur_entry.principal || 1207ab9b2e15Sgtb M(new_entry.vno) > M(cur_entry.vno)) { 1208ab9b2e15Sgtb krb5_kt_free_entry(context, &cur_entry); 1209ab9b2e15Sgtb cur_entry = new_entry; 1210ab9b2e15Sgtb } else { 1211ab9b2e15Sgtb krb5_kt_free_entry(context, &new_entry); 1212ab9b2e15Sgtb } 1213ab9b2e15Sgtb } else { 1214ab9b2e15Sgtb /* 1215ab9b2e15Sgtb * if this kvno matches, free the current (will there ever 1216ab9b2e15Sgtb * be one?), keep the new, and break out. Otherwise, remember 1217ab9b2e15Sgtb * that we were here so we can return the right error, and 1218ab9b2e15Sgtb * free the new 1219ab9b2e15Sgtb */ 1220ab9b2e15Sgtb /* 1221ab9b2e15Sgtb * Yuck. The krb5-1.2.x keytab format only stores one byte 1222ab9b2e15Sgtb * for the kvno, so we're toast if the kvno requested is 1223ab9b2e15Sgtb * higher than that. Short-term workaround: only compare 1224ab9b2e15Sgtb * the low 8 bits. 1225ab9b2e15Sgtb */ 12267c478bd9Sstevel@tonic-gate 1227ab9b2e15Sgtb if (new_entry.vno == (kvno & 0xff)) { 1228ab9b2e15Sgtb krb5_kt_free_entry(context, &cur_entry); 1229ab9b2e15Sgtb cur_entry = new_entry; 1230ab9b2e15Sgtb break; 1231ab9b2e15Sgtb } else { 1232ab9b2e15Sgtb found_wrong_kvno++; 1233ab9b2e15Sgtb krb5_kt_free_entry(context, &new_entry); 1234ab9b2e15Sgtb } 12357c478bd9Sstevel@tonic-gate } 1236ab9b2e15Sgtb } 12377c478bd9Sstevel@tonic-gate 1238ab9b2e15Sgtb if (kerror == KRB5_KT_END) { 1239ab9b2e15Sgtb if (cur_entry.principal) 1240ab9b2e15Sgtb kerror = 0; 1241ab9b2e15Sgtb else if (found_wrong_kvno) 1242ab9b2e15Sgtb kerror = KRB5_KT_KVNONOTFOUND; 1243ab9b2e15Sgtb else 1244ab9b2e15Sgtb kerror = KRB5_KT_NOTFOUND; 1245ab9b2e15Sgtb } 1246ab9b2e15Sgtb if (kerror) { 1247ab9b2e15Sgtb (void) krb5_ktfileint_close(context, id); 1248ab9b2e15Sgtb krb5_kt_free_entry(context, &cur_entry); 1249ab9b2e15Sgtb KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, kerror=" 1250ab9b2e15Sgtb "%d\n", kerror); 1251ab9b2e15Sgtb return kerror; 1252ab9b2e15Sgtb } 1253ab9b2e15Sgtb if ((kerror = krb5_ktfileint_close(context, id)) != 0) { 1254ab9b2e15Sgtb krb5_kt_free_entry(context, &cur_entry); 1255ab9b2e15Sgtb KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, ktfileint_close() " 1256ab9b2e15Sgtb "kerror= %d\n", kerror); 1257ab9b2e15Sgtb return kerror; 1258ab9b2e15Sgtb } 1259ab9b2e15Sgtb *entry = cur_entry; 12607c478bd9Sstevel@tonic-gate 1261ab9b2e15Sgtb /* Let us close the file before we leave */ 1262ab9b2e15Sgtb (void) krb5_ktfileint_close(context, id); 12637c478bd9Sstevel@tonic-gate 1264ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() end"); 1265ab9b2e15Sgtb 1266ab9b2e15Sgtb return 0; 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 1269ab9b2e15Sgtb 12707c478bd9Sstevel@tonic-gate /* 1271ab9b2e15Sgtb * Solaris Kerberos 1272ab9b2e15Sgtb * Given a princ of name/instance@LOCALREALM, search the keytab 1273ab9b2e15Sgtb * for a match of name and LOCALREALM and if found, return instance 1274ab9b2e15Sgtb * as a string. 12757c478bd9Sstevel@tonic-gate * 1276ab9b2e15Sgtb * Caller must free returned string. 12777c478bd9Sstevel@tonic-gate */ 1278ab9b2e15Sgtb static krb5_error_code 1279ab9b2e15Sgtb get_instance_keytab( 1280ab9b2e15Sgtb krb5_context context, 1281ab9b2e15Sgtb const char *sname, 1282ab9b2e15Sgtb krb5_keytab keytab, 1283ab9b2e15Sgtb char **instance) /* out */ 12847c478bd9Sstevel@tonic-gate { 1285ab9b2e15Sgtb krb5_error_code ret=0; 1286ab9b2e15Sgtb krb5_keytab_entry kt_ent; 1287ab9b2e15Sgtb krb5_int32 nelem, free_kt_ent=0; 1288ab9b2e15Sgtb register const krb5_data *p; 1289ab9b2e15Sgtb char *realm=NULL, *s=NULL; 1290ab9b2e15Sgtb krb5_principal client=NULL, princ=NULL; 12917c478bd9Sstevel@tonic-gate 1292ab9b2e15Sgtb if (!keytab) 1293ab9b2e15Sgtb return EINVAL; 12947c478bd9Sstevel@tonic-gate 1295ab9b2e15Sgtb if (ret = krb5_get_default_realm(context, &realm)) 1296ab9b2e15Sgtb return ret; 12977c478bd9Sstevel@tonic-gate 1298ab9b2e15Sgtb ret = krb5_build_principal(context, &client, strlen(realm), 1299ab9b2e15Sgtb realm, sname, "*", 1300ab9b2e15Sgtb (char *)0); 1301ab9b2e15Sgtb if (ret) 1302ab9b2e15Sgtb goto out; 13037c478bd9Sstevel@tonic-gate 1304ab9b2e15Sgtb ret = ktfile_get_entry(context, keytab, client, 1305ab9b2e15Sgtb 0, /* don't have vno available */ 1306ab9b2e15Sgtb 0, &kt_ent); 1307ab9b2e15Sgtb if (ret) 1308ab9b2e15Sgtb goto out; 13097c478bd9Sstevel@tonic-gate 1310ab9b2e15Sgtb free_kt_ent++; /* kt_ent is not a ptr */ 13117c478bd9Sstevel@tonic-gate 1312ab9b2e15Sgtb princ = kt_ent.principal; 1313ab9b2e15Sgtb nelem = krb5_princ_size(context, princ); 1314ab9b2e15Sgtb if (nelem != 2) { 1315ab9b2e15Sgtb ret = KRB5_PRINC_NOMATCH; 1316ab9b2e15Sgtb goto out; 1317ab9b2e15Sgtb } 13187c478bd9Sstevel@tonic-gate 1319ab9b2e15Sgtb p = krb5_princ_component(context, princ, 1); 1320ab9b2e15Sgtb s = calloc(p->length + sizeof(char), sizeof(char)); 1321ab9b2e15Sgtb if (!s) { 1322ab9b2e15Sgtb ret = ENOMEM; 1323ab9b2e15Sgtb goto out; 1324ab9b2e15Sgtb } 13257c478bd9Sstevel@tonic-gate 1326ab9b2e15Sgtb (void) memcpy(s, p->data, p->length); 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate 1329ab9b2e15Sgtb out: 1330ab9b2e15Sgtb free(realm); 1331ab9b2e15Sgtb if (client) 1332ab9b2e15Sgtb krb5_free_principal(context, client); 1333ab9b2e15Sgtb if (free_kt_ent) 1334ab9b2e15Sgtb (void) krb5_kt_free_entry(context, &kt_ent); 1335ab9b2e15Sgtb 1336ab9b2e15Sgtb if (ret == 0) 1337ab9b2e15Sgtb *instance = s; 1338ab9b2e15Sgtb return ret; 1339ab9b2e15Sgtb } 13407c478bd9Sstevel@tonic-gate 1341ab9b2e15Sgtb static OM_uint32 1342ab9b2e15Sgtb load_root_cred_using_keytab( 1343ab9b2e15Sgtb OM_uint32 *minor_status, 1344ab9b2e15Sgtb krb5_context context, 1345ab9b2e15Sgtb const char *sname, 1346ab9b2e15Sgtb int use_nodename) 1347ab9b2e15Sgtb { 1348ab9b2e15Sgtb krb5_creds my_creds; 1349ab9b2e15Sgtb krb5_principal me; 1350ab9b2e15Sgtb krb5_principal server; 1351ab9b2e15Sgtb krb5_error_code code; 1352ab9b2e15Sgtb krb5_ccache ccache = NULL; 1353ab9b2e15Sgtb krb5_keytab keytab = NULL; 1354ab9b2e15Sgtb krb5_timestamp now; 1355ab9b2e15Sgtb krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */ 1356ab9b2e15Sgtb krb5_get_init_creds_opt opt; 1357ab9b2e15Sgtb krb5_data tgtname = { 1358ab9b2e15Sgtb 0, 1359ab9b2e15Sgtb KRB5_TGS_NAME_SIZE, 1360ab9b2e15Sgtb KRB5_TGS_NAME 1361ab9b2e15Sgtb }; 1362ab9b2e15Sgtb char *svcname = NULL; 13637c478bd9Sstevel@tonic-gate 1364ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() start \n"); 13657c478bd9Sstevel@tonic-gate 1366ab9b2e15Sgtb if (!sname) 1367ab9b2e15Sgtb return (GSS_S_FAILURE); 13687c478bd9Sstevel@tonic-gate 1369ab9b2e15Sgtb memset((char *)&my_creds, 0, sizeof(my_creds)); 13707c478bd9Sstevel@tonic-gate 1371ab9b2e15Sgtb if (code = krb5_kt_default(context, &keytab)) { 1372ab9b2e15Sgtb *minor_status = code; 1373ab9b2e15Sgtb return (GSS_S_FAILURE); 1374ab9b2e15Sgtb } 13757c478bd9Sstevel@tonic-gate 1376ab9b2e15Sgtb if (!use_nodename) { 1377ab9b2e15Sgtb char *instance = NULL; 13787c478bd9Sstevel@tonic-gate 1379ab9b2e15Sgtb code = get_instance_keytab(context, sname, keytab, &instance); 1380ab9b2e15Sgtb if (code == 0) { 1381ab9b2e15Sgtb code = krb5_sname_to_principal(context, 1382ab9b2e15Sgtb instance, sname, 1383ab9b2e15Sgtb KRB5_NT_UNKNOWN, &me); 1384ab9b2e15Sgtb free(instance); 1385ab9b2e15Sgtb } 1386ab9b2e15Sgtb } else { 1387ab9b2e15Sgtb code = krb5_sname_to_principal(context, NULL, sname, 1388ab9b2e15Sgtb KRB5_NT_SRV_HST, &me); 1389ab9b2e15Sgtb } 1390ab9b2e15Sgtb if (code) { 1391ab9b2e15Sgtb (void) krb5_kt_close(context, keytab); 1392ab9b2e15Sgtb *minor_status = code; 1393ab9b2e15Sgtb return (GSS_S_FAILURE); 1394ab9b2e15Sgtb } 13957c478bd9Sstevel@tonic-gate 1396ab9b2e15Sgtb my_creds.client = me; 13977c478bd9Sstevel@tonic-gate 1398ab9b2e15Sgtb if((code = krb5_build_principal_ext(context, &server, 1399ab9b2e15Sgtb krb5_princ_realm(context, me)->length, 1400ab9b2e15Sgtb krb5_princ_realm(context, me)->data, 1401ab9b2e15Sgtb tgtname.length, tgtname.data, 1402ab9b2e15Sgtb krb5_princ_realm(context, me)->length, 1403ab9b2e15Sgtb krb5_princ_realm(context, me)->data, 1404ab9b2e15Sgtb 0))) { 1405ab9b2e15Sgtb *minor_status = code; 1406ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1407ab9b2e15Sgtb (void) krb5_kt_close(context, keytab); 14087c478bd9Sstevel@tonic-gate 1409ab9b2e15Sgtb return (GSS_S_FAILURE); 1410ab9b2e15Sgtb } 14117c478bd9Sstevel@tonic-gate 1412ab9b2e15Sgtb my_creds.server = server; 1413ab9b2e15Sgtb my_creds.times.starttime = 0; /* start timer 1414ab9b2e15Sgtb * when request 1415ab9b2e15Sgtb * gets to KDC 1416ab9b2e15Sgtb */ 1417ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now))) { 1418ab9b2e15Sgtb *minor_status = code; 1419ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1420ab9b2e15Sgtb (void) krb5_kt_close(context, keytab); 14217c478bd9Sstevel@tonic-gate 1422ab9b2e15Sgtb return (GSS_S_FAILURE); 1423ab9b2e15Sgtb } 1424ab9b2e15Sgtb my_creds.times.endtime = now + lifetime; 1425ab9b2e15Sgtb my_creds.times.renew_till = 0; 14267c478bd9Sstevel@tonic-gate 1427ab9b2e15Sgtb memset(&opt, 0, sizeof (opt)); 1428ab9b2e15Sgtb krb5_get_init_creds_opt_init(&opt); 1429ab9b2e15Sgtb krb5_get_init_creds_opt_set_tkt_life(&opt, lifetime); 14307c478bd9Sstevel@tonic-gate 1431ab9b2e15Sgtb code = krb5_unparse_name(context, server, &svcname); 1432ab9b2e15Sgtb if (code != 0) { 1433ab9b2e15Sgtb *minor_status = code; 1434ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1435ab9b2e15Sgtb (void) krb5_kt_close(context, keytab); 14367c478bd9Sstevel@tonic-gate 1437ab9b2e15Sgtb return (GSS_S_FAILURE); 1438ab9b2e15Sgtb } 1439ab9b2e15Sgtb /* 1440ab9b2e15Sgtb * Evidently (sigh), on success, krb5_get_init_creds_keytab 1441ab9b2e15Sgtb * changes the my_creds princ ptrs so we need to free those 1442ab9b2e15Sgtb * princs (me&server) as well as freeing all of my_creds contents. 1443ab9b2e15Sgtb */ 1444ab9b2e15Sgtb code = krb5_get_init_creds_keytab(context, 1445ab9b2e15Sgtb &my_creds, me, keytab, 1446ab9b2e15Sgtb 0, svcname, &opt); 14477c478bd9Sstevel@tonic-gate 1448ab9b2e15Sgtb (void) krb5_kt_close(context, keytab); 14497c478bd9Sstevel@tonic-gate 1450ab9b2e15Sgtb if (svcname != NULL) 1451ab9b2e15Sgtb free(svcname); 1452ab9b2e15Sgtb if (code) { 1453ab9b2e15Sgtb *minor_status = code; 1454ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 14557c478bd9Sstevel@tonic-gate 1456ab9b2e15Sgtb return (GSS_S_FAILURE); 1457ab9b2e15Sgtb } 14587c478bd9Sstevel@tonic-gate 1459ab9b2e15Sgtb krb5_free_principal(context, server); 1460ab9b2e15Sgtb server = NULL; 14617c478bd9Sstevel@tonic-gate 1462ab9b2e15Sgtb code = krb5_cc_resolve (context, 1463ab9b2e15Sgtb krb5_cc_default_name(context), 1464ab9b2e15Sgtb &ccache); 1465ab9b2e15Sgtb if (code != 0) { 1466ab9b2e15Sgtb *minor_status = code; 1467ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1468ab9b2e15Sgtb krb5_free_principal(context, me); 14697c478bd9Sstevel@tonic-gate 1470ab9b2e15Sgtb return (GSS_S_FAILURE); 1471ab9b2e15Sgtb } 1472ab9b2e15Sgtb code = krb5_cc_initialize (context, ccache, me); 1473ab9b2e15Sgtb krb5_free_principal(context, me); 1474ab9b2e15Sgtb me = NULL; 1475ab9b2e15Sgtb if (code != 0) { 1476ab9b2e15Sgtb *minor_status = code; 1477ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1478ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 14797c478bd9Sstevel@tonic-gate 1480ab9b2e15Sgtb return (GSS_S_FAILURE); 1481ab9b2e15Sgtb } 14827c478bd9Sstevel@tonic-gate 1483ab9b2e15Sgtb code = krb5_cc_store_cred(context, ccache, 1484ab9b2e15Sgtb &my_creds); 1485ab9b2e15Sgtb krb5_free_cred_contents(context, &my_creds); 1486ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 14877c478bd9Sstevel@tonic-gate 1488ab9b2e15Sgtb if (code) { 1489ab9b2e15Sgtb *minor_status = code; 14907c478bd9Sstevel@tonic-gate 1491ab9b2e15Sgtb KRB5_LOG(KRB5_ERR, "load_root_cred_using_keytab() end, error " 1492ab9b2e15Sgtb "code = %d\n", code); 14937c478bd9Sstevel@tonic-gate 1494ab9b2e15Sgtb return (GSS_S_FAILURE); 14957c478bd9Sstevel@tonic-gate } 1496ab9b2e15Sgtb 1497ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() end \n"); 14987c478bd9Sstevel@tonic-gate 1499ab9b2e15Sgtb return (GSS_S_COMPLETE); 1500ab9b2e15Sgtb } 15017c478bd9Sstevel@tonic-gate 1502ab9b2e15Sgtb static OM_uint32 1503ab9b2e15Sgtb renew_ccache(OM_uint32 *minor_status, krb5_context context, uid_t uid) 1504ab9b2e15Sgtb { 1505ab9b2e15Sgtb krb5_principal me; 1506ab9b2e15Sgtb krb5_principal server; 1507ab9b2e15Sgtb krb5_creds creds; 1508ab9b2e15Sgtb krb5_creds tmpcreds; 1509ab9b2e15Sgtb krb5_creds *out_creds; 1510ab9b2e15Sgtb krb5_error_code code; 1511ab9b2e15Sgtb krb5_ccache ccache = NULL; 1512ab9b2e15Sgtb static char ccache_name_buf[CACHE_FILENAME_LEN]; 1513ab9b2e15Sgtb int options = 0; 1514ab9b2e15Sgtb krb5_data tgtname = { 1515ab9b2e15Sgtb 0, 1516ab9b2e15Sgtb KRB5_TGS_NAME_SIZE, 1517ab9b2e15Sgtb KRB5_TGS_NAME 1518ab9b2e15Sgtb }; 1519ab9b2e15Sgtb gid_t gid = getgid(); 15207c478bd9Sstevel@tonic-gate 1521ab9b2e15Sgtb memset((char *)&creds, 0, sizeof(creds)); 1522ab9b2e15Sgtb memset((char *)&tmpcreds, 0, sizeof(creds)); 15237c478bd9Sstevel@tonic-gate 1524ab9b2e15Sgtb if ((code = krb5_cc_default(context, &ccache))) { 1525ab9b2e15Sgtb *minor_status = code; 1526ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 1527ab9b2e15Sgtb return (GSS_S_FAILURE); 1528ab9b2e15Sgtb } 15297c478bd9Sstevel@tonic-gate 1530ab9b2e15Sgtb if ((code = krb5_cc_get_principal(context, ccache, &me)) != 0) { 1531ab9b2e15Sgtb *minor_status = code; 1532ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 1533ab9b2e15Sgtb return (GSS_S_FAILURE); 1534ab9b2e15Sgtb } 15357c478bd9Sstevel@tonic-gate 1536ab9b2e15Sgtb creds.client = me; 15377c478bd9Sstevel@tonic-gate 1538ab9b2e15Sgtb if((code = krb5_build_principal_ext(context, &server, 1539ab9b2e15Sgtb krb5_princ_realm(context, me)->length, 1540ab9b2e15Sgtb krb5_princ_realm(context, me)->data, 1541ab9b2e15Sgtb tgtname.length, tgtname.data, 1542ab9b2e15Sgtb krb5_princ_realm(context, me)->length, 1543ab9b2e15Sgtb krb5_princ_realm(context, me)->data, 1544ab9b2e15Sgtb 0))) { 1545ab9b2e15Sgtb krb5_free_principal(context, me); 1546ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 1547ab9b2e15Sgtb *minor_status = code; 1548ab9b2e15Sgtb return (GSS_S_FAILURE); 1549ab9b2e15Sgtb } 15507c478bd9Sstevel@tonic-gate 1551ab9b2e15Sgtb creds.server = server; 1552ab9b2e15Sgtb creds.ticket_flags = TKT_FLG_RENEWABLE; 1553ab9b2e15Sgtb 1554ab9b2e15Sgtb if ((krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_FLAGS, 1555ab9b2e15Sgtb &creds, &tmpcreds))) { 1556ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 1557ab9b2e15Sgtb return (KDC_ERR_BADOPTION); 1558ab9b2e15Sgtb } 1559ab9b2e15Sgtb 1560ab9b2e15Sgtb creds.ticket_flags = 0; 1561ab9b2e15Sgtb code = krb5_get_credentials_renew(context, options, ccache, 1562ab9b2e15Sgtb &creds, &out_creds); 1563ab9b2e15Sgtb krb5_free_cred_contents(context, &creds); 1564ab9b2e15Sgtb krb5_free_cred_contents(context, &tmpcreds); 15657c478bd9Sstevel@tonic-gate 1566ab9b2e15Sgtb if (code) { 1567ab9b2e15Sgtb *minor_status = code; 1568ab9b2e15Sgtb return (GSS_S_FAILURE); 1569ab9b2e15Sgtb } 15707c478bd9Sstevel@tonic-gate 1571ab9b2e15Sgtb krb5_free_creds(context, out_creds); 1572ab9b2e15Sgtb snprintf(ccache_name_buf, CACHE_FILENAME_LEN, "/tmp/krb5cc_%d", 1573ab9b2e15Sgtb uid, -1); 1574ab9b2e15Sgtb code = safechown(ccache_name_buf, uid, gid, -1); 15757c478bd9Sstevel@tonic-gate 1576ab9b2e15Sgtb if (code == -1) { 1577ab9b2e15Sgtb (void) krb5_cc_destroy(context, ccache); 1578ab9b2e15Sgtb *minor_status = code; 1579ab9b2e15Sgtb return (GSS_S_FAILURE); 1580ab9b2e15Sgtb } 15817c478bd9Sstevel@tonic-gate 1582ab9b2e15Sgtb (void) krb5_cc_close(context, ccache); 1583ab9b2e15Sgtb 1584ab9b2e15Sgtb return (GSS_S_COMPLETE); 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate /* 1589ab9b2e15Sgtb * Solaris Kerberos: 1590ab9b2e15Sgtb * We enforce a minimum refresh time on the root cred. This avoids problems for 1591ab9b2e15Sgtb * the higher level communication protocol for having valid creds and 1592ab9b2e15Sgtb * setting up a valid context, only to have it expire before or while 1593ab9b2e15Sgtb * it is being used. For non root users we don't care since we do not refresh 1594ab9b2e15Sgtb * there creds, they get what they can get. 15957c478bd9Sstevel@tonic-gate */ 1596ab9b2e15Sgtb #define MIN_REFRESH_TIME 300 1597ab9b2e15Sgtb #define MIN_RENEW_TIME 1500 1598ab9b2e15Sgtb 1599ab9b2e15Sgtb /* get_default_cred() must be called with the krb5_mutex lock held */ 1600ab9b2e15Sgtb static OM_uint32 1601ab9b2e15Sgtb get_default_cred(OM_uint32 *minor_status, void *ct, gss_cred_id_t *cred_handle) 16027c478bd9Sstevel@tonic-gate { 1603ab9b2e15Sgtb krb5_timestamp now; 1604ab9b2e15Sgtb krb5_gss_cred_id_t cred; 1605ab9b2e15Sgtb OM_uint32 major; 1606ab9b2e15Sgtb OM_uint32 mntmp; 1607ab9b2e15Sgtb /* 1608ab9b2e15Sgtb * Solaris Kerberos 1609ab9b2e15Sgtb * Use krb5_getuid() to select the mechanism to obtain the uid. 1610ab9b2e15Sgtb */ 1611ab9b2e15Sgtb uid_t uid = krb5_getuid(); 1612ab9b2e15Sgtb krb5_context context = (krb5_context)ct; 16137c478bd9Sstevel@tonic-gate 1614ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "get_default_cred() start\n"); 16157c478bd9Sstevel@tonic-gate 1616ab9b2e15Sgtb /* Get the default cred for user */ 1617ab9b2e15Sgtb if (((major = kg_get_defcred(minor_status, cred_handle)) != NULL) && 1618ab9b2e15Sgtb GSS_ERROR(major)) { 16197c478bd9Sstevel@tonic-gate 1620ab9b2e15Sgtb /* If we're not root we're done */ 1621ab9b2e15Sgtb if (uid != ROOT_UID) 1622ab9b2e15Sgtb return (major); 16237c478bd9Sstevel@tonic-gate 1624ab9b2e15Sgtb /* 1625ab9b2e15Sgtb * Try and get root's cred in the cache using keytab. 1626ab9b2e15Sgtb * 1627ab9b2e15Sgtb * First try "root" and then try "host" - this allows 1628ab9b2e15Sgtb * Secure NFS to use the host principal for mounting if 1629ab9b2e15Sgtb * there is no root principal. 1630ab9b2e15Sgtb * 1631ab9b2e15Sgtb * Then try "host/<anything>" to match any instance (needed 1632ab9b2e15Sgtb * for DHCP clients). 1633ab9b2e15Sgtb */ 1634ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1635ab9b2e15Sgtb context, "root", 1); 16367c478bd9Sstevel@tonic-gate 1637ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1638ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1639ab9b2e15Sgtb context, "host", 1); 1640ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1641ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1642ab9b2e15Sgtb context, "host", 0); 16437c478bd9Sstevel@tonic-gate 1644ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1645ab9b2e15Sgtb return (major); 16467c478bd9Sstevel@tonic-gate 1647ab9b2e15Sgtb /* We should have valid tgt now in the cache, so get it. */ 1648ab9b2e15Sgtb major = kg_get_defcred(minor_status, cred_handle); 16497c478bd9Sstevel@tonic-gate 1650ab9b2e15Sgtb return (major); 1651ab9b2e15Sgtb } 16527c478bd9Sstevel@tonic-gate 1653ab9b2e15Sgtb /* We've got a gss cred handle that is a kerberos cred handle. */ 1654ab9b2e15Sgtb cred = (krb5_gss_cred_id_t)*cred_handle; 1655ab9b2e15Sgtb 1656ab9b2e15Sgtb /* If we can't get the time, assume the worst. */ 1657ab9b2e15Sgtb if (krb5_timeofday(context, &now)) { 1658ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle); 1659ab9b2e15Sgtb return (GSS_S_CREDENTIALS_EXPIRED); 1660ab9b2e15Sgtb } 16617c478bd9Sstevel@tonic-gate 1662ab9b2e15Sgtb /* If root's cred has expired re-get it */ 1663ab9b2e15Sgtb if (cred->tgt_expire < now + MIN_REFRESH_TIME && uid == ROOT_UID) { 1664ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle); 16657c478bd9Sstevel@tonic-gate 1666ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1667ab9b2e15Sgtb context, "root", 1); 16687c478bd9Sstevel@tonic-gate 1669ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1670ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1671ab9b2e15Sgtb context, "host", 1); 16727c478bd9Sstevel@tonic-gate 1673ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1674ab9b2e15Sgtb major = load_root_cred_using_keytab(minor_status, 1675ab9b2e15Sgtb context, "host", 0); 1676ab9b2e15Sgtb 1677ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1678ab9b2e15Sgtb return (major); 1679ab9b2e15Sgtb 1680ab9b2e15Sgtb major = kg_get_defcred(minor_status, cred_handle); 1681ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1682ab9b2e15Sgtb return (major); 1683ab9b2e15Sgtb 1684ab9b2e15Sgtb /* Any body else is SOL unless we can renew their credential cache */ 1685ab9b2e15Sgtb } else if ((cred->tgt_expire < now + MIN_RENEW_TIME) && 1686ab9b2e15Sgtb (cred->tgt_expire > now)) { 1687ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle); 1688ab9b2e15Sgtb 1689ab9b2e15Sgtb major = renew_ccache(minor_status, context, uid); 1690ab9b2e15Sgtb if ((major != GSS_S_COMPLETE) && 1691ab9b2e15Sgtb (major != KDC_ERR_BADOPTION)) 1692ab9b2e15Sgtb return (major); 1693ab9b2e15Sgtb 1694ab9b2e15Sgtb major = kg_get_defcred(minor_status, cred_handle); 1695ab9b2e15Sgtb if (major != GSS_S_COMPLETE) 1696ab9b2e15Sgtb return (major); 16977c478bd9Sstevel@tonic-gate 1698ab9b2e15Sgtb } 16997c478bd9Sstevel@tonic-gate 1700ab9b2e15Sgtb /* Otherwise we got non expired creds */ 17017c478bd9Sstevel@tonic-gate 1702ab9b2e15Sgtb KRB5_LOG0(KRB5_INFO, "get_default_cred() end\n"); 17037c478bd9Sstevel@tonic-gate 1704ab9b2e15Sgtb return (GSS_S_COMPLETE); 17057c478bd9Sstevel@tonic-gate } 1706ab9b2e15Sgtb 1707ab9b2e15Sgtb /* Solaris Kerberos specific routines end */ 1708