17c478bd9Sstevel@tonic-gate /*
25e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate /*
57c478bd9Sstevel@tonic-gate * Copyright 2000 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.
12*55fea89dSDan Cross *
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.
26*55fea89dSDan Cross *
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc.
30*55fea89dSDan Cross *
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.
40*55fea89dSDan Cross *
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.
52*55fea89dSDan Cross *
537c478bd9Sstevel@tonic-gate * All rights reserved.
54*55fea89dSDan Cross *
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.
59*55fea89dSDan Cross *
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.
70*55fea89dSDan Cross *
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
76ab9b2e15Sgtb #include "k5-int.h"
77ab9b2e15Sgtb #include "gss_libinit.h"
78ab9b2e15Sgtb #include "gssapiP_krb5.h"
79ab9b2e15Sgtb #include "mglueP.h"
807c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H
817c478bd9Sstevel@tonic-gate #include <string.h>
827c478bd9Sstevel@tonic-gate #else
837c478bd9Sstevel@tonic-gate #include <strings.h>
847c478bd9Sstevel@tonic-gate #endif
855e01956fSGlenn Barry #include <syslog.h>
865e01956fSGlenn Barry #include <locale.h> /* Solaris Kerberos */
875e01956fSGlenn Barry #include "file/ktfile.h" /* Solaris Kerberos */
887c478bd9Sstevel@tonic-gate
89ab9b2e15Sgtb #if defined(USE_LOGIN_LIBRARY)
90ab9b2e15Sgtb #include <Kerberos/KerberosLoginPrivate.h>
91ab9b2e15Sgtb #elif defined(USE_LEASH)
92159d09a2SMark Phalan #ifdef _WIN64
93159d09a2SMark Phalan #define LEASH_DLL "leashw64.dll"
94159d09a2SMark Phalan #else
95159d09a2SMark Phalan #define LEASH_DLL "leashw32.dll"
96159d09a2SMark Phalan #endif
97ab9b2e15Sgtb static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL;
98ab9b2e15Sgtb static HANDLE hLeashDLL = INVALID_HANDLE_VALUE;
99ab9b2e15Sgtb #endif
100ab9b2e15Sgtb
101ab9b2e15Sgtb k5_mutex_t gssint_krb5_keytab_lock = K5_MUTEX_PARTIAL_INITIALIZER;
102ab9b2e15Sgtb static char *krb5_gss_keytab = NULL;
103ab9b2e15Sgtb
104ab9b2e15Sgtb /* Heimdal calls this gsskrb5_register_acceptor_identity. */
105ab9b2e15Sgtb OM_uint32 KRB5_CALLCONV
krb5_gss_register_acceptor_identity(const char * keytab)106ab9b2e15Sgtb krb5_gss_register_acceptor_identity(const char *keytab)
107ab9b2e15Sgtb {
108ab9b2e15Sgtb size_t len;
109ab9b2e15Sgtb char *new, *old;
110ab9b2e15Sgtb int err;
111ab9b2e15Sgtb
112ab9b2e15Sgtb err = gssint_initialize_library();
113ab9b2e15Sgtb if (err != 0)
114ab9b2e15Sgtb return GSS_S_FAILURE;
115ab9b2e15Sgtb
116ab9b2e15Sgtb if (keytab == NULL)
117ab9b2e15Sgtb return GSS_S_FAILURE;
118ab9b2e15Sgtb
119ab9b2e15Sgtb len = strlen(keytab);
120ab9b2e15Sgtb new = malloc(len + 1);
121ab9b2e15Sgtb if (new == NULL)
122ab9b2e15Sgtb return GSS_S_FAILURE;
123ab9b2e15Sgtb strcpy(new, keytab);
124ab9b2e15Sgtb
125ab9b2e15Sgtb err = k5_mutex_lock(&gssint_krb5_keytab_lock);
126ab9b2e15Sgtb if (err) {
127ab9b2e15Sgtb free(new);
128ab9b2e15Sgtb return GSS_S_FAILURE;
129ab9b2e15Sgtb }
130ab9b2e15Sgtb old = krb5_gss_keytab;
131ab9b2e15Sgtb krb5_gss_keytab = new;
132ab9b2e15Sgtb k5_mutex_unlock(&gssint_krb5_keytab_lock);
133ab9b2e15Sgtb if (old != NULL)
134ab9b2e15Sgtb free(old);
135ab9b2e15Sgtb return GSS_S_COMPLETE;
136ab9b2e15Sgtb }
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /* get credentials corresponding to a key in the krb5 keytab.
1397c478bd9Sstevel@tonic-gate If the default name is requested, return the name in output_princ.
1407c478bd9Sstevel@tonic-gate If output_princ is non-NULL, the caller will use or free it, regardless
1417c478bd9Sstevel@tonic-gate of the return value.
1427c478bd9Sstevel@tonic-gate If successful, set the keytab-specific fields in cred
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate
145*55fea89dSDan Cross static OM_uint32
acquire_accept_cred(context,minor_status,desired_name,output_princ,cred)1467c478bd9Sstevel@tonic-gate acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
1477c478bd9Sstevel@tonic-gate krb5_context context;
1487c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
1497c478bd9Sstevel@tonic-gate gss_name_t desired_name;
1507c478bd9Sstevel@tonic-gate krb5_principal *output_princ;
1517c478bd9Sstevel@tonic-gate krb5_gss_cred_id_rec *cred;
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate krb5_error_code code;
1547c478bd9Sstevel@tonic-gate krb5_principal princ;
1557c478bd9Sstevel@tonic-gate krb5_keytab kt;
1567c478bd9Sstevel@tonic-gate krb5_keytab_entry entry;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate *output_princ = NULL;
1597c478bd9Sstevel@tonic-gate cred->keytab = NULL;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /* open the default keytab */
1627c478bd9Sstevel@tonic-gate
163ab9b2e15Sgtb code = gssint_initialize_library();
164ab9b2e15Sgtb if (code != 0) {
165ab9b2e15Sgtb *minor_status = code;
166ab9b2e15Sgtb return GSS_S_FAILURE;
167ab9b2e15Sgtb }
168ab9b2e15Sgtb code = k5_mutex_lock(&gssint_krb5_keytab_lock);
169ab9b2e15Sgtb if (code) {
170ab9b2e15Sgtb *minor_status = code;
171ab9b2e15Sgtb return GSS_S_FAILURE;
172ab9b2e15Sgtb }
173ab9b2e15Sgtb if (krb5_gss_keytab != NULL) {
174ab9b2e15Sgtb code = krb5_kt_resolve(context, krb5_gss_keytab, &kt);
175ab9b2e15Sgtb k5_mutex_unlock(&gssint_krb5_keytab_lock);
176ab9b2e15Sgtb } else {
177ab9b2e15Sgtb k5_mutex_unlock(&gssint_krb5_keytab_lock);
178ab9b2e15Sgtb code = krb5_kt_default(context, &kt);
179ab9b2e15Sgtb }
180ab9b2e15Sgtb
181ab9b2e15Sgtb if (code) {
1827c478bd9Sstevel@tonic-gate *minor_status = code;
183ab9b2e15Sgtb /* Solaris Kerb NOTE: GSS_S_CRED_UNAVAIL is not RFC 2743 compliant */
1847c478bd9Sstevel@tonic-gate return(GSS_S_NO_CRED);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1875e01956fSGlenn Barry if (desired_name != GSS_C_NO_NAME) {
1885e01956fSGlenn Barry princ = (krb5_principal) desired_name;
1895e01956fSGlenn Barry if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
1905e01956fSGlenn Barry if (code == KRB5_KT_NOTFOUND) {
1915e01956fSGlenn Barry char *s_name;
1925e01956fSGlenn Barry if (krb5_unparse_name(context, princ, &s_name) == 0) {
1935e01956fSGlenn Barry krb5_set_error_message(context, KG_KEYTAB_NOMATCH,
1945e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
1955e01956fSGlenn Barry "No principal in keytab ('%s') matches desired name %s"),
1965e01956fSGlenn Barry KTFILENAME(kt),
1975e01956fSGlenn Barry s_name);
1985e01956fSGlenn Barry krb5_free_unparsed_name(context, s_name);
1995e01956fSGlenn Barry }
2005e01956fSGlenn Barry *minor_status = KG_KEYTAB_NOMATCH;
2015e01956fSGlenn Barry } else
2025e01956fSGlenn Barry *minor_status = code;
203ab9b2e15Sgtb /* Solaris Kerb NOTE: GSS_S_CRED_UNAVAIL is not RFC 2743 compliant */
2045e01956fSGlenn Barry (void) krb5_kt_close(context, kt);
2055e01956fSGlenn Barry return(GSS_S_NO_CRED);
2065e01956fSGlenn Barry }
2075e01956fSGlenn Barry krb5_kt_free_entry(context, &entry);
2083dba6097Smp
2093dba6097Smp /* Open the replay cache for this principal. */
2103dba6097Smp if ((code = krb5_get_server_rcache(context,
2113dba6097Smp krb5_princ_component(context, princ, 0),
2123dba6097Smp &cred->rcache))) {
2137c478bd9Sstevel@tonic-gate *minor_status = code;
2147c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2175e01956fSGlenn Barry }
2187c478bd9Sstevel@tonic-gate
219ab9b2e15Sgtb /* hooray. we made it */
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate cred->keytab = kt;
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* get credentials corresponding to the default credential cache.
2277c478bd9Sstevel@tonic-gate If the default name is requested, return the name in output_princ.
2287c478bd9Sstevel@tonic-gate If output_princ is non-NULL, the caller will use or free it, regardless
2297c478bd9Sstevel@tonic-gate of the return value.
2307c478bd9Sstevel@tonic-gate If successful, set the ccache-specific fields in cred.
2317c478bd9Sstevel@tonic-gate */
2327c478bd9Sstevel@tonic-gate
233*55fea89dSDan Cross static OM_uint32
acquire_init_cred(context,minor_status,desired_name,output_princ,cred)2347c478bd9Sstevel@tonic-gate acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
2357c478bd9Sstevel@tonic-gate krb5_context context;
2367c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
2377c478bd9Sstevel@tonic-gate gss_name_t desired_name;
2387c478bd9Sstevel@tonic-gate krb5_principal *output_princ;
2397c478bd9Sstevel@tonic-gate krb5_gss_cred_id_rec *cred;
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate krb5_error_code code;
2427c478bd9Sstevel@tonic-gate krb5_ccache ccache;
2437c478bd9Sstevel@tonic-gate krb5_principal princ, tmp_princ;
2447c478bd9Sstevel@tonic-gate krb5_flags flags;
2457c478bd9Sstevel@tonic-gate krb5_cc_cursor cur;
2467c478bd9Sstevel@tonic-gate krb5_creds creds;
2477c478bd9Sstevel@tonic-gate int got_endtime;
248159d09a2SMark Phalan int caller_provided_ccache_name = 0;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate cred->ccache = NULL;
2517c478bd9Sstevel@tonic-gate
252505d05c7Sgtb /* load the GSS ccache name into the kg_context */
253*55fea89dSDan Cross
254505d05c7Sgtb if (GSS_ERROR(kg_sync_ccache_name(context, minor_status)))
255505d05c7Sgtb return(GSS_S_FAILURE);
2567c478bd9Sstevel@tonic-gate
257*55fea89dSDan Cross /* check to see if the caller provided a ccache name if so
258159d09a2SMark Phalan * we will just use that and not search the cache collection */
259159d09a2SMark Phalan if (GSS_ERROR(kg_caller_provided_ccache_name (minor_status, &caller_provided_ccache_name))) {
260159d09a2SMark Phalan return(GSS_S_FAILURE);
261159d09a2SMark Phalan }
262159d09a2SMark Phalan
263ab9b2e15Sgtb #if defined(USE_LOGIN_LIBRARY) || defined(USE_LEASH)
264159d09a2SMark Phalan if (desired_name && !caller_provided_ccache_name) {
265ab9b2e15Sgtb #if defined(USE_LOGIN_LIBRARY)
266159d09a2SMark Phalan KLStatus err = klNoErr;
267ab9b2e15Sgtb char *ccache_name = NULL;
268ab9b2e15Sgtb KLPrincipal kl_desired_princ = NULL;
269159d09a2SMark Phalan
270159d09a2SMark Phalan err = __KLCreatePrincipalFromKerberos5Principal ((krb5_principal) desired_name,
271159d09a2SMark Phalan &kl_desired_princ);
272*55fea89dSDan Cross
273159d09a2SMark Phalan if (!err) {
274159d09a2SMark Phalan err = KLAcquireInitialTickets (kl_desired_princ, NULL, NULL, &ccache_name);
275ab9b2e15Sgtb }
276159d09a2SMark Phalan
277159d09a2SMark Phalan if (!err) {
278159d09a2SMark Phalan err = krb5_cc_resolve (context, ccache_name, &ccache);
279ab9b2e15Sgtb }
280*55fea89dSDan Cross
281159d09a2SMark Phalan if (err) {
282159d09a2SMark Phalan *minor_status = err;
283159d09a2SMark Phalan return(GSS_S_CRED_UNAVAIL);
284ab9b2e15Sgtb }
285*55fea89dSDan Cross
286ab9b2e15Sgtb if (kl_desired_princ != NULL) { KLDisposePrincipal (kl_desired_princ); }
287ab9b2e15Sgtb if (ccache_name != NULL) { KLDisposeString (ccache_name); }
288*55fea89dSDan Cross
289ab9b2e15Sgtb #elif defined(USE_LEASH)
290ab9b2e15Sgtb if ( hLeashDLL == INVALID_HANDLE_VALUE ) {
291159d09a2SMark Phalan hLeashDLL = LoadLibrary(LEASH_DLL);
292ab9b2e15Sgtb if ( hLeashDLL != INVALID_HANDLE_VALUE ) {
293ab9b2e15Sgtb (FARPROC) pLeash_AcquireInitialTicketsIfNeeded =
294ab9b2e15Sgtb GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded");
295ab9b2e15Sgtb }
296ab9b2e15Sgtb }
297*55fea89dSDan Cross
298ab9b2e15Sgtb if ( pLeash_AcquireInitialTicketsIfNeeded ) {
299ab9b2e15Sgtb char ccname[256]="";
300ab9b2e15Sgtb pLeash_AcquireInitialTicketsIfNeeded(context, (krb5_principal) desired_name, ccname, sizeof(ccname));
301ab9b2e15Sgtb if (!ccname[0]) {
302ab9b2e15Sgtb *minor_status = KRB5_CC_NOTFOUND;
303ab9b2e15Sgtb return(GSS_S_NO_CRED);
304ab9b2e15Sgtb }
305ab9b2e15Sgtb
306ab9b2e15Sgtb if ((code = krb5_cc_resolve (context, ccname, &ccache))) {
307ab9b2e15Sgtb *minor_status = code;
308ab9b2e15Sgtb return(GSS_S_NO_CRED);
309ab9b2e15Sgtb }
310ab9b2e15Sgtb } else {
311ab9b2e15Sgtb /* leash dll not available, open the default credential cache */
312*55fea89dSDan Cross
313ab9b2e15Sgtb if ((code = krb5int_cc_default(context, &ccache))) {
314ab9b2e15Sgtb *minor_status = code;
315ab9b2e15Sgtb return(GSS_S_NO_CRED);
316ab9b2e15Sgtb }
317ab9b2e15Sgtb }
318ab9b2e15Sgtb #endif /* USE_LEASH */
319ab9b2e15Sgtb } else
320ab9b2e15Sgtb #endif /* USE_LOGIN_LIBRARY || USE_LEASH */
321ab9b2e15Sgtb {
322ab9b2e15Sgtb /* open the default credential cache */
323*55fea89dSDan Cross
324ab9b2e15Sgtb if ((code = krb5int_cc_default(context, &ccache))) {
325ab9b2e15Sgtb *minor_status = code;
326ab9b2e15Sgtb return(GSS_S_NO_CRED);
327ab9b2e15Sgtb }
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate /* turn off OPENCLOSE mode while extensive frobbing is going on */
331505d05c7Sgtb /*
332505d05c7Sgtb * SUNW14resync
333505d05c7Sgtb * Added calls to krb5_cc_set_flags(... KRB5_TC_OPENCLOSE)
334505d05c7Sgtb * on the error returns cuz the 1.4 krb5_cc_close does not always close
335505d05c7Sgtb * the file like it used to and caused STC test gss.27 to fail.
336505d05c7Sgtb */
3377c478bd9Sstevel@tonic-gate flags = 0; /* turns off OPENCLOSE mode */
338ab9b2e15Sgtb if ((code = krb5_cc_set_flags(context, ccache, flags))) {
339505d05c7Sgtb (void)krb5_cc_close(context, ccache);
3407c478bd9Sstevel@tonic-gate *minor_status = code;
3417c478bd9Sstevel@tonic-gate return(GSS_S_NO_CRED);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /* get out the principal name and see if it matches */
3457c478bd9Sstevel@tonic-gate
346ab9b2e15Sgtb if ((code = krb5_cc_get_principal(context, ccache, &princ))) {
347159d09a2SMark Phalan /* Solaris Kerberos */
348505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
3497c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
3507c478bd9Sstevel@tonic-gate *minor_status = code;
3517c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate if (desired_name != (gss_name_t) NULL) {
3557c478bd9Sstevel@tonic-gate if (! krb5_principal_compare(context, princ, (krb5_principal) desired_name)) {
3567c478bd9Sstevel@tonic-gate (void)krb5_free_principal(context, princ);
357159d09a2SMark Phalan /* Solaris Kerberos */
358ab9b2e15Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
3597c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
3607c478bd9Sstevel@tonic-gate *minor_status = KG_CCACHE_NOMATCH;
3617c478bd9Sstevel@tonic-gate return(GSS_S_NO_CRED);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate (void)krb5_free_principal(context, princ);
3647c478bd9Sstevel@tonic-gate princ = (krb5_principal) desired_name;
3657c478bd9Sstevel@tonic-gate } else {
3667c478bd9Sstevel@tonic-gate *output_princ = princ;
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /* iterate over the ccache, find the tgt */
3707c478bd9Sstevel@tonic-gate
371ab9b2e15Sgtb if ((code = krb5_cc_start_seq_get(context, ccache, &cur))) {
372159d09a2SMark Phalan /* Solaris Kerberos */
373505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
3747c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
3757c478bd9Sstevel@tonic-gate *minor_status = code;
3767c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate /* this is hairy. If there's a tgt for the principal's local realm
3807c478bd9Sstevel@tonic-gate in here, that's what we want for the expire time. But if
3817c478bd9Sstevel@tonic-gate there's not, then we want to use the first key. */
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate got_endtime = 0;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate code = krb5_build_principal_ext(context, &tmp_princ,
3867c478bd9Sstevel@tonic-gate krb5_princ_realm(context, princ)->length,
3877c478bd9Sstevel@tonic-gate krb5_princ_realm(context, princ)->data,
3887c478bd9Sstevel@tonic-gate 6, "krbtgt",
3897c478bd9Sstevel@tonic-gate krb5_princ_realm(context, princ)->length,
3907c478bd9Sstevel@tonic-gate krb5_princ_realm(context, princ)->data,
3917c478bd9Sstevel@tonic-gate 0);
3927c478bd9Sstevel@tonic-gate if (code) {
393159d09a2SMark Phalan /* Solaris Kerberos */
394505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
3957c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
3967c478bd9Sstevel@tonic-gate *minor_status = code;
3977c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
3987c478bd9Sstevel@tonic-gate }
399ab9b2e15Sgtb while (!(code = krb5_cc_next_cred(context, ccache, &cur, &creds))) {
4007c478bd9Sstevel@tonic-gate if (krb5_principal_compare(context, tmp_princ, creds.server)) {
4017c478bd9Sstevel@tonic-gate cred->tgt_expire = creds.times.endtime;
4027c478bd9Sstevel@tonic-gate got_endtime = 1;
4037c478bd9Sstevel@tonic-gate *minor_status = 0;
4047c478bd9Sstevel@tonic-gate code = 0;
4057c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &creds);
4067c478bd9Sstevel@tonic-gate break;
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate if (got_endtime == 0) {
4097c478bd9Sstevel@tonic-gate cred->tgt_expire = creds.times.endtime;
4107c478bd9Sstevel@tonic-gate got_endtime = 1;
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate krb5_free_cred_contents(context, &creds);
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate krb5_free_principal(context, tmp_princ);
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate if (code && code != KRB5_CC_END) {
4177c478bd9Sstevel@tonic-gate /* this means some error occurred reading the ccache */
4187c478bd9Sstevel@tonic-gate (void)krb5_cc_end_seq_get(context, ccache, &cur);
419159d09a2SMark Phalan /* Solaris Kerberos */
420505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
4217c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
4227c478bd9Sstevel@tonic-gate *minor_status = code;
4237c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
4247c478bd9Sstevel@tonic-gate } else if (! got_endtime) {
4257c478bd9Sstevel@tonic-gate /* this means the ccache was entirely empty */
4267c478bd9Sstevel@tonic-gate (void)krb5_cc_end_seq_get(context, ccache, &cur);
427159d09a2SMark Phalan /* Solaris Kerberos */
428505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
4297c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
4307c478bd9Sstevel@tonic-gate *minor_status = KG_EMPTY_CCACHE;
4317c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
4327c478bd9Sstevel@tonic-gate } else {
4337c478bd9Sstevel@tonic-gate /* this means that we found an endtime to use. */
434ab9b2e15Sgtb if ((code = krb5_cc_end_seq_get(context, ccache, &cur))) {
435159d09a2SMark Phalan /* Solaris Kerberos */
436505d05c7Sgtb (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
4377c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
4387c478bd9Sstevel@tonic-gate *minor_status = code;
4397c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
442ab9b2e15Sgtb if ((code = krb5_cc_set_flags(context, ccache, flags))) {
4437c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, ccache);
4447c478bd9Sstevel@tonic-gate *minor_status = code;
4457c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate /* the credentials match and are valid */
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate cred->ccache = ccache;
4527c478bd9Sstevel@tonic-gate /* minor_status is set while we are iterating over the ccache */
4537c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
4547c478bd9Sstevel@tonic-gate }
455*55fea89dSDan Cross
4567c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4577c478bd9Sstevel@tonic-gate OM_uint32
krb5_gss_acquire_cred(minor_status,desired_name,time_req,desired_mechs,cred_usage,output_cred_handle,actual_mechs,time_rec)458ab9b2e15Sgtb krb5_gss_acquire_cred(minor_status, desired_name, time_req,
4597c478bd9Sstevel@tonic-gate desired_mechs, cred_usage, output_cred_handle,
4607c478bd9Sstevel@tonic-gate actual_mechs, time_rec)
4617c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
4627c478bd9Sstevel@tonic-gate gss_name_t desired_name;
4637c478bd9Sstevel@tonic-gate OM_uint32 time_req;
4647c478bd9Sstevel@tonic-gate gss_OID_set desired_mechs;
4657c478bd9Sstevel@tonic-gate gss_cred_usage_t cred_usage;
4667c478bd9Sstevel@tonic-gate gss_cred_id_t *output_cred_handle;
4677c478bd9Sstevel@tonic-gate gss_OID_set *actual_mechs;
4687c478bd9Sstevel@tonic-gate OM_uint32 *time_rec;
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate krb5_context context;
4717c478bd9Sstevel@tonic-gate size_t i;
4727c478bd9Sstevel@tonic-gate krb5_gss_cred_id_t cred;
473ab9b2e15Sgtb gss_OID_set ret_mechs;
4747c478bd9Sstevel@tonic-gate int req_old, req_new;
4757c478bd9Sstevel@tonic-gate OM_uint32 ret;
4767c478bd9Sstevel@tonic-gate krb5_error_code code;
4777c478bd9Sstevel@tonic-gate
478ab9b2e15Sgtb code = gssint_initialize_library();
479ab9b2e15Sgtb if (code) {
480ab9b2e15Sgtb *minor_status = code;
481ab9b2e15Sgtb return GSS_S_FAILURE;
482ab9b2e15Sgtb }
4837c478bd9Sstevel@tonic-gate
484ab9b2e15Sgtb code = krb5_gss_init_context(&context);
485ab9b2e15Sgtb if (code) {
486ab9b2e15Sgtb *minor_status = code;
487ab9b2e15Sgtb return GSS_S_FAILURE;
488ab9b2e15Sgtb }
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate /* make sure all outputs are valid */
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate *output_cred_handle = NULL;
4937c478bd9Sstevel@tonic-gate if (actual_mechs)
4947c478bd9Sstevel@tonic-gate *actual_mechs = NULL;
4957c478bd9Sstevel@tonic-gate if (time_rec)
4967c478bd9Sstevel@tonic-gate *time_rec = 0;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate /* validate the name */
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate /*SUPPRESS 29*/
5017c478bd9Sstevel@tonic-gate if ((desired_name != (gss_name_t) NULL) &&
5027c478bd9Sstevel@tonic-gate (! kg_validate_name(desired_name))) {
503*55fea89dSDan Cross *minor_status = (OM_uint32) G_VALIDATE_FAILED;
5045e01956fSGlenn Barry krb5_free_context(context);
5055e01956fSGlenn Barry return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /* verify that the requested mechanism set is the default, or
5097c478bd9Sstevel@tonic-gate contains krb5 */
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate if (desired_mechs == GSS_C_NULL_OID_SET) {
5127c478bd9Sstevel@tonic-gate req_old = 1;
5137c478bd9Sstevel@tonic-gate req_new = 1;
5147c478bd9Sstevel@tonic-gate } else {
5157c478bd9Sstevel@tonic-gate req_old = 0;
5167c478bd9Sstevel@tonic-gate req_new = 0;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate for (i=0; i<desired_mechs->count; i++) {
5197c478bd9Sstevel@tonic-gate if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i])))
5207c478bd9Sstevel@tonic-gate req_old++;
5217c478bd9Sstevel@tonic-gate if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i])))
5227c478bd9Sstevel@tonic-gate req_new++;
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate if (!req_old && !req_new) {
5267c478bd9Sstevel@tonic-gate *minor_status = 0;
527ab9b2e15Sgtb krb5_free_context(context);
5287c478bd9Sstevel@tonic-gate return(GSS_S_BAD_MECH);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate /* create the gss cred structure */
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate if ((cred =
5357c478bd9Sstevel@tonic-gate (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec))) == NULL) {
5367c478bd9Sstevel@tonic-gate *minor_status = ENOMEM;
537ab9b2e15Sgtb krb5_free_context(context);
5387c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate cred->usage = cred_usage;
5437c478bd9Sstevel@tonic-gate cred->princ = NULL;
5447c478bd9Sstevel@tonic-gate cred->prerfc_mech = req_old;
5457c478bd9Sstevel@tonic-gate cred->rfc_mech = req_new;
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate cred->keytab = NULL;
5487c478bd9Sstevel@tonic-gate cred->ccache = NULL;
5497c478bd9Sstevel@tonic-gate
550ab9b2e15Sgtb code = k5_mutex_init(&cred->lock);
551ab9b2e15Sgtb if (code) {
552ab9b2e15Sgtb *minor_status = code;
553ab9b2e15Sgtb krb5_free_context(context);
554ab9b2e15Sgtb return GSS_S_FAILURE;
555ab9b2e15Sgtb }
556ab9b2e15Sgtb /* Note that we don't need to lock this GSSAPI credential record
557ab9b2e15Sgtb here, because no other thread can gain access to it until we
558ab9b2e15Sgtb return it. */
559ab9b2e15Sgtb
5607c478bd9Sstevel@tonic-gate if ((cred_usage != GSS_C_INITIATE) &&
5617c478bd9Sstevel@tonic-gate (cred_usage != GSS_C_ACCEPT) &&
5627c478bd9Sstevel@tonic-gate (cred_usage != GSS_C_BOTH)) {
563ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
5647c478bd9Sstevel@tonic-gate xfree(cred);
5657c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_BAD_USAGE;
566ab9b2e15Sgtb krb5_free_context(context);
5677c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate /* if requested, acquire credentials for accepting */
5717c478bd9Sstevel@tonic-gate /* this will fill in cred->princ if the desired_name is not specified */
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate if ((cred_usage == GSS_C_ACCEPT) ||
5747c478bd9Sstevel@tonic-gate (cred_usage == GSS_C_BOTH))
5757c478bd9Sstevel@tonic-gate if ((ret = acquire_accept_cred(context, minor_status, desired_name,
5767c478bd9Sstevel@tonic-gate &(cred->princ), cred))
5777c478bd9Sstevel@tonic-gate != GSS_S_COMPLETE) {
5787c478bd9Sstevel@tonic-gate if (cred->princ)
5797c478bd9Sstevel@tonic-gate krb5_free_principal(context, cred->princ);
580ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
581ab9b2e15Sgtb xfree(cred);
5827c478bd9Sstevel@tonic-gate /* minor_status set by acquire_accept_cred() */
5835e01956fSGlenn Barry save_error_info(*minor_status, context);
584ab9b2e15Sgtb krb5_free_context(context);
5857c478bd9Sstevel@tonic-gate return(ret);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate /* if requested, acquire credentials for initiation */
5897c478bd9Sstevel@tonic-gate /* this will fill in cred->princ if it wasn't set above, and
5907c478bd9Sstevel@tonic-gate the desired_name is not specified */
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate if ((cred_usage == GSS_C_INITIATE) ||
5937c478bd9Sstevel@tonic-gate (cred_usage == GSS_C_BOTH))
5947c478bd9Sstevel@tonic-gate if ((ret =
5957c478bd9Sstevel@tonic-gate acquire_init_cred(context, minor_status,
5967c478bd9Sstevel@tonic-gate cred->princ?(gss_name_t)cred->princ:desired_name,
5977c478bd9Sstevel@tonic-gate &(cred->princ), cred))
5987c478bd9Sstevel@tonic-gate != GSS_S_COMPLETE) {
5997c478bd9Sstevel@tonic-gate if (cred->keytab)
600ab9b2e15Sgtb krb5_kt_close(context, cred->keytab);
6017c478bd9Sstevel@tonic-gate if (cred->princ)
6027c478bd9Sstevel@tonic-gate krb5_free_principal(context, cred->princ);
603ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
604ab9b2e15Sgtb xfree(cred);
6057c478bd9Sstevel@tonic-gate /* minor_status set by acquire_init_cred() */
6065e01956fSGlenn Barry save_error_info(*minor_status, context);
607ab9b2e15Sgtb krb5_free_context(context);
6087c478bd9Sstevel@tonic-gate return(ret);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6113dba6097Smp /* Solaris Kerberos:
612ab9b2e15Sgtb * if the princ wasn't filled in already, fill it in now unless
6133dba6097Smp * a cred with no associated princ is requested (will invoke default
6143dba6097Smp * behaviour when gss_accept_init_context() is called).
615ab9b2e15Sgtb * Note MIT 1.4 has GSS_C_NO_CREDENTIAL instead of GSS_C_NO_NAME
6163dba6097Smp */
6173dba6097Smp if (!cred->princ && (desired_name != GSS_C_NO_NAME))
6187c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, (krb5_principal) desired_name,
6197c478bd9Sstevel@tonic-gate &(cred->princ)))) {
6207c478bd9Sstevel@tonic-gate if (cred->ccache)
6217c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, cred->ccache);
6227c478bd9Sstevel@tonic-gate if (cred->keytab)
6237c478bd9Sstevel@tonic-gate (void)krb5_kt_close(context, cred->keytab);
624ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
625ab9b2e15Sgtb xfree(cred);
6267c478bd9Sstevel@tonic-gate *minor_status = code;
6275e01956fSGlenn Barry save_error_info(*minor_status, context);
628ab9b2e15Sgtb krb5_free_context(context);
6297c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*** at this point, the cred structure has been completely created */
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate /* compute time_rec */
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) {
6377c478bd9Sstevel@tonic-gate if (time_rec)
6387c478bd9Sstevel@tonic-gate *time_rec = GSS_C_INDEFINITE;
6397c478bd9Sstevel@tonic-gate } else {
6407c478bd9Sstevel@tonic-gate krb5_timestamp now;
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(context, &now))) {
6437c478bd9Sstevel@tonic-gate if (cred->ccache)
6447c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, cred->ccache);
6457c478bd9Sstevel@tonic-gate if (cred->keytab)
6467c478bd9Sstevel@tonic-gate (void)krb5_kt_close(context, cred->keytab);
6477c478bd9Sstevel@tonic-gate if (cred->princ)
6487c478bd9Sstevel@tonic-gate krb5_free_principal(context, cred->princ);
649ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
650ab9b2e15Sgtb xfree(cred);
6517c478bd9Sstevel@tonic-gate *minor_status = code;
6525e01956fSGlenn Barry save_error_info(*minor_status, context);
653ab9b2e15Sgtb krb5_free_context(context);
6547c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate if (time_rec)
6587c478bd9Sstevel@tonic-gate *time_rec = (cred->tgt_expire > now) ? (cred->tgt_expire - now) : 0;
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate /* create mechs */
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate if (actual_mechs) {
664ab9b2e15Sgtb if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
6657c478bd9Sstevel@tonic-gate &ret_mechs)) ||
6667c478bd9Sstevel@tonic-gate (cred->prerfc_mech &&
667ab9b2e15Sgtb GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
668159d09a2SMark Phalan (const gss_OID) gss_mech_krb5_old,
6697c478bd9Sstevel@tonic-gate &ret_mechs))) ||
6707c478bd9Sstevel@tonic-gate (cred->rfc_mech &&
671ab9b2e15Sgtb GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
672159d09a2SMark Phalan (const gss_OID) gss_mech_krb5,
6737c478bd9Sstevel@tonic-gate &ret_mechs)))) {
6747c478bd9Sstevel@tonic-gate if (cred->ccache)
6757c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, cred->ccache);
6767c478bd9Sstevel@tonic-gate if (cred->keytab)
6777c478bd9Sstevel@tonic-gate (void)krb5_kt_close(context, cred->keytab);
6787c478bd9Sstevel@tonic-gate if (cred->princ)
6797c478bd9Sstevel@tonic-gate krb5_free_principal(context, cred->princ);
680ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
6817c478bd9Sstevel@tonic-gate xfree(cred);
682ab9b2e15Sgtb /* *minor_status set above */
683ab9b2e15Sgtb krb5_free_context(context);
6847c478bd9Sstevel@tonic-gate return(ret);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate /* intern the credential handle */
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate if (! kg_save_cred_id((gss_cred_id_t) cred)) {
6917c478bd9Sstevel@tonic-gate free(ret_mechs->elements);
6927c478bd9Sstevel@tonic-gate free(ret_mechs);
6937c478bd9Sstevel@tonic-gate if (cred->ccache)
6947c478bd9Sstevel@tonic-gate (void)krb5_cc_close(context, cred->ccache);
6957c478bd9Sstevel@tonic-gate if (cred->keytab)
6967c478bd9Sstevel@tonic-gate (void)krb5_kt_close(context, cred->keytab);
6977c478bd9Sstevel@tonic-gate if (cred->princ)
6987c478bd9Sstevel@tonic-gate krb5_free_principal(context, cred->princ);
699ab9b2e15Sgtb k5_mutex_destroy(&cred->lock);
7007c478bd9Sstevel@tonic-gate xfree(cred);
7017c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_VALIDATE_FAILED;
7025e01956fSGlenn Barry save_error_string(*minor_status, "error saving credentials");
703ab9b2e15Sgtb krb5_free_context(context);
7047c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate /* return success */
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate *minor_status = 0;
7107c478bd9Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t) cred;
7117c478bd9Sstevel@tonic-gate if (actual_mechs)
7127c478bd9Sstevel@tonic-gate *actual_mechs = ret_mechs;
713ab9b2e15Sgtb
714ab9b2e15Sgtb krb5_free_context(context);
7157c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE);
7167c478bd9Sstevel@tonic-gate }
717