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 if (ent->fail_auth_count >= (krb5_kvno)0) { 431 ULOG_ENTRY_TYPE(upd, ++final).av_type = 432 AT_FAIL_AUTH_COUNT; 433 ULOG_ENTRY(upd, 434 final).av_fail_auth_count = 435 (uint32_t)ent->fail_auth_count; 436 } 437 break; 438 439 case AT_PRINC: 440 if (ent->princ->length > 0) { 441 ULOG_ENTRY_TYPE(upd, ++final).av_type = 442 AT_PRINC; 443 if ((ret = conv_princ_2ulog(ent->princ, 444 upd, final, REG_PRINC))) { 445 free(attr_types); 446 return (ret); 447 } 448 } 449 break; 450 451 case AT_KEYDATA: 452 /* BEGIN CSTYLED */ 453 if (ent->n_key_data >= 0) { 454 ULOG_ENTRY_TYPE(upd, ++final).av_type = 455 AT_KEYDATA; 456 ULOG_ENTRY(upd, final).av_keydata.av_keydata_len = ent->n_key_data; 457 458 ULOG_ENTRY(upd, final).av_keydata.av_keydata_val = malloc(ent->n_key_data * sizeof (kdbe_key_t)); 459 if (ULOG_ENTRY(upd, final).av_keydata.av_keydata_val == NULL) { 460 free(attr_types); 461 return (ENOMEM); 462 } 463 464 for (j = 0; j < ent->n_key_data; j++) { 465 ULOG_ENTRY_KEYVAL(upd, final, j).k_ver = ent->key_data[j].key_data_ver; 466 ULOG_ENTRY_KEYVAL(upd, final, j).k_kvno = ent->key_data[j].key_data_kvno; 467 ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_len = ent->key_data[j].key_data_ver; 468 ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_len = ent->key_data[j].key_data_ver; 469 470 ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val = malloc(ent->key_data[j].key_data_ver * sizeof(int32_t)); 471 if (ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val == NULL) { 472 free(attr_types); 473 return (ENOMEM); 474 } 475 476 ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val = malloc(ent->key_data[j].key_data_ver * sizeof(utf8str_t)); 477 if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val == NULL) { 478 free(attr_types); 479 return (ENOMEM); 480 } 481 482 for (cnt = 0; cnt < ent->key_data[j].key_data_ver; cnt++) { 483 ULOG_ENTRY_KEYVAL(upd, final, j).k_enctype.k_enctype_val[cnt] = ent->key_data[j].key_data_type[cnt]; 484 ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_len = ent->key_data[j].key_data_length[cnt]; 485 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)); 486 if (ULOG_ENTRY_KEYVAL(upd, final, j).k_contents.k_contents_val[cnt].utf8str_t_val == NULL) { 487 free(attr_types); 488 return (ENOMEM); 489 } 490 (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]); 491 } 492 } 493 } 494 break; 495 496 case AT_TL_DATA: 497 ret = krb5_dbe_lookup_last_pwd_change(context, 498 ent, &tmpint); 499 if (ret == 0) { 500 ULOG_ENTRY_TYPE(upd, ++final).av_type = 501 AT_PW_LAST_CHANGE; 502 ULOG_ENTRY(upd, final).av_pw_last_change = tmpint; 503 } 504 tmpint = 0; 505 506 if(!(ret = krb5_dbe_lookup_mod_princ_data( 507 context, ent, &tmpint, &tmpprinc))) { 508 509 ULOG_ENTRY_TYPE(upd, ++final).av_type = 510 AT_MOD_PRINC; 511 512 ret = conv_princ_2ulog(tmpprinc, 513 upd, final, MOD_PRINC); 514 krb5_free_principal(context, tmpprinc); 515 if (ret) { 516 free(attr_types); 517 return (ret); 518 } 519 ULOG_ENTRY_TYPE(upd, ++final).av_type = 520 AT_MOD_TIME; 521 ULOG_ENTRY(upd, final).av_mod_time = 522 tmpint; 523 } 524 525 newtl = ent->tl_data; 526 while (newtl) { 527 switch (newtl->tl_data_type) { 528 case KRB5_TL_LAST_PWD_CHANGE: 529 case KRB5_TL_MOD_PRINC: 530 break; 531 532 case KRB5_TL_KADM_DATA: 533 default: 534 if (kadm_data_yes == 0) { 535 ULOG_ENTRY_TYPE(upd, ++final).av_type = AT_TL_DATA; 536 ULOG_ENTRY(upd, final).av_tldata.av_tldata_len = 0; 537 ULOG_ENTRY(upd, final).av_tldata.av_tldata_val = malloc(ent->n_tl_data * sizeof(kdbe_tl_t)); 538 539 if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val == NULL) { 540 free(attr_types); 541 return (ENOMEM); 542 } 543 kadm_data_yes = 1; 544 } 545 546 tmpint = ULOG_ENTRY(upd, final).av_tldata.av_tldata_len; 547 ULOG_ENTRY(upd, final).av_tldata.av_tldata_len++; 548 ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_type = newtl->tl_data_type; 549 ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_len = newtl->tl_data_length; 550 ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val = malloc(newtl->tl_data_length * sizeof (char)); 551 if (ULOG_ENTRY(upd, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val == NULL) { 552 free(attr_types); 553 return (ENOMEM); 554 } 555 (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); 556 break; 557 } 558 newtl = newtl->tl_data_next; 559 } 560 break; 561 /* END CSTYLED */ 562 563 case AT_LEN: 564 ULOG_ENTRY_TYPE(upd, ++final).av_type = 565 AT_LEN; 566 ULOG_ENTRY(upd, final).av_len = 567 (int16_t)ent->len; 568 break; 569 570 default: 571 break; 572 } 573 574 } 575 576 if (attr_types) 577 free(attr_types); 578 579 /* 580 * Update len field in kdb_update 581 */ 582 upd->kdb_update.kdbe_t_len = ++final; 583 584 /* 585 * Bump up to next struct 586 */ 587 upd++; 588 ent++; 589 } 590 return (0); 591 } 592 593 /* 594 * This routine converts one or more update log (ulog) entries into 595 * kerberos db2 records. Required memory should be allocated 596 * for the db2 records (pointed to by krb5_db_entry *ent), prior 597 * to calling this routine. 598 */ 599 krb5_error_code 600 ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries, 601 kdb_incr_update_t *updates, 602 int nentries) 603 { 604 int k; 605 krb5_db_entry *ent; 606 kdb_incr_update_t *upd; 607 608 if ((updates == NULL) || (entries == NULL)) 609 return (KRB5KRB_ERR_GENERIC); 610 611 ent = entries; 612 upd = updates; 613 614 for (k = 0; k < nentries; k++) { 615 krb5_principal mod_princ = NULL; 616 int i, j, cnt = 0, mod_time = 0, nattrs, nprincs = 0; 617 krb5_principal dbprinc; 618 char *dbprincstr = NULL; 619 620 krb5_tl_data *newtl = NULL; 621 krb5_error_code ret; 622 unsigned int more; 623 unsigned int prev_n_keys = 0; 624 625 /* 626 * If the ulog entry represents a DELETE update, 627 * just skip to the next entry. 628 */ 629 if (upd->kdb_deleted == TRUE) 630 goto next; 631 632 /* 633 * Store the no. of changed attributes in nattrs 634 */ 635 nattrs = upd->kdb_update.kdbe_t_len; 636 637 dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len + 1) 638 * sizeof (char)); 639 if (dbprincstr == NULL) 640 return (ENOMEM); 641 strncpy(dbprincstr, (char *)upd->kdb_princ_name.utf8str_t_val, 642 upd->kdb_princ_name.utf8str_t_len); 643 dbprincstr[upd->kdb_princ_name.utf8str_t_len] = 0; 644 ret = krb5_parse_name(context, dbprincstr, &dbprinc); 645 free(dbprincstr); 646 if (ret) 647 return (ret); 648 649 ret = krb5_db_get_principal(context, dbprinc, ent, &nprincs, 650 &more); 651 krb5_free_principal(context, dbprinc); 652 if (ret) 653 return (ret); 654 655 /* 656 * Set ent->n_tl_data = 0 initially, if this is an ADD update 657 */ 658 if (nprincs == 0) 659 ent->n_tl_data = 0; 660 661 for (i = 0; i < nattrs; i++) { 662 krb5_principal tmpprinc = NULL; 663 664 #define u (ULOG_ENTRY(upd, i)) 665 switch (ULOG_ENTRY_TYPE(upd, i).av_type) { 666 case AT_ATTRFLAGS: 667 ent->attributes = (krb5_flags) u.av_attrflags; 668 break; 669 670 case AT_MAX_LIFE: 671 ent->max_life = (krb5_deltat) u.av_max_life; 672 break; 673 674 case AT_MAX_RENEW_LIFE: 675 ent->max_renewable_life = (krb5_deltat) u.av_max_renew_life; 676 break; 677 678 case AT_EXP: 679 ent->expiration = (krb5_timestamp) u.av_exp; 680 break; 681 682 case AT_PW_EXP: 683 ent->pw_expiration = (krb5_timestamp) u.av_pw_exp; 684 break; 685 686 case AT_LAST_SUCCESS: 687 ent->last_success = (krb5_timestamp) u.av_last_success; 688 break; 689 690 case AT_LAST_FAILED: 691 ent->last_failed = (krb5_timestamp) u.av_last_failed; 692 break; 693 694 case AT_FAIL_AUTH_COUNT: 695 ent->fail_auth_count = (krb5_kvno) u.av_fail_auth_count; 696 break; 697 698 case AT_PRINC: 699 tmpprinc = conv_princ_2db(context, &u.av_princ); 700 if (tmpprinc == NULL) 701 return ENOMEM; 702 if (nprincs) 703 krb5_free_principal(context, ent->princ); 704 ent->princ = tmpprinc; 705 break; 706 707 case AT_KEYDATA: 708 709 if (nprincs != 0) 710 prev_n_keys = ent->n_key_data; 711 else 712 prev_n_keys = 0; 713 ent->n_key_data = (krb5_int16)u.av_keydata.av_keydata_len; 714 if (nprincs == 0) 715 ent->key_data = NULL; 716 717 ent->key_data = (krb5_key_data *)realloc(ent->key_data, 718 (ent->n_key_data * 719 sizeof (krb5_key_data))); 720 /* XXX Memory leak: Old key data in 721 records eliminated by resizing to 722 smaller size. */ 723 if (ent->key_data == NULL) 724 /* XXX Memory leak: old storage. */ 725 return (ENOMEM); 726 727 /* BEGIN CSTYLED */ 728 for (j = prev_n_keys; j < ent->n_key_data; j++) { 729 for (cnt = 0; cnt < 2; cnt++) { 730 ent->key_data[j].key_data_contents[cnt] = NULL; 731 } 732 } 733 for (j = 0; j < ent->n_key_data; j++) { 734 krb5_key_data *kp = &ent->key_data[j]; 735 kdbe_key_t *kv = &ULOG_ENTRY_KEYVAL(upd, i, j); 736 kp->key_data_ver = (krb5_int16)kv->k_ver; 737 kp->key_data_kvno = (krb5_int16)kv->k_kvno; 738 if (kp->key_data_ver > 2) { 739 return EINVAL; /* XXX ? */ 740 } 741 742 for (cnt = 0; cnt < kp->key_data_ver; cnt++) { 743 void *newptr; 744 kp->key_data_type[cnt] = (krb5_int16)kv->k_enctype.k_enctype_val[cnt]; 745 kp->key_data_length[cnt] = (krb5_int16)kv->k_contents.k_contents_val[cnt].utf8str_t_len; 746 newptr = realloc(kp->key_data_contents[cnt], 747 kp->key_data_length[cnt]); 748 if (newptr == NULL) 749 return ENOMEM; 750 kp->key_data_contents[cnt] = newptr; 751 752 (void) memset(kp->key_data_contents[cnt], 0, 753 kp->key_data_length[cnt]); 754 (void) memcpy(kp->key_data_contents[cnt], 755 kv->k_contents.k_contents_val[cnt].utf8str_t_val, 756 kp->key_data_length[cnt]); 757 } 758 } 759 break; 760 761 case AT_TL_DATA: 762 cnt = u.av_tldata.av_tldata_len; 763 newtl = malloc(cnt * sizeof (krb5_tl_data)); 764 (void) memset(newtl, 0, (cnt * sizeof (krb5_tl_data))); 765 if (newtl == NULL) 766 return (ENOMEM); 767 768 for (j = 0; j < cnt; j++) { 769 newtl[j].tl_data_type = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_type; 770 newtl[j].tl_data_length = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_data.tl_data_len; 771 newtl[j].tl_data_contents = NULL; 772 newtl[j].tl_data_contents = malloc(newtl[j].tl_data_length * sizeof (krb5_octet)); 773 if (newtl[j].tl_data_contents == NULL) 774 /* XXX Memory leak: newtl 775 and previously 776 allocated elements. */ 777 return (ENOMEM); 778 779 (void) memset(newtl[j].tl_data_contents, 0, (newtl[j].tl_data_length * sizeof (krb5_octet))); 780 (void) memcpy(newtl[j].tl_data_contents, u.av_tldata.av_tldata_val[j].tl_data.tl_data_val, newtl[j].tl_data_length); 781 newtl[j].tl_data_next = NULL; 782 if (j > 0) 783 newtl[j - 1].tl_data_next = &newtl[j]; 784 } 785 786 if ((ret = krb5_dbe_update_tl_data(context, ent, newtl))) 787 return (ret); 788 for (j = 0; j < cnt; j++) 789 if (newtl[j].tl_data_contents) { 790 free(newtl[j].tl_data_contents); 791 newtl[j].tl_data_contents = NULL; 792 } 793 if (newtl) { 794 free(newtl); 795 newtl = NULL; 796 } 797 break; 798 /* END CSTYLED */ 799 800 case AT_PW_LAST_CHANGE: 801 if ((ret = krb5_dbe_update_last_pwd_change(context, ent, 802 u.av_pw_last_change))) 803 return (ret); 804 break; 805 806 case AT_MOD_PRINC: 807 tmpprinc = conv_princ_2db(context, &u.av_mod_princ); 808 if (tmpprinc == NULL) 809 return ENOMEM; 810 mod_princ = tmpprinc; 811 break; 812 813 case AT_MOD_TIME: 814 mod_time = u.av_mod_time; 815 break; 816 817 case AT_LEN: 818 ent->len = (krb5_int16) u.av_len; 819 break; 820 821 default: 822 break; 823 } 824 #undef u 825 } 826 827 /* 828 * process mod_princ_data request 829 */ 830 if (mod_time && mod_princ) { 831 ret = krb5_dbe_update_mod_princ_data(context, ent, 832 mod_time, mod_princ); 833 krb5_free_principal(context, mod_princ); 834 mod_princ = NULL; 835 if (ret) 836 return (ret); 837 } 838 839 next: 840 /* 841 * Bump up to next struct 842 */ 843 upd++; 844 ent++; 845 } 846 return (0); 847 } 848 849 850 851 /* 852 * This routine frees up memory associated with the bunched ulog entries. 853 */ 854 void 855 ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates) 856 { 857 858 kdb_incr_update_t *upd; 859 int i, j, k, cnt; 860 861 if (updates == NULL) 862 return; 863 864 upd = updates; 865 866 /* 867 * Loop thru each ulog entry 868 */ 869 for (cnt = 0; cnt < no_of_updates; cnt++) { 870 871 /* 872 * ulog entry - kdb_princ_name 873 */ 874 free(upd->kdb_princ_name.utf8str_t_val); 875 876 /* BEGIN CSTYLED */ 877 878 /* 879 * ulog entry - kdb_kdcs_seen_by 880 */ 881 if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) { 882 for (i = 0; i < upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len; i++) 883 free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val); 884 free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val); 885 } 886 887 /* 888 * ulog entry - kdb_futures 889 */ 890 free(upd->kdb_futures.kdb_futures_val); 891 892 /* 893 * ulog entry - kdb_update 894 */ 895 if (upd->kdb_update.kdbe_t_val) { 896 /* 897 * Loop thru all the attributes and free up stuff 898 */ 899 for (i = 0; i < upd->kdb_update.kdbe_t_len; i++) { 900 901 /* 902 * Free av_key_data 903 */ 904 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_KEYDATA) && ULOG_ENTRY(upd, i).av_keydata.av_keydata_val) { 905 906 for (j = 0; j < ULOG_ENTRY(upd, i).av_keydata.av_keydata_len; j++) { 907 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val); 908 if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val) { 909 for (k = 0; k < ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; k++) { 910 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val); 911 } 912 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val); 913 } 914 } 915 free(ULOG_ENTRY(upd, i).av_keydata.av_keydata_val); 916 } 917 918 919 /* 920 * Free av_tl_data 921 */ 922 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_TL_DATA) && ULOG_ENTRY(upd, i).av_tldata.av_tldata_val) { 923 for (j = 0; j < ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; j++) { 924 free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val); 925 } 926 free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val); 927 } 928 929 /* 930 * Free av_princ 931 */ 932 if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_PRINC) { 933 free(ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val); 934 if (ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val) { 935 for (j = 0; j < ULOG_ENTRY(upd, i).av_princ.k_components.k_components_len; j++) { 936 free(ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val); 937 } 938 free(ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val); 939 } 940 } 941 942 /* 943 * Free av_mod_princ 944 */ 945 if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_PRINC) { 946 free(ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val); 947 if (ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val) { 948 for (j = 0; j < ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_len; j++) { 949 free(ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val); 950 } 951 free(ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val); 952 } 953 } 954 955 /* 956 * Free av_mod_where 957 */ 958 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_WHERE) && ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val) 959 free(ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val); 960 961 /* 962 * Free av_pw_policy 963 */ 964 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_POLICY) && ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val) 965 free(ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val); 966 967 /* 968 * XXX: Free av_pw_hist 969 * 970 * For now, we just free the pointer 971 * to av_pw_hist_val, since we aren't 972 * populating this union member in 973 * the conv api function(s) anyways. 974 */ 975 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_HIST) && ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val) 976 free(ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val); 977 978 } 979 980 /* 981 * Free up the pointer to kdbe_t_val 982 */ 983 free(upd->kdb_update.kdbe_t_val); 984 } 985 986 /* END CSTYLED */ 987 988 /* 989 * Bump up to next struct 990 */ 991 upd++; 992 } 993 994 995 /* 996 * Finally, free up the pointer to the bunched ulog entries 997 */ 998 free(updates); 999 } 1000