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 if (ent->len >= 0) { 613 ULOG_ENTRY_TYPE(upd, ++final).av_type = 614 AT_LEN; 615 ULOG_ENTRY(upd, final).av_len = 616 (int16_t)ent->len; 617 } 618 break; 619 620 default: 621 break; 622 } 623 624 } 625 626 if (attr_types) 627 free(attr_types); 628 629 /* 630 * Update len field in kdb_update 631 */ 632 upd->kdb_update.kdbe_t_len = ++final; 633 634 /* 635 * Bump up to next struct 636 */ 637 upd++; 638 ent++; 639 } 640 return (0); 641 } 642 643 /* 644 * This routine converts one or more update log (ulog) entries into 645 * kerberos db2 records. Required memory should be allocated 646 * for the db2 records (pointed to by krb5_db_entry *ent), prior 647 * to calling this routine. 648 */ 649 krb5_error_code 650 ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries, 651 kdb_incr_update_t *updates, 652 int nentries) { 653 int i, j, k, cnt, mod_time, nattrs, nprincs; 654 krb5_principal mod_princ = NULL; 655 krb5_principal dbprinc; 656 char *dbprincstr = NULL; 657 658 krb5_db_entry *ent; 659 kdb_incr_update_t *upd; 660 661 krb5_tl_data *newtl = NULL; 662 krb5_error_code ret; 663 unsigned int more; 664 unsigned int prev_n_keys = 0; 665 666 if ((updates == NULL) || (entries == NULL)) 667 return (KRB5KRB_ERR_GENERIC); 668 669 ent = entries; 670 upd = updates; 671 672 for (k = 0; k < nentries; k++) { 673 cnt = nprincs = 0; 674 675 /* 676 * If the ulog entry represents a DELETE update, 677 * just skip to the next entry. 678 */ 679 if (upd->kdb_deleted == TRUE) 680 goto next; 681 682 /* 683 * Store the no. of changed attributes in nattrs 684 */ 685 nattrs = upd->kdb_update.kdbe_t_len; 686 687 dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len + 1) 688 * sizeof (char)); 689 if (dbprincstr == NULL) 690 return (ENOMEM); 691 strlcpy(dbprincstr, (char *)upd->kdb_princ_name.utf8str_t_val, 692 (upd->kdb_princ_name.utf8str_t_len + 1)); 693 694 ret = krb5_parse_name(context, dbprincstr, &dbprinc); 695 free(dbprincstr); 696 if (ret) 697 return (ret); 698 699 ret = krb5_db_get_principal(context, dbprinc, ent, &nprincs, 700 &more); 701 krb5_free_principal(context, dbprinc); 702 if (ret) 703 return (ret); 704 705 /* 706 * Set ent->n_tl_data = 0 initially, if this is an ADD update 707 */ 708 if (nprincs == 0) 709 ent->n_tl_data = 0; 710 711 for (i = 0; i < nattrs; i++) { 712 switch (ULOG_ENTRY_TYPE(upd, i).av_type) { 713 case AT_ATTRFLAGS: 714 ent->attributes = (krb5_flags) 715 ULOG_ENTRY(upd, i).av_attrflags; 716 break; 717 718 case AT_MAX_LIFE: 719 ent->max_life = (krb5_deltat) 720 ULOG_ENTRY(upd, i).av_max_life; 721 break; 722 723 case AT_MAX_RENEW_LIFE: 724 ent->max_renewable_life = (krb5_deltat) 725 ULOG_ENTRY(upd, i).av_max_renew_life; 726 break; 727 728 case AT_EXP: 729 ent->expiration = (krb5_timestamp) 730 ULOG_ENTRY(upd, i).av_exp; 731 break; 732 733 case AT_PW_EXP: 734 ent->pw_expiration = (krb5_timestamp) 735 ULOG_ENTRY(upd, i).av_pw_exp; 736 break; 737 738 case AT_LAST_SUCCESS: 739 ent->last_success = (krb5_timestamp) 740 ULOG_ENTRY(upd, i).av_last_success; 741 break; 742 743 case AT_LAST_FAILED: 744 ent->last_failed = (krb5_timestamp) 745 ULOG_ENTRY(upd, i).av_last_failed; 746 break; 747 748 case AT_FAIL_AUTH_COUNT: 749 ent->fail_auth_count = (krb5_kvno) 750 ULOG_ENTRY(upd, i).av_fail_auth_count; 751 break; 752 753 case AT_PRINC: 754 if ((ret = conv_princ_2db(context, 755 &(ent->princ), upd, 756 i, REG_PRINC, nprincs))) 757 return (ret); 758 break; 759 760 case AT_KEYDATA: 761 762 if (nprincs != 0) 763 prev_n_keys = ent->n_key_data; 764 765 ent->n_key_data = (krb5_int16)ULOG_ENTRY(upd, 766 i).av_keydata.av_keydata_len; 767 if (nprincs == 0) 768 ent->key_data = NULL; 769 770 ent->key_data = (krb5_key_data *)realloc( 771 ent->key_data, 772 (ent->n_key_data * 773 sizeof (krb5_key_data))); 774 if (ent->key_data == NULL) 775 return (ENOMEM); 776 777 /* BEGIN CSTYLED */ 778 for (j = 0; j < ent->n_key_data; j++) { 779 ent->key_data[j].key_data_ver = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; 780 ent->key_data[j].key_data_kvno = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_kvno; 781 782 for (cnt = 0; cnt < ent->key_data[j].key_data_ver; cnt++) { 783 ent->key_data[j].key_data_type[cnt] = (krb5_int16)ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val[cnt]; 784 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; 785 if ((nprincs == 0) || (j >= prev_n_keys)) 786 ent->key_data[j].key_data_contents[cnt] = NULL; 787 788 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]); 789 if (ent->key_data[j].key_data_contents[cnt] == NULL) 790 return (ENOMEM); 791 792 (void) memset(ent->key_data[j].key_data_contents[cnt], 0, (ent->key_data[j].key_data_length[cnt] * sizeof (krb5_octet))); 793 (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]); 794 } 795 } 796 break; 797 798 case AT_TL_DATA: 799 cnt = ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; 800 newtl = malloc(cnt * sizeof (krb5_tl_data)); 801 (void) memset(newtl, 0, (cnt * sizeof (krb5_tl_data))); 802 if (newtl == NULL) 803 return (ENOMEM); 804 805 for (j = 0; j < cnt; j++){ 806 newtl[j].tl_data_type = (krb5_int16)ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_type; 807 newtl[j].tl_data_length = (krb5_int16)ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_len; 808 newtl[j].tl_data_contents = NULL; 809 newtl[j].tl_data_contents = malloc(newtl[j].tl_data_length * sizeof (krb5_octet)); 810 if (newtl[j].tl_data_contents == NULL) 811 return (ENOMEM); 812 813 (void) memset(newtl[j].tl_data_contents, 0, (newtl[j].tl_data_length * sizeof (krb5_octet))); 814 (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); 815 newtl[j].tl_data_next = NULL; 816 if (j > 0) 817 newtl[j - 1].tl_data_next = 818 &newtl[j]; 819 } 820 821 if ((ret = krb5_dbe_update_tl_data(context, 822 ent, newtl))) 823 return (ret); 824 for (j = 0; j < cnt; j++) 825 if (newtl[j].tl_data_contents) { 826 free(newtl[j].tl_data_contents); 827 newtl[j].tl_data_contents = NULL; 828 } 829 if (newtl) { 830 free(newtl); 831 newtl = NULL; 832 } 833 break; 834 /* END CSTYLED */ 835 836 case AT_PW_LAST_CHANGE: 837 if ((ret = krb5_dbe_update_last_pwd_change( 838 context, ent, 839 ULOG_ENTRY(upd, i).av_pw_last_change))) 840 return (ret); 841 break; 842 843 case AT_MOD_PRINC: 844 if ((ret = conv_princ_2db(context, 845 &mod_princ, upd, 846 i, MOD_PRINC, 0))) 847 return (ret); 848 break; 849 850 case AT_MOD_TIME: 851 mod_time = ULOG_ENTRY(upd, i).av_mod_time; 852 break; 853 854 case AT_LEN: 855 ent->len = (krb5_int16) 856 ULOG_ENTRY(upd, i).av_len; 857 break; 858 859 default: 860 break; 861 } 862 863 } 864 865 /* 866 * process mod_princ_data request 867 */ 868 if (mod_time && mod_princ) { 869 ret = krb5_dbe_update_mod_princ_data(context, ent, 870 mod_time, mod_princ); 871 krb5_free_principal(context, mod_princ); 872 if (ret) 873 return (ret); 874 } 875 876 next: 877 /* 878 * Bump up to next struct 879 */ 880 upd++; 881 ent++; 882 } 883 return (0); 884 } 885 886 887 888 /* 889 * This routine frees up memory associated with the bunched ulog entries. 890 */ 891 void 892 ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates) { 893 894 kdb_incr_update_t *upd; 895 int i, j, k, cnt; 896 897 if (updates == NULL) 898 return; 899 900 upd = updates; 901 902 /* 903 * Loop thru each ulog entry 904 */ 905 for (cnt = 0; cnt < no_of_updates; cnt++) { 906 907 /* 908 * ulog entry - kdb_princ_name 909 */ 910 if (upd->kdb_princ_name.utf8str_t_val) 911 free(upd->kdb_princ_name.utf8str_t_val); 912 913 /* BEGIN CSTYLED */ 914 915 /* 916 * ulog entry - kdb_kdcs_seen_by 917 */ 918 if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) { 919 for (i = 0; i < upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len; i++) { 920 if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val) 921 free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val); 922 } 923 if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) 924 free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val); 925 } 926 927 /* 928 * ulog entry - kdb_futures 929 */ 930 if (upd->kdb_futures.kdb_futures_val) 931 free(upd->kdb_futures.kdb_futures_val); 932 933 /* 934 * ulog entry - kdb_update 935 */ 936 if(upd->kdb_update.kdbe_t_val) { 937 /* 938 * Loop thru all the attributes and free up stuff 939 */ 940 for (i = 0; i < upd->kdb_update.kdbe_t_len; i++) { 941 942 /* 943 * Free av_key_data 944 */ 945 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_KEYDATA) && ULOG_ENTRY(upd, i).av_keydata.av_keydata_val) { 946 947 for (j = 0; j < ULOG_ENTRY(upd, i).av_keydata.av_keydata_len; j++) { 948 if (ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val) 949 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val); 950 if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val) { 951 for (k = 0; k < ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; k++) { 952 if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val) 953 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val); 954 } 955 free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val); 956 } 957 } 958 free(ULOG_ENTRY(upd, i).av_keydata.av_keydata_val); 959 } 960 961 962 /* 963 * Free av_tl_data 964 */ 965 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_TL_DATA) && ULOG_ENTRY(upd, i).av_tldata.av_tldata_val) { 966 for (j = 0; j < ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; j++) { 967 if (ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val) 968 free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val); 969 } 970 free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val); 971 } 972 973 /* 974 * Free av_princ 975 */ 976 if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_PRINC) { 977 if (ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val) 978 free(ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val); 979 if (ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val) { 980 for (j = 0; j < ULOG_ENTRY(upd, i).av_princ.k_components.k_components_len; j++) { 981 if (ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val) 982 free(ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val); 983 } 984 free(ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val); 985 } 986 } 987 988 /* 989 * Free av_mod_princ 990 */ 991 if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_PRINC) { 992 if (ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val) 993 free(ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val); 994 if (ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val) { 995 for (j = 0; j < ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_len; j++) { 996 if (ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val) 997 free(ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val); 998 } 999 free(ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val); 1000 } 1001 } 1002 1003 /* 1004 * Free av_mod_where 1005 */ 1006 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_WHERE) && ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val) 1007 free(ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val); 1008 1009 /* 1010 * Free av_pw_policy 1011 */ 1012 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_POLICY) && ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val) 1013 free(ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val); 1014 1015 /* 1016 * XXX: Free av_pw_hist 1017 * 1018 * For now, we just free the pointer 1019 * to av_pw_hist_val, since we arent 1020 * populating this union member in 1021 * the conv api function(s) anyways. 1022 */ 1023 if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_HIST) && ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val) 1024 free(ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val); 1025 1026 } 1027 1028 /* 1029 * Free up the pointer to kdbe_t_val 1030 */ 1031 if (upd->kdb_update.kdbe_t_val) 1032 free(upd->kdb_update.kdbe_t_val); 1033 } 1034 1035 /* END CSTYLED */ 1036 1037 /* 1038 * Bump up to next struct 1039 */ 1040 upd++; 1041 } 1042 1043 1044 /* 1045 * Finally, free up the pointer to the bunched ulog entries 1046 */ 1047 if (updates) 1048 free(updates); 1049 } 1050