17c478bd9Sstevel@tonic-gate /* 2*5e01956fSGlenn 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. 147c478bd9Sstevel@tonic-gate * 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 34*5e01956fSGlenn 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 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) 42159d09a2SMark Phalan 43159d09a2SMark Phalan 44159d09a2SMark Phalan 45159d09a2SMark Phalan 46159d09a2SMark Phalan 47159d09a2SMark Phalan 48159d09a2SMark Phalan /* Should forwarded TGT also be forwardable? */ 49159d09a2SMark Phalan 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) { 687c478bd9Sstevel@tonic-gate if ((retval = krb5int_cc_default(context, &cc))) 697c478bd9Sstevel@tonic-gate goto errout; 707c478bd9Sstevel@tonic-gate close_cc = 1; 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate retval = krb5_auth_con_getkey (context, auth_context, &session_key); 737c478bd9Sstevel@tonic-gate if (retval) 747c478bd9Sstevel@tonic-gate 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) 877c478bd9Sstevel@tonic-gate goto punt; 887c478bd9Sstevel@tonic-gate retval = krb5_copy_principal (context, client, &in.client); 897c478bd9Sstevel@tonic-gate if (retval) 907c478bd9Sstevel@tonic-gate goto punt; 917c478bd9Sstevel@tonic-gate retval = krb5_get_credentials (context, 0, cc, &in, &out); 927c478bd9Sstevel@tonic-gate if (retval) 937c478bd9Sstevel@tonic-gate goto punt; 947c478bd9Sstevel@tonic-gate /* 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: 997c478bd9Sstevel@tonic-gate 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; 1047c478bd9Sstevel@tonic-gate 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; 1147c478bd9Sstevel@tonic-gate 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 */ 1247c478bd9Sstevel@tonic-gate if (!krb5_principal_compare(context, tgt.client, creds.client)) { 125*5e01956fSGlenn Barry /* Solaris Kerberos */ 126*5e01956fSGlenn Barry char *r_name = NULL; 127*5e01956fSGlenn Barry char *t_name = NULL; 128*5e01956fSGlenn Barry krb5_error_code r_err, t_err; 129*5e01956fSGlenn Barry t_err = krb5_unparse_name(context, tgt.client, &t_name); 130*5e01956fSGlenn Barry r_err = krb5_unparse_name(context, creds.client, &r_name); 131*5e01956fSGlenn Barry krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 132*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN, 133*5e01956fSGlenn Barry "Requested principal and ticket don't match: Requested principal is '%s' and TGT principal is '%s'"), 134*5e01956fSGlenn Barry r_err ? "unknown" : r_name, 135*5e01956fSGlenn Barry t_err ? "unknown" : t_name); 136*5e01956fSGlenn Barry if (r_name) 137*5e01956fSGlenn Barry krb5_free_unparsed_name(context, r_name); 138*5e01956fSGlenn Barry if (t_name) 139*5e01956fSGlenn 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 } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if (tgt.addresses && *tgt.addresses) { 1507c478bd9Sstevel@tonic-gate if (rhost == NULL) { 1517c478bd9Sstevel@tonic-gate if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) { 1527c478bd9Sstevel@tonic-gate retval = KRB5_FWD_BAD_PRINCIPAL; 1537c478bd9Sstevel@tonic-gate goto errout; 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (krb5_princ_size(context, server) < 2){ 1577c478bd9Sstevel@tonic-gate retval = KRB5_CC_BADNAME; 1587c478bd9Sstevel@tonic-gate goto errout; 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate rhost = malloc(server->data[1].length+1); 1627c478bd9Sstevel@tonic-gate if (!rhost) { 1637c478bd9Sstevel@tonic-gate retval = ENOMEM; 1647c478bd9Sstevel@tonic-gate goto errout; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate free_rhost = 1; 167159d09a2SMark Phalan /* Solaris Kerberos */ 1687c478bd9Sstevel@tonic-gate (void) memcpy(rhost, server->data[1].data, server->data[1].length); 1697c478bd9Sstevel@tonic-gate rhost[server->data[1].length] = '\0'; 1707c478bd9Sstevel@tonic-gate } 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 } 1767c478bd9Sstevel@tonic-gate 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, 1907c478bd9Sstevel@tonic-gate addrs, &creds, &pcreds))) 1917c478bd9Sstevel@tonic-gate goto errout; 1927c478bd9Sstevel@tonic-gate } 193159d09a2SMark Phalan else goto errout; 194159d09a2SMark Phalan } 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); 2067c478bd9Sstevel@tonic-gate else { 2077c478bd9Sstevel@tonic-gate *outbuf = *scratch; 2087c478bd9Sstevel@tonic-gate krb5_xfree(scratch); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 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