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__)
27 static 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 
37 extern	caddr_t xdralloc_getdata(XDR *xdrs);
38 extern	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  */
78 krb5_error_code
79 osa_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 
128 error:
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  */
153 krb5_error_code
154 osa_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 
185 error:
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  */
206 krb5_error_code
207 osa_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 
256 error:
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  */
281 krb5_error_code
282 osa_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 
328 error:
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  */
348 krb5_error_code
349 osa_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 
396 error:
397     CLOSELOCK(db);
398     return ret;
399 }
400 
401 void
402 osa_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