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