+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/gic_keytab.c */
/*
- * lib/krb5/krb/gic_keytab.c
- *
* Copyright (C) 2002, 2003, 2008 by the Massachusetts Institute of Technology.
* All rights reserved.
*
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
- *
+ *
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*/
-#ifndef LEAN_CLIENT
+#ifndef LEAN_CLIENT
#include "k5-int.h"
+#include "int-proto.h"
+#include "init_creds_ctx.h"
static krb5_error_code
-krb5_get_as_key_keytab(
- krb5_context context,
- krb5_principal client,
- krb5_enctype etype,
- krb5_prompter_fct prompter,
- void *prompter_data,
- krb5_data *salt,
- krb5_data *params,
- krb5_keyblock *as_key,
- void *gak_data)
+get_as_key_keytab(krb5_context context,
+ krb5_principal client,
+ krb5_enctype etype,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_data *salt,
+ krb5_data *params,
+ krb5_keyblock *as_key,
+ void *gak_data)
{
krb5_keytab keytab = (krb5_keytab) gak_data;
krb5_error_code ret;
a new one. */
if (as_key->length) {
- if (as_key->enctype == etype)
- return(0);
+ if (as_key->enctype == etype)
+ return(0);
- krb5_free_keyblock_contents(context, as_key);
- as_key->length = 0;
+ krb5_free_keyblock_contents(context, as_key);
+ as_key->length = 0;
}
if (!krb5_c_valid_enctype(etype))
- return(KRB5_PROG_ETYPE_NOSUPP);
+ return(KRB5_PROG_ETYPE_NOSUPP);
if ((ret = krb5_kt_get_entry(context, keytab, client,
- 0, /* don't have vno available */
- etype, &kt_ent)))
- return(ret);
+ 0, /* don't have vno available */
+ etype, &kt_ent)))
+ return(ret);
ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);
return(ret);
}
+krb5_error_code KRB5_CALLCONV
+krb5_init_creds_set_keytab(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keytab keytab)
+{
+ ctx->gak_fct = get_as_key_keytab;
+ ctx->gak_data = keytab;
+
+ return 0;
+}
+
+static krb5_error_code
+get_init_creds_keytab(krb5_context context, krb5_creds *creds,
+ krb5_principal client, krb5_keytab keytab,
+ krb5_deltat start_time, char *in_tkt_service,
+ krb5_get_init_creds_opt *options, int *use_master)
+{
+ krb5_error_code ret;
+ krb5_init_creds_context ctx = NULL;
+
+ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time,
+ options, &ctx);
+ if (ret != 0)
+ goto cleanup;
+
+ if (in_tkt_service) {
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret != 0)
+ goto cleanup;
+ }
+
+ ret = krb5_init_creds_set_keytab(context, ctx, keytab);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = k5_init_creds_get(context, ctx, use_master);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = krb5_init_creds_get_creds(context, ctx, creds);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ krb5_init_creds_free(context, ctx);
+
+ return ret;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_keytab(krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_keytab arg_keytab,
- krb5_deltat start_time,
- char *in_tkt_service,
- krb5_get_init_creds_opt *options)
+ krb5_creds *creds,
+ krb5_principal client,
+ krb5_keytab arg_keytab,
+ krb5_deltat start_time,
+ char *in_tkt_service,
+ krb5_get_init_creds_opt *options)
{
- krb5_error_code ret, ret2;
- int use_master;
- krb5_keytab keytab;
- krb5_gic_opt_ext *opte = NULL;
+ krb5_error_code ret, ret2;
+ int use_master;
+ krb5_keytab keytab;
- if (arg_keytab == NULL) {
- if ((ret = krb5_kt_default(context, &keytab)))
- return ret;
- } else {
- keytab = arg_keytab;
- }
+ if (arg_keytab == NULL) {
+ if ((ret = krb5_kt_default(context, &keytab)))
+ return ret;
+ } else {
+ keytab = arg_keytab;
+ }
- ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
- "krb5_get_init_creds_keytab");
- if (ret)
- return ret;
+ use_master = 0;
- use_master = 0;
+ /* first try: get the requested tkt from any kdc */
- /* first try: get the requested tkt from any kdc */
+ ret = get_init_creds_keytab(context, creds, client, keytab, start_time,
+ in_tkt_service, options, &use_master);
- ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
- start_time, in_tkt_service, opte,
- krb5_get_as_key_keytab, (void *) keytab,
- &use_master,NULL);
+ /* check for success */
- /* check for success */
+ if (ret == 0)
+ goto cleanup;
- if (ret == 0)
- goto cleanup;
+ /* If all the kdc's are unavailable fail */
- /* If all the kdc's are unavailable fail */
+ if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE))
+ goto cleanup;
- if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE))
- goto cleanup;
+ /* if the reply did not come from the master kdc, try again with
+ the master kdc */
- /* if the reply did not come from the master kdc, try again with
- the master kdc */
+ if (!use_master) {
+ use_master = 1;
- if (!use_master) {
- use_master = 1;
+ ret2 = get_init_creds_keytab(context, creds, client, keytab,
+ start_time, in_tkt_service, options,
+ &use_master);
- ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL,
- start_time, in_tkt_service, opte,
- krb5_get_as_key_keytab, (void *) keytab,
- &use_master, NULL);
-
- if (ret2 == 0) {
- ret = 0;
- goto cleanup;
- }
+ if (ret2 == 0) {
+ ret = 0;
+ goto cleanup;
+ }
- /* if the master is unreachable, return the error from the
- slave we were able to contact */
+ /* if the master is unreachable, return the error from the
+ slave we were able to contact */
- if ((ret2 == KRB5_KDC_UNREACH) ||
- (ret2 == KRB5_REALM_CANT_RESOLVE) ||
- (ret2 == KRB5_REALM_UNKNOWN))
- goto cleanup;
+ if ((ret2 == KRB5_KDC_UNREACH) ||
+ (ret2 == KRB5_REALM_CANT_RESOLVE) ||
+ (ret2 == KRB5_REALM_UNKNOWN))
+ goto cleanup;
- ret = ret2;
- }
+ ret = ret2;
+ }
- /* at this point, we have a response from the master. Since we don't
- do any prompting or changing for keytabs, that's it. */
+ /* at this point, we have a response from the master. Since we don't
+ do any prompting or changing for keytabs, that's it. */
cleanup:
- if (opte && krb5_gic_opt_is_shadowed(opte))
- krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
- if (arg_keytab == NULL)
- krb5_kt_close(context, keytab);
+ if (arg_keytab == NULL)
+ krb5_kt_close(context, keytab);
- return(ret);
+ return(ret);
}
krb5_error_code KRB5_CALLCONV
krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
- krb5_address *const *addrs, krb5_enctype *ktypes,
- krb5_preauthtype *pre_auth_types,
- krb5_keytab arg_keytab, krb5_ccache ccache,
- krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+ krb5_address *const *addrs, krb5_enctype *ktypes,
+ krb5_preauthtype *pre_auth_types,
+ krb5_keytab arg_keytab, krb5_ccache ccache,
+ krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
{
krb5_error_code retval;
- krb5_gic_opt_ext *opte;
+ krb5_get_init_creds_opt *opts;
char * server = NULL;
krb5_keytab keytab;
krb5_principal client_princ, server_princ;
int use_master = 0;
-
- retval = krb5int_populate_gic_opt(context, &opte,
- options, addrs, ktypes,
- pre_auth_types, creds);
+
+ retval = krb5int_populate_gic_opt(context, &opts,
+ options, addrs, ktypes,
+ pre_auth_types, creds);
if (retval)
- return retval;
+ return retval;
if (arg_keytab == NULL) {
- retval = krb5_kt_default(context, &keytab);
- if (retval)
- return retval;
+ retval = krb5_kt_default(context, &keytab);
+ if (retval)
+ goto cleanup;
}
else keytab = arg_keytab;
-
+
retval = krb5_unparse_name( context, creds->server, &server);
if (retval)
- goto cleanup;
+ goto cleanup;
server_princ = creds->server;
client_princ = creds->client;
- retval = krb5_get_init_creds (context,
- creds, creds->client,
- krb5_prompter_posix, NULL,
- 0, server, opte,
- krb5_get_as_key_keytab, (void *)keytab,
- &use_master, ret_as_reply);
+ retval = krb5int_get_init_creds(context, creds, creds->client,
+ krb5_prompter_posix, NULL,
+ 0, server, opts,
+ get_as_key_keytab, (void *)keytab,
+ &use_master, ret_as_reply);
krb5_free_unparsed_name( context, server);
- krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
if (retval) {
- goto cleanup;
+ goto cleanup;
}
- if (creds->server)
- krb5_free_principal( context, creds->server);
- if (creds->client)
- krb5_free_principal( context, creds->client);
- creds->client = client_princ;
- creds->server = server_princ;
-
+ krb5_free_principal(context, creds->server);
+ krb5_free_principal(context, creds->client);
+ creds->client = client_princ;
+ creds->server = server_princ;
+
/* store it in the ccache! */
if (ccache)
- if ((retval = krb5_cc_store_cred(context, ccache, creds)))
- goto cleanup;
- cleanup: if (arg_keytab == NULL)
- krb5_kt_close(context, keytab);
+ if ((retval = krb5_cc_store_cred(context, ccache, creds)))
+ goto cleanup;
+cleanup:
+ krb5_get_init_creds_opt_free(context, opts);
+ if (arg_keytab == NULL)
+ krb5_kt_close(context, keytab);
return retval;
}
#endif /* LEAN_CLIENT */
-