/* * Prompt for a password. * * This function handles prompting both for a password for regular * authentication and for passwords when changing one's password. The default * prompt is simply "Password:"******"Kerberos"). * * If args->config->expose_account is set, we append the principal name (taken * from args->config->ctx->princ) before the colon, so the prompts are: * * Password for <principal>: * <prefix> <banner> password for <principal>: * * Normally this is not done because it exposes the realm and possibly any * username to principal mappings, plus may confuse some ssh clients if sshd * passes the prompt back to the client. * * The entered password is stored in password. The memory is allocated by the * application and returned as part of the PAM conversation. It must be freed * by the caller. * * Returns a PAM success or error code. */ int pamk5_get_password(struct pam_args *args, const char *prefix, char **password) { struct context *ctx = args->config->ctx; char *prompt = NULL; char *principal = NULL; krb5_error_code k5_errno; int retval; if (args->config->expose_account || prefix != NULL) if (ctx != NULL && ctx->context != NULL && ctx->princ != NULL) { k5_errno = krb5_unparse_name(ctx->context, ctx->princ, &principal); if (k5_errno != 0) putil_debug_krb5(args, k5_errno, "krb5_unparse_name failed"); } if (prefix == NULL) { if (args->config->expose_account && principal != NULL) { if (asprintf(&prompt, "Password for %s: ", principal) < 0) goto fail; } else { prompt = strdup("Password: "******"" : args->config->banner; bspace = (args->config->banner == NULL) ? "" : " "; if (args->config->expose_account && principal != NULL) { retval = asprintf(&prompt, "%s%s%s password for %s: ", prefix, bspace, banner, principal); if (retval < 0) goto fail; } else { retval = asprintf(&prompt, "%s%s%s password: ", prefix, bspace, banner); if (retval < 0) goto fail; } } if (principal != NULL) krb5_free_unparsed_name(ctx->context, principal); retval = pamk5_conv(args, prompt, PAM_PROMPT_ECHO_OFF, password); free(prompt); return retval; fail: if (principal != NULL) krb5_free_unparsed_name(ctx->context, principal); return PAM_BUF_ERR; }
static PyObject * k5_cc_get_principal(PyObject *self, PyObject *args) { krb5_context ctx; char *ccname, *name; krb5_error_code code; krb5_ccache ccache; krb5_principal principal; PyObject *ret; if (!PyArg_ParseTuple( args, "s", &ccname)) return NULL; code = krb5_init_context(&ctx); RETURN_ON_ERROR("krb5_init_context()", code); code = krb5_cc_resolve(ctx, ccname, &ccache); RETURN_ON_ERROR("krb5_cc_resolve()", code); code = krb5_cc_get_principal(ctx, ccache, &principal); RETURN_ON_ERROR("krb5_cc_get_principal()", code); code = krb5_unparse_name(ctx, principal, &name); RETURN_ON_ERROR("krb5_unparse_name()", code); ret = PyString_FromString(name); if (ret == NULL) return ret; code = krb5_cc_close(ctx, ccache); RETURN_ON_ERROR("krb5_cc_close()", code); krb5_free_unparsed_name(ctx, name); krb5_free_principal(ctx, principal); krb5_free_context(ctx); return ret; }
static void DEFAULT_CC k5_end(struct k5_data *k5) { if (k5->name) { krb5_free_unparsed_name(k5->ctx, k5->name); } if (k5->me) { krb5_free_principal(k5->ctx, k5->me); } if (k5->cc) { krb5_cc_close(k5->ctx, k5->cc); } if (k5->ctx) { krb5_free_context(k5->ctx); } g_memset(k5, 0, sizeof(struct k5_data)); }
int main(int argc, char **argv) { krb5_principal princ; krb5_int32 type; const char *service, *hostname; char *name; /* Parse arguments. */ assert(argc == 4); hostname = argv[1]; service = argv[2]; if (strcmp(argv[3], "unknown") == 0) type = KRB5_NT_UNKNOWN; else if (strcmp(argv[3], "srv-hst") == 0) type = KRB5_NT_SRV_HST; else abort(); check(krb5_init_context(&ctx)); check(krb5_sname_to_principal(ctx, hostname, service, type, &princ)); check(krb5_unparse_name(ctx, princ, &name)); printf("%s\n", name); krb5_free_unparsed_name(ctx, name); krb5_free_principal(ctx, princ); krb5_free_context(ctx); return 0; }
static int list_ccache(krb5_ccache cache) { krb5_error_code ret; krb5_principal princ = NULL; char *princname = NULL, *ccname = NULL; int expired, status = 1; ret = krb5_cc_get_principal(context, cache, &princ); if (ret) /* Uninitialized cache file, probably. */ goto cleanup; ret = krb5_unparse_name(context, princ, &princname); if (ret) goto cleanup; ret = krb5_cc_get_full_name(context, cache, &ccname); if (ret) goto cleanup; expired = check_ccache(cache); printf("%-30.30s %s", princname, ccname); if (expired) printf(" %s", _("(Expired)")); printf("\n"); status = 0; cleanup: krb5_free_principal(context, princ); krb5_free_unparsed_name(context, princname); krb5_free_string(context, ccname); return status; }
/* * Set up cred to be an S4U2Proxy credential by copying in the impersonator's * creds, setting a cache config variable with the impersonator principal name, * and saving the impersonator principal name in the cred structure. */ static krb5_error_code make_proxy_cred(krb5_context context, krb5_gss_cred_id_t cred, krb5_gss_cred_id_t impersonator_cred) { krb5_error_code code; krb5_data data; char *str; code = krb5_cc_copy_creds(context, impersonator_cred->ccache, cred->ccache); if (code) return code; code = krb5_unparse_name(context, impersonator_cred->name->princ, &str); if (code) return code; data = string2data(str); code = krb5_cc_set_config(context, cred->ccache, NULL, KRB5_CONF_PROXY_IMPERSONATOR, &data); krb5_free_unparsed_name(context, str); if (code) return code; return krb5_copy_principal(context, impersonator_cred->name->princ, &cred->impersonator); }
krb5_error_code k5_build_conf_principals(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char *name, krb5_creds *cred) { krb5_principal client; krb5_error_code ret; char *pname = NULL; memset(cred, 0, sizeof(*cred)); ret = krb5_cc_get_principal(context, id, &client); if (ret) return ret; if (principal) { ret = krb5_unparse_name(context, principal, &pname); if (ret) return ret; } ret = krb5_build_principal(context, &cred->server, sizeof(conf_realm) - 1, conf_realm, conf_name, name, pname, (char *)NULL); krb5_free_unparsed_name(context, pname); if (ret) { krb5_free_principal(context, client); return ret; } ret = krb5_copy_principal(context, client, &cred->client); krb5_free_principal(context, client); return ret; }
static krb5_error_code k5_insert_client_info(krb5_context context, krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal) { krb5_error_code ret; krb5_data client_info; char *princ_name_utf8 = NULL; unsigned char *princ_name_ucs2 = NULL, *p; size_t princ_name_ucs2_len = 0; krb5_ui_8 nt_authtime; /* If we already have a CLIENT_INFO buffer, then just validate it */ if (k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO, &client_info) == 0) { return k5_pac_validate_client(context, pac, authtime, principal); } ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &princ_name_utf8); if (ret != 0) goto cleanup; ret = krb5int_utf8s_to_ucs2les(princ_name_utf8, &princ_name_ucs2, &princ_name_ucs2_len); if (ret != 0) goto cleanup; client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_ucs2_len; client_info.data = NULL; ret = k5_pac_add_buffer(context, pac, KRB5_PAC_CLIENT_INFO, &client_info, TRUE, &client_info); if (ret != 0) goto cleanup; p = (unsigned char *)client_info.data; /* copy in authtime converted to a 64-bit NT time */ k5_seconds_since_1970_to_time(authtime, &nt_authtime); store_64_le(nt_authtime, p); p += 8; /* copy in number of UCS-2 characters in principal name */ store_16_le(princ_name_ucs2_len, p); p += 2; /* copy in principal name */ memcpy(p, princ_name_ucs2, princ_name_ucs2_len); cleanup: if (princ_name_ucs2 != NULL) free(princ_name_ucs2); krb5_free_unparsed_name(context, princ_name_utf8); return ret; }
static krb5_error_code sss_an2ln(krb5_context context, krb5_localauth_moddata data, const char *type, const char *residual, krb5_const_principal aname, char **lname_out) { krb5_error_code kerr; char *princ_str; struct passwd pwd = { 0 }; char *buffer = NULL; size_t buflen; enum nss_status nss_status; int nss_errno; int ret; char *str; kerr = krb5_unparse_name(context, aname, &princ_str); if (kerr != 0) { return kerr; } buflen = DEFAULT_BUFSIZE; buffer = malloc(buflen); if (buffer == NULL) { ret = ENOMEM; goto done; } nss_status = _nss_sss_getpwnam_r(princ_str, &pwd, buffer, buflen, &nss_errno); if (nss_status != NSS_STATUS_SUCCESS) { if (nss_status == NSS_STATUS_NOTFOUND) { ret = KRB5_PLUGIN_NO_HANDLE; } else { ret = EIO; } goto done; } if (pwd.pw_name == NULL) { ret = EINVAL; goto done; } str = strdup(pwd.pw_name); if (str == NULL) { ret = ENOMEM; goto done; } *lname_out = str; ret = 0; done: krb5_free_unparsed_name(context, princ_str); free(buffer); return ret; }
static void pg_krb5_destroy(struct krb5_info * info) { krb5_free_principal(info->pg_krb5_context, info->pg_krb5_client); krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache); krb5_free_unparsed_name(info->pg_krb5_context, info->pg_krb5_name); krb5_free_context(info->pg_krb5_context); }
DWORD ADUKrb5GetPrincipalName( PCSTR pszCachePath, PSTR* ppszPrincipalName ) { DWORD dwError = 0; krb5_error_code ret = 0; krb5_context ctx = NULL; krb5_ccache cc = NULL; krb5_principal pKrb5Principal = NULL; PSTR pszKrb5PrincipalName = NULL; PSTR pszPrincipalName = NULL; ret = krb5_init_context(&ctx); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_cc_resolve(ctx, pszCachePath, &cc); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_cc_get_principal(ctx, cc, &pKrb5Principal); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_unparse_name(ctx, pKrb5Principal, &pszKrb5PrincipalName); BAIL_ON_KRB_ERROR(ctx, ret); dwError = LwAllocateString(pszKrb5PrincipalName, &pszPrincipalName); BAIL_ON_MAC_ERROR(dwError); *ppszPrincipalName = pszPrincipalName; cleanup: if (ctx) { if (pszKrb5PrincipalName) { krb5_free_unparsed_name(ctx, pszKrb5PrincipalName); } if (pKrb5Principal) { krb5_free_principal(ctx, pKrb5Principal); } if (cc) { krb5_cc_close(ctx, cc); } krb5_free_context(ctx); } return dwError; error: *ppszPrincipalName = NULL; goto cleanup; }
krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, krb5_keytab arg_keytab, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply) { krb5_error_code retval; krb5_gic_opt_ext *opte; char * server = NULL; krb5_keytab keytab; krb5_principal client_princ, server_princ; int use_master = 0; retval = krb5int_populate_gic_opt(context, &opte, options, addrs, ktypes, pre_auth_types, creds); if (retval) return retval; if (arg_keytab == NULL) { retval = krb5_kt_default(context, &keytab); if (retval) return retval; } else keytab = arg_keytab; retval = krb5_unparse_name( context, creds->server, &server); if (retval) goto cleanup; server_princ = creds->server; client_princ = creds->client; retval = krb5_get_init_creds (context, creds, creds->client, krb5_prompter_posix, NULL, 0, server, opte, krb5_get_as_key_keytab, (void *)keytab, &use_master, ret_as_reply); krb5_free_unparsed_name( context, server); krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); if (retval) { goto cleanup; } if (creds->server) krb5_free_principal( context, creds->server); if (creds->client) krb5_free_principal( context, creds->client); creds->client = client_princ; creds->server = server_princ; /* store it in the ccache! */ if (ccache) if ((retval = krb5_cc_store_cred(context, ccache, creds))) goto cleanup; cleanup: if (arg_keytab == NULL) krb5_kt_close(context, keytab); return retval; }
/* * Push a password change to Active Directory. Takes the module * configuration, a Kerberos context, the principal whose password is being * changed (we will have to change the realm), and the new password and its * length. Returns a Kerberos error code. */ krb5_error_code sync_ad_chpass(kadm5_hook_modinfo *config, krb5_context ctx, krb5_principal principal, const char *password) { krb5_error_code code; char *target = NULL; krb5_ccache ccache; krb5_principal ad_principal = NULL; int result_code; krb5_data result_code_string, result_string; /* Ensure the configuration is sane. */ CHECK_CONFIG(ad_realm); /* Get the credentials we'll use to make the change in AD. */ code = get_creds(config, ctx, &ccache); if (code != 0) return code; /* Get the corresponding AD principal. */ code = get_ad_principal(config, ctx, principal, &ad_principal); if (code != 0) goto done; /* This is just for logging purposes. */ code = krb5_unparse_name(ctx, ad_principal, &target); if (code != 0) goto done; /* Do the actual password change and record any error. */ code = krb5_set_password_using_ccache(ctx, ccache, (char *) password, ad_principal, &result_code, &result_code_string, &result_string); if (code != 0) goto done; if (result_code != 0) { code = sync_error_generic(ctx, "password change failed for %s: (%d)" " %.*s%s%.*s", target, result_code, (int) result_code_string.length, (char *) result_code_string.data, result_string.length ? ": " : "", (int) result_string.length, (char *) result_string.data); goto done; } free(result_string.data); free(result_code_string.data); sync_syslog_info(config, "krb5-sync: %s password changed", target); done: krb5_cc_destroy(ctx, ccache); if (target != NULL) krb5_free_unparsed_name(ctx, target); if (ad_principal != NULL) krb5_free_principal(ctx, ad_principal); return code; }
/* Rewrites get_in_tkt in terms of newer get_init_creds API. Attempts to get an initial ticket for creds->client to use server creds->server, (realm is taken from creds->client), with options options, and using creds->times.starttime, creds->times.endtime, creds->times.renew_till as from, till, and rtime. creds->times.renew_till is ignored unless the RENEWABLE option is requested. If addrs is non-NULL, it is used for the addresses requested. If it is null, the system standard addresses are used. If password is non-NULL, it is converted using the cryptosystem entry point for a string conversion routine, seeded with the client's name. If password is passed as NULL, the password is read from the terminal, and then converted into a key. A succesful call will place the ticket in the credentials cache ccache. returns system errors, encryption errors */ krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, const char *password, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply) { krb5_error_code retval; krb5_data pw0; char pw0array[1024]; char * server; krb5_principal server_princ, client_princ; int use_master = 0; krb5_get_init_creds_opt *opts = NULL; pw0.data = pw0array; if (password && password[0]) { if (strlcpy(pw0.data, password, sizeof(pw0array)) >= sizeof(pw0array)) return EINVAL; pw0.length = strlen(password); } else { pw0.data[0] = '\0'; pw0.length = sizeof(pw0array); } retval = krb5int_populate_gic_opt(context, &opts, options, addrs, ktypes, pre_auth_types, creds); if (retval) return (retval); retval = krb5_unparse_name( context, creds->server, &server); if (retval) { krb5_get_init_creds_opt_free(context, opts); return (retval); } server_princ = creds->server; client_princ = creds->client; retval = krb5int_get_init_creds(context, creds, creds->client, krb5_prompter_posix, NULL, 0, server, opts, krb5_get_as_key_password, &pw0, &use_master, ret_as_reply); krb5_free_unparsed_name( context, server); krb5_get_init_creds_opt_free(context, opts); if (retval) { return (retval); } krb5_free_principal( context, creds->server); krb5_free_principal( context, creds->client); creds->client = client_princ; creds->server = server_princ; /* store it in the ccache! */ if (ccache) if ((retval = krb5_cc_store_cred(context, ccache, creds))) return (retval); return retval; }
/* Return a helpful code and error when we cannot iterate over the keytab and * the specified server does not match the ticket server. */ static krb5_error_code nomatch_error(krb5_context context, krb5_const_principal server, krb5_const_principal tkt_server) { krb5_error_code ret; char *sname = NULL, *tsname = NULL; assert(server != NULL); ret = unparse_princs(context, server, tkt_server, &sname, &tsname); if (ret) return ret; krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US, _("Server principal %s does not match request " "ticket server %s"), sname, tsname); krb5_free_unparsed_name(context, sname); krb5_free_unparsed_name(context, tsname); return KRB5KRB_AP_ERR_NOT_US; }
/* Return a helpful code and error when we cannot look up the keytab entry for * an explicit server principal using the ticket's kvno and enctype. */ static krb5_error_code keytab_fetch_error(krb5_context context, krb5_error_code code, krb5_const_principal princ, krb5_const_principal tkt_server, krb5_kvno tkt_kvno, krb5_boolean explicit_server) { krb5_error_code ret; char *sname = NULL, *tsname = NULL; if (code == ENOENT || code == EPERM || code == EACCES) { k5_change_error_message_code(context, code, KRB5KRB_AP_ERR_NOKEY); return KRB5KRB_AP_ERR_NOKEY; } if (code == KRB5_KT_NOTFOUND) { ret = explicit_server ? KRB5KRB_AP_ERR_NOKEY : KRB5KRB_AP_ERR_NOT_US; k5_change_error_message_code(context, code, ret); return ret; } if (code != KRB5_KT_KVNONOTFOUND) return code; assert(princ != NULL); ret = unparse_princs(context, princ, tkt_server, &sname, &tsname); if (ret) return ret; if (krb5_principal_compare(context, princ, tkt_server)) { ret = KRB5KRB_AP_ERR_BADKEYVER; krb5_set_error_message(context, ret, _("Cannot find key for %s kvno %d in keytab"), sname, (int)tkt_kvno); } else { ret = KRB5KRB_AP_ERR_NOT_US; krb5_set_error_message(context, ret, _("Cannot find key for %s kvno %d in keytab " "(request ticket server %s)"), sname, (int)tkt_kvno, tsname); } krb5_free_unparsed_name(context, sname); krb5_free_unparsed_name(context, tsname); return ret; }
krb5_error_code smb_krb5_unparse_name(krb5_context context, krb5_const_principal principal, char **unix_name) { krb5_error_code ret; char *utf8_name; ret = krb5_unparse_name(context, principal, &utf8_name); if (ret) { return ret; } if (pull_utf8_allocate(unix_name, utf8_name)==-1) { krb5_free_unparsed_name(context, utf8_name); return ENOMEM; } krb5_free_unparsed_name(context, utf8_name); return 0; }
static void tr_dbg_rtree(struct tr_state *ts, const char *prog, krb5_principal princ) { char *str; if (krb5_unparse_name(ts->ctx, princ, &str)) return; fprintf(stderr, "%s: %s\n", prog, str); krb5_free_unparsed_name(ts->ctx, str); }
/* * initialize * * initialize the cache, check to see if one already exists for this * principal if not set our principal to this principal. This * searching enables ticket sharing */ krb5_error_code KRB5_CALLCONV krb5_stdcc_initialize (krb5_context context, krb5_ccache id, krb5_principal princ) { stdccCacheDataPtr ccapi_data = NULL; int err; char *cName = NULL; krb5_error_code retval; if ((retval = stdcc_setup(context, NULL))) return retval; /* test id for null */ if (id == NULL) return KRB5_CC_NOMEM; if ((retval = krb5_unparse_name(context, princ, &cName))) return retval; ccapi_data = id->data; if (ccapi_data->NamedCache) cc_close(gCntrlBlock, &ccapi_data->NamedCache); err = cc_create(gCntrlBlock, ccapi_data->cache_name, cName, CC_CRED_V5, 0L, &ccapi_data->NamedCache); if (err != CC_NOERROR) { krb5_free_unparsed_name(context, cName); return cc_err_xlate(err); } #if 0 /* * Some implementations don't set the principal name * correctly, so we force set it to the correct value. */ err = cc_set_principal(gCntrlBlock, ccapi_data->NamedCache, CC_CRED_V5, cName); #endif krb5_free_unparsed_name(context, cName); cache_changed(); return cc_err_xlate(err); }
static rlm_rcode_t krb5_parse_user(rlm_krb5_t *inst, REQUEST *request, krb5_principal *client) { krb5_error_code ret; char *princ_name; /* * We can only authenticate user requests which HAVE * a User-Name attribute. */ if (!request->username) { RDEBUG("Attribute \"User-Name\" is required for " "authentication"); return RLM_MODULE_INVALID; } /* * We can only authenticate user requests which HAVE * a User-Password attribute. */ if (!request->password) { RDEBUG("Attribute \"User-Password\" is required for " "authentication"); return RLM_MODULE_INVALID; } /* * Ensure that we're being passed a plain-text password, * and not anything else. */ if (request->password->da->attr != PW_USER_PASSWORD) { RDEBUG("Attribute \"User-Password\" is required for " "authentication. Cannot use \"%s\".", request->password->da->name); return RLM_MODULE_INVALID; } ret = krb5_parse_name(*(inst->context), request->username->vp_strvalue, client); if (ret) { RDEBUG("Failed parsing username as principal: %s", error_message(ret)); return RLM_MODULE_FAIL; } krb5_unparse_name(*(inst->context), *client, &princ_name); RDEBUG("Using client principal \"%s\"", princ_name); krb5_free_unparsed_name(*(inst->context), princ_name); return RLM_MODULE_OK; }
void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name) { #ifdef HAVE_KRB5_FREE_UNPARSED_NAME krb5_free_unparsed_name(context, name); #else if (name != NULL) { memset(name, 0, strlen(name)); free(name); } #endif }
/* Display the contents of cache. */ static int show_ccache(krb5_ccache cache) { krb5_cc_cursor cur; krb5_creds creds; krb5_principal princ; krb5_error_code ret; ret = krb5_cc_get_principal(context, cache, &princ); if (ret) { com_err(progname, ret, ""); return 1; } ret = krb5_unparse_name(context, princ, &defname); if (ret) { com_err(progname, ret, _("while unparsing principal name")); return 1; } printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"), krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache), defname); /* XXX Translating would disturb table alignment; skip for now. */ fputs("Valid starting", stdout); fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' '); fputs("Expires", stdout); fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' '); fputs("Service principal\n", stdout); ret = krb5_cc_start_seq_get(context, cache, &cur); if (ret) { com_err(progname, ret, _("while starting to retrieve tickets")); return 1; } while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { if (show_config || !krb5_is_config_principal(context, creds.server)) show_credential(&creds); krb5_free_cred_contents(context, &creds); } krb5_free_principal(context, princ); krb5_free_unparsed_name(context, defname); defname = NULL; if (ret == KRB5_CC_END) { ret = krb5_cc_end_seq_get(context, cache, &cur); if (ret) { com_err(progname, ret, _("while finishing ticket retrieval")); return 1; } return 0; } else { com_err(progname, ret, _("while retrieving a ticket")); return 1; } }
jobject BuildClientPrincipal(JNIEnv *env, krb5_context kcontext, krb5_principal principalName) { // Get the full principal string. char *principalString = NULL; jobject principal = NULL; int err = krb5_unparse_name (kcontext, principalName, &principalString); if (!err) { // Make a PrincipalName from the full string and the type. Let the PrincipalName class parse it out. jstring principalStringObj = (*env)->NewStringUTF(env, principalString); if (principalStringObj == NULL) { if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); } return (jobject) NULL; } principal = (*env)->NewObject(env, principalNameClass, principalNameConstructor, principalStringObj, principalName->type); if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); } (*env)->DeleteLocalRef(env, principalStringObj); } return principal; }
/* Return a helpful code and error when ticket decryption fails using the key * for an explicit server principal. */ static krb5_error_code integrity_error(krb5_context context, krb5_const_principal server, krb5_const_principal tkt_server) { krb5_error_code ret; char *sname = NULL, *tsname = NULL; assert(server != NULL); ret = unparse_princs(context, server, tkt_server, &sname, &tsname); if (ret) return ret; ret = krb5_principal_compare(context, server, tkt_server) ? KRB5KRB_AP_ERR_BAD_INTEGRITY : KRB5KRB_AP_ERR_NOT_US; krb5_set_error_message(context, ret, _("Cannot decrypt ticket for %s using keytab " "key for %s"), tsname, sname); krb5_free_unparsed_name(context, sname); krb5_free_unparsed_name(context, tsname); return ret; }
/* Similar to krb5_get_in_tkt_with_password. Attempts to get an initial ticket for creds->client to use server creds->server, (realm is taken from creds->client), with options options, and using creds->times.starttime, creds->times.endtime, creds->times.renew_till as from, till, and rtime. creds->times.renew_till is ignored unless the RENEWABLE option is requested. If addrs is non-NULL, it is used for the addresses requested. If it is null, the system standard addresses are used. If keyblock is NULL, an appropriate key for creds->client is retrieved from the system key store (e.g. /etc/srvtab). If keyblock is non-NULL, it is used as the decryption key. A succesful call will place the ticket in the credentials cache ccache. returns system errors, encryption errors */ krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, const krb5_keyblock *key, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply) { krb5_error_code retval; char *server; krb5_principal server_princ, client_princ; int use_master = 0; krb5_get_init_creds_opt *opts = NULL; retval = k5_populate_gic_opt(context, &opts, options, addrs, ktypes, pre_auth_types, creds); if (retval) return retval; retval = krb5_get_init_creds_opt_set_out_ccache(context, opts, ccache); if (retval) goto cleanup; #ifndef LEAN_CLIENT if (key == NULL) { retval = krb5_get_init_creds_keytab(context, creds, creds->client, NULL /* keytab */, creds->times.starttime, NULL /* in_tkt_service */, opts); goto cleanup; } #endif /* LEAN_CLIENT */ retval = krb5_unparse_name(context, creds->server, &server); if (retval) goto cleanup; server_princ = creds->server; client_princ = creds->client; retval = k5_get_init_creds(context, creds, creds->client, krb5_prompter_posix, NULL, 0, server, opts, get_as_key_skey, (void *)key, &use_master, ret_as_reply); krb5_free_unparsed_name(context, server); if (retval) goto cleanup; krb5_free_principal( context, creds->server); krb5_free_principal( context, creds->client); creds->client = client_princ; creds->server = server_princ; cleanup: krb5_get_init_creds_opt_free(context, opts); return retval; }
static krb5_error_code get_switched_ccache(krb5_context context, const char * type, krb5_principal principal, krb5_ccache *ccache) { krb5_error_code ret; #ifdef _WIN32 if (strcmp(type, "API") == 0) { /* * Windows stores the default ccache name in the * registry which is shared across multiple logon * sessions for the same user. The API credential * cache provides a unique name space per logon * session. Therefore there is no need to generate * a unique ccache name. Instead use the principal * name. This provides a friendlier user experience. */ char * unparsed_name; char * cred_cache; ret = krb5_unparse_name(context, principal, &unparsed_name); if (ret) krb5_err(context, 1, ret, N_("unparsing principal name", "")); ret = asprintf(&cred_cache, "API:%s", unparsed_name); krb5_free_unparsed_name(context, unparsed_name); if (ret == -1 || cred_cache == NULL) krb5_err(context, 1, ret, N_("building credential cache name", "")); ret = krb5_cc_resolve(context, cred_cache, ccache); free(cred_cache); } else if (strcmp(type, "MSLSA") == 0) { /* * The Windows MSLSA cache when it is writeable * stores tickets for multiple client principals * in a single credential cache. */ ret = krb5_cc_resolve(context, "MSLSA:", ccache); } else { ret = krb5_cc_new_unique(context, type, NULL, ccache); } #else /* !_WIN32 */ ret = krb5_cc_new_unique(context, type, NULL, ccache); #endif /* _WIN32 */ return ret; }
static void get_tickets(krb5_context context) { char *server; krb5_error_code retval; krb5_keytab keytab = NULL; krb5_principal server_princ = NULL; /* Figure out what tickets we'll be using to send. */ retval = sn2princ_realm(context, NULL, KPROP_SERVICE_NAME, realm, &my_principal); if (retval) { com_err(progname, errno, _("while setting client principal name")); exit(1); } /* Construct the principal name for the slave host. */ memset(&creds, 0, sizeof(creds)); retval = sn2princ_realm(context, slave_host, KPROP_SERVICE_NAME, realm, &server_princ); if (retval) { com_err(progname, errno, _("while setting server principal name")); exit(1); } retval = krb5_unparse_name_flags(context, server_princ, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &server); if (retval) { com_err(progname, retval, _("while unparsing server name")); exit(1); } if (srvtab != NULL) { retval = krb5_kt_resolve(context, srvtab, &keytab); if (retval) { com_err(progname, retval, _("while resolving keytab")); exit(1); } } retval = krb5_get_init_creds_keytab(context, &creds, my_principal, keytab, 0, server, NULL); if (retval) { com_err(progname, retval, _("while getting initial credentials\n")); exit(1); } if (keytab != NULL) krb5_kt_close(context, keytab); krb5_free_unparsed_name(context, server); krb5_free_principal(context, server_princ); }
static void tr_dbg(struct tr_state *ts, const char *prog) { krb5_error_code retval; char *cur_tgt_str, *cur_kdc_str, *nxt_kdc_str; cur_tgt_str = cur_kdc_str = nxt_kdc_str = NULL; retval = krb5_unparse_name(ts->ctx, ts->cur_tgt->server, &cur_tgt_str); if (retval) goto cleanup; retval = krb5_unparse_name(ts->ctx, *ts->cur_kdc, &cur_kdc_str); if (retval) goto cleanup; retval = krb5_unparse_name(ts->ctx, *ts->nxt_kdc, &nxt_kdc_str); if (retval) goto cleanup; fprintf(stderr, "%s: cur_tgt %s\n", prog, cur_tgt_str); fprintf(stderr, "%s: cur_kdc %s\n", prog, cur_kdc_str); fprintf(stderr, "%s: nxt_kdc %s\n", prog, nxt_kdc_str); cleanup: if (cur_tgt_str) krb5_free_unparsed_name(ts->ctx, cur_tgt_str); if (cur_kdc_str) krb5_free_unparsed_name(ts->ctx, cur_kdc_str); if (nxt_kdc_str) krb5_free_unparsed_name(ts->ctx, nxt_kdc_str); }
/* * Construct the secure cookie encryption key for the given local-realm TGT * entry, kvno, and client principal. The cookie key is derived from the first * TGT key for the given kvno, using the concatenation of "COOKIE" and the * unparsed client principal name as input. If kvno is 0, the highest current * kvno of the TGT is used. If kvno_out is not null, *kvno_out is set to the * kvno used. */ static krb5_error_code get_cookie_key(krb5_context context, krb5_db_entry *tgt, krb5_kvno kvno, krb5_const_principal client_princ, krb5_keyblock **key_out, krb5_kvno *kvno_out) { krb5_error_code ret; krb5_key_data *kd; krb5_keyblock kb; krb5_data d; krb5_int32 start = 0; char *princstr = NULL, *derive_input = NULL; *key_out = NULL; memset(&kb, 0, sizeof(kb)); /* Find the first krbtgt key with the specified kvno. */ ret = krb5_dbe_search_enctype(context, tgt, &start, -1, -1, kvno, &kd); if (ret) goto cleanup; /* Decrypt the key. */ ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL); if (ret) goto cleanup; /* Construct the input string and derive the cookie key. */ ret = krb5_unparse_name(context, client_princ, &princstr); if (ret) goto cleanup; if (asprintf(&derive_input, "COOKIE%s", princstr) < 0) { ret = ENOMEM; goto cleanup; } d = string2data(derive_input); ret = krb5_c_derive_prfplus(context, &kb, &d, ENCTYPE_NULL, key_out); if (kvno_out != NULL) *kvno_out = kd->key_data_kvno; cleanup: krb5_free_keyblock_contents(context, &kb); krb5_free_unparsed_name(context, princstr); free(derive_input); return ret; }
/* Iterator function for krb5_db_iterate() */ static krb5_error_code tditer(void *ptr, krb5_db_entry *entry) { krb5_error_code ret; struct rec_args *args = ptr; char *name; ret = krb5_unparse_name(util_context, entry->princ, &name); if (ret) { com_err(progname, ret, _("while unparsing principal name")); return ret; } ret = args->tdtype->princ_fn(args, name, entry); krb5_free_unparsed_name(util_context, name); if (ret) return ret; return 0; }