static void get_default_principal(krb5_context context, krb5_principal *princ) { krb5_error_code ret; if ((ret = krb5_get_default_principal(context, princ)) != 0) krb5_err(context, 1, ret, "krb5_get_default_principal"); }
static krb5_error_code init_cred (krb5_context context, krb5_creds *cred, krb5_principal client, krb5_deltat start_time, krb5_get_init_creds_opt *options) { krb5_error_code ret; int tmp; krb5_timestamp now; krb5_timeofday (context, &now); memset (cred, 0, sizeof(*cred)); if (client) krb5_copy_principal(context, client, &cred->client); else { ret = krb5_get_default_principal (context, &cred->client); if (ret) goto out; } if (start_time) cred->times.starttime = now + start_time; if (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE) tmp = options->tkt_life; else tmp = 10 * 60 * 60; cred->times.endtime = now + tmp; if ((options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) && options->renew_life > 0) { cred->times.renew_till = now + options->renew_life; } return 0; out: krb5_free_cred_contents (context, cred); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_set_password(krb5_context context, krb5_creds *creds, char *newpw, krb5_principal targprinc, int *result_code, krb5_data *result_code_string, krb5_data *result_string) { krb5_principal principal = NULL; krb5_error_code ret = 0; int i; *result_code = KRB5_KPASSWD_MALFORMED; result_code_string->data = result_string->data = NULL; result_code_string->length = result_string->length = 0; if (targprinc == NULL) { ret = krb5_get_default_principal(context, &principal); if (ret) return ret; } else principal = targprinc; for (i = 0; procs[i].name != NULL; i++) { *result_code = 0; ret = change_password_loop(context, creds, targprinc, newpw, result_code, result_code_string, result_string, &procs[i]); if (ret == 0 && *result_code == 0) break; } if (targprinc == NULL) krb5_free_principal(context, principal); return ret; }
/* * This function produces a cred with a MEMORY ccache containing a TGT * acquired with a password. */ static OM_uint32 acquire_cred_with_password(OM_uint32 *minor_status, krb5_context context, const char *password, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gsskrb5_cred handle) { OM_uint32 ret = GSS_S_FAILURE; krb5_creds cred; krb5_get_init_creds_opt *opt; krb5_ccache ccache = NULL; krb5_error_code kret; time_t now; OM_uint32 left; if (cred_usage == GSS_C_ACCEPT) { /* * TODO: Here we should eventually support user2user (when we get * support for that via an extension to the mechanism * allowing for more than two security context tokens), * and/or new unique MEMORY keytabs (we have MEMORY keytab * support, but we don't have a keytab equivalent of * krb5_cc_new_unique()). Either way, for now we can't * support this. */ *minor_status = ENOTSUP; /* XXX Better error? */ return GSS_S_FAILURE; } memset(&cred, 0, sizeof(cred)); if (handle->principal == NULL) { kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; /* * Get the current time before the AS exchange so we don't * accidentally end up returning a value that puts advertised * expiration past the real expiration. * * We need to do this because krb5_cc_get_lifetime() returns a * relative time that we need to add to the current time. We ought * to have a version of krb5_cc_get_lifetime() that returns absolute * time... */ krb5_timeofday(context, &now); kret = krb5_get_init_creds_password(context, &cred, handle->principal, password, NULL, NULL, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (kret) goto end; kret = krb5_cc_initialize(context, ccache, cred.client); if (kret) goto end; kret = krb5_cc_store_cred(context, ccache, &cred); if (kret) goto end; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, handle->principal, &left); if (ret != GSS_S_COMPLETE) goto end; handle->endtime = now + left; handle->ccache = ccache; ccache = NULL; ret = GSS_S_COMPLETE; kret = 0; end: if (ccache != NULL) krb5_cc_destroy(context, ccache); if (cred.client != NULL) krb5_free_cred_contents(context, &cred); if (ret != GSS_S_COMPLETE && kret != 0) *minor_status = kret; return (ret); }
/* * Acquires an initiator credential from a ccache or using a keytab. */ static OM_uint32 acquire_initiator_cred(OM_uint32 *minor_status, krb5_context context, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gsskrb5_cred handle) { OM_uint32 ret = GSS_S_FAILURE; krb5_creds cred; krb5_get_init_creds_opt *opt; krb5_principal def_princ = NULL; krb5_ccache def_ccache = NULL; krb5_ccache ccache = NULL; /* we may store into this ccache */ krb5_keytab keytab = NULL; krb5_error_code kret = 0; OM_uint32 left; time_t lifetime = 0; time_t now; memset(&cred, 0, sizeof(cred)); /* * Get current time early so we can set handle->endtime to a value that * cannot accidentally be past the real endtime. We need a variant of * krb5_cc_get_lifetime() that returns absolute endtime. */ krb5_timeofday(context, &now); /* * First look for a ccache that has the desired_name (which may be * the default credential name). * * If we don't have an unexpired credential, acquire one with a * keytab. * * If we acquire one with a keytab, save it in the ccache we found * with the expired credential, if any. * * If we don't have any such ccache, then use a MEMORY ccache. */ if (handle->principal != NULL) { /* * Not default credential case. See if we can find a ccache in * the cccol for the desired_name. */ kret = krb5_cc_cache_match(context, handle->principal, &ccache); if (kret == 0) { kret = krb5_cc_get_lifetime(context, ccache, &lifetime); if (kret == 0) { if (lifetime > 0) goto found; else goto try_keytab; } } /* * Fall through. We shouldn't find this in the default ccache * either, but we'll give it a try, then we'll try using a keytab. */ } /* * Either desired_name was GSS_C_NO_NAME (default cred) or * krb5_cc_cache_match() failed (or found expired). */ kret = krb5_cc_default(context, &def_ccache); if (kret != 0) goto try_keytab; kret = krb5_cc_get_lifetime(context, def_ccache, &lifetime); if (kret != 0) lifetime = 0; kret = krb5_cc_get_principal(context, def_ccache, &def_princ); if (kret != 0) goto try_keytab; /* * Have a default ccache; see if it matches desired_name. */ if (handle->principal == NULL || krb5_principal_compare(context, handle->principal, def_princ) == TRUE) { /* * It matches. * * If we end up trying a keytab then we can write the result to * the default ccache. */ if (handle->principal == NULL) { kret = krb5_copy_principal(context, def_princ, &handle->principal); if (kret) goto end; } if (ccache != NULL) krb5_cc_close(context, ccache); ccache = def_ccache; def_ccache = NULL; if (lifetime > 0) goto found; /* else we fall through and try using a keytab */ } try_keytab: if (handle->principal == NULL) { /* We need to know what client principal to use */ kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } kret = get_keytab(context, &keytab); if (kret) goto end; kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; krb5_timeofday(context, &now); kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; /* * We got a credential with a keytab. Save it if we can. */ if (ccache == NULL) { /* * There's no ccache we can overwrite with the credentials we acquired * with a keytab. We'll use a MEMORY ccache then. * * Note that an application that falls into this repeatedly will do an * AS exchange every time it acquires a credential handle. Hopefully * this doesn't happen much. A workaround is to kinit -k once so that * we always re-initialize the matched/default ccache here. I.e., once * there's a FILE/DIR ccache, we'll keep it frash automatically if we * have a keytab, but if there's no FILE/DIR ccache, then we'll * get a fresh credential *every* time we're asked. */ kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (kret) goto end; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } /* else we'll re-initialize whichever ccache we matched above */ kret = krb5_cc_initialize(context, ccache, cred.client); if (kret) goto end; kret = krb5_cc_store_cred(context, ccache, &cred); if (kret) goto end; found: assert(handle->principal != NULL); ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, handle->principal, &left); if (ret != GSS_S_COMPLETE) goto end; handle->endtime = now + left; handle->ccache = ccache; ccache = NULL; ret = GSS_S_COMPLETE; kret = 0; end: if (ccache != NULL) { if ((handle->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) != 0) krb5_cc_destroy(context, ccache); else krb5_cc_close(context, ccache); } if (def_ccache != NULL) krb5_cc_close(context, def_ccache); if (cred.client != NULL) krb5_free_cred_contents(context, &cred); if (def_princ != NULL) krb5_free_principal(context, def_princ); if (keytab != NULL) krb5_kt_close(context, keytab); if (ret != GSS_S_COMPLETE && kret != 0) *minor_status = kret; return (ret); }
int main(int argc, char **argv) { krb5_context context; krb5_error_code ret; krb5_creds cred; krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP}; krb5_get_init_creds_opt *get_options; krb5_verify_init_creds_opt verify_options; krb5_principal principal = NULL; int optidx = 0; setprogname (argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_get_init_creds_opt_alloc (context, &get_options); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_preauth_list (get_options, pre_auth_types, 1); krb5_verify_init_creds_opt_init (&verify_options); if (argc) { ret = krb5_parse_name(context, argv[0], &principal); if (ret) krb5_err(context, 1, ret, "krb5_parse_name: %s", argv[0]); } else { ret = krb5_get_default_principal(context, &principal); if (ret) krb5_err(context, 1, ret, "krb5_get_default_principal"); } ret = krb5_get_init_creds_password (context, &cred, principal, NULL, krb5_prompter_posix, NULL, 0, NULL, get_options); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); ret = krb5_verify_init_creds (context, &cred, NULL, NULL, NULL, &verify_options); if (ret) krb5_err(context, 1, ret, "krb5_verify_init_creds"); krb5_free_cred_contents (context, &cred); krb5_free_context (context); return 0; }
static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, gss_const_OID credential_type, const void *credential_data, gss_const_name_t desired_name, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gsskrb5_cred handle ) { OM_uint32 ret; krb5_creds cred; krb5_principal def_princ; krb5_get_init_creds_opt *opt; krb5_ccache ccache; krb5_keytab keytab; krb5_error_code kret; keytab = NULL; ccache = NULL; def_princ = NULL; ret = GSS_S_FAILURE; memset(&cred, 0, sizeof(cred)); /* * If we have a preferred principal, lets try to find it in all * caches, otherwise, fall back to default cache, ignore all * errors while searching. */ if (credential_type != GSS_C_NO_OID && !gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { kret = KRB5_NOCREDS_SUPPLIED; /* XXX */ goto end; } if (handle->principal) { kret = krb5_cc_cache_match (context, handle->principal, &ccache); if (kret == 0) { ret = GSS_S_COMPLETE; goto found; } } if (ccache == NULL) { kret = krb5_cc_default(context, &ccache); if (kret) goto end; } kret = krb5_cc_get_principal(context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ krb5_cc_close(context, ccache); def_princ = NULL; kret = 0; } else if (handle->principal == NULL) { kret = krb5_copy_principal(context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && krb5_principal_compare(context, handle->principal, def_princ) == FALSE) { krb5_free_principal(context, def_princ); def_princ = NULL; krb5_cc_close(context, ccache); ccache = NULL; } if (def_princ == NULL) { /* We have no existing credentials cache, * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; if (credential_type != GSS_C_NO_OID && gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { gss_buffer_t password = (gss_buffer_t)credential_data; /* XXX are we requiring password to be NUL terminated? */ kret = krb5_get_init_creds_password(context, &cred, handle->principal, password->value, NULL, NULL, 0, NULL, opt); } else { kret = get_keytab(context, &keytab); if (kret) { krb5_get_init_creds_opt_free(context, opt); goto end; } kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, keytab, 0, NULL, opt); } krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (kret) goto end; kret = krb5_cc_initialize(context, ccache, cred.client); if (kret) { krb5_cc_destroy(context, ccache); goto end; } kret = krb5_cc_store_cred(context, ccache, &cred); if (kret) { krb5_cc_destroy(context, ccache); goto end; } handle->lifetime = cred.times.endtime; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } else { ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, handle->principal, &handle->lifetime); if (ret != GSS_S_COMPLETE) { krb5_cc_close(context, ccache); goto end; } kret = 0; } found: handle->ccache = ccache; ret = GSS_S_COMPLETE; end: if (cred.client != NULL) krb5_free_cred_contents(context, &cred); if (def_princ != NULL) krb5_free_principal(context, def_princ); if (keytab != NULL) krb5_kt_close(context, keytab); if (ret != GSS_S_COMPLETE && kret != 0) *minor_status = kret; return (ret); }
static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, const gss_name_t desired_name, OM_uint32 time_req, gss_cred_usage_t cred_usage, gsskrb5_cred handle ) { OM_uint32 ret = GSS_S_FAILURE; krb5_creds cred; krb5_principal def_princ = NULL; krb5_get_init_creds_opt *opt; krb5_ccache ccache = NULL; krb5_error_code kret; memset(&cred, 0, sizeof(cred)); /* * If we have a preferred principal, lets try to find it in all * caches, otherwise, fall back to default cache, ignore all * errors while searching. */ if (handle->principal) { kret = krb5_cc_cache_match (context, handle->principal, &ccache); if (kret == 0) { goto found; } } if (ccache == NULL) { kret = krb5_cc_default(context, &ccache); if (kret) goto end; } kret = krb5_cc_get_principal(context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ krb5_cc_close(context, ccache); def_princ = NULL; kret = 0; } else if (handle->principal == NULL) { kret = krb5_copy_principal(context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && krb5_principal_compare(context, handle->principal, def_princ) == FALSE) { krb5_free_principal(context, def_princ); def_princ = NULL; krb5_cc_close(context, ccache); ccache = NULL; } if (def_princ == NULL) { /* We have no existing credentials cache, * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } /* * Require user is in the keytab before trying to talk to * the KDC. */ kret = get_keytab(context, handle, 0); if (kret) goto end; /* since the name might have changed, let double check the credential cache */ kret = krb5_cc_cache_match(context, handle->principal, &ccache); if (kret == 0) goto found; kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, handle->keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (kret) goto end; kret = krb5_cc_initialize(context, ccache, cred.client); if (kret) { krb5_cc_destroy(context, ccache); goto end; } kret = krb5_cc_store_cred(context, ccache, &cred); if (kret) { krb5_cc_destroy(context, ccache); goto end; } handle->endtime = cred.times.endtime; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } else { found: ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, handle->principal, &handle->endtime); if (ret != GSS_S_COMPLETE) { krb5_cc_close(context, ccache); goto end; } kret = 0; } handle->ccache = ccache; ret = GSS_S_COMPLETE; end: if (cred.client != NULL) krb5_free_cred_contents(context, &cred); if (def_princ != NULL) krb5_free_principal(context, def_princ); if (ret != GSS_S_COMPLETE && kret != 0) *minor_status = kret; return (ret); }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; krb5_principal principal; int optidx = 0; krb5_deltat ticket_life = 0; int parseflags = 0; setprogname (argv[0]); setlocale (LC_ALL, ""); bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR); textdomain("heimdal_kuser"); ret = krb5_init_context (&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx(1, "krb5_init_context failed: %d", ret); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (canonicalize_flag || enterprise_flag) parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; if (pk_enterprise_flag) { ret = krb5_pk_enterprise_cert(context, pk_user_id, argv[0], &principal, &ent_user_id); if (ret) krb5_err(context, 1, ret, "krb5_pk_enterprise_certs"); pk_user_id = NULL; } else if (anonymous_flag) { ret = krb5_make_principal(context, &principal, argv[0], KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); if (ret) krb5_err(context, 1, ret, "krb5_make_principal"); krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN); } else { if (argv[0]) { ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { ret = krb5_get_default_principal (context, &principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } } if(fcache_version) krb5_set_fcache_version(context, fcache_version); if(renewable_flag == -1) /* this seems somewhat pointless, but whatever */ krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "renewable", FALSE, &renewable_flag); if(do_afslog == -1) krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "afslog", TRUE, &do_afslog); if(cred_cache) ret = krb5_cc_resolve(context, cred_cache, &ccache); else { if(argc > 1) { char s[1024]; ret = krb5_cc_new_unique(context, NULL, NULL, &ccache); if(ret) krb5_err(context, 1, ret, "creating cred cache"); snprintf(s, sizeof(s), "%s:%s", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); setenv("KRB5CCNAME", s, 1); } else { ret = krb5_cc_cache_match(context, principal, &ccache); if (ret) { const char *type; ret = krb5_cc_default (context, &ccache); if (ret) krb5_err (context, 1, ret, N_("resolving credentials cache", "")); /* * Check if the type support switching, and we do, * then do that instead over overwriting the current * default credential */ type = krb5_cc_get_type(context, ccache); if (krb5_cc_support_switch(context, type)) { krb5_cc_close(context, ccache); ret = krb5_cc_new_unique(context, type, NULL, &ccache); } } } } if (ret) krb5_err (context, 1, ret, N_("resolving credentials cache", "")); #ifndef NO_AFS if(argc > 1 && k_hasafs ()) k_setpag(); #endif if (lifetime) { int tmp = parse_time (lifetime, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), lifetime); ticket_life = tmp; } if(addrs_flag == 0 && extra_addresses.num_strings > 0) krb5_errx(context, 1, N_("specifying both extra addresses and " "no addresses makes no sense", "")); { int i; krb5_addresses addresses; memset(&addresses, 0, sizeof(addresses)); for(i = 0; i < extra_addresses.num_strings; i++) { ret = krb5_parse_address(context, extra_addresses.strings[i], &addresses); if (ret == 0) { krb5_add_extra_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } free_getarg_strings(&extra_addresses); } if(renew_flag || validate_flag) { ret = renew_validate(context, renew_flag, validate_flag, ccache, server_str, ticket_life); exit(ret != 0); } get_new_tickets(context, principal, ccache, ticket_life, 1); #ifndef NO_AFS if(do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); #endif if(argc > 1) { struct renew_ctx ctx; time_t timeout; timeout = ticket_lifetime(context, ccache, principal, server_str, NULL) / 2; ctx.context = context; ctx.ccache = ccache; ctx.principal = principal; ctx.ticket_life = ticket_life; ret = simple_execvp_timed(argv[1], argv+1, renew_func, &ctx, timeout); #define EX_NOEXEC 126 #define EX_NOTFOUND 127 if(ret == EX_NOEXEC) krb5_warnx(context, N_("permission denied: %s", ""), argv[1]); else if(ret == EX_NOTFOUND) krb5_warnx(context, N_("command not found: %s", ""), argv[1]); krb5_cc_destroy(context, ccache); #ifndef NO_AFS if(k_hasafs()) k_unlog(); #endif } else { krb5_cc_close (context, ccache); ret = 0; } krb5_free_principal(context, principal); krb5_free_context (context); return ret; }
static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) { OM_uint32 ret; krb5_creds cred; krb5_principal def_princ; krb5_get_init_creds_opt *opt; krb5_ccache ccache; krb5_keytab keytab; krb5_error_code kret; keytab = NULL; ccache = NULL; def_princ = NULL; ret = GSS_S_FAILURE; memset(&cred, 0, sizeof(cred)); kret = krb5_cc_default(gssapi_krb5_context, &ccache); if (kret) goto end; kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ krb5_cc_destroy(gssapi_krb5_context, ccache); ccache = NULL; kret = 0; } else if (handle->principal == NULL) { kret = krb5_copy_principal(gssapi_krb5_context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && krb5_principal_compare(gssapi_krb5_context, handle->principal, def_princ) == FALSE) { /* Before failing, lets check the keytab */ krb5_free_principal(gssapi_krb5_context, def_princ); def_princ = NULL; } if (def_princ == NULL) { /* We have no existing credentials cache, * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { kret = krb5_get_default_principal(gssapi_krb5_context, &handle->principal); if (kret) goto end; } kret = get_keytab(&keytab); if (kret) goto end; kret = krb5_get_init_creds_opt_alloc(gssapi_krb5_context, &opt); if (kret) goto end; kret = krb5_get_init_creds_keytab(gssapi_krb5_context, &cred, handle->principal, keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(opt); if (kret) goto end; kret = krb5_cc_gen_new(gssapi_krb5_context, &krb5_mcc_ops, &ccache); if (kret) goto end; kret = krb5_cc_initialize(gssapi_krb5_context, ccache, cred.client); if (kret) goto end; kret = krb5_cc_store_cred(gssapi_krb5_context, ccache, &cred); if (kret) goto end; handle->lifetime = cred.times.endtime; } else { krb5_creds in_cred, *out_cred; krb5_const_realm realm; memset(&in_cred, 0, sizeof(in_cred)); in_cred.client = handle->principal; realm = krb5_principal_get_realm(gssapi_krb5_context, handle->principal); if (realm == NULL) { kret = KRB5_PRINC_NOMATCH; /* XXX */ goto end; } kret = krb5_make_principal(gssapi_krb5_context, &in_cred.server, realm, KRB5_TGS_NAME, realm, NULL); if (kret) goto end; kret = krb5_get_credentials(gssapi_krb5_context, 0, ccache, &in_cred, &out_cred); krb5_free_principal(gssapi_krb5_context, in_cred.server); if (kret) goto end; handle->lifetime = out_cred->times.endtime; krb5_free_creds(gssapi_krb5_context, out_cred); } handle->ccache = ccache; ret = GSS_S_COMPLETE; end: if (cred.client != NULL) krb5_free_cred_contents(gssapi_krb5_context, &cred); if (def_princ != NULL) krb5_free_principal(gssapi_krb5_context, def_princ); if (keytab != NULL) krb5_kt_close(gssapi_krb5_context, keytab); if (ret != GSS_S_COMPLETE) { if (ccache != NULL) krb5_cc_close(gssapi_krb5_context, ccache); if (kret != 0) { *minor_status = kret; gssapi_krb5_set_error_string (); } } return (ret); }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_principal principal; krb5_get_init_creds_opt *opt; krb5_ccache id = NULL; int exit_value; int optidx = 0; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1, args, sizeof(args) / sizeof(args[0])); if (help_flag) usage(0, args, sizeof(args) / sizeof(args[0])); if (version_flag) { print_version(NULL); return 0; } argc -= optidx; argv += optidx; ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_get_init_creds_opt_alloc (context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_tkt_life (opt, 300); krb5_get_init_creds_opt_set_forwardable (opt, FALSE); krb5_get_init_creds_opt_set_proxiable (opt, FALSE); if (cred_cache_str) { ret = krb5_cc_resolve(context, cred_cache_str, &id); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } else { ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); if (ret) krb5_err (context, 1, ret, "krb5_cc_new_unique"); } if (cred_cache_str == NULL) { krb5_principal admin_principal = NULL; krb5_creds cred; if (admin_principal_str) { ret = krb5_parse_name (context, admin_principal_str, &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else if (argc == 1) { ret = krb5_parse_name (context, argv[0], &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { ret = krb5_get_default_principal (context, &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } ret = krb5_get_init_creds_password (context, &cred, admin_principal, NULL, krb5_prompter_posix, NULL, 0, "kadmin/changepw", opt); switch (ret) { case 0: break; case KRB5_LIBOS_PWDINTR : return 1; case KRB5KRB_AP_ERR_BAD_INTEGRITY : case KRB5KRB_AP_ERR_MODIFIED : krb5_errx(context, 1, "Password incorrect"); break; default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } krb5_get_init_creds_opt_free(context, opt); ret = krb5_cc_initialize(context, id, admin_principal); krb5_free_principal(context, admin_principal); if (ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, &cred); if (ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); } if (argc == 0) { exit_value = change_password(context, NULL, id); } else { exit_value = 0; while (argc-- > 0) { ret = krb5_parse_name (context, argv[0], &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); ret = change_password(context, principal, id); if (ret) exit_value = 1; krb5_free_principal(context, principal); argv++; } } if (cred_cache_str == NULL) { ret = krb5_cc_destroy(context, id); if (ret) krb5_err (context, 1, ret, "krb5_cc_destroy"); } else { ret = krb5_cc_close(context, id); if (ret) krb5_err (context, 1, ret, "krb5_cc_close"); } krb5_free_context (context); return exit_value; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred (OM_uint32 * minor_status, const gss_cred_id_t cred_handle, gss_name_t * output_name, OM_uint32 * lifetime, gss_cred_usage_t * cred_usage, gss_OID_set * mechanisms ) { krb5_context context; gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL; gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL; gsskrb5_cred acred = NULL, icred = NULL; OM_uint32 ret; *minor_status = 0; if (output_name) *output_name = NULL; if (mechanisms) *mechanisms = GSS_C_NO_OID_SET; GSSAPI_KRB5_INIT (&context); if (cred_handle == GSS_C_NO_CREDENTIAL) { ret = _gsskrb5_acquire_cred(minor_status, GSS_C_NO_NAME, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &aqcred_accept, NULL, NULL); if (ret == GSS_S_COMPLETE) acred = (gsskrb5_cred)aqcred_accept; ret = _gsskrb5_acquire_cred(minor_status, GSS_C_NO_NAME, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &aqcred_init, NULL, NULL); if (ret == GSS_S_COMPLETE) icred = (gsskrb5_cred)aqcred_init; if (icred == NULL && acred == NULL) { *minor_status = 0; return GSS_S_NO_CRED; } } else acred = (gsskrb5_cred)cred_handle; if (acred) HEIMDAL_MUTEX_lock(&acred->cred_id_mutex); if (icred) HEIMDAL_MUTEX_lock(&icred->cred_id_mutex); if (output_name != NULL) { if (icred && icred->principal != NULL) { gss_name_t name; if (acred && acred->principal) name = (gss_name_t)acred->principal; else name = (gss_name_t)icred->principal; ret = _gsskrb5_duplicate_name(minor_status, name, output_name); if (ret) goto out; } else if (acred && acred->usage == GSS_C_ACCEPT) { krb5_principal princ; *minor_status = krb5_sname_to_principal(context, NULL, NULL, KRB5_NT_SRV_HST, &princ); if (*minor_status) { ret = GSS_S_FAILURE; goto out; } *output_name = (gss_name_t)princ; } else { krb5_principal princ; *minor_status = krb5_get_default_principal(context, &princ); if (*minor_status) { ret = GSS_S_FAILURE; goto out; } *output_name = (gss_name_t)princ; } } if (lifetime != NULL) { OM_uint32 alife = GSS_C_INDEFINITE, ilife = GSS_C_INDEFINITE; if (acred) alife = acred->lifetime; if (icred) ilife = icred->lifetime; ret = _gsskrb5_lifetime_left(minor_status, context, min(alife,ilife), lifetime); if (ret) goto out; } if (cred_usage != NULL) { if (acred && icred) *cred_usage = GSS_C_BOTH; else if (acred) *cred_usage = GSS_C_ACCEPT; else if (icred) *cred_usage = GSS_C_INITIATE; else abort(); } if (mechanisms != NULL) { ret = gss_create_empty_oid_set(minor_status, mechanisms); if (ret) goto out; if (acred) ret = gss_add_oid_set_member(minor_status, &acred->mechanisms->elements[0], mechanisms); if (ret == GSS_S_COMPLETE && icred) ret = gss_add_oid_set_member(minor_status, &icred->mechanisms->elements[0], mechanisms); if (ret) goto out; } ret = GSS_S_COMPLETE; out: if (acred) HEIMDAL_MUTEX_unlock(&acred->cred_id_mutex); if (icred) HEIMDAL_MUTEX_unlock(&icred->cred_id_mutex); if (aqcred_init != GSS_C_NO_CREDENTIAL) ret = _gsskrb5_release_cred(minor_status, &aqcred_init); if (aqcred_accept != GSS_C_NO_CREDENTIAL) ret = _gsskrb5_release_cred(minor_status, &aqcred_accept); return ret; }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; krb5_principal principal; int optidx = 0; krb5_deltat ticket_life = 0; int parseflags = 0; setprogname (argv[0]); setlocale (LC_ALL, ""); #if defined(HEIMDAL_LOCALEDIR) bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR); textdomain("heimdal_kuser"); #endif ret = krb5_init_context (&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx(1, "krb5_init_context failed: %d", ret); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (canonicalize_flag) parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; if (argv[0]) { ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { ret = krb5_get_default_principal (context, &principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } if(fcache_version) krb5_set_fcache_version(context, fcache_version); if(renewable_flag == -1) /* this seems somewhat pointless, but whatever */ krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "renewable", FALSE, &renewable_flag); #ifndef HEIMDAL_SMALLER if(get_v4_tgt == -1) krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "krb4_get_tickets", FALSE, &get_v4_tgt); #endif if(do_afslog == -1) krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "afslog", TRUE, &do_afslog); if(cred_cache) ret = krb5_cc_resolve(context, cred_cache, &ccache); else { if(argc > 1) { char s[1024]; ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache); if(ret) krb5_err(context, 1, ret, "creating cred cache"); snprintf(s, sizeof(s), "%s:%s", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); setenv("KRB5CCNAME", s, 1); #ifndef HEIMDAL_SMALLER if (get_v4_tgt) { int fd; if (asprintf(&krb4_cc_name, "%s_XXXXXX", TKT_ROOT) < 0) krb5_errx(context, 1, "out of memory"); if((fd = mkstemp(krb4_cc_name)) >= 0) { close(fd); setenv("KRBTKFILE", krb4_cc_name, 1); } else { free(krb4_cc_name); krb4_cc_name = NULL; } } #endif } else { ret = krb5_cc_cache_match(context, principal, &ccache); if (ret) ret = krb5_cc_default (context, &ccache); } } if (ret) krb5_err (context, 1, ret, N_("resolving credentials cache", "")); if(argc > 1 && k_hasafs ()) k_setpag(); if (lifetime) { int tmp = parse_time (lifetime, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), lifetime); ticket_life = tmp; } if(addrs_flag == 0 && extra_addresses.num_strings > 0) krb5_errx(context, 1, N_("specifying both extra addresses and " "no addresses makes no sense", "")); { int i; krb5_addresses addresses; memset(&addresses, 0, sizeof(addresses)); for(i = 0; i < extra_addresses.num_strings; i++) { ret = krb5_parse_address(context, extra_addresses.strings[i], &addresses); if (ret == 0) { krb5_add_extra_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } free_getarg_strings(&extra_addresses); } if(renew_flag || validate_flag) { ret = renew_validate(context, renew_flag, validate_flag, ccache, server_str, ticket_life); exit(ret != 0); } #ifndef HEIMDAL_SMALLER if(!convert_524) #endif get_new_tickets(context, principal, ccache, ticket_life, 1); #ifndef HEIMDAL_SMALLER if(get_v4_tgt || convert_524) do_524init(context, ccache, NULL, server_str); #endif if(do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); if(argc > 1) { struct renew_ctx ctx; time_t timeout; timeout = ticket_lifetime(context, ccache, principal, server_str) / 2; ctx.context = context; ctx.ccache = ccache; ctx.principal = principal; ctx.ticket_life = ticket_life; ret = simple_execvp_timed(argv[1], argv+1, renew_func, &ctx, timeout); #define EX_NOEXEC 126 #define EX_NOTFOUND 127 if(ret == EX_NOEXEC) krb5_warnx(context, N_("permission denied: %s", ""), argv[1]); else if(ret == EX_NOTFOUND) krb5_warnx(context, N_("command not found: %s", ""), argv[1]); krb5_cc_destroy(context, ccache); #ifndef HEIMDAL_SMALLER _krb5_krb_dest_tkt(context, krb4_cc_name); #endif if(k_hasafs()) k_unlog(); } else { krb5_cc_close (context, ccache); ret = 0; } krb5_free_principal(context, principal); krb5_free_context (context); return ret; }