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