1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/fwd_tgt.c Definition of krb5_fwd_tgt_creds() routine */
4 * Copyright 1995 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
31 #include "int-proto.h"
33 /* helper function: convert flags to necessary KDC options */
34 #define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
36 /* Get a TGT for use at the remote host */
37 krb5_error_code KRB5_CALLCONV
38 krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
39 char *rhost, krb5_principal client, krb5_principal server,
40 krb5_ccache cc, int forwardable, krb5_data *outbuf)
41 /* Should forwarded TGT also be forwardable? */
43 krb5_replay_data replaydata;
44 krb5_data * scratch = 0;
45 krb5_address **addrs = NULL;
46 krb5_error_code retval;
47 krb5_creds creds, tgt;
49 krb5_flags kdcoptions;
52 krb5_enctype enctype = 0;
53 krb5_keyblock *session_key;
54 krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;
56 memset(&creds, 0, sizeof(creds));
57 memset(&tgt, 0, sizeof(creds));
60 if ((retval = krb5int_cc_default(context, &cc)))
64 retval = krb5_auth_con_getkey (context, auth_context, &session_key);
68 enctype = session_key->enctype;
69 krb5_free_keyblock (context, session_key);
71 } else if (server) { /* must server be non-NULL when rhost is given? */
72 /* Try getting credentials to see what the remote side supports.
73 Not bulletproof, just a heuristic. */
74 krb5_creds in, *out = 0;
75 memset (&in, 0, sizeof(in));
77 retval = krb5_copy_principal (context, server, &in.server);
80 retval = krb5_copy_principal (context, client, &in.client);
83 retval = krb5_get_credentials (context, 0, cc, &in, &out);
86 /* Got the credentials. Okay, now record the enctype and
88 enctype = out->keyblock.enctype;
89 krb5_free_creds (context, out);
91 krb5_free_cred_contents (context, &in);
94 if ((retval = krb5_copy_principal(context, client, &creds.client)))
97 retval = krb5int_tgtname(context, &client->realm, &client->realm,
102 /* fetch tgt directly from cache */
103 context->use_conf_ktypes = 1;
104 retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
106 context->use_conf_ktypes = old_use_conf_ktypes;
110 /* tgt->client must be equal to creds.client */
111 if (!krb5_principal_compare(context, tgt.client, creds.client)) {
112 retval = KRB5_PRINC_NOMATCH;
116 if (!tgt.ticket.length) {
117 retval = KRB5_NO_TKT_SUPPLIED;
121 if (tgt.addresses && *tgt.addresses) {
123 if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
124 retval = KRB5_FWD_BAD_PRINCIPAL;
128 if (krb5_princ_size(context, server) < 2){
129 retval = KRB5_CC_BADNAME;
133 rhost = malloc(server->data[1].length+1);
139 memcpy(rhost, server->data[1].data, server->data[1].length);
140 rhost[server->data[1].length] = '\0';
143 retval = krb5_os_hostaddr(context, rhost, &addrs);
148 creds.keyblock.enctype = enctype;
149 creds.times = tgt.times;
150 creds.times.starttime = 0;
151 kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
153 if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
154 kdcoptions &= ~(KDC_OPT_FORWARDABLE);
156 if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
157 addrs, &creds, &pcreds))) {
159 creds.keyblock.enctype = 0;
160 if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
161 addrs, &creds, &pcreds)))
166 retval = krb5_mk_1cred(context, auth_context, pcreds,
167 &scratch, &replaydata);
168 krb5_free_creds(context, pcreds);
172 krb5_free_data(context, scratch);
180 krb5_free_addresses(context, addrs);
182 krb5_cc_close(context, cc);
185 krb5_free_cred_contents(context, &creds);
186 krb5_free_cred_contents(context, &tgt);