17c478bd9Sstevel@tonic-gate /*
25e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate /*
5ab9b2e15Sgtb * Copyright 2000,2002, 2003 by the Massachusetts Institute of Technology.
67c478bd9Sstevel@tonic-gate * All Rights Reserved.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
97c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
107c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
117c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
147c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
157c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
167c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
177c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
187c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
197c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
207c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
217c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
227c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
237c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
247c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
257c478bd9Sstevel@tonic-gate * or implied warranty.
267c478bd9Sstevel@tonic-gate *
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc.
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, distribute, and sell this software
327c478bd9Sstevel@tonic-gate * and its documentation for any purpose is hereby granted without fee,
337c478bd9Sstevel@tonic-gate * provided that the above copyright notice appears in all copies and
347c478bd9Sstevel@tonic-gate * that both that copyright notice and this permission notice appear in
357c478bd9Sstevel@tonic-gate * supporting documentation, and that the name of OpenVision not be used
367c478bd9Sstevel@tonic-gate * in advertising or publicity pertaining to distribution of the software
377c478bd9Sstevel@tonic-gate * without specific, written prior permission. OpenVision makes no
387c478bd9Sstevel@tonic-gate * representations about the suitability of this software for any
397c478bd9Sstevel@tonic-gate * purpose. It is provided "as is" without express or implied warranty.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
427c478bd9Sstevel@tonic-gate * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
437c478bd9Sstevel@tonic-gate * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
447c478bd9Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
457c478bd9Sstevel@tonic-gate * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
467c478bd9Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
477c478bd9Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC.
527c478bd9Sstevel@tonic-gate *
537c478bd9Sstevel@tonic-gate * All rights reserved.
547c478bd9Sstevel@tonic-gate *
557c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require
567c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the
577c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to
587c478bd9Sstevel@tonic-gate * obtain such a license before exporting.
597c478bd9Sstevel@tonic-gate *
607c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
617c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
627c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
637c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
647c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
657c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining
667c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
677c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of
687c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
697c478bd9Sstevel@tonic-gate * or implied warranty.
707c478bd9Sstevel@tonic-gate *
717c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
727c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
737c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate
76db02be57S /* Solaris Kerberos */
77db02be57S #include <libintl.h>
78db02be57S #include <locale.h>
79db02be57S
80ab9b2e15Sgtb #include "k5-int.h"
81ab9b2e15Sgtb #include "gss_libinit.h"
82159d09a2SMark Phalan #include "gssapiP_krb5.h"
83ab9b2e15Sgtb #include "mglueP.h"
84ab9b2e15Sgtb #ifdef HAVE_MEMORY_H
857c478bd9Sstevel@tonic-gate #include <memory.h>
86ab9b2e15Sgtb #endif
877c478bd9Sstevel@tonic-gate #include <stdlib.h>
887c478bd9Sstevel@tonic-gate #include <assert.h>
89ab9b2e15Sgtb
90ab9b2e15Sgtb /* Solaris Kerberos start */
91ab9b2e15Sgtb static OM_uint32 get_default_cred(OM_uint32 *, void *, gss_cred_id_t *);
92ab9b2e15Sgtb /* Solaris Kerberos end */
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /*
95159d09a2SMark Phalan * $Id: init_sec_context.c 18721 2006-10-16 16:18:29Z epeisach $
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate
98ab9b2e15Sgtb /* XXX This is for debugging only!!! Should become a real bitfield
99ab9b2e15Sgtb at some point */
1007c478bd9Sstevel@tonic-gate int krb5_gss_dbg_client_expcreds = 0;
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * Common code which fetches the correct krb5 credentials from the
1047c478bd9Sstevel@tonic-gate * ccache.
1057c478bd9Sstevel@tonic-gate */
get_credentials(context,cred,server,now,endtime,out_creds)1067c478bd9Sstevel@tonic-gate static krb5_error_code get_credentials(context, cred, server, now,
1077c478bd9Sstevel@tonic-gate endtime, out_creds)
1087c478bd9Sstevel@tonic-gate krb5_context context;
1097c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred;
1107c478bd9Sstevel@tonic-gate krb5_principal server;
1117c478bd9Sstevel@tonic-gate krb5_timestamp now;
1127c478bd9Sstevel@tonic-gate krb5_timestamp endtime;
1137c478bd9Sstevel@tonic-gate krb5_creds **out_creds;
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate krb5_error_code code;
1167c478bd9Sstevel@tonic-gate krb5_creds in_creds;
1177c478bd9Sstevel@tonic-gate
118ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock);
1197c478bd9Sstevel@tonic-gate memset((char *) &in_creds, 0, sizeof(krb5_creds));
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client)))
1227c478bd9Sstevel@tonic-gate goto cleanup;
1237c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, server, &in_creds.server)))
1247c478bd9Sstevel@tonic-gate goto cleanup;
1257c478bd9Sstevel@tonic-gate in_creds.times.endtime = endtime;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate in_creds.keyblock.enctype = 0;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate code = krb5_get_credentials(context, 0, cred->ccache,
1307c478bd9Sstevel@tonic-gate &in_creds, out_creds);
1317c478bd9Sstevel@tonic-gate if (code)
1327c478bd9Sstevel@tonic-gate goto cleanup;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate * Enforce a stricter limit (without timeskew forgiveness at the
1367c478bd9Sstevel@tonic-gate * boundaries) because accept_sec_context code is also similarly
1377c478bd9Sstevel@tonic-gate * non-forgiving.
1387c478bd9Sstevel@tonic-gate */
1397c478bd9Sstevel@tonic-gate if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL &&
1407c478bd9Sstevel@tonic-gate (*out_creds)->times.endtime < now) {
1417c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_TKT_EXPIRED;
1427c478bd9Sstevel@tonic-gate goto cleanup;
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate cleanup:
1467c478bd9Sstevel@tonic-gate if (in_creds.client)
1477c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.client);
1487c478bd9Sstevel@tonic-gate if (in_creds.server)
1497c478bd9Sstevel@tonic-gate krb5_free_principal(context, in_creds.server);
1507c478bd9Sstevel@tonic-gate return code;
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate struct gss_checksum_data {
1537c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx;
1547c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred;
1557c478bd9Sstevel@tonic-gate krb5_checksum md5;
1567c478bd9Sstevel@tonic-gate krb5_data checksum_data;
1577c478bd9Sstevel@tonic-gate };
1587c478bd9Sstevel@tonic-gate
159ab9b2e15Sgtb #ifdef CFX_EXERCISE
160ab9b2e15Sgtb #include "../../krb5/krb/auth_con.h"
161ab9b2e15Sgtb #endif
1627c478bd9Sstevel@tonic-gate static krb5_error_code KRB5_CALLCONV
make_gss_checksum(krb5_context context,krb5_auth_context auth_context,void * cksum_data,krb5_data ** out)1637c478bd9Sstevel@tonic-gate make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
1647c478bd9Sstevel@tonic-gate void *cksum_data, krb5_data **out)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate krb5_error_code code;
1677c478bd9Sstevel@tonic-gate krb5_int32 con_flags;
1687c478bd9Sstevel@tonic-gate unsigned char *ptr;
1697c478bd9Sstevel@tonic-gate struct gss_checksum_data *data = cksum_data;
1707c478bd9Sstevel@tonic-gate krb5_data credmsg;
171ab9b2e15Sgtb unsigned int junk;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate data->checksum_data.data = 0;
1747c478bd9Sstevel@tonic-gate credmsg.data = 0;
1757c478bd9Sstevel@tonic-gate /* build the checksum field */
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate if (data->ctx->gss_flags & GSS_C_DELEG_FLAG) {
1787c478bd9Sstevel@tonic-gate /* first get KRB_CRED message, so we know its length */
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* clear the time check flag that was set in krb5_auth_con_init() */
1817c478bd9Sstevel@tonic-gate krb5_auth_con_getflags(context, auth_context, &con_flags);
1827c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context,
1837c478bd9Sstevel@tonic-gate con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME);
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate code = krb5_fwd_tgt_creds(context, auth_context, 0,
1867c478bd9Sstevel@tonic-gate data->cred->princ, data->ctx->there,
1877c478bd9Sstevel@tonic-gate data->cred->ccache, 1,
1887c478bd9Sstevel@tonic-gate &credmsg);
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */
1917c478bd9Sstevel@tonic-gate krb5_auth_con_setflags(context, auth_context, con_flags);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (code) {
1947c478bd9Sstevel@tonic-gate /* don't fail here; just don't accept/do the delegation
1957c478bd9Sstevel@tonic-gate request */
1967c478bd9Sstevel@tonic-gate data->ctx->gss_flags &= ~GSS_C_DELEG_FLAG;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate data->checksum_data.length = 24;
1997c478bd9Sstevel@tonic-gate } else {
2007c478bd9Sstevel@tonic-gate if (credmsg.length+28 > KRB5_INT16_MAX) {
2017c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg);
2027c478bd9Sstevel@tonic-gate return(KRB5KRB_ERR_FIELD_TOOLONG);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate data->checksum_data.length = 28+credmsg.length;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate } else {
2087c478bd9Sstevel@tonic-gate data->checksum_data.length = 24;
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate #ifdef CFX_EXERCISE
211ab9b2e15Sgtb if (data->ctx->auth_context->keyblock != NULL
212ab9b2e15Sgtb && data->ctx->auth_context->keyblock->enctype == 18) {
2137c478bd9Sstevel@tonic-gate srand(time(0) ^ getpid());
2147c478bd9Sstevel@tonic-gate /* Our ftp client code stupidly assumes a base64-encoded
2157c478bd9Sstevel@tonic-gate version of the token will fit in 10K, so don't make this
2167c478bd9Sstevel@tonic-gate too big. */
2177c478bd9Sstevel@tonic-gate junk = rand() & 0xff;
2187c478bd9Sstevel@tonic-gate } else
2197c478bd9Sstevel@tonic-gate junk = 0;
2207c478bd9Sstevel@tonic-gate #else
2217c478bd9Sstevel@tonic-gate junk = 0;
2227c478bd9Sstevel@tonic-gate #endif
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate data->checksum_data.length += junk;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* now allocate a buffer to hold the checksum data and
2277c478bd9Sstevel@tonic-gate (maybe) KRB_CRED msg */
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if ((data->checksum_data.data =
2307c478bd9Sstevel@tonic-gate (char *) xmalloc(data->checksum_data.length)) == NULL) {
2317c478bd9Sstevel@tonic-gate if (credmsg.data)
2327c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg);
2337c478bd9Sstevel@tonic-gate return(ENOMEM);
2347c478bd9Sstevel@tonic-gate }
235159d09a2SMark Phalan /* Solaris Kerberos */
236ab9b2e15Sgtb ptr = (uchar_t *)data->checksum_data.data; /* SUNW15resync */
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->md5.length, 0);
2397c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) data->md5.contents, data->md5.length);
2407c478bd9Sstevel@tonic-gate TWRITE_INT(ptr, data->ctx->gss_flags, 0);
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate /* done with this, free it */
2437c478bd9Sstevel@tonic-gate xfree(data->md5.contents);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate if (credmsg.data) {
2467c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, KRB5_GSS_FOR_CREDS_OPTION, 0);
2477c478bd9Sstevel@tonic-gate TWRITE_INT16(ptr, credmsg.length, 0);
2487c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) credmsg.data, credmsg.length);
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate /* free credmsg data */
2517c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &credmsg);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate if (junk)
2547c478bd9Sstevel@tonic-gate memset(ptr, 'i', junk);
2557c478bd9Sstevel@tonic-gate *out = &data->checksum_data;
2567c478bd9Sstevel@tonic-gate return 0;
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate static krb5_error_code
make_ap_req_v1(context,ctx,cred,k_cred,chan_bindings,mech_type,token)2607c478bd9Sstevel@tonic-gate make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token)
2617c478bd9Sstevel@tonic-gate krb5_context context;
2627c478bd9Sstevel@tonic-gate krb5_gss_ctx_id_rec *ctx;
2637c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred;
2647c478bd9Sstevel@tonic-gate krb5_creds *k_cred;
2657c478bd9Sstevel@tonic-gate gss_channel_bindings_t chan_bindings;
2667c478bd9Sstevel@tonic-gate gss_OID mech_type;
2677c478bd9Sstevel@tonic-gate gss_buffer_t token;
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate krb5_flags mk_req_flags = 0;
2707c478bd9Sstevel@tonic-gate krb5_error_code code;
2717c478bd9Sstevel@tonic-gate struct gss_checksum_data cksum_struct;
2727c478bd9Sstevel@tonic-gate krb5_checksum md5;
2737c478bd9Sstevel@tonic-gate krb5_data ap_req;
2747c478bd9Sstevel@tonic-gate krb5_data *checksum_data = NULL;
2757c478bd9Sstevel@tonic-gate unsigned char *ptr;
2767c478bd9Sstevel@tonic-gate unsigned char *t;
277ab9b2e15Sgtb unsigned int tlen;
2787c478bd9Sstevel@tonic-gate
279ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock);
2807c478bd9Sstevel@tonic-gate ap_req.data = 0;
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate /* compute the hash of the channel bindings */
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5, 0)))
2857c478bd9Sstevel@tonic-gate return(code);
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate krb5_auth_con_set_req_cksumtype(context, ctx->auth_context,
2887c478bd9Sstevel@tonic-gate CKSUMTYPE_KG_CB);
2897c478bd9Sstevel@tonic-gate cksum_struct.md5 = md5;
2907c478bd9Sstevel@tonic-gate cksum_struct.ctx = ctx;
2917c478bd9Sstevel@tonic-gate cksum_struct.cred = cred;
2927c478bd9Sstevel@tonic-gate cksum_struct.checksum_data.data = NULL;
2937c478bd9Sstevel@tonic-gate switch (k_cred->keyblock.enctype) {
2947c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_CRC:
2957c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD4:
2967c478bd9Sstevel@tonic-gate case ENCTYPE_DES_CBC_MD5:
2977c478bd9Sstevel@tonic-gate case ENCTYPE_DES3_CBC_SHA1:
2987c478bd9Sstevel@tonic-gate code = make_gss_checksum(context, ctx->auth_context, &cksum_struct,
2997c478bd9Sstevel@tonic-gate &checksum_data);
3007c478bd9Sstevel@tonic-gate if (code)
3017c478bd9Sstevel@tonic-gate goto cleanup;
3027c478bd9Sstevel@tonic-gate break;
3037c478bd9Sstevel@tonic-gate default:
3047c478bd9Sstevel@tonic-gate krb5_auth_con_set_checksum_func(context, ctx->auth_context,
3057c478bd9Sstevel@tonic-gate make_gss_checksum, &cksum_struct);
3067c478bd9Sstevel@tonic-gate break;
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
309ab9b2e15Sgtb
3107c478bd9Sstevel@tonic-gate /* call mk_req. subkey and ap_req need to be used or destroyed */
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate mk_req_flags = AP_OPTS_USE_SUBKEY;
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate if (ctx->gss_flags & GSS_C_MUTUAL_FLAG)
3157c478bd9Sstevel@tonic-gate mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED;
3167c478bd9Sstevel@tonic-gate
317ab9b2e15Sgtb code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags,
318ab9b2e15Sgtb checksum_data, k_cred, &ap_req);
319ab9b2e15Sgtb krb5_free_data_contents(context, &cksum_struct.checksum_data);
320ab9b2e15Sgtb if (code)
3217c478bd9Sstevel@tonic-gate goto cleanup;
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate /* store the interesting stuff from creds and authent */
3247c478bd9Sstevel@tonic-gate ctx->endtime = k_cred->times.endtime;
3257c478bd9Sstevel@tonic-gate ctx->krb_flags = k_cred->ticket_flags;
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate /* build up the token */
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate /* allocate space for the token */
3307c478bd9Sstevel@tonic-gate tlen = g_token_size((gss_OID) mech_type, ap_req.length);
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
3337c478bd9Sstevel@tonic-gate code = ENOMEM;
3347c478bd9Sstevel@tonic-gate goto cleanup;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate /* fill in the buffer */
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate ptr = t;
3407c478bd9Sstevel@tonic-gate
341ab9b2e15Sgtb g_make_token_header(mech_type, ap_req.length,
3427c478bd9Sstevel@tonic-gate &ptr, KG_TOK_CTX_AP_REQ);
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate TWRITE_STR(ptr, (unsigned char *) ap_req.data, ap_req.length);
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate /* pass it back */
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate token->length = tlen;
3497c478bd9Sstevel@tonic-gate token->value = (void *) t;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate code = 0;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate cleanup:
354ab9b2e15Sgtb if (checksum_data && checksum_data->data)
355ab9b2e15Sgtb krb5_free_data_contents(context, checksum_data);
3567c478bd9Sstevel@tonic-gate if (ap_req.data)
357ab9b2e15Sgtb krb5_free_data_contents(context, &ap_req);
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate return (code);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
362ab9b2e15Sgtb /*
363ab9b2e15Sgtb * setup_enc
364ab9b2e15Sgtb *
365ab9b2e15Sgtb * Fill in the encryption descriptors. Called after AP-REQ is made.
366ab9b2e15Sgtb */
367ab9b2e15Sgtb static OM_uint32
setup_enc(OM_uint32 * minor_status,krb5_gss_ctx_id_rec * ctx,krb5_context context)368ab9b2e15Sgtb setup_enc(
369ab9b2e15Sgtb OM_uint32 *minor_status,
370ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx,
371ab9b2e15Sgtb krb5_context context)
372ab9b2e15Sgtb {
373ab9b2e15Sgtb krb5_error_code code;
374ab9b2e15Sgtb int i;
375ab9b2e15Sgtb krb5int_access kaccess;
376ab9b2e15Sgtb
377ab9b2e15Sgtb code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
378ab9b2e15Sgtb if (code)
379ab9b2e15Sgtb goto fail;
380ab9b2e15Sgtb
381ab9b2e15Sgtb ctx->have_acceptor_subkey = 0;
382ab9b2e15Sgtb ctx->proto = 0;
383ab9b2e15Sgtb ctx->cksumtype = 0;
384ab9b2e15Sgtb switch(ctx->subkey->enctype) {
385ab9b2e15Sgtb case ENCTYPE_DES_CBC_MD5:
386ab9b2e15Sgtb case ENCTYPE_DES_CBC_MD4:
387ab9b2e15Sgtb case ENCTYPE_DES_CBC_CRC:
388ab9b2e15Sgtb ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
389ab9b2e15Sgtb ctx->signalg = SGN_ALG_DES_MAC_MD5;
390ab9b2e15Sgtb ctx->cksum_size = 8;
391ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_DES;
392ab9b2e15Sgtb
393ab9b2e15Sgtb /* The encryption key is the session key XOR
394ab9b2e15Sgtb 0xf0f0f0f0f0f0f0f0. */
395ab9b2e15Sgtb if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
396ab9b2e15Sgtb goto fail;
397ab9b2e15Sgtb
398ab9b2e15Sgtb for (i=0; i<ctx->enc->length; i++)
399ab9b2e15Sgtb ctx->enc->contents[i] ^= 0xf0;
400ab9b2e15Sgtb
401ab9b2e15Sgtb goto copy_subkey_to_seq;
402ab9b2e15Sgtb
403ab9b2e15Sgtb case ENCTYPE_DES3_CBC_SHA1:
404ab9b2e15Sgtb /* MIT extension */
405ab9b2e15Sgtb ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
406ab9b2e15Sgtb ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
407ab9b2e15Sgtb ctx->cksum_size = 20;
408ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_DES3KD;
409ab9b2e15Sgtb
410ab9b2e15Sgtb copy_subkey:
411ab9b2e15Sgtb code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
412ab9b2e15Sgtb if (code)
413ab9b2e15Sgtb goto fail;
414ab9b2e15Sgtb copy_subkey_to_seq:
415ab9b2e15Sgtb code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
416ab9b2e15Sgtb if (code) {
417ab9b2e15Sgtb krb5_free_keyblock (context, ctx->enc);
418ab9b2e15Sgtb goto fail;
419ab9b2e15Sgtb }
420ab9b2e15Sgtb goto success;
421ab9b2e15Sgtb
422ab9b2e15Sgtb case ENCTYPE_ARCFOUR_HMAC:
423ab9b2e15Sgtb /* Microsoft extension */
424ab9b2e15Sgtb ctx->signalg = SGN_ALG_HMAC_MD5 ;
425ab9b2e15Sgtb ctx->cksum_size = 8;
426ab9b2e15Sgtb ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
427ab9b2e15Sgtb
428ab9b2e15Sgtb goto copy_subkey;
429ab9b2e15Sgtb
430ab9b2e15Sgtb default:
431ab9b2e15Sgtb /* Fill some fields we shouldn't be using on this path
432ab9b2e15Sgtb with garbage. */
433ab9b2e15Sgtb ctx->signalg = -10;
434ab9b2e15Sgtb ctx->sealalg = -10;
435ab9b2e15Sgtb
436ab9b2e15Sgtb ctx->proto = 1;
437ab9b2e15Sgtb code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
438ab9b2e15Sgtb &ctx->cksumtype);
439ab9b2e15Sgtb if (code)
440ab9b2e15Sgtb goto fail;
441ab9b2e15Sgtb code = krb5_c_checksum_length(context, ctx->cksumtype,
442ab9b2e15Sgtb &ctx->cksum_size);
443ab9b2e15Sgtb if (code)
444ab9b2e15Sgtb goto fail;
445ab9b2e15Sgtb goto copy_subkey;
446ab9b2e15Sgtb }
447ab9b2e15Sgtb fail:
448ab9b2e15Sgtb /* SUNW15resync - (as in prev snv code) add if-code and success label fix */
449ab9b2e15Sgtb if (code) {
450ab9b2e15Sgtb *minor_status = code;
451ab9b2e15Sgtb return GSS_S_FAILURE;
452ab9b2e15Sgtb }
453ab9b2e15Sgtb
454ab9b2e15Sgtb success:
455159d09a2SMark Phalan return (GSS_S_COMPLETE);
456ab9b2e15Sgtb }
457ab9b2e15Sgtb
458ab9b2e15Sgtb /*
459ab9b2e15Sgtb * new_connection
460ab9b2e15Sgtb *
461ab9b2e15Sgtb * Do the grunt work of setting up a new context.
462ab9b2e15Sgtb */
463ab9b2e15Sgtb static OM_uint32
new_connection(OM_uint32 * minor_status,krb5_gss_cred_id_t cred,gss_ctx_id_t * context_handle,gss_name_t target_name,gss_OID mech_type,OM_uint32 req_flags,OM_uint32 time_req,gss_channel_bindings_t input_chan_bindings,gss_buffer_t input_token,gss_OID * actual_mech_type,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec,krb5_context context,int default_mech)464ab9b2e15Sgtb new_connection(
465ab9b2e15Sgtb OM_uint32 *minor_status,
466ab9b2e15Sgtb krb5_gss_cred_id_t cred,
467ab9b2e15Sgtb gss_ctx_id_t *context_handle,
468ab9b2e15Sgtb gss_name_t target_name,
469ab9b2e15Sgtb gss_OID mech_type,
470ab9b2e15Sgtb OM_uint32 req_flags,
471ab9b2e15Sgtb OM_uint32 time_req,
472ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings,
473ab9b2e15Sgtb gss_buffer_t input_token,
474ab9b2e15Sgtb gss_OID *actual_mech_type,
475ab9b2e15Sgtb gss_buffer_t output_token,
476ab9b2e15Sgtb OM_uint32 *ret_flags,
477ab9b2e15Sgtb OM_uint32 *time_rec,
478ab9b2e15Sgtb krb5_context context,
479ab9b2e15Sgtb int default_mech)
480ab9b2e15Sgtb {
481ab9b2e15Sgtb OM_uint32 major_status;
482ab9b2e15Sgtb krb5_error_code code;
483ab9b2e15Sgtb krb5_creds *k_cred;
484ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx, *ctx_free;
485ab9b2e15Sgtb krb5_timestamp now;
486ab9b2e15Sgtb gss_buffer_desc token;
487ab9b2e15Sgtb
488ab9b2e15Sgtb k5_mutex_assert_locked(&cred->lock);
489ab9b2e15Sgtb major_status = GSS_S_FAILURE;
490ab9b2e15Sgtb token.length = 0;
491ab9b2e15Sgtb token.value = NULL;
492ab9b2e15Sgtb
493ab9b2e15Sgtb /* make sure the cred is usable for init */
494ab9b2e15Sgtb
495ab9b2e15Sgtb if ((cred->usage != GSS_C_INITIATE) &&
496ab9b2e15Sgtb (cred->usage != GSS_C_BOTH)) {
497ab9b2e15Sgtb *minor_status = 0;
498ab9b2e15Sgtb return(GSS_S_NO_CRED);
499ab9b2e15Sgtb }
500ab9b2e15Sgtb
501ab9b2e15Sgtb /* complain if the input token is non-null */
502ab9b2e15Sgtb
503ab9b2e15Sgtb if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
504ab9b2e15Sgtb *minor_status = 0;
505ab9b2e15Sgtb return(GSS_S_DEFECTIVE_TOKEN);
506ab9b2e15Sgtb }
507ab9b2e15Sgtb
508ab9b2e15Sgtb /* create the ctx */
509ab9b2e15Sgtb
510ab9b2e15Sgtb if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
511ab9b2e15Sgtb == NULL) {
512ab9b2e15Sgtb *minor_status = ENOMEM;
513ab9b2e15Sgtb return(GSS_S_FAILURE);
514ab9b2e15Sgtb }
515ab9b2e15Sgtb
516ab9b2e15Sgtb /* fill in the ctx */
517ab9b2e15Sgtb memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
518ab9b2e15Sgtb ctx_free = ctx;
519ab9b2e15Sgtb if ((code = krb5_auth_con_init(context, &ctx->auth_context)))
520ab9b2e15Sgtb goto fail;
521ab9b2e15Sgtb krb5_auth_con_setflags(context, ctx->auth_context,
522ab9b2e15Sgtb KRB5_AUTH_CONTEXT_DO_SEQUENCE);
523ab9b2e15Sgtb
524ab9b2e15Sgtb /* limit the encryption types negotiated (if requested) */
525ab9b2e15Sgtb if (cred->req_enctypes) {
526ab9b2e15Sgtb if ((code = krb5_set_default_tgs_enctypes(context,
527ab9b2e15Sgtb cred->req_enctypes))) {
528ab9b2e15Sgtb goto fail;
529ab9b2e15Sgtb }
530ab9b2e15Sgtb }
531ab9b2e15Sgtb
532ab9b2e15Sgtb ctx->initiate = 1;
533ab9b2e15Sgtb ctx->gss_flags = (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
534ab9b2e15Sgtb GSS_C_TRANS_FLAG |
535ab9b2e15Sgtb ((req_flags) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
536ab9b2e15Sgtb GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
537ab9b2e15Sgtb ctx->seed_init = 0;
538ab9b2e15Sgtb ctx->big_endian = 0; /* all initiators do little-endian, as per spec */
539ab9b2e15Sgtb ctx->seqstate = 0;
540ab9b2e15Sgtb
541ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now)))
542ab9b2e15Sgtb goto fail;
543ab9b2e15Sgtb
544ab9b2e15Sgtb if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
545ab9b2e15Sgtb ctx->endtime = 0;
546ab9b2e15Sgtb } else {
547ab9b2e15Sgtb ctx->endtime = now + time_req;
548ab9b2e15Sgtb }
549ab9b2e15Sgtb
550ab9b2e15Sgtb if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
551ab9b2e15Sgtb goto fail;
552ab9b2e15Sgtb
553ab9b2e15Sgtb if ((code = krb5_copy_principal(context, (krb5_principal) target_name,
554ab9b2e15Sgtb &ctx->there)))
555ab9b2e15Sgtb goto fail;
556ab9b2e15Sgtb
557ab9b2e15Sgtb code = get_credentials(context, cred, ctx->there, now,
558ab9b2e15Sgtb ctx->endtime, &k_cred);
559ab9b2e15Sgtb if (code)
560ab9b2e15Sgtb goto fail;
561ab9b2e15Sgtb
562ab9b2e15Sgtb if (default_mech) {
563ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5;
564ab9b2e15Sgtb }
565ab9b2e15Sgtb
566ab9b2e15Sgtb if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used)
567ab9b2e15Sgtb != GSS_S_COMPLETE) {
568ab9b2e15Sgtb code = *minor_status;
569ab9b2e15Sgtb goto fail;
570ab9b2e15Sgtb }
571ab9b2e15Sgtb /*
572ab9b2e15Sgtb * Now try to make it static if at all possible....
573ab9b2e15Sgtb */
574ab9b2e15Sgtb ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
575ab9b2e15Sgtb
576ab9b2e15Sgtb {
577ab9b2e15Sgtb /* gsskrb5 v1 */
578ab9b2e15Sgtb krb5_ui_4 seq_temp;
579ab9b2e15Sgtb if ((code = make_ap_req_v1(context, ctx,
580ab9b2e15Sgtb cred, k_cred, input_chan_bindings,
581ab9b2e15Sgtb mech_type, &token))) {
582ab9b2e15Sgtb if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
583ab9b2e15Sgtb (code == KG_EMPTY_CCACHE))
584ab9b2e15Sgtb major_status = GSS_S_NO_CRED;
585ab9b2e15Sgtb if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
586ab9b2e15Sgtb major_status = GSS_S_CREDENTIALS_EXPIRED;
587ab9b2e15Sgtb goto fail;
588ab9b2e15Sgtb }
589ab9b2e15Sgtb
590ab9b2e15Sgtb krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
591ab9b2e15Sgtb (krb5_int32 *)&seq_temp); /* SUNW15resync */
592ab9b2e15Sgtb ctx->seq_send = seq_temp;
593ab9b2e15Sgtb krb5_auth_con_getsendsubkey(context, ctx->auth_context,
594ab9b2e15Sgtb &ctx->subkey);
595ab9b2e15Sgtb }
596ab9b2e15Sgtb
597ab9b2e15Sgtb major_status = setup_enc(minor_status, ctx, context);
598ab9b2e15Sgtb
599ab9b2e15Sgtb if (k_cred) {
600ab9b2e15Sgtb krb5_free_creds(context, k_cred);
601ab9b2e15Sgtb k_cred = 0;
602ab9b2e15Sgtb }
603ab9b2e15Sgtb
604ab9b2e15Sgtb /* at this point, the context is constructed and valid,
605ab9b2e15Sgtb hence, releaseable */
606ab9b2e15Sgtb
607ab9b2e15Sgtb /* intern the context handle */
608ab9b2e15Sgtb
609ab9b2e15Sgtb if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
610ab9b2e15Sgtb code = G_VALIDATE_FAILED;
611ab9b2e15Sgtb goto fail;
612ab9b2e15Sgtb }
613ab9b2e15Sgtb *context_handle = (gss_ctx_id_t) ctx;
614ab9b2e15Sgtb ctx_free = 0;
615ab9b2e15Sgtb
616ab9b2e15Sgtb /* compute time_rec */
617ab9b2e15Sgtb if (time_rec) {
618ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now)))
619ab9b2e15Sgtb goto fail;
620ab9b2e15Sgtb *time_rec = ctx->endtime - now;
621ab9b2e15Sgtb }
622ab9b2e15Sgtb
623ab9b2e15Sgtb /* set the other returns */
624ab9b2e15Sgtb *output_token = token;
625ab9b2e15Sgtb
626ab9b2e15Sgtb if (ret_flags)
627ab9b2e15Sgtb *ret_flags = ctx->gss_flags;
628ab9b2e15Sgtb
629ab9b2e15Sgtb if (actual_mech_type)
630ab9b2e15Sgtb *actual_mech_type = mech_type;
631ab9b2e15Sgtb
632ab9b2e15Sgtb /* return successfully */
633ab9b2e15Sgtb
634ab9b2e15Sgtb *minor_status = 0;
635ab9b2e15Sgtb if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
636ab9b2e15Sgtb ctx->established = 0;
637ab9b2e15Sgtb return(GSS_S_CONTINUE_NEEDED);
638ab9b2e15Sgtb } else {
639ab9b2e15Sgtb ctx->seq_recv = ctx->seq_send;
640ab9b2e15Sgtb g_order_init(&(ctx->seqstate), ctx->seq_recv,
641ab9b2e15Sgtb (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
642ab9b2e15Sgtb (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
643ab9b2e15Sgtb ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
644ab9b2e15Sgtb ctx->established = 1;
645ab9b2e15Sgtb return(GSS_S_COMPLETE);
646ab9b2e15Sgtb }
647ab9b2e15Sgtb
648ab9b2e15Sgtb fail:
649ab9b2e15Sgtb if (ctx_free) {
650ab9b2e15Sgtb if (ctx_free->auth_context)
651ab9b2e15Sgtb krb5_auth_con_free(context, ctx_free->auth_context);
652ab9b2e15Sgtb if (ctx_free->here)
653ab9b2e15Sgtb krb5_free_principal(context, ctx_free->here);
654ab9b2e15Sgtb if (ctx_free->there)
655ab9b2e15Sgtb krb5_free_principal(context, ctx_free->there);
656ab9b2e15Sgtb if (ctx_free->subkey)
657ab9b2e15Sgtb krb5_free_keyblock(context, ctx_free->subkey);
658ab9b2e15Sgtb xfree(ctx_free);
659ab9b2e15Sgtb } else
660ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
661ab9b2e15Sgtb
662ab9b2e15Sgtb *minor_status = code;
663ab9b2e15Sgtb return (major_status);
664ab9b2e15Sgtb }
665ab9b2e15Sgtb
666ab9b2e15Sgtb /*
667ab9b2e15Sgtb * mutual_auth
668ab9b2e15Sgtb *
669ab9b2e15Sgtb * Handle the reply from the acceptor, if we're doing mutual auth.
670ab9b2e15Sgtb */
671ab9b2e15Sgtb static OM_uint32
mutual_auth(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_name_t target_name,gss_OID mech_type,OM_uint32 req_flags,OM_uint32 time_req,gss_channel_bindings_t input_chan_bindings,gss_buffer_t input_token,gss_OID * actual_mech_type,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec,krb5_context context)672ab9b2e15Sgtb mutual_auth(
673ab9b2e15Sgtb OM_uint32 *minor_status,
674ab9b2e15Sgtb gss_ctx_id_t *context_handle,
675ab9b2e15Sgtb gss_name_t target_name,
676ab9b2e15Sgtb gss_OID mech_type,
677ab9b2e15Sgtb OM_uint32 req_flags,
678ab9b2e15Sgtb OM_uint32 time_req,
679ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings,
680ab9b2e15Sgtb gss_buffer_t input_token,
681ab9b2e15Sgtb gss_OID *actual_mech_type,
682ab9b2e15Sgtb gss_buffer_t output_token,
683ab9b2e15Sgtb OM_uint32 *ret_flags,
684ab9b2e15Sgtb OM_uint32 *time_rec,
685ab9b2e15Sgtb krb5_context context)
686ab9b2e15Sgtb {
687ab9b2e15Sgtb OM_uint32 major_status;
688ab9b2e15Sgtb unsigned char *ptr;
689ab9b2e15Sgtb char *sptr;
690ab9b2e15Sgtb krb5_data ap_rep;
691ab9b2e15Sgtb krb5_ap_rep_enc_part *ap_rep_data;
692ab9b2e15Sgtb krb5_timestamp now;
693ab9b2e15Sgtb krb5_gss_ctx_id_rec *ctx;
694ab9b2e15Sgtb krb5_error *krb_error;
695ab9b2e15Sgtb krb5_error_code code;
696ab9b2e15Sgtb krb5int_access kaccess;
697ab9b2e15Sgtb
698ab9b2e15Sgtb major_status = GSS_S_FAILURE;
699ab9b2e15Sgtb
700ab9b2e15Sgtb code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
701ab9b2e15Sgtb if (code)
702ab9b2e15Sgtb goto fail;
703ab9b2e15Sgtb
704ab9b2e15Sgtb /* validate the context handle */
705ab9b2e15Sgtb /*SUPPRESS 29*/
706ab9b2e15Sgtb if (! kg_validate_ctx_id(*context_handle)) {
707ab9b2e15Sgtb *minor_status = (OM_uint32) G_VALIDATE_FAILED;
708ab9b2e15Sgtb return(GSS_S_NO_CONTEXT);
709ab9b2e15Sgtb }
710ab9b2e15Sgtb
711159d09a2SMark Phalan ctx = (krb5_gss_ctx_id_t) *context_handle;
712ab9b2e15Sgtb
713ab9b2e15Sgtb /* make sure the context is non-established, and that certain
714ab9b2e15Sgtb arguments are unchanged */
715ab9b2e15Sgtb
716ab9b2e15Sgtb if ((ctx->established) ||
717ab9b2e15Sgtb ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
718ab9b2e15Sgtb code = KG_CONTEXT_ESTABLISHED;
719ab9b2e15Sgtb goto fail;
720ab9b2e15Sgtb }
721ab9b2e15Sgtb
722ab9b2e15Sgtb if (! krb5_principal_compare(context, ctx->there,
723ab9b2e15Sgtb (krb5_principal) target_name)) {
7245e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */
7255e01956fSGlenn Barry krb5_principal tname = (krb5_principal) target_name;
7265e01956fSGlenn Barry char *s_name = NULL, *s_princ= NULL;
7275e01956fSGlenn Barry int kret = krb5_unparse_name(context, tname, &s_name);
7285e01956fSGlenn Barry int kret1 = krb5_unparse_name(context, ctx->there, &s_princ);
7295e01956fSGlenn Barry code = KRB5_PRINC_NOMATCH;
7305e01956fSGlenn Barry if (kret == 0 && kret1 == 0) {
7315e01956fSGlenn Barry krb5_set_error_message(context, code,
7325e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
7335e01956fSGlenn Barry "Target name principal '%s' does not match '%s'"),
7345e01956fSGlenn Barry s_name, s_princ);
7355e01956fSGlenn Barry save_error_info(code, context);
7365e01956fSGlenn Barry }
7375e01956fSGlenn Barry if (s_name)
7385e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
7395e01956fSGlenn Barry if (s_princ)
7405e01956fSGlenn Barry krb5_free_unparsed_name(context, s_princ);
7415e01956fSGlenn Barry
742ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status,
743ab9b2e15Sgtb context_handle, NULL);
744ab9b2e15Sgtb major_status = GSS_S_BAD_NAME;
745ab9b2e15Sgtb goto fail;
746ab9b2e15Sgtb }
747ab9b2e15Sgtb
748ab9b2e15Sgtb /* verify the token and leave the AP_REP message in ap_rep */
749ab9b2e15Sgtb
750ab9b2e15Sgtb if (input_token == GSS_C_NO_BUFFER) {
751ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status,
752ab9b2e15Sgtb context_handle, NULL);
753ab9b2e15Sgtb code = 0;
754ab9b2e15Sgtb major_status = GSS_S_DEFECTIVE_TOKEN;
755ab9b2e15Sgtb goto fail;
756ab9b2e15Sgtb }
757ab9b2e15Sgtb
758ab9b2e15Sgtb ptr = (unsigned char *) input_token->value;
759ab9b2e15Sgtb
760ab9b2e15Sgtb if (g_verify_token_header(ctx->mech_used,
761ab9b2e15Sgtb &(ap_rep.length),
762ab9b2e15Sgtb &ptr, KG_TOK_CTX_AP_REP,
763ab9b2e15Sgtb input_token->length, 1)) {
764ab9b2e15Sgtb if (g_verify_token_header((gss_OID) ctx->mech_used,
765ab9b2e15Sgtb &(ap_rep.length),
766ab9b2e15Sgtb &ptr, KG_TOK_CTX_ERROR,
767ab9b2e15Sgtb input_token->length, 1) == 0) {
768ab9b2e15Sgtb
769ab9b2e15Sgtb /* Handle a KRB_ERROR message from the server */
770ab9b2e15Sgtb
771ab9b2e15Sgtb sptr = (char *) ptr; /* PC compiler bug */
772ab9b2e15Sgtb TREAD_STR(sptr, ap_rep.data, ap_rep.length);
773ab9b2e15Sgtb
774ab9b2e15Sgtb code = krb5_rd_error(context, &ap_rep, &krb_error);
775ab9b2e15Sgtb if (code)
776ab9b2e15Sgtb goto fail;
777ab9b2e15Sgtb if (krb_error->error)
778ab9b2e15Sgtb code = krb_error->error + ERROR_TABLE_BASE_krb5;
779ab9b2e15Sgtb else
780ab9b2e15Sgtb code = 0;
781ab9b2e15Sgtb krb5_free_error(context, krb_error);
782ab9b2e15Sgtb goto fail;
783ab9b2e15Sgtb } else {
784ab9b2e15Sgtb *minor_status = 0;
785ab9b2e15Sgtb return(GSS_S_DEFECTIVE_TOKEN);
786ab9b2e15Sgtb }
787ab9b2e15Sgtb }
788ab9b2e15Sgtb
789ab9b2e15Sgtb sptr = (char *) ptr; /* PC compiler bug */
790ab9b2e15Sgtb TREAD_STR(sptr, ap_rep.data, ap_rep.length);
791ab9b2e15Sgtb
792ab9b2e15Sgtb /* decode the ap_rep */
793ab9b2e15Sgtb if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
794ab9b2e15Sgtb &ap_rep_data))) {
795ab9b2e15Sgtb /*
796ab9b2e15Sgtb * XXX A hack for backwards compatiblity.
797ab9b2e15Sgtb * To be removed in 1999 -- proven
798ab9b2e15Sgtb */
799ab9b2e15Sgtb krb5_auth_con_setuseruserkey(context, ctx->auth_context,
800ab9b2e15Sgtb ctx->subkey);
801ab9b2e15Sgtb if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
802ab9b2e15Sgtb &ap_rep_data)))
803ab9b2e15Sgtb goto fail;
804ab9b2e15Sgtb }
805ab9b2e15Sgtb
806ab9b2e15Sgtb /* store away the sequence number */
807ab9b2e15Sgtb ctx->seq_recv = ap_rep_data->seq_number;
808ab9b2e15Sgtb g_order_init(&(ctx->seqstate), ctx->seq_recv,
809ab9b2e15Sgtb (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
810ab9b2e15Sgtb (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0, ctx->proto);
811ab9b2e15Sgtb
812ab9b2e15Sgtb if (ctx->proto == 1 && ap_rep_data->subkey) {
813ab9b2e15Sgtb /* Keep acceptor's subkey. */
814ab9b2e15Sgtb ctx->have_acceptor_subkey = 1;
815ab9b2e15Sgtb code = krb5_copy_keyblock(context, ap_rep_data->subkey,
816ab9b2e15Sgtb &ctx->acceptor_subkey);
817ab9b2e15Sgtb if (code)
818ab9b2e15Sgtb goto fail;
819ab9b2e15Sgtb code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
820ab9b2e15Sgtb ctx->acceptor_subkey->enctype,
821ab9b2e15Sgtb &ctx->acceptor_subkey_cksumtype);
822ab9b2e15Sgtb if (code)
823ab9b2e15Sgtb goto fail;
824ab9b2e15Sgtb }
825ab9b2e15Sgtb
826ab9b2e15Sgtb /* free the ap_rep_data */
827ab9b2e15Sgtb krb5_free_ap_rep_enc_part(context, ap_rep_data);
828ab9b2e15Sgtb
829ab9b2e15Sgtb /* set established */
830ab9b2e15Sgtb ctx->established = 1;
831ab9b2e15Sgtb
832ab9b2e15Sgtb /* set returns */
833ab9b2e15Sgtb
834ab9b2e15Sgtb if (time_rec) {
835ab9b2e15Sgtb if ((code = krb5_timeofday(context, &now)))
836ab9b2e15Sgtb goto fail;
837ab9b2e15Sgtb *time_rec = ctx->endtime - now;
838ab9b2e15Sgtb }
839ab9b2e15Sgtb
840ab9b2e15Sgtb if (ret_flags)
841ab9b2e15Sgtb *ret_flags = ctx->gss_flags;
842ab9b2e15Sgtb
843ab9b2e15Sgtb if (actual_mech_type)
844ab9b2e15Sgtb *actual_mech_type = mech_type;
845ab9b2e15Sgtb
846ab9b2e15Sgtb /* success */
847ab9b2e15Sgtb
848ab9b2e15Sgtb *minor_status = 0;
849ab9b2e15Sgtb return GSS_S_COMPLETE;
850ab9b2e15Sgtb
851ab9b2e15Sgtb fail:
852ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
853ab9b2e15Sgtb
854ab9b2e15Sgtb *minor_status = code;
855ab9b2e15Sgtb return (major_status);
856ab9b2e15Sgtb }
857ab9b2e15Sgtb
858ab9b2e15Sgtb OM_uint32
krb5_gss_init_sec_context(minor_status,claimant_cred_handle,context_handle,target_name,mech_type,req_flags,time_req,input_chan_bindings,input_token,actual_mech_type,output_token,ret_flags,time_rec)859ab9b2e15Sgtb krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
860ab9b2e15Sgtb context_handle, target_name, mech_type,
861ab9b2e15Sgtb req_flags, time_req, input_chan_bindings,
862ab9b2e15Sgtb input_token, actual_mech_type, output_token,
863ab9b2e15Sgtb ret_flags, time_rec)
864ab9b2e15Sgtb OM_uint32 *minor_status;
865ab9b2e15Sgtb gss_cred_id_t claimant_cred_handle;
866ab9b2e15Sgtb gss_ctx_id_t *context_handle;
867ab9b2e15Sgtb gss_name_t target_name;
868ab9b2e15Sgtb gss_OID mech_type;
869ab9b2e15Sgtb OM_uint32 req_flags;
870ab9b2e15Sgtb OM_uint32 time_req;
871ab9b2e15Sgtb gss_channel_bindings_t input_chan_bindings;
872ab9b2e15Sgtb gss_buffer_t input_token;
873ab9b2e15Sgtb gss_OID *actual_mech_type;
874ab9b2e15Sgtb gss_buffer_t output_token;
875ab9b2e15Sgtb OM_uint32 *ret_flags;
876ab9b2e15Sgtb OM_uint32 *time_rec;
877ab9b2e15Sgtb {
878ab9b2e15Sgtb krb5_context context;
879ab9b2e15Sgtb krb5_gss_cred_id_t cred;
880ab9b2e15Sgtb int err;
881ab9b2e15Sgtb krb5_error_code kerr;
882ab9b2e15Sgtb int default_mech = 0;
883ab9b2e15Sgtb OM_uint32 major_status;
884ab9b2e15Sgtb OM_uint32 tmp_min_stat;
885ab9b2e15Sgtb
886ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) {
887ab9b2e15Sgtb kerr = krb5_gss_init_context(&context);
888ab9b2e15Sgtb if (kerr) {
889ab9b2e15Sgtb *minor_status = kerr;
890ab9b2e15Sgtb return GSS_S_FAILURE;
891ab9b2e15Sgtb }
8925e01956fSGlenn Barry if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) {
8935e01956fSGlenn Barry save_error_info(*minor_status, context);
8945e01956fSGlenn Barry krb5_free_context(context);
895ab9b2e15Sgtb return GSS_S_FAILURE;
8965e01956fSGlenn Barry }
897ab9b2e15Sgtb } else {
898ab9b2e15Sgtb context = ((krb5_gss_ctx_id_rec *)*context_handle)->k5_context;
899ab9b2e15Sgtb }
900ab9b2e15Sgtb
901ab9b2e15Sgtb /* set up return values so they can be "freed" successfully */
902ab9b2e15Sgtb
903ab9b2e15Sgtb major_status = GSS_S_FAILURE; /* Default major code */
904ab9b2e15Sgtb output_token->length = 0;
905ab9b2e15Sgtb output_token->value = NULL;
906ab9b2e15Sgtb if (actual_mech_type)
907ab9b2e15Sgtb *actual_mech_type = NULL;
908ab9b2e15Sgtb
909ab9b2e15Sgtb /* verify that the target_name is valid and usable */
910ab9b2e15Sgtb
911ab9b2e15Sgtb if (! kg_validate_name(target_name)) {
9125e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */
9135e01956fSGlenn Barry krb5_principal princ = (krb5_principal) target_name;
9145e01956fSGlenn Barry char *s_name = NULL;
9155e01956fSGlenn Barry int kret = krb5_unparse_name(context, princ, &s_name);
916ab9b2e15Sgtb *minor_status = (OM_uint32) G_VALIDATE_FAILED;
9175e01956fSGlenn Barry if (kret == 0) {
9185e01956fSGlenn Barry krb5_set_error_message(context, *minor_status,
9195e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
9205e01956fSGlenn Barry "Target name principal '%s' is invalid"),
9215e01956fSGlenn Barry s_name);
9225e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
9235e01956fSGlenn Barry save_error_info(*minor_status, context);
9245e01956fSGlenn Barry }
9255e01956fSGlenn Barry
926ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT)
927ab9b2e15Sgtb krb5_free_context(context);
928ab9b2e15Sgtb return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
929ab9b2e15Sgtb }
930ab9b2e15Sgtb
931ab9b2e15Sgtb /* verify the credential, or use the default */
932ab9b2e15Sgtb /*SUPPRESS 29*/
933ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
934ab9b2e15Sgtb /*
935ab9b2e15Sgtb * Solaris Kerberos: here we are using the Solaris specific
936ab9b2e15Sgtb * function get_default_cred() to handle the special case of a
937ab9b2e15Sgtb * root principal
938ab9b2e15Sgtb */
939ab9b2e15Sgtb major_status = get_default_cred(minor_status, context,
940ab9b2e15Sgtb (gss_cred_id_t *)&cred);
941ab9b2e15Sgtb if (major_status && GSS_ERROR(major_status)) {
9425e01956fSGlenn Barry save_error_info(*minor_status, context);
943ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT)
944ab9b2e15Sgtb krb5_free_context(context);
945ab9b2e15Sgtb return(major_status);
946ab9b2e15Sgtb }
947ab9b2e15Sgtb } else {
948ab9b2e15Sgtb major_status = krb5_gss_validate_cred(minor_status, claimant_cred_handle);
949ab9b2e15Sgtb if (GSS_ERROR(major_status)) {
9505e01956fSGlenn Barry save_error_info(*minor_status, context);
951ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT)
952ab9b2e15Sgtb krb5_free_context(context);
953ab9b2e15Sgtb return(major_status);
954ab9b2e15Sgtb }
955ab9b2e15Sgtb cred = (krb5_gss_cred_id_t) claimant_cred_handle;
956ab9b2e15Sgtb }
957ab9b2e15Sgtb kerr = k5_mutex_lock(&cred->lock);
958ab9b2e15Sgtb if (kerr) {
959ab9b2e15Sgtb krb5_free_context(context);
960ab9b2e15Sgtb *minor_status = kerr;
961ab9b2e15Sgtb return GSS_S_FAILURE;
962ab9b2e15Sgtb }
963ab9b2e15Sgtb
964ab9b2e15Sgtb /* verify the mech_type */
965ab9b2e15Sgtb
966ab9b2e15Sgtb err = 0;
967ab9b2e15Sgtb if (mech_type == GSS_C_NULL_OID) {
968ab9b2e15Sgtb default_mech = 1;
969ab9b2e15Sgtb if (cred->rfc_mech) {
970ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5;
971ab9b2e15Sgtb } else if (cred->prerfc_mech) {
972ab9b2e15Sgtb mech_type = (gss_OID) gss_mech_krb5_old;
973ab9b2e15Sgtb } else {
974ab9b2e15Sgtb err = 1;
975ab9b2e15Sgtb }
976ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5)) {
977ab9b2e15Sgtb if (!cred->rfc_mech)
978ab9b2e15Sgtb err = 1;
979ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
980ab9b2e15Sgtb if (!cred->prerfc_mech)
981ab9b2e15Sgtb err = 1;
982ab9b2e15Sgtb } else if (g_OID_equal(mech_type, gss_mech_krb5_wrong)) {
983ab9b2e15Sgtb if (!cred->rfc_mech)
984ab9b2e15Sgtb err = 1;
985ab9b2e15Sgtb } else {
986ab9b2e15Sgtb err = 1;
987ab9b2e15Sgtb }
988ab9b2e15Sgtb
989ab9b2e15Sgtb if (err) {
990ab9b2e15Sgtb k5_mutex_unlock(&cred->lock);
991ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
992ab9b2e15Sgtb krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
993ab9b2e15Sgtb *minor_status = 0;
994ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT)
995ab9b2e15Sgtb krb5_free_context(context);
996ab9b2e15Sgtb return(GSS_S_BAD_MECH);
997ab9b2e15Sgtb }
998ab9b2e15Sgtb
999ab9b2e15Sgtb /* is this a new connection or not? */
1000ab9b2e15Sgtb
1001ab9b2e15Sgtb /*SUPPRESS 29*/
1002ab9b2e15Sgtb if (*context_handle == GSS_C_NO_CONTEXT) {
1003ab9b2e15Sgtb major_status = new_connection(minor_status, cred, context_handle,
1004ab9b2e15Sgtb target_name, mech_type, req_flags,
1005ab9b2e15Sgtb time_req, input_chan_bindings,
1006ab9b2e15Sgtb input_token, actual_mech_type,
1007ab9b2e15Sgtb output_token, ret_flags, time_rec,
1008ab9b2e15Sgtb context, default_mech);
1009ab9b2e15Sgtb k5_mutex_unlock(&cred->lock);
10105e01956fSGlenn Barry if (*context_handle == GSS_C_NO_CONTEXT) {
10115e01956fSGlenn Barry save_error_info (*minor_status, context);
1012ab9b2e15Sgtb krb5_free_context(context);
10135e01956fSGlenn Barry } else
1014ab9b2e15Sgtb ((krb5_gss_ctx_id_rec *) *context_handle)->k5_context = context;
1015ab9b2e15Sgtb } else {
1016ab9b2e15Sgtb /* mutual_auth doesn't care about the credentials */
1017ab9b2e15Sgtb k5_mutex_unlock(&cred->lock);
1018ab9b2e15Sgtb major_status = mutual_auth(minor_status, context_handle,
1019ab9b2e15Sgtb target_name, mech_type, req_flags,
1020ab9b2e15Sgtb time_req, input_chan_bindings,
1021ab9b2e15Sgtb input_token, actual_mech_type,
1022ab9b2e15Sgtb output_token, ret_flags, time_rec,
1023ab9b2e15Sgtb context);
1024ab9b2e15Sgtb /* If context_handle is now NO_CONTEXT, mutual_auth called
1025ab9b2e15Sgtb delete_sec_context, which would've zapped the krb5 context
1026ab9b2e15Sgtb too. */
1027ab9b2e15Sgtb }
1028ab9b2e15Sgtb
1029ab9b2e15Sgtb if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
1030ab9b2e15Sgtb krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t *)&cred);
1031ab9b2e15Sgtb
1032ab9b2e15Sgtb return(major_status);
1033ab9b2e15Sgtb }
1034ab9b2e15Sgtb
1035159d09a2SMark Phalan #ifndef _WIN32
1036ab9b2e15Sgtb k5_mutex_t kg_kdc_flag_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
1037ab9b2e15Sgtb static int kdc_flag = 0;
1038ab9b2e15Sgtb #endif
1039ab9b2e15Sgtb
1040ab9b2e15Sgtb krb5_error_code
krb5_gss_init_context(krb5_context * ctxp)1041ab9b2e15Sgtb krb5_gss_init_context (krb5_context *ctxp)
1042ab9b2e15Sgtb {
1043ab9b2e15Sgtb krb5_error_code err;
1044159d09a2SMark Phalan #ifndef _WIN32
1045ab9b2e15Sgtb int is_kdc;
1046159d09a2SMark Phalan #endif
1047ab9b2e15Sgtb
1048ab9b2e15Sgtb err = gssint_initialize_library();
1049ab9b2e15Sgtb if (err)
1050ab9b2e15Sgtb return err;
1051159d09a2SMark Phalan #ifndef _WIN32
1052ab9b2e15Sgtb err = k5_mutex_lock(&kg_kdc_flag_mutex);
1053ab9b2e15Sgtb if (err)
1054ab9b2e15Sgtb return err;
1055ab9b2e15Sgtb is_kdc = kdc_flag;
1056ab9b2e15Sgtb k5_mutex_unlock(&kg_kdc_flag_mutex);
1057ab9b2e15Sgtb
1058ab9b2e15Sgtb if (is_kdc)
1059ab9b2e15Sgtb return krb5int_init_context_kdc(ctxp);
1060ab9b2e15Sgtb #endif
1061ab9b2e15Sgtb
1062159d09a2SMark Phalan return krb5_init_context(ctxp);
1063ab9b2e15Sgtb }
1064ab9b2e15Sgtb
1065159d09a2SMark Phalan #ifndef _WIN32
1066ab9b2e15Sgtb krb5_error_code
krb5_gss_use_kdc_context()1067ab9b2e15Sgtb krb5_gss_use_kdc_context()
1068ab9b2e15Sgtb {
1069ab9b2e15Sgtb krb5_error_code err;
1070ab9b2e15Sgtb
1071ab9b2e15Sgtb err = gssint_initialize_library();
1072ab9b2e15Sgtb if (err)
1073ab9b2e15Sgtb return err;
1074ab9b2e15Sgtb err = k5_mutex_lock(&kg_kdc_flag_mutex);
1075ab9b2e15Sgtb if (err)
1076ab9b2e15Sgtb return err;
1077ab9b2e15Sgtb kdc_flag = 1;
1078ab9b2e15Sgtb k5_mutex_unlock(&kg_kdc_flag_mutex);
1079ab9b2e15Sgtb return 0;
1080ab9b2e15Sgtb }
1081ab9b2e15Sgtb #endif
1082ab9b2e15Sgtb
1083ab9b2e15Sgtb /* Solaris Kerberos specific routines start */
1084ab9b2e15Sgtb
1085ab9b2e15Sgtb #define ROOT_UID 0
1086ab9b2e15Sgtb #define KRB5_DEFAULT_LIFE 60*60*10
1087ab9b2e15Sgtb #define CACHE_FILENAME_LEN 35
1088ab9b2e15Sgtb
1089ab9b2e15Sgtb extern int
1090ab9b2e15Sgtb safechown(const char *src, uid_t uid, gid_t gid, int mode);
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate static krb5_boolean
principal_ignore_inst_compare(context,princ1,princ2)10937c478bd9Sstevel@tonic-gate principal_ignore_inst_compare(context, princ1, princ2)
10947c478bd9Sstevel@tonic-gate krb5_context context;
10957c478bd9Sstevel@tonic-gate krb5_const_principal princ1;
10967c478bd9Sstevel@tonic-gate krb5_const_principal princ2;
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate krb5_int32 nelem;
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate nelem = krb5_princ_size(context, princ1);
11017c478bd9Sstevel@tonic-gate if (nelem != krb5_princ_size(context, princ2))
11027c478bd9Sstevel@tonic-gate return FALSE;
11037c478bd9Sstevel@tonic-gate
1104db02be57S /*
1105db02be57S * Solaris Kerberos:
1106db02be57S * Don't bother to compare the realms as princ1 will always have a
1107db02be57S * referral realm set.
1108db02be57S */
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate /*
11117c478bd9Sstevel@tonic-gate * Solaris Kerberos
11127c478bd9Sstevel@tonic-gate * If princ1 is elem1/metachar@REALM, compare just elem1 (and REALM).
11137c478bd9Sstevel@tonic-gate */
11147c478bd9Sstevel@tonic-gate if (nelem == 2) {
11157c478bd9Sstevel@tonic-gate const krb5_data *p = krb5_princ_component(context, princ1, 1);
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate if (p->length == 1) {
11187c478bd9Sstevel@tonic-gate const char *s = p->data;
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate if (s[0] == '*') {
11217c478bd9Sstevel@tonic-gate const krb5_data *p1 = krb5_princ_component(context, princ1, 0);
11227c478bd9Sstevel@tonic-gate const krb5_data *p2 = krb5_princ_component(context, princ2, 0);
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate if (p1->length != p2->length ||
11257c478bd9Sstevel@tonic-gate memcmp(p1->data, p2->data, p1->length))
11267c478bd9Sstevel@tonic-gate return FALSE;
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate return TRUE;
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate }
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate
11337c478bd9Sstevel@tonic-gate return FALSE;
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate /*
11377c478bd9Sstevel@tonic-gate * Solaris Kerberos
11387c478bd9Sstevel@tonic-gate * This is a dup of krb5_ktfile_get_entry (sigh) but is necessary to
11397c478bd9Sstevel@tonic-gate * to get a custom princ compare above (principal_ignore_inst_compare)
11407c478bd9Sstevel@tonic-gate * and thus avoid mucking w/important krb5 internal
11417c478bd9Sstevel@tonic-gate * api (krb5_principal_compare)
11427c478bd9Sstevel@tonic-gate */
11437c478bd9Sstevel@tonic-gate #include "../krb5/keytab/file/ktfile.h"
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate static krb5_error_code KRB5_CALLCONV
ktfile_get_entry(context,id,principal,kvno,enctype,entry)11467c478bd9Sstevel@tonic-gate ktfile_get_entry(context, id, principal, kvno, enctype, entry)
11477c478bd9Sstevel@tonic-gate krb5_context context;
11487c478bd9Sstevel@tonic-gate krb5_keytab id;
11497c478bd9Sstevel@tonic-gate krb5_const_principal principal;
11507c478bd9Sstevel@tonic-gate krb5_kvno kvno;
11517c478bd9Sstevel@tonic-gate krb5_enctype enctype;
11527c478bd9Sstevel@tonic-gate krb5_keytab_entry * entry;
11537c478bd9Sstevel@tonic-gate {
11547c478bd9Sstevel@tonic-gate krb5_keytab_entry cur_entry, new_entry;
11557c478bd9Sstevel@tonic-gate krb5_error_code kerror = 0;
11567c478bd9Sstevel@tonic-gate int found_wrong_kvno = 0;
11577c478bd9Sstevel@tonic-gate krb5_boolean similar;
11587c478bd9Sstevel@tonic-gate int kvno_offset = 0;
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() start\n");
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate /* Open the keyfile for reading */
11637c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_openr(context, id))){
11647c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "ktfile_get_entry() end, ktfileint_openr() "
11657c478bd9Sstevel@tonic-gate "kerror= %d\n", kerror);
11667c478bd9Sstevel@tonic-gate return(kerror);
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate * For efficiency and simplicity, we'll use a while true that
11717c478bd9Sstevel@tonic-gate * is exited with a break statement.
11727c478bd9Sstevel@tonic-gate */
11737c478bd9Sstevel@tonic-gate cur_entry.principal = 0;
11747c478bd9Sstevel@tonic-gate cur_entry.vno = 0;
11757c478bd9Sstevel@tonic-gate cur_entry.key.contents = 0;
11767c478bd9Sstevel@tonic-gate /*CONSTCOND*/
11777c478bd9Sstevel@tonic-gate while (TRUE) {
11787c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry)))
11797c478bd9Sstevel@tonic-gate break;
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate /*
11827c478bd9Sstevel@tonic-gate * by the time this loop exits, it must either free cur_entry,
11837c478bd9Sstevel@tonic-gate * and copy new_entry there, or free new_entry. Otherwise, it
11847c478bd9Sstevel@tonic-gate * leaks.
11857c478bd9Sstevel@tonic-gate */
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate /*
11887c478bd9Sstevel@tonic-gate * if the principal isn't the one requested, free new_entry
11897c478bd9Sstevel@tonic-gate * and continue to the next.
11907c478bd9Sstevel@tonic-gate */
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate if (!principal_ignore_inst_compare(context, principal,
11937c478bd9Sstevel@tonic-gate new_entry.principal)) {
11947c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry);
11957c478bd9Sstevel@tonic-gate continue;
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate /*
11997c478bd9Sstevel@tonic-gate * if the enctype is not ignored and doesn't match, free new_entry
12007c478bd9Sstevel@tonic-gate * and continue to the next
12017c478bd9Sstevel@tonic-gate */
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate if (enctype != IGNORE_ENCTYPE) {
12047c478bd9Sstevel@tonic-gate if ((kerror = krb5_c_enctype_compare(context, enctype,
12057c478bd9Sstevel@tonic-gate new_entry.key.enctype,
12067c478bd9Sstevel@tonic-gate &similar))) {
12077c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry);
12087c478bd9Sstevel@tonic-gate break;
12097c478bd9Sstevel@tonic-gate }
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate if (!similar) {
12127c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry);
12137c478bd9Sstevel@tonic-gate continue;
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate /*
12167c478bd9Sstevel@tonic-gate * Coerce the enctype of the output keyblock in case we
12177c478bd9Sstevel@tonic-gate * got an inexact match on the enctype.
12187c478bd9Sstevel@tonic-gate */
12197c478bd9Sstevel@tonic-gate new_entry.key.enctype = enctype;
12207c478bd9Sstevel@tonic-gate }
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate if (kvno == IGNORE_VNO) {
12237c478bd9Sstevel@tonic-gate /*
12247c478bd9Sstevel@tonic-gate * if this is the first match, or if the new vno is
12257c478bd9Sstevel@tonic-gate * bigger, free the current and keep the new. Otherwise,
12267c478bd9Sstevel@tonic-gate * free the new.
12277c478bd9Sstevel@tonic-gate */
12287c478bd9Sstevel@tonic-gate /*
12297c478bd9Sstevel@tonic-gate * A 1.2.x keytab contains only the low 8 bits of the key
12307c478bd9Sstevel@tonic-gate * version number. Since it can be much bigger, and thus
12317c478bd9Sstevel@tonic-gate * the 8-bit value can wrap, we need some heuristics to
12327c478bd9Sstevel@tonic-gate * figure out the "highest" numbered key if some numbers
12337c478bd9Sstevel@tonic-gate * close to 255 and some near 0 are used.
12347c478bd9Sstevel@tonic-gate *
12357c478bd9Sstevel@tonic-gate * The heuristic here:
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate * If we have any keys with versions over 240, then assume
12387c478bd9Sstevel@tonic-gate * that all version numbers 0-127 refer to 256+N instead.
12397c478bd9Sstevel@tonic-gate * Not perfect, but maybe good enough?
12407c478bd9Sstevel@tonic-gate */
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate #define M(VNO) (((VNO) - kvno_offset + 256) % 256)
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate if (new_entry.vno > 240)
12457c478bd9Sstevel@tonic-gate kvno_offset = 128;
12467c478bd9Sstevel@tonic-gate if (! cur_entry.principal ||
12477c478bd9Sstevel@tonic-gate M(new_entry.vno) > M(cur_entry.vno)) {
12487c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry);
12497c478bd9Sstevel@tonic-gate cur_entry = new_entry;
12507c478bd9Sstevel@tonic-gate } else {
12517c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate } else {
12547c478bd9Sstevel@tonic-gate /*
12557c478bd9Sstevel@tonic-gate * if this kvno matches, free the current (will there ever
12567c478bd9Sstevel@tonic-gate * be one?), keep the new, and break out. Otherwise, remember
12577c478bd9Sstevel@tonic-gate * that we were here so we can return the right error, and
12587c478bd9Sstevel@tonic-gate * free the new
12597c478bd9Sstevel@tonic-gate */
12607c478bd9Sstevel@tonic-gate /*
12617c478bd9Sstevel@tonic-gate * Yuck. The krb5-1.2.x keytab format only stores one byte
12627c478bd9Sstevel@tonic-gate * for the kvno, so we're toast if the kvno requested is
12637c478bd9Sstevel@tonic-gate * higher than that. Short-term workaround: only compare
12647c478bd9Sstevel@tonic-gate * the low 8 bits.
12657c478bd9Sstevel@tonic-gate */
12667c478bd9Sstevel@tonic-gate
12677c478bd9Sstevel@tonic-gate if (new_entry.vno == (kvno & 0xff)) {
12687c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry);
12697c478bd9Sstevel@tonic-gate cur_entry = new_entry;
12707c478bd9Sstevel@tonic-gate break;
12717c478bd9Sstevel@tonic-gate } else {
12727c478bd9Sstevel@tonic-gate found_wrong_kvno++;
12737c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &new_entry);
12747c478bd9Sstevel@tonic-gate }
12757c478bd9Sstevel@tonic-gate }
12767c478bd9Sstevel@tonic-gate }
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate if (kerror == KRB5_KT_END) {
12797c478bd9Sstevel@tonic-gate if (cur_entry.principal)
12807c478bd9Sstevel@tonic-gate kerror = 0;
12817c478bd9Sstevel@tonic-gate else if (found_wrong_kvno)
12827c478bd9Sstevel@tonic-gate kerror = KRB5_KT_KVNONOTFOUND;
12837c478bd9Sstevel@tonic-gate else
12847c478bd9Sstevel@tonic-gate kerror = KRB5_KT_NOTFOUND;
12857c478bd9Sstevel@tonic-gate }
12867c478bd9Sstevel@tonic-gate if (kerror) {
12877c478bd9Sstevel@tonic-gate (void) krb5_ktfileint_close(context, id);
12887c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry);
12897c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, kerror="
12907c478bd9Sstevel@tonic-gate "%d\n", kerror);
12917c478bd9Sstevel@tonic-gate return kerror;
12927c478bd9Sstevel@tonic-gate }
12937c478bd9Sstevel@tonic-gate if ((kerror = krb5_ktfileint_close(context, id)) != 0) {
12947c478bd9Sstevel@tonic-gate krb5_kt_free_entry(context, &cur_entry);
12957c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR,"ktfile_get_entry() end, ktfileint_close() "
12967c478bd9Sstevel@tonic-gate "kerror= %d\n", kerror);
12977c478bd9Sstevel@tonic-gate return kerror;
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate *entry = cur_entry;
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate /* Let us close the file before we leave */
13027c478bd9Sstevel@tonic-gate (void) krb5_ktfileint_close(context, id);
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "ktfile_get_entry() end");
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate return 0;
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate /*
13117c478bd9Sstevel@tonic-gate * Solaris Kerberos
13127c478bd9Sstevel@tonic-gate * Given a princ of name/instance@LOCALREALM, search the keytab
13137c478bd9Sstevel@tonic-gate * for a match of name and LOCALREALM and if found, return instance
13147c478bd9Sstevel@tonic-gate * as a string.
13157c478bd9Sstevel@tonic-gate *
13167c478bd9Sstevel@tonic-gate * Caller must free returned string.
13177c478bd9Sstevel@tonic-gate */
13187c478bd9Sstevel@tonic-gate static krb5_error_code
get_instance_keytab(krb5_context context,const char * sname,krb5_keytab keytab,char ** instance)13197c478bd9Sstevel@tonic-gate get_instance_keytab(
13207c478bd9Sstevel@tonic-gate krb5_context context,
13217c478bd9Sstevel@tonic-gate const char *sname,
13227c478bd9Sstevel@tonic-gate krb5_keytab keytab,
13237c478bd9Sstevel@tonic-gate char **instance) /* out */
13247c478bd9Sstevel@tonic-gate {
13257c478bd9Sstevel@tonic-gate krb5_error_code ret=0;
13267c478bd9Sstevel@tonic-gate krb5_keytab_entry kt_ent;
13277c478bd9Sstevel@tonic-gate krb5_int32 nelem, free_kt_ent=0;
13287c478bd9Sstevel@tonic-gate register const krb5_data *p;
13297c478bd9Sstevel@tonic-gate char *realm=NULL, *s=NULL;
13307c478bd9Sstevel@tonic-gate krb5_principal client=NULL, princ=NULL;
1331db02be57S size_t realm_size = strlen(KRB5_REFERRAL_REALM) + 1;
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate if (!keytab)
13347c478bd9Sstevel@tonic-gate return EINVAL;
13357c478bd9Sstevel@tonic-gate
1336db02be57S realm = malloc(realm_size);
1337db02be57S if (realm == NULL)
1338db02be57S return (ENOMEM);
1339db02be57S strlcpy(realm, KRB5_REFERRAL_REALM, realm_size);
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate ret = krb5_build_principal(context, &client, strlen(realm),
13427c478bd9Sstevel@tonic-gate realm, sname, "*",
13437c478bd9Sstevel@tonic-gate (char *)0);
13447c478bd9Sstevel@tonic-gate if (ret)
13457c478bd9Sstevel@tonic-gate goto out;
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate ret = ktfile_get_entry(context, keytab, client,
13487c478bd9Sstevel@tonic-gate 0, /* don't have vno available */
13497c478bd9Sstevel@tonic-gate 0, &kt_ent);
13507c478bd9Sstevel@tonic-gate if (ret)
13517c478bd9Sstevel@tonic-gate goto out;
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate free_kt_ent++; /* kt_ent is not a ptr */
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate princ = kt_ent.principal;
13567c478bd9Sstevel@tonic-gate nelem = krb5_princ_size(context, princ);
13577c478bd9Sstevel@tonic-gate if (nelem != 2) {
13587c478bd9Sstevel@tonic-gate ret = KRB5_PRINC_NOMATCH;
13597c478bd9Sstevel@tonic-gate goto out;
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate p = krb5_princ_component(context, princ, 1);
13637c478bd9Sstevel@tonic-gate s = calloc(p->length + sizeof(char), sizeof(char));
13647c478bd9Sstevel@tonic-gate if (!s) {
13657c478bd9Sstevel@tonic-gate ret = ENOMEM;
13667c478bd9Sstevel@tonic-gate goto out;
13677c478bd9Sstevel@tonic-gate }
13687c478bd9Sstevel@tonic-gate
13697c478bd9Sstevel@tonic-gate (void) memcpy(s, p->data, p->length);
13707c478bd9Sstevel@tonic-gate
13717c478bd9Sstevel@tonic-gate
13727c478bd9Sstevel@tonic-gate out:
13737c478bd9Sstevel@tonic-gate free(realm);
13747c478bd9Sstevel@tonic-gate if (client)
13757c478bd9Sstevel@tonic-gate krb5_free_principal(context, client);
13767c478bd9Sstevel@tonic-gate if (free_kt_ent)
13777c478bd9Sstevel@tonic-gate (void) krb5_kt_free_entry(context, &kt_ent);
13787c478bd9Sstevel@tonic-gate
13797c478bd9Sstevel@tonic-gate if (ret == 0)
13807c478bd9Sstevel@tonic-gate *instance = s;
13817c478bd9Sstevel@tonic-gate return ret;
13827c478bd9Sstevel@tonic-gate }
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate static OM_uint32
load_root_cred_using_keytab(OM_uint32 * minor_status,krb5_context context,const char * sname,int use_nodename)13857c478bd9Sstevel@tonic-gate load_root_cred_using_keytab(
13867c478bd9Sstevel@tonic-gate OM_uint32 *minor_status,
13877c478bd9Sstevel@tonic-gate krb5_context context,
13887c478bd9Sstevel@tonic-gate const char *sname,
13897c478bd9Sstevel@tonic-gate int use_nodename)
13907c478bd9Sstevel@tonic-gate {
13917c478bd9Sstevel@tonic-gate krb5_creds my_creds;
13927c478bd9Sstevel@tonic-gate krb5_principal me;
13937c478bd9Sstevel@tonic-gate krb5_principal server;
13947c478bd9Sstevel@tonic-gate krb5_error_code code;
13957c478bd9Sstevel@tonic-gate krb5_ccache ccache = NULL;
13967c478bd9Sstevel@tonic-gate krb5_keytab keytab = NULL;
13977c478bd9Sstevel@tonic-gate krb5_timestamp now;
13987c478bd9Sstevel@tonic-gate krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */
13997c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opt;
14007c478bd9Sstevel@tonic-gate krb5_data tgtname = {
14017c478bd9Sstevel@tonic-gate 0,
14027c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE,
14037c478bd9Sstevel@tonic-gate KRB5_TGS_NAME
14047c478bd9Sstevel@tonic-gate };
14057c478bd9Sstevel@tonic-gate char *svcname = NULL;
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() start \n");
14087c478bd9Sstevel@tonic-gate
14097c478bd9Sstevel@tonic-gate if (!sname)
14107c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate memset((char *)&my_creds, 0, sizeof(my_creds));
14137c478bd9Sstevel@tonic-gate
14147c478bd9Sstevel@tonic-gate if (code = krb5_kt_default(context, &keytab)) {
14157c478bd9Sstevel@tonic-gate *minor_status = code;
14167c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
14177c478bd9Sstevel@tonic-gate }
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate if (!use_nodename) {
14207c478bd9Sstevel@tonic-gate char *instance = NULL;
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate code = get_instance_keytab(context, sname, keytab, &instance);
14237c478bd9Sstevel@tonic-gate if (code == 0) {
14247c478bd9Sstevel@tonic-gate code = krb5_sname_to_principal(context,
14257c478bd9Sstevel@tonic-gate instance, sname,
14267c478bd9Sstevel@tonic-gate KRB5_NT_UNKNOWN, &me);
14277c478bd9Sstevel@tonic-gate free(instance);
14287c478bd9Sstevel@tonic-gate }
14297c478bd9Sstevel@tonic-gate } else {
14307c478bd9Sstevel@tonic-gate code = krb5_sname_to_principal(context, NULL, sname,
14317c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &me);
14327c478bd9Sstevel@tonic-gate }
1433db02be57S
1434db02be57S /* Solaris Kerberos */
143582449e72SMark Phalan if (code == 0 && krb5_is_referral_realm(&me->realm)) {
1436db02be57S krb5_data realm;
1437db02be57S code = krb5_kt_find_realm(context, keytab, me, &realm);
1438db02be57S if (code == 0) {
1439db02be57S krb5_free_data_contents(context, &me->realm);
1440db02be57S me->realm.length = realm.length;
1441db02be57S me->realm.data = realm.data;
1442db02be57S } else {
1443db02be57S /* Try to set a useful error message */
1444db02be57S char *princ = NULL;
14455e01956fSGlenn Barry krb5_error_code ret;
14465e01956fSGlenn Barry ret = krb5_unparse_name(context, me, &princ);
1447db02be57S
1448db02be57S krb5_set_error_message(context, code,
14495e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
14505e01956fSGlenn Barry "Failed to find realm for %s in keytab"),
14515e01956fSGlenn Barry ret == 0 ? princ : "unknown");
1452db02be57S if (princ)
1453db02be57S krb5_free_unparsed_name(context, princ);
1454db02be57S }
1455db02be57S }
1456db02be57S
14577c478bd9Sstevel@tonic-gate if (code) {
14587c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab);
14597c478bd9Sstevel@tonic-gate *minor_status = code;
14607c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
14617c478bd9Sstevel@tonic-gate }
1462fe598cdcSmp153739
14637c478bd9Sstevel@tonic-gate my_creds.client = me;
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate if((code = krb5_build_principal_ext(context, &server,
14667c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length,
14677c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data,
14687c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data,
14697c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length,
14707c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data,
14717c478bd9Sstevel@tonic-gate 0))) {
14727c478bd9Sstevel@tonic-gate *minor_status = code;
14737c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
14747c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab);
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate my_creds.server = server;
14807c478bd9Sstevel@tonic-gate my_creds.times.starttime = 0; /* start timer
14817c478bd9Sstevel@tonic-gate * when request
14827c478bd9Sstevel@tonic-gate * gets to KDC
14837c478bd9Sstevel@tonic-gate */
14847c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) {
14857c478bd9Sstevel@tonic-gate *minor_status = code;
14867c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
14877c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab);
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate my_creds.times.endtime = now + lifetime;
14927c478bd9Sstevel@tonic-gate my_creds.times.renew_till = 0;
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate memset(&opt, 0, sizeof (opt));
14957c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opt);
14967c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opt, lifetime);
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate code = krb5_unparse_name(context, server, &svcname);
14997c478bd9Sstevel@tonic-gate if (code != 0) {
15007c478bd9Sstevel@tonic-gate *minor_status = code;
15017c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
15027c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab);
15037c478bd9Sstevel@tonic-gate
15047c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15057c478bd9Sstevel@tonic-gate }
1506ab9b2e15Sgtb /*
1507ab9b2e15Sgtb * Evidently (sigh), on success, krb5_get_init_creds_keytab
1508ab9b2e15Sgtb * changes the my_creds princ ptrs so we need to free those
1509ab9b2e15Sgtb * princs (me&server) as well as freeing all of my_creds contents.
1510ab9b2e15Sgtb */
15117c478bd9Sstevel@tonic-gate code = krb5_get_init_creds_keytab(context,
15127c478bd9Sstevel@tonic-gate &my_creds, me, keytab,
15137c478bd9Sstevel@tonic-gate 0, svcname, &opt);
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate (void) krb5_kt_close(context, keytab);
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate if (svcname != NULL)
15187c478bd9Sstevel@tonic-gate free(svcname);
15197c478bd9Sstevel@tonic-gate if (code) {
15207c478bd9Sstevel@tonic-gate *minor_status = code;
15217c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
15227c478bd9Sstevel@tonic-gate
15237c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15247c478bd9Sstevel@tonic-gate }
1525ab9b2e15Sgtb
1526ab9b2e15Sgtb krb5_free_principal(context, server);
1527ab9b2e15Sgtb server = NULL;
1528ab9b2e15Sgtb
15297c478bd9Sstevel@tonic-gate code = krb5_cc_resolve (context,
15307c478bd9Sstevel@tonic-gate krb5_cc_default_name(context),
15317c478bd9Sstevel@tonic-gate &ccache);
15327c478bd9Sstevel@tonic-gate if (code != 0) {
15337c478bd9Sstevel@tonic-gate *minor_status = code;
15347c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
1535ab9b2e15Sgtb krb5_free_principal(context, me);
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate code = krb5_cc_initialize (context, ccache, me);
1540ab9b2e15Sgtb krb5_free_principal(context, me);
1541ab9b2e15Sgtb me = NULL;
15427c478bd9Sstevel@tonic-gate if (code != 0) {
15437c478bd9Sstevel@tonic-gate *minor_status = code;
15447c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
15457c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
15467c478bd9Sstevel@tonic-gate
15477c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15487c478bd9Sstevel@tonic-gate }
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate code = krb5_cc_store_cred(context, ccache,
15517c478bd9Sstevel@tonic-gate &my_creds);
15527c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &my_creds);
15537c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate if (code) {
15567c478bd9Sstevel@tonic-gate *minor_status = code;
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate KRB5_LOG(KRB5_ERR, "load_root_cred_using_keytab() end, error "
15597c478bd9Sstevel@tonic-gate "code = %d\n", code);
15607c478bd9Sstevel@tonic-gate
15617c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "load_root_cred_using_keytab() end \n");
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
15677c478bd9Sstevel@tonic-gate }
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate static OM_uint32
renew_ccache(OM_uint32 * minor_status,krb5_context context,uid_t uid)15707c478bd9Sstevel@tonic-gate renew_ccache(OM_uint32 *minor_status, krb5_context context, uid_t uid)
15717c478bd9Sstevel@tonic-gate {
15727c478bd9Sstevel@tonic-gate krb5_principal me;
15737c478bd9Sstevel@tonic-gate krb5_principal server;
15747c478bd9Sstevel@tonic-gate krb5_creds creds;
15757c478bd9Sstevel@tonic-gate krb5_creds tmpcreds;
15767c478bd9Sstevel@tonic-gate krb5_creds *out_creds;
15777c478bd9Sstevel@tonic-gate krb5_error_code code;
15787c478bd9Sstevel@tonic-gate krb5_ccache ccache = NULL;
15797c478bd9Sstevel@tonic-gate static char ccache_name_buf[CACHE_FILENAME_LEN];
15807c478bd9Sstevel@tonic-gate int options = 0;
15817c478bd9Sstevel@tonic-gate krb5_data tgtname = {
15827c478bd9Sstevel@tonic-gate 0,
15837c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE,
15847c478bd9Sstevel@tonic-gate KRB5_TGS_NAME
15857c478bd9Sstevel@tonic-gate };
15867c478bd9Sstevel@tonic-gate gid_t gid = getgid();
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate memset((char *)&creds, 0, sizeof(creds));
15897c478bd9Sstevel@tonic-gate memset((char *)&tmpcreds, 0, sizeof(creds));
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate if ((code = krb5_cc_default(context, &ccache))) {
15927c478bd9Sstevel@tonic-gate *minor_status = code;
15937c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
15947c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
15957c478bd9Sstevel@tonic-gate }
15967c478bd9Sstevel@tonic-gate
15977c478bd9Sstevel@tonic-gate if ((code = krb5_cc_get_principal(context, ccache, &me)) != 0) {
15987c478bd9Sstevel@tonic-gate *minor_status = code;
15997c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
16007c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
16017c478bd9Sstevel@tonic-gate }
16027c478bd9Sstevel@tonic-gate
16037c478bd9Sstevel@tonic-gate creds.client = me;
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate if((code = krb5_build_principal_ext(context, &server,
16067c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length,
16077c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data,
16087c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data,
16097c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->length,
16107c478bd9Sstevel@tonic-gate krb5_princ_realm(context, me)->data,
16117c478bd9Sstevel@tonic-gate 0))) {
16127c478bd9Sstevel@tonic-gate krb5_free_principal(context, me);
16137c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
16147c478bd9Sstevel@tonic-gate *minor_status = code;
16157c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate creds.server = server;
16197c478bd9Sstevel@tonic-gate creds.ticket_flags = TKT_FLG_RENEWABLE;
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate if ((krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_FLAGS,
16227c478bd9Sstevel@tonic-gate &creds, &tmpcreds))) {
16237c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
16247c478bd9Sstevel@tonic-gate return (KDC_ERR_BADOPTION);
16257c478bd9Sstevel@tonic-gate }
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate creds.ticket_flags = 0;
16287c478bd9Sstevel@tonic-gate code = krb5_get_credentials_renew(context, options, ccache,
16297c478bd9Sstevel@tonic-gate &creds, &out_creds);
16307c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &creds);
16317c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &tmpcreds);
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate if (code) {
16347c478bd9Sstevel@tonic-gate *minor_status = code;
16357c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
16367c478bd9Sstevel@tonic-gate }
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate krb5_free_creds(context, out_creds);
16397c478bd9Sstevel@tonic-gate snprintf(ccache_name_buf, CACHE_FILENAME_LEN, "/tmp/krb5cc_%d",
16407c478bd9Sstevel@tonic-gate uid, -1);
16417c478bd9Sstevel@tonic-gate code = safechown(ccache_name_buf, uid, gid, -1);
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate if (code == -1) {
16447c478bd9Sstevel@tonic-gate (void) krb5_cc_destroy(context, ccache);
16457c478bd9Sstevel@tonic-gate *minor_status = code;
16467c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE);
16477c478bd9Sstevel@tonic-gate }
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate (void) krb5_cc_close(context, ccache);
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate /*
16567c478bd9Sstevel@tonic-gate * Solaris Kerberos:
16577c478bd9Sstevel@tonic-gate * We enforce a minimum refresh time on the root cred. This avoids problems for
16587c478bd9Sstevel@tonic-gate * the higher level communication protocol for having valid creds and
16597c478bd9Sstevel@tonic-gate * setting up a valid context, only to have it expire before or while
16607c478bd9Sstevel@tonic-gate * it is being used. For non root users we don't care since we do not refresh
16617c478bd9Sstevel@tonic-gate * there creds, they get what they can get.
16627c478bd9Sstevel@tonic-gate */
16637c478bd9Sstevel@tonic-gate #define MIN_REFRESH_TIME 300
16647c478bd9Sstevel@tonic-gate #define MIN_RENEW_TIME 1500
16657c478bd9Sstevel@tonic-gate
16667c478bd9Sstevel@tonic-gate /* get_default_cred() must be called with the krb5_mutex lock held */
16677c478bd9Sstevel@tonic-gate static OM_uint32
get_default_cred(OM_uint32 * minor_status,void * ct,gss_cred_id_t * cred_handle)16687c478bd9Sstevel@tonic-gate get_default_cred(OM_uint32 *minor_status, void *ct, gss_cred_id_t *cred_handle)
16697c478bd9Sstevel@tonic-gate {
16707c478bd9Sstevel@tonic-gate krb5_timestamp now;
16717c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred;
16727c478bd9Sstevel@tonic-gate OM_uint32 major;
16737c478bd9Sstevel@tonic-gate OM_uint32 mntmp;
167424da5b34Srie /*
167524da5b34Srie * Solaris Kerberos
167624da5b34Srie * Use krb5_getuid() to select the mechanism to obtain the uid.
167724da5b34Srie */
167824da5b34Srie uid_t uid = krb5_getuid();
16797c478bd9Sstevel@tonic-gate krb5_context context = (krb5_context)ct;
16807c478bd9Sstevel@tonic-gate
16817c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "get_default_cred() start\n");
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate /* Get the default cred for user */
1684*940daf74SToomas Soome if (((major = kg_get_defcred(minor_status, cred_handle)) != 0) &&
16857c478bd9Sstevel@tonic-gate GSS_ERROR(major)) {
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate /* If we're not root we're done */
16887c478bd9Sstevel@tonic-gate if (uid != ROOT_UID)
16897c478bd9Sstevel@tonic-gate return (major);
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate /*
16927c478bd9Sstevel@tonic-gate * Try and get root's cred in the cache using keytab.
16937c478bd9Sstevel@tonic-gate *
16947c478bd9Sstevel@tonic-gate * First try "root" and then try "host" - this allows
16957c478bd9Sstevel@tonic-gate * Secure NFS to use the host principal for mounting if
16967c478bd9Sstevel@tonic-gate * there is no root principal.
16977c478bd9Sstevel@tonic-gate *
16987c478bd9Sstevel@tonic-gate * Then try "host/<anything>" to match any instance (needed
16997c478bd9Sstevel@tonic-gate * for DHCP clients).
17007c478bd9Sstevel@tonic-gate */
17017c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17027c478bd9Sstevel@tonic-gate context, "root", 1);
17037c478bd9Sstevel@tonic-gate
17047c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17057c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17067c478bd9Sstevel@tonic-gate context, "host", 1);
17077c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17087c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17097c478bd9Sstevel@tonic-gate context, "host", 0);
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17127c478bd9Sstevel@tonic-gate return (major);
17137c478bd9Sstevel@tonic-gate
17147c478bd9Sstevel@tonic-gate /* We should have valid tgt now in the cache, so get it. */
17157c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle);
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate return (major);
17187c478bd9Sstevel@tonic-gate }
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate /* We've got a gss cred handle that is a kerberos cred handle. */
17217c478bd9Sstevel@tonic-gate cred = (krb5_gss_cred_id_t)*cred_handle;
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate /* If we can't get the time, assume the worst. */
17247c478bd9Sstevel@tonic-gate if (krb5_timeofday(context, &now)) {
1725ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle);
17267c478bd9Sstevel@tonic-gate return (GSS_S_CREDENTIALS_EXPIRED);
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate /* If root's cred has expired re-get it */
17307c478bd9Sstevel@tonic-gate if (cred->tgt_expire < now + MIN_REFRESH_TIME && uid == ROOT_UID) {
1731ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle);
17327c478bd9Sstevel@tonic-gate
17337c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17347c478bd9Sstevel@tonic-gate context, "root", 1);
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17377c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17387c478bd9Sstevel@tonic-gate context, "host", 1);
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17417c478bd9Sstevel@tonic-gate major = load_root_cred_using_keytab(minor_status,
17427c478bd9Sstevel@tonic-gate context, "host", 0);
17437c478bd9Sstevel@tonic-gate
17447c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17457c478bd9Sstevel@tonic-gate return (major);
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle);
17487c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17497c478bd9Sstevel@tonic-gate return (major);
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate /* Any body else is SOL unless we can renew their credential cache */
17527c478bd9Sstevel@tonic-gate } else if ((cred->tgt_expire < now + MIN_RENEW_TIME) &&
17537c478bd9Sstevel@tonic-gate (cred->tgt_expire > now)) {
1754ab9b2e15Sgtb (void) krb5_gss_release_cred(&mntmp, cred_handle);
17557c478bd9Sstevel@tonic-gate
17567c478bd9Sstevel@tonic-gate major = renew_ccache(minor_status, context, uid);
17577c478bd9Sstevel@tonic-gate if ((major != GSS_S_COMPLETE) &&
17587c478bd9Sstevel@tonic-gate (major != KDC_ERR_BADOPTION))
17597c478bd9Sstevel@tonic-gate return (major);
17607c478bd9Sstevel@tonic-gate
17617c478bd9Sstevel@tonic-gate major = kg_get_defcred(minor_status, cred_handle);
17627c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE)
17637c478bd9Sstevel@tonic-gate return (major);
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate /* Otherwise we got non expired creds */
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "get_default_cred() end\n");
17707c478bd9Sstevel@tonic-gate
17717c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
17727c478bd9Sstevel@tonic-gate }
17737c478bd9Sstevel@tonic-gate
1774ab9b2e15Sgtb /* Solaris Kerberos specific routines end */
1775