17c478bd9Sstevel@tonic-gate /*
2d71c749dSMark Phalan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * lib/krb5/krb/get_creds.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 1990 by the Massachusetts Institute of Technology.
117c478bd9Sstevel@tonic-gate  * All Rights Reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*55fea89dSDan Cross  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
31*55fea89dSDan Cross  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * krb5_get_credentials()
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  Attempts to use the credentials cache or TGS exchange to get an additional
407c478bd9Sstevel@tonic-gate  ticket for the
417c478bd9Sstevel@tonic-gate  client identified by in_creds->client, the server identified by
427c478bd9Sstevel@tonic-gate  in_creds->server, with options options, expiration date specified in
437c478bd9Sstevel@tonic-gate  in_creds->times.endtime (0 means as long as possible), session key type
447c478bd9Sstevel@tonic-gate  specified in in_creds->keyblock.enctype (if non-zero)
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate  Any returned ticket and intermediate ticket-granting tickets are
477c478bd9Sstevel@tonic-gate  stored in ccache.
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate  returns errors from encryption routines, system errors
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
52159d09a2SMark Phalan #include "k5-int.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
557c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_get_credentials_core(krb5_context context,krb5_flags options,krb5_creds * in_creds,krb5_creds * mcreds,krb5_flags * fields)56505d05c7Sgtb krb5_get_credentials_core(krb5_context context, krb5_flags options,
57505d05c7Sgtb 			  krb5_creds *in_creds, krb5_creds *mcreds,
58505d05c7Sgtb 			  krb5_flags *fields)
597c478bd9Sstevel@tonic-gate {
60159d09a2SMark Phalan     /* Solaris Kerberos */
617c478bd9Sstevel@tonic-gate     krb5_error_code ret = 0;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate     if (!in_creds || !in_creds->server || !in_creds->client)
647c478bd9Sstevel@tonic-gate         return EINVAL;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate     memset((char *)mcreds, 0, sizeof(krb5_creds));
677c478bd9Sstevel@tonic-gate     mcreds->magic = KV5M_CREDS;
687c478bd9Sstevel@tonic-gate     /*
69159d09a2SMark Phalan      * Solaris Kerberos:
707c478bd9Sstevel@tonic-gate      * Set endtime appropriately to make sure we do not rope in
717c478bd9Sstevel@tonic-gate      * expired creds. If endtime is set to 0 (which it almost always
727c478bd9Sstevel@tonic-gate      * is, courtesy memset/calloc) the krb5_cc_retrieve_cred() call in
737c478bd9Sstevel@tonic-gate      * krb5_get_credentials() with KRB5_TC_MATCH_TIMES will
747c478bd9Sstevel@tonic-gate      * succeed and return the expired cred.
757c478bd9Sstevel@tonic-gate      *
767c478bd9Sstevel@tonic-gate      * Hence, endtime below is set to "now" if in_creds->times.endtime
777c478bd9Sstevel@tonic-gate      * is 0, so that krb5_cc_retrieve_cred fails and we get fresh creds,
787c478bd9Sstevel@tonic-gate      * if necessary. But, if in_creds has a non-zero endtime, we honor it.
797c478bd9Sstevel@tonic-gate      */
807c478bd9Sstevel@tonic-gate     if (in_creds->times.endtime != 0)
817c478bd9Sstevel@tonic-gate 	mcreds->times.endtime = in_creds->times.endtime;
827c478bd9Sstevel@tonic-gate     else
837c478bd9Sstevel@tonic-gate 	if ((ret = krb5_timeofday(context, &mcreds->times.endtime)) != 0)
847c478bd9Sstevel@tonic-gate 		return (ret);
857c478bd9Sstevel@tonic-gate 
86d71c749dSMark Phalan     ret = krb5_copy_keyblock_contents(context, &in_creds->keyblock,
877c478bd9Sstevel@tonic-gate 		&mcreds->keyblock);
887c478bd9Sstevel@tonic-gate     if (ret)
897c478bd9Sstevel@tonic-gate 	return (ret);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate     mcreds->authdata = in_creds->authdata;
927c478bd9Sstevel@tonic-gate     mcreds->server = in_creds->server;
937c478bd9Sstevel@tonic-gate     mcreds->client = in_creds->client;
94*55fea89dSDan Cross 
957c478bd9Sstevel@tonic-gate     *fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */
967c478bd9Sstevel@tonic-gate 	| KRB5_TC_MATCH_AUTHDATA
977c478bd9Sstevel@tonic-gate 	| KRB5_TC_SUPPORTED_KTYPES;
987c478bd9Sstevel@tonic-gate     if (mcreds->keyblock.enctype) {
997c478bd9Sstevel@tonic-gate 	krb5_enctype *ktypes;
1007c478bd9Sstevel@tonic-gate 	int i;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	*fields |= KRB5_TC_MATCH_KTYPE;
1037c478bd9Sstevel@tonic-gate 	ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
1047c478bd9Sstevel@tonic-gate 	for (i = 0; ktypes[i]; i++)
105159d09a2SMark Phalan 	    if (ktypes[i] == mcreds->keyblock.enctype)
1067c478bd9Sstevel@tonic-gate 		break;
1077c478bd9Sstevel@tonic-gate 	if (ktypes[i] == 0)
108159d09a2SMark Phalan 	    ret = KRB5_CC_NOT_KTYPE;
1097c478bd9Sstevel@tonic-gate 	free (ktypes);
110d71c749dSMark Phalan 	if (ret) {
111d71c749dSMark Phalan 	    krb5_free_keyblock_contents(context, &mcreds->keyblock);
112159d09a2SMark Phalan 	    return ret;
113d71c749dSMark Phalan 	}
1147c478bd9Sstevel@tonic-gate     }
1157c478bd9Sstevel@tonic-gate     if (options & KRB5_GC_USER_USER) {
1167c478bd9Sstevel@tonic-gate 	/* also match on identical 2nd tkt and tkt encrypted in a
1177c478bd9Sstevel@tonic-gate 	   session key */
1187c478bd9Sstevel@tonic-gate 	*fields |= KRB5_TC_MATCH_2ND_TKT|KRB5_TC_MATCH_IS_SKEY;
1197c478bd9Sstevel@tonic-gate 	mcreds->is_skey = TRUE;
1207c478bd9Sstevel@tonic-gate 	mcreds->second_ticket = in_creds->second_ticket;
121d71c749dSMark Phalan 	if (!in_creds->second_ticket.length) {
122d71c749dSMark Phalan 	    krb5_free_keyblock_contents(context, &mcreds->keyblock);
1237c478bd9Sstevel@tonic-gate 	    return KRB5_NO_2ND_TKT;
124d71c749dSMark Phalan 	}
1257c478bd9Sstevel@tonic-gate     }
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate     return 0;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
130505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_credentials(krb5_context context,krb5_flags options,krb5_ccache ccache,krb5_creds * in_creds,krb5_creds ** out_creds)131505d05c7Sgtb krb5_get_credentials(krb5_context context, krb5_flags options,
132505d05c7Sgtb 		     krb5_ccache ccache, krb5_creds *in_creds,
133505d05c7Sgtb 		     krb5_creds **out_creds)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1367c478bd9Sstevel@tonic-gate     krb5_creds mcreds;
1377c478bd9Sstevel@tonic-gate     krb5_creds *ncreds;
1387c478bd9Sstevel@tonic-gate     krb5_creds **tgts;
1397c478bd9Sstevel@tonic-gate     krb5_flags fields;
1407c478bd9Sstevel@tonic-gate     int not_ktype;
1417c478bd9Sstevel@tonic-gate 
142505d05c7Sgtb     retval = krb5_get_credentials_core(context, options,
143505d05c7Sgtb 				       in_creds,
1447c478bd9Sstevel@tonic-gate 				       &mcreds, &fields);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate     if (retval) return retval;
1477c478bd9Sstevel@tonic-gate 
148d71c749dSMark Phalan     if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
149d71c749dSMark Phalan 	krb5_free_keyblock_contents(context, &mcreds.keyblock);
1507c478bd9Sstevel@tonic-gate 	return ENOMEM;
151d71c749dSMark Phalan     }
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate     memset((char *)ncreds, 0, sizeof(krb5_creds));
1547c478bd9Sstevel@tonic-gate     ncreds->magic = KV5M_CREDS;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate     /* The caller is now responsible for cleaning up in_creds */
157159d09a2SMark Phalan     /* Solaris Kerberos */
1587c478bd9Sstevel@tonic-gate     if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
1597c478bd9Sstevel@tonic-gate 					ncreds)) !=0) {
1607c478bd9Sstevel@tonic-gate 	krb5_xfree(ncreds);
1617c478bd9Sstevel@tonic-gate 	ncreds = in_creds;
1627c478bd9Sstevel@tonic-gate     } else {
1637c478bd9Sstevel@tonic-gate 	*out_creds = ncreds;
1647c478bd9Sstevel@tonic-gate     }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate     if ((retval != KRB5_CC_NOTFOUND && retval != KRB5_CC_NOT_KTYPE)
167d71c749dSMark Phalan 	|| options & KRB5_GC_CACHED) {
168d71c749dSMark Phalan 	krb5_free_keyblock_contents(context, &mcreds.keyblock);
1697c478bd9Sstevel@tonic-gate 	return retval;
170d71c749dSMark Phalan     }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate     if (retval == KRB5_CC_NOT_KTYPE)
1737c478bd9Sstevel@tonic-gate 	not_ktype = 1;
1747c478bd9Sstevel@tonic-gate     else
1757c478bd9Sstevel@tonic-gate 	not_ktype = 0;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate     retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
1787c478bd9Sstevel@tonic-gate     if (tgts) {
1797c478bd9Sstevel@tonic-gate 	register int i = 0;
1807c478bd9Sstevel@tonic-gate 	krb5_error_code rv2;
1817c478bd9Sstevel@tonic-gate 	while (tgts[i]) {
182159d09a2SMark Phalan 	    /* Solaris Kerberos */
1837c478bd9Sstevel@tonic-gate 	    if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i])) != 0) {
1847c478bd9Sstevel@tonic-gate 		retval = rv2;
1857c478bd9Sstevel@tonic-gate 		break;
1867c478bd9Sstevel@tonic-gate 	    }
1877c478bd9Sstevel@tonic-gate 	    i++;
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate 	krb5_free_tgt_creds(context, tgts);
1907c478bd9Sstevel@tonic-gate     }
1917c478bd9Sstevel@tonic-gate     /*
1927c478bd9Sstevel@tonic-gate      * Translate KRB5_CC_NOTFOUND if we previously got
1937c478bd9Sstevel@tonic-gate      * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to
1947c478bd9Sstevel@tonic-gate      * handle the case where there is no TGT in the ccache and the
1957c478bd9Sstevel@tonic-gate      * input enctype didn't match.  This handling is necessary because
1967c478bd9Sstevel@tonic-gate      * some callers, such as GSSAPI, iterate through enctypes and
1977c478bd9Sstevel@tonic-gate      * KRB5_CC_NOTFOUND passed through from the
1987c478bd9Sstevel@tonic-gate      * krb5_get_cred_from_kdc() is semantically incorrect, since the
1997c478bd9Sstevel@tonic-gate      * actual failure was the non-existence of a ticket of the correct
2007c478bd9Sstevel@tonic-gate      * enctype rather than the missing TGT.
2017c478bd9Sstevel@tonic-gate      */
2027c478bd9Sstevel@tonic-gate     if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
2037c478bd9Sstevel@tonic-gate 	&& not_ktype)
2047c478bd9Sstevel@tonic-gate 	retval = KRB5_CC_NOT_KTYPE;
2057c478bd9Sstevel@tonic-gate 
206159d09a2SMark Phalan     if (!retval) {
207*55fea89dSDan Cross         /* the purpose of the krb5_get_credentials call is to
208*55fea89dSDan Cross          * obtain a set of credentials for the caller.  the
209159d09a2SMark Phalan          * krb5_cc_store_cred() call is to optimize performance
210159d09a2SMark Phalan          * for future calls.  Ignore any errors, since the credentials
211159d09a2SMark Phalan          * are still valid even if we fail to store them in the cache.
212159d09a2SMark Phalan          */
213159d09a2SMark Phalan 	/* Solaris Kerberos */
2147c478bd9Sstevel@tonic-gate 	retval = krb5_cc_store_cred(context, ccache, *out_creds);
215159d09a2SMark Phalan     }
216d71c749dSMark Phalan 
217d71c749dSMark Phalan     krb5_free_keyblock_contents(context, &mcreds.keyblock);
2187c478bd9Sstevel@tonic-gate     return retval;
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #define INT_GC_VALIDATE 1
2227c478bd9Sstevel@tonic-gate #define INT_GC_RENEW 2
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
225*55fea89dSDan Cross static krb5_error_code
krb5_get_credentials_val_renew_core(krb5_context context,krb5_flags options,krb5_ccache ccache,krb5_creds * in_creds,krb5_creds ** out_creds,int which)226505d05c7Sgtb krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
227505d05c7Sgtb 				    krb5_ccache ccache, krb5_creds *in_creds,
228505d05c7Sgtb 				    krb5_creds **out_creds, int which)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate     krb5_error_code retval;
2317c478bd9Sstevel@tonic-gate     krb5_principal tmp;
2327c478bd9Sstevel@tonic-gate     krb5_creds **tgts = 0;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate     switch(which) {
2357c478bd9Sstevel@tonic-gate     case INT_GC_VALIDATE:
236*55fea89dSDan Cross 	    retval = krb5_get_cred_from_kdc_validate(context, ccache,
2377c478bd9Sstevel@tonic-gate 					     in_creds, out_creds, &tgts);
2387c478bd9Sstevel@tonic-gate 	    break;
2397c478bd9Sstevel@tonic-gate     case INT_GC_RENEW:
240*55fea89dSDan Cross 	    retval = krb5_get_cred_from_kdc_renew(context, ccache,
2417c478bd9Sstevel@tonic-gate 					     in_creds, out_creds, &tgts);
2427c478bd9Sstevel@tonic-gate 	    break;
2437c478bd9Sstevel@tonic-gate     default:
2447c478bd9Sstevel@tonic-gate 	    /* Should never happen */
2457c478bd9Sstevel@tonic-gate 	    retval = 255;
2467c478bd9Sstevel@tonic-gate 	    break;
2477c478bd9Sstevel@tonic-gate     }
2487c478bd9Sstevel@tonic-gate     if (retval) return retval;
2497c478bd9Sstevel@tonic-gate     if (tgts) krb5_free_tgt_creds(context, tgts);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate     retval = krb5_cc_get_principal(context, ccache, &tmp);
2527c478bd9Sstevel@tonic-gate     if (retval) return retval;
253*55fea89dSDan Cross 
2547c478bd9Sstevel@tonic-gate     retval = krb5_cc_initialize(context, ccache, tmp);
255159d09a2SMark Phalan     /* Solaris Kerberos */
2567c478bd9Sstevel@tonic-gate     if (retval) {
2577c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, tmp);
2587c478bd9Sstevel@tonic-gate 	return retval;
2597c478bd9Sstevel@tonic-gate     }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate     retval = krb5_cc_store_cred(context, ccache, *out_creds);
2627c478bd9Sstevel@tonic-gate     krb5_free_principal(context, tmp);
2637c478bd9Sstevel@tonic-gate     return retval;
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate 
266505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_credentials_validate(krb5_context context,krb5_flags options,krb5_ccache ccache,krb5_creds * in_creds,krb5_creds ** out_creds)267505d05c7Sgtb krb5_get_credentials_validate(krb5_context context, krb5_flags options,
268505d05c7Sgtb 			      krb5_ccache ccache, krb5_creds *in_creds,
269505d05c7Sgtb 			      krb5_creds **out_creds)
2707c478bd9Sstevel@tonic-gate {
271*55fea89dSDan Cross     return(krb5_get_credentials_val_renew_core(context, options, ccache,
272*55fea89dSDan Cross 					       in_creds, out_creds,
2737c478bd9Sstevel@tonic-gate 					       INT_GC_VALIDATE));
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate 
276505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_credentials_renew(krb5_context context,krb5_flags options,krb5_ccache ccache,krb5_creds * in_creds,krb5_creds ** out_creds)277505d05c7Sgtb krb5_get_credentials_renew(krb5_context context, krb5_flags options,
278505d05c7Sgtb 			   krb5_ccache ccache, krb5_creds *in_creds,
279505d05c7Sgtb 			   krb5_creds **out_creds)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 
282*55fea89dSDan Cross     return(krb5_get_credentials_val_renew_core(context, options, ccache,
283*55fea89dSDan Cross 					       in_creds, out_creds,
2847c478bd9Sstevel@tonic-gate 					       INT_GC_RENEW));
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_validate_or_renew_creds(krb5_context context,krb5_creds * creds,krb5_principal client,krb5_ccache ccache,char * in_tkt_service,int validate)288505d05c7Sgtb krb5_validate_or_renew_creds(krb5_context context, krb5_creds *creds,
289505d05c7Sgtb 			     krb5_principal client, krb5_ccache ccache,
290505d05c7Sgtb 			     char *in_tkt_service, int validate)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate     krb5_error_code ret;
2937c478bd9Sstevel@tonic-gate     krb5_creds in_creds; /* only client and server need to be filled in */
2947c478bd9Sstevel@tonic-gate     krb5_creds *out_creds = 0; /* for check before dereferencing below */
2957c478bd9Sstevel@tonic-gate     krb5_creds **tgts;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate     memset((char *)&in_creds, 0, sizeof(krb5_creds));
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate     in_creds.server = NULL;
3007c478bd9Sstevel@tonic-gate     tgts = NULL;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate     in_creds.client = client;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate     if (in_tkt_service) {
3057c478bd9Sstevel@tonic-gate 	/* this is ugly, because so are the data structures involved.  I'm
3067c478bd9Sstevel@tonic-gate 	   in the library, so I'm going to manipulate the data structures
3077c478bd9Sstevel@tonic-gate 	   directly, otherwise, it will be worse. */
3087c478bd9Sstevel@tonic-gate 
309505d05c7Sgtb         if ((ret = krb5_parse_name(context, in_tkt_service, &in_creds.server)))
3107c478bd9Sstevel@tonic-gate 	    goto cleanup;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/* stuff the client realm into the server principal.
3137c478bd9Sstevel@tonic-gate 	   realloc if necessary */
3147c478bd9Sstevel@tonic-gate 	if (in_creds.server->realm.length < in_creds.client->realm.length)
3157c478bd9Sstevel@tonic-gate 	    if ((in_creds.server->realm.data =
3167c478bd9Sstevel@tonic-gate 		 (char *) realloc(in_creds.server->realm.data,
3177c478bd9Sstevel@tonic-gate 				  in_creds.client->realm.length)) == NULL) {
3187c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
3197c478bd9Sstevel@tonic-gate 		goto cleanup;
3207c478bd9Sstevel@tonic-gate 	    }
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	in_creds.server->realm.length = in_creds.client->realm.length;
3237c478bd9Sstevel@tonic-gate 	memcpy(in_creds.server->realm.data, in_creds.client->realm.data,
3247c478bd9Sstevel@tonic-gate 	       in_creds.client->realm.length);
3257c478bd9Sstevel@tonic-gate     } else {
326505d05c7Sgtb 	if ((ret = krb5_build_principal_ext(context, &in_creds.server,
3277c478bd9Sstevel@tonic-gate 					   in_creds.client->realm.length,
3287c478bd9Sstevel@tonic-gate 					   in_creds.client->realm.data,
3297c478bd9Sstevel@tonic-gate 					   KRB5_TGS_NAME_SIZE,
3307c478bd9Sstevel@tonic-gate 					   KRB5_TGS_NAME,
3317c478bd9Sstevel@tonic-gate 					   in_creds.client->realm.length,
3327c478bd9Sstevel@tonic-gate 					   in_creds.client->realm.data,
333505d05c7Sgtb 					    0)))
3347c478bd9Sstevel@tonic-gate 	    goto cleanup;
3357c478bd9Sstevel@tonic-gate     }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate     if (validate)
338*55fea89dSDan Cross 	ret = krb5_get_cred_from_kdc_validate(context, ccache,
3397c478bd9Sstevel@tonic-gate 					      &in_creds, &out_creds, &tgts);
3407c478bd9Sstevel@tonic-gate     else
341*55fea89dSDan Cross 	ret = krb5_get_cred_from_kdc_renew(context, ccache,
3427c478bd9Sstevel@tonic-gate 					   &in_creds, &out_creds, &tgts);
343*55fea89dSDan Cross 
3447c478bd9Sstevel@tonic-gate     /* ick.  copy the struct contents, free the container */
3457c478bd9Sstevel@tonic-gate     if (out_creds) {
3467c478bd9Sstevel@tonic-gate 	*creds = *out_creds;
3477c478bd9Sstevel@tonic-gate 	krb5_xfree(out_creds);
3487c478bd9Sstevel@tonic-gate     }
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate cleanup:
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate     if (in_creds.server)
3537c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, in_creds.server);
3547c478bd9Sstevel@tonic-gate     if (tgts)
3557c478bd9Sstevel@tonic-gate 	krb5_free_tgt_creds(context, tgts);
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate     return(ret);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
360505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_validated_creds(krb5_context context,krb5_creds * creds,krb5_principal client,krb5_ccache ccache,char * in_tkt_service)361505d05c7Sgtb krb5_get_validated_creds(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, char *in_tkt_service)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate     return(krb5_validate_or_renew_creds(context, creds, client, ccache,
3647c478bd9Sstevel@tonic-gate 					in_tkt_service, 1));
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
367505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_get_renewed_creds(krb5_context context,krb5_creds * creds,krb5_principal client,krb5_ccache ccache,char * in_tkt_service)368505d05c7Sgtb krb5_get_renewed_creds(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, char *in_tkt_service)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate     return(krb5_validate_or_renew_creds(context, creds, client, ccache,
3717c478bd9Sstevel@tonic-gate 					in_tkt_service, 0));
3727c478bd9Sstevel@tonic-gate }
373