krb5_error_code krb5_db_fetch_mkey(krb5_context context, krb5_principal mname, krb5_enctype etype, krb5_boolean fromkeyboard, krb5_boolean twice, char *db_args, krb5_data * salt, krb5_keyblock * key) { krb5_error_code retval; char password[BUFSIZ]; krb5_data pwd; unsigned int size = sizeof(password); int kvno; krb5_keyblock tmp_key; memset(&tmp_key, 0, sizeof(tmp_key)); if (fromkeyboard) { krb5_data scratch; if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1, twice ? krb5_mkey_pwd_prompt2 : 0, password, &size))) { goto clean_n_exit; } pwd.data = password; pwd.length = size; if (!salt) { retval = krb5_principal2salt(context, mname, &scratch); if (retval) goto clean_n_exit; } retval = krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch, key); if (!salt) krb5_xfree(scratch.data); memset(password, 0, sizeof(password)); /* erase it */ } else { kdb5_dal_handle *dal_handle; if (context->db_context == NULL) { retval = kdb_setup_lib_handle(context); if (retval) { goto clean_n_exit; } } dal_handle = (kdb5_dal_handle *) context->db_context; retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } tmp_key.enctype = key->enctype; retval = dal_handle->lib_handle->vftabl.fetch_master_key(context, mname, &tmp_key, &kvno, db_args); get_errmsg(context, retval); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } key->contents = malloc(tmp_key.length); if (key->contents == NULL) { retval = ENOMEM; goto clean_n_exit; } key->magic = tmp_key.magic; key->enctype = tmp_key.enctype; key->length = tmp_key.length; memcpy(key->contents, tmp_key.contents, tmp_key.length); } clean_n_exit: if (tmp_key.contents) { memset(tmp_key.contents, 0, tmp_key.length); krb5_db_free(context, tmp_key.contents); } return retval; }
krb5_error_code krb5_db_put_principal(krb5_context kcontext, krb5_db_entry * entries, int *nentries) { krb5_error_code status = 0; kdb5_dal_handle *dal_handle; char **db_args = NULL; krb5_tl_data *prev, *curr, *next; int db_args_size = 0; if (kcontext->db_context == NULL) { status = kdb_setup_lib_handle(kcontext); if (status) { goto clean_n_exit; } } /* Giving db_args as part of tl data causes, db2 to store the tl_data as such. To prevent this, tl_data is collated and passed as a sepearte argument. Currently supports only one principal. but passing it as a seperate argument makes it difficult for kadmin remote to pass arguments to server. */ prev = NULL, curr = entries->tl_data; while (curr) { if (curr->tl_data_type == KRB5_TL_DB_ARGS) { char **t; /* Since this is expected to be NULL terminated string and this could come from any client, do a check before passing it to db. */ if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] != '\0') { /* not null terminated. Dangerous input */ status = EINVAL; goto clean_n_exit; } db_args_size++; t = realloc(db_args, sizeof(char *) * (db_args_size + 1)); /* 1 for NULL */ if (t == NULL) { status = ENOMEM; goto clean_n_exit; } db_args = t; db_args[db_args_size - 1] = (char *) curr->tl_data_contents; db_args[db_args_size] = NULL; next = curr->tl_data_next; if (prev == NULL) { /* current node is the first in the linked list. remove it */ entries->tl_data = curr->tl_data_next; } else { prev->tl_data_next = curr->tl_data_next; } entries->n_tl_data--; krb5_db_free(kcontext, curr); /* previous does not change */ curr = next; } else { prev = curr; curr = curr->tl_data_next; } } dal_handle = (kdb5_dal_handle *) kcontext->db_context; status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); if (status) { goto clean_n_exit; } status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries, nentries, db_args); get_errmsg(kcontext, status); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); clean_n_exit: while (db_args_size) { if (db_args[db_args_size - 1]) krb5_db_free(kcontext, db_args[db_args_size - 1]); db_args_size--; } if (db_args) free(db_args); return status; }
kadm5_ret_t kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t entry, long mask) { kadm5_server_handle_t handle = server_handle; krb5_tl_data *tl; osa_policy_ent_t p; int ret; size_t len; CHECK_HANDLE(server_handle); krb5_clear_error_message(handle->context); if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL)) return EINVAL; if(strlen(entry->policy) == 0) return KADM5_BAD_POLICY; if((mask & KADM5_POLICY)) return KADM5_BAD_MASK; if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) && entry->allowed_keysalts != NULL) { ret = validate_allowed_keysalts(entry->allowed_keysalts); if (ret) return ret; } if ((mask & KADM5_POLICY_TL_DATA)) { tl = entry->tl_data; while (tl != NULL) { if (tl->tl_data_type < 256) return KADM5_BAD_TL_TYPE; tl = tl->tl_data_next; } } ret = krb5_db_get_policy(handle->context, entry->policy, &p); if (ret == KRB5_KDB_NOENTRY) return KADM5_UNK_POLICY; else if (ret) return ret; if ((mask & KADM5_PW_MAX_LIFE)) p->pw_max_life = entry->pw_max_life; if ((mask & KADM5_PW_MIN_LIFE)) { if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0) { krb5_db_free_policy(handle->context, p); return KADM5_BAD_MIN_PASS_LIFE; } p->pw_min_life = entry->pw_min_life; } if ((mask & KADM5_PW_MIN_LENGTH)) { if(entry->pw_min_length < MIN_PW_LENGTH) { krb5_db_free_policy(handle->context, p); return KADM5_BAD_LENGTH; } p->pw_min_length = entry->pw_min_length; } if ((mask & KADM5_PW_MIN_CLASSES)) { if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES) { krb5_db_free_policy(handle->context, p); return KADM5_BAD_CLASS; } p->pw_min_classes = entry->pw_min_classes; } if ((mask & KADM5_PW_HISTORY_NUM)) { if(entry->pw_history_num < MIN_PW_HISTORY) { krb5_db_free_policy(handle->context, p); return KADM5_BAD_HISTORY; } p->pw_history_num = entry->pw_history_num; } if (handle->api_version >= KADM5_API_VERSION_3) { if ((mask & KADM5_PW_MAX_FAILURE)) p->pw_max_fail = entry->pw_max_fail; if ((mask & KADM5_PW_FAILURE_COUNT_INTERVAL)) p->pw_failcnt_interval = entry->pw_failcnt_interval; if ((mask & KADM5_PW_LOCKOUT_DURATION)) p->pw_lockout_duration = entry->pw_lockout_duration; } if (handle->api_version >= KADM5_API_VERSION_4) { if ((mask & KADM5_POLICY_ATTRIBUTES)) p->attributes = entry->attributes; if ((mask & KADM5_POLICY_MAX_LIFE)) p->max_life = entry->max_life; if ((mask & KADM5_POLICY_MAX_RLIFE)) p->max_renewable_life = entry->max_renewable_life; if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS)) { krb5_db_free(handle->context, p->allowed_keysalts); p->allowed_keysalts = NULL; if (entry->allowed_keysalts != NULL) { len = strlen(entry->allowed_keysalts) + 1; p->allowed_keysalts = krb5_db_alloc(handle->context, NULL, len); if (p->allowed_keysalts == NULL) { ret = ENOMEM; goto cleanup; } memcpy(p->allowed_keysalts, entry->allowed_keysalts, len); } } if ((mask & KADM5_POLICY_TL_DATA)) { for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) { ret = krb5_db_update_tl_data(handle->context, &p->n_tl_data, &p->tl_data, tl); if (ret) goto cleanup; } } } ret = krb5_db_put_policy(handle->context, p); cleanup: krb5_db_free_policy(handle->context, p); return ret; }