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