static kadm5_ret_t modify_principal(void *server_handle, kadm5_principal_ent_t princ, uint32_t mask, uint32_t forbidden_mask) { kadm5_server_context *context = server_handle; hdb_entry_ex ent; kadm5_ret_t ret; memset(&ent, 0, sizeof(ent)); if((mask & forbidden_mask)) return KADM5_BAD_MASK; if((mask & KADM5_POLICY) && strcmp(princ->policy, "default")) return KADM5_UNK_POLICY; if (!context->keep_open) { ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); if(ret) return ret; } ret = kadm5_log_init(context); if (ret) goto out; ret = context->db->hdb_fetch_kvno(context->context, context->db, princ->principal, HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent); if(ret) goto out; ret = _kadm5_setup_entry(context, &ent, mask, princ, mask, NULL, 0); if(ret) goto out2; ret = _kadm5_set_modifier(context, &ent.entry); if(ret) goto out2; /* * If any keys are bogus, disallow the modify. If the keys were * bogus as stored in the HDB we could allow those through, but * distinguishing that case from a pre-1.6 client using add_enctype * without the get-keys privilege requires more work (mainly: checking that * the bogus keys in princ->key_data[] have corresponding bogus keys in ent * before calling _kadm5_setup_entry()). */ if ((mask & KADM5_KEY_DATA) && kadm5_some_keys_are_bogus(princ->n_key_data, princ->key_data)) { ret = KADM5_AUTH_GET_KEYS; /* Not quite appropriate, but it'll do */ goto out2; } ret = hdb_seal_keys(context->context, context->db, &ent.entry); if (ret) goto out2; if ((mask & KADM5_POLICY)) { HDB_extension ext; memset(&ext, 0, sizeof(ext)); /* XXX should be TRUE, but we don't yet support policies */ ext.mandatory = FALSE; ext.data.element = choice_HDB_extension_data_policy; ext.data.u.policy = strdup(princ->policy); if (ext.data.u.policy == NULL) { ret = ENOMEM; goto out2; } /* This calls free_HDB_extension(), freeing ext.data.u.policy */ ret = hdb_replace_extension(context->context, &ent.entry, &ext); free(ext.data.u.policy); if (ret) goto out2; } /* This logs the change for iprop and writes to the HDB */ ret = kadm5_log_modify(context, &ent.entry, mask | KADM5_MOD_NAME | KADM5_MOD_TIME); out2: hdb_free_entry(context->context, &ent); out: (void) kadm5_log_end(context); if (!context->keep_open) { kadm5_ret_t ret2; ret2 = context->db->hdb_close(context->context, context->db); if (ret == 0 && ret2 != 0) ret = ret2; } return _kadm5_error_code(ret); }
static int do_ext_keytab(krb5_principal principal, void *data) { krb5_error_code ret; kadm5_principal_ent_rec princ; struct ext_keytab_data *e = data; krb5_keytab_entry *keys = NULL; krb5_keyblock *k = NULL; size_t i; int n_k = 0; uint32_t mask; char *unparsed = NULL; mask = KADM5_PRINCIPAL; if (!e->random_key_flag) mask |= KADM5_KVNO | KADM5_KEY_DATA; ret = kadm5_get_principal(kadm_handle, principal, &princ, mask); if (ret) return ret; ret = krb5_unparse_name(context, principal, &unparsed); if (ret) goto out; if (!e->random_key_flag) { if (princ.n_key_data == 0) { krb5_warnx(context, "principal has no keys, or user lacks " "get-keys privilege for %s", unparsed); goto out; } /* * kadmin clients and servers from master between 1.5 and 1.6 * can have corrupted a principal's keys in the HDB. If some * are bogus but not all are, then that must have happened. * * If all keys are bogus then the server may be a pre-1.6, * post-1.5 server and the client lacks get-keys privilege, or * the keys are corrupted. We can't tell here. */ if (kadm5_all_keys_are_bogus(princ.n_key_data, princ.key_data)) { krb5_warnx(context, "user lacks get-keys privilege for %s", unparsed); goto out; } if (kadm5_some_keys_are_bogus(princ.n_key_data, princ.key_data)) { krb5_warnx(context, "some keys for %s are corrupted in the HDB", unparsed); } keys = calloc(sizeof(*keys), princ.n_key_data); if (keys == NULL) { ret = krb5_enomem(context); goto out; } for (i = 0; i < princ.n_key_data; i++) { krb5_key_data *kd = &princ.key_data[i]; /* Don't extract bogus keys */ if (kadm5_all_keys_are_bogus(1, kd)) continue; keys[i].principal = princ.principal; keys[i].vno = kd->key_data_kvno; keys[i].keyblock.keytype = kd->key_data_type[0]; keys[i].keyblock.keyvalue.length = kd->key_data_length[0]; keys[i].keyblock.keyvalue.data = kd->key_data_contents[0]; keys[i].timestamp = time(NULL); n_k++; } } else if (e->random_key_flag) { ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k); if (ret) goto out; keys = calloc(sizeof(*keys), n_k); if (keys == NULL) { ret = krb5_enomem(context); goto out; } for (i = 0; i < n_k; i++) { keys[i].principal = principal; keys[i].vno = princ.kvno + 1; /* XXX get entry again */ keys[i].keyblock = k[i]; keys[i].timestamp = time(NULL); } } if (n_k == 0) krb5_warn(context, ret, "no keys written to keytab for %s", unparsed); for (i = 0; i < n_k; i++) { ret = krb5_kt_add_entry(context, e->keytab, &keys[i]); if (ret) krb5_warn(context, ret, "krb5_kt_add_entry(%lu)", (unsigned long)i); } out: kadm5_free_principal_ent(kadm_handle, &princ); if (k) { for (i = 0; i < n_k; i++) memset(k[i].keyvalue.data, 0, k[i].keyvalue.length); free(k); } free(unparsed); free(keys); return 0; }