1
2/*
3 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
4 *
5 *	Openvision retains the copyright to derivative works of
6 *	this source code.  Do *NOT* create a derivative of this
7 *	source code before consulting with your legal department.
8 *	Do *NOT* integrate *ANY* of this source code into another
9 *	product before consulting with your legal department.
10 *
11 *	For further information, read the top-level Openvision
12 *	copyright which is contained in the top-level MIT Kerberos
13 *	copyright.
14 *
15 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
16 *
17 */
18
19
20/*
21 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
22 *
23 * $Header$
24 */
25
26#if !defined(lint) && !defined(__CODECENTER__)
27static char *rcsid = "$Header$";
28#endif
29
30#include	<sys/file.h>
31#include	<fcntl.h>
32#include	"policy_db.h"
33#include	<stdlib.h>
34#include	<string.h>
35#include <errno.h>
36
37extern	caddr_t xdralloc_getdata(XDR *xdrs);
38extern	void xdralloc_create(XDR *xdrs, enum xdr_op op);
39
40#define OPENLOCK(db, mode) \
41{ \
42       int olret; \
43	    if (db == NULL) \
44		 return EINVAL; \
45	    else if (db->magic != OSA_ADB_POLICY_DB_MAGIC) \
46		 return OSA_ADB_DBINIT; \
47	    else if ((olret = osa_adb_open_and_lock(db, mode)) != OSA_ADB_OK) \
48		 return olret; \
49	    }
50
51#define CLOSELOCK(db) \
52{ \
53     int cl_ret; \
54     if ((cl_ret = osa_adb_close_and_unlock(db)) != OSA_ADB_OK) \
55	  return cl_ret; \
56}
57
58
59/*
60 * Function: osa_adb_create_policy
61 *
62 * Purpose: create a policy entry in the policy db.
63 *
64 * Arguments:
65 *	entry		(input) pointer to the entry to be added
66 * 	<return value>	OSA_ADB_OK on success, else error code.
67 *
68 * Requires:
69 *	entry have a valid name.
70 *
71 * Effects:
72 *	creates the entry in the db
73 *
74 * Modifies:
75 *	the policy db.
76 *
77 */
78krb5_error_code
79osa_adb_create_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
80{
81    DBT			dbkey;
82    DBT			dbdata;
83    XDR			xdrs;
84    int			ret;
85
86    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
87
88    if(entry->name == NULL) {
89	 ret = EINVAL;
90	 goto error;
91    }
92    dbkey.data = entry->name;
93    dbkey.size = (strlen(entry->name) + 1);
94
95    switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
96    case 0:
97	 ret = OSA_ADB_DUP;
98	 goto error;
99    case 1:
100	break;
101    default:
102	 ret = errno;
103	 goto error;
104    }
105    xdralloc_create(&xdrs, XDR_ENCODE);
106    if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
107	xdr_destroy(&xdrs);
108	ret = OSA_ADB_XDR_FAILURE;
109	goto error;
110    }
111    dbdata.data = xdralloc_getdata(&xdrs);
112    dbdata.size = xdr_getpos(&xdrs);
113    switch(db->db->put(db->db, &dbkey, &dbdata, R_NOOVERWRITE)) {
114    case 0:
115	if((db->db->sync(db->db, 0)) == -1)
116	    ret = OSA_ADB_FAILURE;
117	ret = OSA_ADB_OK;
118	break;
119    case 1:
120	ret = OSA_ADB_DUP;
121	break;
122    default:
123	ret = OSA_ADB_FAILURE;
124	break;
125    }
126    xdr_destroy(&xdrs);
127
128error:
129    CLOSELOCK(db);
130    return ret;
131}
132
133/*
134 * Function: osa_adb_destroy_policy
135 *
136 * Purpose: destroy a policy entry
137 *
138 * Arguments:
139 *	db		(input) database handle
140 *	name		(input) name of policy
141 * 	<return value>	OSA_ADB_OK on success, or error code.
142 *
143 * Requires:
144 *	db being valid.
145 *	name being non-null.
146 * Effects:
147 *	deletes policy from db.
148 *
149 * Modifies:
150 *	policy db.
151 *
152 */
153krb5_error_code
154osa_adb_destroy_policy(osa_adb_policy_t db, char *name)
155{
156    DBT	    dbkey;
157    int	    status, ret;
158
159    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
160
161    if(name == NULL) {
162	 ret = EINVAL;
163	 goto error;
164    }
165    dbkey.data = name;
166    dbkey.size = (strlen(name) + 1);
167
168    status = db->db->del(db->db, &dbkey, 0);
169    switch(status) {
170    case 1:
171	 ret = OSA_ADB_NOENT;
172	 goto error;
173    case 0:
174	 if ((db->db->sync(db->db, 0)) == -1) {
175	      ret = OSA_ADB_FAILURE;
176	      goto error;
177	 }
178	 ret = OSA_ADB_OK;
179	 break;
180    default:
181	 ret = OSA_ADB_FAILURE;
182	 goto error;
183    }
184
185error:
186    CLOSELOCK(db);
187    return ret;
188}
189
190/*
191 * Function: osa_adb_get_policy
192 *
193 * Purpose: retrieve policy
194 *
195 * Arguments:
196 *	db		(input) db handle
197 *	name		(input) name of policy
198 *	entry		(output) policy entry
199 *      cnt             (inout) Number of entries
200 * 	<return value>	0 on success, error code on failure.
201 *
202 * Requires:
203 * Effects:
204 * Modifies:
205 */
206krb5_error_code
207osa_adb_get_policy(osa_adb_policy_t db, char *name,
208		   osa_policy_ent_t *entry, int *cnt)
209{
210    DBT			dbkey;
211    DBT			dbdata;
212    XDR			xdrs;
213    int			ret;
214    char		*aligned_data;
215
216    OPENLOCK(db, KRB5_DB_LOCKMODE_SHARED);
217
218    *cnt = 1;
219
220    if(name == NULL) {
221	 ret = EINVAL;
222	 goto error;
223    }
224    dbkey.data = name;
225    dbkey.size = (strlen(dbkey.data) + 1);
226    dbdata.data = NULL;
227    dbdata.size = 0;
228    switch((db->db->get(db->db, &dbkey, &dbdata, 0))) {
229    case 1:
230	 ret = OSA_ADB_OK;
231	 *cnt = 0;
232	 goto error;
233    case 0:
234	break;
235    default:
236	 ret = OSA_ADB_FAILURE;
237	 goto error;
238    }
239    if (!(*(entry) = (osa_policy_ent_t)malloc(sizeof(osa_policy_ent_rec)))) {
240	 ret = ENOMEM;
241	 goto error;
242    }
243    if (!(aligned_data = (char *) malloc(dbdata.size))) {
244	 ret = ENOMEM;
245	 goto error;
246    }
247    memcpy(aligned_data, dbdata.data, dbdata.size);
248    memset(*entry, 0, sizeof(osa_policy_ent_rec));
249    xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
250    if (!xdr_osa_policy_ent_rec(&xdrs, *entry))
251	ret =  OSA_ADB_FAILURE;
252    else ret = OSA_ADB_OK;
253    xdr_destroy(&xdrs);
254    free(aligned_data);
255
256error:
257    CLOSELOCK(db);
258    return ret;
259}
260
261/*
262 * Function: osa_adb_put_policy
263 *
264 * Purpose: update a policy in the dababase
265 *
266 * Arguments:
267 *	db		(input) db handle
268 *	entry		(input) policy entry
269 * 	<return value>	0 on success error code on failure.
270 *
271 * Requires:
272 *	[requires]
273 *
274 * Effects:
275 *	[effects]
276 *
277 * Modifies:
278 *	[modifies]
279 *
280 */
281krb5_error_code
282osa_adb_put_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
283{
284    DBT			dbkey;
285    DBT			dbdata;
286    DBT			tmpdb;
287    XDR			xdrs;
288    int			ret;
289
290    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
291
292    if(entry->name == NULL) {
293	 ret = EINVAL;
294	 goto error;
295    }
296    dbkey.data = entry->name;
297    dbkey.size = (strlen(entry->name) + 1);
298    switch(db->db->get(db->db, &dbkey, &tmpdb, 0)) {
299    case 0:
300	break;
301    case 1:
302	ret = OSA_ADB_NOENT;
303	goto error;
304    default:
305	ret = OSA_ADB_FAILURE;
306	goto error;
307    }
308    xdralloc_create(&xdrs, XDR_ENCODE);
309    if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
310	xdr_destroy(&xdrs);
311	ret = OSA_ADB_XDR_FAILURE;
312	goto error;
313    }
314    dbdata.data = xdralloc_getdata(&xdrs);
315    dbdata.size = xdr_getpos(&xdrs);
316    switch(db->db->put(db->db, &dbkey, &dbdata, 0)) {
317    case 0:
318	if((db->db->sync(db->db, 0)) == -1)
319	    ret = OSA_ADB_FAILURE;
320	ret = OSA_ADB_OK;
321	break;
322    default:
323	ret = OSA_ADB_FAILURE;
324	break;
325    }
326    xdr_destroy(&xdrs);
327
328error:
329    CLOSELOCK(db);
330    return ret;
331}
332
333/*
334 * Function: osa_adb_iter_policy
335 *
336 * Purpose: iterate over the policy database.
337 *
338 * Arguments:
339 *	db		(input) db handle
340 *	func		(input) fucntion pointer to call
341 *	data		opaque data type
342 * 	<return value>	0 on success error code on failure
343 *
344 * Requires:
345 * Effects:
346 * Modifies:
347 */
348krb5_error_code
349osa_adb_iter_policy(osa_adb_policy_t db, osa_adb_iter_policy_func func,
350		    void *data)
351{
352    DBT			    dbkey,
353			    dbdata;
354    XDR			    xdrs;
355    int			    ret;
356    osa_policy_ent_t	    entry;
357    char		    *aligned_data;
358
359    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE); /* hmmm */
360
361    if((ret = db->db->seq(db->db, &dbkey, &dbdata, R_FIRST)) == -1) {
362	 ret = errno;
363	 goto error;
364    }
365
366    while (ret == 0) {
367	if (!(entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)))) {
368	     ret = ENOMEM;
369	     goto error;
370	}
371
372	if(!(aligned_data = (char *) malloc(dbdata.size))) {
373	     ret = ENOMEM;
374	     goto error;
375	}
376	memcpy(aligned_data, dbdata.data, dbdata.size);
377
378	memset(entry, 0, sizeof(osa_policy_ent_rec));
379	xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
380	if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
381	    xdr_destroy(&xdrs);
382	    free(aligned_data);
383	    ret = OSA_ADB_FAILURE;
384	    goto error;
385	}
386	(*func)(data, entry);
387	xdr_destroy(&xdrs);
388	free(aligned_data);
389	osa_free_policy_ent(entry);
390	ret = db->db->seq(db->db, &dbkey, &dbdata, R_NEXT);
391    }
392    if(ret == -1)
393	 ret = errno;
394    else ret = OSA_ADB_OK;
395
396error:
397    CLOSELOCK(db);
398    return ret;
399}
400
401void
402osa_free_policy_ent(osa_policy_ent_t val)
403{
404  XDR xdrs;
405
406  xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
407
408  xdr_osa_policy_ent_rec(&xdrs, val);
409
410  free(val);
411}
412