Path: blob/main/crypto/krb5/src/lib/kadm5/srv/svr_policy.c
39566 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved3*4* $Header$5*/67#include <sys/types.h>8#include <kadm5/admin.h>9#include "server_internal.h"10#include <stdlib.h>11#include <string.h>12#include <errno.h>1314#define MIN_PW_HISTORY 115#define MIN_PW_CLASSES 116#define MAX_PW_CLASSES 517#define MIN_PW_LENGTH 11819/* Validate allowed_keysalts. */20static kadm5_ret_t21validate_allowed_keysalts(const char *allowed_keysalts)22{23kadm5_ret_t ret;24krb5_key_salt_tuple *ks_tuple = NULL;25krb5_int32 n_ks_tuple = 0;2627if (strchr(allowed_keysalts, '\t') != NULL)28return KADM5_BAD_KEYSALTS;29ret = krb5_string_to_keysalts(allowed_keysalts, ",", NULL, 0,30&ks_tuple, &n_ks_tuple);31free(ks_tuple);32if (ret == EINVAL)33return KADM5_BAD_KEYSALTS;34return ret;35}3637/*38* Function: kadm5_create_policy39*40* Purpose: Create Policies in the policy DB.41*42* Arguments:43* entry (input) The policy entry to be written out to the DB.44* mask (input) Specifies which fields in entry are to ge written out45* and which get default values.46* <return value> 0 if successful otherwise an error code is returned.47*48* Requires:49* Entry must be a valid principal entry, and mask have a valid value.50*51* Effects:52* Writes the data to the database, and does a database sync if53* successful.54*55*/5657kadm5_ret_t58kadm5_create_policy(void *server_handle, kadm5_policy_ent_t entry, long mask)59{60kadm5_server_handle_t handle = server_handle;61osa_policy_ent_rec pent, *check_pol;62int ret;63char *p;6465CHECK_HANDLE(server_handle);6667krb5_clear_error_message(handle->context);6869if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))70return EINVAL;71if(strlen(entry->policy) == 0)72return KADM5_BAD_POLICY;73if (!(mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK))74return KADM5_BAD_MASK;75if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) &&76entry->allowed_keysalts != NULL) {77ret = validate_allowed_keysalts(entry->allowed_keysalts);78if (ret)79return ret;80}8182ret = krb5_db_get_policy(handle->context, entry->policy, &check_pol);83if (!ret) {84krb5_db_free_policy(handle->context, check_pol);85return KADM5_DUP;86} else if (ret != KRB5_KDB_NOENTRY) {87return ret;88}8990memset(&pent, 0, sizeof(pent));91pent.name = entry->policy;92p = entry->policy;93while(*p != '\0') {94if(*p < ' ' || *p > '~')95return KADM5_BAD_POLICY;96else97p++;98}99if (!(mask & KADM5_PW_MAX_LIFE))100pent.pw_max_life = 0;101else102pent.pw_max_life = entry->pw_max_life;103if (!(mask & KADM5_PW_MIN_LIFE))104pent.pw_min_life = 0;105else {106if((mask & KADM5_PW_MAX_LIFE)) {107if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0)108return KADM5_BAD_MIN_PASS_LIFE;109}110pent.pw_min_life = entry->pw_min_life;111}112if (!(mask & KADM5_PW_MIN_LENGTH))113pent.pw_min_length = MIN_PW_LENGTH;114else {115if(entry->pw_min_length < MIN_PW_LENGTH)116return KADM5_BAD_LENGTH;117pent.pw_min_length = entry->pw_min_length;118}119if (!(mask & KADM5_PW_MIN_CLASSES))120pent.pw_min_classes = MIN_PW_CLASSES;121else {122if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES)123return KADM5_BAD_CLASS;124pent.pw_min_classes = entry->pw_min_classes;125}126if (!(mask & KADM5_PW_HISTORY_NUM))127pent.pw_history_num = MIN_PW_HISTORY;128else {129if(entry->pw_history_num < MIN_PW_HISTORY)130return KADM5_BAD_HISTORY;131else132pent.pw_history_num = entry->pw_history_num;133}134135if (handle->api_version >= KADM5_API_VERSION_4) {136if (!(mask & KADM5_POLICY_ATTRIBUTES))137pent.attributes = 0;138else139pent.attributes = entry->attributes;140if (!(mask & KADM5_POLICY_MAX_LIFE))141pent.max_life = 0;142else143pent.max_life = entry->max_life;144if (!(mask & KADM5_POLICY_MAX_RLIFE))145pent.max_renewable_life = 0;146else147pent.max_renewable_life = entry->max_renewable_life;148if (!(mask & KADM5_POLICY_ALLOWED_KEYSALTS))149pent.allowed_keysalts = 0;150else151pent.allowed_keysalts = entry->allowed_keysalts;152if (!(mask & KADM5_POLICY_TL_DATA)) {153pent.n_tl_data = 0;154pent.tl_data = NULL;155} else {156pent.n_tl_data = entry->n_tl_data;157pent.tl_data = entry->tl_data;158}159}160if (handle->api_version >= KADM5_API_VERSION_3) {161if (!(mask & KADM5_PW_MAX_FAILURE))162pent.pw_max_fail = 0;163else164pent.pw_max_fail = entry->pw_max_fail;165if (!(mask & KADM5_PW_FAILURE_COUNT_INTERVAL))166pent.pw_failcnt_interval = 0;167else168pent.pw_failcnt_interval = entry->pw_failcnt_interval;169if (!(mask & KADM5_PW_LOCKOUT_DURATION))170pent.pw_lockout_duration = 0;171else172pent.pw_lockout_duration = entry->pw_lockout_duration;173}174175if ((ret = krb5_db_create_policy(handle->context, &pent)))176return ret;177else178return KADM5_OK;179}180181kadm5_ret_t182kadm5_delete_policy(void *server_handle, kadm5_policy_t name)183{184kadm5_server_handle_t handle = server_handle;185osa_policy_ent_t entry;186int ret;187188CHECK_HANDLE(server_handle);189190krb5_clear_error_message(handle->context);191192if(name == (kadm5_policy_t) NULL)193return EINVAL;194if(strlen(name) == 0)195return KADM5_BAD_POLICY;196ret = krb5_db_get_policy(handle->context, name, &entry);197if (ret == KRB5_KDB_NOENTRY)198return KADM5_UNK_POLICY;199else if (ret)200return ret;201202krb5_db_free_policy(handle->context, entry);203ret = krb5_db_delete_policy(handle->context, name);204if (ret == KRB5_KDB_POLICY_REF)205ret = KADM5_POLICY_REF;206return (ret == 0) ? KADM5_OK : ret;207}208209/* Allocate and form a TL data list of a desired size. */210static int211alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp)212{213krb5_tl_data **tlp = tldp;214int i;215216for (i = 0; i < n_tl_data; i++) {217*tlp = calloc(1, sizeof(krb5_tl_data));218if (*tlp == NULL)219return ENOMEM; /* caller cleans up */220memset(*tlp, 0, sizeof(krb5_tl_data));221tlp = &((*tlp)->tl_data_next);222}223224return 0;225}226227static kadm5_ret_t228copy_tl_data(krb5_int16 n_tl_data, krb5_tl_data *tl_data,229krb5_tl_data **out)230{231kadm5_ret_t ret;232krb5_tl_data *tl, *tl_new;233234if ((ret = alloc_tl_data(n_tl_data, out)))235return ret; /* caller cleans up */236237tl = tl_data;238tl_new = *out;239for (; tl; tl = tl->tl_data_next, tl_new = tl_new->tl_data_next) {240tl_new->tl_data_contents = malloc(tl->tl_data_length);241if (tl_new->tl_data_contents == NULL)242return ENOMEM;243memcpy(tl_new->tl_data_contents, tl->tl_data_contents,244tl->tl_data_length);245tl_new->tl_data_type = tl->tl_data_type;246tl_new->tl_data_length = tl->tl_data_length;247}248249return 0;250}251252kadm5_ret_t253kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t entry, long mask)254{255kadm5_server_handle_t handle = server_handle;256krb5_tl_data *tl;257osa_policy_ent_t p;258int ret;259260CHECK_HANDLE(server_handle);261262krb5_clear_error_message(handle->context);263264if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))265return EINVAL;266if(strlen(entry->policy) == 0)267return KADM5_BAD_POLICY;268if ((mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK))269return KADM5_BAD_MASK;270if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) &&271entry->allowed_keysalts != NULL) {272ret = validate_allowed_keysalts(entry->allowed_keysalts);273if (ret)274return ret;275}276if ((mask & KADM5_POLICY_TL_DATA)) {277tl = entry->tl_data;278while (tl != NULL) {279if (tl->tl_data_type < 256)280return KADM5_BAD_TL_TYPE;281tl = tl->tl_data_next;282}283}284285ret = krb5_db_get_policy(handle->context, entry->policy, &p);286if (ret == KRB5_KDB_NOENTRY)287return KADM5_UNK_POLICY;288else if (ret)289return ret;290291if ((mask & KADM5_PW_MAX_LIFE))292p->pw_max_life = entry->pw_max_life;293if ((mask & KADM5_PW_MIN_LIFE)) {294if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0) {295krb5_db_free_policy(handle->context, p);296return KADM5_BAD_MIN_PASS_LIFE;297}298p->pw_min_life = entry->pw_min_life;299}300if ((mask & KADM5_PW_MIN_LENGTH)) {301if(entry->pw_min_length < MIN_PW_LENGTH) {302krb5_db_free_policy(handle->context, p);303return KADM5_BAD_LENGTH;304}305p->pw_min_length = entry->pw_min_length;306}307if ((mask & KADM5_PW_MIN_CLASSES)) {308if(entry->pw_min_classes > MAX_PW_CLASSES ||309entry->pw_min_classes < MIN_PW_CLASSES) {310krb5_db_free_policy(handle->context, p);311return KADM5_BAD_CLASS;312}313p->pw_min_classes = entry->pw_min_classes;314}315if ((mask & KADM5_PW_HISTORY_NUM)) {316if(entry->pw_history_num < MIN_PW_HISTORY) {317krb5_db_free_policy(handle->context, p);318return KADM5_BAD_HISTORY;319}320p->pw_history_num = entry->pw_history_num;321}322if (handle->api_version >= KADM5_API_VERSION_3) {323if ((mask & KADM5_PW_MAX_FAILURE))324p->pw_max_fail = entry->pw_max_fail;325if ((mask & KADM5_PW_FAILURE_COUNT_INTERVAL))326p->pw_failcnt_interval = entry->pw_failcnt_interval;327if ((mask & KADM5_PW_LOCKOUT_DURATION))328p->pw_lockout_duration = entry->pw_lockout_duration;329}330if (handle->api_version >= KADM5_API_VERSION_4) {331if ((mask & KADM5_POLICY_ATTRIBUTES))332p->attributes = entry->attributes;333if ((mask & KADM5_POLICY_MAX_LIFE))334p->max_life = entry->max_life;335if ((mask & KADM5_POLICY_MAX_RLIFE))336p->max_renewable_life = entry->max_renewable_life;337if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS)) {338free(p->allowed_keysalts);339p->allowed_keysalts = NULL;340if (entry->allowed_keysalts != NULL) {341p->allowed_keysalts = strdup(entry->allowed_keysalts);342if (p->allowed_keysalts == NULL) {343ret = ENOMEM;344goto cleanup;345}346}347}348if ((mask & KADM5_POLICY_TL_DATA)) {349for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) {350ret = krb5_db_update_tl_data(handle->context, &p->n_tl_data,351&p->tl_data, tl);352if (ret)353goto cleanup;354}355}356}357ret = krb5_db_put_policy(handle->context, p);358359cleanup:360krb5_db_free_policy(handle->context, p);361return ret;362}363364kadm5_ret_t365kadm5_get_policy(void *server_handle, kadm5_policy_t name,366kadm5_policy_ent_t entry)367{368osa_policy_ent_t t;369kadm5_ret_t ret;370kadm5_server_handle_t handle = server_handle;371372memset(entry, 0, sizeof(*entry));373374CHECK_HANDLE(server_handle);375376krb5_clear_error_message(handle->context);377378if (name == (kadm5_policy_t) NULL)379return EINVAL;380if(strlen(name) == 0)381return KADM5_BAD_POLICY;382ret = krb5_db_get_policy(handle->context, name, &t);383if (ret == KRB5_KDB_NOENTRY)384return KADM5_UNK_POLICY;385else if (ret)386return ret;387388if ((entry->policy = strdup(t->name)) == NULL) {389ret = ENOMEM;390goto cleanup;391}392entry->pw_min_life = t->pw_min_life;393entry->pw_max_life = t->pw_max_life;394entry->pw_min_length = t->pw_min_length;395entry->pw_min_classes = t->pw_min_classes;396entry->pw_history_num = t->pw_history_num;397if (handle->api_version >= KADM5_API_VERSION_3) {398entry->pw_max_fail = t->pw_max_fail;399entry->pw_failcnt_interval = t->pw_failcnt_interval;400entry->pw_lockout_duration = t->pw_lockout_duration;401}402if (handle->api_version >= KADM5_API_VERSION_4) {403entry->attributes = t->attributes;404entry->max_life = t->max_life;405entry->max_renewable_life = t->max_renewable_life;406if (t->allowed_keysalts) {407entry->allowed_keysalts = strdup(t->allowed_keysalts);408if (!entry->allowed_keysalts) {409ret = ENOMEM;410goto cleanup;411}412}413ret = copy_tl_data(t->n_tl_data, t->tl_data, &entry->tl_data);414if (ret)415goto cleanup;416entry->n_tl_data = t->n_tl_data;417}418419ret = 0;420421cleanup:422if (ret)423kadm5_free_policy_ent(handle, entry);424krb5_db_free_policy(handle->context, t);425return ret;426}427428429