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