1 /* 2 * lib/kdb/kdb_ldap/ldap_principal2.c 3 * 4 * Copyright (c) 2004-2005, Novell, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * * The copyright holder's name is not used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 32 * Use is subject to license terms. 33 */ 34 35 #include <time.h> 36 #include "ldap_main.h" 37 #include "kdb_ldap.h" 38 #include "ldap_principal.h" 39 #include "princ_xdr.h" 40 #include "ldap_tkt_policy.h" 41 #include "ldap_pwd_policy.h" 42 #include "ldap_err.h" 43 #include <kadm5/admin.h> 44 #include <libintl.h> 45 46 extern char* principal_attributes[]; 47 extern char* max_pwd_life_attr[]; 48 49 static char * 50 getstringtime(krb5_timestamp); 51 52 krb5_error_code 53 berval2tl_data(struct berval *in, krb5_tl_data **out) 54 { 55 *out = (krb5_tl_data *) malloc (sizeof (krb5_tl_data)); 56 if (*out == NULL) 57 return ENOMEM; 58 59 (*out)->tl_data_length = in->bv_len - 2; 60 (*out)->tl_data_contents = (krb5_octet *) malloc 61 ((*out)->tl_data_length * sizeof (krb5_octet)); 62 if ((*out)->tl_data_contents == NULL) { 63 free (*out); 64 return ENOMEM; 65 } 66 67 /* Solaris Kerberos: need cast */ 68 UNSTORE16_INT ((unsigned char *)in->bv_val, (*out)->tl_data_type); 69 memcpy ((*out)->tl_data_contents, in->bv_val + 2, (*out)->tl_data_length); 70 71 return 0; 72 } 73 74 /* 75 * look up a principal in the directory. 76 */ 77 78 krb5_error_code 79 krb5_ldap_get_principal(context, searchfor, entries, nentries, more) 80 krb5_context context; 81 krb5_const_principal searchfor; 82 krb5_db_entry *entries; /* filled in */ 83 int *nentries; /* how much room/how many found */ 84 krb5_boolean *more; /* are there more? */ 85 { 86 char *user=NULL, *filter=NULL, **subtree=NULL; 87 unsigned int tree=0, ntrees=1, princlen=0; 88 krb5_error_code tempst=0, st=0; 89 char **values=NULL; 90 LDAP *ld=NULL; 91 LDAPMessage *result=NULL, *ent=NULL; 92 krb5_ldap_context *ldap_context=NULL; 93 kdb5_dal_handle *dal_handle=NULL; 94 krb5_ldap_server_handle *ldap_server_handle=NULL; 95 96 /* Clear the global error string */ 97 krb5_clear_error_message(context); 98 99 /* set initial values */ 100 *nentries = 0; 101 *more = 0; 102 memset(entries, 0, sizeof(*entries)); 103 104 if (searchfor == NULL) 105 return EINVAL; 106 107 dal_handle = (kdb5_dal_handle *) context->db_context; 108 ldap_context = (krb5_ldap_context *) dal_handle->db_context; 109 110 CHECK_LDAP_HANDLE(ldap_context); 111 112 if (is_principal_in_realm(ldap_context, searchfor) != 0) { 113 *more = 0; 114 krb5_set_error_message (context, st, gettext("Principal does not belong to realm")); 115 goto cleanup; 116 } 117 118 if ((st=krb5_unparse_name(context, searchfor, &user)) != 0) 119 goto cleanup; 120 121 if ((st=krb5_ldap_unparse_principal_name(user)) != 0) 122 goto cleanup; 123 124 princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ 125 if ((filter = malloc(princlen)) == NULL) { 126 st = ENOMEM; 127 goto cleanup; 128 } 129 snprintf(filter, princlen, FILTER"%s))", user); 130 131 if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0) 132 goto cleanup; 133 134 GET_HANDLE(); 135 for (tree=0; tree < ntrees && *nentries == 0; ++tree) { 136 137 LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes); 138 for (ent=ldap_first_entry(ld, result); ent != NULL && *nentries == 0; ent=ldap_next_entry(ld, ent)) { 139 140 /* get the associated directory user information */ 141 if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { 142 int i; 143 144 /* a wild-card in a principal name can return a list of kerberos principals. 145 * Make sure that the correct principal is returned. 146 * NOTE: a principalname k* in ldap server will return all the principals starting with a k 147 */ 148 for (i=0; values[i] != NULL; ++i) { 149 if (strcasecmp(values[i], user) == 0) { 150 *nentries = 1; 151 break; 152 } 153 } 154 ldap_value_free(values); 155 156 if (*nentries == 0) /* no matching principal found */ 157 continue; 158 } 159 160 if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, searchfor, 161 entries)) != 0) 162 goto cleanup; 163 } 164 ldap_msgfree(result); 165 result = NULL; 166 } /* for (tree=0 ... */ 167 168 /* once done, put back the ldap handle */ 169 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 170 ldap_server_handle = NULL; 171 172 cleanup: 173 ldap_msgfree(result); 174 175 if (*nentries == 0 || st != 0) 176 krb5_dbe_free_contents(context, entries); 177 178 if (filter) 179 free (filter); 180 181 if (subtree) { 182 for (; ntrees; --ntrees) 183 if (subtree[ntrees-1]) 184 free (subtree[ntrees-1]); 185 free (subtree); 186 } 187 188 if (ldap_server_handle) 189 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 190 191 if (user) 192 free(user); 193 194 return st; 195 } 196 197 typedef enum{ ADD_PRINCIPAL, MODIFY_PRINCIPAL } OPERATION; 198 /* 199 * ptype is creating confusions. Additionally the logic 200 * surronding ptype is redundunt and can be achevied 201 * with the help of dn and containerdn members. 202 * so dropping the ptype member 203 */ 204 205 typedef struct _xargs_t { 206 char *dn; 207 char *linkdn; 208 krb5_boolean dn_from_kbd; 209 char *containerdn; 210 char *tktpolicydn; 211 }xargs_t; 212 213 static void 214 free_xargs(xargs) 215 xargs_t xargs; 216 { 217 if (xargs.dn) 218 free (xargs.dn); 219 if (xargs.linkdn) 220 free(xargs.linkdn); 221 if (xargs.containerdn) 222 free (xargs.containerdn); 223 if (xargs.tktpolicydn) 224 free (xargs.tktpolicydn); 225 } 226 227 static krb5_error_code 228 process_db_args(context, db_args, xargs, optype) 229 krb5_context context; 230 char **db_args; 231 xargs_t *xargs; 232 OPERATION optype; 233 { 234 int i=0; 235 krb5_error_code st=0; 236 char errbuf[1024]; 237 char *arg=NULL, *arg_val=NULL; 238 char **dptr=NULL; 239 unsigned int arg_val_len=0; 240 241 if (db_args) { 242 for (i=0; db_args[i]; ++i) { 243 arg = strtok_r(db_args[i], "=", &arg_val); 244 if (strcmp(arg, TKTPOLICY_ARG) == 0) { 245 dptr = &xargs->tktpolicydn; 246 } else { 247 if (strcmp(arg, USERDN_ARG) == 0) { 248 if (optype == MODIFY_PRINCIPAL || 249 xargs->dn != NULL || xargs->containerdn != NULL || 250 xargs->linkdn != NULL) { 251 st = EINVAL; 252 snprintf(errbuf, sizeof(errbuf), 253 gettext("%s option not supported"), arg); 254 krb5_set_error_message(context, st, "%s", errbuf); 255 goto cleanup; 256 } 257 dptr = &xargs->dn; 258 } else if (strcmp(arg, CONTAINERDN_ARG) == 0) { 259 if (optype == MODIFY_PRINCIPAL || 260 xargs->dn != NULL || xargs->containerdn != NULL) { 261 st = EINVAL; 262 snprintf(errbuf, sizeof(errbuf), 263 gettext("%s option not supported"), arg); 264 krb5_set_error_message(context, st, "%s", errbuf); 265 goto cleanup; 266 } 267 dptr = &xargs->containerdn; 268 } else if (strcmp(arg, LINKDN_ARG) == 0) { 269 if (xargs->dn != NULL || xargs->linkdn != NULL) { 270 st = EINVAL; 271 snprintf(errbuf, sizeof(errbuf), 272 gettext("%s option not supported"), arg); 273 krb5_set_error_message(context, st, "%s", errbuf); 274 goto cleanup; 275 } 276 dptr = &xargs->linkdn; 277 } else { 278 st = EINVAL; 279 snprintf(errbuf, sizeof(errbuf), gettext("unknown option: %s"), arg); 280 krb5_set_error_message(context, st, "%s", errbuf); 281 goto cleanup; 282 } 283 284 xargs->dn_from_kbd = TRUE; 285 if (arg_val == NULL || strlen(arg_val) == 0) { 286 st = EINVAL; 287 snprintf(errbuf, sizeof(errbuf), 288 gettext("%s option value missing"), arg); 289 krb5_set_error_message(context, st, "%s", errbuf); 290 goto cleanup; 291 } 292 } 293 294 if (arg_val == NULL) { 295 st = EINVAL; 296 snprintf(errbuf, sizeof(errbuf), 297 gettext("%s option value missing"), arg); 298 krb5_set_error_message(context, st, "%s", errbuf); 299 goto cleanup; 300 } 301 arg_val_len = strlen(arg_val) + 1; 302 303 if (strcmp(arg, TKTPOLICY_ARG) == 0) { 304 if ((st = krb5_ldap_name_to_policydn (context, 305 arg_val, 306 dptr)) != 0) 307 goto cleanup; 308 } else { 309 *dptr = calloc (1, arg_val_len); 310 if (*dptr == NULL) { 311 st = ENOMEM; 312 goto cleanup; 313 } 314 memcpy(*dptr, arg_val, arg_val_len); 315 } 316 } 317 } 318 319 cleanup: 320 return st; 321 } 322 323 krb5int_access accessor; 324 extern int kldap_ensure_initialized (void); 325 326 static krb5_error_code 327 asn1_encode_sequence_of_keys (krb5_key_data *key_data, krb5_int16 n_key_data, 328 krb5_int32 mkvno, krb5_data **code) 329 { 330 krb5_error_code err; 331 332 /* 333 * This should be pushed back into other library initialization 334 * code. 335 */ 336 err = kldap_ensure_initialized (); 337 if (err) 338 return err; 339 340 return accessor.asn1_ldap_encode_sequence_of_keys(key_data, n_key_data, 341 mkvno, code); 342 } 343 344 static krb5_error_code 345 asn1_decode_sequence_of_keys (krb5_data *in, krb5_key_data **out, 346 krb5_int16 *n_key_data, int *mkvno) 347 { 348 krb5_error_code err; 349 350 /* 351 * This should be pushed back into other library initialization 352 * code. 353 */ 354 err = kldap_ensure_initialized (); 355 if (err) 356 return err; 357 358 return accessor.asn1_ldap_decode_sequence_of_keys(in, out, n_key_data, 359 mkvno); 360 } 361 362 363 /* Decoding ASN.1 encoded key */ 364 static struct berval ** 365 krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data) { 366 struct berval **ret = NULL; 367 int currkvno; 368 int num_versions = 1; 369 int i, j, last; 370 krb5_error_code err = 0; 371 372 if (n_key_data <= 0) 373 return NULL; 374 375 /* Find the number of key versions */ 376 for (i = 0; i < n_key_data - 1; i++) 377 if (key_data[i].key_data_kvno != key_data[i + 1].key_data_kvno) 378 num_versions++; 379 380 ret = (struct berval **) calloc (num_versions + 1, sizeof (struct berval *)); 381 if (ret == NULL) { 382 err = ENOMEM; 383 goto cleanup; 384 } 385 for (i = 0, last = 0, j = 0, currkvno = key_data[0].key_data_kvno; i < n_key_data; i++) { 386 krb5_data *code; 387 if (i == n_key_data - 1 || key_data[i + 1].key_data_kvno != currkvno) { 388 code = NULL; 389 asn1_encode_sequence_of_keys (key_data+last, 390 (krb5_int16) i - last + 1, 391 0, /* For now, mkvno == 0*/ 392 &code); 393 if (code == NULL) { 394 err = ENOMEM; 395 goto cleanup; 396 } 397 ret[j] = malloc (sizeof (struct berval)); 398 if (ret[j] == NULL) { 399 err = ENOMEM; 400 goto cleanup; 401 } 402 /*CHECK_NULL(ret[j]); */ 403 ret[j]->bv_len = code->length; 404 ret[j]->bv_val = code->data; 405 j++; 406 last = i + 1; 407 408 currkvno = key_data[i].key_data_kvno; 409 /* Solaris Kerberos: fix memleak */ 410 free(code); 411 } 412 } 413 ret[num_versions] = NULL; 414 415 cleanup: 416 417 if (err != 0) { 418 if (ret != NULL) { 419 for (i = 0; i <= num_versions; i++) 420 if (ret[i] != NULL) 421 free (ret[i]); 422 free (ret); 423 ret = NULL; 424 } 425 } 426 427 return ret; 428 } 429 430 static krb5_error_code tl_data2berval (krb5_tl_data *in, struct berval **out) { 431 *out = (struct berval *) malloc (sizeof (struct berval)); 432 if (*out == NULL) 433 return ENOMEM; 434 435 (*out)->bv_len = in->tl_data_length + 2; 436 (*out)->bv_val = (char *) malloc ((*out)->bv_len); 437 if ((*out)->bv_val == NULL) { 438 free (*out); 439 return ENOMEM; 440 } 441 442 /* Solaris Kerberos: need cast */ 443 STORE16_INT((unsigned char *)(*out)->bv_val, in->tl_data_type); 444 memcpy ((*out)->bv_val + 2, in->tl_data_contents, in->tl_data_length); 445 446 return 0; 447 } 448 449 krb5_error_code 450 krb5_ldap_put_principal(context, entries, nentries, db_args) 451 krb5_context context; 452 krb5_db_entry *entries; 453 register int *nentries; /* number of entry structs to update */ 454 char **db_args; 455 { 456 int i=0, l=0, kerberos_principal_object_type=0; 457 krb5_error_code st=0, tempst=0; 458 LDAP *ld=NULL; 459 LDAPMessage *result=NULL, *ent=NULL; 460 char *user=NULL, *subtree=NULL, *principal_dn=NULL; 461 char **values=NULL, *strval[10]={NULL}, errbuf[1024]; 462 struct berval **bersecretkey=NULL; 463 LDAPMod **mods=NULL; 464 krb5_boolean create_standalone_prinicipal=FALSE; 465 krb5_boolean krb_identity_exists=FALSE, establish_links=FALSE; 466 char *standalone_principal_dn=NULL; 467 krb5_tl_data *tl_data=NULL; 468 kdb5_dal_handle *dal_handle=NULL; 469 krb5_ldap_context *ldap_context=NULL; 470 krb5_ldap_server_handle *ldap_server_handle=NULL; 471 osa_princ_ent_rec princ_ent; 472 xargs_t xargs = {0}; 473 char *polname = NULL; 474 OPERATION optype; 475 krb5_boolean found_entry = FALSE; 476 struct berval **ber_tl_data = NULL; 477 478 /* Clear the global error string */ 479 krb5_clear_error_message(context); 480 481 SETUP_CONTEXT(); 482 if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL) 483 return EINVAL; 484 485 /* get ldap handle */ 486 GET_HANDLE(); 487 488 for (i=0; i < *nentries; ++i, ++entries) { 489 if (is_principal_in_realm(ldap_context, entries->princ) != 0) { 490 st = EINVAL; 491 krb5_set_error_message(context, st, gettext("Principal does not belong to the default realm")); 492 goto cleanup; 493 } 494 495 /* get the principal information to act on */ 496 if (entries->princ) { 497 if (((st=krb5_unparse_name(context, entries->princ, &user)) != 0) || 498 ((st=krb5_ldap_unparse_principal_name(user)) != 0)) 499 goto cleanup; 500 } 501 502 /* Identity the type of operation, it can be 503 * add principal or modify principal. 504 * hack if the entries->mask has KRB_PRINCIPAL flag set 505 * then it is a add operation 506 */ 507 if (entries->mask & KADM5_PRINCIPAL) 508 optype = ADD_PRINCIPAL; 509 else 510 optype = MODIFY_PRINCIPAL; 511 512 if (((st=krb5_get_princ_type(context, entries, &kerberos_principal_object_type)) != 0) || 513 ((st=krb5_get_userdn(context, entries, &principal_dn)) != 0)) 514 goto cleanup; 515 516 if ((st=process_db_args(context, db_args, &xargs, optype)) != 0) 517 goto cleanup; 518 519 if (entries->mask & KADM5_LOAD) { 520 int tree = 0, princlen = 0, numlentries = 0; 521 unsigned int ntrees = 0; 522 char **subtreelist = NULL, *filter = NULL; 523 524 /* A load operation is special, will do a mix-in (add krbprinc 525 * attrs to a non-krb object entry) if an object exists with a 526 * matching krbprincipalname attribute so try to find existing 527 * object and set principal_dn. This assumes that the 528 * krbprincipalname attribute is unique (only one object entry has 529 * a particular krbprincipalname attribute). 530 */ 531 if (user == NULL) { 532 /* must have principal name for search */ 533 st = EINVAL; 534 krb5_set_error_message(context, st, gettext("operation can not continue, principal name not found")); 535 goto cleanup; 536 } 537 princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ 538 if ((filter = malloc(princlen)) == NULL) { 539 st = ENOMEM; 540 goto cleanup; 541 } 542 snprintf(filter, princlen, FILTER"%s))", user); 543 544 /* get the current subtree list */ 545 if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) 546 goto cleanup; 547 548 found_entry = FALSE; 549 /* search for entry with matching krbprincipalname attribute */ 550 for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) { 551 result = NULL; 552 if (principal_dn == NULL) { 553 LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS); 554 } else { 555 /* just look for entry with principal_dn */ 556 LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS); 557 } 558 if (st == LDAP_SUCCESS) { 559 numlentries = ldap_count_entries(ld, result); 560 if (numlentries > 1) { 561 ldap_msgfree(result); 562 free(filter); 563 st = EINVAL; 564 krb5_set_error_message(context, st, 565 gettext("operation can not continue, more than one entry with principal name \"%s\" found"), 566 user); 567 goto cleanup; 568 } else if (numlentries == 1) { 569 found_entry = TRUE; 570 if (principal_dn == NULL) { 571 ent = ldap_first_entry(ld, result); 572 if (ent != NULL) { 573 /* setting principal_dn will cause that entry to be modified further down */ 574 if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { 575 ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); 576 st = set_ldap_error (context, st, 0); 577 ldap_msgfree(result); 578 free(filter); 579 goto cleanup; 580 } 581 } 582 } 583 } 584 if (result) 585 ldap_msgfree(result); 586 } else if (st != LDAP_NO_SUCH_OBJECT) { 587 /* could not perform search, return with failure */ 588 st = set_ldap_error (context, st, 0); 589 free(filter); 590 goto cleanup; 591 } 592 /* 593 * If it isn't found then assume a standalone princ entry is to 594 * be created. 595 */ 596 } /* end for (tree = 0; principal_dn == ... */ 597 598 free(filter); 599 600 if (found_entry == FALSE && principal_dn != NULL) { 601 /* 602 * if principal_dn is null then there is code further down to 603 * deal with setting standalone_principal_dn. Also note that 604 * this will set create_standalone_prinicipal true for 605 * non-mix-in entries which is okay if loading from a dump. 606 */ 607 create_standalone_prinicipal = TRUE; 608 standalone_principal_dn = strdup(principal_dn); 609 CHECK_NULL(standalone_principal_dn); 610 } 611 } /* end if (entries->mask & KADM5_LOAD */ 612 613 /* time to generate the DN information with the help of 614 * containerdn, principalcontainerreference or 615 * realmcontainerdn information 616 */ 617 if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */ 618 /* get the subtree information */ 619 if (entries->princ->length == 2 && entries->princ->data[0].length == strlen("krbtgt") && 620 strncmp(entries->princ->data[0].data, "krbtgt", entries->princ->data[0].length) == 0) { 621 /* if the principal is a inter-realm principal, always created in the realm container */ 622 subtree = strdup(ldap_context->lrparams->realmdn); 623 } else if (xargs.containerdn) { 624 if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) { 625 if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) { 626 int ost = st; 627 st = EINVAL; 628 snprintf(errbuf, sizeof(errbuf), gettext("'%s' not found: "), xargs.containerdn); 629 prepend_err_str(context, errbuf, st, ost); 630 } 631 goto cleanup; 632 } 633 subtree = strdup(xargs.containerdn); 634 } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) { 635 /* 636 * Here the subtree should be changed with 637 * principalcontainerreference attribute value 638 */ 639 subtree = strdup(ldap_context->lrparams->containerref); 640 } else { 641 subtree = strdup(ldap_context->lrparams->realmdn); 642 } 643 CHECK_NULL(subtree); 644 645 standalone_principal_dn = malloc(strlen("krbprincipalname=") + strlen(user) + strlen(",") + 646 strlen(subtree) + 1); 647 CHECK_NULL(standalone_principal_dn); 648 /*LINTED*/ 649 sprintf(standalone_principal_dn, "krbprincipalname=%s,%s", user, subtree); 650 /* 651 * free subtree when you are done using the subtree 652 * set the boolean create_standalone_prinicipal to TRUE 653 */ 654 create_standalone_prinicipal = TRUE; 655 free(subtree); 656 subtree = NULL; 657 } 658 659 /* 660 * If the DN information is presented by the user, time to 661 * validate the input to ensure that the DN falls under 662 * any of the subtrees 663 */ 664 if (xargs.dn_from_kbd == TRUE) { 665 /* make sure the DN falls in the subtree */ 666 int tre=0, dnlen=0, subtreelen=0; 667 unsigned int ntrees = 0; 668 char **subtreelist=NULL; 669 char *dn=NULL; 670 krb5_boolean outofsubtree=TRUE; 671 672 if (xargs.dn != NULL) { 673 dn = xargs.dn; 674 } else if (xargs.linkdn != NULL) { 675 dn = xargs.linkdn; 676 } else if (standalone_principal_dn != NULL) { 677 /* 678 * Even though the standalone_principal_dn is constructed 679 * within this function, there is the containerdn input 680 * from the user that can become part of the it. 681 */ 682 dn = standalone_principal_dn; 683 } 684 685 /* get the current subtree list */ 686 if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) 687 goto cleanup; 688 689 for (tre=0; tre<ntrees; ++tre) { 690 if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) { 691 outofsubtree = FALSE; 692 break; 693 } else { 694 dnlen = strlen (dn); 695 subtreelen = strlen(subtreelist[tre]); 696 if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) { 697 outofsubtree = FALSE; 698 break; 699 } 700 } 701 } 702 703 for (tre=0; tre < ntrees; ++tre) { 704 free(subtreelist[tre]); 705 } 706 707 if (outofsubtree == TRUE) { 708 st = EINVAL; 709 krb5_set_error_message(context, st, gettext("DN is out of the realm subtree")); 710 goto cleanup; 711 } 712 713 /* 714 * dn value will be set either by dn, linkdn or the standalone_principal_dn 715 * In the first 2 cases, the dn should be existing and in the last case we 716 * are supposed to create the ldap object. so the below should not be 717 * executed for the last case. 718 */ 719 720 if (standalone_principal_dn == NULL) { 721 /* 722 * If the ldap object is missing, this results in an error. 723 */ 724 725 /* 726 * Search for krbprincipalname attribute here. 727 * This is to find if a kerberos identity is already present 728 * on the ldap object, in which case adding a kerberos identity 729 * on the ldap object should result in an error. 730 */ 731 char *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL}; 732 733 LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS); 734 if (st == LDAP_SUCCESS) { 735 ent = ldap_first_entry(ld, result); 736 if (ent != NULL) { 737 if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) { 738 ldap_value_free(values); 739 } 740 741 if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { 742 krb_identity_exists = TRUE; 743 ldap_value_free(values); 744 } 745 } 746 ldap_msgfree(result); 747 } else { 748 st = set_ldap_error(context, st, OP_SEARCH); 749 goto cleanup; 750 } 751 } 752 } 753 754 /* 755 * If xargs.dn is set then the request is to add a 756 * kerberos principal on a ldap object, but if 757 * there is one already on the ldap object this 758 * should result in an error. 759 */ 760 761 if (xargs.dn != NULL && krb_identity_exists == TRUE) { 762 st = EINVAL; 763 snprintf(errbuf, sizeof(errbuf), gettext("ldap object is already kerberized")); 764 krb5_set_error_message(context, st, "%s", errbuf); 765 goto cleanup; 766 } 767 768 if (xargs.linkdn != NULL) { 769 /* 770 * link information can be changed using modprinc. 771 * However, link information can be changed only on the 772 * standalone kerberos principal objects. A standalone 773 * kerberos principal object is of type krbprincipal 774 * structural objectclass. 775 * 776 * NOTE: kerberos principals on an ldap object can't be 777 * linked to other ldap objects. 778 */ 779 if (optype == MODIFY_PRINCIPAL && 780 kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) { 781 st = EINVAL; 782 snprintf(errbuf, sizeof(errbuf), 783 gettext("link information can not be set/updated as the kerberos principal belongs to an ldap object")); 784 krb5_set_error_message(context, st, "%s", errbuf); 785 goto cleanup; 786 } 787 /* 788 * Check the link information. If there is already a link 789 * existing then this operation is not allowed. 790 */ 791 { 792 char **linkdns=NULL; 793 int j=0; 794 795 if ((st=krb5_get_linkdn(context, entries, &linkdns)) != 0) { 796 snprintf(errbuf, sizeof(errbuf), 797 gettext("Failed getting object references")); 798 krb5_set_error_message(context, st, "%s", errbuf); 799 goto cleanup; 800 } 801 if (linkdns != NULL) { 802 st = EINVAL; 803 snprintf(errbuf, sizeof(errbuf), 804 gettext("kerberos principal is already linked " 805 "to a ldap object")); 806 krb5_set_error_message(context, st, "%s", errbuf); 807 for (j=0; linkdns[j] != NULL; ++j) 808 free (linkdns[j]); 809 free (linkdns); 810 goto cleanup; 811 } 812 } 813 814 establish_links = TRUE; 815 } 816 817 if ((entries->last_success)!=0) { 818 memset(strval, 0, sizeof(strval)); 819 if ((strval[0]=getstringtime(entries->last_success)) == NULL) 820 goto cleanup; 821 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) { 822 free (strval[0]); 823 goto cleanup; 824 } 825 free (strval[0]); 826 } 827 828 if (entries->last_failed!=0) { 829 memset(strval, 0, sizeof(strval)); 830 if ((strval[0]=getstringtime(entries->last_failed)) == NULL) 831 goto cleanup; 832 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) { 833 free (strval[0]); 834 goto cleanup; 835 } 836 free(strval[0]); 837 } 838 839 if (entries->fail_auth_count!=0) { 840 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, entries->fail_auth_count)) !=0) 841 goto cleanup; 842 } 843 844 if (entries->mask & KADM5_MAX_LIFE) { 845 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entries->max_life)) != 0) 846 goto cleanup; 847 } 848 849 if (entries->mask & KADM5_MAX_RLIFE) { 850 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE, 851 entries->max_renewable_life)) != 0) 852 goto cleanup; 853 } 854 855 if (entries->mask & KADM5_ATTRIBUTES) { 856 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE, 857 entries->attributes)) != 0) 858 goto cleanup; 859 } 860 861 if (entries->mask & KADM5_PRINCIPAL) { 862 memset(strval, 0, sizeof(strval)); 863 strval[0] = user; 864 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0) 865 goto cleanup; 866 } 867 868 /* 869 * Solaris Kerberos: this logic was not working properly when 870 * default_principal_expiration set. 871 */ 872 if (entries->mask & KADM5_PRINC_EXPIRE_TIME || entries->expiration != 0) { 873 memset(strval, 0, sizeof(strval)); 874 if ((strval[0]=getstringtime(entries->expiration)) == NULL) 875 goto cleanup; 876 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) { 877 free (strval[0]); 878 goto cleanup; 879 } 880 free (strval[0]); 881 } 882 883 /* 884 * Solaris Kerberos: in case KADM5_PW_EXPIRATION isn't set, check 885 * pw_expiration 886 */ 887 if (entries->mask & KADM5_PW_EXPIRATION || entries->pw_expiration != 0) { 888 memset(strval, 0, sizeof(strval)); 889 if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL) 890 goto cleanup; 891 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration", 892 LDAP_MOD_REPLACE, 893 strval)) != 0) { 894 free (strval[0]); 895 goto cleanup; 896 } 897 free (strval[0]); 898 } 899 900 if (entries->mask & KADM5_POLICY) { 901 memset(&princ_ent, 0, sizeof(princ_ent)); 902 for (tl_data=entries->tl_data; tl_data; tl_data=tl_data->tl_data_next) { 903 if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) { 904 /* FIX ME: I guess the princ_ent should be freed after this call */ 905 if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) { 906 goto cleanup; 907 } 908 } 909 } 910 911 if (princ_ent.aux_attributes & KADM5_POLICY) { 912 memset(strval, 0, sizeof(strval)); 913 if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0) 914 goto cleanup; 915 strval[0] = polname; 916 /* Solaris Kerberos: fix memleak */ 917 free(princ_ent.policy); 918 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) 919 goto cleanup; 920 } else { 921 st = EINVAL; 922 krb5_set_error_message(context, st, gettext("Password policy value null")); 923 goto cleanup; 924 } 925 } else if (entries->mask & KADM5_LOAD && found_entry == TRUE) { 926 /* 927 * a load is special in that existing entries must have attrs that 928 * removed. 929 */ 930 931 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0) 932 goto cleanup; 933 } 934 935 if (entries->mask & KADM5_POLICY_CLR) { 936 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) 937 goto cleanup; 938 } 939 940 if (entries->mask & KADM5_KEY_DATA || entries->mask & KADM5_KVNO) { 941 bersecretkey = krb5_encode_krbsecretkey (entries->key_data, 942 entries->n_key_data); 943 944 if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", 945 LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0) 946 goto cleanup; 947 948 if (!(entries->mask & KADM5_PRINCIPAL)) { 949 memset(strval, 0, sizeof(strval)); 950 if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL) 951 goto cleanup; 952 if ((st=krb5_add_str_mem_ldap_mod(&mods, 953 "krbpasswordexpiration", 954 LDAP_MOD_REPLACE, strval)) != 0) { 955 free (strval[0]); 956 goto cleanup; 957 } 958 free (strval[0]); 959 } 960 961 /* Update last password change whenever a new key is set */ 962 { 963 krb5_timestamp last_pw_changed; 964 if ((st=krb5_dbe_lookup_last_pwd_change(context, entries, 965 &last_pw_changed)) != 0) 966 goto cleanup; 967 968 memset(strval, 0, sizeof(strval)); 969 if ((strval[0] = getstringtime(last_pw_changed)) == NULL) 970 goto cleanup; 971 972 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange", 973 LDAP_MOD_REPLACE, strval)) != 0) { 974 free (strval[0]); 975 goto cleanup; 976 } 977 free (strval[0]); 978 } 979 980 } /* Modify Key data ends here */ 981 982 /* Set tl_data */ 983 if (entries->tl_data != NULL) { 984 int count = 0; 985 /* struct berval **ber_tl_data = NULL; */ 986 krb5_tl_data *ptr; 987 for (ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { 988 if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE 989 #ifdef SECURID 990 || ptr->tl_data_type == KRB5_TL_DB_ARGS 991 #endif 992 || ptr->tl_data_type == KDB_TL_USER_INFO) 993 continue; 994 995 /* Solaris Kerberos: fix key history issue */ 996 if (ptr->tl_data_type == KRB5_TL_KADM_DATA && ! entries->mask & KADM5_KEY_HIST) 997 continue; 998 999 count++; 1000 } 1001 if (count != 0) { 1002 int j; 1003 ber_tl_data = (struct berval **) calloc (count + 1, 1004 sizeof (struct berval*)); 1005 if (ber_tl_data == NULL) { 1006 st = ENOMEM; 1007 goto cleanup; 1008 } 1009 for (j = 0, ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { 1010 /* Ignore tl_data that are stored in separate directory 1011 * attributes */ 1012 if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE 1013 #ifdef SECURID 1014 || ptr->tl_data_type == KRB5_TL_DB_ARGS 1015 #endif 1016 || ptr->tl_data_type == KDB_TL_USER_INFO) 1017 continue; 1018 1019 /* 1020 * Solaris Kerberos: key history needs to be stored (it's in 1021 * the KRB5_TL_KADM_DATA). 1022 */ 1023 if (ptr->tl_data_type == KRB5_TL_KADM_DATA && ! entries->mask & KADM5_KEY_HIST) 1024 continue; 1025 1026 if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0) 1027 break; 1028 j++; 1029 } 1030 if (st != 0) { 1031 /* Solaris Kerberos: don't free here, do it at cleanup */ 1032 goto cleanup; 1033 } 1034 ber_tl_data[count] = NULL; 1035 if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData", 1036 LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, 1037 ber_tl_data)) != 0) 1038 goto cleanup; 1039 } 1040 } 1041 1042 /* Directory specific attribute */ 1043 if (xargs.tktpolicydn != NULL) { 1044 int tmask=0; 1045 1046 if (strlen(xargs.tktpolicydn) != 0) { 1047 st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask); 1048 CHECK_CLASS_VALIDITY(st, tmask, "ticket policy object value: "); 1049 1050 strval[0] = xargs.tktpolicydn; 1051 strval[1] = NULL; 1052 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) 1053 goto cleanup; 1054 1055 } else { 1056 /* if xargs.tktpolicydn is a empty string, then delete 1057 * already existing krbticketpolicyreference attr */ 1058 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) 1059 goto cleanup; 1060 } 1061 1062 } 1063 1064 if (establish_links == TRUE) { 1065 memset(strval, 0, sizeof(strval)); 1066 strval[0] = xargs.linkdn; 1067 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0) 1068 goto cleanup; 1069 } 1070 1071 /* 1072 * in case mods is NULL then return 1073 * not sure but can happen in a modprinc 1074 * so no need to return an error 1075 * addprinc will at least have the principal name 1076 * and the keys passed in 1077 */ 1078 if (mods == NULL) 1079 goto cleanup; 1080 1081 if (create_standalone_prinicipal == TRUE) { 1082 memset(strval, 0, sizeof(strval)); 1083 strval[0] = "krbprincipal"; 1084 strval[1] = "krbprincipalaux"; 1085 strval[2] = "krbTicketPolicyAux"; 1086 1087 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 1088 goto cleanup; 1089 1090 st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); 1091 if (st == LDAP_ALREADY_EXISTS && entries->mask & KADM5_LOAD) { 1092 /* a load operation must replace an existing entry */ 1093 st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL); 1094 if (st != LDAP_SUCCESS) { 1095 snprintf(errbuf, sizeof (errbuf), gettext("Principal delete failed (trying to replace entry): %s"), 1096 ldap_err2string(st)); 1097 st = translate_ldap_error (st, OP_ADD); 1098 krb5_set_error_message(context, st, "%s", errbuf); 1099 goto cleanup; 1100 } else { 1101 st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); 1102 } 1103 } 1104 if (st != LDAP_SUCCESS) { 1105 snprintf(errbuf, sizeof (errbuf), gettext("Principal add failed: %s"), ldap_err2string(st)); 1106 st = translate_ldap_error (st, OP_ADD); 1107 krb5_set_error_message(context, st, "%s", errbuf); 1108 goto cleanup; 1109 } 1110 } else { 1111 /* 1112 * Here existing ldap object is modified and can be related 1113 * to any attribute, so always ensure that the ldap 1114 * object is extended with all the kerberos related 1115 * objectclasses so that there are no constraint 1116 * violations. 1117 */ 1118 { 1119 char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL}; 1120 int p, q, r=0, amask=0; 1121 1122 if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn, 1123 "objectclass", attrvalues, &amask)) != 0) 1124 goto cleanup; 1125 1126 memset(strval, 0, sizeof(strval)); 1127 for (p=1, q=0; p<=2; p<<=1, ++q) { 1128 if ((p & amask) == 0) 1129 strval[r++] = attrvalues[q]; 1130 } 1131 if (r != 0) { 1132 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 1133 goto cleanup; 1134 } 1135 } 1136 if (xargs.dn != NULL) 1137 st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL); 1138 else 1139 st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL); 1140 1141 if (st != LDAP_SUCCESS) { 1142 snprintf(errbuf, sizeof (errbuf), gettext("User modification failed: %s"), ldap_err2string(st)); 1143 st = translate_ldap_error (st, OP_MOD); 1144 krb5_set_error_message(context, st, "%s", errbuf); 1145 goto cleanup; 1146 } 1147 } 1148 } 1149 1150 cleanup: 1151 if (user) 1152 free(user); 1153 1154 free_xargs(xargs); 1155 1156 if (standalone_principal_dn) 1157 free(standalone_principal_dn); 1158 1159 if (principal_dn) 1160 free (principal_dn); 1161 1162 /* Solaris Kerberos: fix memleak */ 1163 if (ber_tl_data) { 1164 int j; 1165 1166 for (j = 0; ber_tl_data[j] != NULL; j++) { 1167 free (ber_tl_data[j]->bv_val); 1168 free (ber_tl_data[j]); 1169 } 1170 free(ber_tl_data); 1171 } 1172 1173 if (polname != NULL) 1174 free(polname); 1175 1176 if (subtree) 1177 free (subtree); 1178 1179 if (bersecretkey) { 1180 for (l=0; bersecretkey[l]; ++l) { 1181 if (bersecretkey[l]->bv_val) 1182 free (bersecretkey[l]->bv_val); 1183 free (bersecretkey[l]); 1184 } 1185 free (bersecretkey); 1186 } 1187 1188 ldap_mods_free(mods, 1); 1189 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 1190 *nentries = i; 1191 return(st); 1192 } 1193 1194 krb5_error_code 1195 krb5_read_tkt_policy (context, ldap_context, entries, policy) 1196 krb5_context context; 1197 krb5_ldap_context *ldap_context; 1198 krb5_db_entry *entries; 1199 char *policy; 1200 { 1201 krb5_error_code st=0; 1202 unsigned int mask=0, omask=0; 1203 int tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR); 1204 krb5_ldap_policy_params *tktpoldnparam=NULL; 1205 1206 if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0) 1207 goto cleanup; 1208 1209 if ((mask & tkt_mask) == tkt_mask) 1210 goto cleanup; 1211 1212 if (policy != NULL) { 1213 st = krb5_ldap_read_policy(context, policy, &tktpoldnparam, &omask); 1214 if (st && st != KRB5_KDB_NOENTRY) { 1215 prepend_err_str(context, gettext("Error reading ticket policy. "), st, st); 1216 goto cleanup; 1217 } 1218 1219 st = 0; /* reset the return status */ 1220 } 1221 1222 if ((mask & KDB_MAX_LIFE_ATTR) == 0) { 1223 if ((omask & KDB_MAX_LIFE_ATTR) == KDB_MAX_LIFE_ATTR) 1224 entries->max_life = tktpoldnparam->maxtktlife; 1225 else if (ldap_context->lrparams->max_life) 1226 entries->max_life = ldap_context->lrparams->max_life; 1227 } 1228 1229 if ((mask & KDB_MAX_RLIFE_ATTR) == 0) { 1230 if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR) 1231 entries->max_renewable_life = tktpoldnparam->maxrenewlife; 1232 else if (ldap_context->lrparams->max_renewable_life) 1233 entries->max_renewable_life = ldap_context->lrparams->max_renewable_life; 1234 } 1235 1236 if ((mask & KDB_TKT_FLAGS_ATTR) == 0) { 1237 if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR) 1238 entries->attributes = tktpoldnparam->tktflags; 1239 else if (ldap_context->lrparams->tktflags) 1240 entries->attributes |= ldap_context->lrparams->tktflags; 1241 } 1242 krb5_ldap_free_policy(context, tktpoldnparam); 1243 1244 cleanup: 1245 return st; 1246 } 1247 1248 krb5_error_code 1249 krb5_decode_krbsecretkey(context, entries, bvalues) 1250 krb5_context context; 1251 krb5_db_entry *entries; 1252 struct berval **bvalues; 1253 { 1254 char *user=NULL; 1255 int i=0, j=0, noofkeys=0; 1256 krb5_key_data *key_data=NULL, *tmp; 1257 krb5_error_code st=0; 1258 1259 if ((st=krb5_unparse_name(context, entries->princ, &user)) != 0) 1260 goto cleanup; 1261 1262 for (i=0; bvalues[i] != NULL; ++i) { 1263 int mkvno; /* Not used currently */ 1264 krb5_int16 n_kd; 1265 krb5_key_data *kd; 1266 krb5_data in; 1267 1268 if (bvalues[i]->bv_len == 0) 1269 continue; 1270 in.length = bvalues[i]->bv_len; 1271 in.data = bvalues[i]->bv_val; 1272 1273 st = asn1_decode_sequence_of_keys (&in, 1274 &kd, 1275 &n_kd, 1276 &mkvno); 1277 1278 if (st != 0) { 1279 const char *msg = error_message(st); 1280 st = -1; /* Something more appropriate ? */ 1281 krb5_set_error_message (context, st, 1282 gettext("unable to decode stored principal key data (%s)"), msg); 1283 goto cleanup; 1284 } 1285 noofkeys += n_kd; 1286 tmp = key_data; 1287 key_data = realloc (key_data, noofkeys * sizeof (krb5_key_data)); 1288 if (key_data == NULL) { 1289 key_data = tmp; 1290 st = ENOMEM; 1291 goto cleanup; 1292 } 1293 for (j = 0; j < n_kd; j++) 1294 key_data[noofkeys - n_kd + j] = kd[j]; 1295 free (kd); 1296 } 1297 1298 entries->n_key_data = noofkeys; 1299 entries->key_data = key_data; 1300 1301 cleanup: 1302 ldap_value_free_len(bvalues); 1303 free (user); 1304 return st; 1305 } 1306 1307 static char * 1308 getstringtime(epochtime) 1309 krb5_timestamp epochtime; 1310 { 1311 struct tm tme; 1312 char *strtime=NULL; 1313 time_t posixtime = epochtime; 1314 1315 strtime = calloc (50, 1); 1316 if (strtime == NULL) 1317 return NULL; 1318 1319 if (gmtime_r(&posixtime, &tme) == NULL) 1320 return NULL; 1321 1322 strftime(strtime, 50, DATE_FORMAT, &tme); 1323 return strtime; 1324 } 1325 1326