xref: /freebsd/crypto/krb5/src/lib/kadm5/srv/server_kdb.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  * $Header$
6*7f2fe78bSCy Schubert  */
7*7f2fe78bSCy Schubert 
8*7f2fe78bSCy Schubert /*
9*7f2fe78bSCy Schubert  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
10*7f2fe78bSCy Schubert  * Use is subject to license terms.
11*7f2fe78bSCy Schubert  */
12*7f2fe78bSCy Schubert 
13*7f2fe78bSCy Schubert #include "k5-int.h"
14*7f2fe78bSCy Schubert #include <kadm5/admin.h>
15*7f2fe78bSCy Schubert #include "server_internal.h"
16*7f2fe78bSCy Schubert 
17*7f2fe78bSCy Schubert krb5_principal      master_princ;
18*7f2fe78bSCy Schubert krb5_keyblock       master_keyblock; /* local mkey */
19*7f2fe78bSCy Schubert krb5_db_entry       master_db;
20*7f2fe78bSCy Schubert 
21*7f2fe78bSCy Schubert krb5_principal      hist_princ;
22*7f2fe78bSCy Schubert 
23*7f2fe78bSCy Schubert /* much of this code is stolen from the kdc.  there should be some
24*7f2fe78bSCy Schubert    library code to deal with this. */
25*7f2fe78bSCy Schubert 
kdb_init_master(kadm5_server_handle_t handle,char * r,int from_keyboard)26*7f2fe78bSCy Schubert krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
27*7f2fe78bSCy Schubert                                 char *r, int from_keyboard)
28*7f2fe78bSCy Schubert {
29*7f2fe78bSCy Schubert     int            ret = 0;
30*7f2fe78bSCy Schubert     char           *realm;
31*7f2fe78bSCy Schubert     krb5_boolean   from_kbd = FALSE;
32*7f2fe78bSCy Schubert     krb5_kvno       mkvno = IGNORE_VNO;
33*7f2fe78bSCy Schubert 
34*7f2fe78bSCy Schubert     if (from_keyboard)
35*7f2fe78bSCy Schubert         from_kbd = TRUE;
36*7f2fe78bSCy Schubert 
37*7f2fe78bSCy Schubert     if (r == NULL)  {
38*7f2fe78bSCy Schubert         if ((ret = krb5_get_default_realm(handle->context, &realm)))
39*7f2fe78bSCy Schubert             return ret;
40*7f2fe78bSCy Schubert     } else {
41*7f2fe78bSCy Schubert         realm = r;
42*7f2fe78bSCy Schubert     }
43*7f2fe78bSCy Schubert 
44*7f2fe78bSCy Schubert     krb5_free_principal(handle->context, master_princ);
45*7f2fe78bSCy Schubert     master_princ = NULL;
46*7f2fe78bSCy Schubert     if ((ret = krb5_db_setup_mkey_name(handle->context,
47*7f2fe78bSCy Schubert                                        handle->params.mkey_name,
48*7f2fe78bSCy Schubert                                        realm, NULL, &master_princ)))
49*7f2fe78bSCy Schubert         goto done;
50*7f2fe78bSCy Schubert 
51*7f2fe78bSCy Schubert     krb5_free_keyblock_contents(handle->context, &master_keyblock);
52*7f2fe78bSCy Schubert     master_keyblock.enctype = handle->params.enctype;
53*7f2fe78bSCy Schubert 
54*7f2fe78bSCy Schubert     /*
55*7f2fe78bSCy Schubert      * Fetch the local mkey, may not be the latest but that's okay because we
56*7f2fe78bSCy Schubert      * really want the list of all mkeys and those can be retrieved with any
57*7f2fe78bSCy Schubert      * valid mkey.
58*7f2fe78bSCy Schubert      */
59*7f2fe78bSCy Schubert     ret = krb5_db_fetch_mkey(handle->context, master_princ,
60*7f2fe78bSCy Schubert                              master_keyblock.enctype, from_kbd,
61*7f2fe78bSCy Schubert                              FALSE /* only prompt once */,
62*7f2fe78bSCy Schubert                              handle->params.stash_file,
63*7f2fe78bSCy Schubert                              &mkvno  /* get the kvno of the returned mkey */,
64*7f2fe78bSCy Schubert                              NULL /* I'm not sure about this,
65*7f2fe78bSCy Schubert                                      but it's what the kdc does --marc */,
66*7f2fe78bSCy Schubert                              &master_keyblock);
67*7f2fe78bSCy Schubert     if (ret)
68*7f2fe78bSCy Schubert         goto done;
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert     if ((ret = krb5_db_fetch_mkey_list(handle->context, master_princ,
71*7f2fe78bSCy Schubert                                        &master_keyblock))) {
72*7f2fe78bSCy Schubert         krb5_db_fini(handle->context);
73*7f2fe78bSCy Schubert         return (ret);
74*7f2fe78bSCy Schubert     }
75*7f2fe78bSCy Schubert 
76*7f2fe78bSCy Schubert done:
77*7f2fe78bSCy Schubert     if (r == NULL)
78*7f2fe78bSCy Schubert         free(realm);
79*7f2fe78bSCy Schubert 
80*7f2fe78bSCy Schubert     return(ret);
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert 
83*7f2fe78bSCy Schubert /* Fetch the currently active master key version number and keyblock. */
84*7f2fe78bSCy Schubert krb5_error_code
kdb_get_active_mkey(kadm5_server_handle_t handle,krb5_kvno * act_kvno_out,krb5_keyblock ** act_mkey_out)85*7f2fe78bSCy Schubert kdb_get_active_mkey(kadm5_server_handle_t handle, krb5_kvno *act_kvno_out,
86*7f2fe78bSCy Schubert                     krb5_keyblock **act_mkey_out)
87*7f2fe78bSCy Schubert {
88*7f2fe78bSCy Schubert     krb5_error_code ret;
89*7f2fe78bSCy Schubert     krb5_actkvno_node *active_mkey_list;
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert     ret = krb5_dbe_fetch_act_key_list(handle->context, master_princ,
92*7f2fe78bSCy Schubert                                       &active_mkey_list);
93*7f2fe78bSCy Schubert     if (ret)
94*7f2fe78bSCy Schubert         return ret;
95*7f2fe78bSCy Schubert     ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list,
96*7f2fe78bSCy Schubert                                  act_kvno_out, act_mkey_out);
97*7f2fe78bSCy Schubert     krb5_dbe_free_actkvno_list(handle->context, active_mkey_list);
98*7f2fe78bSCy Schubert     return ret;
99*7f2fe78bSCy Schubert }
100*7f2fe78bSCy Schubert 
101*7f2fe78bSCy Schubert /*
102*7f2fe78bSCy Schubert  * Function: kdb_init_hist
103*7f2fe78bSCy Schubert  *
104*7f2fe78bSCy Schubert  * Purpose: Initializes the hist_princ variable.
105*7f2fe78bSCy Schubert  *
106*7f2fe78bSCy Schubert  * Arguments:
107*7f2fe78bSCy Schubert  *
108*7f2fe78bSCy Schubert  *      handle          (r) kadm5 api server handle
109*7f2fe78bSCy Schubert  *      r               (r) realm of history principal to use, or NULL
110*7f2fe78bSCy Schubert  *
111*7f2fe78bSCy Schubert  * Effects: This function sets the value of the hist_princ global variable.
112*7f2fe78bSCy Schubert  */
kdb_init_hist(kadm5_server_handle_t handle,char * r)113*7f2fe78bSCy Schubert krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
114*7f2fe78bSCy Schubert {
115*7f2fe78bSCy Schubert     int     ret = 0;
116*7f2fe78bSCy Schubert     char    *realm, *hist_name;
117*7f2fe78bSCy Schubert 
118*7f2fe78bSCy Schubert     if (r == NULL)  {
119*7f2fe78bSCy Schubert         if ((ret = krb5_get_default_realm(handle->context, &realm)))
120*7f2fe78bSCy Schubert             return ret;
121*7f2fe78bSCy Schubert     } else {
122*7f2fe78bSCy Schubert         realm = r;
123*7f2fe78bSCy Schubert     }
124*7f2fe78bSCy Schubert 
125*7f2fe78bSCy Schubert     if (asprintf(&hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm) < 0) {
126*7f2fe78bSCy Schubert         hist_name = NULL;
127*7f2fe78bSCy Schubert         goto done;
128*7f2fe78bSCy Schubert     }
129*7f2fe78bSCy Schubert 
130*7f2fe78bSCy Schubert     krb5_free_principal(handle->context, hist_princ);
131*7f2fe78bSCy Schubert     hist_princ = NULL;
132*7f2fe78bSCy Schubert     if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
133*7f2fe78bSCy Schubert         goto done;
134*7f2fe78bSCy Schubert 
135*7f2fe78bSCy Schubert done:
136*7f2fe78bSCy Schubert     free(hist_name);
137*7f2fe78bSCy Schubert     if (r == NULL)
138*7f2fe78bSCy Schubert         free(realm);
139*7f2fe78bSCy Schubert     return ret;
140*7f2fe78bSCy Schubert }
141*7f2fe78bSCy Schubert 
142*7f2fe78bSCy Schubert static krb5_error_code
create_hist(kadm5_server_handle_t handle)143*7f2fe78bSCy Schubert create_hist(kadm5_server_handle_t handle)
144*7f2fe78bSCy Schubert {
145*7f2fe78bSCy Schubert     kadm5_ret_t ret;
146*7f2fe78bSCy Schubert     krb5_key_salt_tuple ks[1];
147*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
148*7f2fe78bSCy Schubert     long mask = KADM5_PRINCIPAL | KADM5_MAX_LIFE | KADM5_ATTRIBUTES;
149*7f2fe78bSCy Schubert 
150*7f2fe78bSCy Schubert     /* Create the history principal. */
151*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
152*7f2fe78bSCy Schubert     ent.principal = hist_princ;
153*7f2fe78bSCy Schubert     ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX;
154*7f2fe78bSCy Schubert     ent.attributes = 0;
155*7f2fe78bSCy Schubert     ks[0].ks_enctype = handle->params.enctype;
156*7f2fe78bSCy Schubert     ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
157*7f2fe78bSCy Schubert     ret = kadm5_create_principal_3(handle, &ent, mask, 1, ks, NULL);
158*7f2fe78bSCy Schubert     if (ret)
159*7f2fe78bSCy Schubert         return ret;
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert     /* For better compatibility with pre-1.8 libkadm5 code, we want the
162*7f2fe78bSCy Schubert      * initial history kvno to be 2, so re-randomize it. */
163*7f2fe78bSCy Schubert     return kadm5_randkey_principal_3(handle, ent.principal, 0, 1, ks,
164*7f2fe78bSCy Schubert                                      NULL, NULL);
165*7f2fe78bSCy Schubert }
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert /*
168*7f2fe78bSCy Schubert  * Fetch the current history key(s), creating the history principal if
169*7f2fe78bSCy Schubert  * necessary.  Database created since krb5 1.3 will have only one key, but
170*7f2fe78bSCy Schubert  * databases created before that may have multiple keys (of the same kvno)
171*7f2fe78bSCy Schubert  * and we need to try them all.  History keys will be returned in a list
172*7f2fe78bSCy Schubert  * terminated by an entry with enctype 0.
173*7f2fe78bSCy Schubert  */
174*7f2fe78bSCy Schubert krb5_error_code
kdb_get_hist_key(kadm5_server_handle_t handle,krb5_keyblock ** keyblocks_out,krb5_kvno * kvno_out)175*7f2fe78bSCy Schubert kdb_get_hist_key(kadm5_server_handle_t handle, krb5_keyblock **keyblocks_out,
176*7f2fe78bSCy Schubert                  krb5_kvno *kvno_out)
177*7f2fe78bSCy Schubert {
178*7f2fe78bSCy Schubert     krb5_error_code ret;
179*7f2fe78bSCy Schubert     krb5_db_entry *kdb;
180*7f2fe78bSCy Schubert     krb5_keyblock *mkey, *kblist = NULL;
181*7f2fe78bSCy Schubert     krb5_int16 i;
182*7f2fe78bSCy Schubert 
183*7f2fe78bSCy Schubert     /* Fetch the history principal, creating it if necessary. */
184*7f2fe78bSCy Schubert     ret = kdb_get_entry(handle, hist_princ, &kdb, NULL);
185*7f2fe78bSCy Schubert     if (ret == KADM5_UNK_PRINC) {
186*7f2fe78bSCy Schubert         ret = create_hist(handle);
187*7f2fe78bSCy Schubert         if (ret)
188*7f2fe78bSCy Schubert             return ret;
189*7f2fe78bSCy Schubert         ret = kdb_get_entry(handle, hist_princ, &kdb, NULL);
190*7f2fe78bSCy Schubert     }
191*7f2fe78bSCy Schubert     if (ret)
192*7f2fe78bSCy Schubert         return ret;
193*7f2fe78bSCy Schubert 
194*7f2fe78bSCy Schubert     if (kdb->n_key_data <= 0) {
195*7f2fe78bSCy Schubert         ret = KRB5_KDB_NO_MATCHING_KEY;
196*7f2fe78bSCy Schubert         k5_setmsg(handle->context, ret,
197*7f2fe78bSCy Schubert                   _("History entry contains no key data"));
198*7f2fe78bSCy Schubert         goto done;
199*7f2fe78bSCy Schubert     }
200*7f2fe78bSCy Schubert 
201*7f2fe78bSCy Schubert     ret = krb5_dbe_find_mkey(handle->context, kdb, &mkey);
202*7f2fe78bSCy Schubert     if (ret)
203*7f2fe78bSCy Schubert         goto done;
204*7f2fe78bSCy Schubert 
205*7f2fe78bSCy Schubert     kblist = k5calloc(kdb->n_key_data + 1, sizeof(*kblist), &ret);
206*7f2fe78bSCy Schubert     if (kblist == NULL)
207*7f2fe78bSCy Schubert         goto done;
208*7f2fe78bSCy Schubert     for (i = 0; i < kdb->n_key_data; i++) {
209*7f2fe78bSCy Schubert         ret = krb5_dbe_decrypt_key_data(handle->context, mkey,
210*7f2fe78bSCy Schubert                                         &kdb->key_data[i], &kblist[i],
211*7f2fe78bSCy Schubert                                         NULL);
212*7f2fe78bSCy Schubert         if (ret)
213*7f2fe78bSCy Schubert             goto done;
214*7f2fe78bSCy Schubert     }
215*7f2fe78bSCy Schubert 
216*7f2fe78bSCy Schubert     *keyblocks_out = kblist;
217*7f2fe78bSCy Schubert     kblist = NULL;
218*7f2fe78bSCy Schubert     *kvno_out = kdb->key_data[0].key_data_kvno;
219*7f2fe78bSCy Schubert 
220*7f2fe78bSCy Schubert done:
221*7f2fe78bSCy Schubert     kdb_free_entry(handle, kdb, NULL);
222*7f2fe78bSCy Schubert     kdb_free_keyblocks(handle, kblist);
223*7f2fe78bSCy Schubert     return ret;
224*7f2fe78bSCy Schubert }
225*7f2fe78bSCy Schubert 
226*7f2fe78bSCy Schubert /* Free all keyblocks in a list (terminated by a keyblock with enctype 0). */
227*7f2fe78bSCy Schubert void
kdb_free_keyblocks(kadm5_server_handle_t handle,krb5_keyblock * keyblocks)228*7f2fe78bSCy Schubert kdb_free_keyblocks(kadm5_server_handle_t handle, krb5_keyblock *keyblocks)
229*7f2fe78bSCy Schubert {
230*7f2fe78bSCy Schubert     krb5_keyblock *kb;
231*7f2fe78bSCy Schubert 
232*7f2fe78bSCy Schubert     if (keyblocks == NULL)
233*7f2fe78bSCy Schubert         return;
234*7f2fe78bSCy Schubert     for (kb = keyblocks; kb->enctype != 0; kb++)
235*7f2fe78bSCy Schubert         krb5_free_keyblock_contents(handle->context, kb);
236*7f2fe78bSCy Schubert     free(keyblocks);
237*7f2fe78bSCy Schubert }
238*7f2fe78bSCy Schubert 
239*7f2fe78bSCy Schubert /*
240*7f2fe78bSCy Schubert  * Function: kdb_get_entry
241*7f2fe78bSCy Schubert  *
242*7f2fe78bSCy Schubert  * Purpose: Gets an entry from the kerberos database and breaks
243*7f2fe78bSCy Schubert  * it out into a krb5_db_entry and an osa_princ_ent_t.
244*7f2fe78bSCy Schubert  *
245*7f2fe78bSCy Schubert  * Arguments:
246*7f2fe78bSCy Schubert  *
247*7f2fe78bSCy Schubert  *              handle          (r) the server_handle
248*7f2fe78bSCy Schubert  *              principal       (r) the principal to get
249*7f2fe78bSCy Schubert  *              kdb             (w) krb5_db_entry to create
250*7f2fe78bSCy Schubert  *              adb             (w) osa_princ_ent_rec to fill in
251*7f2fe78bSCy Schubert  *
252*7f2fe78bSCy Schubert  * when the caller is done with kdb and adb, kdb_free_entry must be
253*7f2fe78bSCy Schubert  * called to release them.  The adb record is filled in with the
254*7f2fe78bSCy Schubert  * contents of the KRB5_TL_KADM_DATA record; if that record doesn't
255*7f2fe78bSCy Schubert  * exist, an empty but valid adb record is returned.
256*7f2fe78bSCy Schubert  */
257*7f2fe78bSCy Schubert krb5_error_code
kdb_get_entry(kadm5_server_handle_t handle,krb5_principal principal,krb5_db_entry ** kdb_ptr,osa_princ_ent_rec * adb)258*7f2fe78bSCy Schubert kdb_get_entry(kadm5_server_handle_t handle,
259*7f2fe78bSCy Schubert               krb5_principal principal, krb5_db_entry **kdb_ptr,
260*7f2fe78bSCy Schubert               osa_princ_ent_rec *adb)
261*7f2fe78bSCy Schubert {
262*7f2fe78bSCy Schubert     krb5_error_code ret;
263*7f2fe78bSCy Schubert     krb5_tl_data tl_data;
264*7f2fe78bSCy Schubert     XDR xdrs;
265*7f2fe78bSCy Schubert     krb5_db_entry *kdb;
266*7f2fe78bSCy Schubert 
267*7f2fe78bSCy Schubert     *kdb_ptr = NULL;
268*7f2fe78bSCy Schubert 
269*7f2fe78bSCy Schubert     ret = krb5_db_get_principal(handle->context, principal, 0, &kdb);
270*7f2fe78bSCy Schubert     if (ret == KRB5_KDB_NOENTRY)
271*7f2fe78bSCy Schubert         return(KADM5_UNK_PRINC);
272*7f2fe78bSCy Schubert     if (ret)
273*7f2fe78bSCy Schubert         return(ret);
274*7f2fe78bSCy Schubert 
275*7f2fe78bSCy Schubert     if (adb) {
276*7f2fe78bSCy Schubert         memset(adb, 0, sizeof(*adb));
277*7f2fe78bSCy Schubert 
278*7f2fe78bSCy Schubert         tl_data.tl_data_type = KRB5_TL_KADM_DATA;
279*7f2fe78bSCy Schubert         /*
280*7f2fe78bSCy Schubert          * XXX Currently, lookup_tl_data always returns zero; it sets
281*7f2fe78bSCy Schubert          * tl_data->tl_data_length to zero if the type isn't found.
282*7f2fe78bSCy Schubert          * This should be fixed...
283*7f2fe78bSCy Schubert          */
284*7f2fe78bSCy Schubert         if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data))
285*7f2fe78bSCy Schubert             || (tl_data.tl_data_length == 0)) {
286*7f2fe78bSCy Schubert             /* there's no admin data.  this can happen, if the admin
287*7f2fe78bSCy Schubert                server is put into production after some principals
288*7f2fe78bSCy Schubert                are created.  In this case, return valid admin
289*7f2fe78bSCy Schubert                data (which is all zeros with the hist_kvno filled
290*7f2fe78bSCy Schubert                in), and when the entry is written, the admin
291*7f2fe78bSCy Schubert                data will get stored correctly. */
292*7f2fe78bSCy Schubert 
293*7f2fe78bSCy Schubert             adb->admin_history_kvno = INITIAL_HIST_KVNO;
294*7f2fe78bSCy Schubert             *kdb_ptr = kdb;
295*7f2fe78bSCy Schubert             return(ret);
296*7f2fe78bSCy Schubert         }
297*7f2fe78bSCy Schubert 
298*7f2fe78bSCy Schubert         xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents,
299*7f2fe78bSCy Schubert                       tl_data.tl_data_length, XDR_DECODE);
300*7f2fe78bSCy Schubert         if (! xdr_osa_princ_ent_rec(&xdrs, adb)) {
301*7f2fe78bSCy Schubert             xdr_destroy(&xdrs);
302*7f2fe78bSCy Schubert             krb5_db_free_principal(handle->context, kdb);
303*7f2fe78bSCy Schubert             return(KADM5_XDR_FAILURE);
304*7f2fe78bSCy Schubert         }
305*7f2fe78bSCy Schubert         xdr_destroy(&xdrs);
306*7f2fe78bSCy Schubert     }
307*7f2fe78bSCy Schubert 
308*7f2fe78bSCy Schubert     *kdb_ptr = kdb;
309*7f2fe78bSCy Schubert     return(0);
310*7f2fe78bSCy Schubert }
311*7f2fe78bSCy Schubert 
312*7f2fe78bSCy Schubert /*
313*7f2fe78bSCy Schubert  * Function: kdb_free_entry
314*7f2fe78bSCy Schubert  *
315*7f2fe78bSCy Schubert  * Purpose: frees the resources allocated by kdb_get_entry
316*7f2fe78bSCy Schubert  *
317*7f2fe78bSCy Schubert  * Arguments:
318*7f2fe78bSCy Schubert  *
319*7f2fe78bSCy Schubert  *              handle          (r) the server_handle
320*7f2fe78bSCy Schubert  *              kdb             (w) krb5_db_entry to fill in
321*7f2fe78bSCy Schubert  *              adb             (w) osa_princ_ent_rec to fill in
322*7f2fe78bSCy Schubert  *
323*7f2fe78bSCy Schubert  * when the caller is done with kdb and adb, kdb_free_entry must be
324*7f2fe78bSCy Schubert  * called to release them.
325*7f2fe78bSCy Schubert  */
326*7f2fe78bSCy Schubert 
327*7f2fe78bSCy Schubert krb5_error_code
kdb_free_entry(kadm5_server_handle_t handle,krb5_db_entry * kdb,osa_princ_ent_rec * adb)328*7f2fe78bSCy Schubert kdb_free_entry(kadm5_server_handle_t handle,
329*7f2fe78bSCy Schubert                krb5_db_entry *kdb, osa_princ_ent_rec *adb)
330*7f2fe78bSCy Schubert {
331*7f2fe78bSCy Schubert     XDR xdrs;
332*7f2fe78bSCy Schubert 
333*7f2fe78bSCy Schubert 
334*7f2fe78bSCy Schubert     if (kdb)
335*7f2fe78bSCy Schubert         krb5_db_free_principal(handle->context, kdb);
336*7f2fe78bSCy Schubert 
337*7f2fe78bSCy Schubert     if (adb) {
338*7f2fe78bSCy Schubert         xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
339*7f2fe78bSCy Schubert         xdr_osa_princ_ent_rec(&xdrs, adb);
340*7f2fe78bSCy Schubert         xdr_destroy(&xdrs);
341*7f2fe78bSCy Schubert     }
342*7f2fe78bSCy Schubert 
343*7f2fe78bSCy Schubert     return(0);
344*7f2fe78bSCy Schubert }
345*7f2fe78bSCy Schubert 
346*7f2fe78bSCy Schubert /*
347*7f2fe78bSCy Schubert  * Function: kdb_put_entry
348*7f2fe78bSCy Schubert  *
349*7f2fe78bSCy Schubert  * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
350*7f2fe78bSCy Schubert  * database.
351*7f2fe78bSCy Schubert  *
352*7f2fe78bSCy Schubert  * Arguments:
353*7f2fe78bSCy Schubert  *
354*7f2fe78bSCy Schubert  *              handle  (r) the server_handle
355*7f2fe78bSCy Schubert  *              kdb     (r/w) the krb5_db_entry to store
356*7f2fe78bSCy Schubert  *              adb     (r) the osa_princ_db_ent to store
357*7f2fe78bSCy Schubert  *
358*7f2fe78bSCy Schubert  * Effects:
359*7f2fe78bSCy Schubert  *
360*7f2fe78bSCy Schubert  * The last modifier field of the kdb is set to the caller at now.
361*7f2fe78bSCy Schubert  * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
362*7f2fe78bSCy Schubert  * KRB5_TL_KADM_DATA.  kdb is then written to the database.
363*7f2fe78bSCy Schubert  */
364*7f2fe78bSCy Schubert krb5_error_code
kdb_put_entry(kadm5_server_handle_t handle,krb5_db_entry * kdb,osa_princ_ent_rec * adb)365*7f2fe78bSCy Schubert kdb_put_entry(kadm5_server_handle_t handle,
366*7f2fe78bSCy Schubert               krb5_db_entry *kdb, osa_princ_ent_rec *adb)
367*7f2fe78bSCy Schubert {
368*7f2fe78bSCy Schubert     krb5_error_code ret;
369*7f2fe78bSCy Schubert     krb5_timestamp now;
370*7f2fe78bSCy Schubert     XDR xdrs;
371*7f2fe78bSCy Schubert     krb5_tl_data tl_data;
372*7f2fe78bSCy Schubert 
373*7f2fe78bSCy Schubert     ret = krb5_timeofday(handle->context, &now);
374*7f2fe78bSCy Schubert     if (ret)
375*7f2fe78bSCy Schubert         return(ret);
376*7f2fe78bSCy Schubert 
377*7f2fe78bSCy Schubert     ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
378*7f2fe78bSCy Schubert                                          handle->current_caller);
379*7f2fe78bSCy Schubert     if (ret)
380*7f2fe78bSCy Schubert         return(ret);
381*7f2fe78bSCy Schubert 
382*7f2fe78bSCy Schubert     xdralloc_create(&xdrs, XDR_ENCODE);
383*7f2fe78bSCy Schubert     if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
384*7f2fe78bSCy Schubert         xdr_destroy(&xdrs);
385*7f2fe78bSCy Schubert         return(KADM5_XDR_FAILURE);
386*7f2fe78bSCy Schubert     }
387*7f2fe78bSCy Schubert     tl_data.tl_data_type = KRB5_TL_KADM_DATA;
388*7f2fe78bSCy Schubert     tl_data.tl_data_length = xdr_getpos(&xdrs);
389*7f2fe78bSCy Schubert     tl_data.tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs);
390*7f2fe78bSCy Schubert 
391*7f2fe78bSCy Schubert     ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);
392*7f2fe78bSCy Schubert 
393*7f2fe78bSCy Schubert     xdr_destroy(&xdrs);
394*7f2fe78bSCy Schubert 
395*7f2fe78bSCy Schubert     if (ret)
396*7f2fe78bSCy Schubert         return(ret);
397*7f2fe78bSCy Schubert 
398*7f2fe78bSCy Schubert     /* we are always updating TL data */
399*7f2fe78bSCy Schubert     kdb->mask |= KADM5_TL_DATA;
400*7f2fe78bSCy Schubert 
401*7f2fe78bSCy Schubert     ret = krb5_db_put_principal(handle->context, kdb);
402*7f2fe78bSCy Schubert     if (ret)
403*7f2fe78bSCy Schubert         return(ret);
404*7f2fe78bSCy Schubert 
405*7f2fe78bSCy Schubert     return(0);
406*7f2fe78bSCy Schubert }
407*7f2fe78bSCy Schubert 
408*7f2fe78bSCy Schubert krb5_error_code
kdb_delete_entry(kadm5_server_handle_t handle,krb5_principal name)409*7f2fe78bSCy Schubert kdb_delete_entry(kadm5_server_handle_t handle, krb5_principal name)
410*7f2fe78bSCy Schubert {
411*7f2fe78bSCy Schubert     krb5_error_code ret;
412*7f2fe78bSCy Schubert 
413*7f2fe78bSCy Schubert     ret = krb5_db_delete_principal(handle->context, name);
414*7f2fe78bSCy Schubert     if (ret == KRB5_KDB_NOENTRY)
415*7f2fe78bSCy Schubert         ret = 0;
416*7f2fe78bSCy Schubert     return ret;
417*7f2fe78bSCy Schubert }
418*7f2fe78bSCy Schubert 
419*7f2fe78bSCy Schubert typedef struct _iter_data {
420*7f2fe78bSCy Schubert     void (*func)(void *, krb5_principal);
421*7f2fe78bSCy Schubert     void *data;
422*7f2fe78bSCy Schubert } iter_data;
423*7f2fe78bSCy Schubert 
424*7f2fe78bSCy Schubert static krb5_error_code
kdb_iter_func(krb5_pointer data,krb5_db_entry * kdb)425*7f2fe78bSCy Schubert kdb_iter_func(krb5_pointer data, krb5_db_entry *kdb)
426*7f2fe78bSCy Schubert {
427*7f2fe78bSCy Schubert     iter_data *id = (iter_data *) data;
428*7f2fe78bSCy Schubert 
429*7f2fe78bSCy Schubert     (*(id->func))(id->data, kdb->princ);
430*7f2fe78bSCy Schubert 
431*7f2fe78bSCy Schubert     return(0);
432*7f2fe78bSCy Schubert }
433*7f2fe78bSCy Schubert 
434*7f2fe78bSCy Schubert krb5_error_code
kdb_iter_entry(kadm5_server_handle_t handle,char * match_entry,void (* iter_fct)(void *,krb5_principal),void * data)435*7f2fe78bSCy Schubert kdb_iter_entry(kadm5_server_handle_t handle, char *match_entry,
436*7f2fe78bSCy Schubert                void (*iter_fct)(void *, krb5_principal), void *data)
437*7f2fe78bSCy Schubert {
438*7f2fe78bSCy Schubert     iter_data id;
439*7f2fe78bSCy Schubert     krb5_error_code ret;
440*7f2fe78bSCy Schubert 
441*7f2fe78bSCy Schubert     id.func = iter_fct;
442*7f2fe78bSCy Schubert     id.data = data;
443*7f2fe78bSCy Schubert 
444*7f2fe78bSCy Schubert     ret = krb5_db_iterate(handle->context, match_entry, kdb_iter_func, &id, 0);
445*7f2fe78bSCy Schubert     if (ret)
446*7f2fe78bSCy Schubert         return(ret);
447*7f2fe78bSCy Schubert 
448*7f2fe78bSCy Schubert     return(0);
449*7f2fe78bSCy Schubert }
450