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