15e01956fSGlenn Barry /*
25e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
35e01956fSGlenn Barry  */
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 (C) 1998 by the FundsXpress, INC.
30*55fea89dSDan Cross  *
317c478bd9Sstevel@tonic-gate  * All rights reserved.
32*55fea89dSDan Cross  *
337c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
347c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
357c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
367c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
37*55fea89dSDan Cross  *
387c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
397c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
407c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
417c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
427c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
437c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
447c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
457c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
467c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
477c478bd9Sstevel@tonic-gate  * or implied warranty.
48*55fea89dSDan Cross  *
497c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
507c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
517c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
54ab9b2e15Sgtb #include "gssapiP_krb5.h"
557c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H
567c478bd9Sstevel@tonic-gate #include <string.h>
577c478bd9Sstevel@tonic-gate #else
587c478bd9Sstevel@tonic-gate #include <strings.h>
597c478bd9Sstevel@tonic-gate #endif
605e01956fSGlenn Barry #include <locale.h> /* Solaris Kerberos */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
63159d09a2SMark Phalan  * $Id: add_cred.c 18396 2006-07-25 20:29:43Z lxs $
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /* V2 interface */
677c478bd9Sstevel@tonic-gate OM_uint32
krb5_gss_add_cred(minor_status,input_cred_handle,desired_name,desired_mech,cred_usage,initiator_time_req,acceptor_time_req,output_cred_handle,actual_mechs,initiator_time_rec,acceptor_time_rec)68ab9b2e15Sgtb krb5_gss_add_cred(minor_status, input_cred_handle,
697c478bd9Sstevel@tonic-gate 		  desired_name, desired_mech, cred_usage,
707c478bd9Sstevel@tonic-gate 		  initiator_time_req, acceptor_time_req,
71*55fea89dSDan Cross 		  output_cred_handle, actual_mechs,
727c478bd9Sstevel@tonic-gate 		  initiator_time_rec, acceptor_time_rec)
737c478bd9Sstevel@tonic-gate     OM_uint32		*minor_status;
747c478bd9Sstevel@tonic-gate     gss_cred_id_t	input_cred_handle;
757c478bd9Sstevel@tonic-gate     gss_name_t		desired_name;
767c478bd9Sstevel@tonic-gate     gss_OID		desired_mech;
777c478bd9Sstevel@tonic-gate     gss_cred_usage_t	cred_usage;
787c478bd9Sstevel@tonic-gate     OM_uint32		initiator_time_req;
797c478bd9Sstevel@tonic-gate     OM_uint32		acceptor_time_req;
807c478bd9Sstevel@tonic-gate     gss_cred_id_t	*output_cred_handle;
817c478bd9Sstevel@tonic-gate     gss_OID_set		*actual_mechs;
827c478bd9Sstevel@tonic-gate     OM_uint32		*initiator_time_rec;
837c478bd9Sstevel@tonic-gate     OM_uint32		*acceptor_time_rec;
847c478bd9Sstevel@tonic-gate {
85ab9b2e15Sgtb     krb5_context	context;
86ab9b2e15Sgtb     OM_uint32		major_status, lifetime;
877c478bd9Sstevel@tonic-gate     krb5_gss_cred_id_t	cred;
887c478bd9Sstevel@tonic-gate     krb5_error_code	code;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate     /* this is pretty simple, since there's not really any difference
917c478bd9Sstevel@tonic-gate        between the underlying mechanisms.  The main hair is in copying
927c478bd9Sstevel@tonic-gate        a mechanism if requested. */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate     /* check if the desired_mech is bogus */
957c478bd9Sstevel@tonic-gate 
96ab9b2e15Sgtb     if (!g_OID_equal(desired_mech, gss_mech_krb5) &&
977c478bd9Sstevel@tonic-gate 	!g_OID_equal(desired_mech, gss_mech_krb5_old)) {
987c478bd9Sstevel@tonic-gate 	*minor_status = 0;
997c478bd9Sstevel@tonic-gate 	return(GSS_S_BAD_MECH);
1007c478bd9Sstevel@tonic-gate     }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate     /* check if the desired_mech is bogus */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate     if ((cred_usage != GSS_C_INITIATE) &&
1057c478bd9Sstevel@tonic-gate 	(cred_usage != GSS_C_ACCEPT) &&
1067c478bd9Sstevel@tonic-gate 	(cred_usage != GSS_C_BOTH)) {
1077c478bd9Sstevel@tonic-gate 	*minor_status = (OM_uint32) G_BAD_USAGE;
1087c478bd9Sstevel@tonic-gate 	return(GSS_S_FAILURE);
1097c478bd9Sstevel@tonic-gate     }
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate     /* since the default credential includes all the mechanisms,
1127c478bd9Sstevel@tonic-gate        return an error for that case. */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate     /*SUPPRESS 29*/
1157c478bd9Sstevel@tonic-gate     if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
1167c478bd9Sstevel@tonic-gate 	*minor_status = 0;
1177c478bd9Sstevel@tonic-gate 	return(GSS_S_DUPLICATE_ELEMENT);
1187c478bd9Sstevel@tonic-gate     }
1197c478bd9Sstevel@tonic-gate 
120ab9b2e15Sgtb     code = krb5_gss_init_context(&context);
121ab9b2e15Sgtb     if (code) {
122ab9b2e15Sgtb 	*minor_status = code;
123ab9b2e15Sgtb 	return GSS_S_FAILURE;
124ab9b2e15Sgtb     }
1257c478bd9Sstevel@tonic-gate 
126ab9b2e15Sgtb     major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle,
127ab9b2e15Sgtb 					    context);
128ab9b2e15Sgtb     if (GSS_ERROR(major_status)) {
1295e01956fSGlenn Barry         save_error_info(*minor_status, context);
130ab9b2e15Sgtb 	krb5_free_context(context);
131ab9b2e15Sgtb 	return major_status;
1327c478bd9Sstevel@tonic-gate     }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate     cred = (krb5_gss_cred_id_t) input_cred_handle;
135ab9b2e15Sgtb     k5_mutex_assert_locked(&cred->lock);
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate     /* check if the cred_usage is equal or "less" than the passed-in cred
1387c478bd9Sstevel@tonic-gate        if copying */
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate     if (!((cred->usage == cred_usage) ||
1417c478bd9Sstevel@tonic-gate 	  ((cred->usage == GSS_C_BOTH) &&
1427c478bd9Sstevel@tonic-gate 	   (output_cred_handle != NULL)))) {
143ab9b2e15Sgtb       *minor_status = (OM_uint32) G_BAD_USAGE;
144ab9b2e15Sgtb       krb5_free_context(context);
145ab9b2e15Sgtb       return(GSS_S_FAILURE);
1467c478bd9Sstevel@tonic-gate     }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate     /* check that desired_mech isn't already in the credential */
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate     if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) ||
1517c478bd9Sstevel@tonic-gate 	(g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech)) {
1527c478bd9Sstevel@tonic-gate 	*minor_status = 0;
153ab9b2e15Sgtb 	krb5_free_context(context);
154ab9b2e15Sgtb 	return(GSS_S_DUPLICATE_ELEMENT);
155ab9b2e15Sgtb     }
156ab9b2e15Sgtb 
157ab9b2e15Sgtb     if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) {
1585e01956fSGlenn Barry         save_error_info(*minor_status, context);
159ab9b2e15Sgtb 	krb5_free_context(context);
160ab9b2e15Sgtb 	return GSS_S_FAILURE;
1617c478bd9Sstevel@tonic-gate     }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate     /* verify the desired_name */
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate     /*SUPPRESS 29*/
1667c478bd9Sstevel@tonic-gate     if ((desired_name != (gss_name_t) NULL) &&
1677c478bd9Sstevel@tonic-gate 	(! kg_validate_name(desired_name))) {
168*55fea89dSDan Cross 	*minor_status = (OM_uint32) G_VALIDATE_FAILED;
169ab9b2e15Sgtb 	krb5_free_context(context);
170ab9b2e15Sgtb 	return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
1717c478bd9Sstevel@tonic-gate     }
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate     /* make sure the desired_name is the same as the existing one */
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate     if (desired_name &&
1767c478bd9Sstevel@tonic-gate 	!krb5_principal_compare(context, (krb5_principal) desired_name,
1777c478bd9Sstevel@tonic-gate 				cred->princ)) {
1785e01956fSGlenn Barry         /* Solaris Kerberos: spruce-up the err msg */
1795e01956fSGlenn Barry         krb5_principal dname = (krb5_principal) desired_name;
1805e01956fSGlenn Barry 	char *s_name = NULL, *s_princ= NULL;
1815e01956fSGlenn Barry 	int kret = krb5_unparse_name(context, dname, &s_name);
1825e01956fSGlenn Barry 	int kret1 = krb5_unparse_name(context, cred->princ, &s_princ);
1835e01956fSGlenn Barry 	*minor_status = (OM_uint32) G_BAD_USAGE;
1845e01956fSGlenn Barry 	if (kret == 0 && kret1 == 0) {
1855e01956fSGlenn Barry 	    krb5_set_error_message(context, *minor_status,
1865e01956fSGlenn Barry 				dgettext(TEXT_DOMAIN,
1875e01956fSGlenn Barry 					"Desired name principal '%s' does not match '%s'"),
1885e01956fSGlenn Barry 				s_name, s_princ);
1895e01956fSGlenn Barry 	    save_error_info(*minor_status, context);
1905e01956fSGlenn Barry 	}
1915e01956fSGlenn Barry 	if (s_name)
1925e01956fSGlenn Barry 	    krb5_free_unparsed_name(context, s_name);
1935e01956fSGlenn Barry 	if (s_princ)
1945e01956fSGlenn Barry 	    krb5_free_unparsed_name(context, s_princ);
1955e01956fSGlenn Barry 
196ab9b2e15Sgtb 	krb5_free_context(context);
197ab9b2e15Sgtb 	return(GSS_S_BAD_NAME);
1987c478bd9Sstevel@tonic-gate     }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate     /* copy the cred if necessary */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate     if (output_cred_handle) {
2037c478bd9Sstevel@tonic-gate 	/* make a copy */
2047c478bd9Sstevel@tonic-gate 	krb5_gss_cred_id_t new_cred;
2057c478bd9Sstevel@tonic-gate 	char *kttype, ktboth[1024];
206505d05c7Sgtb 	const char *cctype, *ccname;
207505d05c7Sgtb 	char ccboth[1024];
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if ((new_cred =
2107c478bd9Sstevel@tonic-gate 	     (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))
2117c478bd9Sstevel@tonic-gate 	    == NULL) {
2127c478bd9Sstevel@tonic-gate 	    *minor_status = ENOMEM;
213ab9b2e15Sgtb 	    krb5_free_context(context);
214ab9b2e15Sgtb 	    return(GSS_S_FAILURE);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	memset(new_cred, 0, sizeof(krb5_gss_cred_id_rec));
217*55fea89dSDan Cross 
2187c478bd9Sstevel@tonic-gate 	new_cred->usage = cred_usage;
2197c478bd9Sstevel@tonic-gate 	new_cred->prerfc_mech = cred->prerfc_mech;
2207c478bd9Sstevel@tonic-gate 	new_cred->rfc_mech = cred->rfc_mech;
2217c478bd9Sstevel@tonic-gate 	new_cred->tgt_expire = cred->tgt_expire;
2227c478bd9Sstevel@tonic-gate 
223ab9b2e15Sgtb 	if (cred->princ)
224ab9b2e15Sgtb 	    code = krb5_copy_principal(context, cred->princ, &new_cred->princ);
225ab9b2e15Sgtb 	if (code) {
226ab9b2e15Sgtb 	    xfree(new_cred);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	    *minor_status = code;
2295e01956fSGlenn Barry 	    save_error_info(*minor_status, context);
230ab9b2e15Sgtb 	    krb5_free_context(context);
231ab9b2e15Sgtb 	    return(GSS_S_FAILURE);
2327c478bd9Sstevel@tonic-gate 	}
233*55fea89dSDan Cross 
2347c478bd9Sstevel@tonic-gate 	if (cred->keytab) {
2357c478bd9Sstevel@tonic-gate 	    kttype = krb5_kt_get_type(context, cred->keytab);
2367c478bd9Sstevel@tonic-gate 	    if ((strlen(kttype)+2) > sizeof(ktboth)) {
237ab9b2e15Sgtb 		if (new_cred->princ)
238ab9b2e15Sgtb 		    krb5_free_principal(context, new_cred->princ);
239ab9b2e15Sgtb 		xfree(new_cred);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 		*minor_status = ENOMEM;
242ab9b2e15Sgtb 		krb5_free_context(context);
243ab9b2e15Sgtb 		return(GSS_S_FAILURE);
2447c478bd9Sstevel@tonic-gate 	    }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	    strncpy(ktboth, kttype, sizeof(ktboth) - 1);
2477c478bd9Sstevel@tonic-gate 	    ktboth[sizeof(ktboth) - 1] = '\0';
2487c478bd9Sstevel@tonic-gate 	    strncat(ktboth, ":", sizeof(ktboth) - 1 - strlen(ktboth));
2497c478bd9Sstevel@tonic-gate 
250*55fea89dSDan Cross 	    code = krb5_kt_get_name(context, cred->keytab,
251ab9b2e15Sgtb 				    ktboth+strlen(ktboth),
252ab9b2e15Sgtb 				    sizeof(ktboth)-strlen(ktboth));
2537c478bd9Sstevel@tonic-gate 	    if (code) {
254ab9b2e15Sgtb 		if(new_cred->princ)
255ab9b2e15Sgtb 		    krb5_free_principal(context, new_cred->princ);
256ab9b2e15Sgtb 		xfree(new_cred);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 		*minor_status = code;
2595e01956fSGlenn Barry 		save_error_info(*minor_status, context);
260ab9b2e15Sgtb 		krb5_free_context(context);
261ab9b2e15Sgtb 		return(GSS_S_FAILURE);
2627c478bd9Sstevel@tonic-gate 	    }
2637c478bd9Sstevel@tonic-gate 
264ab9b2e15Sgtb 	    code = krb5_kt_resolve(context, ktboth, &new_cred->keytab);
265ab9b2e15Sgtb 	    if (code) {
266ab9b2e15Sgtb 		if (new_cred->princ)
2677c478bd9Sstevel@tonic-gate 		krb5_free_principal(context, new_cred->princ);
268ab9b2e15Sgtb 		xfree(new_cred);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		*minor_status = code;
2715e01956fSGlenn Barry 		save_error_info(*minor_status, context);
272ab9b2e15Sgtb 		krb5_free_context(context);
273ab9b2e15Sgtb 		return(GSS_S_FAILURE);
2747c478bd9Sstevel@tonic-gate 	    }
2757c478bd9Sstevel@tonic-gate 	} else {
2767c478bd9Sstevel@tonic-gate 	    new_cred->keytab = NULL;
2777c478bd9Sstevel@tonic-gate 	}
278*55fea89dSDan Cross 
2797c478bd9Sstevel@tonic-gate 	if (cred->rcache) {
2807c478bd9Sstevel@tonic-gate 	    /* Open the replay cache for this principal. */
2817c478bd9Sstevel@tonic-gate 	    if ((code = krb5_get_server_rcache(context,
2827c478bd9Sstevel@tonic-gate 					       krb5_princ_component(context, cred->princ, 0),
2837c478bd9Sstevel@tonic-gate 					       &new_cred->rcache))) {
2847c478bd9Sstevel@tonic-gate 		if (new_cred->keytab)
2857c478bd9Sstevel@tonic-gate 		    krb5_kt_close(context, new_cred->keytab);
286ab9b2e15Sgtb 		if (new_cred->princ)
287ab9b2e15Sgtb 		    krb5_free_principal(context, new_cred->princ);
288ab9b2e15Sgtb 		xfree(new_cred);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 		*minor_status = code;
2915e01956fSGlenn Barry 		save_error_info(*minor_status, context);
2925e01956fSGlenn Barry 		krb5_free_context(context);
293ab9b2e15Sgtb 		return(GSS_S_FAILURE);
2947c478bd9Sstevel@tonic-gate 	    }
2957c478bd9Sstevel@tonic-gate 	} else {
2967c478bd9Sstevel@tonic-gate 	    new_cred->rcache = NULL;
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (cred->ccache) {
3007c478bd9Sstevel@tonic-gate 	    cctype = krb5_cc_get_type(context, cred->ccache);
3017c478bd9Sstevel@tonic-gate 	    ccname = krb5_cc_get_name(context, cred->ccache);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	    if ((strlen(cctype)+strlen(ccname)+2) > sizeof(ccboth)) {
3047c478bd9Sstevel@tonic-gate 		if (new_cred->rcache)
3057c478bd9Sstevel@tonic-gate 		    krb5_rc_close(context, new_cred->rcache);
3067c478bd9Sstevel@tonic-gate 		if (new_cred->keytab)
3077c478bd9Sstevel@tonic-gate 		    krb5_kt_close(context, new_cred->keytab);
308ab9b2e15Sgtb 		if (new_cred->princ)
3097c478bd9Sstevel@tonic-gate 		krb5_free_principal(context, new_cred->princ);
310ab9b2e15Sgtb 		xfree(new_cred);
3117c478bd9Sstevel@tonic-gate 
312ab9b2e15Sgtb 		krb5_free_context(context);
3137c478bd9Sstevel@tonic-gate 		*minor_status = ENOMEM;
314ab9b2e15Sgtb 		return(GSS_S_FAILURE);
3157c478bd9Sstevel@tonic-gate 	    }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	    strncpy(ccboth, cctype, sizeof(ccboth) - 1);
3187c478bd9Sstevel@tonic-gate 	    ccboth[sizeof(ccboth) - 1] = '\0';
3197c478bd9Sstevel@tonic-gate 	    strncat(ccboth, ":", sizeof(ccboth) - 1 - strlen(ccboth));
3207c478bd9Sstevel@tonic-gate 	    strncat(ccboth, ccname, sizeof(ccboth) - 1 - strlen(ccboth));
3217c478bd9Sstevel@tonic-gate 
322ab9b2e15Sgtb 	    code = krb5_cc_resolve(context, ccboth, &new_cred->ccache);
323ab9b2e15Sgtb 	    if (code) {
3247c478bd9Sstevel@tonic-gate 		if (new_cred->rcache)
3257c478bd9Sstevel@tonic-gate 		    krb5_rc_close(context, new_cred->rcache);
3267c478bd9Sstevel@tonic-gate 		if (new_cred->keytab)
3277c478bd9Sstevel@tonic-gate 		    krb5_kt_close(context, new_cred->keytab);
328ab9b2e15Sgtb 		if (new_cred->princ)
329ab9b2e15Sgtb 		    krb5_free_principal(context, new_cred->princ);
330ab9b2e15Sgtb 		xfree(new_cred);
3317c478bd9Sstevel@tonic-gate 		*minor_status = code;
3325e01956fSGlenn Barry 		save_error_info(*minor_status, context);
3335e01956fSGlenn Barry 		krb5_free_context(context);
334ab9b2e15Sgtb 		return(GSS_S_FAILURE);
3357c478bd9Sstevel@tonic-gate 	    }
3367c478bd9Sstevel@tonic-gate 	} else {
3377c478bd9Sstevel@tonic-gate 	    new_cred->ccache = NULL;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	/* intern the credential handle */
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	if (! kg_save_cred_id((gss_cred_id_t) new_cred)) {
3437c478bd9Sstevel@tonic-gate 	    if (new_cred->ccache)
3447c478bd9Sstevel@tonic-gate 		krb5_cc_close(context, new_cred->ccache);
3457c478bd9Sstevel@tonic-gate 	    if (new_cred->rcache)
3467c478bd9Sstevel@tonic-gate 		krb5_rc_close(context, new_cred->rcache);
3477c478bd9Sstevel@tonic-gate 	    if (new_cred->keytab)
3487c478bd9Sstevel@tonic-gate 		krb5_kt_close(context, new_cred->keytab);
349ab9b2e15Sgtb 	    if (new_cred->princ)
3507c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, new_cred->princ);
351ab9b2e15Sgtb 	    xfree(new_cred);
352ab9b2e15Sgtb 	    krb5_free_context(context);
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	    *minor_status = (OM_uint32) G_VALIDATE_FAILED;
355ab9b2e15Sgtb 	    return(GSS_S_FAILURE);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	/* modify new_cred */
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	cred = new_cred;
3617c478bd9Sstevel@tonic-gate     }
362*55fea89dSDan Cross 
3637c478bd9Sstevel@tonic-gate     /* set the flag for the new mechanism */
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate     if (g_OID_equal(desired_mech, gss_mech_krb5_old))
3667c478bd9Sstevel@tonic-gate 	cred->prerfc_mech = 1;
3677c478bd9Sstevel@tonic-gate     else if (g_OID_equal(desired_mech, gss_mech_krb5))
3687c478bd9Sstevel@tonic-gate 	cred->rfc_mech = 1;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate     /* set the outputs */
3717c478bd9Sstevel@tonic-gate 
372*55fea89dSDan Cross     if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status,
373159d09a2SMark Phalan 						       (gss_cred_id_t)cred,
374ab9b2e15Sgtb 						       NULL, &lifetime,
375ab9b2e15Sgtb 						       NULL, actual_mechs))) {
3767c478bd9Sstevel@tonic-gate 	OM_uint32 dummy;
377*55fea89dSDan Cross 
3787c478bd9Sstevel@tonic-gate 	if (output_cred_handle)
379ab9b2e15Sgtb 	    (void) krb5_gss_release_cred(&dummy, (gss_cred_id_t *) &cred);
380ab9b2e15Sgtb 	krb5_free_context(context);
3817c478bd9Sstevel@tonic-gate 
382ab9b2e15Sgtb 	return(major_status);
3837c478bd9Sstevel@tonic-gate     }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate     if (initiator_time_rec)
3867c478bd9Sstevel@tonic-gate 	*initiator_time_rec = lifetime;
3877c478bd9Sstevel@tonic-gate     if (acceptor_time_rec)
3887c478bd9Sstevel@tonic-gate 	*acceptor_time_rec = lifetime;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate     if (output_cred_handle)
391159d09a2SMark Phalan 	*output_cred_handle = (gss_cred_id_t)cred;
3927c478bd9Sstevel@tonic-gate 
393ab9b2e15Sgtb     krb5_free_context(context);
3947c478bd9Sstevel@tonic-gate     *minor_status = 0;
395ab9b2e15Sgtb     return(GSS_S_COMPLETE);
3967c478bd9Sstevel@tonic-gate }
397