Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/kadm5/srv/svr_policy.c
39566 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4
*
5
* $Header$
6
*/
7
8
#include <sys/types.h>
9
#include <kadm5/admin.h>
10
#include "server_internal.h"
11
#include <stdlib.h>
12
#include <string.h>
13
#include <errno.h>
14
15
#define MIN_PW_HISTORY 1
16
#define MIN_PW_CLASSES 1
17
#define MAX_PW_CLASSES 5
18
#define MIN_PW_LENGTH 1
19
20
/* Validate allowed_keysalts. */
21
static kadm5_ret_t
22
validate_allowed_keysalts(const char *allowed_keysalts)
23
{
24
kadm5_ret_t ret;
25
krb5_key_salt_tuple *ks_tuple = NULL;
26
krb5_int32 n_ks_tuple = 0;
27
28
if (strchr(allowed_keysalts, '\t') != NULL)
29
return KADM5_BAD_KEYSALTS;
30
ret = krb5_string_to_keysalts(allowed_keysalts, ",", NULL, 0,
31
&ks_tuple, &n_ks_tuple);
32
free(ks_tuple);
33
if (ret == EINVAL)
34
return KADM5_BAD_KEYSALTS;
35
return ret;
36
}
37
38
/*
39
* Function: kadm5_create_policy
40
*
41
* Purpose: Create Policies in the policy DB.
42
*
43
* Arguments:
44
* entry (input) The policy entry to be written out to the DB.
45
* mask (input) Specifies which fields in entry are to ge written out
46
* and which get default values.
47
* <return value> 0 if successful otherwise an error code is returned.
48
*
49
* Requires:
50
* Entry must be a valid principal entry, and mask have a valid value.
51
*
52
* Effects:
53
* Writes the data to the database, and does a database sync if
54
* successful.
55
*
56
*/
57
58
kadm5_ret_t
59
kadm5_create_policy(void *server_handle, kadm5_policy_ent_t entry, long mask)
60
{
61
kadm5_server_handle_t handle = server_handle;
62
osa_policy_ent_rec pent, *check_pol;
63
int ret;
64
char *p;
65
66
CHECK_HANDLE(server_handle);
67
68
krb5_clear_error_message(handle->context);
69
70
if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
71
return EINVAL;
72
if(strlen(entry->policy) == 0)
73
return KADM5_BAD_POLICY;
74
if (!(mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK))
75
return KADM5_BAD_MASK;
76
if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) &&
77
entry->allowed_keysalts != NULL) {
78
ret = validate_allowed_keysalts(entry->allowed_keysalts);
79
if (ret)
80
return ret;
81
}
82
83
ret = krb5_db_get_policy(handle->context, entry->policy, &check_pol);
84
if (!ret) {
85
krb5_db_free_policy(handle->context, check_pol);
86
return KADM5_DUP;
87
} else if (ret != KRB5_KDB_NOENTRY) {
88
return ret;
89
}
90
91
memset(&pent, 0, sizeof(pent));
92
pent.name = entry->policy;
93
p = entry->policy;
94
while(*p != '\0') {
95
if(*p < ' ' || *p > '~')
96
return KADM5_BAD_POLICY;
97
else
98
p++;
99
}
100
if (!(mask & KADM5_PW_MAX_LIFE))
101
pent.pw_max_life = 0;
102
else
103
pent.pw_max_life = entry->pw_max_life;
104
if (!(mask & KADM5_PW_MIN_LIFE))
105
pent.pw_min_life = 0;
106
else {
107
if((mask & KADM5_PW_MAX_LIFE)) {
108
if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0)
109
return KADM5_BAD_MIN_PASS_LIFE;
110
}
111
pent.pw_min_life = entry->pw_min_life;
112
}
113
if (!(mask & KADM5_PW_MIN_LENGTH))
114
pent.pw_min_length = MIN_PW_LENGTH;
115
else {
116
if(entry->pw_min_length < MIN_PW_LENGTH)
117
return KADM5_BAD_LENGTH;
118
pent.pw_min_length = entry->pw_min_length;
119
}
120
if (!(mask & KADM5_PW_MIN_CLASSES))
121
pent.pw_min_classes = MIN_PW_CLASSES;
122
else {
123
if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES)
124
return KADM5_BAD_CLASS;
125
pent.pw_min_classes = entry->pw_min_classes;
126
}
127
if (!(mask & KADM5_PW_HISTORY_NUM))
128
pent.pw_history_num = MIN_PW_HISTORY;
129
else {
130
if(entry->pw_history_num < MIN_PW_HISTORY)
131
return KADM5_BAD_HISTORY;
132
else
133
pent.pw_history_num = entry->pw_history_num;
134
}
135
136
if (handle->api_version >= KADM5_API_VERSION_4) {
137
if (!(mask & KADM5_POLICY_ATTRIBUTES))
138
pent.attributes = 0;
139
else
140
pent.attributes = entry->attributes;
141
if (!(mask & KADM5_POLICY_MAX_LIFE))
142
pent.max_life = 0;
143
else
144
pent.max_life = entry->max_life;
145
if (!(mask & KADM5_POLICY_MAX_RLIFE))
146
pent.max_renewable_life = 0;
147
else
148
pent.max_renewable_life = entry->max_renewable_life;
149
if (!(mask & KADM5_POLICY_ALLOWED_KEYSALTS))
150
pent.allowed_keysalts = 0;
151
else
152
pent.allowed_keysalts = entry->allowed_keysalts;
153
if (!(mask & KADM5_POLICY_TL_DATA)) {
154
pent.n_tl_data = 0;
155
pent.tl_data = NULL;
156
} else {
157
pent.n_tl_data = entry->n_tl_data;
158
pent.tl_data = entry->tl_data;
159
}
160
}
161
if (handle->api_version >= KADM5_API_VERSION_3) {
162
if (!(mask & KADM5_PW_MAX_FAILURE))
163
pent.pw_max_fail = 0;
164
else
165
pent.pw_max_fail = entry->pw_max_fail;
166
if (!(mask & KADM5_PW_FAILURE_COUNT_INTERVAL))
167
pent.pw_failcnt_interval = 0;
168
else
169
pent.pw_failcnt_interval = entry->pw_failcnt_interval;
170
if (!(mask & KADM5_PW_LOCKOUT_DURATION))
171
pent.pw_lockout_duration = 0;
172
else
173
pent.pw_lockout_duration = entry->pw_lockout_duration;
174
}
175
176
if ((ret = krb5_db_create_policy(handle->context, &pent)))
177
return ret;
178
else
179
return KADM5_OK;
180
}
181
182
kadm5_ret_t
183
kadm5_delete_policy(void *server_handle, kadm5_policy_t name)
184
{
185
kadm5_server_handle_t handle = server_handle;
186
osa_policy_ent_t entry;
187
int ret;
188
189
CHECK_HANDLE(server_handle);
190
191
krb5_clear_error_message(handle->context);
192
193
if(name == (kadm5_policy_t) NULL)
194
return EINVAL;
195
if(strlen(name) == 0)
196
return KADM5_BAD_POLICY;
197
ret = krb5_db_get_policy(handle->context, name, &entry);
198
if (ret == KRB5_KDB_NOENTRY)
199
return KADM5_UNK_POLICY;
200
else if (ret)
201
return ret;
202
203
krb5_db_free_policy(handle->context, entry);
204
ret = krb5_db_delete_policy(handle->context, name);
205
if (ret == KRB5_KDB_POLICY_REF)
206
ret = KADM5_POLICY_REF;
207
return (ret == 0) ? KADM5_OK : ret;
208
}
209
210
/* Allocate and form a TL data list of a desired size. */
211
static int
212
alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp)
213
{
214
krb5_tl_data **tlp = tldp;
215
int i;
216
217
for (i = 0; i < n_tl_data; i++) {
218
*tlp = calloc(1, sizeof(krb5_tl_data));
219
if (*tlp == NULL)
220
return ENOMEM; /* caller cleans up */
221
memset(*tlp, 0, sizeof(krb5_tl_data));
222
tlp = &((*tlp)->tl_data_next);
223
}
224
225
return 0;
226
}
227
228
static kadm5_ret_t
229
copy_tl_data(krb5_int16 n_tl_data, krb5_tl_data *tl_data,
230
krb5_tl_data **out)
231
{
232
kadm5_ret_t ret;
233
krb5_tl_data *tl, *tl_new;
234
235
if ((ret = alloc_tl_data(n_tl_data, out)))
236
return ret; /* caller cleans up */
237
238
tl = tl_data;
239
tl_new = *out;
240
for (; tl; tl = tl->tl_data_next, tl_new = tl_new->tl_data_next) {
241
tl_new->tl_data_contents = malloc(tl->tl_data_length);
242
if (tl_new->tl_data_contents == NULL)
243
return ENOMEM;
244
memcpy(tl_new->tl_data_contents, tl->tl_data_contents,
245
tl->tl_data_length);
246
tl_new->tl_data_type = tl->tl_data_type;
247
tl_new->tl_data_length = tl->tl_data_length;
248
}
249
250
return 0;
251
}
252
253
kadm5_ret_t
254
kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t entry, long mask)
255
{
256
kadm5_server_handle_t handle = server_handle;
257
krb5_tl_data *tl;
258
osa_policy_ent_t p;
259
int ret;
260
261
CHECK_HANDLE(server_handle);
262
263
krb5_clear_error_message(handle->context);
264
265
if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
266
return EINVAL;
267
if(strlen(entry->policy) == 0)
268
return KADM5_BAD_POLICY;
269
if ((mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK))
270
return KADM5_BAD_MASK;
271
if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) &&
272
entry->allowed_keysalts != NULL) {
273
ret = validate_allowed_keysalts(entry->allowed_keysalts);
274
if (ret)
275
return ret;
276
}
277
if ((mask & KADM5_POLICY_TL_DATA)) {
278
tl = entry->tl_data;
279
while (tl != NULL) {
280
if (tl->tl_data_type < 256)
281
return KADM5_BAD_TL_TYPE;
282
tl = tl->tl_data_next;
283
}
284
}
285
286
ret = krb5_db_get_policy(handle->context, entry->policy, &p);
287
if (ret == KRB5_KDB_NOENTRY)
288
return KADM5_UNK_POLICY;
289
else if (ret)
290
return ret;
291
292
if ((mask & KADM5_PW_MAX_LIFE))
293
p->pw_max_life = entry->pw_max_life;
294
if ((mask & KADM5_PW_MIN_LIFE)) {
295
if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0) {
296
krb5_db_free_policy(handle->context, p);
297
return KADM5_BAD_MIN_PASS_LIFE;
298
}
299
p->pw_min_life = entry->pw_min_life;
300
}
301
if ((mask & KADM5_PW_MIN_LENGTH)) {
302
if(entry->pw_min_length < MIN_PW_LENGTH) {
303
krb5_db_free_policy(handle->context, p);
304
return KADM5_BAD_LENGTH;
305
}
306
p->pw_min_length = entry->pw_min_length;
307
}
308
if ((mask & KADM5_PW_MIN_CLASSES)) {
309
if(entry->pw_min_classes > MAX_PW_CLASSES ||
310
entry->pw_min_classes < MIN_PW_CLASSES) {
311
krb5_db_free_policy(handle->context, p);
312
return KADM5_BAD_CLASS;
313
}
314
p->pw_min_classes = entry->pw_min_classes;
315
}
316
if ((mask & KADM5_PW_HISTORY_NUM)) {
317
if(entry->pw_history_num < MIN_PW_HISTORY) {
318
krb5_db_free_policy(handle->context, p);
319
return KADM5_BAD_HISTORY;
320
}
321
p->pw_history_num = entry->pw_history_num;
322
}
323
if (handle->api_version >= KADM5_API_VERSION_3) {
324
if ((mask & KADM5_PW_MAX_FAILURE))
325
p->pw_max_fail = entry->pw_max_fail;
326
if ((mask & KADM5_PW_FAILURE_COUNT_INTERVAL))
327
p->pw_failcnt_interval = entry->pw_failcnt_interval;
328
if ((mask & KADM5_PW_LOCKOUT_DURATION))
329
p->pw_lockout_duration = entry->pw_lockout_duration;
330
}
331
if (handle->api_version >= KADM5_API_VERSION_4) {
332
if ((mask & KADM5_POLICY_ATTRIBUTES))
333
p->attributes = entry->attributes;
334
if ((mask & KADM5_POLICY_MAX_LIFE))
335
p->max_life = entry->max_life;
336
if ((mask & KADM5_POLICY_MAX_RLIFE))
337
p->max_renewable_life = entry->max_renewable_life;
338
if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS)) {
339
free(p->allowed_keysalts);
340
p->allowed_keysalts = NULL;
341
if (entry->allowed_keysalts != NULL) {
342
p->allowed_keysalts = strdup(entry->allowed_keysalts);
343
if (p->allowed_keysalts == NULL) {
344
ret = ENOMEM;
345
goto cleanup;
346
}
347
}
348
}
349
if ((mask & KADM5_POLICY_TL_DATA)) {
350
for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) {
351
ret = krb5_db_update_tl_data(handle->context, &p->n_tl_data,
352
&p->tl_data, tl);
353
if (ret)
354
goto cleanup;
355
}
356
}
357
}
358
ret = krb5_db_put_policy(handle->context, p);
359
360
cleanup:
361
krb5_db_free_policy(handle->context, p);
362
return ret;
363
}
364
365
kadm5_ret_t
366
kadm5_get_policy(void *server_handle, kadm5_policy_t name,
367
kadm5_policy_ent_t entry)
368
{
369
osa_policy_ent_t t;
370
kadm5_ret_t ret;
371
kadm5_server_handle_t handle = server_handle;
372
373
memset(entry, 0, sizeof(*entry));
374
375
CHECK_HANDLE(server_handle);
376
377
krb5_clear_error_message(handle->context);
378
379
if (name == (kadm5_policy_t) NULL)
380
return EINVAL;
381
if(strlen(name) == 0)
382
return KADM5_BAD_POLICY;
383
ret = krb5_db_get_policy(handle->context, name, &t);
384
if (ret == KRB5_KDB_NOENTRY)
385
return KADM5_UNK_POLICY;
386
else if (ret)
387
return ret;
388
389
if ((entry->policy = strdup(t->name)) == NULL) {
390
ret = ENOMEM;
391
goto cleanup;
392
}
393
entry->pw_min_life = t->pw_min_life;
394
entry->pw_max_life = t->pw_max_life;
395
entry->pw_min_length = t->pw_min_length;
396
entry->pw_min_classes = t->pw_min_classes;
397
entry->pw_history_num = t->pw_history_num;
398
if (handle->api_version >= KADM5_API_VERSION_3) {
399
entry->pw_max_fail = t->pw_max_fail;
400
entry->pw_failcnt_interval = t->pw_failcnt_interval;
401
entry->pw_lockout_duration = t->pw_lockout_duration;
402
}
403
if (handle->api_version >= KADM5_API_VERSION_4) {
404
entry->attributes = t->attributes;
405
entry->max_life = t->max_life;
406
entry->max_renewable_life = t->max_renewable_life;
407
if (t->allowed_keysalts) {
408
entry->allowed_keysalts = strdup(t->allowed_keysalts);
409
if (!entry->allowed_keysalts) {
410
ret = ENOMEM;
411
goto cleanup;
412
}
413
}
414
ret = copy_tl_data(t->n_tl_data, t->tl_data, &entry->tl_data);
415
if (ret)
416
goto cleanup;
417
entry->n_tl_data = t->n_tl_data;
418
}
419
420
ret = 0;
421
422
cleanup:
423
if (ret)
424
kadm5_free_policy_ent(handle, entry);
425
krb5_db_free_policy(handle->context, t);
426
return ret;
427
}
428
429