static void cc_test(krb5_context context, const char *name, krb5_flags flags) { krb5_ccache id, id2; krb5_creds creds; krb5_error_code kret; krb5_cc_cursor cursor; krb5_principal tmp; const char *c_name; char newcache[300]; char *save_type; kret = init_test_cred(context); CHECK(kret, "init_creds"); kret = krb5_cc_resolve(context, name, &id); CHECK(kret, "resolve"); kret = krb5_cc_initialize(context, id, test_creds.client); CHECK(kret, "initialize"); c_name = krb5_cc_get_name(context, id); CHECK_STR(c_name, "get_name"); c_name = krb5_cc_get_type(context, id); CHECK_STR(c_name, "get_type"); save_type=strdup(c_name); CHECK_STR(save_type, "copying type"); kret = krb5_cc_store_cred(context, id, &test_creds); CHECK(kret, "store"); kret = krb5_cc_get_principal(context, id, &tmp); CHECK(kret, "get_principal"); CHECK_BOOL(krb5_realm_compare(context, tmp, test_creds.client) != TRUE, "realms do not match", "realm_compare"); CHECK_BOOL(krb5_principal_compare(context, tmp, test_creds.client) != TRUE, "principals do not match", "principal_compare"); krb5_free_principal(context, tmp); kret = krb5_cc_set_flags (context, id, flags); CHECK(kret, "set_flags"); kret = krb5_cc_start_seq_get(context, id, &cursor); CHECK(kret, "start_seq_get"); kret = 0; while (kret != KRB5_CC_END) { if(debug) printf("Calling next_cred\n"); kret = krb5_cc_next_cred(context, id, &cursor, &creds); if(kret == KRB5_CC_END) { if(debug) printf("next_cred: ok at end\n"); } else { CHECK(kret, "next_cred"); krb5_free_cred_contents(context, &creds); } } kret = krb5_cc_end_seq_get(context, id, &cursor); CHECK(kret, "end_seq_get"); kret = krb5_cc_close(context, id); CHECK(kret, "close"); /* ------------------------------------------------- */ kret = krb5_cc_resolve(context, name, &id); CHECK(kret, "resolve2"); { /* Copy the cache test*/ snprintf(newcache, sizeof(newcache), "%s.new", name); kret = krb5_cc_resolve(context, newcache, &id2); CHECK(kret, "resolve of new cache"); /* This should fail as the new creds are not initialized */ kret = krb5_cc_copy_creds(context, id, id2); CHECK_FAIL(KRB5_FCC_NOFILE, kret, "copy_creds"); kret = krb5_cc_initialize(context, id2, test_creds.client); CHECK(kret, "initialize of id2"); kret = krb5_cc_copy_creds(context, id, id2); CHECK(kret, "copy_creds"); kret = krb5_cc_destroy(context, id2); CHECK(kret, "destroy new cache"); } /* Destroy the first cache */ kret = krb5_cc_destroy(context, id); CHECK(kret, "destroy"); /* ----------------------------------------------------- */ /* Tests the generate new code */ kret = krb5_cc_new_unique(context, save_type, NULL, &id2); CHECK(kret, "new_unique"); kret = krb5_cc_initialize(context, id2, test_creds.client); CHECK(kret, "initialize"); kret = krb5_cc_store_cred(context, id2, &test_creds); CHECK(kret, "store"); kret = krb5_cc_destroy(context, id2); CHECK(kret, "destroy id2"); free(save_type); free_test_cred(context); }
static OM_uint32 gsskrb5_accept_delegated_token (OM_uint32 * minor_status, gsskrb5_ctx ctx, krb5_context context, gss_cred_id_t * delegated_cred_handle ) { krb5_ccache ccache = NULL; krb5_error_code kret; int32_t ac_flags, ret = GSS_S_COMPLETE; *minor_status = 0; /* XXX Create a new delegated_cred_handle? */ if (delegated_cred_handle == NULL) { kret = krb5_cc_default (context, &ccache); } else { *delegated_cred_handle = NULL; kret = krb5_cc_new_unique (context, krb5_cc_type_memory, NULL, &ccache); } if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } kret = krb5_cc_initialize(context, ccache, ctx->source); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } krb5_auth_con_removeflags(context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_TIME, &ac_flags); kret = krb5_rd_cred2(context, ctx->auth_context, ccache, &ctx->fwd_data); krb5_auth_con_setflags(context, ctx->auth_context, ac_flags); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; ret = GSS_S_FAILURE; *minor_status = kret; goto out; } if (delegated_cred_handle) { gsskrb5_cred handle; ret = _gsskrb5_krb5_import_cred(minor_status, ccache, NULL, NULL, delegated_cred_handle); if (ret != GSS_S_COMPLETE) goto out; handle = (gsskrb5_cred) *delegated_cred_handle; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; krb5_cc_close(context, ccache); ccache = NULL; } out: if (ccache) { /* Don't destroy the default cred cache */ if (delegated_cred_handle == NULL) krb5_cc_close(context, ccache); else krb5_cc_destroy(context, ccache); } 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 int CommandProc(struct cmd_syndesc *as, void *arock) { krb5_principal princ = 0; char *cell, *pname, **hrealms, *service; char service_temp[MAXKTCREALMLEN + 20]; krb5_creds incred[1], mcred[1], *outcred = 0, *afscred; krb5_ccache cc = 0; #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC krb5_get_init_creds_opt *gic_opts; #else krb5_get_init_creds_opt gic_opts[1]; #endif char *tofree = NULL, *outname; int code; char *what; int i, dosetpag, evil, noprdb, id; #ifdef AFS_RXK5 int authtype; #endif krb5_data enc_part[1]; krb5_prompter_fct pf = NULL; char *pass = 0; void *pa = 0; struct kp_arg klog_arg[1]; char passwd[BUFSIZ]; struct afsconf_cell cellconfig[1]; static char rn[] = "klog"; /*Routine name */ static int Pipe = 0; /* reading from a pipe */ static int Silent = 0; /* Don't want error messages */ int writeTicketFile = 0; /* write ticket file to /tmp */ service = 0; memset(incred, 0, sizeof *incred); /* blow away command line arguments */ for (i = 1; i < zero_argc; i++) memset(zero_argv[i], 0, strlen(zero_argv[i])); zero_argc = 0; memset(klog_arg, 0, sizeof *klog_arg); /* first determine quiet flag based on -silent switch */ Silent = (as->parms[aSILENT].items ? 1 : 0); if (Silent) { afs_set_com_err_hook(silent_errors); } if ((code = krb5_init_context(&k5context))) { afs_com_err(rn, code, "while initializing Kerberos 5 library"); KLOGEXIT(code); } if ((code = rx_Init(0))) { afs_com_err(rn, code, "while initializing rx"); KLOGEXIT(code); } initialize_U_error_table(); /*initialize_krb5_error_table();*/ initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); /* initialize_rx_error_table(); */ if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))", AFSDIR_CLIENT_ETC_DIRPATH); KLOGEXIT(1); } /* * Enable DES enctypes, which are currently still required for AFS. * krb5_allow_weak_crypto is MIT Kerberos 1.8. krb5_enctype_enable is * Heimdal. */ #if defined(HAVE_KRB5_ENCTYPE_ENABLE) i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC); if (i) krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC); #elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO) krb5_allow_weak_crypto(k5context, 1); #endif /* Parse remaining arguments. */ dosetpag = !! as->parms[aSETPAG].items; Pipe = !! as->parms[aPIPE].items; writeTicketFile = !! as->parms[aTMP].items; noprdb = !! as->parms[aNOPRDB].items; evil = (always_evil&1) || !! as->parms[aUNWRAP].items; #ifdef AFS_RXK5 authtype = 0; if (as->parms[aK5].items) authtype |= FORCE_RXK5; if (as->parms[aK4].items) authtype |= FORCE_RXKAD; if (!authtype) authtype |= env_afs_rxk5_default(); #endif cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0; if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) { if (cell) afs_com_err(rn, code, "Can't get cell information for '%s'", cell); else afs_com_err(rn, code, "Can't get determine local cell!"); KLOGEXIT(code); } if (as->parms[aKRBREALM].items) { code = krb5_set_default_realm(k5context, as->parms[aKRBREALM].items->data); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", as->parms[aKRBREALM].items->data); KLOGEXIT(code); } } else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) { afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n", cellconfig->hostName[0], cellconfig->name); KLOGEXIT(code); } else { if (hrealms && *hrealms) { code = krb5_set_default_realm(k5context, *hrealms); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", *hrealms); KLOGEXIT(code); } } if (hrealms) krb5_free_host_realm(k5context, hrealms); } id = getuid(); if (as->parms[aPRINCIPAL].items) { pname = as->parms[aPRINCIPAL].items->data; } else { /* No explicit name provided: use Unix uid. */ struct passwd *pw; pw = getpwuid(id); if (pw == 0) { afs_com_err(rn, 0, "Can't figure out your name from your user id (%d).", id); if (!Silent) fprintf(stderr, "%s: Try providing the user name.\n", rn); KLOGEXIT(1); } pname = pw->pw_name; } code = krb5_parse_name(k5context, pname, &princ); if (code) { afs_com_err(rn, code, "Can't parse principal <%s>", pname); KLOGEXIT(code); } if (as->parms[aPASSWORD].items) { /* * Current argument is the desired password string. Remember it in * our local buffer, and zero out the argument string - anyone can * see it there with ps! */ strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); memset(as->parms[aPASSWORD].items->data, 0, strlen(as->parms[aPASSWORD].items->data)); pass = passwd; } /* Get the password if it wasn't provided. */ if (!pass) { if (Pipe) { strncpy(passwd, getpipepass(), sizeof(passwd)); pass = passwd; } else { pf = klog_prompter; pa = klog_arg; } } service = 0; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { tofree = get_afs_krb5_svc_princ(cellconfig); snprintf(service_temp, sizeof service_temp, "%s", tofree); } else #endif snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name); klog_arg->pp = &pass; klog_arg->pstore = passwd; klog_arg->allocated = sizeof(passwd); /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/ #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts); if (code) { afs_com_err(rn, code, "Can't allocate get_init_creds options"); KLOGEXIT(code); } #else krb5_get_init_creds_opt_init(gic_opts); #endif for (;;) { code = krb5_get_init_creds_password(k5context, incred, princ, pass, pf, /* prompter */ pa, /* data */ 0, /* start_time */ 0, /* in_tkt_service */ gic_opts); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) break; } memset(passwd, 0, sizeof(passwd)); if (code) { char *r = 0; if (krb5_get_default_realm(k5context, &r)) r = 0; if (r) afs_com_err(rn, code, "Unable to authenticate in realm %s", r); else afs_com_err(rn, code, "Unable to authenticate to use cell %s", cellconfig->name); if (r) free(r); KLOGEXIT(code); } for (;;writeTicketFile = 0) { if (writeTicketFile) { what = "getting default ccache"; code = krb5_cc_default(k5context, &cc); } else { what = "krb5_cc_resolve"; code = krb5_cc_resolve(k5context, "MEMORY:core", &cc); if (code) goto Failed; } what = "initializing ccache"; code = krb5_cc_initialize(k5context, cc, princ); if (code) goto Failed; what = "writing Kerberos ticket file"; code = krb5_cc_store_cred(k5context, cc, incred); if (code) goto Failed; if (writeTicketFile) fprintf(stderr, "Wrote ticket file to %s\n", krb5_cc_get_name(k5context, cc)); break; Failed: if (code) afs_com_err(rn, code, "%s", what); if (writeTicketFile) { if (cc) { krb5_cc_close(k5context, cc); cc = 0; } continue; } KLOGEXIT(code); } for (service = service_temp;;service = "afs") { memset(mcred, 0, sizeof *mcred); mcred->client = princ; code = krb5_parse_name(k5context, service, &mcred->server); if (code) { afs_com_err(rn, code, "Unable to parse service <%s>\n", service); KLOGEXIT(code); } if (tofree) { free(tofree); tofree = 0; } if (!(code = krb5_unparse_name(k5context, mcred->server, &outname))) tofree = outname; else outname = service; code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred); krb5_free_principal(k5context, mcred->server); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) break; #endif } afscred = outcred; if (code) { afs_com_err(rn, code, "Unable to get credentials to use %s", outname); KLOGEXIT(code); } #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { struct ktc_principal aserver[1]; int viceid = 555; memset(aserver, 0, sizeof *aserver); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } else #endif { struct ktc_principal aserver[1], aclient[1]; struct ktc_token atoken[1]; memset(atoken, 0, sizeof *atoken); if (evil) { size_t elen = enc_part->length; atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data, afscred->ticket.length, (char **) &enc_part->data, &elen)) { afs_com_err(rn, 0, "Can't unwrap %s AFS credential", cellconfig->name); KLOGEXIT(1); } } else { atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; *enc_part = afscred->ticket; } atoken->startTime = afscred->times.starttime; atoken->endTime = afscred->times.endtime; if (tkt_DeriveDesKey(get_creds_enctype(afscred), get_cred_keydata(afscred), get_cred_keylen(afscred), &atoken->sessionKey)) { afs_com_err(rn, 0, "Cannot derive DES key from enctype %i of length %u", get_creds_enctype(afscred), (unsigned)get_cred_keylen(afscred)); KLOGEXIT(1); } memcpy(atoken->ticket, enc_part->data, atoken->ticketLen = enc_part->length); memset(aserver, 0, sizeof *aserver); strncpy(aserver->name, "afs", 4); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); memset(aclient, 0, sizeof *aclient); i = realm_len(k5context, afscred->client); if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1; memcpy(aclient->cell, realm_data(k5context, afscred->client), i); if (!noprdb) { int viceid = 0; k5_to_k4_name(k5context, afscred->client, aclient); code = whoami(atoken, cellconfig, aclient, &viceid); if (code) { afs_com_err(rn, code, "Can't get your viceid for cell %s", cellconfig->name); *aclient->name = 0; } else snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid); } if (!*aclient->name) k5_to_k4_name(k5context, afscred->client, aclient); code = ktc_SetToken(aserver, atoken, aclient, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } krb5_free_principal(k5context, princ); krb5_free_cred_contents(k5context, incred); if (outcred) krb5_free_creds(k5context, outcred); if (cc) krb5_cc_close(k5context, cc); if (tofree) free(tofree); return 0; }
static int32_t acquire_cred(struct client *c, krb5_principal principal, krb5_get_init_creds_opt *opt, int32_t *handle) { krb5_error_code ret; krb5_creds cred; krb5_ccache id; gss_cred_id_t gcred; OM_uint32 maj_stat, min_stat; *handle = 0; krb5_get_init_creds_opt_set_forwardable (opt, 1); krb5_get_init_creds_opt_set_renew_life (opt, 3600 * 24 * 30); memset(&cred, 0, sizeof(cred)); ret = krb5_get_init_creds_password (context, &cred, principal, NULL, NULL, NULL, 0, NULL, opt); if (ret) { logmessage(c, __FILE__, __LINE__, 0, "krb5_get_init_creds failed: %d", ret); return convert_krb5_to_gsm(ret); } ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_initialize (context, id, cred.client); 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); maj_stat = gss_krb5_import_cred(&min_stat, id, NULL, NULL, &gcred); krb5_cc_close(context, id); if (maj_stat) { logmessage(c, __FILE__, __LINE__, 0, "krb5 import creds failed with: %d", maj_stat); return convert_gss_to_gsm(maj_stat); } *handle = add_handle(c, handle_cred, gcred); return 0; }
/* Free a disk-based ccache */ static int free_dccache(struct ccache_container *ccc) { krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache); return 0; }
int mr_krb5_auth(char *prog) { mr_params params, reply; char host[BUFSIZ], *p; char *args[2]; int argl[2]; krb5_ccache ccache = NULL; krb5_data auth; krb5_error_code problem = 0; CHECK_CONNECTED; memset(&auth, 0, sizeof(auth)); if ((problem = mr_host(host, sizeof(host) - 1))) return problem; if (!context) { problem = krb5_init_context(&context); if (problem) goto out; } problem = krb5_auth_con_init(context, &auth_con); if (problem) goto out; problem = krb5_cc_default(context, &ccache); if (problem) goto out; problem = krb5_mk_req(context, &auth_con, 0, MOIRA_SNAME, host, NULL, ccache, &auth); if (problem) goto out; params.u.mr_procno = MR_KRB5_AUTH; params.mr_argc = 2; params.mr_argv = args; params.mr_argl = argl; params.mr_argv[0] = (char *)auth.data; params.mr_argl[0] = auth.length; params.mr_argv[1] = prog; params.mr_argl[1] = strlen(prog) + 1; if ((problem = mr_do_call(¶ms, &reply)) == MR_SUCCESS) problem = reply.u.mr_status; mr_destroy_reply(reply); out: if (ccache) krb5_cc_close(context, ccache); krb5_free_data_contents(context, &auth); if (auth_con) krb5_auth_con_free(context, auth_con); auth_con = NULL; return problem; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_store_cred(OM_uint32 *minor_status, gss_cred_id_t input_cred_handle, gss_cred_usage_t cred_usage, const gss_OID desired_mech, OM_uint32 overwrite_cred, OM_uint32 default_cred, gss_OID_set *elements_stored, gss_cred_usage_t *cred_usage_stored) { krb5_context context; krb5_error_code ret; gsskrb5_cred cred; krb5_ccache id; int destroy = 0; *minor_status = 0; if (cred_usage != GSS_C_INITIATE) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) return GSS_S_BAD_MECH; cred = (gsskrb5_cred)input_cred_handle; if (cred == NULL) return GSS_S_NO_CRED; GSSAPI_KRB5_INIT (&context); HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = GSS_KRB5_S_G_BAD_USAGE; return(GSS_S_FAILURE); } if (cred->principal == NULL) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = GSS_KRB5_S_KG_TGT_MISSING; return(GSS_S_FAILURE); } /* write out cred to credential cache */ ret = krb5_cc_cache_match(context, cred->principal, &id); if (ret) { ret = krb5_cc_new_unique(context, NULL, NULL, &id); if (ret) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = ret; return(GSS_S_FAILURE); } destroy = 1; } ret = krb5_cc_initialize(context, id, cred->principal); if (ret == 0) ret = krb5_cc_copy_match_f(context, cred->ccache, id, NULL, NULL, NULL); if (ret) { if (destroy) krb5_cc_destroy(context, id); else krb5_cc_close(context, id); HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = ret; return(GSS_S_FAILURE); } if (default_cred) krb5_cc_switch(context, id); krb5_cc_close(context, id); HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = 0; return GSS_S_COMPLETE; }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *principal, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; krb5_principal princ = NULL; krb5_ccache ccache = NULL; int result_code; krb5_data result_code_string = { 0 }; krb5_data result_string = { 0 }; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (principal) { ret = smb_krb5_parse_name(context, principal, &princ); if (ret) { krb5_free_context(context); DEBUG(1, ("Failed to parse %s (%s)\n", principal, error_message(ret))); return ADS_ERROR_KRB5(ret); } } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_principal(context, princ); krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_set_password_using_ccache(context, ccache, discard_const_p(char, newpw), princ, &result_code, &result_code_string, &result_string); if (ret) { DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } if (result_code != KRB5_KPASSWD_SUCCESS) { ret = kpasswd_err_to_krb5_err(result_code); DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } aret = ADS_SUCCESS; done: kerberos_free_data_contents(context, &result_code_string); kerberos_free_data_contents(context, &result_string); krb5_free_principal(context, princ); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
static krb5_error_code login_perform_kinit (krb5_context k5, const gchar *realm, const gchar *login, const gchar *password, const gchar *filename) { krb5_get_init_creds_opt *opts; krb5_error_code code; krb5_principal principal; krb5_ccache ccache; krb5_creds creds; gchar *name; name = g_strdup_printf ("%s@%s", login, realm); code = krb5_parse_name (k5, name, &principal); if (code != 0) { g_debug ("Couldn't parse principal name: %s: %s", name, krb5_get_error_message (k5, code)); g_free (name); return code; } g_debug ("Using principal name to kinit: %s", name); g_free (name); if (filename == NULL) code = krb5_cc_default (k5, &ccache); else code = krb5_cc_resolve (k5, filename, &ccache); if (code != 0) { krb5_free_principal (k5, principal); g_debug ("Couldn't open credential cache: %s: %s", filename ? filename : "<default>", krb5_get_error_message (k5, code)); return code; } code = krb5_get_init_creds_opt_alloc (k5, &opts); g_return_val_if_fail (code == 0, code); code = krb5_get_init_creds_opt_set_out_ccache (k5, opts, ccache); g_return_val_if_fail (code == 0, code); code = krb5_get_init_creds_password (k5, &creds, principal, (char *)password, NULL, 0, 0, NULL, opts); krb5_get_init_creds_opt_free (k5, opts); krb5_cc_close (k5, ccache); krb5_free_principal (k5, principal); if (code == 0) { g_debug ("kinit succeeded"); krb5_free_cred_contents (k5, &creds); } else { g_debug ("kinit failed: %s", krb5_get_error_message (k5, code)); } return code; }
int main(int argc, char **argv) { int log_level = 0; char *ap_req_str = NULL; /* krb5 */ krb5_error_code ret; krb5_context context; krb5_auth_context auth_context; char *princ_str_tn = "kink/tn.example.com"; krb5_principal princ_tn; char *princ_str_nut = "kink/nut.example.com"; krb5_principal princ_nut; char *princ_str_krbtgt = "krbtgt/EXAMPLE.COM"; krb5_principal princ_krbtgt; krb5_ccache ccache; krb5_keytab keytab; krb5_creds creds_tgt; krb5_data ap_req; prog = (const char *) basename(argv[0]); if (prog == NULL) { fprintf(stderr, "basename: %s -- %s\n", strerror(errno), argv[0]); return(0); /* NOTREACHED */ } { int ch = 0; while ((ch = getopt(argc, argv, "dq:")) != -1) { switch (ch) { case 'd': log_level++; break; case 'q': ap_req_str = optarg; break; default: usage(); /* NOTREACHED */ break; } } argc -= optind; argv += optind; } if (argc) { usage(); /* NOTREACHED */ } { printf("dbg: %s starts\n", prog); } if (ap_req_str != NULL) { hex2krb5data(ap_req_str, &ap_req); if (log_level) { dump_krb5_data(&ap_req); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)ap_req.data; printf("std:ap_req:"); for (i = 0; i < ap_req.length; i++) { printf("%02x", *p++); } printf("\n"); } } /* prepare krb5 context */ { /** init context */ ret = krb5_init_context(&context); if (ret != 0) { printf("ERR:krb5_init_context:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** setup principals */ ret = krb5_parse_name(context, princ_str_tn, &princ_tn); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_nut, &princ_nut); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_krbtgt, &princ_krbtgt); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare credential cache */ ret = krb5_cc_default(context, &ccache); if (ret != 0) { printf("ERR:krb5_cc_default:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare keytab */ /*ret = krb5_kt_resolve(context, "/usr/local/var/krb5kdc/kadm5.keytab", &keytab);*/ ret = krb5_kt_default(context, &keytab); if (ret != 0) { /* printf("ERR:krb5_kt_default:%s", krb5_get_err_text(context, ret)); */ printf("ERR:krb5_kt_resolve:%s", krb5_get_err_text(context, ret)); return(ret); } } /* get TGT */ { krb5_creds mcreds; memset(&mcreds, 0, sizeof(mcreds)); mcreds.client = princ_tn; mcreds.server = princ_krbtgt; ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds_tgt); if (ret != 0) { printf("ERR:krb5_cc_retrieve_cred:%s\n", krb5_get_err_text(context, ret)); return(ret); } } /* prepare authentiation context */ { ret = krb5_auth_con_init(context, &auth_context); if (ret != 0) { printf("ERR:krb5_auth_con_init:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret != 0) { printf("ERR:krb5_auth_con_setflags:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* if USE_SKEY */ /* ret = krb5_auth_con_setuserkey(context, auth_context, &creds_tgt.session); if (ret != 0) { printf("ERR:krb5_auth_con_setuseruserkey:%s\n", krb5_get_err_text(context, ret)); return(ret); } */ } /* set keyblock in auth_context */ { krb5_ticket *ticket; krb5_flags ap_req_options; ap_req_options = AP_OPTS_MUTUAL_REQUIRED; ticket = NULL; ret = krb5_rd_req(context, &auth_context, &ap_req, NULL, keytab, &ap_req_options, &ticket); if (log_level) { printf("info: ticket.ticket.key is SKEYID_d\n"); /*dump_krb5_ticket(context, *ticket);*/ } if (log_level) { printf("ap_req_opt (%d)\n", ap_req_options); } if (ret != 0) { printf("ERR:krb5_rd_req:%s\n", krb5_get_err_text(context, ret)); return(ret); } if (log_level) { dump_krb5_keyblock(auth_context->keyblock); } krb5_free_ticket(context, ticket); } /* make AP_REP */ { krb5_data ap_rep; ret = krb5_mk_rep(context, auth_context, &ap_rep); if (ret != 0) { printf("ERR:krb5_mk_rep:%s\n", krb5_get_err_text(context, ret)); return(ret); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)ap_rep.data; printf("std:ap_rep:"); for (i = 0; i < ap_rep.length; i++) { printf("%02x", *p++); } printf("\n"); } } /* clenaup */ { /*free(data);*/ /*krb5_data_free(&ap_req);*/ krb5_free_cred_contents(context, &creds_tgt); ret = krb5_kt_close(context, keytab); if (ret != 0) { printf("ERR:krb5_kt_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_cc_close(context, ccache); if (ret != 0) { printf("ERR:krb5_cc_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } krb5_free_principal(context, princ_krbtgt); krb5_free_principal(context, princ_nut); krb5_free_principal(context, princ_tn); krb5_free_context(context); } return(0); }
krb5_error_code KRB5_LIB_FUNCTION krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer p_fd, const char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **ret_error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) { krb5_error_code ret; uint32_t len, net_len; const char *version = KRB5_SENDAUTH_VERSION; u_char repl; krb5_data ap_req, error_data; krb5_creds this_cred; krb5_principal this_client = NULL; krb5_creds *creds; ssize_t sret; krb5_boolean my_ccache = FALSE; len = strlen(version) + 1; net_len = htonl(len); if (krb5_net_write (context, p_fd, &net_len, 4) != 4 || krb5_net_write (context, p_fd, version, len) != len) { ret = errno; krb5_set_error_string (context, "write: %s", strerror(ret)); return ret; } len = strlen(appl_version) + 1; net_len = htonl(len); if (krb5_net_write (context, p_fd, &net_len, 4) != 4 || krb5_net_write (context, p_fd, appl_version, len) != len) { ret = errno; krb5_set_error_string (context, "write: %s", strerror(ret)); return ret; } sret = krb5_net_read (context, p_fd, &repl, sizeof(repl)); if (sret < 0) { ret = errno; krb5_set_error_string (context, "read: %s", strerror(ret)); return ret; } else if (sret != sizeof(repl)) { krb5_clear_error_string (context); return KRB5_SENDAUTH_BADRESPONSE; } if (repl != 0) { krb5_clear_error_string (context); return KRB5_SENDAUTH_REJECTED; } if (in_creds == NULL) { if (ccache == NULL) { ret = krb5_cc_default (context, &ccache); if (ret) return ret; my_ccache = TRUE; } if (client == NULL) { ret = krb5_cc_get_principal (context, ccache, &this_client); if (ret) { if(my_ccache) krb5_cc_close(context, ccache); return ret; } client = this_client; } memset(&this_cred, 0, sizeof(this_cred)); this_cred.client = client; this_cred.server = server; this_cred.times.endtime = 0; this_cred.ticket.length = 0; in_creds = &this_cred; } if (in_creds->ticket.length == 0) { ret = krb5_get_credentials (context, 0, ccache, in_creds, &creds); if (ret) { if(my_ccache) krb5_cc_close(context, ccache); return ret; } } else { creds = in_creds; } if(my_ccache) krb5_cc_close(context, ccache); ret = krb5_mk_req_extended (context, auth_context, ap_req_options, in_data, creds, &ap_req); if (out_creds) *out_creds = creds; else krb5_free_creds(context, creds); if(this_client) krb5_free_principal(context, this_client); if (ret) return ret; ret = krb5_write_message (context, p_fd, &ap_req); if (ret) return ret; krb5_data_free (&ap_req); ret = krb5_read_message (context, p_fd, &error_data); if (ret) return ret; if (error_data.length != 0) { KRB_ERROR error; ret = krb5_rd_error (context, &error_data, &error); krb5_data_free (&error_data); if (ret == 0) { ret = krb5_error_from_rd_error(context, &error, NULL); if (ret_error != NULL) { *ret_error = malloc (sizeof(krb5_error)); if (*ret_error == NULL) { krb5_free_error_contents (context, &error); } else { **ret_error = error; } } else { krb5_free_error_contents (context, &error); } return ret; } else { krb5_clear_error_string(context); return ret; } } if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) { krb5_data ap_rep; krb5_ap_rep_enc_part *ignore; krb5_data_zero (&ap_rep); ret = krb5_read_message (context, p_fd, &ap_rep); if (ret) return ret; ret = krb5_rd_rep (context, *auth_context, &ap_rep, rep_result ? rep_result : &ignore); krb5_data_free (&ap_rep); if (ret) return ret; if (rep_result == NULL) krb5_free_ap_rep_enc_part (context, ignore); } return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache src_cc = NULL; krb5_ccache dst_cc = NULL; krb5_cc_cursor cursor; krb5_principal me = NULL; krb5_creds cred; const char *during; Ticket t; size_t len; int make_kvno_absent = 0; int opt; memset(&cred, 0, sizeof (cred)); during = "init_context"; ret = krb5_init_context(&context); if (ret) goto err; while ((opt = getopt(argc, argv, "c:n")) != -1) { switch (opt) { case 'c': during = "cc_resolve of source ccache"; ret = krb5_cc_resolve(context, optarg, &src_cc); if (ret) goto err; break; case 'n': make_kvno_absent++; break; case 'h': default: fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } } if (!src_cc) { during = "cc_default"; ret = krb5_cc_default(context, &src_cc); if (ret) goto err; } during = "cc_get_principal"; ret = krb5_cc_get_principal(context, src_cc, &me); if (ret) goto err; if (optind != argc) { fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } during = "cc_new_unique of temporary ccache"; ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, src_cc), NULL, &dst_cc); during = "cc_initialize of temporary ccache"; ret = krb5_cc_initialize(context, dst_cc, me); if (ret) goto err; during = "cc_start_seq_get"; ret = krb5_cc_start_seq_get(context, src_cc, &cursor); if (ret) goto err; while ((ret = krb5_cc_next_cred(context, src_cc, &cursor, &cred)) == 0) { krb5_data data; during = "decode_Ticket"; memset(&t, 0, sizeof (t)); ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len); if (ret == ASN1_MISSING_FIELD) continue; if (ret) goto err; if (t.enc_part.kvno) { *t.enc_part.kvno = 0; if (make_kvno_absent) { free(t.enc_part.kvno); t.enc_part.kvno = NULL; } /* * The new Ticket has to need less or same space as before, so * we reuse cred->icket.data. */ during = "encode_Ticket"; ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, &t, &len, ret); if (ret) { free_Ticket(&t); goto err; } krb5_data_free(&cred.ticket); cred.ticket = data; } free_Ticket(&t); during = "cc_store_cred"; ret = krb5_cc_store_cred(context, dst_cc, &cred); if (ret) goto err; krb5_free_cred_contents(context, &cred); memset(&cred, 0, sizeof (cred)); } during = "cc_next_cred"; if (ret != KRB5_CC_END) goto err; during = "cc_end_seq_get"; ret = krb5_cc_end_seq_get(context, src_cc, &cursor); if (ret) goto err; during = "cc_move"; ret = krb5_cc_move(context, dst_cc, src_cc); if (ret) goto err; dst_cc = NULL; during = "cc_switch"; ret = krb5_cc_switch(context, src_cc); if (ret) goto err; err: (void) krb5_free_principal(context, me); if (src_cc) (void) krb5_cc_close(context, src_cc); if (dst_cc) (void) krb5_cc_destroy(context, dst_cc); if (ret) { fprintf(stderr, "Failed while doing %s (%d)\n", during, ret); ret = 1; } return (ret); }
static void do_v5_kvno (int count, char *names[], char * ccache_name, char *etype_str, char *keytab_name, char *sname) { krb5_error_code ret; krb5_context context = 0; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; krb5_creds in_creds, *out_creds = NULL; Ticket ticket; size_t len; char *princ = NULL; krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if (etype_str) { ret = krb5_string_to_enctype(context, etype_str, &etype); if (ret) krb5_err(context, 1, ret, "Failed to convert encryption type %s", etype_str); } else { etype = 0; } if (ccache_name) ret = krb5_cc_resolve(context, ccache_name, &ccache); else ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, "Failed to open credentials cache %s", (ccache_name) ? ccache_name : "(Default)"); if (keytab_name) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) krb5_err(context, 1, ret, "Can't resolve keytab %s", keytab_name); } ret = krb5_cc_get_principal(context, ccache, &me); if (ret) krb5_err(context, 1, ret, "krb5_cc_get_principal"); errors = 0; for (i = 0; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); memset(&ticket, 0, sizeof(ticket)); in_creds.client = me; if (sname != NULL) { ret = krb5_sname_to_principal(context, names[i], sname, KRB5_NT_SRV_HST, &in_creds.server); } else { ret = krb5_parse_name(context, names[i], &in_creds.server); } if (ret) { if (!quiet_flag) krb5_warn(context, ret, "Couldn't parse principal name %s", names[i]); errors++; continue; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { krb5_warn(context, ret, "Couldn't format parsed principal name for '%s'", names[i]); errors++; goto next; } in_creds.session.keytype = etype; ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds); if (ret) { krb5_warn(context, ret, "Couldn't get credentials for %s", princ); errors++; goto next; } ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length, &ticket, &len); if (ret) { krb5_err(context, 1, ret, "Can't decode ticket for %s", princ); errors++; goto next; continue; } if (keytab) { krb5_keytab_entry kte; krb5_crypto crypto; krb5_data dec_data; EncTicketPart decr_part; ret = krb5_kt_get_entry(context, keytab, in_creds.server, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0, ticket.enc_part.etype, &kte); if (ret) { krb5_warn(context, ret, "Can't decrypt ticket for %s", princ); if (!quiet_flag) printf("%s: kvno = %d, keytab entry invalid", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); errors ++; goto next; } ret = krb5_crypto_init(context, &kte.keyblock, 0, &crypto); if (ret) { krb5_warn(context, ret, "krb5_crypto_init"); errors ++; krb5_kt_free_entry(context, &kte); goto next; } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET, &ticket.enc_part, &dec_data); krb5_crypto_destroy(context, crypto); krb5_kt_free_entry(context, &kte); if (ret) { krb5_warn(context, ret, "krb5_decrypt_EncryptedData"); errors ++; goto next; } ret = decode_EncTicketPart(dec_data.data, dec_data.length, &decr_part, &len); krb5_data_free(&dec_data); if (ret) { krb5_warn(context, ret, "decode_EncTicketPart"); errors ++; goto next; } if (!quiet_flag) printf("%s: kvno = %d, keytab entry valid\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); free_EncTicketPart(&decr_part); } else { if (!quiet_flag) printf("%s: kvno = %d\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); } next: if (out_creds) { krb5_free_creds(context, out_creds); out_creds = NULL; } if (princ) { krb5_free_unparsed_name(context, princ); princ = NULL; } krb5_free_principal(context, in_creds.server); free_Ticket(&ticket); } if (keytab) krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_cc_close(context, ccache); krb5_free_context(context); if (errors) exit(1); exit(0); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds *out; int optidx = 0; int32_t nametype = KRB5_NT_UNKNOWN; krb5_get_creds_opt opt; krb5_principal server = NULL; krb5_principal impersonate; setprogname(argv[0]); ret = krb5_init_context(&context); 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 (debug_flag) { ret = krb5_set_debug_dest(context, getprogname(), "STDERR"); if (ret) krb5_warn(context, ret, "krb5_set_debug_dest"); } if (cache_str) { ret = krb5_cc_resolve(context, cache_str, &cache); if (ret) krb5_err(context, 1, ret, "%s", cache_str); } else { ret = krb5_cc_default (context, &cache); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); } ret = krb5_get_creds_opt_alloc(context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_creds_opt_alloc"); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx(context, 1, N_("unrecognized enctype: %s", ""), etype_str); krb5_get_creds_opt_set_enctype(context, opt, enctype); } if (impersonate_str) { ret = krb5_parse_name(context, impersonate_str, &impersonate); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", impersonate_str); krb5_get_creds_opt_set_impersonate(context, opt, impersonate); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); krb5_free_principal(context, impersonate); } if (out_cache_str) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (forwardable_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE); if (!transit_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK); if (canonicalize_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE); if (!store_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (cached_only_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CACHED); if (delegation_cred_str) { krb5_ccache id; krb5_creds c, mc; Ticket ticket; krb5_cc_clear_mcred(&mc); ret = krb5_cc_get_principal(context, cache, &mc.server); if (ret) krb5_err(context, 1, ret, "krb5_cc_get_principal"); ret = krb5_cc_resolve(context, delegation_cred_str, &id); if(ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c); if(ret) krb5_err(context, 1, ret, "krb5_cc_retrieve_cred"); ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL); if (ret) { krb5_clear_error_message(context); krb5_err(context, 1, ret, "decode_Ticket"); } krb5_free_cred_contents(context, &c); ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket); if(ret) krb5_err(context, 1, ret, "krb5_get_creds_opt_set_ticket"); free_Ticket(&ticket); krb5_cc_close(context, id); krb5_free_principal(context, mc.server); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CONSTRAINED_DELEGATION); } if (nametype_str != NULL) { ret = krb5_parse_nametype(context, nametype_str, &nametype); if (ret) krb5_err(context, 1, ret, "krb5_parse_nametype"); } if (nametype == KRB5_NT_SRV_HST || nametype == KRB5_NT_SRV_HST_NEEDS_CANON) is_hostbased_flag = 1; if (is_hostbased_flag) { const char *sname = NULL; const char *hname = NULL; if (nametype_str != NULL && nametype != KRB5_NT_SRV_HST && nametype != KRB5_NT_SRV_HST_NEEDS_CANON) krb5_errx(context, 1, "--hostbased not compatible with " "non-hostbased --name-type"); if (is_canonical_flag) nametype = KRB5_NT_SRV_HST; else nametype = KRB5_NT_SRV_HST_NEEDS_CANON; /* * Host-based service names can have more than one component. * * RFC5179 did not, but should have, assign a Kerberos name-type * corresponding to GSS_C_NT_DOMAINBASED. But it's basically a * host-based service name type with one additional component. * * So that's how we're treating host-based service names here: * two or more components. */ if (argc == 0) { usage(1); } else if (argc == 1) { krb5_principal server2; /* * In this case the one argument is a principal name, not the * service name. * * We parse the argument as a principal name, extract the service * and hostname components, use krb5_sname_to_principal(), then * extract the service and hostname components from that. */ ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]); sname = krb5_principal_get_comp_string(context, server, 0); /* * If a single-component principal name is given, then we'll * default the hostname, as krb5_principal_get_comp_string() * returns NULL in this case. */ hname = krb5_principal_get_comp_string(context, server, 1); ret = krb5_sname_to_principal(context, hname, sname, KRB5_NT_SRV_HST, &server2); sname = krb5_principal_get_comp_string(context, server2, 0); hname = krb5_principal_get_comp_string(context, server2, 1); /* * Modify the original with the new sname/hname. This way we * retain any additional principal name components from the given * principal name. * * The name-type is set further below. */ ret = krb5_principal_set_comp_string(context, server, 0, sname); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]); ret = krb5_principal_set_comp_string(context, server, 1, hname); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]); krb5_free_principal(context, server2); } else { size_t i; /* * In this case the arguments are principal name components. * * The service and hostname components can be defaulted by passing * empty strings. */ sname = argv[0]; if (*sname == '\0') sname = NULL; hname = argv[1]; if (hname == NULL || *hname == '\0') hname = NULL; ret = krb5_sname_to_principal(context, hname, sname, KRB5_NT_SRV_HST, &server); if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal"); for (i = 2; i < argc; i++) { ret = krb5_principal_set_comp_string(context, server, i, argv[i]); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string"); } } } else if (argc == 1) { ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]); } else { usage(1); } if (nametype != KRB5_NT_UNKNOWN) server->name.name_type = (NAME_TYPE)nametype; ret = krb5_get_creds(context, opt, cache, server, &out); if (ret) krb5_err(context, 1, ret, "krb5_get_creds"); if (out_cache_str) { krb5_ccache id; ret = krb5_cc_resolve(context, out_cache_str, &id); if(ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_initialize(context, id, out->client); if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, out); if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_cc_close(context, id); } krb5_free_creds(context, out); krb5_free_principal(context, server); krb5_get_creds_opt_free(context, opt); krb5_cc_close (context, cache); krb5_free_context (context); return 0; }
static krb5_error_code renew_creds( char *princ, time_t *new_exp_time) /* out */ { krb5_creds my_creds; krb5_error_code code = 0; struct k5_data k5; uid_t saved_u = getuid(); uid_t u; if (kwarnd_debug) printf("renew start: uid=%d\n", getuid()); if (!getpruid(princ, &u)) { if (kwarnd_debug) printf("renew: getpruid failed, princ='%s'\n", princ ? princ : "<null>"); return (-1); /* better err num? */ } set_warnd_uid(u); (void) memset(&my_creds, 0, sizeof (my_creds)); (void) memset(&k5, 0, sizeof (k5)); if (code = krb5_init_context(&k5.ctx)) { com_err(progname, code, gettext("while initializing Kerberos 5 library")); goto out; } if ((code = krb5_cc_default(k5.ctx, &k5.cc))) { com_err(progname, code, gettext("while getting default ccache")); goto out; } if ((code = krb5_parse_name(k5.ctx, princ, &k5.me))) { com_err(progname, code, gettext("when parsing name %s"), princ); goto out; } if ((code = krb5_get_renewed_creds(k5.ctx, &my_creds, k5.me, k5.cc, NULL))) { com_err(progname, code, gettext("while renewing creds")); goto out; } if (code = krb5_cc_initialize(k5.ctx, k5.cc, k5.me)) { com_err(progname, code, gettext("when initializing cache %s"), "defcc"); goto out; } if (code = krb5_cc_store_cred(k5.ctx, k5.cc, &my_creds)) { com_err(progname, code, gettext("while storing credentials")); goto out; } /* "return" new expire time */ *new_exp_time = my_creds.times.endtime; out: krb5_free_cred_contents(k5.ctx, &my_creds); if (k5.name) krb5_free_unparsed_name(k5.ctx, k5.name); if (k5.me) krb5_free_principal(k5.ctx, k5.me); if (k5.cc) krb5_cc_close(k5.ctx, k5.cc); if (k5.ctx) krb5_free_context(k5.ctx); set_warnd_uid(saved_u); if (kwarnd_debug) printf("renew end: code=%s, uid=%d\n", error_message(code), getuid()); return (code); }
int main(int argc, char *argv[]) { krb5_context kcontext = NULL; krb5_error_code code; krb5_ccache ccache=NULL; krb5_ccache mslsa_ccache=NULL; krb5_cc_cursor cursor; krb5_creds creds; krb5_principal princ = NULL; int found_tgt = 0; int has_tickets; int option; char * ccachestr = 0; prog = strrchr(argv[0], '/'); prog = prog ? (prog + 1) : argv[0]; while ((option = getopt(argc, argv, "c:h")) != -1) { switch (option) { case 'c': ccachestr = optarg; break; case 'h': default: xusage(); break; } } if (code = krb5_init_context(&kcontext)) { com_err(argv[0], code, "while initializing kerberos library"); goto cleanup; } if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) { com_err(argv[0], code, "while opening MS LSA ccache"); goto cleanup; } /* Enumerate tickets from cache looking for a TGT */ if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) { com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); goto cleanup; } while (!found_tgt) { code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds); if (code) break; /* Check if the ticket is a TGT */ if (is_local_tgt(creds.server)) found_tgt = 1; krb5_free_cred_contents(kcontext, &creds); } krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); if (!found_tgt) { fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n", argv[0]); /* Only set the LSA cache as the default if it actually has tickets. */ code = cc_has_tickets(kcontext, mslsa_ccache, &has_tickets); if (code) goto cleanup; if (has_tickets) code = krb5int_cc_user_set_default_name(kcontext, "MSLSA:"); goto cleanup; } if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) { com_err(argv[0], code, "while obtaining MS LSA principal"); goto cleanup; } if (ccachestr) code = krb5_cc_resolve(kcontext, ccachestr, &ccache); else code = krb5_cc_resolve(kcontext, "API:", &ccache); if (code) { com_err(argv[0], code, "while getting default ccache"); goto cleanup; } if (code = krb5_cc_initialize(kcontext, ccache, princ)) { com_err (argv[0], code, "when initializing ccache"); goto cleanup; } if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) { com_err (argv[0], code, "while copying MS LSA ccache to default ccache"); goto cleanup; } /* Don't try and set the default cache if the cache name was specified. */ if (ccachestr == NULL) { /* On success set the default cache to API. */ code = krb5int_cc_user_set_default_name(kcontext, "API:"); if (code) { com_err(argv[0], code, "when setting default to API"); goto cleanup; } } cleanup: krb5_free_principal(kcontext, princ); if (ccache != NULL) krb5_cc_close(kcontext, ccache); if (mslsa_ccache != NULL) krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); return code ? 1 : 0; }
static krb5_error_code get_ccache(krb5_context context, int *destroy, krb5_ccache *id) { krb5_principal principal = NULL; krb5_error_code ret; krb5_keytab kt = NULL; *id = NULL; if (!issuid()) { const char *cache; cache = getenv("NTLM_ACCEPTOR_CCACHE"); if (cache) { ret = krb5_cc_resolve(context, cache, id); if (ret) goto out; return 0; } } ret = krb5_sname_to_principal(context, NULL, "host", KRB5_NT_SRV_HST, &principal); if (ret) goto out; ret = krb5_cc_cache_match(context, principal, id); if (ret == 0) return 0; /* did not find in default credcache, lets try default keytab */ ret = krb5_kt_default(context, &kt); if (ret) goto out; /* XXX check in keytab */ { krb5_get_init_creds_opt *opt; krb5_creds cred; memset(&cred, 0, sizeof(cred)); ret = krb5_cc_new_unique(context, "MEMORY", NULL, id); if (ret) goto out; *destroy = 1; ret = krb5_get_init_creds_opt_alloc(context, &opt); if (ret) goto out; ret = krb5_get_init_creds_keytab (context, &cred, principal, kt, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (ret) goto out; ret = krb5_cc_initialize (context, *id, cred.client); if (ret) { krb5_free_cred_contents (context, &cred); goto out; } ret = krb5_cc_store_cred (context, *id, &cred); krb5_free_cred_contents (context, &cred); if (ret) goto out; } krb5_kt_close(context, kt); return 0; out: if (*id) { if (*destroy) krb5_cc_destroy(context, *id); else krb5_cc_close(context, *id); *id = NULL; } if (kt) krb5_kt_close(context, kt); if (principal) krb5_free_principal(context, principal); 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); }
static int create_krb5_tickets (krb5_context context, krb5_keytab kt) { krb5_error_code ret; krb5_keytab_entry entry; krb5_creds cred; krb5_enctype etype; krb5_ccache ccache; memset (&cred, 0, sizeof(cred)); ret = krb5_string_to_enctype (context, enc_type, &etype); if (ret) krb5_err (context, 1, ret, "krb5_string_to_enctype"); ret = krb5_kt_get_entry (context, kt, server_principal, 0, etype, &entry); if (ret) krb5_err (context, 1, ret, "krb5_kt_get_entry"); /* * setup cred */ ret = krb5_copy_principal (context, client_principal, &cred.client); if (ret) krb5_err (context, 1, ret, "krb5_copy_principal"); ret = krb5_copy_principal (context, server_principal, &cred.server); if (ret) krb5_err (context, 1, ret, "krb5_copy_principal"); krb5_generate_random_keyblock(context, etype, &cred.session); cred.times.authtime = time(NULL); cred.times.starttime = time(NULL); cred.times.endtime = time(NULL) + expiration_time; cred.times.renew_till = 0; krb5_data_zero(&cred.second_ticket); ret = krb5_get_all_client_addrs (context, &cred.addresses); if (ret) krb5_err (context, 1, ret, "krb5_get_all_client_addrs"); cred.flags.b = ticket_flags; /* * Encode encrypted part of ticket */ encode_ticket (context, &entry.keyblock, etype, entry.vno, &cred); /* * Write to cc */ if (ccache_str) { ret = krb5_cc_resolve(context, ccache_str, &ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } else { ret = krb5_cc_default (context, &ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_default"); } ret = krb5_cc_initialize (context, ccache, cred.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred (context, ccache, &cred); if (ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); krb5_cc_close (context, ccache); return 0; }
int get_credentials(const char * princname, const char * password, const char * cache_name) { char* name; krb5_error_code ret; krb5_creds creds; krb5_principal client_princ; krb5_ccache ccache; if (cache_name) { ret = krb5_cc_resolve(this->ctx, cache_name, &ccache); if (ret) { LOG(LOG_ERR, "ERREUR CC Resolve %d", ret); } } else { ret = krb5_cc_default(this->ctx, &ccache); if (ret) { LOG(LOG_ERR, "ERREUR CC Default resolve "); } } memset(&creds, 0, sizeof(creds)); ret = krb5_parse_name(this->ctx, princname, &client_princ); LOG(LOG_INFO, "Parse name %s", princname); if (ret) { LOG(LOG_ERR, "ERREUR Parse name %s", princname); goto cleanup; } ret = krb5_unparse_name(this->ctx, client_princ, &name); if (ret) { LOG(LOG_ERR, "ERREUR Unparse name"); goto cleanup; } LOG(LOG_INFO, "Using principal: %s", name); krb5_free_unparsed_name(this->ctx, name); // get TGT // 4th argument should be const char * !!! ret = krb5_get_init_creds_password(this->ctx, &creds, client_princ, const_cast<char*>(password), nullptr, nullptr, 0, nullptr, nullptr); if (ret) { LOG(LOG_INFO, "Init creds password failed: Wrong password or no such user"); goto cleanup; } // ret = krb5_verify_init_creds(this->ctx, &creds, nullptr, nullptr, nullptr, nullptr); // if (ret) { // LOG(LOG_ERR, "ERREUR Verify creds"); // goto cleanup; // } ret = krb5_cc_initialize(this->ctx, ccache, client_princ); if (ret) { LOG(LOG_ERR, "ERREUR CC INITIALIZE"); goto cleanup; } ret = krb5_cc_store_cred(this->ctx, ccache, &creds); if (ret) { LOG(LOG_ERR, "ERREUR CC Store Creds"); goto cleanup; } else { LOG(LOG_INFO, "Credentials Cache stored in %s", cache_name?cache_name:"Default Cache"); } cleanup: krb5_cc_close(this->ctx, ccache); krb5_free_principal(this->ctx, client_princ); krb5_free_cred_contents(this->ctx, &creds); return ret; }
static krb5_error_code digest_request(krb5_context context, krb5_realm realm, krb5_ccache ccache, krb5_key_usage usage, const DigestReqInner *ireq, DigestRepInner *irep) { DigestREQ req; DigestREP rep; krb5_error_code ret; krb5_data data, data2; size_t size = 0; krb5_crypto crypto = NULL; krb5_auth_context ac = NULL; krb5_principal principal = NULL; krb5_ccache id = NULL; krb5_realm r = NULL; krb5_data_zero(&data); krb5_data_zero(&data2); memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); if (ccache == NULL) { ret = krb5_cc_default(context, &id); if (ret) goto out; } else id = ccache; if (realm == NULL) { ret = krb5_get_default_realm(context, &r); if (ret) goto out; } else r = realm; /* * */ ret = krb5_make_principal(context, &principal, r, KRB5_DIGEST_NAME, r, NULL); if (ret) goto out; ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, ireq, &size, ret); if (ret) { krb5_set_error_message(context, ret, N_("Failed to encode digest inner request", "")); goto out; } if (size != data.length) krb5_abortx(context, "ASN.1 internal encoder error"); ret = krb5_mk_req_exact(context, &ac, AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, principal, NULL, id, &req.apReq); if (ret) goto out; { krb5_keyblock *key; ret = krb5_auth_con_getlocalsubkey(context, ac, &key); if (ret) goto out; if (key == NULL) { ret = EINVAL; krb5_set_error_message(context, ret, N_("Digest failed to get local subkey", "")); goto out; } ret = krb5_crypto_init(context, key, 0, &crypto); krb5_free_keyblock (context, key); if (ret) goto out; } ret = krb5_encrypt_EncryptedData(context, crypto, usage, data.data, data.length, 0, &req.innerReq); if (ret) goto out; krb5_data_free(&data); ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, &req, &size, ret); if (ret) { krb5_set_error_message(context, ret, N_("Failed to encode DigestREQest", "")); goto out; } if (size != data.length) krb5_abortx(context, "ASN.1 internal encoder error"); ret = krb5_sendto_kdc(context, &data, &r, &data2); if (ret) goto out; ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); if (ret) { krb5_set_error_message(context, ret, N_("Failed to parse digest response", "")); goto out; } { krb5_ap_rep_enc_part *repl; ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); if (ret) goto out; krb5_free_ap_rep_enc_part(context, repl); } { krb5_keyblock *key; ret = krb5_auth_con_getremotesubkey(context, ac, &key); if (ret) goto out; if (key == NULL) { ret = EINVAL; krb5_set_error_message(context, ret, N_("Digest reply have no remote subkey", "")); goto out; } krb5_crypto_destroy(context, crypto); ret = krb5_crypto_init(context, key, 0, &crypto); krb5_free_keyblock (context, key); if (ret) goto out; } krb5_data_free(&data); ret = krb5_decrypt_EncryptedData(context, crypto, usage, &rep.innerRep, &data); if (ret) goto out; ret = decode_DigestRepInner(data.data, data.length, irep, NULL); if (ret) { krb5_set_error_message(context, ret, N_("Failed to decode digest inner reply", "")); goto out; } out: if (ccache == NULL && id) krb5_cc_close(context, id); if (realm == NULL && r) free(r); if (crypto) krb5_crypto_destroy(context, crypto); if (ac) krb5_auth_con_free(context, ac); if (principal) krb5_free_principal(context, principal); krb5_data_free(&data); krb5_data_free(&data2); free_DigestREQ(&req); free_DigestREP(&rep); return ret; }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; const char *realm = NULL; unsigned int realm_len = 0; krb5_creds creds, *credsp = NULL; krb5_ccache ccache = NULL; ZERO_STRUCT(creds); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_cc_get_principal(context, ccache, &creds.client); if (ret) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to get principal from ccache (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } realm = smb_krb5_principal_get_realm(context, creds.client); realm_len = strlen(realm); ret = krb5_build_principal(context, &creds.server, realm_len, realm, "kadmin", "changepw", NULL); ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("krb5_build_prinipal_ext (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* we might have to call krb5_free_creds(...) from now on ... */ aret = do_krb5_kpasswd_request(context, kdc_host, KRB5_KPASSWD_VERS_SETPW, credsp, princ, newpw); krb5_free_creds(context, credsp); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
isc_result_t krb5_get_tgt(const char *principal, const char *keyfile) { isc_result_t result = ISC_R_FAILURE; char *ccname = NULL; krb5_context context = NULL; krb5_error_code krberr; krb5_ccache ccache = NULL; krb5_principal kprincpw = NULL; krb5_creds my_creds; krb5_creds * my_creds_ptr = NULL; krb5_get_init_creds_opt options; krb5_keytab keytab = NULL; int ret; if (keyfile == NULL || keyfile[0] == '\0') { keyfile = KRB_DEFAULT_KEYTAB; log_info("Using default keytab %s\n", keyfile); } else { if (strncmp(keyfile, "FILE:", 5) != 0) { log_error("Unknown keytab path format: Does it start with FILE:?\n"); return ISC_R_FAILURE; } } krberr = krb5_init_context(&context); CHECK_KRB5(NULL, krberr, "Kerberos context initialization failed"); result = ISC_R_SUCCESS; ccname = "MEMORY:dhcp_ld_krb5_cc"; log_info("Using ccache %s\n" , ccname); ret = setenv("KRB5CCNAME", ccname, 1); if (ret == -1) { log_error("Failed to setup environment\n"); result = ISC_R_FAILURE; goto cleanup; } krberr = krb5_cc_resolve(context, ccname, &ccache); CHECK_KRB5(context, krberr, "Couldnt resolve ccache '%s'", ccname); krberr = krb5_parse_name(context, principal, &kprincpw); CHECK_KRB5(context, krberr, "Failed to parse princ '%s'", princpal); result = check_credentials(context, ccache, kprincpw); if (result == ISC_R_SUCCESS) { log_info("Found valid kerberos credentials\n"); goto cleanup; } else { log_error("No valid krb5 credentials\n"); } krberr = krb5_kt_resolve(context, keyfile, &keytab); CHECK_KRB5(context, krberr, "Failed to resolve kt files '%s'\n", keyfile); memset(&my_creds, 0, sizeof(my_creds)); memset(&options, 0, sizeof(options)); krb5_get_init_creds_opt_set_tkt_life(&options, KRB_MIN_TIME * 2); krb5_get_init_creds_opt_set_address_list(&options, NULL); krb5_get_init_creds_opt_set_forwardable(&options, 0); krb5_get_init_creds_opt_set_proxiable(&options, 0); krberr = krb5_get_init_creds_keytab(context, &my_creds, kprincpw, keytab, 0, NULL, &options); CHECK_KRB5(context, krberr, "Failed to get initial credentials TGT\n"); my_creds_ptr = &my_creds; krberr = krb5_cc_initialize(context, ccache, kprincpw); CHECK_KRB5(context, krberr, "Failed to init ccache\n"); krberr = krb5_cc_store_cred(context, ccache, &my_creds); CHECK_KRB5(context, krberr, "Failed to store credentials\n"); result = ISC_R_SUCCESS; log_info("Successfully init krb tgt %s", principal); cleanup: if (ccache) krb5_cc_close(context, ccache); if (keytab) krb5_kt_close(context, keytab); if (kprincpw) krb5_free_principal(context, kprincpw); if (my_creds_ptr) krb5_free_cred_contents(context, &my_creds); if (context) krb5_free_context(context); return result; }
static void kerberos_kinit(void) { char *name, *krbtgt; krb5_error_code code; krb5_context ctx; krb5_ccache ccache; krb5_principal kprinc; krb5_keytab keytab; krb5_get_init_creds_opt *opts; krb5_creds creds; const char *realm; /* * Determine the principal corresponding to that keytab. We copy the * memory to ensure that it's allocated in the right memory domain on * systems where that may matter (like Windows). */ code = krb5_init_context(&ctx); if (code != 0) bail_krb5(ctx, code, "error initializing Kerberos"); kprinc = kerberos_keytab_principal(ctx, config->keytab); code = krb5_unparse_name(ctx, kprinc, &name); if (code != 0) bail_krb5(ctx, code, "error unparsing name"); krb5_free_principal(ctx, kprinc); config->principal = bstrdup(name); krb5_free_unparsed_name(ctx, name); /* Now do the Kerberos initialization. */ code = krb5_cc_default(ctx, &ccache); if (code != 0) bail_krb5(ctx, code, "error setting ticket cache"); code = krb5_parse_name(ctx, config->principal, &kprinc); if (code != 0) bail_krb5(ctx, code, "error parsing principal %s", config->principal); realm = krb5_principal_get_realm(ctx, kprinc); basprintf(&krbtgt, "krbtgt/%s@%s", realm, realm); code = krb5_kt_resolve(ctx, config->keytab, &keytab); if (code != 0) bail_krb5(ctx, code, "cannot open keytab %s", config->keytab); code = krb5_get_init_creds_opt_alloc(ctx, &opts); if (code != 0) bail_krb5(ctx, code, "cannot allocate credential options"); krb5_get_init_creds_opt_set_default_flags(ctx, NULL, realm, opts); krb5_get_init_creds_opt_set_forwardable(opts, 0); krb5_get_init_creds_opt_set_proxiable(opts, 0); code = krb5_get_init_creds_keytab(ctx, &creds, kprinc, keytab, 0, krbtgt, opts); if (code != 0) bail_krb5(ctx, code, "cannot get Kerberos tickets"); code = krb5_cc_initialize(ctx, ccache, kprinc); if (code != 0) bail_krb5(ctx, code, "error initializing ticket cache"); code = krb5_cc_store_cred(ctx, ccache, &creds); if (code != 0) bail_krb5(ctx, code, "error storing credentials"); krb5_cc_close(ctx, ccache); krb5_free_cred_contents(ctx, &creds); krb5_kt_close(ctx, keytab); krb5_free_principal(ctx, kprinc); krb5_get_init_creds_opt_free(ctx, opts); krb5_free_context(ctx); free(krbtgt); }
static OM_uint32 copy_initiator_creds(OM_uint32 *minor_status, gss_cred_id_t input_cred_handle, const gss_OID desired_mech, OM_uint32 overwrite_cred, OM_uint32 default_cred, gss_const_key_value_set_t cred_store) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t kcred = NULL; krb5_context context = NULL; krb5_ccache ccache = NULL; const char *ccache_name; *minor_status = 0; if (!default_cred && cred_store == GSS_C_NO_CRED_STORE) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle, context); if (GSS_ERROR(major_status)) goto cleanup; kcred = (krb5_gss_cred_id_t)input_cred_handle; if (kcred->ccache == NULL) { *minor_status = KG_CCACHE_NOMATCH; major_status = GSS_S_DEFECTIVE_CREDENTIAL; goto cleanup; } if (!overwrite_cred && has_unexpired_creds(kcred, desired_mech, default_cred, cred_store)) { major_status = GSS_S_DUPLICATE_ELEMENT; goto cleanup; } major_status = kg_value_from_cred_store(cred_store, KRB5_CS_CCACHE_URN, &ccache_name); if (GSS_ERROR(major_status)) goto cleanup; if (ccache_name != NULL) { code = krb5_cc_resolve(context, ccache_name, &ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_CRED_UNAVAIL; goto cleanup; } code = krb5_cc_initialize(context, ccache, kcred->name->princ); if (code != 0) { *minor_status = code; major_status = GSS_S_CRED_UNAVAIL; goto cleanup; } } if (ccache == NULL) { if (!default_cred) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5int_cc_default(context, &ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } } code = krb5_cc_copy_creds(context, kcred->ccache, ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } *minor_status = 0; major_status = GSS_S_COMPLETE; cleanup: if (kcred != NULL) k5_mutex_unlock(&kcred->lock); if (ccache != NULL) krb5_cc_close(context, ccache); krb5_free_context(context); return major_status; }
static void do_kcpytkt (int count, char *names[], char *fromccachestr, char *etypestr, int flags) { krb5_context context; krb5_error_code ret; int i, errors; krb5_enctype etype; krb5_ccache fromccache; krb5_ccache destccache; krb5_principal me; krb5_creds in_creds, out_creds; int retflags; char *princ; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if (etypestr) { ret = krb5_string_to_enctype(context, etypestr, &etype); if (ret) krb5_err(context, 1, ret, "Can't convert enctype %s", etypestr); retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_MATCH_KEYTYPE; } else { etype = 0; retflags = KRB5_TC_MATCH_SRV_NAMEONLY; } if (fromccachestr) ret = krb5_cc_resolve(context, fromccachestr, &fromccache); else ret = krb5_cc_default(context, &fromccache); if (ret) krb5_err(context, 1, ret, "Can't resolve credentials cache"); ret = krb5_cc_get_principal(context, fromccache, &me); if (ret) krb5_err(context, 1, ret, "Can't query client principal name"); ret = krb5_cc_resolve(context, names[0], &destccache); if (ret) krb5_err(context, 1, ret, "Can't resolve destination cache"); errors = 0; for (i = 1; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = me; ret = krb5_parse_name(context, names[i], &in_creds.server); if (ret) { if (!quiet_flag) krb5_warn(context, ret, "Parse error for %s", names[i]); errors++; continue; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { krb5_warn(context, ret, "Unparse error for %s", names[i]); errors++; continue; } in_creds.session.keytype = etype; ret = krb5_cc_retrieve_cred(context, fromccache, retflags, &in_creds, &out_creds); if (ret) { krb5_warn(context, ret, "Can't retrieve credentials for %s", princ); krb5_free_unparsed_name(context, princ); errors++; continue; } ret = krb5_cc_store_cred(context, destccache, &out_creds); krb5_free_principal(context, in_creds.server); if (ret) { krb5_warn(context, ret, "Can't store credentials for %s", princ); krb5_free_cred_contents(context, &out_creds); krb5_free_unparsed_name(context, princ); errors++; continue; } krb5_free_unparsed_name(context, princ); krb5_free_cred_contents(context, &out_creds); } krb5_free_principal(context, me); krb5_cc_close(context, fromccache); krb5_cc_close(context, destccache); krb5_free_context(context); if (errors) exit(1); exit(0); }
int cosign_login_krb5( struct connlist *head, char *cosignname, char *id, char *realm, char *passwd, char *ip_addr, char *cookie, struct subparams *sp, char **msg ) { krb5_error_code kerror = 0; krb5_context kcontext; krb5_principal kprinc; krb5_principal sprinc; krb5_get_init_creds_opt kopts; krb5_verify_init_creds_opt kvic_opts[ 1 ]; krb5_creds kcreds; krb5_ccache kccache; krb5_keytab keytab = 0; char *tmpl = ERROR_HTML; char *sprinc_name = NULL; char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; char tmpkrb[ 16 ], krbpath [ MAXPATHLEN ]; int i; lcgi_configure(); if (( kerror = krb5_init_context( &kcontext ))) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_parse_name( kcontext, id, &kprinc ))) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } /* need to get realm out */ if ( realm == NULL || *realm == '\0' ) { if (( kerror = krb5_get_default_realm( kcontext, &realm )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required " "( krb realm error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } } if ( store_tickets ) { if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) { sl[ SL_ERROR ].sl_data = "An unknown error occurred."; sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s", ticket_path, tmpkrb ) >= sizeof( krbpath )) { sl[ SL_ERROR ].sl_data = "An unknown error occurred."; sl[ SL_TITLE ].sl_data = "Authentication Required (krbpath error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_cc_resolve( kcontext, krbpath, &kccache )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } } krb5_get_init_creds_opt_init( &kopts ); krb5_get_init_creds_opt_set_tkt_life( &kopts, tkt_life ); krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); if (( kerror = krb5_get_init_creds_password( kcontext, &kcreds, kprinc, passwd, NULL, NULL, 0, NULL /*keytab */, &kopts ))) { if (( kerror == KRB5KRB_AP_ERR_BAD_INTEGRITY ) || ( kerror == KRB5KDC_ERR_PREAUTH_FAILED ) || ( kerror == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN )) { return( COSIGN_CGI_ERROR ); /* draw login or reauth page */ } else if ( kerror == KRB5KDC_ERR_KEY_EXP ) { *msg = (char *)error_message( kerror ); return( COSIGN_CGI_PASSWORD_EXPIRED ); } else { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } } /* verify no KDC spoofing */ if ( *keytab_path != '\0' ) { if ( strlen( keytab_path ) > MAX_KEYTAB_NAME_LEN ) { sl[ SL_ERROR ].sl_data = "server configuration error"; sl[ SL_TITLE ].sl_data = "Ticket Verification Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } strcpy( ktbuf, keytab_path ); /* from mdw */ krb5_verify_init_creds_opt_init( kvic_opts ); krb5_verify_init_creds_opt_set_ap_req_nofail( kvic_opts, 1 ); if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "KT Resolve Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if ( cosign_princ ) { kerror = krb5_parse_name( kcontext, cosign_princ, &sprinc ); } else { kerror = krb5_sname_to_principal( kcontext, NULL, "cosign", KRB5_NT_SRV_HST, &sprinc ); } if ( kerror != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Server Principal Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_verify_init_creds( kcontext, &kcreds, sprinc, keytab, NULL, kvic_opts )) != 0 ) { if ( krb5_unparse_name( kcontext, sprinc, &sprinc_name ) == 0 ) { fprintf( stderr, "ticket verify error for " "user %s, keytab principal %s", id, sprinc_name ); free( sprinc_name ); } else { fprintf( stderr, "ticket verify error for user %s", id ); } sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Ticket Verify Error"; subfile( tmpl, sl, 0 ); krb5_free_principal( kcontext, sprinc ); exit( 0 ); } (void)krb5_kt_close( kcontext, keytab ); krb5_free_principal( kcontext, sprinc ); } for ( i = 0; i < COSIGN_MAXFACTORS - 1; i++ ) { if ( new_factors[ i ] == NULL ) { new_factors[ i ] = strdup( realm ); new_factors[ i + 1 ] = NULL; break; } if ( strcmp( new_factors[ i ], realm ) == 0 ) { break; } } if ( sp->sp_reauth && sp->sp_ipchanged == 0 ) { return( COSIGN_CGI_OK ); } if ( store_tickets ) { if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "CC Initialize Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_cc_store_cred( kcontext, kccache, &kcreds )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "CC Storing Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } krb5_cc_close( kcontext, kccache ); } krb5_free_cred_contents( kcontext, &kcreds ); krb5_free_principal( kcontext, kprinc ); krb5_free_context( kcontext ); /* password has been accepted, tell cosignd */ if ( cosign_login( head, cookie, ip_addr, cosignname, realm, ( store_tickets ? krbpath : NULL )) < 0 ) { fprintf( stderr, "cosign_login_krb5: login failed\n") ; sl[ SL_ERROR ].sl_data = "We were unable to contact the " "authentication server. Please try again later."; sl[ SL_TITLE ].sl_data = "Error: Please try later"; subfile( tmpl, sl, 0 ); exit( 0 ); } return( COSIGN_CGI_OK ); }
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 kswitch(struct kswitch_options *opt, int argc, char **argv) { krb5_error_code ret; krb5_ccache id = NULL; if (opt->cache_string && opt->principal_string) krb5_errx(kcc_context, 1, N_("Both --cache and --principal given, choose one", "")); if (opt->interactive_flag) { krb5_cc_cache_cursor cursor; krb5_ccache *ids = NULL; size_t i, len = 0; char *name; rtbl_t ct; ct = rtbl_create(); rtbl_add_column_by_id(ct, 0, "#", 0); rtbl_add_column_by_id(ct, 1, "Principal", 0); rtbl_set_column_affix_by_id(ct, 1, " ", ""); rtbl_add_column_by_id(ct, 2, "Type", 0); rtbl_set_column_affix_by_id(ct, 2, " ", ""); ret = krb5_cc_cache_get_first(kcc_context, NULL, &cursor); if (ret) krb5_err(kcc_context, 1, ret, "krb5_cc_cache_get_first"); while (krb5_cc_cache_next(kcc_context, cursor, &id) == 0) { krb5_principal p; char num[10]; ret = krb5_cc_get_principal(kcc_context, id, &p); if (ret) continue; ret = krb5_unparse_name(kcc_context, p, &name); krb5_free_principal(kcc_context, p); snprintf(num, sizeof(num), "%d", (int)(len + 1)); rtbl_add_column_entry_by_id(ct, 0, num); rtbl_add_column_entry_by_id(ct, 1, name); rtbl_add_column_entry_by_id(ct, 2, krb5_cc_get_type(kcc_context, id)); free(name); ids = erealloc(ids, (len + 1) * sizeof(ids[0])); ids[len] = id; len++; } krb5_cc_cache_end_seq_get(kcc_context, cursor); rtbl_format(ct, stdout); rtbl_destroy(ct); name = readline("Select number: "); if (name) { i = atoi(name); if (i == 0) krb5_errx(kcc_context, 1, "Cache number '%s' is invalid", name); if (i > len) krb5_errx(kcc_context, 1, "Cache number '%s' is too large", name); id = ids[i - 1]; ids[i - 1] = NULL; } else krb5_errx(kcc_context, 1, "No cache selected"); for (i = 0; i < len; i++) if (ids[i]) krb5_cc_close(kcc_context, ids[i]); } else if (opt->principal_string) { krb5_principal p; ret = krb5_parse_name(kcc_context, opt->principal_string, &p); if (ret) krb5_err(kcc_context, 1, ret, "krb5_parse_name: %s", opt->principal_string); ret = krb5_cc_cache_match(kcc_context, p, &id); if (ret) krb5_err(kcc_context, 1, ret, N_("Did not find principal: %s", ""), opt->principal_string); krb5_free_principal(kcc_context, p); } else if (opt->cache_string) { const krb5_cc_ops *ops; char *str; ops = krb5_cc_get_prefix_ops(kcc_context, opt->type_string); if (ops == NULL) krb5_err(kcc_context, 1, 0, "krb5_cc_get_prefix_ops"); asprintf(&str, "%s:%s", ops->prefix, opt->cache_string); if (str == NULL) krb5_errx(kcc_context, 1, N_("out of memory", "")); ret = krb5_cc_resolve(kcc_context, str, &id); if (ret) krb5_err(kcc_context, 1, ret, "krb5_cc_resolve: %s", str); free(str); } else { krb5_errx(kcc_context, 1, "missing option for kswitch"); } ret = krb5_cc_switch(kcc_context, id); if (ret) krb5_err(kcc_context, 1, ret, "krb5_cc_switch"); return 0; }