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 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 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 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 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 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 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 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 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