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