xref: /onnv-gate/usr/src/lib/krb5/kadm5/srv/server_kdb.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
6*0Sstevel@tonic-gate 
7*0Sstevel@tonic-gate /*
8*0Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
9*0Sstevel@tonic-gate  *
10*0Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
11*0Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
12*0Sstevel@tonic-gate  *	source code before consulting with your legal department.
13*0Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
14*0Sstevel@tonic-gate  *	product before consulting with your legal department.
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  *	For further information, read the top-level Openvision
17*0Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
18*0Sstevel@tonic-gate  *	copyright.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
21*0Sstevel@tonic-gate  *
22*0Sstevel@tonic-gate  */
23*0Sstevel@tonic-gate 
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate /*
26*0Sstevel@tonic-gate  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
27*0Sstevel@tonic-gate  *
28*0Sstevel@tonic-gate  * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_kdb.c,v 1.2 1998/10/30 02:54:39 marc Exp $
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #if !defined(lint) && !defined(__CODECENTER__)
32*0Sstevel@tonic-gate static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_kdb.c,v 1.2 1998/10/30 02:54:39 marc Exp $";
33*0Sstevel@tonic-gate #endif
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <stdio.h>
36*0Sstevel@tonic-gate #include <stdlib.h>
37*0Sstevel@tonic-gate #include <com_err.h>
38*0Sstevel@tonic-gate #include <kadm5/admin.h>
39*0Sstevel@tonic-gate #include <krb5.h>
40*0Sstevel@tonic-gate #include "server_internal.h"
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate extern caddr_t xdralloc_getdata(XDR *xdrs);
43*0Sstevel@tonic-gate extern void xdralloc_create(XDR *xdrs, enum xdr_op op);
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate krb5_principal	    master_princ;
46*0Sstevel@tonic-gate krb5_db_entry	    master_db;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate krb5_principal	    hist_princ;
49*0Sstevel@tonic-gate krb5_encrypt_block  hist_encblock;
50*0Sstevel@tonic-gate krb5_keyblock	    hist_key;
51*0Sstevel@tonic-gate krb5_db_entry	    hist_db;
52*0Sstevel@tonic-gate krb5_kvno	    hist_kvno;
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /* much of this code is stolen from the kdc.  there should be some
55*0Sstevel@tonic-gate    library code to deal with this. */
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
58*0Sstevel@tonic-gate 				char *r, int from_keyboard)
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate     int		   ret = 0;
61*0Sstevel@tonic-gate     char	   *realm;
62*0Sstevel@tonic-gate     krb5_keyblock  tmk;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate     if (r == NULL)  {
65*0Sstevel@tonic-gate 	if ((ret = krb5_get_default_realm(handle->context, &realm)))
66*0Sstevel@tonic-gate 	    return ret;
67*0Sstevel@tonic-gate     } else {
68*0Sstevel@tonic-gate 	realm = r;
69*0Sstevel@tonic-gate     }
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate     if ((ret = krb5_db_setup_mkey_name(handle->context,
72*0Sstevel@tonic-gate 				       handle->params.mkey_name,
73*0Sstevel@tonic-gate 				       realm, NULL, &master_princ)))
74*0Sstevel@tonic-gate 	goto done;
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate     if (ret = krb5_db_fetch_mkey(handle->context, master_princ,
77*0Sstevel@tonic-gate 				 handle->params.enctype,
78*0Sstevel@tonic-gate 				from_keyboard,
79*0Sstevel@tonic-gate 				 FALSE /* only prompt once */,
80*0Sstevel@tonic-gate 				 handle->params.stash_file,
81*0Sstevel@tonic-gate 				 NULL /* I'm not sure about this,
82*0Sstevel@tonic-gate 					 but it's what the kdc does --marc */,
83*0Sstevel@tonic-gate 				 &handle->master_keyblock))
84*0Sstevel@tonic-gate 	goto done;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate     if ((ret = krb5_db_init(handle->context)) != KSUCCESS)
87*0Sstevel@tonic-gate 	goto done;
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate     if ((ret = krb5_db_verify_master_key(handle->context, master_princ,
90*0Sstevel@tonic-gate 					 &handle->master_keyblock))) {
91*0Sstevel@tonic-gate 	  krb5_db_fini(handle->context);
92*0Sstevel@tonic-gate 	  return ret;
93*0Sstevel@tonic-gate     }
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate done:
96*0Sstevel@tonic-gate     if (r == NULL)
97*0Sstevel@tonic-gate 	free(realm);
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate     return(ret);
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate /*
103*0Sstevel@tonic-gate  * Function: kdb_init_hist
104*0Sstevel@tonic-gate  *
105*0Sstevel@tonic-gate  * Purpose: Initializes the global history variables.
106*0Sstevel@tonic-gate  *
107*0Sstevel@tonic-gate  * Arguments:
108*0Sstevel@tonic-gate  *
109*0Sstevel@tonic-gate  *	handle		(r) kadm5 api server handle
110*0Sstevel@tonic-gate  *	r		(r) realm of history principal to use, or NULL
111*0Sstevel@tonic-gate  *
112*0Sstevel@tonic-gate  * Effects: This function sets the value of the following global
113*0Sstevel@tonic-gate  * variables:
114*0Sstevel@tonic-gate  *
115*0Sstevel@tonic-gate  *	hist_princ	krb5_principal holding the history principal
116*0Sstevel@tonic-gate  *	hist_db		krb5_db_entry of the history principal
117*0Sstevel@tonic-gate  *	hist_key	krb5_keyblock holding the history principal's key
118*0Sstevel@tonic-gate  *	hist_encblock	krb5_encrypt_block holding the procssed hist_key
119*0Sstevel@tonic-gate  *	hist_kvno	the version number of the history key
120*0Sstevel@tonic-gate  *
121*0Sstevel@tonic-gate  * If the history principal does not already exist, this function
122*0Sstevel@tonic-gate  * attempts to create it with kadm5_create_principal.  WARNING!
123*0Sstevel@tonic-gate  * If the history principal is deleted and this function is executed
124*0Sstevel@tonic-gate  * (by kadmind, or kadmin.local, or anything else with permission),
125*0Sstevel@tonic-gate  * the principal will be assigned a new random key and all existing
126*0Sstevel@tonic-gate  * password history information will become useless.
127*0Sstevel@tonic-gate  */
128*0Sstevel@tonic-gate krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate     int	    ret = 0;
131*0Sstevel@tonic-gate     char    *realm, *hist_name;
132*0Sstevel@tonic-gate     krb5_key_data *key_data;
133*0Sstevel@tonic-gate     krb5_key_salt_tuple ks[1];
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate     if (r == NULL)  {
136*0Sstevel@tonic-gate 	if ((ret = krb5_get_default_realm(handle->context, &realm)))
137*0Sstevel@tonic-gate 	    return ret;
138*0Sstevel@tonic-gate     } else {
139*0Sstevel@tonic-gate 	realm = r;
140*0Sstevel@tonic-gate     }
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate     if ((hist_name = (char *) malloc(strlen(KADM5_HIST_PRINCIPAL) +
143*0Sstevel@tonic-gate 				     strlen(realm) + 2)) == NULL)
144*0Sstevel@tonic-gate 	goto done;
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate     (void) sprintf(hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm);
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate     if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
149*0Sstevel@tonic-gate 	goto done;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate     if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL))) {
152*0Sstevel@tonic-gate 	kadm5_principal_ent_rec ent;
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	if (ret != KADM5_UNK_PRINC)
155*0Sstevel@tonic-gate 	    goto done;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	/* try to create the principal */
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 	memset(&ent, 0, sizeof(ent));
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	ent.principal = hist_princ;
162*0Sstevel@tonic-gate 	ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX;
163*0Sstevel@tonic-gate 	ent.attributes = 0;
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 	/* this uses hist_kvno.  So we set it to 2, which will be the
166*0Sstevel@tonic-gate 	   correct value once the principal is created and randomized.
167*0Sstevel@tonic-gate 	   Of course, it doesn't make sense to keep a history for the
168*0Sstevel@tonic-gate 	   history principal, anyway. */
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	hist_kvno = 2;
171*0Sstevel@tonic-gate 	ks[0].ks_enctype = handle->params.enctype;
172*0Sstevel@tonic-gate 	ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
173*0Sstevel@tonic-gate 	ret = kadm5_create_principal_3(handle, &ent,
174*0Sstevel@tonic-gate 				     (KADM5_PRINCIPAL |
175*0Sstevel@tonic-gate 				       KADM5_MAX_LIFE |
176*0Sstevel@tonic-gate 				       KADM5_ATTRIBUTES),
177*0Sstevel@tonic-gate 				       1, ks,
178*0Sstevel@tonic-gate 				      "to-be-random");
179*0Sstevel@tonic-gate 	if (ret)
180*0Sstevel@tonic-gate 	    goto done;
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 	/* this won't let us randomize the hist_princ.  So we cheat. */
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	hist_princ = NULL;
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	ret = kadm5_randkey_principal_3(handle, ent.principal, 0, 1, ks,
187*0Sstevel@tonic-gate 					NULL, NULL);
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	hist_princ = ent.principal;
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	if (ret)
192*0Sstevel@tonic-gate 	    goto done;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	/* now read the newly-created kdb record out of the
195*0Sstevel@tonic-gate 	   database. */
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL)))
198*0Sstevel@tonic-gate 	    goto done;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate     }
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate     ret = krb5_dbe_find_enctype(handle->context, &hist_db,
203*0Sstevel@tonic-gate 			    handle->params.enctype, -1, -1, &key_data);
204*0Sstevel@tonic-gate     if (ret)
205*0Sstevel@tonic-gate 	goto done;
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate     ret = krb5_dbekd_decrypt_key_data(handle->context,
208*0Sstevel@tonic-gate 		&handle->master_keyblock, key_data, &hist_key, NULL);
209*0Sstevel@tonic-gate     if (ret)
210*0Sstevel@tonic-gate 	goto done;
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate     hist_kvno = key_data->key_data_kvno;
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate done:
215*0Sstevel@tonic-gate     free(hist_name);
216*0Sstevel@tonic-gate     if (r == NULL)
217*0Sstevel@tonic-gate 	free(realm);
218*0Sstevel@tonic-gate     return ret;
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate /*
222*0Sstevel@tonic-gate  * Function: kdb_get_entry
223*0Sstevel@tonic-gate  *
224*0Sstevel@tonic-gate  * Purpose: Gets an entry from the kerberos database and breaks
225*0Sstevel@tonic-gate  * it out into a krb5_db_entry and an osa_princ_ent_t.
226*0Sstevel@tonic-gate  *
227*0Sstevel@tonic-gate  * Arguments:
228*0Sstevel@tonic-gate  *
229*0Sstevel@tonic-gate  *		handle		(r) the server_handle
230*0Sstevel@tonic-gate  * 		principal	(r) the principal to get
231*0Sstevel@tonic-gate  * 		kdb		(w) krb5_db_entry to fill in
232*0Sstevel@tonic-gate  * 		adb		(w) osa_princ_ent_rec to fill in
233*0Sstevel@tonic-gate  *
234*0Sstevel@tonic-gate  * when the caller is done with kdb and adb, kdb_free_entry must be
235*0Sstevel@tonic-gate  * called to release them.  The adb record is filled in with the
236*0Sstevel@tonic-gate  * contents of the KRB5_TL_KADM_DATA record; if that record doesn't
237*0Sstevel@tonic-gate  * exist, an empty but valid adb record is returned.
238*0Sstevel@tonic-gate  */
239*0Sstevel@tonic-gate krb5_error_code
240*0Sstevel@tonic-gate kdb_get_entry(kadm5_server_handle_t handle,
241*0Sstevel@tonic-gate 	      krb5_principal principal, krb5_db_entry *kdb,
242*0Sstevel@tonic-gate 	      osa_princ_ent_rec *adb)
243*0Sstevel@tonic-gate {
244*0Sstevel@tonic-gate     krb5_error_code ret;
245*0Sstevel@tonic-gate     int nprincs;
246*0Sstevel@tonic-gate     krb5_boolean more;
247*0Sstevel@tonic-gate     krb5_tl_data tl_data;
248*0Sstevel@tonic-gate     XDR xdrs;
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate     if (ret = krb5_db_get_principal(handle->context, principal, kdb, &nprincs,
251*0Sstevel@tonic-gate 				    &more))
252*0Sstevel@tonic-gate 	return(ret);
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate     if (more) {
255*0Sstevel@tonic-gate 	krb5_db_free_principal(handle->context, kdb, nprincs);
256*0Sstevel@tonic-gate 	return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
257*0Sstevel@tonic-gate     } else if (nprincs != 1) {
258*0Sstevel@tonic-gate 	krb5_db_free_principal(handle->context, kdb, nprincs);
259*0Sstevel@tonic-gate 	return(KADM5_UNK_PRINC);
260*0Sstevel@tonic-gate     }
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate     if (adb) {
263*0Sstevel@tonic-gate 	memset(adb, 0, sizeof(*adb));
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	tl_data.tl_data_type = KRB5_TL_KADM_DATA;
266*0Sstevel@tonic-gate 	/*
267*0Sstevel@tonic-gate 	 * XXX Currently, lookup_tl_data always returns zero; it sets
268*0Sstevel@tonic-gate 	 * tl_data->tl_data_length to zero if the type isn't found.
269*0Sstevel@tonic-gate 	 * This should be fixed...
270*0Sstevel@tonic-gate 	 */
271*0Sstevel@tonic-gate 	if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data))
272*0Sstevel@tonic-gate 	    || (tl_data.tl_data_length == 0)) {
273*0Sstevel@tonic-gate 	    /* there's no admin data.  this can happen, if the admin
274*0Sstevel@tonic-gate 	       server is put into production after some principals
275*0Sstevel@tonic-gate 	       are created.  In this case, return valid admin
276*0Sstevel@tonic-gate 	       data (which is all zeros with the hist_kvno filled
277*0Sstevel@tonic-gate 	       in), and when the entry is written, the admin
278*0Sstevel@tonic-gate 	       data will get stored correctly. */
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate 	    adb->admin_history_kvno = hist_kvno;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	    return(ret);
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents,
286*0Sstevel@tonic-gate 		      tl_data.tl_data_length, XDR_DECODE);
287*0Sstevel@tonic-gate 	if (! xdr_osa_princ_ent_rec(&xdrs, adb)) {
288*0Sstevel@tonic-gate 	   xdr_destroy(&xdrs);
289*0Sstevel@tonic-gate 	   krb5_db_free_principal(handle->context, kdb, 1);
290*0Sstevel@tonic-gate 	   return(OSA_ADB_XDR_FAILURE);
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 	xdr_destroy(&xdrs);
293*0Sstevel@tonic-gate     }
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate     return(0);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate /*
299*0Sstevel@tonic-gate  * Function: kdb_free_entry
300*0Sstevel@tonic-gate  *
301*0Sstevel@tonic-gate  * Purpose: frees the resources allocated by kdb_get_entry
302*0Sstevel@tonic-gate  *
303*0Sstevel@tonic-gate  * Arguments:
304*0Sstevel@tonic-gate  *
305*0Sstevel@tonic-gate  *		handle		(r) the server_handle
306*0Sstevel@tonic-gate  * 		kdb		(w) krb5_db_entry to fill in
307*0Sstevel@tonic-gate  * 		adb		(w) osa_princ_ent_rec to fill in
308*0Sstevel@tonic-gate  *
309*0Sstevel@tonic-gate  * when the caller is done with kdb and adb, kdb_free_entry must be
310*0Sstevel@tonic-gate  * called to release them.
311*0Sstevel@tonic-gate  */
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate krb5_error_code
314*0Sstevel@tonic-gate kdb_free_entry(kadm5_server_handle_t handle,
315*0Sstevel@tonic-gate 	       krb5_db_entry *kdb, osa_princ_ent_rec *adb)
316*0Sstevel@tonic-gate {
317*0Sstevel@tonic-gate     XDR xdrs;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate     if (kdb)
321*0Sstevel@tonic-gate 	krb5_db_free_principal(handle->context, kdb, 1);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate     if (adb) {
324*0Sstevel@tonic-gate 	xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
325*0Sstevel@tonic-gate 	xdr_osa_princ_ent_rec(&xdrs, adb);
326*0Sstevel@tonic-gate 	xdr_destroy(&xdrs);
327*0Sstevel@tonic-gate     }
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate     return(0);
330*0Sstevel@tonic-gate }
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate /*
333*0Sstevel@tonic-gate  * Function: kdb_put_entry
334*0Sstevel@tonic-gate  *
335*0Sstevel@tonic-gate  * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
336*0Sstevel@tonic-gate  * database.
337*0Sstevel@tonic-gate  *
338*0Sstevel@tonic-gate  * Arguments:
339*0Sstevel@tonic-gate  *
340*0Sstevel@tonic-gate  *		handle	(r) the server_handle
341*0Sstevel@tonic-gate  * 		kdb	(r/w) the krb5_db_entry to store
342*0Sstevel@tonic-gate  * 		adb	(r) the osa_princ_db_ent to store
343*0Sstevel@tonic-gate  *
344*0Sstevel@tonic-gate  * Effects:
345*0Sstevel@tonic-gate  *
346*0Sstevel@tonic-gate  * The last modifier field of the kdb is set to the caller at now.
347*0Sstevel@tonic-gate  * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
348*0Sstevel@tonic-gate  * KRB5_TL_KADM_DATA.  kdb is then written to the database.
349*0Sstevel@tonic-gate  */
350*0Sstevel@tonic-gate krb5_error_code
351*0Sstevel@tonic-gate kdb_put_entry(kadm5_server_handle_t handle,
352*0Sstevel@tonic-gate 	      krb5_db_entry *kdb, osa_princ_ent_rec *adb)
353*0Sstevel@tonic-gate {
354*0Sstevel@tonic-gate     krb5_error_code ret;
355*0Sstevel@tonic-gate     krb5_int32 now;
356*0Sstevel@tonic-gate     XDR xdrs;
357*0Sstevel@tonic-gate     krb5_tl_data tl_data;
358*0Sstevel@tonic-gate     int one;
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate     if (ret = krb5_timeofday(handle->context, &now))
361*0Sstevel@tonic-gate 	return(ret);
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate     if (ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
364*0Sstevel@tonic-gate 					     handle->current_caller))
365*0Sstevel@tonic-gate 	return(ret);
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate     xdralloc_create(&xdrs, XDR_ENCODE);
368*0Sstevel@tonic-gate     if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
369*0Sstevel@tonic-gate 	xdr_destroy(&xdrs);
370*0Sstevel@tonic-gate 	return(OSA_ADB_XDR_FAILURE);
371*0Sstevel@tonic-gate     }
372*0Sstevel@tonic-gate     tl_data.tl_data_type = KRB5_TL_KADM_DATA;
373*0Sstevel@tonic-gate     tl_data.tl_data_length = xdr_getpos(&xdrs);
374*0Sstevel@tonic-gate     tl_data.tl_data_contents = (unsigned char *) xdralloc_getdata(&xdrs);
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate     ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate     xdr_destroy(&xdrs);
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate     if (ret)
381*0Sstevel@tonic-gate 	return(ret);
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate     one = 1;
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate     if (ret = krb5_db_put_principal(handle->context, kdb, &one))
386*0Sstevel@tonic-gate 	return(ret);
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate     return(0);
389*0Sstevel@tonic-gate }
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate krb5_error_code
392*0Sstevel@tonic-gate kdb_delete_entry(kadm5_server_handle_t handle, krb5_principal name)
393*0Sstevel@tonic-gate {
394*0Sstevel@tonic-gate     int one = 1;
395*0Sstevel@tonic-gate     krb5_error_code ret;
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate     ret = krb5_db_delete_principal(handle->context, name, &one);
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate     return ret;
400*0Sstevel@tonic-gate }
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate typedef struct _iter_data {
403*0Sstevel@tonic-gate     void (*func)(void *, krb5_principal);
404*0Sstevel@tonic-gate     void *data;
405*0Sstevel@tonic-gate } iter_data;
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate static krb5_error_code
408*0Sstevel@tonic-gate kdb_iter_func(krb5_pointer data, krb5_db_entry *kdb)
409*0Sstevel@tonic-gate {
410*0Sstevel@tonic-gate     iter_data *id = (iter_data *) data;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate     (*(id->func))(id->data, kdb->princ);
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate     return(0);
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate krb5_error_code
418*0Sstevel@tonic-gate kdb_iter_entry(kadm5_server_handle_t handle,
419*0Sstevel@tonic-gate 	       void (*iter_fct)(void *, krb5_principal), void *data)
420*0Sstevel@tonic-gate {
421*0Sstevel@tonic-gate     iter_data id;
422*0Sstevel@tonic-gate     krb5_error_code ret;
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate     id.func = iter_fct;
425*0Sstevel@tonic-gate     id.data = data;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate     if (ret = krb5_db_iterate(handle->context, kdb_iter_func, &id))
428*0Sstevel@tonic-gate 	return(ret);
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate     return(0);
431*0Sstevel@tonic-gate }
432*0Sstevel@tonic-gate 
433