1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <ctype.h> 29 #include <strings.h> 30 #include <pwd.h> 31 #include <shadow.h> 32 #include <netdb.h> 33 #include <mp.h> 34 #include <rpcsvc/nis.h> 35 #include <rpc/key_prot.h> 36 #include <nsswitch.h> 37 #include <ns_sldap.h> 38 39 extern char *crypt(); 40 extern long random(); 41 extern char *getpassphrase(); 42 extern char *program_name; 43 static const char *CRED_TABLE = "cred.org_dir"; 44 45 #define ROOTKEY_FILE "/etc/.rootkey" 46 47 #ifndef MAXHOSTNAMELEN 48 #define MAXHOSTNAMELEN 256 49 #endif 50 51 #define PK_FILES 1 52 #define PK_YP 2 53 #define PK_LDAP 4 54 55 #define LDAP_BINDDN_DEFAULT "cn=Directory Manager" 56 #define PROMPTGET_SUCCESS 1 57 #define PROMPTGET_FAIL -1 58 #define PROMPTGET_MEMORY_FAIL -2 59 #define PASSWD_UNMATCHED -3 60 61 #define FREE_CREDINFO(s) \ 62 if ((s)) { (void) memset((s), 0, strlen((s))); } 63 64 65 /* ************************ switch functions *************************** */ 66 67 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ 68 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} 69 70 static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, 71 lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; 72 static struct __nsw_switchconfig publickey_default = 73 {0, "publickey", 2, &lookup_nis}; 74 75 static int get_ldap_bindDN(char **); 76 static int get_ldap_bindPassword(char **); 77 78 /* 79 * Prompt the users for a ldap bind DN. If users do not enter a value but just 80 * simply hit the return key, the default bindDN "cn=Directory Manager" 81 * will be used. 82 */ 83 static int 84 get_ldap_bindDN(char **ret_bindDN) 85 { 86 87 char bindDN[BUFSIZ]; 88 char prompt[BUFSIZ]; 89 int blen, pos; 90 91 /* set the initial value for bindDN buffer */ 92 (void) memset(bindDN, 0, BUFSIZ); 93 94 (void) snprintf(prompt, BUFSIZ, 95 "\nThe LDAP bind DN and password are required for this update.\n" 96 "If you are not sure what values to enter, please contact your\n" 97 "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ", 98 LDAP_BINDDN_DEFAULT); 99 100 printf(prompt); 101 102 if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) { 103 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 104 } 105 106 blen = strlen(bindDN); 107 108 /* Check if the buffer ends with a newline */ 109 if ((blen > 0) && (bindDN[blen - 1] == '\n')) { 110 bindDN[blen - 1] = '\0'; 111 blen -= 1; 112 } 113 114 /* Remove the white spaces */ 115 if (blen > 0) { 116 for (pos = blen - 1; pos >= 0; pos--) { 117 if (isspace(bindDN[pos])) 118 bindDN[pos] = '\0'; 119 else 120 break; 121 } 122 } 123 124 /* Use the default bindDN, if the buffer contains no characters */ 125 if (strlen(bindDN) == 0) 126 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 127 128 if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) { 129 (void) memset(bindDN, 0, BUFSIZ); 130 return (PROMPTGET_MEMORY_FAIL); 131 } 132 133 (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1); 134 135 /* Clean up and erase the credential info */ 136 (void) memset(bindDN, 0, BUFSIZ); 137 138 return (PROMPTGET_SUCCESS); 139 } 140 141 142 /* 143 * Prompt the user for a ldap bind password. 144 */ 145 static int 146 get_ldap_bindPassword(char **ret_bindPass) 147 { 148 149 char bindPassword[BUFSIZ]; 150 char prompt[BUFSIZ]; 151 char *bindPass = NULL; 152 153 /* set the initial value for bindPassword buffer */ 154 (void) memset(bindPassword, 0, BUFSIZ); 155 *ret_bindPass = NULL; 156 157 (void) snprintf(prompt, BUFSIZ, 158 "Please enter LDAP bind password: "); 159 160 bindPass = getpassphrase(prompt); 161 162 if (bindPass == NULL) 163 return (PROMPTGET_FAIL); 164 165 (void) strlcpy(bindPassword, bindPass, BUFSIZ); 166 167 /* clean the static buffer returned from getpassphrase call */ 168 (void) memset(bindPass, 0, strlen(bindPass)); 169 bindPass = NULL; 170 171 /* 172 * Re-enter the bind passowrd and compare it with the one 173 * from previous entered. 174 */ 175 (void) snprintf(prompt, BUFSIZ, 176 "Re-enter LDAP bind password to confirm: "); 177 178 bindPass = getpassphrase(prompt); 179 180 if (bindPass == NULL) { 181 (void) memset(bindPassword, 0, BUFSIZ); 182 return (PASSWD_UNMATCHED); 183 } 184 185 if (strcmp(bindPass, bindPassword) != 0) { 186 (void) memset(bindPassword, 0, BUFSIZ); 187 (void) memset(bindPass, 0, strlen(bindPass)); 188 return (PASSWD_UNMATCHED); 189 } else { 190 (void) memset(bindPass, 0, strlen(bindPass)); 191 if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1)) 192 == NULL) { 193 (void) memset(bindPassword, 0, BUFSIZ); 194 return (PROMPTGET_MEMORY_FAIL); 195 } 196 197 (void) strlcpy(*ret_bindPass, bindPassword, 198 strlen(bindPassword)+1); 199 200 /* Clean up and erase the credential info */ 201 (void) memset(bindPassword, 0, BUFSIZ); 202 203 return (PROMPTGET_SUCCESS); 204 } 205 } 206 207 208 209 char * 210 switch_policy_str(struct __nsw_switchconfig *conf) 211 { 212 struct __nsw_lookup *look; 213 static char policy[256]; /* 256 is enough for (nis, files...etc) */ 214 int previous = 0; 215 216 memset((char *)policy, 0, 256); 217 218 for (look = conf->lookups; look; look = look->next) { 219 if (previous) 220 strcat(policy, " "); 221 strcat(policy, look->service_name); 222 previous = 1; 223 } 224 return (policy); 225 } 226 227 int 228 no_switch_policy(struct __nsw_switchconfig *conf) 229 { 230 return (conf == NULL || conf->lookups == NULL); 231 } 232 233 int 234 is_switch_policy(struct __nsw_switchconfig *conf, char *target) 235 { 236 return (conf && 237 conf->lookups && 238 strcmp(conf->lookups->service_name, target) == 0 && 239 conf->lookups->next == NULL); 240 } 241 242 char * 243 first_and_only_switch_policy(char *policy, 244 struct __nsw_switchconfig *default_conf, char *head_msg) 245 { 246 struct __nsw_switchconfig *conf; 247 enum __nsw_parse_err perr; 248 int policy_correct = 1; 249 char *target_service = 0; 250 int use_default = 0; 251 252 if (default_conf == 0) 253 default_conf = &publickey_default; 254 255 conf = __nsw_getconfig(policy, &perr); 256 if (no_switch_policy(conf)) { 257 use_default = 1; 258 conf = default_conf; 259 } 260 261 target_service = conf->lookups->service_name; 262 263 if (conf->lookups->next != NULL) { 264 policy_correct = 0; 265 if (use_default) { 266 (void) fprintf(stderr, 267 "\n%s\n There is no publickey entry in %s.\n", 268 head_msg, __NSW_CONFIG_FILE); 269 (void) fprintf(stderr, 270 "The default publickey policy is \"publickey: %s\".\n", 271 switch_policy_str(default_conf)); 272 } else 273 (void) fprintf(stderr, 274 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", 275 head_msg, __NSW_CONFIG_FILE, 276 switch_policy_str(conf)); 277 } 278 279 if (policy_correct == 0) 280 (void) fprintf(stderr, 281 "I cannot figure out which publickey database you want to update.\n"); 282 if (!use_default && conf) 283 __nsw_freeconfig(conf); 284 285 if (policy_correct) 286 return (target_service); 287 else 288 return (0); 289 } 290 291 292 293 int 294 check_switch_policy(char *policy, char *target_service, 295 struct __nsw_switchconfig *default_conf, char *head_msg, char *tail_msg) 296 { 297 struct __nsw_switchconfig *conf; 298 enum __nsw_parse_err perr; 299 int policy_correct = 1; 300 301 if (default_conf == 0) 302 default_conf = &publickey_default; 303 304 conf = __nsw_getconfig(policy, &perr); 305 if (no_switch_policy(conf)) { 306 if (!is_switch_policy(default_conf, target_service)) { 307 (void) fprintf(stderr, 308 "\n%s\nThere is no publickey entry in %s.\n", 309 head_msg, __NSW_CONFIG_FILE); 310 (void) fprintf(stderr, 311 "The default publickey policy is \"publickey: %s\".\n", 312 switch_policy_str(default_conf)); 313 policy_correct = 0; 314 } 315 } else if (!is_switch_policy(conf, target_service)) { 316 (void) fprintf(stderr, 317 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", 318 head_msg, __NSW_CONFIG_FILE, 319 switch_policy_str(conf)); 320 policy_correct = 0; 321 } 322 /* should we exit ? */ 323 if (policy_correct == 0) 324 (void) fprintf(stderr, 325 "It should be \"publickey: %s\"%s\n\n", 326 target_service, tail_msg); 327 if (conf) 328 __nsw_freeconfig(conf); 329 330 return (policy_correct); 331 } 332 333 int 334 get_pk_source(char *pk_service) 335 { 336 int db = 0, got_from_switch = 0; 337 338 /* No service specified, try to figure out from switch */ 339 if (pk_service == 0) { 340 pk_service = first_and_only_switch_policy("publickey", 0, 341 "ERROR:"); 342 if (pk_service == 0) 343 return (0); 344 (void) fprintf(stdout, 345 "Updating %s publickey database.\n", 346 pk_service); 347 got_from_switch = 1; 348 } 349 350 if (strcmp(pk_service, "ldap") == 0) 351 db = PK_LDAP; 352 else if (strcmp(pk_service, "nis") == 0) 353 db = PK_YP; 354 else if (strcmp(pk_service, "files") == 0) 355 db = PK_FILES; 356 else return (0); 357 358 /* 359 * If we didn't get service name from switch, check switch 360 * and print warning about it source of publickeys if not unique 361 */ 362 if (got_from_switch == 0) 363 check_switch_policy("publickey", pk_service, 0, "WARNING:", 364 db == PK_FILES ? "" : 365 "; add 'files' if you want the 'nobody' key."); 366 367 368 return (db); /* all passed */ 369 } 370 371 372 /* ***************************** keylogin stuff *************************** */ 373 int 374 keylogin(char *netname, char *secret) 375 { 376 struct key_netstarg netst; 377 378 netst.st_pub_key[0] = 0; 379 memcpy(netst.st_priv_key, secret, HEXKEYBYTES); 380 netst.st_netname = netname; 381 382 #ifdef NFS_AUTH 383 nra.authtype = AUTH_DES; /* only revoke DES creds */ 384 nra.uid = getuid(); /* use the real uid */ 385 if (_nfssys(NFS_REVAUTH, &nra) < 0) { 386 perror("Warning: NFS credentials not destroyed"); 387 err = 1; 388 } 389 #endif 390 391 392 /* do actual key login */ 393 if (key_setnet(&netst) < 0) { 394 (void) fprintf(stderr, 395 "Could not set %s's secret key\n", netname); 396 (void) fprintf(stderr, "May be the keyserv is down?\n"); 397 return (0); 398 } 399 400 return (1); 401 } 402 403 nis_object * 404 init_entry() 405 { 406 static nis_object obj; 407 static entry_col cred_data[10]; 408 entry_obj *eo; 409 410 memset((char *)(&obj), 0, sizeof (obj)); 411 memset((char *)(cred_data), 0, sizeof (entry_col) * 10); 412 413 obj.zo_name = "cred"; 414 obj.zo_group = ""; 415 obj.zo_ttl = 43200; 416 obj.zo_data.zo_type = NIS_ENTRY_OBJ; 417 eo = &(obj.EN_data); 418 eo->en_type = "cred_tbl"; 419 eo->en_cols.en_cols_val = cred_data; 420 eo->en_cols.en_cols_len = 5; 421 cred_data[4].ec_flags |= EN_CRYPT; 422 return (&obj); 423 } 424 425 426 static char *attrFilter[] = { 427 "objectclass", 428 "nispublickey", 429 "nissecretkey", 430 (char *)NULL 431 }; 432 433 434 /* Determines if there is a NisKeyObject objectclass in a given entry */ 435 static int 436 ldap_keyobj_exist(ns_ldap_entry_t *entry) 437 { 438 char **fattrs; 439 440 fattrs = __ns_ldap_getAttr(entry, "objectClass"); 441 442 if (fattrs == NULL) 443 return (1); 444 445 while (*fattrs) { 446 if (strcasecmp("NisKeyObject", *fattrs) == 0) 447 return (1); 448 fattrs++; 449 } 450 451 return (0); 452 } 453 454 455 static char *keyAttrs[] = { 456 "nispublickey", 457 "nissecretkey", 458 NULL 459 }; 460 461 /* 462 * Replace or append new attribute value(s) to an attribute. 463 * Don't care about memory leaks, because program is short running. 464 */ 465 466 static int 467 ldap_attr_mod(ns_ldap_entry_t *entry, char *mechname, char *public, 468 ns_ldap_attr_t **pkeyattrs, char *crypt, ns_ldap_attr_t **ckeyattrs) 469 { 470 char **alist[2]; 471 char *keys[2]; 472 473 char *mechfilter; 474 int mechfilterlen; 475 int q = 0; 476 int i, j; 477 int keycount[] = {0, 0}; 478 ns_ldap_attr_t *attrs; 479 480 keys[0] = public; 481 keys[1] = crypt; 482 483 mechfilter = (char *)malloc(strlen(mechname) + 3); 484 if (mechfilter == NULL) 485 return (0); 486 sprintf(mechfilter, "{%s}", mechname); 487 mechfilterlen = strlen(mechfilter); 488 489 for (q = 0; keyAttrs[q] != NULL; q++) { 490 int found = 0; 491 492 for (i = 0; i < entry->attr_count; i++) { 493 int rep = 0; 494 ns_ldap_attr_t *attr = entry->attr_pair[i]; 495 char *name = attr->attrname; 496 int count = 0; 497 498 if (strcasecmp(keyAttrs[q], name) == 0) { 499 found++; 500 count = attr->value_count; 501 alist[q] = (char **)malloc(sizeof (char *) * (count + 1)); 502 if (alist[q] == NULL) 503 return (0); 504 alist[q][attr->value_count] = NULL; 505 for (j = 0; j < attr->value_count; j++) { 506 char *val = attr->attrvalue[j]; 507 if (strncasecmp(val, mechfilter, 508 mechfilterlen) == 0) { 509 /* Replace entry */ 510 rep++; 511 alist[q][j] = keys[q]; 512 } else 513 alist[q][j] = val; 514 ++keycount[q]; 515 } 516 if (!rep) { 517 /* Add entry to list */ 518 alist[q] = (char **)realloc(alist[q], 519 sizeof (char *) * (count + 2)); 520 if (alist[q] == NULL) 521 return (0); 522 alist[q][attr->value_count + 1] = NULL; 523 alist[q][attr->value_count] = keys[q]; 524 ++keycount[q]; 525 } 526 } 527 } 528 if (!found) { 529 /* Attribute does not exist, add entry anyways */ 530 alist[q] = (char **)malloc(sizeof (char *) * 2); 531 if (alist[q] == NULL) 532 return (0); 533 alist[q][0] = keys[q]; 534 alist[q][1] = NULL; 535 ++keycount[q]; 536 } 537 } 538 if ((attrs = (ns_ldap_attr_t *)calloc(1, 539 sizeof (ns_ldap_attr_t))) == NULL) 540 return (0); 541 attrs->attrname = "nisPublicKey"; 542 attrs->attrvalue = alist[0]; 543 attrs->value_count = keycount[0]; 544 *pkeyattrs = attrs; 545 546 if ((attrs = (ns_ldap_attr_t *)calloc(1, 547 sizeof (ns_ldap_attr_t))) == NULL) 548 return (0); 549 attrs->attrname = "nisSecretKey"; 550 attrs->attrvalue = alist[1]; 551 attrs->value_count = keycount[1]; 552 *ckeyattrs = attrs; 553 return (1); 554 } 555 556 557 /* 558 * Do the actual Add or update of attributes in attrs. 559 * The parameter 'update4host' is a flag that tells the function which 560 * DN and password should be used to bind to ldap. If it is an update 561 * for a host (update4host > 0), the two parameters "bindDN" and 562 * "bindPasswd" would be used to bind as the directory manager, 563 * otherwise "dn" and "passwd" would be used to bind as an individual 564 * user. 565 */ 566 static void 567 update_ldap_attr(const char *dn, ns_ldap_attr_t **attrs, const char *passwd, 568 int add, int update4host, const char *bindDN, const char *bindPasswd) 569 { 570 int ldaprc; 571 int authstried = 0; 572 char *msg; 573 char *ldap_pw; 574 char **certpath = NULL; 575 ns_auth_t **app; 576 ns_auth_t **authpp = NULL; 577 ns_auth_t *authp = NULL; 578 ns_cred_t *credp; 579 ns_ldap_error_t *errorp = NULL; 580 int status; 581 582 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) { 583 fprintf(stderr, "Can not allocate cred buffer.\n"); 584 goto out; 585 } 586 587 /* 588 * if this is an update for host, use the bindDN from the 589 * command prompt, otherwise use user's DN directly. 590 */ 591 if (update4host) 592 credp->cred.unix_cred.userID = strdup(bindDN); 593 else 594 credp->cred.unix_cred.userID = strdup(dn); 595 596 if (credp->cred.unix_cred.userID == NULL) { 597 fprintf(stderr, "Memory allocation failure (userID)\n"); 598 goto out; 599 } 600 601 if (update4host) { 602 credp->cred.unix_cred.passwd = strdup(bindPasswd); 603 } else { 604 if (passwd) 605 credp->cred.unix_cred.passwd = strdup(passwd); 606 else { 607 /* Make sure a valid password is received. */ 608 status = get_ldap_bindPassword(&ldap_pw); 609 610 if (status != PROMPTGET_SUCCESS) { 611 if (!ldap_pw) 612 free(ldap_pw); 613 goto out; 614 } 615 credp->cred.unix_cred.passwd = ldap_pw; 616 } 617 } 618 619 if (credp->cred.unix_cred.passwd == NULL) { 620 fprintf(stderr, "Memory allocation failure (passwd)\n"); 621 goto out; 622 } 623 624 /* get host certificate path, if one is configured */ 625 if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, 626 (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS) 627 goto out; 628 629 if (certpath && *certpath) 630 credp->hostcertpath = *certpath; 631 632 /* Load the service specific authentication method */ 633 if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) != 634 NS_LDAP_SUCCESS) 635 goto out; 636 637 /* 638 * if authpp is null, there is no serviceAuthenticationMethod 639 * try default authenticationMethod 640 */ 641 if (authpp == NULL) { 642 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 643 &errorp) != NS_LDAP_SUCCESS) 644 goto out; 645 } 646 647 /* 648 * if authpp is still null, then can not authenticate, log 649 * error message and return error 650 */ 651 if (authpp == NULL) { 652 fprintf(stderr, "No LDAP authentication method configured.\n" 653 " configured.\n"); 654 goto out; 655 } 656 657 /* 658 * Walk the array and try all authentication methods in order except 659 * for "none". 660 */ 661 for (app = authpp; *app; app++) { 662 authp = *app; 663 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ 664 if (authp->type == NS_LDAP_AUTH_NONE) 665 continue; 666 authstried++; 667 credp->auth.type = authp->type; 668 credp->auth.tlstype = authp->tlstype; 669 credp->auth.saslmech = authp->saslmech; 670 credp->auth.saslopt = authp->saslopt; 671 672 if (add == TRUE) 673 ldaprc = __ns_ldap_addAttr("publickey", dn, 674 (const ns_ldap_attr_t * const *)attrs, 675 credp, 0, &errorp); 676 else 677 ldaprc = __ns_ldap_repAttr("publickey", dn, 678 (const ns_ldap_attr_t * const *)attrs, 679 credp, 0, &errorp); 680 if (ldaprc == NS_LDAP_SUCCESS) { 681 /* clean up ns_cred_t structure in memory */ 682 if (credp != NULL) 683 (void) __ns_ldap_freeCred(&credp); 684 return; 685 } 686 687 /* XXX add checking for cases of authentication errors */ 688 if ((ldaprc == NS_LDAP_INTERNAL) && 689 ((errorp->status == LDAP_INAPPROPRIATE_AUTH) || 690 (errorp->status == LDAP_INVALID_CREDENTIALS))) { 691 fprintf(stderr, "LDAP authentication failed.\n"); 692 goto out; 693 } 694 } 695 if (authstried == 0) 696 fprintf(stderr, "No legal authentication method configured.\n"); 697 698 out: 699 /* clean up ns_cred_t structure in memory */ 700 if (credp != NULL) { 701 (void) __ns_ldap_freeCred(&credp); 702 } 703 704 if (errorp) { 705 __ns_ldap_err2str(errorp->status, &msg); 706 fprintf(stderr, "LDAP error: %s.\n", msg); 707 } 708 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 709 exit(1); 710 } 711 712 713 /* 714 * Update LDAP nisplublickey entry with new key information via SLDAP. 715 * Free and clean up memory that stores credential data soon after 716 * they are not used or an error comes up. 717 */ 718 int 719 ldap_update(char *mechname, char *netname, char *public, char *crypt, 720 char *passwd) 721 { 722 char *netnamecpy; 723 char *id; 724 char *domain; 725 char *dn; 726 char *db; 727 char *filter; 728 ns_ldap_error_t *errorp; 729 char *pkeyatval, *ckeyatval; 730 ns_ldap_result_t *res; 731 ns_ldap_attr_t *pattrs, *cattrs; 732 int update4host = FALSE; 733 char *bindDN = NULL; 734 char *bindPasswd = NULL; 735 int status; 736 737 /* Generate DN */ 738 if ((netnamecpy = strdup(netname)) == NULL) 739 return (0); 740 if (((id = strchr(netnamecpy, '.')) == NULL) || 741 ((domain = strchr(netnamecpy, '@')) == NULL)) 742 return (0); 743 else { 744 *domain++ = '\0'; 745 *id++ = '\0'; 746 747 id = strdup(id); 748 if (id == NULL) { 749 free(netnamecpy); 750 fprintf(stderr, "LDAP memory error (id)\n"); 751 return (0); 752 } 753 domain = strdup(domain); 754 if (domain == NULL) { 755 free(netnamecpy); 756 free(id); 757 fprintf(stderr, "LDAP memory error (domain)\n"); 758 return (0); 759 } 760 free(netnamecpy); 761 } 762 763 if (isdigit(*id)) { 764 /* We be user. */ 765 __ns_ldap_uid2dn(id, &dn, NULL, &errorp); 766 if (dn == NULL) { 767 fprintf(stderr, "Could not obtain LDAP dn\n"); 768 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 769 program_name); 770 exit(1); 771 } 772 db = "passwd"; 773 filter = (char *)malloc(strlen(id) + 13); 774 if (filter) 775 sprintf(filter, "(uidnumber=%s)", id); 776 else { 777 fprintf(stderr, "Can not allocate filter buffer.\n"); 778 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 779 program_name); 780 exit(1); 781 } 782 } else { 783 /* We be host. */ 784 update4host = TRUE; 785 786 __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp); 787 if (dn == NULL) { 788 fprintf(stderr, "Could not obtain LDAP dn\n"); 789 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 790 program_name); 791 exit(1); 792 } 793 794 db = "hosts"; 795 filter = (char *)malloc(strlen(id) + 6); 796 if (filter) 797 sprintf(filter, "(cn=%s)", id); 798 else { 799 fprintf(stderr, "Can not allocate filter buffer.\n"); 800 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 801 program_name); 802 exit(1); 803 } 804 805 /* Prompt for ldap bind DN for entry udpates */ 806 status = get_ldap_bindDN(&bindDN); 807 808 if (status != PROMPTGET_SUCCESS) { 809 FREE_CREDINFO(bindDN); 810 fprintf(stderr, 811 "Failed to get a valid LDAP bind DN.\n" 812 "%s: key-pair(s) unchanged.\n", 813 program_name); 814 exit(1); 815 } 816 817 /* Prompt for ldap bind password */ 818 status = get_ldap_bindPassword(&bindPasswd); 819 820 if (status != PROMPTGET_SUCCESS) { 821 FREE_CREDINFO(bindPasswd); 822 FREE_CREDINFO(bindDN); 823 824 fprintf(stderr, 825 "Failed to get a valid LDAP bind password." 826 "\n%s: key-pair(s) unchanged.\n", 827 program_name); 828 exit(1); 829 } 830 } 831 832 /* Construct attribute values */ 833 pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3); 834 if (pkeyatval == NULL) { 835 FREE_CREDINFO(bindPasswd); 836 FREE_CREDINFO(bindDN); 837 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 838 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 839 exit(1); 840 } 841 sprintf(pkeyatval, "{%s}%s", mechname, public); 842 ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3); 843 if (ckeyatval == NULL) { 844 FREE_CREDINFO(pkeyatval); 845 FREE_CREDINFO(bindPasswd); 846 FREE_CREDINFO(bindDN); 847 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 848 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 849 exit(1); 850 } 851 sprintf(ckeyatval, "{%s}%s", mechname, crypt); 852 853 /* Does entry exist? */ 854 if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter, 855 NULL, 0, &res, &errorp, 856 NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) { 857 FREE_CREDINFO(ckeyatval); 858 FREE_CREDINFO(pkeyatval); 859 FREE_CREDINFO(bindPasswd); 860 FREE_CREDINFO(bindDN); 861 fprintf(stderr, "LDAP entry does not exist.\n"); 862 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 863 exit(1); 864 } 865 866 /* Entry exists, modify attributes for public and secret keys */ 867 868 /* Is there a NisKeyObject in entry? */ 869 if (!ldap_keyobj_exist(&res->entry[0])) { 870 /* Add NisKeyObject objectclass and the keys */ 871 char **newattr; 872 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 873 874 /* set objectclass */ 875 newattr = (char **)calloc(2, sizeof (char *)); 876 newattr[0] = "NisKeyObject"; 877 newattr[1] = NULL; 878 if ((attrs[0] = (ns_ldap_attr_t *)calloc(1, 879 sizeof (ns_ldap_attr_t))) == NULL) { 880 FREE_CREDINFO(ckeyatval); 881 FREE_CREDINFO(pkeyatval); 882 FREE_CREDINFO(bindPasswd); 883 FREE_CREDINFO(bindDN); 884 fprintf(stderr, "Memory allocation failed\n"); 885 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 886 program_name); 887 exit(1); 888 } 889 attrs[0]->attrname = "objectClass"; 890 attrs[0]->attrvalue = newattr; 891 attrs[0]->value_count = 1; 892 893 /* set publickey */ 894 newattr = (char **)calloc(2, sizeof (char *)); 895 newattr[0] = pkeyatval; 896 newattr[1] = NULL; 897 if ((attrs[1] = (ns_ldap_attr_t *)calloc(1, 898 sizeof (ns_ldap_attr_t))) == NULL) { 899 FREE_CREDINFO(ckeyatval); 900 FREE_CREDINFO(pkeyatval); 901 FREE_CREDINFO(bindPasswd); 902 FREE_CREDINFO(bindDN); 903 fprintf(stderr, "Memory allocation failed\n"); 904 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 905 program_name); 906 exit(1); 907 } 908 attrs[1]->attrname = "nisPublicKey"; 909 attrs[1]->attrvalue = newattr; 910 attrs[1]->value_count = 1; 911 912 /* set privatekey */ 913 newattr = (char **)calloc(2, sizeof (char *)); 914 newattr[0] = ckeyatval; 915 newattr[1] = NULL; 916 if ((attrs[2] = (ns_ldap_attr_t *)calloc(1, 917 sizeof (ns_ldap_attr_t))) == NULL) { 918 FREE_CREDINFO(ckeyatval); 919 FREE_CREDINFO(pkeyatval); 920 FREE_CREDINFO(bindPasswd); 921 FREE_CREDINFO(bindDN); 922 fprintf(stderr, "Memory allocation failed\n"); 923 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 924 program_name); 925 exit(1); 926 } 927 attrs[2]->attrname = "nisSecretKey"; 928 attrs[2]->attrvalue = newattr; 929 attrs[2]->value_count = 1; 930 931 /* terminator */ 932 attrs[3] = NULL; 933 934 update_ldap_attr(dn, attrs, passwd, TRUE, update4host, 935 bindDN, bindPasswd); 936 } else { 937 /* object class already exists, replace keys */ 938 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 939 940 if (!ldap_attr_mod(&res->entry[0], mechname, 941 pkeyatval, &pattrs, 942 ckeyatval, &cattrs)) { 943 FREE_CREDINFO(ckeyatval); 944 FREE_CREDINFO(pkeyatval); 945 FREE_CREDINFO(bindPasswd); 946 FREE_CREDINFO(bindDN); 947 fprintf(stderr, 948 "Could not generate LDAP attribute list.\n"); 949 fprintf(stderr, 950 "%s: key-pair(s) unchanged.\n", program_name); 951 exit(1); 952 } 953 954 attrs[0] = pattrs; 955 attrs[1] = cattrs; 956 attrs[2] = NULL; 957 958 update_ldap_attr(dn, attrs, passwd, FALSE, update4host, 959 bindDN, bindPasswd); 960 } 961 962 FREE_CREDINFO(ckeyatval); 963 FREE_CREDINFO(pkeyatval); 964 FREE_CREDINFO(bindPasswd); 965 FREE_CREDINFO(bindDN); 966 967 return (0); 968 } 969