/* * Find the principal of the first entry of a keytab and return it. The * caller is responsible for freeing the result with krb5_free_principal. * Exit on error. */ krb5_principal kerberos_keytab_principal(krb5_context ctx, const char *path) { krb5_keytab keytab; krb5_kt_cursor cursor; krb5_keytab_entry entry; krb5_principal princ; krb5_error_code status; status = krb5_kt_resolve(ctx, path, &keytab); if (status != 0) bail_krb5(ctx, status, "error opening %s", path); status = krb5_kt_start_seq_get(ctx, keytab, &cursor); if (status != 0) bail_krb5(ctx, status, "error reading %s", path); status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor); if (status == 0) { status = krb5_copy_principal(ctx, entry.principal, &princ); if (status != 0) bail_krb5(ctx, status, "error copying principal from %s", path); krb5_kt_free_entry(ctx, &entry); } if (status != 0) bail("no principal found in keytab file %s", path); krb5_kt_end_seq_get(ctx, keytab, &cursor); krb5_kt_close(ctx, keytab); return princ; }
static void kerberos_kinit(void) { char *name, *krbtgt; krb5_error_code code; krb5_context ctx; krb5_ccache ccache; krb5_principal kprinc; krb5_keytab keytab; krb5_get_init_creds_opt *opts; krb5_creds creds; const char *realm; /* * Determine the principal corresponding to that keytab. We copy the * memory to ensure that it's allocated in the right memory domain on * systems where that may matter (like Windows). */ code = krb5_init_context(&ctx); if (code != 0) bail_krb5(ctx, code, "error initializing Kerberos"); kprinc = kerberos_keytab_principal(ctx, config->keytab); code = krb5_unparse_name(ctx, kprinc, &name); if (code != 0) bail_krb5(ctx, code, "error unparsing name"); krb5_free_principal(ctx, kprinc); config->principal = bstrdup(name); krb5_free_unparsed_name(ctx, name); /* Now do the Kerberos initialization. */ code = krb5_cc_default(ctx, &ccache); if (code != 0) bail_krb5(ctx, code, "error setting ticket cache"); code = krb5_parse_name(ctx, config->principal, &kprinc); if (code != 0) bail_krb5(ctx, code, "error parsing principal %s", config->principal); realm = krb5_principal_get_realm(ctx, kprinc); basprintf(&krbtgt, "krbtgt/%s@%s", realm, realm); code = krb5_kt_resolve(ctx, config->keytab, &keytab); if (code != 0) bail_krb5(ctx, code, "cannot open keytab %s", config->keytab); code = krb5_get_init_creds_opt_alloc(ctx, &opts); if (code != 0) bail_krb5(ctx, code, "cannot allocate credential options"); krb5_get_init_creds_opt_set_default_flags(ctx, NULL, realm, opts); krb5_get_init_creds_opt_set_forwardable(opts, 0); krb5_get_init_creds_opt_set_proxiable(opts, 0); code = krb5_get_init_creds_keytab(ctx, &creds, kprinc, keytab, 0, krbtgt, opts); if (code != 0) bail_krb5(ctx, code, "cannot get Kerberos tickets"); code = krb5_cc_initialize(ctx, ccache, kprinc); if (code != 0) bail_krb5(ctx, code, "error initializing ticket cache"); code = krb5_cc_store_cred(ctx, ccache, &creds); if (code != 0) bail_krb5(ctx, code, "error storing credentials"); krb5_cc_close(ctx, ccache); krb5_free_cred_contents(ctx, &creds); krb5_kt_close(ctx, keytab); krb5_free_principal(ctx, kprinc); krb5_get_init_creds_opt_free(ctx, opts); krb5_free_context(ctx); free(krbtgt); }
bool kerberos_expire_password(const char *principal, time_t expires) { char *path, *user; const char *realm; krb5_context ctx; krb5_principal admin = NULL; krb5_principal princ = NULL; krb5_error_code code; kadm5_config_params params; kadm5_principal_ent_rec ent; void *handle; bool okay = false; /* Set up for making our call. */ path = test_file_path("config/admin-keytab"); if (path == NULL) return false; code = krb5_init_context(&ctx); if (code != 0) bail_krb5(ctx, code, "error initializing Kerberos"); admin = kerberos_keytab_principal(ctx, path); realm = krb5_principal_get_realm(ctx, admin); code = krb5_set_default_realm(ctx, realm); if (code != 0) bail_krb5(ctx, code, "cannot set default realm"); code = krb5_unparse_name(ctx, admin, &user); if (code != 0) bail_krb5(ctx, code, "cannot unparse admin principal"); code = krb5_parse_name(ctx, principal, &princ); if (code != 0) bail_krb5(ctx, code, "cannot parse principal %s", principal); /* * If the actual kadmin calls fail, we may be built with MIT Kerberos * against a Heimdal server or vice versa. Return false to skip the * tests. */ memset(¶ms, 0, sizeof(params)); params.realm = (char *) realm; params.mask = KADM5_CONFIG_REALM; code = kadm5_init_with_skey_ctx(ctx, user, path, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION, &handle); if (code != 0) { diag_krb5(ctx, code, "error initializing kadmin"); goto done; } memset(&ent, 0, sizeof(ent)); ent.principal = princ; ent.pw_expiration = expires; code = kadm5_modify_principal(handle, &ent, KADM5_PW_EXPIRATION); if (code == 0) okay = true; else diag_krb5(ctx, code, "error setting password expiration"); done: kadm5_destroy(handle); krb5_free_unparsed_name(ctx, user); krb5_free_principal(ctx, admin); krb5_free_principal(ctx, princ); krb5_free_context(ctx); test_file_path_free(path); return okay; }