static krb5_error_code mod_authn_gssapi_verify_krb5_init_creds(server *srv, krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab) { krb5_error_code ret; krb5_data req; krb5_ccache local_ccache = NULL; krb5_creds *new_creds = NULL; krb5_auth_context auth_context = NULL; krb5_keytab keytab = NULL; char *server_name; memset(&req, 0, sizeof(req)); if (ap_req_keytab == NULL) { ret = krb5_kt_default(context, &keytab); if (ret) return ret; } else keytab = ap_req_keytab; ret = krb5_cc_resolve(context, "MEMORY:", &local_ccache); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_resolve() failed when verifying KDC"); /* return ret; */ goto end; } ret = krb5_cc_initialize(context, local_ccache, creds->client); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_initialize() failed when verifying KDC"); goto end; } ret = krb5_cc_store_cred(context, local_ccache, creds); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_store_cred() failed when verifying KDC"); goto end; } ret = krb5_unparse_name(context, ap_req_server, &server_name); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_unparse_name() failed when verifying KDC"); goto end; } krb5_free_unparsed_name(context, server_name); if (!krb5_principal_compare(context, ap_req_server, creds->server)) { krb5_creds match_cred; memset(&match_cred, 0, sizeof(match_cred)); match_cred.client = creds->client; match_cred.server = ap_req_server; ret = krb5_get_credentials(context, 0, local_ccache, &match_cred, &new_creds); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_get_credentials() failed when verifying KDC"); goto end; } creds = new_creds; } ret = krb5_mk_req_extended(context, &auth_context, 0, NULL, creds, &req); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_mk_req_extended() failed when verifying KDC"); goto end; } krb5_auth_con_free(context, auth_context); auth_context = NULL; ret = krb5_auth_con_init(context, &auth_context); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_auth_con_init() failed when verifying KDC"); goto end; } /* use KRB5_AUTH_CONTEXT_DO_SEQUENCE to skip replay cache checks */ krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); ret = krb5_rd_req(context, &auth_context, &req, ap_req_server, keytab, 0, NULL); if (ret) { log_error_write(srv, __FILE__, __LINE__, "s", "krb5_rd_req() failed when verifying KDC"); goto end; } end: krb5_free_data_contents(context, &req); if (auth_context) krb5_auth_con_free(context, auth_context); if (new_creds) krb5_free_creds(context, new_creds); if (ap_req_keytab == NULL && keytab) krb5_kt_close(context, keytab); if (local_ccache) krb5_cc_destroy(context, local_ccache); return ret; }
krb5_error_code KRB5_CALLCONV krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server_arg, krb5_keytab keytab_arg, krb5_ccache *ccache_arg, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_principal server; krb5_keytab keytab; krb5_ccache ccache; krb5_keytab_entry kte; krb5_creds in_creds, *out_creds; krb5_auth_context authcon; krb5_data ap_req; /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */ server = NULL; keytab = NULL; ccache = NULL; out_creds = NULL; authcon = NULL; ap_req.data = NULL; if (keytab_arg) { keytab = keytab_arg; } else { if ((ret = krb5_kt_default(context, &keytab))) goto cleanup; } if (server_arg) { ret = krb5_copy_principal(context, server_arg, &server); if (ret) goto cleanup; } else { /* Use a principal name from the keytab. */ ret = k5_kt_get_principal(context, keytab, &server); if (ret) { /* There's no keytab, or it's empty, or we can't read it. * Allow this unless configuration demands verification. */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } } /* first, check if the server is in the keytab. If not, there's no reason to continue. rd_req does all this, but there's no way to know that a given error is caused by a missing keytab or key, and not by some other problem. */ if (krb5_is_referral_realm(&server->realm)) { krb5_free_data_contents(context, &server->realm); ret = krb5_get_default_realm(context, &server->realm.data); if (ret) goto cleanup; server->realm.length = strlen(server->realm.data); } if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) { /* this means there is no keying material. This is ok, as long as it is not prohibited by the configuration */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } krb5_kt_free_entry(context, &kte); /* If the creds are for the server principal, we're set, just do a mk_req. * Otherwise, do a get_credentials first. */ if (krb5_principal_compare(context, server, creds->server)) { /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req))) goto cleanup; } else { /* this is unclean, but it's the easiest way without ripping the library into very small pieces. store the client's initial cred in a memory ccache, then call the library. Later, we'll copy everything except the initial cred into the ccache we return to the user. A clean implementation would involve library internals with a coherent idea of "in" and "out". */ /* insert the initial cred into the ccache */ if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) { ccache = NULL; goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, creds->client))) goto cleanup; if ((ret = krb5_cc_store_cred(context, ccache, creds))) goto cleanup; /* set up for get_creds */ memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = creds->client; in_creds.server = server; if ((ret = krb5_timeofday(context, &in_creds.times.endtime))) goto cleanup; in_creds.times.endtime += 5*60; if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds))) goto cleanup; /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds, &ap_req))) goto cleanup; } /* wipe the auth context for mk_req */ if (authcon) { krb5_auth_con_free(context, authcon); authcon = NULL; } /* verify the ap_req */ if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL))) goto cleanup; /* if we get this far, then the verification succeeded. We can still fail if the library stuff here fails, but that's it */ if (ccache_arg && ccache) { if (*ccache_arg == NULL) { krb5_ccache retcc; retcc = NULL; if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || (ret = krb5_cc_initialize(context, retcc, creds->client)) || (ret = copy_creds_except(context, ccache, retcc, creds->server))) { if (retcc) krb5_cc_destroy(context, retcc); } else { *ccache_arg = retcc; } } else { ret = copy_creds_except(context, ccache, *ccache_arg, server); } } /* if any of the above paths returned an errors, then ret is set accordingly. * Either that, or it's zero, which is fine, too */ cleanup: if ( server) krb5_free_principal(context, server); if (!keytab_arg && keytab) krb5_kt_close(context, keytab); if (ccache) krb5_cc_destroy(context, ccache); if (out_creds) krb5_free_creds(context, out_creds); if (authcon) krb5_auth_con_free(context, authcon); if (ap_req.data) free(ap_req.data); return(ret); }
static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, krb5_ccache ccache, krb5_deltat ticket_life, int interactive) { krb5_error_code ret; krb5_get_init_creds_opt *opt; krb5_creds cred; char passwd[256]; krb5_deltat start_time = 0; krb5_deltat renew = 0; const char *renewstr = NULL; krb5_enctype *enctype = NULL; krb5_ccache tempccache; #ifndef NO_NTLM struct ntlm_buf ntlmkey; memset(&ntlmkey, 0, sizeof(ntlmkey)); #endif passwd[0] = '\0'; if (password_file) { FILE *f; if (strcasecmp("STDIN", password_file) == 0) f = stdin; else f = fopen(password_file, "r"); if (f == NULL) krb5_errx(context, 1, "Failed to open the password file %s", password_file); if (fgets(passwd, sizeof(passwd), f) == NULL) krb5_errx(context, 1, N_("Failed to read password from file %s", ""), password_file); if (f != stdin) fclose(f); passwd[strcspn(passwd, "\n")] = '\0'; } #ifdef __APPLE__ if (passwd[0] == '\0') { const char *realm; OSStatus osret; UInt32 length; void *buffer; char *name; realm = krb5_principal_get_realm(context, principal); ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) goto nopassword; osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm, strlen(name), name, &length, &buffer, NULL); free(name); if (osret == noErr && length < sizeof(passwd) - 1) { memcpy(passwd, buffer, length); passwd[length] = '\0'; } nopassword: do { } while(0); } #endif memset(&cred, 0, sizeof(cred)); 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_default_flags(context, "kinit", krb5_principal_get_realm(context, principal), opt); if(forwardable_flag != -1) krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag); if(proxiable_flag != -1) krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag); if(anonymous_flag) krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag); if (pac_flag != -1) krb5_get_init_creds_opt_set_pac_request(context, opt, pac_flag ? TRUE : FALSE); if (canonicalize_flag) krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE); if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag) krb5_get_init_creds_opt_set_win2k(context, opt, TRUE); if (pk_user_id || ent_user_id || anonymous_flag) { ret = krb5_get_init_creds_opt_set_pkinit(context, opt, principal, pk_user_id, pk_x509_anchors, NULL, NULL, pk_use_enckey ? 2 : 0 | anonymous_flag ? 4 : 0, krb5_prompter_posix, NULL, passwd); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); if (ent_user_id) krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id); } if (addrs_flag != -1) krb5_get_init_creds_opt_set_addressless(context, opt, addrs_flag ? FALSE : TRUE); if (renew_life == NULL && renewable_flag) renewstr = "1 month"; if (renew_life) renewstr = renew_life; if (renewstr) { renew = parse_time (renewstr, "s"); if (renew < 0) errx (1, "unparsable time: %s", renewstr); krb5_get_init_creds_opt_set_renew_life (opt, renew); } if(ticket_life != 0) krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life); if(start_str) { int tmp = parse_time (start_str, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), start_str); start_time = tmp; } if(etype_str.num_strings) { int i; enctype = malloc(etype_str.num_strings * sizeof(*enctype)); if(enctype == NULL) errx(1, "out of memory"); for(i = 0; i < etype_str.num_strings; i++) { ret = krb5_string_to_enctype(context, etype_str.strings[i], &enctype[i]); if(ret) errx(1, "unrecognized enctype: %s", etype_str.strings[i]); } krb5_get_init_creds_opt_set_etype_list(opt, enctype, etype_str.num_strings); } if(use_keytab || keytab_str) { krb5_keytab kt; if(keytab_str) ret = krb5_kt_resolve(context, keytab_str, &kt); else ret = krb5_kt_default(context, &kt); if (ret) krb5_err (context, 1, ret, "resolving keytab"); ret = krb5_get_init_creds_keytab (context, &cred, principal, kt, start_time, server_str, opt); krb5_kt_close(context, kt); } else if (pk_user_id || ent_user_id || anonymous_flag) { ret = krb5_get_init_creds_password (context, &cred, principal, passwd, krb5_prompter_posix, NULL, start_time, server_str, opt); } else if (!interactive) { krb5_warnx(context, "Not interactive, failed to get initial ticket"); krb5_get_init_creds_opt_free(context, opt); return 0; } else { if (passwd[0] == '\0') { char *p, *prompt; krb5_unparse_name (context, principal, &p); asprintf (&prompt, N_("%s's Password: "******""), p); free (p); if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ memset(passwd, 0, sizeof(passwd)); exit(1); } free (prompt); } ret = krb5_get_init_creds_password (context, &cred, principal, passwd, krb5_prompter_posix, NULL, start_time, server_str, opt); } krb5_get_init_creds_opt_free(context, opt); #ifndef NO_NTLM if (ntlm_domain && passwd[0]) heim_ntlm_nt_key(passwd, &ntlmkey); #endif memset(passwd, 0, sizeof(passwd)); switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: case KRB5KDC_ERR_PREAUTH_FAILED: krb5_errx(context, 1, N_("Password incorrect", "")); break; case KRB5KRB_AP_ERR_V4_REPLY: krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", "")); break; default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } if(ticket_life != 0) { if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) { char life[64]; unparse_time_approx(cred.times.endtime - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life); } } if(renew_life) { if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) { char life[64]; unparse_time_approx(cred.times.renew_till - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket renewable lifetime is %s", ""), life); } } ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), NULL, &tempccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_new_unique"); ret = krb5_cc_initialize (context, tempccache, cred.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred (context, tempccache, &cred); if (ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); ret = krb5_cc_move(context, tempccache, ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_move"); if (switch_cache_flags) krb5_cc_switch(context, ccache); #ifndef NO_NTLM if (ntlm_domain && ntlmkey.data) store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey); #endif if (ok_as_delegate_flag || windows_flag || use_referrals_flag) { unsigned char d = 0; krb5_data data; if (ok_as_delegate_flag || windows_flag) d |= 1; if (use_referrals_flag || windows_flag) d |= 2; data.length = 1; data.data = &d; krb5_cc_set_config(context, ccache, NULL, "realm-config", &data); } if (enctype) free(enctype); return 0; }
static krb5_error_code renew_validate(krb5_context context, int renew, int validate, krb5_ccache cache, const char *server, krb5_deltat life) { krb5_error_code ret; krb5_ccache tempccache = NULL; krb5_creds in, *out = NULL; krb5_kdc_flags flags; memset(&in, 0, sizeof(in)); ret = krb5_cc_get_principal(context, cache, &in.client); if (ret) { krb5_warn(context, ret, "krb5_cc_get_principal"); return ret; } ret = get_server(context, in.client, server, &in.server); if (ret) { krb5_warn(context, ret, "get_server"); goto out; } if (renew) { /* * no need to check the error here, it's only to be * friendly to the user */ krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); } flags.i = 0; flags.b.renewable = flags.b.renew = renew; flags.b.validate = validate; if (forwardable_flag != -1) flags.b.forwardable = forwardable_flag; else if (out) flags.b.forwardable = out->flags.b.forwardable; if (proxiable_flag != -1) flags.b.proxiable = proxiable_flag; else if (out) flags.b.proxiable = out->flags.b.proxiable; if (anonymous_flag) flags.b.request_anonymous = anonymous_flag; if (life) in.times.endtime = time(NULL) + life; if (out) { krb5_free_creds(context, out); out = NULL; } ret = krb5_get_kdc_cred(context, cache, flags, NULL, NULL, &in, &out); if (ret) { krb5_warn(context, ret, "krb5_get_kdc_cred"); goto out; } ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, cache), NULL, &tempccache); if (ret) { krb5_warn(context, ret, "krb5_cc_new_unique"); goto out; } ret = krb5_cc_initialize(context, tempccache, in.client); if (ret) { krb5_warn(context, ret, "krb5_cc_initialize"); goto out; } ret = krb5_cc_store_cred(context, tempccache, out); if (ret) { krb5_warn(context, ret, "krb5_cc_store_cred"); goto out; } /* * We want to preserve cc configs as some are security-relevant, and * anyways it's the friendly thing to do. */ ret = copy_configs(context, tempccache, cache, out->server); if (ret) goto out; ret = krb5_cc_move(context, tempccache, cache); if (ret) { krb5_warn(context, ret, "krb5_cc_move"); goto out; } tempccache = NULL; out: if (tempccache) krb5_cc_close(context, tempccache); if (out) krb5_free_creds(context, out); krb5_free_cred_contents(context, &in); return ret; }
char * /* R: allocated response string */ auth_krb5 ( /* PARAMETERS */ const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service authenticating to */ const char *realm /* I: user's realm */ /* END PARAMETERS */ ) { /* VARIABLES */ krb5_context context; krb5_ccache ccache = NULL; krb5_principal auth_user; krb5_creds creds; krb5_get_init_creds_opt opts; char * result; char tfname[2048]; char principalbuf[2048]; krb5_error_code code; /* END VARIABLES */ if (!user|| !password) { syslog(LOG_ERR, "auth_krb5: NULL password or username?"); return strdup("NO saslauthd internal error"); } if (krb5_init_context(&context)) { syslog(LOG_ERR, "auth_krb5: krb5_init_context"); return strdup("NO saslauthd internal error"); } if (form_principal_name(user, service, realm, principalbuf, sizeof (principalbuf))) { syslog(LOG_ERR, "auth_krb5: form_principal_name"); return strdup("NO saslauthd principal name error"); } if (krb5_parse_name (context, principalbuf, &auth_user)) { krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_parse_name"); return strdup("NO saslauthd internal error"); } if (krbtf_name(tfname, sizeof (tfname)) != 0) { syslog(LOG_ERR, "auth_krb5: could not generate ticket file name"); return strdup("NO saslauthd internal error"); } if (krb5_cc_resolve(context, tfname, &ccache)) { krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_resolve"); return strdup("NO saslauthd internal error"); } if (krb5_cc_initialize (context, ccache, auth_user)) { krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_initialize"); return strdup("NO saslauthd internal error"); } krb5_get_init_creds_opt_init(&opts); /* 15 min should be more than enough */ krb5_get_init_creds_opt_set_tkt_life(&opts, 900); if (code = krb5_get_init_creds_password(context, &creds, auth_user, password, NULL, NULL, 0, NULL, &opts)) { krb5_cc_destroy(context, ccache); krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_get_init_creds_password: %d", code); return strdup("NO saslauthd internal error"); } /* at this point we should have a TGT. Let's make sure it is valid */ if (krb5_cc_store_cred(context, ccache, &creds)) { krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_store_cred"); return strdup("NO saslauthd internal error"); } if (!k5support_verify_tgt(context, ccache)) { syslog(LOG_ERR, "auth_krb5: k5support_verify_tgt"); result = strdup("NO saslauthd internal error"); goto fini; } /* * fall through -- user is valid beyond this point */ result = strdup("OK"); fini: /* destroy any tickets we had */ krb5_free_cred_contents(context, &creds); krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); krb5_free_context(context); return result; }
static krb5_error_code get_new_cache(krb5_context context, krb5_principal client, const char *password, krb5_prompter_fct prompter, const char *keytab, const char *server_name, krb5_ccache *ret_cache) { krb5_error_code ret; krb5_creds cred; krb5_get_init_creds_opt *opt; krb5_ccache id; ret = krb5_get_init_creds_opt_alloc (context, &opt); if (ret) return ret; krb5_get_init_creds_opt_set_default_flags(context, "kadmin", krb5_principal_get_realm(context, client), opt); krb5_get_init_creds_opt_set_forwardable (opt, FALSE); krb5_get_init_creds_opt_set_proxiable (opt, FALSE); if(password == NULL && prompter == NULL) { krb5_keytab kt; if(keytab == NULL) ret = krb5_kt_default(context, &kt); else ret = krb5_kt_resolve(context, keytab, &kt); if(ret) { krb5_get_init_creds_opt_free(context, opt); return ret; } ret = krb5_get_init_creds_keytab (context, &cred, client, kt, 0, server_name, opt); krb5_kt_close(context, kt); } else { ret = krb5_get_init_creds_password (context, &cred, client, password, prompter, NULL, 0, server_name, opt); } krb5_get_init_creds_opt_free(context, opt); switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: return KADM5_BAD_PASSWORD; default: return ret; } ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); if(ret) return ret; ret = krb5_cc_initialize (context, id, cred.client); if (ret) return ret; ret = krb5_cc_store_cred (context, id, &cred); if (ret) return ret; krb5_free_cred_contents (context, &cred); *ret_cache = id; return 0; }
/* * Obtain credentials via a key in the keytab given * a keytab handle and a gssd_k5_kt_princ structure. * Checks to see if current credentials are expired, * if not, uses the keytab to obtain new credentials. * * Returns: * 0 => success (or credentials have not expired) * nonzero => error */ static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt, struct gssd_k5_kt_princ *ple) { #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS krb5_get_init_creds_opt *init_opts = NULL; #else krb5_get_init_creds_opt options; #endif krb5_get_init_creds_opt *opts; krb5_creds my_creds; krb5_ccache ccache = NULL; char kt_name[BUFSIZ]; char cc_name[BUFSIZ]; int code; time_t now = time(0); char *cache_type; char *pname = NULL; char *k5err = NULL; memset(&my_creds, 0, sizeof(my_creds)); if (ple->ccname && ple->endtime > now) { printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", ple->ccname, ple->endtime); code = 0; goto out; } if ((code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ))) { printerr(0, "ERROR: Unable to get keytab name in " "gssd_get_single_krb5_cred\n"); goto out; } if ((krb5_unparse_name(context, ple->princ, &pname))) pname = NULL; #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS code = krb5_get_init_creds_opt_alloc(context, &init_opts); if (code) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s allocating gic options\n", k5err); goto out; } if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1)) printerr(1, "WARNING: Unable to set option for addressless " "tickets. May have problems behind a NAT.\n"); #ifdef TEST_SHORT_LIFETIME /* set a short lifetime (for debugging only!) */ printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60); #endif opts = init_opts; #else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */ krb5_get_init_creds_opt_init(&options); krb5_get_init_creds_opt_set_address_list(&options, NULL); #ifdef TEST_SHORT_LIFETIME /* set a short lifetime (for debugging only!) */ printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); krb5_get_init_creds_opt_set_tkt_life(&options, 5*60); #endif opts = &options; #endif if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ, kt, 0, NULL, opts))) { k5err = gssd_k5_err_msg(context, code); printerr(1, "WARNING: %s while getting initial ticket for " "principal '%s' using keytab '%s'\n", k5err, pname ? pname : "<unparsable>", kt_name); goto out; } /* * Initialize cache file which we're going to be using */ if (use_memcache) cache_type = "MEMORY"; else cache_type = "FILE"; snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", cache_type, ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX, GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); ple->endtime = my_creds.times.endtime; if (ple->ccname != NULL) free(ple->ccname); ple->ccname = strdup(cc_name); if (ple->ccname == NULL) { printerr(0, "ERROR: no storage to duplicate credentials " "cache name '%s'\n", cc_name); code = ENOMEM; goto out; } if ((code = krb5_cc_resolve(context, cc_name, &ccache))) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while opening credential cache '%s'\n", k5err, cc_name); goto out; } if ((code = krb5_cc_initialize(context, ccache, ple->princ))) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while initializing credential " "cache '%s'\n", k5err, cc_name); goto out; } if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while storing credentials in '%s'\n", k5err, cc_name); goto out; } code = 0; printerr(2, "Successfully obtained machine credentials for " "principal '%s' stored in ccache '%s'\n", pname, cc_name); out: #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS if (init_opts) krb5_get_init_creds_opt_free(context, init_opts); #endif if (pname) k5_free_unparsed_name(context, pname); if (ccache) krb5_cc_close(context, ccache); krb5_free_cred_contents(context, &my_creds); free(k5err); return (code); }
static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gsskrb5_cred 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)); /* * 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) { 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 = get_keytab(context, &keytab); if (kret) goto end; kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) 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); }
OM_uint32 Curl_gss_init_sec_context( struct connectdata *conn, OM_uint32 * minor_status, gss_ctx_id_t * context, gss_name_t target_name, gss_channel_bindings_t input_chan_bindings, gss_buffer_t input_token, gss_buffer_t output_token, OM_uint32 * ret_flags) { krb5_context krb_context = NULL; /* Kerberos context object */ krb5_ccache ccache = NULL; krb5_creds creds; krb5_get_init_creds_opt *opts = NULL; krb5_principal principal = NULL; krb5_keytab ktab = NULL; OM_uint32 min_stat, maj_stat; char *cachename = NULL; char *keytabfile = ""; OM_uint32 major_status; struct SessionHandle *data = conn->data; int ret; OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL; memset(&creds, 0, sizeof(creds)); if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) { #ifdef GSS_C_DELEG_POLICY_FLAG req_flags |= GSS_C_DELEG_POLICY_FLAG; #else infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " "compiled in\n"); #endif } if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) req_flags |= GSS_C_DELEG_FLAG; if((ret = krb5_init_context(&krb_context)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } if ((ret = krb5_parse_name(krb_context, conn->user, &principal)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } if ((ret = krb5_get_init_creds_opt_alloc (krb_context , &opts)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } if (conn->bits.user_keytab) { infof(data, "KRB5_DATA: Keytab location is %s \n", conn->keytab_location); if ((ret = krb5_kt_resolve(krb_context, conn->keytab_location, &ktab)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } if ((ret = krb5_get_init_creds_keytab(krb_context, &creds, principal, ktab, 0, NULL, opts)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } } else if(conn->bits.user_passwd) { infof(data,"KRB5_DATA: Using the user password method \n"); if ((ret = krb5_get_init_creds_password(krb_context,&creds,principal,conn->passwd,NULL,NULL,0,NULL,opts)) != 0 ) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } } else if(conn->bits.credential_cache) { infof(data, "Resolving given credential cache \n"); infof(data, "KRB5_DATA: Credential cache location is %s \n", conn->credential_cache); if ((ret = krb5_cc_resolve(krb_context, conn->credential_cache, &ccache))!=0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } } else if(conn->data->isIntermediateServer) { infof(data, "KRB5_DATA: Curl is carrying a gss credential \n"); major_status = gss_init_sec_context(minor_status, conn->data->deleg_gss_creds, /* cred_handle */ context, target_name, GSS_C_NO_OID, /* mech_type */ req_flags, 0, /* time_req */ input_chan_bindings, input_token, NULL, /* actual_mech_type */ output_token, ret_flags, NULL /* time_rec */); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return major_status; } else { infof(data, "KRB5_DATA: Passed no password/keytab location, using default credentials\n "); conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL; major_status = gss_init_sec_context(minor_status, conn->data->curl_gss_creds, /* cred_handle */ context, target_name, GSS_C_NO_OID, /* mech_type */ req_flags, 0, /* time_req */ input_chan_bindings, input_token, NULL, /* actual_mech_type */ output_token, ret_flags, NULL /* time_rec */); curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); return major_status; } if(!conn->bits.credential_cache) { infof(data, "Creating new credential cache, since none specified \n"); if((ret = krb5_cc_new_unique( krb_context, "MEMORY", NULL, &ccache)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } infof(data, "Initializing credential cache \n"); if ((ret = krb5_cc_initialize(krb_context, ccache, principal))!=0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } infof(data, "Storing credential within credential cache \n"); if ((ret = krb5_cc_store_cred(krb_context,ccache,&creds)) != 0) { curl_krb5_print_error_message(krb_context, ret, data); curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED ; } } infof(data, "Attempting to import the credential \n"); if ((maj_stat = gss_krb5_import_cred(&min_stat, ccache, principal, NULL, &conn->data->curl_gss_creds))!=0) { infof(data, "Importing krb5 credential into gss credentials failed\n"); curl_krb5_print_error_message(krb_context, min_stat, data); if(conn->bits.credential_cache) curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); else curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab); return CURLE_KERBEROS_AUTH_FAILED; } infof(data, "Able to convert the credential \n"); infof(data, "Attempting init sec context \n"); major_status = gss_init_sec_context(minor_status, conn->data->curl_gss_creds, /* cred_handle */ context, target_name, GSS_C_NO_OID, /* mech_type */ req_flags, 0, /* time_req */ input_chan_bindings, input_token, NULL, /* actual_mech_type */ output_token, ret_flags, NULL /* time_rec */); if(conn->bits.credential_cache) curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab); else curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab); return major_status; }
static krb5_error_code get_vfy_cred(krb5_context context, krb5_creds *creds, krb5_principal server, krb5_keytab keytab, krb5_ccache *ccache_arg) { krb5_error_code ret; krb5_ccache ccache = NULL, retcc = NULL; krb5_creds in_creds, *out_creds = NULL; krb5_auth_context authcon = NULL; krb5_data ap_req = empty_data(); /* If the creds are for the server principal, we're set, just do a mk_req. * Otherwise, do a get_credentials first. */ if (krb5_principal_compare(context, server, creds->server)) { /* Make an ap-req. */ ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req); if (ret) goto cleanup; } else { /* * This is unclean, but it's the easiest way without ripping the * library into very small pieces. store the client's initial cred * in a memory ccache, then call the library. Later, we'll copy * everything except the initial cred into the ccache we return to * the user. A clean implementation would involve library * internals with a coherent idea of "in" and "out". */ /* Insert the initial cred into the ccache. */ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache); if (ret) goto cleanup; ret = krb5_cc_initialize(context, ccache, creds->client); if (ret) goto cleanup; ret = krb5_cc_store_cred(context, ccache, creds); if (ret) goto cleanup; /* Get credentials with get_creds. */ memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = creds->client; in_creds.server = server; ret = krb5_timeofday(context, &in_creds.times.endtime); if (ret) goto cleanup; in_creds.times.endtime += 5*60; ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds); if (ret) goto cleanup; /* Make an ap-req. */ ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds, &ap_req); if (ret) goto cleanup; } /* Wipe the auth context created by mk_req. */ if (authcon) { krb5_auth_con_free(context, authcon); authcon = NULL; } /* Verify the ap_req. */ ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL); if (ret) goto cleanup; /* If we get this far, then the verification succeeded. We can * still fail if the library stuff here fails, but that's it. */ if (ccache_arg != NULL && ccache != NULL) { if (*ccache_arg == NULL) { ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc); if (ret) goto cleanup; ret = krb5_cc_initialize(context, retcc, creds->client); if (ret) goto cleanup; ret = copy_creds_except(context, ccache, retcc, creds->server); if (ret) goto cleanup; *ccache_arg = retcc; retcc = NULL; } else { ret = copy_creds_except(context, ccache, *ccache_arg, server); } } cleanup: if (retcc != NULL) krb5_cc_destroy(context, retcc); if (ccache != NULL) krb5_cc_destroy(context, ccache); krb5_free_creds(context, out_creds); krb5_auth_con_free(context, authcon); krb5_free_data_contents(context, &ap_req); return ret; }
NTSTATUS SMBCredTokenToKrb5CredCache( PIO_CREDS pCredToken, PSTR* ppszCachePath ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pContext = NULL; krb5_error_code krb5Error = 0; krb5_ccache pCache = NULL; PSTR pszClientPrincipalName = NULL; PSTR pszServerPrincipalName = NULL; PSTR pszCachePath = NULL; krb5_creds creds; memset(&creds, 0, sizeof(creds)); /* Set up an in-memory cache to receive the credentials */ Status = SMBAllocateStringPrintf( &pszCachePath, "MEMORY:%lu", (unsigned long) (size_t) ppszCachePath); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_init_context(&pContext); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } krb5Error = krb5_cc_resolve(pContext, pszCachePath, &pCache); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Convert cred token back into krb5 structure */ /* Convert client and server principal names */ Status = LwRtlCStringAllocateFromWC16String( &pszClientPrincipalName, pCredToken->payload.krb5Tgt.pwszClientPrincipal); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_parse_name(pContext, pszClientPrincipalName, &creds.client); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } Status = LwRtlCStringAllocateFromWC16String( &pszServerPrincipalName, pCredToken->payload.krb5Tgt.pwszServerPrincipal); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_parse_name(pContext, pszServerPrincipalName, &creds.server); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Convert times */ creds.times.authtime = pCredToken->payload.krb5Tgt.authTime; creds.times.starttime = pCredToken->payload.krb5Tgt.startTime; creds.times.endtime = pCredToken->payload.krb5Tgt.endTime; creds.times.renew_till = pCredToken->payload.krb5Tgt.renewTillTime; /* Convert encryption key */ creds.keyblock.enctype = pCredToken->payload.krb5Tgt.keyType; creds.keyblock.length = (unsigned int) pCredToken->payload.krb5Tgt.ulKeySize; creds.keyblock.contents = pCredToken->payload.krb5Tgt.pKeyData; /* Convert tgt */ creds.ticket_flags = pCredToken->payload.krb5Tgt.tgtFlags; creds.ticket.length = pCredToken->payload.krb5Tgt.ulTgtSize; creds.ticket.data = (char*) pCredToken->payload.krb5Tgt.pTgtData; /* Initialize the credential cache with the client principal name */ krb5Error = krb5_cc_initialize(pContext, pCache, creds.client); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Store the converted credentials in the cache */ krb5Error = krb5_cc_store_cred(pContext, pCache, &creds); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } *ppszCachePath = pszCachePath; cleanup: LWIO_SAFE_FREE_MEMORY(pszClientPrincipalName); LWIO_SAFE_FREE_MEMORY(pszServerPrincipalName); if (creds.client) { krb5_free_principal(pContext, creds.client); } if (creds.server) { krb5_free_principal(pContext, creds.server); } if (pCache) { krb5_cc_close(pContext, pCache); } if (pContext) { krb5_free_context(pContext); } return Status; error: *ppszCachePath = NULL; LWIO_SAFE_FREE_MEMORY(pszCachePath); goto cleanup; }
krb5_error_code KRB5_CALLCONV krb5_get_credentials(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds) { krb5_error_code retval; krb5_creds mcreds; krb5_creds *ncreds; krb5_creds **tgts; krb5_flags fields; int not_ktype; retval = krb5_get_credentials_core(context, options, in_creds, &mcreds, &fields); if (retval) return retval; if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) return ENOMEM; memset((char *)ncreds, 0, sizeof(krb5_creds)); ncreds->magic = KV5M_CREDS; /* The caller is now responsible for cleaning up in_creds */ if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds, ncreds))) { krb5_xfree(ncreds); ncreds = in_creds; } else { *out_creds = ncreds; } if ((retval != KRB5_CC_NOTFOUND && retval != KRB5_CC_NOT_KTYPE) || options & KRB5_GC_CACHED) return retval; if (retval == KRB5_CC_NOT_KTYPE) not_ktype = 1; else not_ktype = 0; retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts); if (tgts) { register int i = 0; krb5_error_code rv2; while (tgts[i]) { if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i]))) { retval = rv2; break; } i++; } krb5_free_tgt_creds(context, tgts); } /* * Translate KRB5_CC_NOTFOUND if we previously got * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to * handle the case where there is no TGT in the ccache and the * input enctype didn't match. This handling is necessary because * some callers, such as GSSAPI, iterate through enctypes and * KRB5_CC_NOTFOUND passed through from the * krb5_get_cred_from_kdc() is semantically incorrect, since the * actual failure was the non-existence of a ticket of the correct * enctype rather than the missing TGT. */ if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE) && not_ktype) retval = KRB5_CC_NOT_KTYPE; if (!retval) { /* the purpose of the krb5_get_credentials call is to * obtain a set of credentials for the caller. the * krb5_cc_store_cred() call is to optimize performance * for future calls. Ignore any errors, since the credentials * are still valid even if we fail to store them in the cache. */ krb5_cc_store_cred(context, ccache, *out_creds); } return retval; }
/* * VmDirLoginUser Creates a TGT cache for the Process to * communicate with the VmDir */ DWORD VmDirKrb5LoginUser( PCSTR pszUserName, PCSTR pszPassword, PCSTR pszKrb5ConfPath /* Optional */ ) { DWORD dwError = 0; krb5_context context = NULL; krb5_get_init_creds_opt *opt = NULL; krb5_principal principal = NULL; krb5_ccache ccache = NULL; krb5_creds creds = { 0 }; PSTR pszCacheName = NULL; if (!IsNullOrEmptyString(pszKrb5ConfPath)) { setenv(KRB5_CONF_PATH, pszKrb5ConfPath, 1); } dwError = VmDirMapKrbError( krb5_init_context(&context) ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirMapKrbError( krb5_get_init_creds_opt_alloc(context, &opt) ); BAIL_ON_VMDIR_ERROR(dwError); krb5_get_init_creds_opt_set_tkt_life(opt, 8 * 60 * 60); //8 hours ticket krb5_get_init_creds_opt_set_forwardable(opt, 1); // Creates a File based Credential cache based on defaults dwError = VmDirMapKrbError( krb5_cc_new_unique( context, "FILE", "hint", &ccache) ); BAIL_ON_VMDIR_ERROR(dwError); // it is assumed that pszUserName is in user@REALM format. dwError = VmDirMapKrbError( krb5_parse_name(context, pszUserName, &principal) ); BAIL_ON_VMDIR_ERROR(dwError); // Let us get the Creds from the Kerberos Server dwError = VmDirMapKrbError( krb5_get_init_creds_password( context, &creds, principal, (PSTR) pszPassword, NULL, NULL, 0, NULL, opt) ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirMapKrbError( krb5_cc_initialize(context, ccache, principal) ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirMapKrbError( krb5_cc_store_cred(context, ccache, &creds) ); BAIL_ON_VMDIR_ERROR(dwError); pszCacheName = (PSTR)krb5_cc_get_name(context, ccache); if ( pszCacheName == NULL) { dwError = ERROR_NO_CRED_CACHE_NAME; BAIL_ON_VMDIR_ERROR(dwError); } // let us set the Value to the Env. Variable so GSSAPI can find it. setenv(KRB5_CC_NAME, pszCacheName, 1); krb5_cc_set_default_name(context, pszCacheName); error: if (principal != NULL) { krb5_free_principal(context, principal); } if (opt != NULL) { krb5_get_init_creds_opt_free(context,opt); } krb5_free_cred_contents(context, &creds); if (context != NULL) { krb5_free_context(context); } return dwError; }
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) { krb5_context kcontext = NULL; krb5_keytab keytab = NULL; krb5_principal s_princ = NULL; krb5_principal c_princ = NULL; krb5_creds c_creds; krb5_ccache c_ccache = NULL; krb5_ccache ret_ccache = NULL; krb5_error_code code; int ret; buffer *sprinc; buffer *user_at_realm = NULL; plugin_data * const p = (plugin_data *)p_d; if (*pw == '\0') { log_error_write(srv, __FILE__, __LINE__, "s", "Empty passwords are not accepted"); return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); } mod_authn_gssapi_patch_connection(srv, con, p); code = krb5_init_context(&kcontext); if (code) { log_error_write(srv, __FILE__, __LINE__, "sd", "krb5_init_context():", code); return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/ } code = krb5_kt_resolve(kcontext, p->conf.auth_gssapi_keytab->ptr, &keytab); if (code) { log_error_write(srv, __FILE__, __LINE__, "sdb", "krb5_kt_resolve():", code, p->conf.auth_gssapi_keytab); return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/ } sprinc = buffer_init_buffer(p->conf.auth_gssapi_principal); if (strchr(sprinc->ptr, '/') == NULL) { /*(copy HTTP Host, omitting port if port is present)*/ /* ??? Should con->server_name be used if http_host not present? * ??? What if con->server_name is not set? * ??? Will this work below if IPv6 provided in Host? probably not */ if (!buffer_is_empty(con->request.http_host)) { buffer_append_string(sprinc, "/"); buffer_append_string_len(sprinc, con->request.http_host->ptr, strcspn(con->request.http_host->ptr, ":")); } } /*(init c_creds before anything which might krb5_free_cred_contents())*/ memset(&c_creds, 0, sizeof(c_creds)); ret = krb5_parse_name(kcontext, sprinc->ptr, &s_princ); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", sprinc->ptr, kcontext, ret); ret = -1; goto end; } if (strchr(username->ptr, '@') == NULL) { user_at_realm = buffer_init_buffer(username); BUFFER_APPEND_STRING_CONST(user_at_realm, "@"); buffer_append_string_buffer(user_at_realm, require->realm); } ret = krb5_parse_name(kcontext, (user_at_realm ? user_at_realm->ptr : username->ptr), &c_princ); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", (user_at_realm ? user_at_realm->ptr : username->ptr), kcontext, ret); if (user_at_realm) buffer_free(user_at_realm); ret = -1; goto end; } if (user_at_realm) buffer_free(user_at_realm); /* XXX: if the qualified username with @realm should be in REMOTE_USER, * then http_auth_backend_t basic interface needs to change to pass * modifiable buffer *username, but note that const char *pw follows * in the truncated buffer *username, so pw would need to be copied * before modifying buffer *username */ /* * char *name = NULL; * ret = krb5_unparse_name(kcontext, c_princ, &name); * if (ret == 0) { * log_error_write(srv, __FILE__, __LINE__, "sbss", "Trying to get TGT for user:"******"password:"******"krb5_get_init_creds_password", NULL, kcontext, ret); goto end; } ret = mod_authn_gssapi_verify_krb5_init_creds(srv, kcontext, &c_creds, s_princ, keytab); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "mod_authn_gssapi_verify_krb5_init_creds", NULL, kcontext, ret); goto end; } ret = krb5_cc_resolve(kcontext, "MEMORY:", &ret_ccache); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_resolve", NULL, kcontext, ret); goto end; } ret = krb5_cc_initialize(kcontext, ret_ccache, c_princ); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_initialize", NULL, kcontext, ret); goto end; } ret = krb5_cc_store_cred(kcontext, ret_ccache, &c_creds); if (ret) { mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_store_cred", NULL, kcontext, ret); goto end; } c_ccache = ret_ccache; ret_ccache = NULL; end: krb5_free_cred_contents(kcontext, &c_creds); if (ret_ccache) krb5_cc_destroy(kcontext, ret_ccache); if (!ret && c_ccache && (ret = mod_authn_gssapi_store_krb5_creds(srv, con, p, kcontext, c_ccache))) { log_error_write(srv, __FILE__, __LINE__, "sb", "mod_authn_gssapi_store_krb5_creds failed for", username); } buffer_free(sprinc); if (c_princ) krb5_free_principal(kcontext, c_princ); if (s_princ) krb5_free_principal(kcontext, s_princ); if (c_ccache) krb5_cc_destroy(kcontext, c_ccache); if (keytab) krb5_kt_close(kcontext, keytab); krb5_free_context(kcontext); if (0 == ret && http_auth_match_rules(require,username->ptr,NULL,NULL)){ return HANDLER_GO_ON; } else { /* ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN or no authz rules match */ log_error_write(srv, __FILE__, __LINE__, "sbsBsB", "password doesn't match for", con->uri.path, "username:"******", IP:", con->dst_addr_buf); return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); } }
static int create_krb5_cred(krb5_context ctx, char *realm, char *user, char *password, char *ktname, krb5_ccache *ccache, gss_cred_id_t *gsscred, char **errmsg) { int rc = 0, len = 0; unsigned int minor_stat = 0, major_stat = 0; const char *errmsg_tmp = NULL; const char *cctype = NULL; char *cname = NULL; krb5_ccache defcc = NULL; krb5_creds creds; krb5_principal princ = NULL; krb5_keytab keytab = NULL; gss_key_value_element_desc elems[2]; gss_key_value_set_desc store; gss_name_t sname = NULL; gss_buffer_desc pr_name; pr_name.value = NULL; pr_name.length = 0; store.count = 0; store.elements = elems; if (user == NULL || realm == NULL) return 1; len = strlen(realm); if (len == 0 || strlen(user) == 0) return 0; DEBUG("create_krb5_cred (ctx:%p, realm:%s, user:%s, password:%s, ktname: %s," " ccache:%p, gsscred:%p)", ctx, realm, user, "****", ktname, ccache, gsscred); rc = krb5_cc_default(ctx, &defcc); if (rc != 0) goto end; cctype = krb5_cc_get_type(ctx, defcc); rc = krb5_cc_new_unique(ctx, cctype, NULL, ccache); if (rc != 0) goto end; rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL); if (rc != 0) goto end; rc = krb5_cc_initialize(ctx, *ccache, princ); if (rc != 0) goto end; if (password != NULL && strlen(password) > 0) { rc = krb5_get_init_creds_password(ctx, &creds, princ, password, 0, NULL, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; } if (ktname != NULL && strlen(ktname) > 0) { rc = krb5_kt_resolve(ctx, ktname, &keytab); if (rc != 0) goto end; rc = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "client_keytab"; store.elements[store.count].value = ktname; store.count++; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; rc = krb5_unparse_name(ctx, princ, (char**)&pr_name.value); if (rc != 0) goto end; pr_name.length = strlen(pr_name.value); major_stat = gss_import_name(&minor_stat, &pr_name, GSS_KRB5_NT_PRINCIPAL_NAME, &sname); if (major_stat != 0) goto end; } // Does not work with GSS-SPENGO. //major_stat = gss_krb5_import_cred(&minor_stat, *ccache, princ, NULL, gsscred); major_stat = gss_acquire_cred_from(&minor_stat, sname, 0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &store, gsscred, NULL, NULL); end: if (keytab != NULL) krb5_kt_close(ctx, keytab); if (princ != NULL) krb5_free_principal(ctx, princ); if (defcc != NULL) krb5_cc_close(ctx, defcc); if (cname != NULL) free(cname); if (pr_name.value != NULL) krb5_free_unparsed_name(ctx, pr_name.value); if (sname != NULL) { major_stat = gss_release_name(&minor_stat, &sname); } if (rc != 0) { /* Create error message with the error code. */ errmsg_tmp = krb5_get_error_message(ctx, rc); if (errmsg != NULL && errmsg_tmp != NULL) { len = strlen(errmsg_tmp) + 26; *errmsg = (char *)malloc(len); if (*errmsg == NULL) { krb5_free_error_message(ctx, errmsg_tmp); return -1; } snprintf(*errmsg, len,"%s. (KRB5_ERROR 0x%08x)", errmsg_tmp, rc); } krb5_free_error_message(ctx, errmsg_tmp); } if (major_stat != 0) return major_stat; return rc; }
static char * init_cc_from_keytab(const char *keytab_name, const char *user) { krb5_context context = NULL; krb5_error_code ret; krb5_creds my_creds; krb5_keytab keytab = NULL; krb5_principal me = NULL; krb5_ccache cc = NULL; char *ccname = NULL; memset((char *) &my_creds, 0, sizeof(my_creds)); ret = krb5_init_context(&context); if (ret) { syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret); goto icfk_cleanup; } ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { syslog(LOG_DEBUG, "krb5_kt_resolve: %d", (int)ret); goto icfk_cleanup; } ret = krb5_parse_name(context, user, &me); if (ret) { syslog(LOG_DEBUG, "krb5_parse_name: %d", (int)ret); goto icfk_cleanup; } ret = krb5_get_init_creds_keytab(context, &my_creds, me, keytab, 0, NULL, NULL); if (ret) { syslog(LOG_DEBUG, "krb5_get_init_creds_keytab: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_default(context, &cc); if (ret) { syslog(LOG_DEBUG, "krb5_cc_default: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_initialize(context, cc, me); if (ret) { syslog(LOG_DEBUG, "krb5_cc_initialize: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_store_cred(context, cc, &my_creds); if (ret) syslog(LOG_DEBUG, "krb5_cc_store_cred: %d", (int)ret); ccname = strdup(krb5_cc_default_name(context)); if (ccname == NULL) syslog(LOG_ERR, "Unable to allocate memory"); icfk_cleanup: my_creds.client = 0; krb5_free_cred_contents(context, &my_creds); if (me) krb5_free_principal(context, me); if (cc) krb5_cc_close(context, cc); if (keytab) krb5_kt_close(context, keytab); if (context) krb5_free_context(context); return ccname; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab, krb5_ccache *ccache, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_data req; krb5_ccache local_ccache = NULL; krb5_creds *new_creds = NULL; krb5_auth_context auth_context = NULL; krb5_principal server = NULL; krb5_keytab keytab = NULL; krb5_data_zero (&req); if (ap_req_server == NULL) { char local_hostname[MAXHOSTNAMELEN]; if (gethostname (local_hostname, sizeof(local_hostname)) < 0) { ret = errno; krb5_set_error_message (context, ret, "gethostname: %s", strerror(ret)); return ret; } ret = krb5_sname_to_principal (context, local_hostname, "host", KRB5_NT_SRV_HST, &server); if (ret) goto cleanup; } else server = ap_req_server; if (ap_req_keytab == NULL) { ret = krb5_kt_default (context, &keytab); if (ret) goto cleanup; } else keytab = ap_req_keytab; if (ccache && *ccache) local_ccache = *ccache; else { ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &local_ccache); if (ret) goto cleanup; ret = krb5_cc_initialize (context, local_ccache, creds->client); if (ret) goto cleanup; ret = krb5_cc_store_cred (context, local_ccache, creds); if (ret) goto cleanup; } if (!krb5_principal_compare (context, server, creds->server)) { krb5_creds match_cred; memset (&match_cred, 0, sizeof(match_cred)); match_cred.client = creds->client; match_cred.server = server; ret = krb5_get_credentials (context, 0, local_ccache, &match_cred, &new_creds); if (ret) { if (fail_verify_is_ok (context, options)) ret = 0; goto cleanup; } creds = new_creds; } ret = krb5_mk_req_extended (context, &auth_context, 0, NULL, creds, &req); krb5_auth_con_free (context, auth_context); auth_context = NULL; if (ret) goto cleanup; ret = krb5_rd_req (context, &auth_context, &req, server, keytab, 0, NULL); if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options)) ret = 0; cleanup: if (auth_context) krb5_auth_con_free (context, auth_context); krb5_data_free (&req); if (new_creds != NULL) krb5_free_creds (context, new_creds); if (ap_req_server == NULL && server) krb5_free_principal (context, server); if (ap_req_keytab == NULL && keytab) krb5_kt_close (context, keytab); if (local_ccache != NULL && (ccache == NULL || (ret != 0 && *ccache == NULL))) krb5_cc_destroy (context, local_ccache); if (ret == 0 && ccache != NULL && *ccache == NULL) *ccache = local_ccache; return ret; }
int auth_krb5_password(Authctxt *authctxt, const char *password) { #ifndef HEIMDAL krb5_creds creds; krb5_principal server; #endif krb5_error_code problem; krb5_ccache ccache = NULL; int len; char *client, *platform_client; const char *errmsg; /* get platform-specific kerberos client principal name (if it exists) */ platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name); client = platform_client ? platform_client : authctxt->pw->pw_name; temporarily_use_uid(authctxt->pw); problem = krb5_init(authctxt); if (problem) goto out; problem = krb5_parse_name(authctxt->krb5_ctx, client, &authctxt->krb5_user); if (problem) goto out; #ifdef HEIMDAL # ifdef HAVE_KRB5_CC_NEW_UNIQUE problem = krb5_cc_new_unique(authctxt->krb5_ctx, krb5_mcc_ops.prefix, NULL, &ccache); # else problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache); # endif if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto out; restore_uid(); problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, ccache, password, 1, NULL); temporarily_use_uid(authctxt->pw); if (problem) goto out; # ifdef HAVE_KRB5_CC_NEW_UNIQUE problem = krb5_cc_new_unique(authctxt->krb5_ctx, krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache); # else problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &authctxt->krb5_fwd_ccache); # endif if (problem) goto out; problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache, authctxt->krb5_fwd_ccache); krb5_cc_destroy(authctxt->krb5_ctx, ccache); ccache = NULL; if (problem) goto out; #else problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); if (problem) goto out; problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, KRB5_NT_SRV_HST, &server); if (problem) goto out; restore_uid(); problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, NULL, NULL, NULL); krb5_free_principal(authctxt->krb5_ctx, server); temporarily_use_uid(authctxt->pw); if (problem) goto out; if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name)) { problem = -1; goto out; } problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache); if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, authctxt->krb5_user); if (problem) goto out; problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, &creds); if (problem) goto out; #endif authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); len = strlen(authctxt->krb5_ticket_file) + 6; authctxt->krb5_ccname = xmalloc(len); #ifdef USE_CCAPI snprintf(authctxt->krb5_ccname, len, "API:%s", authctxt->krb5_ticket_file); #else snprintf(authctxt->krb5_ccname, len, "FILE:%s", authctxt->krb5_ticket_file); #endif #ifdef USE_PAM if (options.use_pam) do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); #endif out: restore_uid(); free(platform_client); if (problem) { if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); if (authctxt->krb5_ctx != NULL && problem!=-1) { errmsg = krb5_get_error_message(authctxt->krb5_ctx, problem); debug("Kerberos password authentication failed: %s", errmsg); krb5_free_error_message(authctxt->krb5_ctx, errmsg); } else debug("Kerberos password authentication failed: %d", problem); krb5_cleanup_proc(authctxt); if (options.kerberos_or_local_passwd) return (-1); else return (0); } return (authctxt->valid ? 1 : 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; }
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); }
int auth_krb5_password(Authctxt *authctxt, const char *password) { #ifndef HEIMDAL krb5_creds creds; krb5_principal server; char ccname[40]; int tmpfd; mode_t old_umask; #endif krb5_error_code problem; krb5_ccache ccache = NULL; int len; if (!authctxt->valid) return (0); temporarily_use_uid(authctxt->pw); problem = krb5_init(authctxt); if (problem) goto out; problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, &authctxt->krb5_user); if (problem) goto out; #ifdef HEIMDAL problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache); if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto out; restore_uid(); problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, ccache, password, 1, NULL); temporarily_use_uid(authctxt->pw); if (problem) goto out; problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &authctxt->krb5_fwd_ccache); if (problem) goto out; problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache, authctxt->krb5_fwd_ccache); krb5_cc_destroy(authctxt->krb5_ctx, ccache); ccache = NULL; if (problem) goto out; #else problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); if (problem) goto out; problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, KRB5_NT_SRV_HST, &server); if (problem) goto out; restore_uid(); problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, NULL, NULL, NULL); krb5_free_principal(authctxt->krb5_ctx, server); temporarily_use_uid(authctxt->pw); if (problem) goto out; if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name)) { problem = -1; goto out; } snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); old_umask = umask(0177); tmpfd = mkstemp(ccname + strlen("FILE:")); umask(old_umask); if (tmpfd == -1) { logit("mkstemp(): %.100s", strerror(errno)); problem = errno; goto out; } if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { logit("fchmod(): %.100s", strerror(errno)); close(tmpfd); problem = errno; goto out; } close(tmpfd); problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, authctxt->krb5_user); if (problem) goto out; problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, &creds); if (problem) goto out; #endif authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); len = strlen(authctxt->krb5_ticket_file) + 6; authctxt->krb5_ccname = xmalloc(len); snprintf(authctxt->krb5_ccname, len, "FILE:%s", authctxt->krb5_ticket_file); out: restore_uid(); if (problem) { if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); if (authctxt->krb5_ctx != NULL && problem!=-1) debug("Kerberos password authentication failed: %s", krb5_get_err_text(authctxt->krb5_ctx, problem)); else debug("Kerberos password authentication failed: %d", problem); krb5_cleanup_proc(authctxt); if (options.kerberos_or_local_passwd) return (-1); else return (0); } return (1); }
/* returns boolean */ static int k5_kinit(struct k_opts *opts, struct k5_data *k5, struct user_info *u_info) { char *doing; int notix = 1; krb5_keytab keytab = 0; krb5_creds my_creds; krb5_error_code code = 0; krb5_get_init_creds_opt options; krb5_address **addresses; krb5_get_init_creds_opt_init(&options); g_memset(&my_creds, 0, sizeof(my_creds)); /* From this point on, we can goto cleanup because my_creds is initialized. */ if (opts->lifetime) { krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime); } if (opts->rlife) { krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife); } if (opts->forwardable) { krb5_get_init_creds_opt_set_forwardable(&options, 1); } if (opts->not_forwardable) { krb5_get_init_creds_opt_set_forwardable(&options, 0); } if (opts->proxiable) { krb5_get_init_creds_opt_set_proxiable(&options, 1); } if (opts->not_proxiable) { krb5_get_init_creds_opt_set_proxiable(&options, 0); } if (opts->addresses) { addresses = NULL; code = krb5_os_localaddr(k5->ctx, &addresses); if (code != 0) { g_printf("krb5_os_localaddr failed in k5_kinit\n"); goto cleanup; } krb5_get_init_creds_opt_set_address_list(&options, addresses); } if (opts->no_addresses) { krb5_get_init_creds_opt_set_address_list(&options, NULL); } if ((opts->action == INIT_KT) && opts->keytab_name) { code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); if (code != 0) { g_printf("krb5_kt_resolve failed in k5_kinit\n"); goto cleanup; } } switch (opts->action) { case INIT_PW: code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, 0, kinit_prompter, u_info, opts->starttime, opts->service_name, &options); break; case INIT_KT: code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, keytab, opts->starttime, opts->service_name, &options); break; case VALIDATE: code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc, opts->service_name); break; case RENEW: code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc, opts->service_name); break; } if (code != 0) { doing = 0; switch (opts->action) { case INIT_PW: case INIT_KT: doing = "getting initial credentials"; break; case VALIDATE: doing = "validating credentials"; break; case RENEW: doing = "renewing credentials"; break; } if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { g_printf("sesman: Password incorrect while %s in k5_kinit\n", doing); } else { g_printf("sesman: error while %s in k5_kinit\n", doing); } goto cleanup; } if (!opts->lifetime) { /* We need to figure out what lifetime to use for Kerberos 4. */ opts->lifetime = my_creds.times.endtime - my_creds.times.authtime; } code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me); if (code != 0) { g_printf("krb5_cc_initialize failed in k5_kinit\n"); goto cleanup; } code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds); if (code != 0) { g_printf("krb5_cc_store_cred failed in k5_kinit\n"); goto cleanup; } notix = 0; cleanup: if (my_creds.client == k5->me) { my_creds.client = 0; } krb5_free_cred_contents(k5->ctx, &my_creds); if (keytab) { krb5_kt_close(k5->ctx, keytab); } return notix ? 0 : 1; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_cred(OM_uint32 * minor_status, gss_buffer_t cred_token, gss_cred_id_t * cred_handle) { krb5_context context; krb5_error_code ret; gsskrb5_cred handle; krb5_ccache id; krb5_storage *sp; char *str; uint32_t type; int flags = 0; *cred_handle = GSS_C_NO_CREDENTIAL; GSSAPI_KRB5_INIT (&context); sp = krb5_storage_from_mem(cred_token->value, cred_token->length); if (sp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } ret = krb5_ret_uint32(sp, &type); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } switch (type) { case 0: { krb5_creds creds; ret = krb5_ret_creds(sp, &creds); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_new_unique(context, "API", NULL, &id); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_initialize(context, id, creds.client); if (ret) { krb5_cc_destroy(context, id); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_store_cred(context, id, &creds); krb5_free_cred_contents(context, &creds); if (ret) { krb5_cc_destroy(context, id); *minor_status = ret; return GSS_S_FAILURE; } flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; break; } case 1: ret = krb5_ret_string(sp, &str); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_resolve(context, str, &id); krb5_xfree(str); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } break; default: krb5_storage_free(sp); *minor_status = 0; return GSS_S_NO_CRED; } handle = calloc(1, sizeof(*handle)); if (handle == NULL) { krb5_cc_close(context, id); *minor_status = ENOMEM; return GSS_S_FAILURE; } handle->usage = GSS_C_INITIATE; krb5_cc_get_principal(context, id, &handle->principal); handle->ccache = id; handle->cred_flags = flags; if (handle->principal) __gsskrb5_ccache_lifetime(minor_status, context, id, handle->principal, &handle->endtime); *cred_handle = (gss_cred_id_t)handle; return GSS_S_COMPLETE; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds *out; int optidx = 0; krb5_get_creds_opt opt; krb5_principal server; krb5_principal impersonate = NULL; 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 (argc != 1) usage (1); 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, "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); } 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 (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_string(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); } ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]); if (nametype_str) { ret = krb5_parse_nametype(context, nametype_str, &server->name.name_type); if (ret) krb5_err(context, 1, ret, "krb5_parse_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; }
DWORD LwKrb5CopyFromUserCache( krb5_context ctx, krb5_ccache destCC, uid_t uid ) { DWORD dwError = LW_ERROR_SUCCESS; PSTR pszCachePath = NULL; krb5_ccache srcCC = NULL; krb5_cc_cursor srcPos = NULL; krb5_cc_cursor destPos = NULL; // Free with krb5_free_cred_contents krb5_creds srcCreds = {0}; // Free with krb5_free_cred_contents krb5_creds destCreds = {0}; krb5_error_code ret = 0; krb5_principal destClient = 0; BOOLEAN bIncludeTicket = TRUE; DWORD dwTime = 0; ret = krb5_cc_get_principal( ctx, destCC, &destClient); BAIL_ON_KRB_ERROR(ctx, ret); dwError = LwKrb5GetUserCachePath( uid, KRB5_File_Cache, &pszCachePath); BAIL_ON_LW_ERROR(dwError); ret = krb5_cc_resolve( ctx, pszCachePath, &srcCC); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_cc_start_seq_get( ctx, srcCC, &srcPos); if (ret == KRB5_FCC_NOFILE) { // The cache file does not exist ret = 0; goto cleanup; } if (ret == KRB5_CC_FORMAT) { // Some other user put a bad cc in place - don't copy anything // from it. ret = 0; goto cleanup; } BAIL_ON_KRB_ERROR(ctx, ret); dwTime = time(NULL); while (1) { krb5_free_cred_contents( ctx, &srcCreds); ret = krb5_cc_next_cred( ctx, srcCC, &srcPos, &srcCreds); if (ret == KRB5_CC_FORMAT) { break; } else if (ret == KRB5_CC_END) { break; } else { BAIL_ON_KRB_ERROR(ctx, ret); } if (!krb5_principal_compare(ctx, destClient, srcCreds.client)) { /* Can't keep these creds. The client principal doesn't * match. */ continue; } if ( srcCreds.times.endtime < dwTime ) { /* Credentials are too old. */ continue; } if (destPos != NULL) { krb5_cc_end_seq_get( ctx, destCC, &destPos); destPos = NULL; } ret = krb5_cc_start_seq_get( ctx, destCC, &destPos); BAIL_ON_KRB_ERROR(ctx, ret); bIncludeTicket = TRUE; while(bIncludeTicket) { krb5_free_cred_contents( ctx, &destCreds); ret = krb5_cc_next_cred( ctx, destCC, &destPos, &destCreds); if (ret == KRB5_CC_END) { break; } else { BAIL_ON_KRB_ERROR(ctx, ret); } if (krb5_principal_compare( ctx, destCreds.server, srcCreds.server)) { /* These credentials are already in the dest cache */ bIncludeTicket = FALSE; } } if (bIncludeTicket) { // These creds can go in the new cache ret = krb5_cc_store_cred(ctx, destCC, &srcCreds); BAIL_ON_KRB_ERROR(ctx, ret); } } cleanup: LW_SAFE_FREE_STRING(pszCachePath); if (ctx != NULL) { if (srcPos != NULL) { krb5_cc_end_seq_get( ctx, srcCC, &srcPos); } if (destPos != NULL) { krb5_cc_end_seq_get( ctx, destCC, &destPos); } if (srcCC != NULL) { krb5_cc_close(ctx, srcCC); } krb5_free_cred_contents(ctx, &srcCreds); krb5_free_cred_contents(ctx, &destCreds); if (destClient != NULL) { krb5_free_principal(ctx, destClient); } } return dwError; error: goto cleanup; }
/* * Function: Process WM_COMMAND messages */ static void kwin_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify) { char name[ANAME_SZ]; char realm[REALM_SZ]; char password[MAX_KPW_LEN]; HCURSOR hcursor; BOOL blogin; HMENU hmenu; char menuitem[MAX_K_NAME_SZ + 3]; char copyright[128]; int id; #ifdef KRB4 char instance[INST_SZ]; int lifetime; int krc; #endif #ifdef KRB5 long lifetime; krb5_error_code code; krb5_principal principal; krb5_creds creds; krb5_get_init_creds_opt opts; gic_data gd; #endif #ifdef KRB4 EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0); #endif #ifdef KRB5 EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred(1) > 0); #endif GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); trim(name); blogin = strlen(name) > 0; if (blogin) { GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); trim(realm); blogin = strlen(realm) > 0; } if (blogin) { GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); blogin = strlen(password) > 0; } EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin); id = (blogin) ? IDD_LOGIN : IDD_PASSWORD_CR2; SendMessage(hwnd, DM_SETDEFID, id, 0); if (codeNotify != BN_CLICKED && codeNotify != 0 && codeNotify != 1) return; /* FALSE */ /* * Check to see if this item is in a list of the ``recent hosts'' sort * of list, under the FILE menu. */ if (cid >= IDM_FIRST_LOGIN && cid < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) { hmenu = GetMenu(hwnd); assert(hmenu != NULL); hmenu = GetSubMenu(hmenu, 0); assert(hmenu != NULL); if (!GetMenuString(hmenu, cid, menuitem, sizeof(menuitem), MF_BYCOMMAND)) return; /* TRUE */ if (menuitem[0]) kwin_init_name(hwnd, &menuitem[3]); return; /* TRUE */ } switch (cid) { case IDM_EXIT: if (isblocking) WSACancelBlockingCall(); WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0); PostQuitMessage(0); return; /* TRUE */ case IDD_PASSWORD_CR2: /* Make CR == TAB */ id = GetDlgCtrlID(GetFocus()); assert(id != 0); if (id == IDD_MAX_EDIT) PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDD_MIN_EDIT), MAKELONG(1, 0)); else PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0); return; /* TRUE */ case IDD_LOGIN: if (isblocking) return; /* TRUE */ GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); trim(name); GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); trim(realm); GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, ""); /* nuke the password */ trim(password); #ifdef KRB4 GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); trim(instance); #endif hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); lifetime = cns_res.lifetime; start_blocking_hook(BLOCK_MAX_SEC); #ifdef KRB4 lifetime = (lifetime + 4) / 5; krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, lifetime, password); #endif #ifdef KRB5 principal = NULL; /* * convert the name + realm into a krb5 principal string and parse it into a principal */ sprintf(menuitem, "%s@%s", name, realm); code = krb5_parse_name(k5_context, menuitem, &principal); if (code) goto errorpoint; /* * set the various ticket options. First, initialize the structure, then set the ticket * to be forwardable if desired, and set the lifetime. */ krb5_get_init_creds_opt_init(&opts); krb5_get_init_creds_opt_set_forwardable(&opts, forwardable); krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime * 60); if (noaddresses) { krb5_get_init_creds_opt_set_address_list(&opts, NULL); } /* * get the initial creds using the password and the options we set above */ gd.hinstance = hinstance; gd.hwnd = hwnd; gd.id = ID_VARDLG; code = krb5_get_init_creds_password(k5_context, &creds, principal, password, gic_prompter, &gd, 0, NULL, &opts); if (code) goto errorpoint; /* * initialize the credential cache */ code = krb5_cc_initialize(k5_context, k5_ccache, principal); if (code) goto errorpoint; /* * insert the principal into the cache */ code = krb5_cc_store_cred(k5_context, k5_ccache, &creds); errorpoint: if (principal) krb5_free_principal(k5_context, principal); end_blocking_hook(); SetCursor(hcursor); kwin_set_default_focus(hwnd); if (code) { if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) MessageBox(hwnd, "Password incorrect", NULL, MB_OK | MB_ICONEXCLAMATION); else com_err(NULL, code, "while logging in"); } #endif /* KRB5 */ #ifdef KRB4 if (krc != KSUCCESS) { MessageBox(hwnd, krb_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); return; /* TRUE */ } #endif kwin_save_name(hwnd); alerted = FALSE; switch (action) { case LOGIN_AND_EXIT: SendMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EXIT, 0, 0)); break; case LOGIN_AND_MINIMIZE: ShowWindow(hwnd, SW_MINIMIZE); break; } return; /* TRUE */ case IDD_TICKET_DELETE: if (isblocking) return; /* TRUE */ #ifdef KRB4 krc = dest_tkt(); if (krc != KSUCCESS) MessageBox(hwnd, krb_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); #endif #ifdef KRB5 code = k5_dest_tkt(); #endif kwin_set_default_focus(hwnd); alerted = FALSE; return; /* TRUE */ case IDD_CHANGE_PASSWORD: if (isblocking) return; /* TRUE */ password_dialog(hwnd); kwin_set_default_focus(hwnd); return; /* TRUE */ case IDM_OPTIONS: if (isblocking) return; /* TRUE */ opts_dialog(hwnd); return; /* TRUE */ case IDM_HELP_INDEX: WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0); return; /* TRUE */ case IDM_ABOUT: ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); if (isblocking) return; /* TRUE */ #ifdef KRB4 strcpy(copyright, " Kerberos 4 for Windows "); #endif #ifdef KRB5 strcpy(copyright, " Kerberos V5 for Windows "); #endif #ifdef _WIN32 strncat(copyright, "32-bit\n", sizeof(copyright) - 1 - strlen(copyright)); #else strncat(copyright, "16-bit\n", sizeof(copyright) - 1 - strlen(copyright)); #endif strncat(copyright, "\n Version 1.12\n\n", sizeof(copyright) - 1 - strlen(copyright)); #ifdef ORGANIZATION strncat(copyright, " For information, contact:\n", sizeof(copyright) - 1 - strlen(copyright)); strncat(copyright, ORGANIZATION, sizeof(copyright) - 1 - strlen(copyright)); #endif MessageBox(hwnd, copyright, KWIN_DIALOG_NAME, MB_OK); return; /* TRUE */ } return; /* FALSE */ }
static int renew_validate(krb5_context context, int renew, int validate, krb5_ccache cache, const char *server, krb5_deltat life) { krb5_error_code ret; krb5_creds in, *out = NULL; krb5_kdc_flags flags; memset(&in, 0, sizeof(in)); ret = krb5_cc_get_principal(context, cache, &in.client); if(ret) { krb5_warn(context, ret, "krb5_cc_get_principal"); return ret; } ret = get_server(context, in.client, server, &in.server); if(ret) { krb5_warn(context, ret, "get_server"); goto out; } if (renew) { /* * no need to check the error here, it's only to be * friendly to the user */ krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); } flags.i = 0; flags.b.renewable = flags.b.renew = renew; flags.b.validate = validate; if (forwardable_flag != -1) flags.b.forwardable = forwardable_flag; else if (out) flags.b.forwardable = out->flags.b.forwardable; if (proxiable_flag != -1) flags.b.proxiable = proxiable_flag; else if (out) flags.b.proxiable = out->flags.b.proxiable; if (anonymous_flag) flags.b.request_anonymous = anonymous_flag; if(life) in.times.endtime = time(NULL) + life; if (out) { krb5_free_creds (context, out); out = NULL; } ret = krb5_get_kdc_cred(context, cache, flags, NULL, NULL, &in, &out); if(ret) { krb5_warn(context, ret, "krb5_get_kdc_cred"); goto out; } ret = krb5_cc_initialize(context, cache, in.client); if(ret) { krb5_free_creds (context, out); krb5_warn(context, ret, "krb5_cc_initialize"); goto out; } ret = krb5_cc_store_cred(context, cache, out); if(ret == 0 && server == NULL) { /* only do this if it's a general renew-my-tgt request */ #ifndef NO_AFS if(do_afslog && k_hasafs()) krb5_afslog(context, cache, NULL, NULL); #endif } krb5_free_creds (context, out); if(ret) { krb5_warn(context, ret, "krb5_cc_store_cred"); goto out; } out: krb5_free_cred_contents(context, &in); return ret; }
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, /* FILE:/tmp/krb5cc_0 */ const char *client_string, /* [email protected] */ const char *service_string, /* krbtgt/[email protected] */ time_t *expire_time) { krb5_error_code ret; krb5_context context = NULL; krb5_ccache ccache = NULL; krb5_principal client = NULL; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { goto done; } if (!ccache_string) { ccache_string = krb5_cc_default_name(context); } DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string)); /* FIXME: we should not fall back to defaults */ ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache); if (ret) { goto done; } #ifdef HAVE_KRB5_GET_RENEWED_CREDS /* MIT */ { krb5_creds creds; if (client_string) { ret = smb_krb5_parse_name(context, client_string, &client); if (ret) { goto done; } } else { ret = krb5_cc_get_principal(context, ccache, &client); if (ret) { goto done; } } ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string)); if (ret) { DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret))); goto done; } /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */ ret = krb5_cc_initialize(context, ccache, client); if (ret) { goto done; } ret = krb5_cc_store_cred(context, ccache, &creds); if (expire_time) { *expire_time = (time_t) creds.times.endtime; } krb5_free_cred_contents(context, &creds); } #elif defined(HAVE_KRB5_GET_KDC_CRED) /* Heimdal */ { krb5_kdc_flags flags; krb5_creds creds_in; krb5_realm *client_realm; krb5_creds *creds; memset(&creds_in, 0, sizeof(creds_in)); if (client_string) { ret = smb_krb5_parse_name(context, client_string, &creds_in.client); if (ret) { goto done; } } else { ret = krb5_cc_get_principal(context, ccache, &creds_in.client); if (ret) { goto done; } } if (service_string) { ret = smb_krb5_parse_name(context, service_string, &creds_in.server); if (ret) { goto done; } } else { /* build tgt service by default */ client_realm = krb5_princ_realm(context, creds_in.client); if (!client_realm) { ret = ENOMEM; goto done; } ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL); if (ret) { goto done; } } flags.i = 0; flags.b.renewable = flags.b.renew = True; ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds); if (ret) { DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret))); goto done; } /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */ ret = krb5_cc_initialize(context, ccache, creds_in.client); if (ret) { goto done; } ret = krb5_cc_store_cred(context, ccache, creds); if (expire_time) { *expire_time = (time_t) creds->times.endtime; } krb5_free_cred_contents(context, &creds_in); krb5_free_creds(context, creds); } #else #error No suitable krb5 ticket renew function available #endif done: if (client) { krb5_free_principal(context, client); } if (context) { krb5_free_context(context); } if (ccache) { krb5_cc_close(context, ccache); } 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; }
krb5_error_code KRB5_LIB_FUNCTION krb5_get_credentials_with_flags(krb5_context context, krb5_flags options, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds) { krb5_error_code ret; krb5_creds **tgts; krb5_creds *res_creds; int i; *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } if (in_creds->session.keytype) options |= KRB5_TC_MATCH_KEYTYPE; /* * If we got a credential, check if credential is expired before * returning it. */ ret = krb5_cc_retrieve_cred(context, ccache, in_creds->session.keytype ? KRB5_TC_MATCH_KEYTYPE : 0, in_creds, res_creds); /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ if (ret == 0) { krb5_timestamp timeret; /* If expired ok, don't bother checking */ if(options & KRB5_GC_EXPIRED_OK) { *out_creds = res_creds; return 0; } krb5_timeofday(context, &timeret); if(res_creds->times.endtime > timeret) { *out_creds = res_creds; return 0; } if(options & KRB5_GC_CACHED) krb5_cc_remove_cred(context, ccache, 0, res_creds); } else if(ret != KRB5_CC_END) { free(res_creds); return ret; } free(res_creds); if(options & KRB5_GC_CACHED) { not_found(context, in_creds->server); return KRB5_CC_NOTFOUND; } if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; if (flags.b.enc_tkt_in_skey) options |= KRB5_GC_NO_STORE; tgts = NULL; ret = get_cred_from_kdc_flags(context, flags, ccache, in_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) krb5_cc_store_cred(context, ccache, *out_creds); return ret; }