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