2 * lib/krb5/krb/gic_keytab.c
4 * Copyright (C) 2002, 2003, 2008 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.
30 static krb5_error_code
31 krb5_get_as_key_keytab(
33 krb5_principal client,
35 krb5_prompter_fct prompter,
39 krb5_keyblock *as_key,
42 krb5_keytab keytab = (krb5_keytab) gak_data;
44 krb5_keytab_entry kt_ent;
45 krb5_keyblock *kt_key;
47 /* if there's already a key of the correct etype, we're done.
48 if the etype is wrong, free the existing key, and make
52 if (as_key->enctype == etype)
55 krb5_free_keyblock_contents(context, as_key);
59 if (!krb5_c_valid_enctype(etype))
60 return(KRB5_PROG_ETYPE_NOSUPP);
62 if ((ret = krb5_kt_get_entry(context, keytab, client,
63 0, /* don't have vno available */
67 ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);
69 /* again, krb5's memory management is lame... */
74 (void) krb5_kt_free_entry(context, &kt_ent);
79 krb5_error_code KRB5_CALLCONV
80 krb5_get_init_creds_keytab(krb5_context context,
82 krb5_principal client,
83 krb5_keytab arg_keytab,
84 krb5_deltat start_time,
86 krb5_get_init_creds_opt *options)
88 krb5_error_code ret, ret2;
91 krb5_gic_opt_ext *opte = NULL;
93 if (arg_keytab == NULL) {
94 if ((ret = krb5_kt_default(context, &keytab)))
100 ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
101 "krb5_get_init_creds_keytab");
107 /* first try: get the requested tkt from any kdc */
109 ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
110 start_time, in_tkt_service, opte,
111 krb5_get_as_key_keytab, (void *) keytab,
114 /* check for success */
119 /* If all the kdc's are unavailable fail */
121 if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE))
124 /* if the reply did not come from the master kdc, try again with
130 ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL,
131 start_time, in_tkt_service, opte,
132 krb5_get_as_key_keytab, (void *) keytab,
140 /* if the master is unreachable, return the error from the
141 slave we were able to contact */
143 if ((ret2 == KRB5_KDC_UNREACH) ||
144 (ret2 == KRB5_REALM_CANT_RESOLVE) ||
145 (ret2 == KRB5_REALM_UNKNOWN))
151 /* at this point, we have a response from the master. Since we don't
152 do any prompting or changing for keytabs, that's it. */
155 if (opte && krb5_gic_opt_is_shadowed(opte))
156 krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
157 if (arg_keytab == NULL)
158 krb5_kt_close(context, keytab);
162 krb5_error_code KRB5_CALLCONV
163 krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
164 krb5_address *const *addrs, krb5_enctype *ktypes,
165 krb5_preauthtype *pre_auth_types,
166 krb5_keytab arg_keytab, krb5_ccache ccache,
167 krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
169 krb5_error_code retval;
170 krb5_gic_opt_ext *opte;
171 char * server = NULL;
173 krb5_principal client_princ, server_princ;
176 retval = krb5int_populate_gic_opt(context, &opte,
177 options, addrs, ktypes,
178 pre_auth_types, creds);
182 if (arg_keytab == NULL) {
183 retval = krb5_kt_default(context, &keytab);
187 else keytab = arg_keytab;
189 retval = krb5_unparse_name( context, creds->server, &server);
192 server_princ = creds->server;
193 client_princ = creds->client;
194 retval = krb5_get_init_creds (context,
195 creds, creds->client,
196 krb5_prompter_posix, NULL,
198 krb5_get_as_key_keytab, (void *)keytab,
199 &use_master, ret_as_reply);
200 krb5_free_unparsed_name( context, server);
201 krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
206 krb5_free_principal( context, creds->server);
208 krb5_free_principal( context, creds->client);
209 creds->client = client_princ;
210 creds->server = server_princ;
212 /* store it in the ccache! */
214 if ((retval = krb5_cc_store_cred(context, ccache, creds)))
216 cleanup: if (arg_keytab == NULL)
217 krb5_kt_close(context, keytab);
221 #endif /* LEAN_CLIENT */