1/*
2 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
3 *
4 *	Openvision retains the copyright to derivative works of
5 *	this source code.  Do *NOT* create a derivative of this
6 *	source code before consulting with your legal department.
7 *	Do *NOT* integrate *ANY* of this source code into another
8 *	product before consulting with your legal department.
9 *
10 *	For further information, read the top-level Openvision
11 *	copyright which is contained in the top-level MIT Kerberos
12 *	copyright.
13 *
14 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
15 *
16 */
17
18
19/*
20 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
21 *
22 * $Header$
23 */
24
25#if !defined(lint) && !defined(__CODECENTER__)
26static char *rcsid = "$Header$";
27#endif
28
29#include	"server_internal.h"
30#include	<sys/types.h>
31#include	<kadm5/admin.h>
32#include	<stdlib.h>
33#include	<errno.h>
34
35#define MAX_PW_HISTORY	10
36#define MIN_PW_HISTORY	1
37#define	MIN_PW_CLASSES	1
38#define MAX_PW_CLASSES	5
39#define	MIN_PW_LENGTH	1
40
41/*
42 * Function: kadm5_create_policy
43 *
44 * Purpose: Create Policies in the policy DB.
45 *
46 * Arguments:
47 *	entry	(input) The policy entry to be written out to the DB.
48 *	mask	(input)	Specifies which fields in entry are to ge written out
49 *			and which get default values.
50 *	<return value> 0 if successful otherwise an error code is returned.
51 *
52 * Requires:
53 *	Entry must be a valid principal entry, and mask have a valid value.
54 *
55 * Effects:
56 *	Verifies that mask does not specify that the refcount should
57 *	be set as part of the creation, and calls
58 *	kadm5_create_policy_internal.  If the refcount *is*
59 *	specified, returns KADM5_BAD_MASK.
60 */
61
62kadm5_ret_t
63kadm5_create_policy(void *server_handle,
64			 kadm5_policy_ent_t entry, long mask)
65{
66    CHECK_HANDLE(server_handle);
67
68    krb5_clear_error_message(((kadm5_server_handle_t)server_handle)->context);
69
70    if (mask & KADM5_REF_COUNT)
71	return KADM5_BAD_MASK;
72    else
73	return kadm5_create_policy_internal(server_handle, entry, mask);
74}
75
76/*
77 * Function: kadm5_create_policy_internal
78 *
79 * Purpose: Create Policies in the policy DB.
80 *
81 * Arguments:
82 *	entry	(input) The policy entry to be written out to the DB.
83 *	mask	(input)	Specifies which fields in entry are to ge written out
84 *			and which get default values.
85 *	<return value> 0 if successful otherwise an error code is returned.
86 *
87 * Requires:
88 *	Entry must be a valid principal entry, and mask have a valid value.
89 *
90 * Effects:
91 *	Writes the data to the database, and does a database sync if
92 *	successful.
93 *
94 */
95
96kadm5_ret_t
97kadm5_create_policy_internal(void *server_handle,
98				  kadm5_policy_ent_t entry, long mask)
99{
100    kadm5_server_handle_t handle = server_handle;
101    osa_policy_ent_rec	pent;
102    int			ret;
103    char		*p;
104
105    CHECK_HANDLE(server_handle);
106
107    if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
108	return EINVAL;
109    if(strlen(entry->policy) == 0)
110	return KADM5_BAD_POLICY;
111    if (!(mask & KADM5_POLICY))
112	return KADM5_BAD_MASK;
113
114    pent.name = entry->policy;
115    p = entry->policy;
116    while(*p != '\0') {
117	if(*p < ' ' || *p > '~')
118	    return KADM5_BAD_POLICY;
119	else
120	    p++;
121    }
122    if (!(mask & KADM5_PW_MAX_LIFE))
123	pent.pw_max_life = 0;
124    else
125	pent.pw_max_life = entry->pw_max_life;
126    if (!(mask & KADM5_PW_MIN_LIFE))
127	pent.pw_min_life = 0;
128    else {
129	if((mask & KADM5_PW_MAX_LIFE)) {
130	    if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0)
131		return KADM5_BAD_MIN_PASS_LIFE;
132	}
133	pent.pw_min_life = entry->pw_min_life;
134    }
135    if (!(mask & KADM5_PW_MIN_LENGTH))
136	pent.pw_min_length = MIN_PW_LENGTH;
137    else {
138	if(entry->pw_min_length < MIN_PW_LENGTH)
139	    return KADM5_BAD_LENGTH;
140	pent.pw_min_length = entry->pw_min_length;
141    }
142    if (!(mask & KADM5_PW_MIN_CLASSES))
143	pent.pw_min_classes = MIN_PW_CLASSES;
144    else {
145	if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES)
146	    return KADM5_BAD_CLASS;
147	pent.pw_min_classes = entry->pw_min_classes;
148    }
149    if (!(mask & KADM5_PW_HISTORY_NUM))
150	pent.pw_history_num = MIN_PW_HISTORY;
151    else {
152	if(entry->pw_history_num < MIN_PW_HISTORY ||
153	   entry->pw_history_num > MAX_PW_HISTORY)
154	    return KADM5_BAD_HISTORY;
155	else
156	    pent.pw_history_num = entry->pw_history_num;
157    }
158    if (!(mask & KADM5_REF_COUNT))
159	pent.policy_refcnt = 0;
160    else
161	pent.policy_refcnt = entry->policy_refcnt;
162    if ((ret = krb5_db_create_policy(handle->context, &pent)))
163	return ret;
164    else
165	return KADM5_OK;
166}
167
168kadm5_ret_t
169kadm5_delete_policy(void *server_handle, kadm5_policy_t name)
170{
171    kadm5_server_handle_t handle = server_handle;
172    osa_policy_ent_t		entry;
173    int				ret;
174    int                         cnt=1;
175
176    CHECK_HANDLE(server_handle);
177
178    krb5_clear_error_message(handle->context);
179
180    if(name == (kadm5_policy_t) NULL)
181	return EINVAL;
182    if(strlen(name) == 0)
183	return KADM5_BAD_POLICY;
184    if((ret = krb5_db_get_policy(handle->context, name, &entry,&cnt)))
185	return ret;
186    if( cnt != 1 )
187	return KADM5_UNK_POLICY;
188
189    if(entry->policy_refcnt != 0) {
190	krb5_db_free_policy(handle->context, entry);
191	return KADM5_POLICY_REF;
192    }
193    krb5_db_free_policy(handle->context, entry);
194    if ((ret = krb5_db_delete_policy(handle->context, name)))
195	return ret;
196    else
197	return KADM5_OK;
198}
199
200kadm5_ret_t
201kadm5_modify_policy(void *server_handle,
202			 kadm5_policy_ent_t entry, long mask)
203{
204    CHECK_HANDLE(server_handle);
205
206    krb5_clear_error_message(((kadm5_server_handle_t)server_handle)->context);
207
208    if (mask & KADM5_REF_COUNT)
209	return KADM5_BAD_MASK;
210    else
211	return kadm5_modify_policy_internal(server_handle, entry, mask);
212}
213
214kadm5_ret_t
215kadm5_modify_policy_internal(void *server_handle,
216				  kadm5_policy_ent_t entry, long mask)
217{
218    kadm5_server_handle_t handle = server_handle;
219    osa_policy_ent_t	p;
220    int			ret;
221    int                 cnt=1;
222
223    CHECK_HANDLE(server_handle);
224
225    if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
226	return EINVAL;
227    if(strlen(entry->policy) == 0)
228	return KADM5_BAD_POLICY;
229    if((mask & KADM5_POLICY))
230	return KADM5_BAD_MASK;
231
232    if ((ret = krb5_db_get_policy(handle->context, entry->policy, &p, &cnt)))
233	return ret;
234    if (cnt != 1)
235	return KADM5_UNK_POLICY;
236
237    if ((mask & KADM5_PW_MAX_LIFE))
238	p->pw_max_life = entry->pw_max_life;
239    if ((mask & KADM5_PW_MIN_LIFE)) {
240	if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0)	{
241	     krb5_db_free_policy(handle->context, p);
242	     return KADM5_BAD_MIN_PASS_LIFE;
243	}
244	p->pw_min_life = entry->pw_min_life;
245    }
246    if ((mask & KADM5_PW_MIN_LENGTH)) {
247	if(entry->pw_min_length < MIN_PW_LENGTH) {
248	      krb5_db_free_policy(handle->context, p);
249	      return KADM5_BAD_LENGTH;
250	 }
251	p->pw_min_length = entry->pw_min_length;
252    }
253    if ((mask & KADM5_PW_MIN_CLASSES)) {
254	if(entry->pw_min_classes > MAX_PW_CLASSES ||
255	   entry->pw_min_classes < MIN_PW_CLASSES) {
256	     krb5_db_free_policy(handle->context, p);
257	     return KADM5_BAD_CLASS;
258	}
259	p->pw_min_classes = entry->pw_min_classes;
260    }
261    if ((mask & KADM5_PW_HISTORY_NUM)) {
262	if(entry->pw_history_num < MIN_PW_HISTORY ||
263	   entry->pw_history_num > MAX_PW_HISTORY) {
264	     krb5_db_free_policy(handle->context, p);
265	     return KADM5_BAD_HISTORY;
266	}
267	p->pw_history_num = entry->pw_history_num;
268    }
269    if ((mask & KADM5_REF_COUNT))
270	p->policy_refcnt = entry->policy_refcnt;
271    ret = krb5_db_put_policy(handle->context, p);
272    krb5_db_free_policy(handle->context, p);
273    return ret;
274}
275
276kadm5_ret_t
277kadm5_get_policy(void *server_handle, kadm5_policy_t name,
278		 kadm5_policy_ent_t entry)
279{
280    osa_policy_ent_t		t;
281    kadm5_policy_ent_rec	entry_local, **entry_orig, *new;
282    int				ret;
283    kadm5_server_handle_t handle = server_handle;
284    int                         cnt=1;
285
286    CHECK_HANDLE(server_handle);
287
288    krb5_clear_error_message(handle->context);
289
290    /*
291     * In version 1, entry is a pointer to a kadm5_policy_ent_t that
292     * should be filled with allocated memory.
293     */
294    if (handle->api_version == KADM5_API_VERSION_1) {
295	 entry_orig = (kadm5_policy_ent_rec **) entry;
296	 *entry_orig = NULL;
297	 entry = &entry_local;
298    }
299
300    if (name == (kadm5_policy_t) NULL)
301	return EINVAL;
302    if(strlen(name) == 0)
303	return KADM5_BAD_POLICY;
304    if((ret = krb5_db_get_policy(handle->context, name, &t, &cnt)))
305	return ret;
306
307    if( cnt != 1 )
308	return KADM5_UNK_POLICY;
309
310    if ((entry->policy = (char *) malloc(strlen(t->name) + 1)) == NULL) {
311	 krb5_db_free_policy(handle->context, t);
312	 return ENOMEM;
313    }
314    strcpy(entry->policy, t->name);
315    entry->pw_min_life = t->pw_min_life;
316    entry->pw_max_life = t->pw_max_life;
317    entry->pw_min_length = t->pw_min_length;
318    entry->pw_min_classes = t->pw_min_classes;
319    entry->pw_history_num = t->pw_history_num;
320    entry->policy_refcnt = t->policy_refcnt;
321    krb5_db_free_policy(handle->context, t);
322
323    if (handle->api_version == KADM5_API_VERSION_1) {
324	 new = (kadm5_policy_ent_t) malloc(sizeof(kadm5_policy_ent_rec));
325	 if (new == NULL) {
326	      free(entry->policy);
327	      krb5_db_free_policy(handle->context, t);
328	      return ENOMEM;
329	 }
330	 *new = *entry;
331	 *entry_orig = new;
332    }
333
334    return KADM5_OK;
335}
336