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  * lib/krb5/krb/get_in_tkt.c
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Copyright 1995 by the Massachusetts Institute of Technology.
87c478bd9Sstevel@tonic-gate  * All Rights Reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
117c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
127c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
137c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
14*55fea89dSDan Cross  *
157c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
167c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
177c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
187c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
197c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
207c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
217c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
227c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
237c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
247c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
257c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
267c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
277c478bd9Sstevel@tonic-gate  * or implied warranty.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
30159d09a2SMark Phalan #include "k5-int.h"
31159d09a2SMark Phalan #ifdef HAVE_MEMORY_H
327c478bd9Sstevel@tonic-gate #include <memory.h>
33159d09a2SMark Phalan #endif
345e01956fSGlenn Barry #include <locale.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /* helper function: convert flags to necessary KDC options */
377c478bd9Sstevel@tonic-gate #define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* Get a TGT for use at the remote host */
40505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context,krb5_auth_context auth_context,char * rhost,krb5_principal client,krb5_principal server,krb5_ccache cc,int forwardable,krb5_data * outbuf)41159d09a2SMark Phalan krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
42*55fea89dSDan Cross 
43*55fea89dSDan Cross 
44*55fea89dSDan Cross 
45*55fea89dSDan Cross 
46*55fea89dSDan Cross 
47*55fea89dSDan Cross 
48159d09a2SMark Phalan                           /* Should forwarded TGT also be forwardable? */
49*55fea89dSDan Cross 
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate     krb5_replay_data replaydata;
527c478bd9Sstevel@tonic-gate     krb5_data * scratch = 0;
53159d09a2SMark Phalan     krb5_address **addrs = NULL;
547c478bd9Sstevel@tonic-gate     krb5_error_code retval;
557c478bd9Sstevel@tonic-gate     krb5_creds creds, tgt;
56159d09a2SMark Phalan     krb5_creds *pcreds;
577c478bd9Sstevel@tonic-gate     krb5_flags kdcoptions;
587c478bd9Sstevel@tonic-gate     int close_cc = 0;
597c478bd9Sstevel@tonic-gate     int free_rhost = 0;
607c478bd9Sstevel@tonic-gate     krb5_enctype enctype = 0;
617c478bd9Sstevel@tonic-gate     krb5_keyblock *session_key;
627c478bd9Sstevel@tonic-gate     krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate     memset((char *)&creds, 0, sizeof(creds));
657c478bd9Sstevel@tonic-gate     memset((char *)&tgt, 0, sizeof(creds));
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     if (cc == 0) {
68159d09a2SMark Phalan       if ((retval = krb5int_cc_default(context, &cc)))
697c478bd9Sstevel@tonic-gate 	goto errout;
70159d09a2SMark Phalan       close_cc = 1;
717c478bd9Sstevel@tonic-gate     }
727c478bd9Sstevel@tonic-gate     retval = krb5_auth_con_getkey (context, auth_context, &session_key);
737c478bd9Sstevel@tonic-gate     if (retval)
74159d09a2SMark Phalan       goto errout;
757c478bd9Sstevel@tonic-gate     if (session_key) {
767c478bd9Sstevel@tonic-gate 	enctype = session_key->enctype;
777c478bd9Sstevel@tonic-gate 	krb5_free_keyblock (context, session_key);
787c478bd9Sstevel@tonic-gate 	session_key = NULL;
797c478bd9Sstevel@tonic-gate     } else if (server) { /* must server be non-NULL when rhost is given? */
807c478bd9Sstevel@tonic-gate 	/* Try getting credentials to see what the remote side supports.
817c478bd9Sstevel@tonic-gate 	   Not bulletproof, just a heuristic.  */
827c478bd9Sstevel@tonic-gate 	krb5_creds in, *out = 0;
837c478bd9Sstevel@tonic-gate 	memset (&in, 0, sizeof(in));
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	retval = krb5_copy_principal (context, server, &in.server);
867c478bd9Sstevel@tonic-gate 	if (retval)
87159d09a2SMark Phalan 	    goto punt;
887c478bd9Sstevel@tonic-gate 	retval = krb5_copy_principal (context, client, &in.client);
897c478bd9Sstevel@tonic-gate 	if (retval)
90159d09a2SMark Phalan 	    goto punt;
917c478bd9Sstevel@tonic-gate 	retval = krb5_get_credentials (context, 0, cc, &in, &out);
927c478bd9Sstevel@tonic-gate 	if (retval)
93159d09a2SMark Phalan 	    goto punt;
94159d09a2SMark Phalan 	/* Got the credentials.  Okay, now record the enctype and
957c478bd9Sstevel@tonic-gate 	   throw them away.  */
967c478bd9Sstevel@tonic-gate 	enctype = out->keyblock.enctype;
977c478bd9Sstevel@tonic-gate 	krb5_free_creds (context, out);
987c478bd9Sstevel@tonic-gate     punt:
99159d09a2SMark Phalan 	krb5_free_cred_contents (context, &in);
1007c478bd9Sstevel@tonic-gate     }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate     if ((retval = krb5_copy_principal(context, client, &creds.client)))
1037c478bd9Sstevel@tonic-gate 	goto errout;
104*55fea89dSDan Cross 
1057c478bd9Sstevel@tonic-gate     if ((retval = krb5_build_principal_ext(context, &creds.server,
1067c478bd9Sstevel@tonic-gate 					   client->realm.length,
1077c478bd9Sstevel@tonic-gate 					   client->realm.data,
1087c478bd9Sstevel@tonic-gate 					   KRB5_TGS_NAME_SIZE,
1097c478bd9Sstevel@tonic-gate 					   KRB5_TGS_NAME,
1107c478bd9Sstevel@tonic-gate 					   client->realm.length,
1117c478bd9Sstevel@tonic-gate 					   client->realm.data,
1127c478bd9Sstevel@tonic-gate 					   0)))
1137c478bd9Sstevel@tonic-gate 	goto errout;
114*55fea89dSDan Cross 
1157c478bd9Sstevel@tonic-gate     /* fetch tgt directly from cache */
1167c478bd9Sstevel@tonic-gate     context->use_conf_ktypes = 1;
1177c478bd9Sstevel@tonic-gate     retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
1187c478bd9Sstevel@tonic-gate 				    &creds, &tgt);
1197c478bd9Sstevel@tonic-gate     context->use_conf_ktypes = old_use_conf_ktypes;
1207c478bd9Sstevel@tonic-gate     if (retval)
1217c478bd9Sstevel@tonic-gate 	goto errout;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate     /* tgt->client must be equal to creds.client */
124*55fea89dSDan Cross     if (!krb5_principal_compare(context, tgt.client, creds.client)) {
1255e01956fSGlenn Barry         /* Solaris Kerberos */
1265e01956fSGlenn Barry         char *r_name = NULL;
1275e01956fSGlenn Barry 	char *t_name = NULL;
1285e01956fSGlenn Barry 	krb5_error_code r_err, t_err;
1295e01956fSGlenn Barry 	t_err = krb5_unparse_name(context, tgt.client, &t_name);
1305e01956fSGlenn Barry 	r_err = krb5_unparse_name(context, creds.client, &r_name);
1315e01956fSGlenn Barry 	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
1325e01956fSGlenn Barry 			    dgettext(TEXT_DOMAIN,
1335e01956fSGlenn Barry 				    "Requested principal and ticket don't match:  Requested principal is '%s' and TGT principal is '%s'"),
1345e01956fSGlenn Barry 			    r_err ? "unknown" : r_name,
1355e01956fSGlenn Barry 			    t_err ? "unknown" : t_name);
1365e01956fSGlenn Barry 	if (r_name)
1375e01956fSGlenn Barry 	    krb5_free_unparsed_name(context, r_name);
1385e01956fSGlenn Barry 	if (t_name)
1395e01956fSGlenn Barry 	    krb5_free_unparsed_name(context, t_name);
1407c478bd9Sstevel@tonic-gate 	retval = KRB5_PRINC_NOMATCH;
1417c478bd9Sstevel@tonic-gate 	goto errout;
1427c478bd9Sstevel@tonic-gate     }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate     if (!tgt.ticket.length) {
1457c478bd9Sstevel@tonic-gate 	retval = KRB5_NO_TKT_SUPPLIED;
1467c478bd9Sstevel@tonic-gate 	goto errout;
1477c478bd9Sstevel@tonic-gate     }
148*55fea89dSDan Cross 
1497c478bd9Sstevel@tonic-gate     if (tgt.addresses && *tgt.addresses) {
150159d09a2SMark Phalan       if (rhost == NULL) {
151159d09a2SMark Phalan 	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
152159d09a2SMark Phalan retval = KRB5_FWD_BAD_PRINCIPAL;
153159d09a2SMark Phalan  goto errout;
154159d09a2SMark Phalan 	}
1557c478bd9Sstevel@tonic-gate 
156159d09a2SMark Phalan 	if (krb5_princ_size(context, server) < 2){
157159d09a2SMark Phalan 	  retval = KRB5_CC_BADNAME;
158159d09a2SMark Phalan 	  goto errout;
159159d09a2SMark Phalan 	}
160*55fea89dSDan Cross 
161159d09a2SMark Phalan 	rhost = malloc(server->data[1].length+1);
162159d09a2SMark Phalan 	if (!rhost) {
163159d09a2SMark Phalan 	  retval = ENOMEM;
164159d09a2SMark Phalan 	  goto errout;
1657c478bd9Sstevel@tonic-gate 	}
166159d09a2SMark Phalan 	free_rhost = 1;
167159d09a2SMark Phalan 	/* Solaris Kerberos */
168159d09a2SMark Phalan 	(void) memcpy(rhost, server->data[1].data, server->data[1].length);
169159d09a2SMark Phalan 	rhost[server->data[1].length] = '\0';
170159d09a2SMark Phalan       }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	retval = krb5_os_hostaddr(context, rhost, &addrs);
1737c478bd9Sstevel@tonic-gate 	if (retval)
1747c478bd9Sstevel@tonic-gate 	    goto errout;
1757c478bd9Sstevel@tonic-gate     }
176*55fea89dSDan Cross 
1777c478bd9Sstevel@tonic-gate     creds.keyblock.enctype = enctype;
1787c478bd9Sstevel@tonic-gate     creds.times = tgt.times;
1797c478bd9Sstevel@tonic-gate     creds.times.starttime = 0;
1807c478bd9Sstevel@tonic-gate     kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate     if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
1837c478bd9Sstevel@tonic-gate       kdcoptions &= ~(KDC_OPT_FORWARDABLE);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate     if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
1867c478bd9Sstevel@tonic-gate 					addrs, &creds, &pcreds))) {
1877c478bd9Sstevel@tonic-gate 	if (enctype) {
1887c478bd9Sstevel@tonic-gate 	    creds.keyblock.enctype = 0;
1897c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
190*55fea89dSDan Cross 						addrs, &creds, &pcreds)))
1917c478bd9Sstevel@tonic-gate 		goto errout;
192159d09a2SMark Phalan 	}
193159d09a2SMark Phalan 	else goto errout;
1947c478bd9Sstevel@tonic-gate     }
1957c478bd9Sstevel@tonic-gate     retval = krb5_mk_1cred(context, auth_context, pcreds,
1967c478bd9Sstevel@tonic-gate                            &scratch, &replaydata);
1977c478bd9Sstevel@tonic-gate     krb5_free_creds(context, pcreds);
1987c478bd9Sstevel@tonic-gate 
199159d09a2SMark Phalan     /*
200159d09a2SMark Phalan      * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be
2017c478bd9Sstevel@tonic-gate      * more robust.
2027c478bd9Sstevel@tonic-gate      */
2037c478bd9Sstevel@tonic-gate     if (scratch) {
2047c478bd9Sstevel@tonic-gate 	if (retval)
2057c478bd9Sstevel@tonic-gate 	    krb5_free_data(context, scratch);
206*55fea89dSDan Cross 	else {
2077c478bd9Sstevel@tonic-gate 	    *outbuf = *scratch;
2087c478bd9Sstevel@tonic-gate 	    krb5_xfree(scratch);
209*55fea89dSDan Cross 	}
2107c478bd9Sstevel@tonic-gate     }
211*55fea89dSDan Cross 
2127c478bd9Sstevel@tonic-gate errout:
2137c478bd9Sstevel@tonic-gate     if (addrs)
2147c478bd9Sstevel@tonic-gate 	krb5_free_addresses(context, addrs);
215159d09a2SMark Phalan     /* Solaris Kerberos */
2167c478bd9Sstevel@tonic-gate     if (close_cc)
2177c478bd9Sstevel@tonic-gate 	(void) krb5_cc_close(context, cc);
2187c478bd9Sstevel@tonic-gate     if (free_rhost)
2197c478bd9Sstevel@tonic-gate 	free(rhost);
2207c478bd9Sstevel@tonic-gate     krb5_free_cred_contents(context, &creds);
2217c478bd9Sstevel@tonic-gate     krb5_free_cred_contents(context, &tgt);
2227c478bd9Sstevel@tonic-gate     return retval;
2237c478bd9Sstevel@tonic-gate }
224