xref: /titanic_41/usr/src/lib/krb5/kdb/kdb_convert.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * This file contains api's for conversion of the kdb_incr_update_t
10  * struct(s) into krb5_db_entry struct(s) and vice-versa.
11  */
12 #include <sys/types.h>
13 #include <com_err.h>
14 #include <locale.h>
15 #include <errno.h>
16 #include <iprop_hdr.h>
17 #include "iprop.h"
18 #include <k5-int.h>
19 
20 /* BEGIN CSTYLED */
21 #define	ULOG_ENTRY_TYPE(upd, i)	((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i]
22 
23 #define	ULOG_ENTRY(upd, i) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u
24 
25 #define	ULOG_ENTRY_KEYVAL(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_keydata.av_keydata_val[j]
26 
27 #define	ULOG_ENTRY_PRINC(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_princ.k_components.k_components_val[j]
28 
29 #define	ULOG_ENTRY_MOD_PRINC(upd, i, j)	((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_mod_princ.k_components.k_components_val[j]
30 /* END CSTYLED */
31 
32 typedef enum {
33 	REG_PRINC = 0,
34 	MOD_PRINC = 1
35 } princ_type;
36 
37 
38 /*
39  * This routine tracks the krb5_db_entry fields that have been modified
40  * (by comparing it to the db_entry currently present in principal.db)
41  * in the update.
42  */
43 void
44 find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new,
45 				kdbe_attr_type_t *attrs, int *nattrs) {
46 	int i = 0, j = 0;
47 
48 	krb5_tl_data *first, *second;
49 
50 	if (current->attributes != new->attributes)
51 		attrs[i++] = AT_ATTRFLAGS;
52 
53 	if (current->max_life != new->max_life)
54 		attrs[i++] = AT_MAX_LIFE;
55 
56 	if (current->max_renewable_life != new->max_renewable_life)
57 		attrs[i++] = AT_MAX_RENEW_LIFE;
58 
59 	if (current->expiration != new->expiration)
60 		attrs[i++] = AT_EXP;
61 
62 	if (current->pw_expiration != new->pw_expiration)
63 		attrs[i++] = AT_PW_EXP;
64 
65 	if (current->last_success != new->last_success)
66 		attrs[i++] = AT_LAST_SUCCESS;
67 
68 	if (current->last_failed != new->last_failed)
69 		attrs[i++] = AT_LAST_FAILED;
70 
71 	if (current->fail_auth_count != new->fail_auth_count)
72 		attrs[i++] = AT_FAIL_AUTH_COUNT;
73 
74 	if ((current->princ->type == new->princ->type) &&
75 	    (current->princ->length == new->princ->length)) {
76 		if ((current->princ->realm.length ==
77 			new->princ->realm.length) &&
78 				strncmp(current->princ->realm.data,
79 					new->princ->realm.data,
80 					current->princ->realm.length)) {
81 			for (j = 0; j < current->princ->length; j++) {
82 				if ((current->princ->data[j].data != NULL) &&
83 					(strncmp(current->princ->data[j].data,
84 					    new->princ->data[j].data,
85 					    current->princ->data[j].length))) {
86 					attrs[i++] = AT_PRINC;
87 					break;
88 				}
89 			}
90 		} else {
91 			attrs[i++] = AT_PRINC;
92 		}
93 	} else {
94 		attrs[i++] = AT_PRINC;
95 	}
96 
97 	if (current->n_key_data == new->n_key_data) {
98 		/* Assuming key ordering is the same in new & current */
99 		for (j = 0; j < new->n_key_data; j++) {
100 			if (current->key_data[j].key_data_kvno !=
101 			    new->key_data[j].key_data_kvno) {
102 				attrs[i++] = AT_KEYDATA;
103 				break;
104 			}
105 		}
106 	} else {
107 		attrs[i++] = AT_KEYDATA;
108 	}
109 
110 	if (current->n_tl_data == new->n_tl_data) {
111 		/* Assuming we preserve the TL_DATA ordering between updates */
112 		for (first = current->tl_data, second = new->tl_data;
113 				first; first = first->tl_data_next,
114 					second = second->tl_data_next) {
115 			if ((first->tl_data_length == second->tl_data_length) &&
116 				(first->tl_data_type == second->tl_data_type)) {
117 				if ((memcmp((char *)first->tl_data_contents,
118 					(char *)second->tl_data_contents,
119 					first->tl_data_length)) != 0) {
120 					attrs[i++] = AT_TL_DATA;
121 					break;
122 				}
123 			} else {
124 				attrs[i++] = AT_TL_DATA;
125 				break;
126 			}
127 		}
128 
129 	} else {
130 		attrs[i++] = AT_TL_DATA;
131 	}
132 
133 	if (current->len != new->len)
134 		attrs[i++] = AT_LEN;
135 	/*
136 	 * Store the no. of (possibly :)) changed attributes
137 	 */
138 	*nattrs = i;
139 }
140 
141 
142 /*
143  * Converts the krb5_principal struct from db2 to ulog format.
144  */
145 krb5_error_code
146 conv_princ_2ulog(krb5_principal princ, kdb_incr_update_t *upd,
147 				int cnt, princ_type tp) {
148 	int i = 0;
149 
150 	if ((upd == NULL) || !princ)
151 		return (KRB5KRB_ERR_GENERIC);
152 
153 	switch (tp) {
154 	case REG_PRINC:
155 		ULOG_ENTRY(upd, cnt).av_princ.k_nametype =
156 				(int32_t)princ->type;
157 
158 		ULOG_ENTRY(upd, cnt).av_princ.k_realm.utf8str_t_len =
159 				princ->realm.length;
160 		ULOG_ENTRY(upd, cnt).av_princ.k_realm.utf8str_t_val =
161 				(princ->realm.data != NULL) ?
162 				strdup(princ->realm.data) : NULL;
163 
164 		ULOG_ENTRY(upd, cnt).av_princ.k_components.k_components_len =
165 				(uint_t)princ->length;
166 
167 		ULOG_ENTRY(upd, cnt).av_princ.k_components.k_components_val =
168 				malloc(princ->length * sizeof (kdbe_data_t));
169 		if (ULOG_ENTRY(upd, cnt).av_princ.k_components.k_components_val
170 				== NULL)
171 			return (ENOMEM);
172 
173 		for (i = 0; i < princ->length; i++) {
174 			ULOG_ENTRY_PRINC(upd, cnt, i).k_magic =
175 				princ->data[i].magic;
176 			ULOG_ENTRY_PRINC(upd, cnt, i).k_data.utf8str_t_len =
177 				princ->data[i].length;
178 			ULOG_ENTRY_PRINC(upd, cnt, i).k_data.utf8str_t_val =
179 				(princ->data[i].data != NULL) ?
180 				strdup(princ->data[i].data) : NULL;
181 		}
182 		break;
183 
184 	case MOD_PRINC:
185 		ULOG_ENTRY(upd, cnt).av_mod_princ.k_nametype =
186 				(int32_t)princ->type;
187 
188 		ULOG_ENTRY(upd, cnt).av_mod_princ.k_realm.utf8str_t_len =
189 				princ->realm.length;
190 
191 		ULOG_ENTRY(upd, cnt).av_mod_princ.k_realm.utf8str_t_val =
192 				(princ->realm.data != NULL) ?
193 				strdup(princ->realm.data) : NULL;
194 
195 		ULOG_ENTRY(upd, cnt).av_mod_princ.k_components.k_components_len
196 				= (uint_t)princ->length;
197 
198 		ULOG_ENTRY(upd, cnt).av_mod_princ.k_components.k_components_val
199 				= malloc(princ->length * sizeof (kdbe_data_t));
200 		if (ULOG_ENTRY(upd,
201 			cnt).av_mod_princ.k_components.k_components_val == NULL)
202 			return (ENOMEM);
203 
204 		for (i = 0; i < princ->length; i++) {
205 			ULOG_ENTRY_MOD_PRINC(upd, cnt, i).k_magic =
206 				princ->data[i].magic;
207 			ULOG_ENTRY_MOD_PRINC(upd, cnt, i).k_data.utf8str_t_len
208 				= princ->data[i].length;
209 			ULOG_ENTRY_MOD_PRINC(upd, cnt, i).k_data.utf8str_t_val
210 				= (princ->data[i].data != NULL) ?
211 				strdup(princ->data[i].data) : NULL;
212 		}
213 		break;
214 
215 	default:
216 		break;
217 	}
218 	return (0);
219 }
220 
221 /*
222  * Converts the krb5_principal struct from ulog to db2 format.
223  */
224 krb5_error_code
225 conv_princ_2db(krb5_context context, krb5_principal *dbprinc,
226 			kdb_incr_update_t *upd,
227 			int cnt, princ_type tp,
228 			int princ_exists) {
229 
230 	int i;
231 	krb5_principal princ;
232 
233 	if (upd == NULL)
234 		return (KRB5KRB_ERR_GENERIC);
235 
236 	if (princ_exists == 0) {
237 		princ = NULL;
238 		princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
239 		if (princ == NULL) {
240 			return (ENOMEM);
241 		}
242 	} else {
243 		princ = *dbprinc;
244 	}
245 
246 	switch (tp) {
247 	case REG_PRINC:
248 		princ->type = (krb5_int32)
249 			ULOG_ENTRY(upd, cnt).av_princ.k_nametype;
250 		princ->realm.length = (int)
251 			ULOG_ENTRY(upd, cnt).av_princ.k_realm.utf8str_t_len;
252 
253 		if (princ_exists == 0)
254 			princ->realm.data = NULL;
255 		princ->realm.data = (char *)realloc(princ->realm.data,
256 					(princ->realm.length + 1));
257 		if (princ->realm.data == NULL)
258 			goto error;
259 		strlcpy(princ->realm.data,
260 		(char *)ULOG_ENTRY(upd, cnt).av_princ.k_realm.utf8str_t_val,
261 		(princ->realm.length + 1));
262 
263 		princ->length = (krb5_int32)ULOG_ENTRY(upd,
264 				cnt).av_princ.k_components.k_components_len;
265 
266 		if (princ_exists == 0)
267 			princ->data = NULL;
268 		princ->data = (krb5_data *)realloc(princ->data,
269 			(princ->length * sizeof (krb5_data)));
270 		if (princ->data == NULL)
271 			goto error;
272 
273 		for (i = 0; i < princ->length; i++) {
274 			princ->data[i].magic =
275 				ULOG_ENTRY_PRINC(upd, cnt, i).k_magic;
276 			princ->data[i].length = (int)
277 			ULOG_ENTRY_PRINC(upd, cnt, i).k_data.utf8str_t_len;
278 
279 			if (princ_exists == 0)
280 				princ->data[i].data = NULL;
281 			princ->data[i].data = (char *)realloc(
282 				princ->data[i].data,
283 				(princ->data[i].length + 1));
284 			if (princ->data[i].data == NULL)
285 				goto error;
286 
287 			strlcpy(princ->data[i].data, (char *)ULOG_ENTRY_PRINC(
288 				upd, cnt, i).k_data.utf8str_t_val,
289 				(princ->data[i].length + 1));
290 		}
291 		break;
292 
293 	case MOD_PRINC:
294 		princ->type = (krb5_int32)
295 			ULOG_ENTRY(upd, cnt).av_mod_princ.k_nametype;
296 		princ->realm.length = (int)
297 			ULOG_ENTRY(upd, cnt).av_mod_princ.k_realm.utf8str_t_len;
298 
299 		if (princ_exists == 0)
300 			princ->realm.data = NULL;
301 		princ->realm.data = (char *)realloc(princ->realm.data,
302 			(princ->realm.length + 1));
303 		if (princ->realm.data == NULL)
304 			goto error;
305 		strlcpy(princ->realm.data, (char *)ULOG_ENTRY(upd,
306 				cnt).av_mod_princ.k_realm.utf8str_t_val,
307 				(princ->realm.length + 1));
308 
309 		princ->length = (krb5_int32)ULOG_ENTRY(upd,
310 				cnt).av_mod_princ.k_components.k_components_len;
311 
312 		if (princ_exists == 0)
313 			princ->data = NULL;
314 		princ->data = (krb5_data *)realloc(princ->data,
315 				(princ->length * sizeof (krb5_data)));
316 		if (princ->data == NULL)
317 			goto error;
318 
319 		for (i = 0; i < princ->length; i++) {
320 			princ->data[i].magic =
321 				ULOG_ENTRY_MOD_PRINC(upd, cnt, i).k_magic;
322 			princ->data[i].length = (int)
323 			ULOG_ENTRY_MOD_PRINC(upd, cnt, i).k_data.utf8str_t_len;
324 
325 			if (princ_exists == 0)
326 				princ->data[i].data = NULL;
327 			princ->data[i].data = (char *)realloc(
328 				princ->data[i].data,
329 				(princ->data[i].length + 1));
330 			if (princ->data[i].data == NULL)
331 				goto error;
332 			strlcpy(princ->data[i].data,
333 				(char *)ULOG_ENTRY_MOD_PRINC(upd,
334 					cnt, i).k_data.utf8str_t_val,
335 					(princ->data[i].length + 1));
336 		}
337 		break;
338 
339 	default:
340 		break;
341 	}
342 
343 	*dbprinc = princ;
344 	return (0);
345 error:
346 	krb5_free_principal(context, princ);
347 	return (ENOMEM);
348 }
349 
350 
351 /*
352  * This routine converts one or more krb5 db2 records into update
353  * log (ulog) entry format. Space for the update log entries should
354  * be allocated prior to invocation of this routine.
355  */
356 krb5_error_code
357 ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
358 				kdb_incr_update_t *updates,
359 				int nentries) {
360 	int i, j, k, cnt, final, nattrs, tmpint, nprincs;
361 	unsigned int more;
362 	krb5_principal tmpprinc;
363 	krb5_tl_data *newtl;
364 	krb5_db_entry curr;
365 	krb5_error_code ret;
366 	kdbe_attr_type_t *attr_types;
367 	kdb_incr_update_t *upd;
368 	krb5_db_entry *ent;
369 	boolean_t kadm_data_yes;
370 
371 	if ((updates == NULL) || (entries == NULL))
372 		return (KRB5KRB_ERR_GENERIC);
373 
374 	upd = updates;
375 	ent = entries;
376 
377 	for (k = 0; k < nentries; k++) {
378 		nprincs = nattrs = tmpint = 0;
379 		final = -1;
380 		kadm_data_yes = B_FALSE;
381 		attr_types = NULL;
382 
383 		if ((upd->kdb_update.kdbe_t_val = (kdbe_val_t *)
384 				malloc(MAXENTRY_SIZE)) == NULL) {
385 			return (ENOMEM);
386 		}
387 
388 		/*
389 		 * Find out which attrs have been modified
390 		 */
391 		if ((attr_types = (kdbe_attr_type_t *)malloc(
392 			    sizeof (kdbe_attr_type_t) * MAXATTRS_SIZE))
393 					== NULL) {
394 			return (ENOMEM);
395 		}
396 
397 		if ((ret = krb5_db_get_principal(context, ent->princ, &curr,
398 						&nprincs, &more)))
399 			return (ret);
400 
401 		if (nprincs == 0) {
402 			/*
403 			 * This is a new entry to the database, hence will
404 			 * include all the attribute-value pairs
405 			 *
406 			 * We leave out the TL_DATA types which we model as
407 			 * attrs in kdbe_attr_type_t, since listing AT_TL_DATA
408 			 * encompasses these other types-turned-attributes
409 			 *
410 			 * So, we do *NOT* consider AT_MOD_PRINC, AT_MOD_TIME,
411 			 * AT_MOD_WHERE, AT_PW_LAST_CHANGE, AT_PW_POLICY,
412 			 * AT_PW_POLICY_SWITCH, AT_PW_HIST_KVNO and AT_PW_HIST,
413 			 * totalling 8 attrs.
414 			 */
415 			while (nattrs < MAXATTRS_SIZE - 8) {
416 				attr_types[nattrs] = nattrs;
417 				nattrs++;
418 			}
419 		} else {
420 			find_changed_attrs(&curr, ent, attr_types, &nattrs);
421 
422 			krb5_db_free_principal(context, &curr, nprincs);
423 		}
424 
425 		for (i = 0; i < nattrs; i++) {
426 			switch (attr_types[i]) {
427 			case AT_ATTRFLAGS:
428 				if (ent->attributes >= 0) {
429 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
430 						AT_ATTRFLAGS;
431 					ULOG_ENTRY(upd, final).av_attrflags =
432 						(uint32_t)ent->attributes;
433 				}
434 				break;
435 
436 			case AT_MAX_LIFE:
437 				if (ent->max_life >= 0) {
438 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
439 						AT_MAX_LIFE;
440 					ULOG_ENTRY(upd, final).av_max_life =
441 						(uint32_t)ent->max_life;
442 				}
443 				break;
444 
445 			case AT_MAX_RENEW_LIFE:
446 				if (ent->max_renewable_life >= 0) {
447 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
448 						AT_MAX_RENEW_LIFE;
449 					ULOG_ENTRY(upd,
450 					    final).av_max_renew_life =
451 					    (uint32_t)ent->max_renewable_life;
452 				}
453 				break;
454 
455 			case AT_EXP:
456 				if (ent->expiration >= 0) {
457 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
458 						AT_EXP;
459 					ULOG_ENTRY(upd, final).av_exp =
460 						(uint32_t)ent->expiration;
461 				}
462 				break;
463 
464 			case AT_PW_EXP:
465 				if (ent->pw_expiration >= 0) {
466 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
467 						AT_PW_EXP;
468 					ULOG_ENTRY(upd, final).av_pw_exp =
469 						(uint32_t)ent->pw_expiration;
470 				}
471 				break;
472 
473 			case AT_LAST_SUCCESS:
474 				if (ent->last_success >= 0) {
475 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
476 						AT_LAST_SUCCESS;
477 					ULOG_ENTRY(upd,
478 						final).av_last_success =
479 						    (uint32_t)ent->last_success;
480 				}
481 				break;
482 
483 			case AT_LAST_FAILED:
484 				if (ent->last_failed >= 0) {
485 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
486 						AT_LAST_FAILED;
487 					ULOG_ENTRY(upd,
488 						final).av_last_failed =
489 						(uint32_t)ent->last_failed;
490 				}
491 				break;
492 
493 			case AT_FAIL_AUTH_COUNT:
494 				if (ent->fail_auth_count >= (krb5_kvno)0) {
495 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
496 						AT_FAIL_AUTH_COUNT;
497 					ULOG_ENTRY(upd,
498 						final).av_fail_auth_count =
499 						(uint32_t)ent->fail_auth_count;
500 				}
501 				break;
502 
503 			case AT_PRINC:
504 				if (ent->princ->length > 0) {
505 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
506 						AT_PRINC;
507 					if ((ret = conv_princ_2ulog(ent->princ,
508 						upd, final, REG_PRINC)))
509 						return (ret);
510 				}
511 				break;
512 
513 			case AT_KEYDATA:
514 /* BEGIN CSTYLED */
515 				if (ent->n_key_data >= 0) {
516 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
517 						AT_KEYDATA;
518 					ULOG_ENTRY(upd, final).av_keydata.av_keydata_len = ent->n_key_data;
519 
520 					ULOG_ENTRY(upd, final).av_keydata.av_keydata_val = malloc(ent->n_key_data * sizeof (kdbe_key_t));
521 					if (ULOG_ENTRY(upd, final).av_keydata.av_keydata_val == NULL)
522 						return (ENOMEM);
523 
524 					for (j = 0; j < ent->n_key_data; j++) {
525 						ULOG_ENTRY_KEYVAL(upd, final, j).k_ver = ent->key_data[j].key_data_ver;
526 						ULOG_ENTRY_KEYVAL(upd, final, j).k_kvno = ent->key_data[j].key_data_kvno;
527 						ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_len = ent->key_data[j].key_data_ver;
528 						ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_len = ent->key_data[j].key_data_ver;
529 
530 						ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val = malloc(ent->key_data[j].key_data_ver * sizeof(int32_t));
531 						if (ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val == NULL)
532 							return (ENOMEM);
533 
534 						ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val = malloc(ent->key_data[j].key_data_ver * sizeof(utf8str_t));
535 						if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val == NULL)
536 							return (ENOMEM);
537 
538 						for (cnt = 0; cnt < ent->key_data[j].key_data_ver; cnt++) {
539 							ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val[cnt] = ent->key_data[j].key_data_type[cnt];
540 							ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_len = ent->key_data[j].key_data_length[cnt];
541 							ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val = malloc(ent->key_data[j].key_data_length[cnt] * sizeof (char));
542 							if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val == NULL)
543 								return (ENOMEM);
544 							(void) memcpy(ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val, ent->key_data[j].key_data_contents[cnt], ent->key_data[j].key_data_length[cnt]);
545 						}
546 					}
547 				}
548 				break;
549 
550 			case AT_TL_DATA:
551 				ret = krb5_dbe_lookup_last_pwd_change(context,
552 								ent, &tmpint);
553 				if (ret == 0) {
554 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
555 						AT_PW_LAST_CHANGE;
556 					ULOG_ENTRY(upd, final).av_pw_last_change = tmpint;
557 				}
558 				tmpint = 0;
559 
560 				if(!(ret = krb5_dbe_lookup_mod_princ_data(
561 					context, ent, &tmpint, &tmpprinc))) {
562 
563 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
564 						AT_MOD_PRINC;
565 
566 					ret = conv_princ_2ulog(tmpprinc,
567 					    upd, final, MOD_PRINC);
568 					krb5_free_principal(context, tmpprinc);
569 					if (ret)
570 						return (ret);
571 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
572 						AT_MOD_TIME;
573 					ULOG_ENTRY(upd, final).av_mod_time =
574 						tmpint;
575 				}
576 
577 				newtl = ent->tl_data;
578 				while (newtl) {
579 					switch (newtl->tl_data_type) {
580 					case KRB5_TL_LAST_PWD_CHANGE:
581 					case KRB5_TL_MOD_PRINC:
582 						break;
583 
584 					case KRB5_TL_KADM_DATA:
585 					default:
586 						if (kadm_data_yes == B_FALSE) {
587 							ULOG_ENTRY_TYPE(upd, ++final).av_type = AT_TL_DATA;
588 							ULOG_ENTRY(upd, final).av_tldata.av_tldata_len = 0;
589 							ULOG_ENTRY(upd, final).av_tldata.av_tldata_val = malloc(ent->n_tl_data * sizeof(kdbe_tl_t));
590 
591 							if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val == NULL)
592 								return (ENOMEM);
593 							kadm_data_yes = B_TRUE;
594 						}
595 
596 						tmpint = ULOG_ENTRY(upd, final).av_tldata.av_tldata_len;
597 						ULOG_ENTRY(upd, final).av_tldata.av_tldata_len++;
598 						ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_type = newtl->tl_data_type;
599 						ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_len = newtl->tl_data_length;
600 						ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val = malloc(newtl->tl_data_length * sizeof (char));
601 						if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val == NULL)
602 							return (ENOMEM);
603 						(void) memcpy(ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val, newtl->tl_data_contents, newtl->tl_data_length);
604 						break;
605 					}
606 					newtl = newtl->tl_data_next;
607 				}
608 				break;
609 /* END CSTYLED */
610 
611 			case AT_LEN:
612 				if (ent->len >= 0) {
613 					ULOG_ENTRY_TYPE(upd, ++final).av_type =
614 						AT_LEN;
615 					ULOG_ENTRY(upd, final).av_len =
616 						(int16_t)ent->len;
617 				}
618 				break;
619 
620 			default:
621 				break;
622 			}
623 
624 		}
625 
626 		if (attr_types)
627 			free(attr_types);
628 
629 		/*
630 		 * Update len field in kdb_update
631 		 */
632 		upd->kdb_update.kdbe_t_len = ++final;
633 
634 		/*
635 		 * Bump up to next struct
636 		 */
637 		upd++;
638 		ent++;
639 	}
640 	return (0);
641 }
642 
643 /*
644  * This routine converts one or more update log (ulog) entries into
645  * kerberos db2 records. Required memory should be allocated
646  * for the db2 records (pointed to by krb5_db_entry *ent), prior
647  * to calling this routine.
648  */
649 krb5_error_code
650 ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
651 				kdb_incr_update_t *updates,
652 				int nentries) {
653 	int i, j, k, cnt, mod_time, nattrs, nprincs;
654 	krb5_principal mod_princ = NULL;
655 	krb5_principal dbprinc;
656 	char *dbprincstr = NULL;
657 
658 	krb5_db_entry *ent;
659 	kdb_incr_update_t *upd;
660 
661 	krb5_tl_data *newtl = NULL;
662 	krb5_error_code ret;
663 	unsigned int more;
664 	unsigned int prev_n_keys = 0;
665 
666 	if ((updates == NULL) || (entries == NULL))
667 		return (KRB5KRB_ERR_GENERIC);
668 
669 	ent = entries;
670 	upd = updates;
671 
672 	for (k = 0; k < nentries; k++) {
673 		cnt = nprincs = 0;
674 
675 		/*
676 		 * If the ulog entry represents a DELETE update,
677 		 * just skip to the next entry.
678 		 */
679 		if (upd->kdb_deleted == TRUE)
680 			goto next;
681 
682 		/*
683 		 * Store the no. of changed attributes in nattrs
684 		 */
685 		nattrs = upd->kdb_update.kdbe_t_len;
686 
687 		dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len + 1)
688 					* sizeof (char));
689 		if (dbprincstr == NULL)
690 			return (ENOMEM);
691 		strlcpy(dbprincstr, (char *)upd->kdb_princ_name.utf8str_t_val,
692 				(upd->kdb_princ_name.utf8str_t_len + 1));
693 
694 		ret = krb5_parse_name(context, dbprincstr, &dbprinc);
695 		free(dbprincstr);
696 		if (ret)
697 			return (ret);
698 
699 		ret = krb5_db_get_principal(context, dbprinc, ent, &nprincs,
700 		    &more);
701 		krb5_free_principal(context, dbprinc);
702 		if (ret)
703 			return (ret);
704 
705 		/*
706 		 * Set ent->n_tl_data = 0 initially, if this is an ADD update
707 		 */
708 		if (nprincs == 0)
709 			ent->n_tl_data = 0;
710 
711 		for (i = 0; i < nattrs; i++) {
712 			switch (ULOG_ENTRY_TYPE(upd, i).av_type) {
713 			case AT_ATTRFLAGS:
714 				ent->attributes = (krb5_flags)
715 					ULOG_ENTRY(upd, i).av_attrflags;
716 				break;
717 
718 			case AT_MAX_LIFE:
719 				ent->max_life = (krb5_deltat)
720 					ULOG_ENTRY(upd, i).av_max_life;
721 				break;
722 
723 			case AT_MAX_RENEW_LIFE:
724 				ent->max_renewable_life = (krb5_deltat)
725 					ULOG_ENTRY(upd, i).av_max_renew_life;
726 				break;
727 
728 			case AT_EXP:
729 				ent->expiration = (krb5_timestamp)
730 					ULOG_ENTRY(upd, i).av_exp;
731 				break;
732 
733 			case AT_PW_EXP:
734 				ent->pw_expiration = (krb5_timestamp)
735 					ULOG_ENTRY(upd, i).av_pw_exp;
736 				break;
737 
738 			case AT_LAST_SUCCESS:
739 				ent->last_success = (krb5_timestamp)
740 					ULOG_ENTRY(upd, i).av_last_success;
741 				break;
742 
743 			case AT_LAST_FAILED:
744 				ent->last_failed = (krb5_timestamp)
745 					ULOG_ENTRY(upd, i).av_last_failed;
746 				break;
747 
748 			case AT_FAIL_AUTH_COUNT:
749 				ent->fail_auth_count = (krb5_kvno)
750 					ULOG_ENTRY(upd, i).av_fail_auth_count;
751 				break;
752 
753 			case AT_PRINC:
754 				if ((ret = conv_princ_2db(context,
755 						&(ent->princ), upd,
756 						i, REG_PRINC, nprincs)))
757 					return (ret);
758 				break;
759 
760 			case AT_KEYDATA:
761 
762 				if (nprincs != 0)
763 					prev_n_keys = ent->n_key_data;
764 
765 				ent->n_key_data = (krb5_int16)ULOG_ENTRY(upd,
766 					i).av_keydata.av_keydata_len;
767 				if (nprincs == 0)
768 					ent->key_data = NULL;
769 
770 				ent->key_data = (krb5_key_data *)realloc(
771 					ent->key_data,
772 					(ent->n_key_data *
773 						sizeof (krb5_key_data)));
774 				if (ent->key_data == NULL)
775 					return (ENOMEM);
776 
777 /* BEGIN CSTYLED */
778 				for (j = 0; j < ent->n_key_data; j++) {
779 					ent->key_data[j].key_data_ver = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_ver;
780 					ent->key_data[j].key_data_kvno = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_kvno;
781 
782 					for (cnt = 0; cnt < ent->key_data[j].key_data_ver; cnt++) {
783 						ent->key_data[j].key_data_type[cnt] =  (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val[cnt];
784 						ent->key_data[j].key_data_length[cnt] = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[cnt].utf8str_t_len;
785 						if ((nprincs == 0) || (j >= prev_n_keys))
786 							ent->key_data[j].key_data_contents[cnt] = NULL;
787 
788 						ent->key_data[j].key_data_contents[cnt] = (krb5_octet *)realloc(ent->key_data[j].key_data_contents[cnt], ent->key_data[j].key_data_length[cnt]);
789 						if (ent->key_data[j].key_data_contents[cnt] == NULL)
790 								return (ENOMEM);
791 
792 						(void) memset(ent->key_data[j].key_data_contents[cnt], 0, (ent->key_data[j].key_data_length[cnt] * sizeof (krb5_octet)));
793 						(void) memcpy(ent->key_data[j].key_data_contents[cnt], ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[cnt].utf8str_t_val, ent->key_data[j].key_data_length[cnt]);
794 					}
795 				}
796 				break;
797 
798 			case AT_TL_DATA:
799 				cnt = ULOG_ENTRY(upd, i).av_tldata.av_tldata_len;
800 				newtl = malloc(cnt * sizeof (krb5_tl_data));
801 				(void) memset(newtl, 0, (cnt * sizeof (krb5_tl_data)));
802 				if (newtl == NULL)
803 					return (ENOMEM);
804 
805 				for (j = 0; j < cnt; j++){
806 					newtl[j].tl_data_type = (krb5_int16)ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_type;
807 					newtl[j].tl_data_length = (krb5_int16)ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_len;
808 					newtl[j].tl_data_contents = NULL;
809 					newtl[j].tl_data_contents = malloc(newtl[j].tl_data_length * sizeof (krb5_octet));
810 					if (newtl[j].tl_data_contents == NULL)
811 						return (ENOMEM);
812 
813 					(void) memset(newtl[j].tl_data_contents, 0, (newtl[j].tl_data_length * sizeof (krb5_octet)));
814 					(void) memcpy(newtl[j].tl_data_contents, ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val, newtl[j].tl_data_length);
815 					newtl[j].tl_data_next = NULL;
816 					if (j > 0)
817 						newtl[j - 1].tl_data_next =
818 								&newtl[j];
819 				}
820 
821 				if ((ret = krb5_dbe_update_tl_data(context,
822 								ent, newtl)))
823 					return (ret);
824 				for (j = 0; j < cnt; j++)
825 					if (newtl[j].tl_data_contents) {
826 						free(newtl[j].tl_data_contents);
827 						newtl[j].tl_data_contents = NULL;
828 					}
829 				if (newtl) {
830 					free(newtl);
831 					newtl = NULL;
832 				}
833 				break;
834 /* END CSTYLED */
835 
836 			case AT_PW_LAST_CHANGE:
837 				if ((ret = krb5_dbe_update_last_pwd_change(
838 					context, ent,
839 					ULOG_ENTRY(upd, i).av_pw_last_change)))
840 						return (ret);
841 				break;
842 
843 			case AT_MOD_PRINC:
844 				if ((ret = conv_princ_2db(context,
845 						&mod_princ, upd,
846 						i, MOD_PRINC, 0)))
847 					return (ret);
848 				break;
849 
850 			case AT_MOD_TIME:
851 				mod_time = ULOG_ENTRY(upd, i).av_mod_time;
852 				break;
853 
854 			case AT_LEN:
855 				ent->len = (krb5_int16)
856 						ULOG_ENTRY(upd, i).av_len;
857 				break;
858 
859 			default:
860 				break;
861 			}
862 
863 		}
864 
865 		/*
866 		 * process mod_princ_data request
867 		 */
868 		if (mod_time && mod_princ) {
869 			ret = krb5_dbe_update_mod_princ_data(context, ent,
870 			    mod_time, mod_princ);
871 			krb5_free_principal(context, mod_princ);
872 			if (ret)
873 				return (ret);
874 		}
875 
876 next:
877 		/*
878 		 * Bump up to next struct
879 		 */
880 		upd++;
881 		ent++;
882 	}
883 	return (0);
884 }
885 
886 
887 
888 /*
889  * This routine frees up memory associated with the bunched ulog entries.
890  */
891 void
892 ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates) {
893 
894 	kdb_incr_update_t *upd;
895 	int i, j, k, cnt;
896 
897 	if (updates == NULL)
898 		return;
899 
900 	upd = updates;
901 
902 	/*
903 	 * Loop thru each ulog entry
904 	 */
905 	for (cnt = 0; cnt < no_of_updates; cnt++) {
906 
907 		/*
908 		 * ulog entry - kdb_princ_name
909 		 */
910 		if (upd->kdb_princ_name.utf8str_t_val)
911 			free(upd->kdb_princ_name.utf8str_t_val);
912 
913 /* BEGIN CSTYLED */
914 
915 		/*
916 		 * ulog entry - kdb_kdcs_seen_by
917 		 */
918 		if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) {
919 			for (i = 0; i < upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len; i++) {
920 				if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val)
921 					free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val);
922 			}
923 			if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val)
924 				free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val);
925 		}
926 
927 		/*
928 		 * ulog entry - kdb_futures
929 		 */
930 		if (upd->kdb_futures.kdb_futures_val)
931 			free(upd->kdb_futures.kdb_futures_val);
932 
933 		/*
934 		 * ulog entry - kdb_update
935 		 */
936 		if(upd->kdb_update.kdbe_t_val) {
937 			/*
938 			 * Loop thru all the attributes and free up stuff
939 			 */
940 			for (i = 0; i < upd->kdb_update.kdbe_t_len; i++) {
941 
942 				/*
943 				 * Free av_key_data
944 				 */
945 				if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_KEYDATA) && ULOG_ENTRY(upd, i).av_keydata.av_keydata_val) {
946 
947 					for (j = 0; j < ULOG_ENTRY(upd, i).av_keydata.av_keydata_len; j++) {
948 						if (ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val)
949 							free(ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val);
950 						if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val) {
951 							for (k = 0; k < ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; k++) {
952 							if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val)
953 									free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val);
954 							}
955 							free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val);
956 						}
957 					}
958 					free(ULOG_ENTRY(upd, i).av_keydata.av_keydata_val);
959 				}
960 
961 
962 				/*
963 				 * Free av_tl_data
964 				 */
965 				if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_TL_DATA) && ULOG_ENTRY(upd, i).av_tldata.av_tldata_val) {
966 					for (j = 0; j < ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; j++) {
967 						if (ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val)
968 							free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val);
969 					}
970 					free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val);
971 				}
972 
973 				/*
974 				 * Free av_princ
975 				 */
976 				if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_PRINC) {
977 					if (ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val)
978 						free(ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val);
979 					if (ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val) {
980 						for (j = 0; j < ULOG_ENTRY(upd, i).av_princ.k_components.k_components_len; j++) {
981 							if (ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val)
982 								free(ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val);
983 						}
984 						free(ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val);
985 					}
986 				}
987 
988 				/*
989 				 * Free av_mod_princ
990 				 */
991 				if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_PRINC) {
992 					if (ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val)
993 						free(ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val);
994 					if (ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val) {
995 						for (j = 0; j < ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_len; j++) {
996 							if (ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val)
997 								free(ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val);
998 						}
999 						free(ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val);
1000 					}
1001 				}
1002 
1003 				/*
1004 				 * Free av_mod_where
1005 				 */
1006 				if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_WHERE) && ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val)
1007 					free(ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val);
1008 
1009 				/*
1010 				 * Free av_pw_policy
1011 				 */
1012 				if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_POLICY) && ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val)
1013 					free(ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val);
1014 
1015 				/*
1016 				 * XXX: Free av_pw_hist
1017 				 *
1018 				 * For now, we just free the pointer
1019 				 * to av_pw_hist_val, since we arent
1020 				 * populating this union member in
1021 				 * the conv api function(s) anyways.
1022 				 */
1023 				if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_HIST) && ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val)
1024 					free(ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val);
1025 
1026 			 }
1027 
1028 			/*
1029 			 * Free up the pointer to kdbe_t_val
1030 			 */
1031 			if (upd->kdb_update.kdbe_t_val)
1032 				free(upd->kdb_update.kdbe_t_val);
1033 		}
1034 
1035 /* END CSTYLED */
1036 
1037 		/*
1038 		 * Bump up to next struct
1039 		 */
1040 		upd++;
1041 	}
1042 
1043 
1044 	/*
1045 	 * Finally, free up the pointer to the bunched ulog entries
1046 	 */
1047 	if (updates)
1048 		free(updates);
1049 }
1050