int add_admin_princ(void *handle, krb5_context context, char *name, char *realm, int attrs, int lifetime) { char *fullname; krb5_error_code ret; kadm5_principal_ent_rec ent; memset(&ent, 0, sizeof(ent)); fullname = build_name_with_realm(name, realm); ret = krb5_parse_name(context, fullname, &ent.principal); if (ret) { com_err(progname, ret, str_PARSE_NAME); return(ERR); } ent.max_life = lifetime; ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX; ret = kadm5_create_principal(handle, &ent, (KADM5_PRINCIPAL | KADM5_MAX_LIFE | KADM5_ATTRIBUTES), "to-be-random"); if (ret) { if (ret != KADM5_DUP) { com_err(progname, ret, str_PUT_PRINC, fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } } else { /* only randomize key if we created the principal */ ret = kadm5_randkey_principal(handle, ent.principal, NULL, NULL); if (ret) { com_err(progname, ret, str_RANDOM_KEY, fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } ent.attributes = attrs; ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES); if (ret) { com_err(progname, ret, str_PUT_PRINC, fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } } krb5_free_principal(context, ent.principal); free(fullname); return OK; }
void krb5_modprinc(krb5_context ctx, kadm5_handle hndl, kadm5_principal_ent_rec p, long mask) { kadm5_ret_t ret; char croakstr[256] = ""; K5BAIL(kadm5_modify_principal(hndl, &p, mask)); done: if (ret) croak("%s", croakstr); }
static PyObject *PyKAdminPrincipal_commit(PyKAdminPrincipalObject *self) { kadm5_ret_t retval = KADM5_OK; if (self && self->mask) { retval = kadm5_modify_principal(self->kadmin->server_handle, &self->entry, self->mask); if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_modify_principal"); } self->mask = 0; } Py_RETURN_TRUE; }
static kadm5_ret_t create_random_entry(krb5_principal princ, unsigned max_life, unsigned max_rlife, uint32_t attributes) { kadm5_principal_ent_rec ent; kadm5_ret_t ret; int mask = 0; krb5_keyblock *keys; int n_keys, i; char *name; const char *password; char pwbuf[512]; random_password(pwbuf, sizeof(pwbuf)); password = pwbuf; ret = krb5_unparse_name(context, princ, &name); if (ret) { krb5_warn(context, ret, "failed to unparse principal name"); return ret; } memset(&ent, 0, sizeof(ent)); ent.principal = princ; mask |= KADM5_PRINCIPAL; if (max_life) { ent.max_life = max_life; mask |= KADM5_MAX_LIFE; } if (max_rlife) { ent.max_renewable_life = max_rlife; mask |= KADM5_MAX_RLIFE; } ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX; mask |= KADM5_ATTRIBUTES; /* Create the entry with a random password */ ret = kadm5_create_principal(kadm_handle, &ent, mask, password); if(ret) { krb5_warn(context, ret, "create_random_entry(%s): randkey failed", name); goto out; } /* Replace the string2key based keys with real random bytes */ ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys); if(ret) { krb5_warn(context, ret, "create_random_entry(%s): randkey failed", name); goto out; } for(i = 0; i < n_keys; i++) krb5_free_keyblock_contents(context, &keys[i]); free(keys); ret = kadm5_get_principal(kadm_handle, princ, &ent, KADM5_PRINCIPAL | KADM5_ATTRIBUTES); if(ret) { krb5_warn(context, ret, "create_random_entry(%s): " "unable to get principal", name); goto out; } ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); ent.kvno = 1; ret = kadm5_modify_principal(kadm_handle, &ent, KADM5_ATTRIBUTES|KADM5_KVNO); kadm5_free_principal_ent (kadm_handle, &ent); if(ret) { krb5_warn(context, ret, "create_random_entry(%s): " "unable to modify principal", name); goto out; } out: free(name); return ret; }
int kt_get(struct get_options *opt, int argc, char **argv) { krb5_error_code ret = 0; krb5_keytab keytab; void *kadm_handle = NULL; krb5_enctype *etypes = NULL; size_t netypes = 0; size_t i; int a, j; unsigned int failed = 0; if((keytab = ktutil_open_keytab()) == NULL) return 1; if(opt->realm_string) krb5_set_default_realm(context, opt->realm_string); if (opt->enctypes_strings.num_strings != 0) { etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes)); if (etypes == NULL) { krb5_warnx(context, "malloc failed"); goto out; } netypes = opt->enctypes_strings.num_strings; for(i = 0; i < netypes; i++) { ret = krb5_string_to_enctype(context, opt->enctypes_strings.strings[i], &etypes[i]); if(ret) { krb5_warnx(context, "unrecognized enctype: %s", opt->enctypes_strings.strings[i]); goto out; } } } for(a = 0; a < argc; a++){ krb5_principal princ_ent; kadm5_principal_ent_rec princ; int mask = 0; krb5_keyblock *keys; int n_keys; int created = 0; krb5_keytab_entry entry; ret = krb5_parse_name(context, argv[a], &princ_ent); if (ret) { krb5_warn(context, ret, "can't parse principal %s", argv[a]); failed++; continue; } memset(&princ, 0, sizeof(princ)); princ.principal = princ_ent; mask |= KADM5_PRINCIPAL; princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; mask |= KADM5_ATTRIBUTES; princ.princ_expire_time = 0; mask |= KADM5_PRINC_EXPIRE_TIME; if(kadm_handle == NULL) { const char *r; if(opt->realm_string != NULL) r = opt->realm_string; else r = krb5_principal_get_realm(context, princ_ent); kadm_handle = open_kadmin_connection(opt->principal_string, r, opt->admin_server_string, opt->server_port_integer); if(kadm_handle == NULL) break; } ret = kadm5_create_principal(kadm_handle, &princ, mask, "x"); if(ret == 0) created = 1; else if(ret != KADM5_DUP) { krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]); krb5_free_principal(context, princ_ent); failed++; continue; } ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys); if (ret) { krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]); krb5_free_principal(context, princ_ent); failed++; continue; } ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES); if (ret) { krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]); for (j = 0; j < n_keys; j++) krb5_free_keyblock_contents(context, &keys[j]); krb5_free_principal(context, princ_ent); failed++; continue; } if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX)) krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]); princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); mask = KADM5_ATTRIBUTES; if(created) { princ.kvno = 1; mask |= KADM5_KVNO; } ret = kadm5_modify_principal(kadm_handle, &princ, mask); if (ret) { krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]); for (j = 0; j < n_keys; j++) krb5_free_keyblock_contents(context, &keys[j]); krb5_free_principal(context, princ_ent); failed++; continue; } for(j = 0; j < n_keys; j++) { int do_add = TRUE; if (netypes) { size_t k; do_add = FALSE; for (k = 0; k < netypes; ++k) if (keys[j].keytype == etypes[k]) { do_add = TRUE; break; } } if (do_add) { entry.principal = princ_ent; entry.vno = princ.kvno; entry.keyblock = keys[j]; entry.timestamp = time (NULL); ret = krb5_kt_add_entry(context, keytab, &entry); if (ret) krb5_warn(context, ret, "krb5_kt_add_entry"); } krb5_free_keyblock_contents(context, &keys[j]); } kadm5_free_principal_ent(kadm_handle, &princ); krb5_free_principal(context, princ_ent); } out: free(etypes); if (kadm_handle) kadm5_destroy(kadm_handle); krb5_kt_close(context, keytab); return ret != 0 || failed > 0; }
static int do_mod_entry(krb5_principal principal, void *data) { krb5_error_code ret; kadm5_principal_ent_rec princ; int mask = 0; struct modify_options *e = data; memset (&princ, 0, sizeof(princ)); ret = kadm5_get_principal(kadm_handle, principal, &princ, KADM5_PRINCIPAL | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION); if(ret) return ret; if(e->max_ticket_life_string || e->max_renewable_life_string || e->expiration_time_string || e->pw_expiration_time_string || e->attributes_string || e->policy_string || e->kvno_integer != -1 || e->constrained_delegation_strings.num_strings || e->alias_strings.num_strings || e->pkinit_acl_strings.num_strings || e->hist_kvno_diff_clnt_integer != -1 || e->hist_kvno_diff_svc_integer != -1) { ret = set_entry(context, &princ, &mask, e->max_ticket_life_string, e->max_renewable_life_string, e->expiration_time_string, e->pw_expiration_time_string, e->attributes_string, e->policy_string); if(e->kvno_integer != -1) { princ.kvno = e->kvno_integer; mask |= KADM5_KVNO; } if (e->constrained_delegation_strings.num_strings) { add_constrained_delegation(context, &princ, &e->constrained_delegation_strings); mask |= KADM5_TL_DATA; } if (e->alias_strings.num_strings) { add_aliases(context, &princ, &e->alias_strings); mask |= KADM5_TL_DATA; } if (e->pkinit_acl_strings.num_strings) { add_pkinit_acl(context, &princ, &e->pkinit_acl_strings); mask |= KADM5_TL_DATA; } if (e->hist_kvno_diff_clnt_integer != -1) { add_kvno_diff(context, &princ, 0, e->hist_kvno_diff_clnt_integer); mask |= KADM5_TL_DATA; } if (e->hist_kvno_diff_svc_integer != -1) { add_kvno_diff(context, &princ, 1, e->hist_kvno_diff_clnt_integer); mask |= KADM5_TL_DATA; } } else ret = edit_entry(&princ, &mask, NULL, 0); if(ret == 0) { ret = kadm5_modify_principal(kadm_handle, &princ, mask); if(ret) krb5_warn(context, ret, "kadm5_modify_principal"); } kadm5_free_principal_ent(kadm_handle, &princ); return ret; }
/* Modify Kerberos principal */ long modify_kerberos(char *username, int activate) { void *kadm_server_handle = NULL; krb5_context context = NULL; kadm5_ret_t status; krb5_principal princ; kadm5_principal_ent_rec dprinc; kadm5_policy_ent_rec defpol; kadm5_config_params realm_params; char admin_princ[256]; long mask = 0; #ifdef KERBEROS_TEST_REALM char ubuf[256]; sprintf(admin_princ, "moira/%s@%s", hostname, KERBEROS_TEST_REALM); sprintf(ubuf, "%s@%s", username, KERBEROS_TEST_REALM); username = ubuf; realm_params.realm = KERBEROS_TEST_REALM; realm_params.mask = KADM5_CONFIG_REALM; #else strcpy(admin_princ, MOIRA_SVR_PRINCIPAL); realm_params.mask = 0; #endif status = krb5_init_context(&context); if (status) return status; memset(&princ, 0, sizeof(princ)); memset(&dprinc, 0, sizeof(dprinc)); status = krb5_parse_name(context, username, &princ); if (status) return status; status = kadm5_init_with_skey(admin_princ, NULL, KADM5_ADMIN_SERVICE, &realm_params, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL, &kadm_server_handle); if (status) goto cleanup; status = kadm5_get_principal(kadm_server_handle, princ, &dprinc, KADM5_PRINCIPAL_NORMAL_MASK); if (status) goto cleanup; mask |= KADM5_ATTRIBUTES; if (activate == 2) { /* Force password change */ dprinc.attributes |= KRB5_KDB_REQUIRES_PWCHANGE; dprinc.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; } else if (activate == 1) { /* Enable principal */ dprinc.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; dprinc.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; } else { /* Disable principal */ dprinc.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; dprinc.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; } status = kadm5_modify_principal(kadm_server_handle, &dprinc, mask); cleanup: krb5_free_principal(context, princ); kadm5_free_principal_ent(kadm_server_handle, &dprinc); if (kadm_server_handle) kadm5_destroy(kadm_server_handle); return status; }
static krb5_error_code add_one_principal (const char *name, int rand_key, int rand_password, int use_defaults, char *password, krb5_key_data *key_data, const char *max_ticket_life, const char *max_renewable_life, const char *attributes, const char *expiration, const char *pw_expiration) { krb5_error_code ret; kadm5_principal_ent_rec princ, defrec; kadm5_principal_ent_rec *default_ent = NULL; krb5_principal princ_ent = NULL; int mask = 0; int default_mask = 0; char pwbuf[1024]; memset(&princ, 0, sizeof(princ)); ret = krb5_parse_name(context, name, &princ_ent); if (ret) { krb5_warn(context, ret, "krb5_parse_name"); return ret; } princ.principal = princ_ent; mask |= KADM5_PRINCIPAL; ret = set_entry(context, &princ, &mask, max_ticket_life, max_renewable_life, expiration, pw_expiration, attributes); if (ret) goto out; default_ent = &defrec; ret = get_default (kadm_handle, princ_ent, default_ent); if (ret) { default_ent = NULL; default_mask = 0; } else { default_mask = KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION; } if(use_defaults) set_defaults(&princ, &mask, default_ent, default_mask); else if(edit_entry(&princ, &mask, default_ent, default_mask)) goto out; if(rand_key || key_data) { princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; mask |= KADM5_ATTRIBUTES; random_password (pwbuf, sizeof(pwbuf)); password = pwbuf; } else if (rand_password) { random_password (pwbuf, sizeof(pwbuf)); password = pwbuf; } else if(password == NULL) { char *princ_name; char *prompt; krb5_unparse_name(context, princ_ent, &princ_name); asprintf (&prompt, "%s's Password: "******"failed to verify password"); goto out; } password = pwbuf; } ret = kadm5_create_principal(kadm_handle, &princ, mask, password); if(ret) { krb5_warn(context, ret, "kadm5_create_principal"); goto out; } if(rand_key) { krb5_keyblock *new_keys; int n_keys, i; ret = kadm5_randkey_principal(kadm_handle, princ_ent, &new_keys, &n_keys); if(ret){ krb5_warn(context, ret, "kadm5_randkey_principal"); n_keys = 0; } for(i = 0; i < n_keys; i++) krb5_free_keyblock_contents(context, &new_keys[i]); if (n_keys > 0) free(new_keys); kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES); princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); princ.kvno = 1; kadm5_modify_principal(kadm_handle, &princ, KADM5_ATTRIBUTES | KADM5_KVNO); kadm5_free_principal_ent(kadm_handle, &princ); } else if (key_data) { ret = kadm5_chpass_principal_with_key (kadm_handle, princ_ent, 3, key_data); if (ret) { krb5_warn(context, ret, "kadm5_chpass_principal_with_key"); } kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_ATTRIBUTES); princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); kadm5_modify_principal(kadm_handle, &princ, KADM5_ATTRIBUTES); kadm5_free_principal_ent(kadm_handle, &princ); } else if (rand_password) { char *princ_name; krb5_unparse_name(context, princ_ent, &princ_name); printf ("added %s with password \"%s\"\n", princ_name, password); free (princ_name); } out: if (princ_ent) krb5_free_principal (context, princ_ent); if(default_ent) kadm5_free_principal_ent (kadm_handle, default_ent); if (password != NULL) memset (password, 0, strlen(password)); return ret; }
int add_enctype(struct add_enctype_options*opt, int argc, char **argv) { kadm5_principal_ent_rec princ; krb5_principal princ_ent = NULL; krb5_error_code ret; const char *princ_name; int i, j; krb5_key_data *new_key_data; int n_etypes; krb5_enctype *etypes; if (!opt->random_key_flag) { krb5_warnx (context, "only random key is supported now"); return 0; } memset (&princ, 0, sizeof(princ)); princ_name = argv[0]; n_etypes = argc - 1; etypes = malloc (n_etypes * sizeof(*etypes)); if (etypes == NULL) { krb5_warnx (context, "out of memory"); return 0; } argv++; for (i = 0; i < n_etypes; ++i) { ret = krb5_string_to_enctype (context, argv[i], &etypes[i]); if (ret) { krb5_warnx (context, "bad enctype \"%s\"", argv[i]); goto out2; } } ret = krb5_parse_name(context, princ_name, &princ_ent); if (ret) { krb5_warn (context, ret, "krb5_parse_name %s", princ_name); goto out2; } ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KEY_DATA); if (ret) { krb5_free_principal (context, princ_ent); krb5_warnx (context, "no such principal: %s", princ_name); goto out2; } new_key_data = malloc((princ.n_key_data + n_etypes) * sizeof(*new_key_data)); if (new_key_data == NULL) { krb5_warnx (context, "out of memory"); goto out; } for (i = 0; i < princ.n_key_data; ++i) { krb5_key_data *key = &princ.key_data[i]; for (j = 0; j < n_etypes; ++j) { if (etypes[j] == key->key_data_type[0]) { krb5_warnx(context, "enctype %d already exists", (int)etypes[j]); free(new_key_data); goto out; } } new_key_data[i] = *key; } for (i = 0; i < n_etypes; ++i) { int n = princ.n_key_data + i; krb5_keyblock keyblock; memset(&new_key_data[n], 0, sizeof(new_key_data[n])); new_key_data[n].key_data_ver = 2; new_key_data[n].key_data_kvno = 0; ret = krb5_generate_random_keyblock (context, etypes[i], &keyblock); if (ret) { krb5_warnx(context, "genernate enctype %d failed", (int)etypes[i]); while (--i >= 0) free(new_key_data[--n].key_data_contents[0]); goto out; } /* key */ new_key_data[n].key_data_type[0] = etypes[i]; new_key_data[n].key_data_contents[0] = malloc(keyblock.keyvalue.length); if (new_key_data[n].key_data_contents[0] == NULL) { ret = ENOMEM; krb5_warn(context, ret, "out of memory"); while (--i >= 0) free(new_key_data[--n].key_data_contents[0]); goto out; } new_key_data[n].key_data_length[0] = keyblock.keyvalue.length; memcpy(new_key_data[n].key_data_contents[0], keyblock.keyvalue.data, keyblock.keyvalue.length); krb5_free_keyblock_contents(context, &keyblock); /* salt */ new_key_data[n].key_data_type[1] = KRB5_PW_SALT; new_key_data[n].key_data_length[1] = 0; new_key_data[n].key_data_contents[1] = NULL; } free (princ.key_data); princ.n_key_data += n_etypes; princ.key_data = new_key_data; new_key_data = NULL; ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA); if (ret) krb5_warn(context, ret, "kadm5_modify_principal"); out: krb5_free_principal (context, princ_ent); kadm5_free_principal_ent(kadm_handle, &princ); out2: free (etypes); return ret != 0; }
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; }
/** * This function is allows the caller to set new keys for a principal. * This is a simple wrapper around kadm5_get_principal() and * kadm5_modify_principal(). */ kadm5_ret_t kadm5_setkey_principal_3(void *server_handle, krb5_principal princ, krb5_boolean keepold, int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, krb5_keyblock *keyblocks, int n_keys) { kadm5_principal_ent_rec princ_ent; kadm5_ret_t ret; krb5_key_data *new_key_data = NULL; size_t i; if (n_keys < 1) return EINVAL; if (n_ks_tuple > 0 && n_ks_tuple != n_keys) return KADM5_SETKEY3_ETYPE_MISMATCH; /* * If setkey_principal_3 is defined in the server handle, use that. */ if (__CALLABLE(setkey_principal_3)) return __CALL(setkey_principal_3, (server_handle, princ, keepold, n_ks_tuple, ks_tuple, keyblocks, n_keys)); /* * Otherwise, simulate it via a get, update, modify sequence. */ ret = kadm5_get_principal(server_handle, princ, &princ_ent, KADM5_KVNO | KADM5_PRINCIPAL | KADM5_KEY_DATA); if (ret) return ret; if (keepold) { new_key_data = malloc((n_keys + princ_ent.n_key_data) * sizeof(*new_key_data)); if (new_key_data == NULL) { ret = ENOMEM; goto out; } memcpy(&new_key_data[n_keys], &princ_ent.key_data[0], princ_ent.n_key_data * sizeof (princ_ent.key_data[0])); } else { new_key_data = malloc(n_keys * sizeof(*new_key_data)); if (new_key_data == NULL) { ret = ENOMEM; goto out; } } princ_ent.kvno++; for (i = 0; i < n_keys; i++) { new_key_data[i].key_data_ver = 2; /* Key */ new_key_data[i].key_data_kvno = princ_ent.kvno; new_key_data[i].key_data_type[0] = keyblocks[i].keytype; new_key_data[i].key_data_length[0] = keyblocks[i].keyvalue.length; new_key_data[i].key_data_contents[0] = malloc(keyblocks[i].keyvalue.length); if (new_key_data[i].key_data_contents[0] == NULL) { ret = ENOMEM; goto out; } memcpy(new_key_data[i].key_data_contents[0], keyblocks[i].keyvalue.data, keyblocks[i].keyvalue.length); /* * Salt (but there's no salt, just salttype, which is kinda * silly -- what's the point of setkey_3() then, besides * keepold?!) */ new_key_data[i].key_data_type[1] = 0; if (n_ks_tuple > 0) { if (ks_tuple[i].ks_enctype != keyblocks[i].keytype) return KADM5_SETKEY3_ETYPE_MISMATCH; new_key_data[i].key_data_type[1] = ks_tuple[i].ks_salttype; } new_key_data[i].key_data_length[1] = 0; new_key_data[i].key_data_contents[1] = NULL; } /* Free old keys */ if (!keepold) { for (i = 0; i < princ_ent.n_key_data; i++) { free(princ_ent.key_data[i].key_data_contents[0]); free(princ_ent.key_data[i].key_data_contents[1]); } } free(princ_ent.key_data); princ_ent.key_data = new_key_data; princ_ent.n_key_data = n_keys + (keepold ? princ_ent.n_key_data : 0); new_key_data = NULL; /* Modify the principal */ ret = kadm5_modify_principal(server_handle, &princ_ent, KADM5_KVNO | KADM5_KEY_DATA); out: if (new_key_data != NULL) { for (i = 0; i < n_keys; i++) { free(new_key_data[i].key_data_contents[0]); free(new_key_data[i].key_data_contents[1]); } free(new_key_data); } kadm5_free_principal_ent(server_handle, &princ_ent); return ret; }
static kadm5_ret_t kadmind_dispatch(void *kadm_handle, krb5_boolean initial, krb5_data *in, krb5_data *out) { kadm5_ret_t ret; int32_t cmd, mask, tmp; kadm5_server_context *context = kadm_handle; char client[128], name[128], name2[128]; char *op = ""; krb5_principal princ, princ2; kadm5_principal_ent_rec ent; char *password, *expression; krb5_keyblock *new_keys; int n_keys; char **princs; int n_princs; krb5_storage *sp; krb5_unparse_name_fixed(context->context, context->caller, client, sizeof(client)); sp = krb5_storage_from_data(in); if (sp == NULL) krb5_errx(context->context, 1, "out of memory"); krb5_ret_int32(sp, &cmd); switch(cmd){ case kadm_get:{ op = "GET"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ krb5_free_principal(context->context, princ); goto fail; } mask |= KADM5_PRINCIPAL; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_get_principal(kadm_handle, princ, &ent, mask); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ kadm5_store_principal_ent(sp, &ent); kadm5_free_principal_ent(kadm_handle, &ent); } krb5_free_principal(context->context, princ); break; } case kadm_delete:{ op = "DELETE"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_delete_principal(kadm_handle, princ); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_create:{ op = "CREATE"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(context->context, &ent); goto fail; } ret = krb5_ret_string(sp, &password); if(ret){ kadm5_free_principal_ent(context->context, &ent); goto fail; } krb5_unparse_name_fixed(context->context, ent.principal, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD, ent.principal); if(ret){ kadm5_free_principal_ent(context->context, &ent); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_create_principal(kadm_handle, &ent, mask, password); kadm5_free_principal_ent(kadm_handle, &ent); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_modify:{ op = "MODIFY"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(context, &ent); goto fail; } krb5_unparse_name_fixed(context->context, ent.principal, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_MODIFY, ent.principal); if(ret){ kadm5_free_principal_ent(context, &ent); goto fail; } ret = kadm5_modify_principal(kadm_handle, &ent, mask); kadm5_free_principal_ent(kadm_handle, &ent); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_rename:{ op = "RENAME"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_principal(sp, &princ2); if(ret){ krb5_free_principal(context->context, princ); goto fail; } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_unparse_name_fixed(context->context, princ2, name2, sizeof(name2)); krb5_warnx(context->context, "%s: %s %s -> %s", client, op, name, name2); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD, princ2) || _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(context->context, princ); krb5_free_principal(context->context, princ2); goto fail; } ret = kadm5_rename_principal(kadm_handle, princ, princ2); krb5_free_principal(context->context, princ); krb5_free_principal(context->context, princ2); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass:{ op = "CHPASS"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_string(sp, &password); if(ret){ krb5_free_principal(context->context, princ); goto fail; } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an * initial ticket, but then, check with the password quality * function. * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (context->context, context->caller, princ)) { krb5_data pwd_data; const char *pwd_reason; pwd_data.data = password; pwd_data.length = strlen(password); pwd_reason = kadm5_check_password_quality (context->context, princ, &pwd_data); if (pwd_reason != NULL) ret = KADM5_PASS_Q_DICT; else ret = 0; } else ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_chpass_principal(kadm_handle, princ, password); krb5_free_principal(context->context, princ); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass_with_key:{ int i; krb5_key_data *key_data; int n_key_data; op = "CHPASS_WITH_KEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &n_key_data); if (ret) { krb5_free_principal(context->context, princ); goto fail; } /* n_key_data will be squeezed into an int16_t below. */ if (n_key_data < 0 || n_key_data >= 1 << 16 || n_key_data > UINT_MAX/sizeof(*key_data)) { ret = ERANGE; krb5_free_principal(context->context, princ); goto fail; } key_data = malloc (n_key_data * sizeof(*key_data)); if (key_data == NULL && n_key_data != 0) { ret = ENOMEM; krb5_free_principal(context->context, princ); goto fail; } for (i = 0; i < n_key_data; ++i) { ret = kadm5_ret_key_data (sp, &key_data[i]); if (ret) { int16_t dummy = i; kadm5_free_key_data (context, &dummy, key_data); free (key_data); krb5_free_principal(context->context, princ); goto fail; } } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is only allowed if the user is on the CPW ACL, * this it to force password quality check on the user. */ ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { int16_t dummy = n_key_data; kadm5_free_key_data (context, &dummy, key_data); free (key_data); krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_chpass_principal_with_key(kadm_handle, princ, n_key_data, key_data); { int16_t dummy = n_key_data; kadm5_free_key_data (context, &dummy, key_data); } free (key_data); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_randkey:{ op = "RANDKEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an initial ticket * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (context->context, context->caller, princ)) ret = 0; else ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_randkey_principal(kadm_handle, princ, &new_keys, &n_keys); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_keys); for(i = 0; i < n_keys; i++){ krb5_store_keyblock(sp, new_keys[i]); krb5_free_keyblock_contents(context->context, &new_keys[i]); } free(new_keys); } break; } case kadm_get_privs:{ uint32_t privs; ret = kadm5_get_privs(kadm_handle, &privs); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0) krb5_store_uint32(sp, privs); break; } case kadm_get_princs:{ op = "LIST"; ret = krb5_ret_int32(sp, &tmp); if(ret) goto fail; if(tmp){ ret = krb5_ret_string(sp, &expression); if(ret) goto fail; }else expression = NULL; krb5_warnx(context->context, "%s: %s %s", client, op, expression ? expression : "*"); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST, NULL); if(ret){ free(expression); goto fail; } ret = kadm5_get_principals(kadm_handle, expression, &princs, &n_princs); free(expression); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_princs); for(i = 0; i < n_princs; i++) krb5_store_string(sp, princs[i]); kadm5_free_name_list(kadm_handle, princs, &n_princs); } break; } default: krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, KADM5_FAILURE); break; } krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; fail: krb5_warn(context->context, ret, "%s", op); krb5_storage_seek(sp, 0, SEEK_SET); krb5_store_int32(sp, ret); krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; }
static kadm5_ret_t kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, krb5_data *in, krb5_data *out) { kadm5_ret_t ret; int32_t cmd, mask, tmp; kadm5_server_context *contextp = kadm_handlep; char client[128], name[128], name2[128]; const char *op = ""; krb5_principal princ, princ2; kadm5_principal_ent_rec ent; char *password, *expression; krb5_keyblock *new_keys; krb5_key_salt_tuple *ks_tuple = NULL; krb5_boolean keepold = FALSE; int n_ks_tuple = 0; int n_keys; char **princs; int n_princs; int keys_ok = 0; krb5_storage *sp; krb5_unparse_name_fixed(contextp->context, contextp->caller, client, sizeof(client)); sp = krb5_storage_from_data(in); if (sp == NULL) krb5_errx(contextp->context, 1, "out of memory"); krb5_ret_int32(sp, &cmd); switch(cmd){ case kadm_get:{ op = "GET"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } mask |= KADM5_PRINCIPAL; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* If the caller doesn't have KADM5_PRIV_GET, we're done. */ ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET, princ); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } /* Then check to see if it is ok to return keys */ if ((mask & KADM5_KEY_DATA) != 0) { ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET_KEYS, princ); if (ret == 0) { keys_ok = 1; } else if ((mask == (KADM5_PRINCIPAL|KADM5_KEY_DATA)) || (mask == (KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA))) { /* * Requests for keys will get bogus keys, which is useful if * the client just wants to see what (kvno, enctype)s the * principal has keys for, but terrible if the client wants to * write the keys into a keytab or modify the principal and * write the bogus keys back to the server. * * We use a heuristic to detect which case we're handling here. * If the client only asks for the flags in the above * condition, then it's very likely a kadmin ext_keytab, * add_enctype, or other request that should not see bogus * keys. We deny them. * * The kadmin get command can be coaxed into making a request * with the same mask. But the default long and terse output * modes request other things too, so in all likelihood this * heuristic will not hurt any kadmin get uses. */ krb5_free_principal(contextp->context, princ); goto fail; } } ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if (ret == 0){ if (keys_ok) kadm5_store_principal_ent(sp, &ent); else kadm5_store_principal_ent_nokeys(sp, &ent); kadm5_free_principal_ent(kadm_handlep, &ent); } krb5_free_principal(contextp->context, princ); break; } case kadm_delete:{ op = "DELETE"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } ret = kadm5_delete_principal(kadm_handlep, princ); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_create:{ op = "CREATE"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); goto fail; } ret = krb5_ret_string(sp, &password); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); goto fail; } krb5_unparse_name_fixed(contextp->context, ent.principal, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, ent.principal); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_create_principal(kadm_handlep, &ent, mask, password); kadm5_free_principal_ent(kadm_handlep, &ent); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_modify:{ op = "MODIFY"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(contextp, &ent); goto fail; } krb5_unparse_name_fixed(contextp->context, ent.principal, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_MODIFY, ent.principal); if(ret){ kadm5_free_principal_ent(contextp, &ent); goto fail; } ret = kadm5_modify_principal(kadm_handlep, &ent, mask); kadm5_free_principal_ent(kadm_handlep, &ent); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_rename:{ op = "RENAME"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_principal(sp, &princ2); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_unparse_name_fixed(contextp->context, princ2, name2, sizeof(name2)); krb5_warnx(contextp->context, "%s: %s %s -> %s", client, op, name, name2); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, princ2) || _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(contextp->context, princ); krb5_free_principal(contextp->context, princ2); goto fail; } ret = kadm5_rename_principal(kadm_handlep, princ, princ2); krb5_free_principal(contextp->context, princ); krb5_free_principal(contextp->context, princ2); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass:{ op = "CHPASS"; ret = krb5_ret_principal(sp, &princ); if (ret) goto fail; ret = krb5_ret_string(sp, &password); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &keepold); if (ret && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * * a) allowed by sysadmin * b) it's for the principal him/herself and this was an * initial ticket, but then, check with the password quality * function. * c) the user is on the CPW ACL. */ if (krb5_config_get_bool_default(contextp->context, NULL, TRUE, "kadmin", "allow_self_change_password", NULL) && initial && krb5_principal_compare (contextp->context, contextp->caller, princ)) { krb5_data pwd_data; const char *pwd_reason; pwd_data.data = password; pwd_data.length = strlen(password); pwd_reason = kadm5_check_password_quality (contextp->context, princ, &pwd_data); if (pwd_reason != NULL) ret = KADM5_PASS_Q_DICT; else ret = 0; } else ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(contextp->context, princ); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_chpass_principal_3(kadm_handlep, princ, keepold, 0, NULL, password); krb5_free_principal(contextp->context, princ); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass_with_key:{ int i; krb5_key_data *key_data; int n_key_data; op = "CHPASS_WITH_KEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &n_key_data); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &keepold); if (ret && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } /* n_key_data will be squeezed into an int16_t below. */ if (n_key_data < 0 || n_key_data >= 1 << 16 || (size_t)n_key_data > UINT_MAX/sizeof(*key_data)) { ret = ERANGE; krb5_free_principal(contextp->context, princ); goto fail; } key_data = malloc (n_key_data * sizeof(*key_data)); if (key_data == NULL && n_key_data != 0) { ret = ENOMEM; krb5_free_principal(contextp->context, princ); goto fail; } for (i = 0; i < n_key_data; ++i) { ret = kadm5_ret_key_data (sp, &key_data[i]); if (ret) { int16_t dummy = i; kadm5_free_key_data (contextp, &dummy, key_data); free (key_data); krb5_free_principal(contextp->context, princ); goto fail; } } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is only allowed if the user is on the CPW ACL, * this it to force password quality check on the user. */ ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { int16_t dummy = n_key_data; kadm5_free_key_data (contextp, &dummy, key_data); free (key_data); krb5_free_principal(contextp->context, princ); goto fail; } ret = kadm5_chpass_principal_with_key_3(kadm_handlep, princ, keepold, n_key_data, key_data); { int16_t dummy = n_key_data; kadm5_free_key_data (contextp, &dummy, key_data); } free (key_data); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_randkey:{ op = "RANDKEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an initial ticket * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (contextp->context, contextp->caller, princ)) ret = 0; else ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(contextp->context, princ); goto fail; } /* * See comments in kadm5_c_randkey_principal() regarding the * protocol. */ ret = krb5_ret_int32(sp, &keepold); if (ret != 0 && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &n_ks_tuple); if (ret != 0 && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } else if (ret == 0) { size_t i; if (n_ks_tuple < 0) { ret = EOVERFLOW; krb5_free_principal(contextp->context, princ); goto fail; } if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) { ret = errno; krb5_free_principal(contextp->context, princ); goto fail; } for (i = 0; i < n_ks_tuple; i++) { ret = krb5_ret_int32(sp, &ks_tuple[i].ks_enctype); if (ret != 0) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &ks_tuple[i].ks_salttype); if (ret != 0) { krb5_free_principal(contextp->context, princ); goto fail; } } } ret = kadm5_randkey_principal_3(kadm_handlep, princ, keepold, n_ks_tuple, ks_tuple, &new_keys, &n_keys); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_keys); for(i = 0; i < n_keys; i++){ krb5_store_keyblock(sp, new_keys[i]); krb5_free_keyblock_contents(contextp->context, &new_keys[i]); } free(new_keys); } break; } case kadm_get_privs:{ uint32_t privs; ret = kadm5_get_privs(kadm_handlep, &privs); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0) krb5_store_uint32(sp, privs); break; } case kadm_get_princs:{ op = "LIST"; ret = krb5_ret_int32(sp, &tmp); if(ret) goto fail; if(tmp){ ret = krb5_ret_string(sp, &expression); if(ret) goto fail; }else expression = NULL; krb5_warnx(contextp->context, "%s: %s %s", client, op, expression ? expression : "*"); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_LIST, NULL); if(ret){ free(expression); goto fail; } ret = kadm5_get_principals(kadm_handlep, expression, &princs, &n_princs); free(expression); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_princs); for(i = 0; i < n_princs; i++) krb5_store_string(sp, princs[i]); kadm5_free_name_list(kadm_handlep, princs, &n_princs); } break; } default: krb5_warnx(contextp->context, "%s: UNKNOWN OP %d", client, cmd); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, KADM5_FAILURE); break; } krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; fail: krb5_warn(contextp->context, ret, "%s", op); krb5_storage_seek(sp, 0, SEEK_SET); krb5_store_int32(sp, ret); krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; }
int del_enctype(void *opt, int argc, char **argv) { kadm5_principal_ent_rec princ; krb5_principal princ_ent = NULL; krb5_error_code ret; const char *princ_name; int i, j, k; krb5_key_data *new_key_data; int n_etypes; krb5_enctype *etypes; memset (&princ, 0, sizeof(princ)); princ_name = argv[0]; n_etypes = argc - 1; etypes = malloc (n_etypes * sizeof(*etypes)); if (etypes == NULL) { krb5_warnx (context, "out of memory"); return 0; } argv++; for (i = 0; i < n_etypes; ++i) { ret = krb5_string_to_enctype (context, argv[i], &etypes[i]); if (ret) { krb5_warnx (context, "bad enctype \"%s\"", argv[i]); goto out2; } } ret = krb5_parse_name(context, princ_name, &princ_ent); if (ret) { krb5_warn (context, ret, "krb5_parse_name %s", princ_name); goto out2; } ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KEY_DATA); if (ret) { krb5_free_principal (context, princ_ent); krb5_warnx (context, "no such principal: %s", princ_name); goto out2; } new_key_data = malloc(princ.n_key_data * sizeof(*new_key_data)); if (new_key_data == NULL && princ.n_key_data != 0) { krb5_warnx (context, "out of memory"); goto out; } for (i = 0, j = 0; i < princ.n_key_data; ++i) { krb5_key_data *key = &princ.key_data[i]; int docopy = 1; for (k = 0; k < n_etypes; ++k) if (etypes[k] == key->key_data_type[0]) { docopy = 0; break; } if (docopy) { new_key_data[j++] = *key; } else { int16_t ignore = 1; kadm5_free_key_data (kadm_handle, &ignore, key); } } free (princ.key_data); princ.n_key_data = j; princ.key_data = new_key_data; ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA); if (ret) krb5_warn(context, ret, "kadm5_modify_principal"); out: krb5_free_principal (context, princ_ent); kadm5_free_principal_ent(kadm_handle, &princ); out2: free (etypes); return ret != 0; }