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 char bindDN[BUFSIZ]; 87 char prompt[BUFSIZ]; 88 int blen, pos; 89 90 /* set the initial value for bindDN buffer */ 91 (void) memset(bindDN, 0, BUFSIZ); 92 93 (void) snprintf(prompt, BUFSIZ, 94 "\nThe LDAP bind DN and password are required for this update.\n" 95 "If you are not sure what values to enter, please contact your\n" 96 "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ", 97 LDAP_BINDDN_DEFAULT); 98 99 printf(prompt); 100 101 if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) { 102 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 103 } 104 105 blen = strlen(bindDN); 106 107 /* Check if the buffer ends with a newline */ 108 if ((blen > 0) && (bindDN[blen - 1] == '\n')) { 109 bindDN[blen - 1] = '\0'; 110 blen -= 1; 111 } 112 113 /* Remove the white spaces */ 114 if (blen > 0) { 115 for (pos = blen - 1; pos >= 0; pos--) { 116 if (isspace(bindDN[pos])) 117 bindDN[pos] = '\0'; 118 else 119 break; 120 } 121 } 122 123 /* Use the default bindDN, if the buffer contains no characters */ 124 if (strlen(bindDN) == 0) 125 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); 126 127 if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) { 128 (void) memset(bindDN, 0, BUFSIZ); 129 return (PROMPTGET_MEMORY_FAIL); 130 } 131 132 (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1); 133 134 /* Clean up and erase the credential info */ 135 (void) memset(bindDN, 0, BUFSIZ); 136 137 return (PROMPTGET_SUCCESS); 138 } 139 140 141 /* 142 * Prompt the user for a ldap bind password. 143 */ 144 static int 145 get_ldap_bindPassword(char **ret_bindPass) { 146 147 char bindPassword[BUFSIZ]; 148 char prompt[BUFSIZ]; 149 char *bindPass = NULL; 150 151 /* set the initial value for bindPassword buffer */ 152 (void) memset(bindPassword, 0, BUFSIZ); 153 *ret_bindPass = NULL; 154 155 (void) snprintf(prompt, BUFSIZ, 156 "Please enter LDAP bind password: "); 157 158 bindPass = getpassphrase(prompt); 159 160 if (bindPass == NULL) 161 return (PROMPTGET_FAIL); 162 163 (void) strlcpy(bindPassword, bindPass, BUFSIZ); 164 165 /* clean the static buffer returned from getpassphrase call */ 166 (void) memset(bindPass, 0, strlen(bindPass)); 167 bindPass = NULL; 168 169 /* 170 * Re-enter the bind passowrd and compare it with the one 171 * from previous entered. 172 */ 173 (void) snprintf(prompt, BUFSIZ, 174 "Re-enter LDAP bind password to confirm: "); 175 176 bindPass = getpassphrase(prompt); 177 178 if (bindPass == NULL) { 179 (void) memset(bindPassword, 0, BUFSIZ); 180 return (PASSWD_UNMATCHED); 181 } 182 183 if (strcmp(bindPass, bindPassword) != 0) { 184 (void) memset(bindPassword, 0, BUFSIZ); 185 (void) memset(bindPass, 0, strlen(bindPass)); 186 return (PASSWD_UNMATCHED); 187 } else { 188 (void) memset(bindPass, 0, strlen(bindPass)); 189 if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1)) 190 == NULL) { 191 (void) memset(bindPassword, 0, BUFSIZ); 192 return (PROMPTGET_MEMORY_FAIL); 193 } 194 195 (void) strlcpy(*ret_bindPass, bindPassword, 196 strlen(bindPassword)+1); 197 198 /* Clean up and erase the credential info */ 199 (void) memset(bindPassword, 0, BUFSIZ); 200 201 return (PROMPTGET_SUCCESS); 202 } 203 } 204 205 206 207 char * 208 switch_policy_str(struct __nsw_switchconfig *conf) 209 { 210 struct __nsw_lookup *look; 211 static char policy[256]; /* 256 is enough for (nis, files...etc) */ 212 int previous = 0; 213 214 memset((char *)policy, 0, 256); 215 216 for (look = conf->lookups; look; look = look->next) { 217 if (previous) 218 strcat(policy, " "); 219 strcat(policy, look->service_name); 220 previous = 1; 221 } 222 return (policy); 223 } 224 225 int 226 no_switch_policy(struct __nsw_switchconfig *conf) 227 { 228 return (conf == NULL || conf->lookups == NULL); 229 } 230 231 int 232 is_switch_policy(struct __nsw_switchconfig *conf, char *target) 233 { 234 return (conf && 235 conf->lookups && 236 strcmp(conf->lookups->service_name, target) == 0 && 237 conf->lookups->next == NULL); 238 } 239 240 char * 241 first_and_only_switch_policy(char *policy, 242 struct __nsw_switchconfig *default_conf, 243 char *head_msg) 244 { 245 struct __nsw_switchconfig *conf; 246 enum __nsw_parse_err perr; 247 int policy_correct = 1; 248 char *target_service = 0; 249 int use_default = 0; 250 251 if (default_conf == 0) 252 default_conf = &publickey_default; 253 254 conf = __nsw_getconfig(policy, &perr); 255 if (no_switch_policy(conf)) { 256 use_default = 1; 257 conf = default_conf; 258 } 259 260 target_service = conf->lookups->service_name; 261 262 if (conf->lookups->next != NULL) { 263 policy_correct = 0; 264 if (use_default) { 265 (void) fprintf(stderr, 266 "\n%s\n There is no publickey entry in %s.\n", 267 head_msg, __NSW_CONFIG_FILE); 268 (void) fprintf(stderr, 269 "The default publickey policy is \"publickey: %s\".\n", 270 switch_policy_str(default_conf)); 271 } else 272 (void) fprintf(stderr, 273 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", 274 head_msg, __NSW_CONFIG_FILE, 275 switch_policy_str(conf)); 276 } 277 278 if (policy_correct == 0) 279 (void) fprintf(stderr, 280 "I cannot figure out which publickey database you want to update.\n"); 281 if (!use_default && conf) 282 __nsw_freeconfig(conf); 283 284 if (policy_correct) 285 return (target_service); 286 else 287 return (0); 288 } 289 290 291 292 int 293 check_switch_policy(char *policy, char *target_service, 294 struct __nsw_switchconfig *default_conf, 295 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, 468 char *mechname, 469 char *public, 470 ns_ldap_attr_t **pkeyattrs, 471 char *crypt, 472 ns_ldap_attr_t **ckeyattrs) 473 { 474 char **alist[2]; 475 char *keys[2]; 476 477 char *mechfilter; 478 int mechfilterlen; 479 int q = 0; 480 int i, j; 481 int keycount[] = {0, 0}; 482 ns_ldap_attr_t *attrs; 483 484 keys[0] = public; 485 keys[1] = crypt; 486 487 mechfilter = (char *)malloc(strlen(mechname) + 3); 488 if (mechfilter == NULL) 489 return (0); 490 sprintf(mechfilter, "{%s}", mechname); 491 mechfilterlen = strlen(mechfilter); 492 493 for (q = 0; keyAttrs[q] != NULL; q++) { 494 int found = 0; 495 496 for (i = 0; i < entry->attr_count; i++) { 497 int rep = 0; 498 ns_ldap_attr_t *attr = entry->attr_pair[i]; 499 char *name = attr->attrname; 500 int count = 0; 501 502 if (strcasecmp(keyAttrs[q], name) == 0) { 503 found++; 504 count = attr->value_count; 505 alist[q] = (char **)malloc(sizeof (char *) * (count + 1)); 506 if (alist[q] == NULL) 507 return (0); 508 alist[q][attr->value_count] = NULL; 509 for (j = 0; j < attr->value_count; j++) { 510 char *val = attr->attrvalue[j]; 511 if (strncasecmp(val, mechfilter, 512 mechfilterlen) == 0) { 513 /* Replace entry */ 514 rep++; 515 alist[q][j] = keys[q]; 516 } else 517 alist[q][j] = val; 518 ++keycount[q]; 519 } 520 if (!rep) { 521 /* Add entry to list */ 522 alist[q] = (char **)realloc(alist[q], 523 sizeof (char *) * (count + 2)); 524 if (alist[q] == NULL) 525 return (0); 526 alist[q][attr->value_count + 1] = NULL; 527 alist[q][attr->value_count] = keys[q]; 528 ++keycount[q]; 529 } 530 } 531 } 532 if (!found) { 533 /* Attribute does not exist, add entry anyways */ 534 alist[q] = (char **)malloc(sizeof (char *) * 2); 535 if (alist[q] == NULL) 536 return (0); 537 alist[q][0] = keys[q]; 538 alist[q][1] = NULL; 539 ++keycount[q]; 540 } 541 } 542 if ((attrs = (ns_ldap_attr_t *)calloc(1, 543 sizeof (ns_ldap_attr_t))) == NULL) 544 return (0); 545 attrs->attrname = "nisPublicKey"; 546 attrs->attrvalue = alist[0]; 547 attrs->value_count = keycount[0]; 548 *pkeyattrs = attrs; 549 550 if ((attrs = (ns_ldap_attr_t *)calloc(1, 551 sizeof (ns_ldap_attr_t))) == NULL) 552 return (0); 553 attrs->attrname = "nisSecretKey"; 554 attrs->attrvalue = alist[1]; 555 attrs->value_count = keycount[1]; 556 *ckeyattrs = attrs; 557 return (1); 558 } 559 560 561 /* 562 * Do the actual Add or update of attributes in attrs. 563 * The parameter 'update4host' is a flag that tells the function which 564 * DN and password should be used to bind to ldap. If it is an update 565 * for a host (update4host > 0), the two parameters "bindDN" and 566 * "bindPasswd" would be used to bind as the directory manager, 567 * otherwise "dn" and "passwd" would be used to bind as an individual 568 * user. 569 */ 570 static void 571 update_ldap_attr(const char *dn, 572 ns_ldap_attr_t **attrs, 573 const char *passwd, 574 int add, 575 int update4host, 576 const char *bindDN, 577 const char *bindPasswd) 578 { 579 int ldaprc; 580 int authstried = 0; 581 char *msg; 582 char *ldap_pw; 583 char **certpath = NULL; 584 ns_auth_t **app; 585 ns_auth_t **authpp = NULL; 586 ns_auth_t *authp = NULL; 587 ns_cred_t *credp; 588 ns_ldap_error_t *errorp = NULL; 589 int status; 590 591 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) { 592 fprintf(stderr, "Can not allocate cred buffer.\n"); 593 goto out; 594 } 595 596 /* 597 * if this is an update for host, use the bindDN from the 598 * command prompt, otherwise use user's DN directly. 599 */ 600 if (update4host) 601 credp->cred.unix_cred.userID = strdup(bindDN); 602 else 603 credp->cred.unix_cred.userID = strdup(dn); 604 605 if (credp->cred.unix_cred.userID == NULL) { 606 fprintf(stderr, "Memory allocation failure (userID)\n"); 607 goto out; 608 } 609 610 if (update4host) { 611 credp->cred.unix_cred.passwd = strdup(bindPasswd); 612 } else { 613 if (passwd) 614 credp->cred.unix_cred.passwd = strdup(passwd); 615 else { 616 /* Make sure a valid password is received. */ 617 status = get_ldap_bindPassword(&ldap_pw); 618 619 if (status != PROMPTGET_SUCCESS) { 620 if (!ldap_pw) 621 free(ldap_pw); 622 goto out; 623 } 624 credp->cred.unix_cred.passwd = ldap_pw; 625 } 626 } 627 628 if (credp->cred.unix_cred.passwd == NULL) { 629 fprintf(stderr, "Memory allocation failure (passwd)\n"); 630 goto out; 631 } 632 633 /* get host certificate path, if one is configured */ 634 if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, 635 (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS) 636 goto out; 637 638 if (certpath && *certpath) 639 credp->hostcertpath = *certpath; 640 641 /* Load the service specific authentication method */ 642 if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) != 643 NS_LDAP_SUCCESS) 644 goto out; 645 646 /* 647 * if authpp is null, there is no serviceAuthenticationMethod 648 * try default authenticationMethod 649 */ 650 if (authpp == NULL) { 651 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 652 &errorp) != NS_LDAP_SUCCESS) 653 goto out; 654 } 655 656 /* 657 * if authpp is still null, then can not authenticate, log 658 * error message and return error 659 */ 660 if (authpp == NULL) { 661 fprintf(stderr, "No LDAP authentication method configured.\n" 662 " configured.\n"); 663 goto out; 664 } 665 666 /* 667 * Walk the array and try all authentication methods in order except 668 * for "none". 669 */ 670 for (app = authpp; *app; app++) { 671 authp = *app; 672 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ 673 if (authp->type == NS_LDAP_AUTH_NONE) 674 continue; 675 authstried++; 676 credp->auth.type = authp->type; 677 credp->auth.tlstype = authp->tlstype; 678 credp->auth.saslmech = authp->saslmech; 679 credp->auth.saslopt = authp->saslopt; 680 681 if (add == TRUE) 682 ldaprc = __ns_ldap_addAttr("publickey", dn, 683 (const ns_ldap_attr_t * const *)attrs, 684 credp, NULL, &errorp); 685 else 686 ldaprc = __ns_ldap_repAttr("publickey", dn, 687 (const ns_ldap_attr_t * const *)attrs, 688 credp, NULL, &errorp); 689 if (ldaprc == NS_LDAP_SUCCESS) { 690 /* clean up ns_cred_t structure in memory */ 691 if (credp != NULL) 692 (void) __ns_ldap_freeCred(&credp); 693 return; 694 } 695 696 /* XXX add checking for cases of authentication errors */ 697 if ((ldaprc == NS_LDAP_INTERNAL) && 698 ((errorp->status == LDAP_INAPPROPRIATE_AUTH) || 699 (errorp->status == LDAP_INVALID_CREDENTIALS))) { 700 fprintf(stderr, "LDAP authentication failed.\n"); 701 goto out; 702 } 703 } 704 if (authstried == 0) 705 fprintf(stderr, "No legal authentication method configured.\n"); 706 707 out: 708 /* clean up ns_cred_t structure in memory */ 709 if (credp != NULL) { 710 (void) __ns_ldap_freeCred(&credp); 711 } 712 713 if (errorp) { 714 __ns_ldap_err2str(errorp->status, &msg); 715 fprintf(stderr, "LDAP error: %s.\n", msg); 716 } 717 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 718 exit(1); 719 } 720 721 722 /* 723 * Update LDAP nisplublickey entry with new key information via SLDAP. 724 * Free and clean up memory that stores credential data soon after 725 * they are not used or an error comes up. 726 */ 727 int 728 ldap_update(char *mechname, 729 char *netname, 730 char *public, 731 char *crypt, 732 char *passwd) 733 { 734 char *netnamecpy; 735 char *id; 736 char *domain; 737 char *dn; 738 char *db; 739 char *filter; 740 ns_ldap_error_t *errorp; 741 char *pkeyatval, *ckeyatval; 742 ns_ldap_result_t *res; 743 ns_ldap_attr_t *pattrs, *cattrs; 744 int update4host = FALSE; 745 char *bindDN = NULL; 746 char *bindPasswd = NULL; 747 int status; 748 749 /* Generate DN */ 750 if ((netnamecpy = strdup(netname)) == NULL) 751 return (0); 752 if (((id = strchr(netnamecpy, '.')) == NULL) || 753 ((domain = strchr(netnamecpy, '@')) == NULL)) 754 return (0); 755 else { 756 *domain++ = '\0'; 757 *id++ = '\0'; 758 759 id = strdup(id); 760 if (id == NULL) { 761 free(netnamecpy); 762 fprintf(stderr, "LDAP memory error (id)\n"); 763 return (0); 764 } 765 domain = strdup(domain); 766 if (domain == NULL) { 767 free(netnamecpy); 768 free(id); 769 fprintf(stderr, "LDAP memory error (domain)\n"); 770 return (0); 771 } 772 free(netnamecpy); 773 } 774 775 if (isdigit(*id)) { 776 /* We be user. */ 777 __ns_ldap_uid2dn(id, &dn, NULL, &errorp); 778 if (dn == NULL) { 779 fprintf(stderr, "Could not obtain LDAP dn\n"); 780 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 781 program_name); 782 exit(1); 783 } 784 db = "passwd"; 785 filter = (char *)malloc(strlen(id) + 13); 786 if (filter) 787 sprintf(filter, "(uidnumber=%s)", id); 788 else { 789 fprintf(stderr, "Can not allocate filter buffer.\n"); 790 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 791 program_name); 792 exit(1); 793 } 794 } else { 795 /* We be host. */ 796 update4host = TRUE; 797 798 __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp); 799 if (dn == NULL) { 800 fprintf(stderr, "Could not obtain LDAP dn\n"); 801 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 802 program_name); 803 exit(1); 804 } 805 806 db = "hosts"; 807 filter = (char *)malloc(strlen(id) + 6); 808 if (filter) 809 sprintf(filter, "(cn=%s)", id); 810 else { 811 fprintf(stderr, "Can not allocate filter buffer.\n"); 812 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 813 program_name); 814 exit(1); 815 } 816 817 /* Prompt for ldap bind DN for entry udpates */ 818 status = get_ldap_bindDN(&bindDN); 819 820 if (status != PROMPTGET_SUCCESS) { 821 FREE_CREDINFO(bindDN); 822 fprintf(stderr, 823 "Failed to get a valid LDAP bind DN.\n" 824 "%s: key-pair(s) unchanged.\n", 825 program_name); 826 exit(1); 827 } 828 829 /* Prompt for ldap bind password */ 830 status = get_ldap_bindPassword(&bindPasswd); 831 832 if (status != PROMPTGET_SUCCESS) { 833 FREE_CREDINFO(bindPasswd); 834 FREE_CREDINFO(bindDN); 835 836 fprintf(stderr, 837 "Failed to get a valid LDAP bind password." 838 "\n%s: key-pair(s) unchanged.\n", 839 program_name); 840 exit(1); 841 } 842 } 843 844 /* Construct attribute values */ 845 pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3); 846 if (pkeyatval == NULL) { 847 FREE_CREDINFO(bindPasswd); 848 FREE_CREDINFO(bindDN); 849 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 850 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 851 exit(1); 852 } 853 sprintf(pkeyatval, "{%s}%s", mechname, public); 854 ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3); 855 if (ckeyatval == NULL) { 856 FREE_CREDINFO(pkeyatval); 857 FREE_CREDINFO(bindPasswd); 858 FREE_CREDINFO(bindDN); 859 fprintf(stderr, "LDAP memory error (pkeyatval)\n"); 860 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 861 exit(1); 862 } 863 sprintf(ckeyatval, "{%s}%s", mechname, crypt); 864 865 /* Does entry exist? */ 866 if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter, 867 NULL, 0, &res, &errorp, 868 NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) { 869 FREE_CREDINFO(ckeyatval); 870 FREE_CREDINFO(pkeyatval); 871 FREE_CREDINFO(bindPasswd); 872 FREE_CREDINFO(bindDN); 873 fprintf(stderr, "LDAP entry does not exist.\n"); 874 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); 875 exit(1); 876 } 877 878 /* Entry exists, modify attributes for public and secret keys */ 879 880 /* Is there a NisKeyObject in entry? */ 881 if (!ldap_keyobj_exist(&res->entry[0])) { 882 /* Add NisKeyObject objectclass and the keys */ 883 char **newattr; 884 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 885 886 /* set objectclass */ 887 newattr = (char **)calloc(2, sizeof (char *)); 888 newattr[0] = "NisKeyObject"; 889 newattr[1] = NULL; 890 if ((attrs[0] = (ns_ldap_attr_t *)calloc(1, 891 sizeof (ns_ldap_attr_t))) == NULL) { 892 FREE_CREDINFO(ckeyatval); 893 FREE_CREDINFO(pkeyatval); 894 FREE_CREDINFO(bindPasswd); 895 FREE_CREDINFO(bindDN); 896 fprintf(stderr, "Memory allocation failed\n"); 897 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 898 program_name); 899 exit(1); 900 } 901 attrs[0]->attrname = "objectClass"; 902 attrs[0]->attrvalue = newattr; 903 attrs[0]->value_count = 1; 904 905 /* set publickey */ 906 newattr = (char **)calloc(2, sizeof (char *)); 907 newattr[0] = pkeyatval; 908 newattr[1] = NULL; 909 if ((attrs[1] = (ns_ldap_attr_t *)calloc(1, 910 sizeof (ns_ldap_attr_t))) == NULL) { 911 FREE_CREDINFO(ckeyatval); 912 FREE_CREDINFO(pkeyatval); 913 FREE_CREDINFO(bindPasswd); 914 FREE_CREDINFO(bindDN); 915 fprintf(stderr, "Memory allocation failed\n"); 916 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 917 program_name); 918 exit(1); 919 } 920 attrs[1]->attrname = "nisPublicKey"; 921 attrs[1]->attrvalue = newattr; 922 attrs[1]->value_count = 1; 923 924 /* set privatekey */ 925 newattr = (char **)calloc(2, sizeof (char *)); 926 newattr[0] = ckeyatval; 927 newattr[1] = NULL; 928 if ((attrs[2] = (ns_ldap_attr_t *)calloc(1, 929 sizeof (ns_ldap_attr_t))) == NULL) { 930 FREE_CREDINFO(ckeyatval); 931 FREE_CREDINFO(pkeyatval); 932 FREE_CREDINFO(bindPasswd); 933 FREE_CREDINFO(bindDN); 934 fprintf(stderr, "Memory allocation failed\n"); 935 fprintf(stderr, "%s: key-pair(s) unchanged.\n", 936 program_name); 937 exit(1); 938 } 939 attrs[2]->attrname = "nisSecretKey"; 940 attrs[2]->attrvalue = newattr; 941 attrs[2]->value_count = 1; 942 943 /* terminator */ 944 attrs[3] = NULL; 945 946 update_ldap_attr(dn, attrs, passwd, TRUE, update4host, 947 bindDN, bindPasswd); 948 } else { 949 /* object class already exists, replace keys */ 950 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ 951 952 if (!ldap_attr_mod(&res->entry[0], mechname, 953 pkeyatval, &pattrs, 954 ckeyatval, &cattrs)) { 955 FREE_CREDINFO(ckeyatval); 956 FREE_CREDINFO(pkeyatval); 957 FREE_CREDINFO(bindPasswd); 958 FREE_CREDINFO(bindDN); 959 fprintf(stderr, 960 "Could not generate LDAP attribute list.\n"); 961 fprintf(stderr, 962 "%s: key-pair(s) unchanged.\n", program_name); 963 exit(1); 964 } 965 966 attrs[0] = pattrs; 967 attrs[1] = cattrs; 968 attrs[2] = NULL; 969 970 update_ldap_attr(dn, attrs, passwd, FALSE, update4host, 971 bindDN, bindPasswd); 972 } 973 974 FREE_CREDINFO(ckeyatval); 975 FREE_CREDINFO(pkeyatval); 976 FREE_CREDINFO(bindPasswd); 977 FREE_CREDINFO(bindDN); 978 979 return (0); 980 } 981