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 * Copyright 2012 Milan Jurik. All rights reserved. 25 * Copyright (c) 2016 by Delphix. All rights reserved. 26 */ 27 28 /* 29 * ldapclient command. To make (initiailize) or uninitialize a machines as 30 * and LDAP client. This command MUST be run as root (or it will simply exit). 31 * 32 * -I Install. No file_backup/recover for installing only (no doc). 33 * 34 * init Initialze (create) an LDAP client from a profile stored 35 * in a directory-server. 36 * manual Initialze (create) an LDAP client by hand (-file option 37 * reads from file). 38 * mod Modify the LDAP client configuration on this machine by hand. 39 * list List the contents of the LDAP client cache files. 40 * uninit Uninitialize this machine. 41 * 42 * -v Verbose flag. 43 * -q Quiet flag (mutually exclusive with -v). 44 * 45 * -a attrName=attrVal 46 * <attrName> can be one of the following: 47 * 48 * attributeMap 49 * Attribute map. Can be multiple instances of this option. 50 * (no former option) 51 * authenticationMethod 52 * Authentication method (formerly -a) 53 * bindTimeLimit 54 * Bind time limit. (no former option) 55 * certificatePath 56 * Path to certificates used for secure bind (no former option) 57 * credentialLevel 58 * Client credential level (no former option) 59 * defaultServerList 60 * Default server (no former option) Refer to DUA Config 61 * Schema draft. 62 * defaultSearchBase 63 * Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b) 64 * defaultSearchScope 65 * Search scope. (formerly -s) 66 * domainName 67 * Hosts lookup domain (DNS) Ex. eng.sun.com (formerly -d) 68 * followReferrals 69 * Search dereference. followref or noref (default followref) 70 * (formerly -r) 71 * objectclassMap 72 * Objectclass map. Can be multiple instances of this option. 73 * (no former option) 74 * preferredServerList 75 * Server preference list. Comma ',' seperated list of IPaddr. 76 * (formerly -p) 77 * profileName 78 * Profile name to use for init (ldapclient) or 79 * generate (gen_profile). (formerly -P) 80 * profileTTL 81 * Client info TTL. If set to 0 this information will not be 82 * automatically updated by the ldap_cachemgr(8). 83 * (formerly -e) 84 * proxyDN 85 * Binding DN. Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com 86 * (formerly -D) 87 * proxyPassword 88 * Client password not needed for authentication "none". 89 * (formerly -w) 90 * adminDN 91 * Administrator DN for updating naming data. 92 * adminPassword 93 * Administrator password 94 * enableShadowUpdate 95 * Allow Administrator to change shadow data in LDAP 96 * searchTimeLimit 97 * Timeout value. (formerly -o) 98 * serviceSearchDescriptor 99 * Service search scope. (no former option) 100 * serviceAuthenticationMethod 101 * Service authenticaion method (no former option) 102 * serviceCredentialLevel 103 * Service credential level (no former option) 104 * 105 */ 106 107 #include <stdlib.h> 108 #include <stdio.h> 109 #include <unistd.h> 110 #include <errno.h> 111 #include <sys/types.h> 112 #include <time.h> 113 #include <sys/param.h> 114 #include <sys/stat.h> 115 #include <sys/systeminfo.h> 116 #include <fcntl.h> 117 #include <xti.h> 118 #include <strings.h> 119 #include <limits.h> 120 #include <locale.h> 121 #include <syslog.h> 122 #include <libscf.h> 123 #include <assert.h> 124 125 #include "standalone.h" 126 127 #if !defined(TEXT_DOMAIN) 128 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 129 #endif 130 131 /* error codes */ 132 /* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */ 133 #define CLIENT_SUCCESS 0 134 #define CLIENT_ERR_PARSE -1 135 #define CLIENT_ERR_FAIL 1 136 #define CLIENT_ERR_CREDENTIAL 2 137 #define CLIENT_ERR_MEMORY 3 138 #define CLIENT_ERR_RESTORE 4 139 #define CLIENT_ERR_RENAME 5 140 #define CLIENT_ERR_RECOVER 6 141 #define CLIENT_ERR_TIMEDOUT 7 142 #define CLIENT_ERR_MAINTENANCE 8 143 144 /* Reset flag for start_services() */ 145 #define START_INIT 1 146 #define START_RESET 2 147 #define START_UNINIT 3 148 149 /* Reset flag for stop_services() */ 150 #define STATE_NOSAVE 0 151 #define STATE_SAVE 1 152 153 /* files to (possibiliy) restore */ 154 #define LDAP_RESTORE_DIR "/var/ldap/restore" 155 156 #define DOMAINNAME_DIR "/etc" 157 #define DOMAINNAME_FILE "defaultdomain" 158 #define DOMAINNAME DOMAINNAME_DIR "/" DOMAINNAME_FILE 159 #define DOMAINNAME_BACK LDAP_RESTORE_DIR "/" DOMAINNAME_FILE 160 161 #define NSSWITCH_DIR "/etc" 162 #define NSSWITCH_FILE "nsswitch.conf" 163 #define NSSWITCH_CONF NSSWITCH_DIR "/" NSSWITCH_FILE 164 #define NSSWITCH_BACK LDAP_RESTORE_DIR "/" NSSWITCH_FILE 165 #define NSSWITCH_LDAP "/etc/nsswitch.ldap" 166 167 #define YP_BIND_DIR "/var/yp/binding" 168 169 /* Define the service FMRIs */ 170 #define SENDMAIL_FMRI "network/smtp:sendmail" 171 #define NSCD_FMRI "system/name-service-cache:default" 172 #define AUTOFS_FMRI "system/filesystem/autofs:default" 173 #define LDAP_FMRI "network/ldap/client:default" 174 #define YP_FMRI "network/nis/client:default" 175 #define NS_MILESTONE_FMRI "milestone/name-services:default" 176 177 /* Define flags for checking if services were enabled */ 178 #define SENDMAIL_ON 0x1 179 #define NSCD_ON 0x10 180 #define AUTOFS_ON 0x100 181 182 #define CMD_DOMAIN_START "/usr/bin/domainname" 183 184 /* Command to copy files */ 185 #define CMD_CP "/bin/cp -f" 186 #define CMD_MV "/bin/mv -f" 187 #define CMD_RM "/bin/rm -f" 188 189 #define TO_DEV_NULL " >/dev/null 2>&1" 190 191 /* Files that need to be just removed */ 192 #define LDAP_CACHE_LOG "/var/ldap/cachemgr.log" 193 194 /* Output defines to supress if quiet mode set */ 195 #define CLIENT_FPUTS if (!mode_quiet) (void) fputs 196 #define CLIENT_FPRINTF if (!mode_quiet) (void) fprintf 197 #define CLIENT_FPUTC if (!mode_quiet) (void) fputc 198 199 #define restart_service(fmri, waitflag)\ 200 do_service(fmri, waitflag, RESTART_SERVICE,\ 201 SCF_STATE_STRING_ONLINE) 202 #define start_service(fmri, waitflag) \ 203 do_service(fmri, waitflag, START_SERVICE,\ 204 SCF_STATE_STRING_ONLINE) 205 #define disable_service(fmri, waitflag) \ 206 do_service(fmri, waitflag, STOP_SERVICE,\ 207 SCF_STATE_STRING_DISABLED) 208 209 /* 210 * There isn't a domainName defined as a param, so we set a value here 211 * (1001) should be big enough 212 */ 213 #define LOCAL_DOMAIN_P 1001 214 215 #define START_SERVICE 1 216 #define STOP_SERVICE 2 217 #define RESTART_SERVICE 3 218 219 #define DEFAULT_TIMEOUT 60000000 220 221 #define INIT_WAIT_USECS 50000 222 223 /* Used to turn off profile checking */ 224 #define CACHETTL_OFF "0" 225 226 /* Globals */ 227 static char *cmd; 228 229 static char *dname = NULL; 230 static char dname_buf[BUFSIZ]; 231 232 static boolean_t sysid_install = B_FALSE; 233 234 static int mode_verbose = 0; 235 static int mode_quiet = 0; 236 static int gen = 0; 237 238 static int gStartLdap = 0; 239 static int gStartYp = 0; 240 241 static int enableFlag = 0; 242 243 /* multival_t is used to hold params that can have more than one value */ 244 typedef struct { 245 int count; 246 char **optlist; 247 } multival_t; 248 249 static multival_t *multival_new(); 250 static int multival_add(multival_t *list, char *opt); 251 static void multival_free(multival_t *list); 252 253 /* 254 * clientopts_t is used to hold and pass around the param values from 255 * the cmd line 256 */ 257 typedef struct { 258 multival_t *attributeMap; 259 char *authenticationMethod; 260 char *bindTimeLimit; 261 char *certificatePath; 262 char *credentialLevel; 263 char *defaultSearchBase; 264 char *defaultServerList; 265 char *domainName; 266 char *followReferrals; 267 multival_t *objectclassMap; 268 char *preferredServerList; 269 char *profileName; 270 char *profileTTL; 271 char *proxyDN; 272 char *proxyPassword; 273 char *enableShadowUpdate; 274 char *adminDN; 275 char *adminPassword; 276 char *bindDN; 277 char *bindPasswd; 278 char *defaultSearchScope; 279 char *searchTimeLimit; 280 multival_t *serviceAuthenticationMethod; 281 multival_t *serviceCredentialLevel; 282 multival_t *serviceSearchDescriptor; 283 } clientopts_t; 284 285 static clientopts_t *clientopts_new(); 286 static void clientopts_free(clientopts_t *list); 287 288 extern ns_ldap_error_t *__ns_ldap_print_config(int); 289 extern void __ns_ldap_default_config(); 290 extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **); 291 292 /* Function prototypes (these could be static) */ 293 static void usage(void); 294 295 static int credCheck(clientopts_t *arglist); 296 static int adminCredCheck(clientopts_t *arglist); 297 static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal); 298 static int parseParam(char *param, char **paramVal); 299 static void dumpargs(clientopts_t *arglist); 300 static int num_args(clientopts_t *arglist); 301 302 static int file_backup(void); 303 static int recover(int saveState); 304 static int mod_backup(void); 305 static int mod_recover(void); 306 static void mod_cleanup(void); 307 308 static int client_list(clientopts_t *arglist); 309 static int client_manual(clientopts_t *arglist); 310 static int client_mod(clientopts_t *arglist); 311 static int client_uninit(clientopts_t *arglist); 312 static int client_genProfile(clientopts_t *arglist); 313 static int client_init(clientopts_t *arglist); 314 static int file_move(const char *from, const char *to); 315 316 static int start_services(int flag); 317 static int stop_services(int saveState); 318 static boolean_t is_service(const char *fmri, const char *state); 319 static int wait_till(const char *fmri, const char *state, useconds_t max, 320 const char *what, boolean_t check_maint); 321 static int do_service(const char *fmri, boolean_t waitflag, int dowhat, 322 const char *state); 323 static useconds_t get_timeout_value(int dowhat, const char *fmri, 324 useconds_t default_val); 325 326 int 327 main(int argc, char **argv) 328 { 329 char *ret_locale, *ret_textdomain; 330 int retcode; 331 int paramFlag; 332 char *attrVal; 333 int sysinfostatus; 334 clientopts_t *optlist = NULL; 335 int op_manual = 0, op_mod = 0, op_uninit = 0; 336 int op_list = 0, op_init = 0, op_genprofile = 0; 337 extern char *optarg; 338 extern int optind; 339 int option; 340 341 ret_locale = setlocale(LC_ALL, ""); 342 if (ret_locale == NULL) { 343 CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr); 344 } 345 ret_textdomain = textdomain(TEXT_DOMAIN); 346 if (ret_textdomain == NULL) { 347 CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr); 348 } 349 350 openlog("ldapclient", LOG_PID, LOG_USER); 351 352 /* get name that invoked us */ 353 if (cmd = strrchr(argv[0], '/')) 354 ++cmd; 355 else 356 cmd = argv[0]; 357 358 sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ); 359 if (0 < sysinfostatus) 360 dname = &dname_buf[0]; 361 362 optlist = clientopts_new(); 363 if (optlist == NULL) { 364 CLIENT_FPUTS( 365 gettext("Error getting optlist (malloc fail)\n"), 366 stderr); 367 exit(CLIENT_ERR_FAIL); 368 } 369 370 optind = 1; 371 while (optind < argc) { 372 option = getopt(argc, argv, "vqa:ID:w:j:y:z:"); 373 374 switch (option) { 375 case 'v': 376 mode_verbose = 1; 377 break; 378 case 'q': 379 mode_quiet = 1; 380 break; 381 case 'a': 382 attrVal = NULL; 383 paramFlag = parseParam(optarg, &attrVal); 384 if (paramFlag == CLIENT_ERR_PARSE) { 385 CLIENT_FPRINTF(stderr, 386 gettext("Unrecognized " 387 "parameter \"%s\"\n"), 388 optarg); 389 usage(); 390 exit(CLIENT_ERR_FAIL); 391 } 392 if (paramFlag == NS_LDAP_BINDPASSWD_P && 393 optlist->proxyPassword != NULL) { 394 (void) fprintf(stderr, 395 gettext("The -a proxyPassword option is " 396 "mutually exclusive of -y. " 397 "-a proxyPassword is ignored.\n")); 398 break; 399 } 400 if (paramFlag == NS_LDAP_ADMIN_BINDPASSWD_P && 401 optlist->adminPassword != NULL) { 402 (void) fprintf(stderr, 403 gettext("The -a adminPassword option is " 404 "mutually exclusive of -z. " 405 "-a adminPassword is ignored.\n")); 406 break; 407 } 408 retcode = clientSetParam(optlist, paramFlag, attrVal); 409 if (retcode != CLIENT_SUCCESS) { 410 CLIENT_FPRINTF( 411 stderr, 412 gettext("Error (%d) setting " 413 "param \"%s\"\n"), 414 retcode, optarg); 415 usage(); 416 exit(CLIENT_ERR_FAIL); 417 } 418 break; 419 case 'D': 420 optlist->bindDN = strdup(optarg); 421 break; 422 case 'w': 423 if (optlist->bindPasswd != NULL) { 424 CLIENT_FPRINTF(stderr, 425 gettext("The -w option is mutually " 426 "exclusive of -j. -w is ignored.")); 427 break; 428 } 429 430 if (optarg[0] == '-' && optarg[1] == '\0') { 431 /* Ask for a password later */ 432 break; 433 } 434 435 optlist->bindPasswd = strdup(optarg); 436 break; 437 case 'j': 438 if (optlist->bindPasswd != NULL) { 439 (void) fprintf(stderr, 440 gettext("The -w option is mutually " 441 "exclusive of -j. -w is ignored.\n")); 442 free(optlist->bindPasswd); 443 } 444 optlist->bindPasswd = readPwd(optarg); 445 if (optlist->bindPasswd == NULL) { 446 exit(CLIENT_ERR_FAIL); 447 } 448 break; 449 case 'y': 450 if (optlist->proxyPassword != NULL) { 451 (void) fprintf(stderr, 452 gettext("The -a proxyPassword option is " 453 "mutually exclusive of -y. " 454 "-a proxyPassword is ignored.\n")); 455 } 456 optlist->proxyPassword = readPwd(optarg); 457 if (optlist->proxyPassword == NULL) { 458 exit(CLIENT_ERR_FAIL); 459 } 460 break; 461 case 'z': 462 if (optlist->adminPassword != NULL) { 463 (void) fprintf(stderr, 464 gettext("The -a adminPassword option is " 465 "mutually exclusive of -z. " 466 "-a adminPassword is ignored.\n")); 467 } 468 optlist->adminPassword = readPwd(optarg); 469 if (optlist->adminPassword == NULL) { 470 exit(CLIENT_ERR_FAIL); 471 } 472 break; 473 case EOF: 474 if (strcmp(argv[optind], "init") == 0) { 475 op_init = 1; 476 } else if (strcmp(argv[optind], "manual") == 0) { 477 op_manual = 1; 478 } else if (strcmp(argv[optind], "mod") == 0) { 479 op_mod = 1; 480 } else if (strcmp(argv[optind], "list") == 0) { 481 op_list = 1; 482 } else if (strcmp(argv[optind], "uninit") == 0) { 483 op_uninit = 1; 484 } else if (strcmp(argv[optind], "genprofile") == 0) { 485 gen = 1; 486 op_genprofile = 1; 487 } else if (optind == argc-1) { 488 retcode = clientSetParam( 489 optlist, 490 NS_LDAP_SERVERS_P, 491 argv[optind]); /* ipAddr */ 492 if (retcode != CLIENT_SUCCESS) { 493 CLIENT_FPRINTF( 494 stderr, 495 gettext("Error (%d) setting " 496 "serverList param.\n"), 497 retcode); 498 usage(); 499 exit(CLIENT_ERR_FAIL); 500 } 501 } else { 502 CLIENT_FPUTS( 503 gettext("Error parsing " 504 "command line\n"), 505 stderr); 506 usage(); 507 exit(CLIENT_ERR_FAIL); 508 } 509 optind++; /* get past the verb and keep trying */ 510 break; 511 /* Backwards compatibility to support system install */ 512 case 'I': 513 sysid_install = B_TRUE; 514 op_init = 1; 515 mode_quiet = 1; 516 break; 517 case '?': 518 usage(); 519 CLIENT_FPUTS(gettext("\nOr\n\n"), stderr); 520 gen = 1; 521 usage(); 522 exit(CLIENT_ERR_FAIL); 523 break; 524 } 525 526 } 527 528 if ((getuid() != 0) && (!op_genprofile)) { 529 (void) puts( 530 "You must be root (SuperUser) to run this command."); 531 usage(); 532 exit(CLIENT_ERR_FAIL); 533 } 534 535 /* 536 * All command line arguments are finished being parsed now 537 */ 538 539 /* *** Do semantic checking here *** */ 540 541 /* if gen and no no searchBase then err */ 542 if (gen && !optlist->defaultSearchBase) { 543 CLIENT_FPUTS( 544 gettext("ldapclient: Missing required attrName " 545 "defaultSearchBase\n"), 546 stderr); 547 usage(); 548 clientopts_free(optlist); 549 exit(CLIENT_ERR_FAIL); 550 } 551 552 /* 553 * if init or manual, and if adminDN is specified then enableShadowUpdate 554 * must be set to TRUE. 555 */ 556 if ((op_init || op_manual) && 557 (!optlist->enableShadowUpdate || 558 strcasecmp(optlist->enableShadowUpdate, "TRUE") != 0) && 559 (optlist->adminDN || optlist->adminPassword)) { 560 CLIENT_FPUTS( 561 gettext("ldapclient: adminDN and adminPassword must not " 562 "be specified if enableShadowUpdate is not set to TRUE \n"), 563 stderr); 564 usage(); 565 clientopts_free(optlist); 566 exit(CLIENT_ERR_FAIL); 567 } 568 569 /* Only one verb can be specified */ 570 if ((op_init + op_manual + op_mod + op_uninit + 571 op_list + op_genprofile) != 1) { 572 usage(); 573 clientopts_free(optlist); 574 exit(CLIENT_ERR_FAIL); 575 } 576 577 /* *** We passed semantic checking, so now do the operation *** */ 578 579 if (mode_verbose) { 580 CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr); 581 dumpargs(optlist); 582 } 583 584 585 /* handle "ldapclient list" here. err checking done in func */ 586 if (op_list) { 587 if (mode_verbose) 588 CLIENT_FPUTS( 589 gettext("Handling list option\n"), 590 stderr); 591 retcode = client_list(optlist); 592 } 593 594 /* handle "ldapclient uninit" here */ 595 if (op_uninit) { 596 if (mode_verbose) 597 CLIENT_FPUTS( 598 gettext("Handling uninit option\n"), 599 stderr); 600 retcode = client_uninit(optlist); 601 } 602 603 /* handle "ldapclient init" (profile) */ 604 if (op_init) { 605 if (mode_verbose) 606 CLIENT_FPUTS( 607 gettext("Handling init option\n"), 608 stderr); 609 retcode = client_init(optlist); 610 } 611 612 /* handle "genprofile" here */ 613 if (op_genprofile) { 614 if (mode_verbose) 615 CLIENT_FPUTS( 616 gettext("Handling genProfile\n"), 617 stderr); 618 retcode = client_genProfile(optlist); 619 } 620 621 /* handle "ldapclient manual" here */ 622 if (op_manual) { 623 if (mode_verbose) 624 CLIENT_FPUTS( 625 gettext("Handling manual option\n"), 626 stderr); 627 retcode = client_manual(optlist); 628 } 629 630 /* handle "ldapclient mod" here */ 631 if (op_mod) { 632 if (mode_verbose) 633 CLIENT_FPUTS( 634 gettext("Handling mod option\n"), 635 stderr); 636 retcode = client_mod(optlist); 637 } 638 639 clientopts_free(optlist); 640 if ((retcode == CLIENT_SUCCESS) || 641 (retcode == CLIENT_ERR_FAIL) || 642 (retcode == CLIENT_ERR_CREDENTIAL)) 643 return (retcode); 644 else 645 return (CLIENT_ERR_FAIL); 646 } 647 648 static int 649 client_list(clientopts_t *arglist) 650 { 651 ns_ldap_error_t *errorp; 652 int retcode = CLIENT_SUCCESS; 653 654 if (num_args(arglist) > 0) { 655 CLIENT_FPUTS( 656 gettext("No args supported with \"list\" option\n"), 657 stderr); 658 usage(); 659 return (CLIENT_ERR_FAIL); /* exit code here ? */ 660 } 661 if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) { 662 retcode = CLIENT_ERR_FAIL; 663 CLIENT_FPUTS( 664 gettext("Cannot get print configuration\n"), 665 stderr); 666 CLIENT_FPUTS(errorp->message, stderr); 667 (void) __ns_ldap_freeError(&errorp); 668 CLIENT_FPUTC('\n', stderr); 669 } 670 671 return (retcode); 672 } 673 674 static int 675 client_uninit(clientopts_t *arglist) 676 { 677 int retcode = CLIENT_SUCCESS; 678 ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE; 679 680 if (mode_verbose) { 681 CLIENT_FPUTS( 682 gettext("Restoring machine to previous " 683 "configuration state\n"), 684 stderr); 685 } 686 687 if (num_args(arglist) > 0) { 688 CLIENT_FPUTS( 689 gettext("No args supported with \"uninit\" option\n"), 690 stderr); 691 usage(); 692 return (CLIENT_ERR_FAIL); 693 } 694 695 (void) __ns_ldap_self_gssapi_config(&config); 696 697 retcode = stop_services(STATE_SAVE); 698 699 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 700 (void) system("/usr/sbin/cryptoadm enable metaslot"); 701 702 if (retcode != CLIENT_SUCCESS) { 703 CLIENT_FPUTS( 704 gettext("Errors stopping network services.\n"), stderr); 705 /* restart whatever services we can */ 706 (void) start_services(START_RESET); 707 return (CLIENT_ERR_FAIL); 708 } 709 710 retcode = recover(STATE_SAVE); 711 if (retcode != CLIENT_SUCCESS) { 712 CLIENT_FPUTS( 713 gettext("Cannot recover the configuration on " 714 "this machine.\n"), 715 stderr); 716 (void) start_services(START_RESET); 717 } else { 718 retcode = start_services(START_UNINIT); 719 if (retcode != CLIENT_SUCCESS) { 720 CLIENT_FPUTS( 721 gettext("Config restored but problems " 722 "encountered resetting network " 723 "services.\n"), 724 stderr); 725 } 726 } 727 728 if (retcode == CLIENT_SUCCESS) { 729 CLIENT_FPUTS( 730 gettext("System successfully recovered\n"), 731 stderr); 732 } 733 734 return (retcode); 735 } 736 737 /* 738 * The following macro is used to do a __ns_ldap_setParam(). 739 * On every call, the return code is checked, and if there was 740 * a problem then the error message is printed, the ldaperr 741 * is freed and we return from the function with the offending 742 * error return code. This macro keeps us from having to 743 * repeat this code for every call to setParam as was done 744 * in the previous incarnation of ldapclient. 745 * 746 * assumes a "retcode" variable is available for status 747 */ 748 #define LDAP_SET_PARAM(argval, argdef) \ 749 retcode = 0; \ 750 if (NULL != argval) { \ 751 ns_ldap_error_t *ldaperr; \ 752 retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr); \ 753 if (retcode != NS_LDAP_SUCCESS) { \ 754 if (NULL != ldaperr) { \ 755 CLIENT_FPUTS(ldaperr->message, stderr); \ 756 CLIENT_FPUTC('\n', stderr); \ 757 (void) __ns_ldap_freeError(&ldaperr); \ 758 } \ 759 return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS); \ 760 } \ 761 } 762 763 /* 764 * The following macro is used to check if an arg has already been set 765 * and issues an error message, a usage message and then returns an error. 766 * This was made into a macro to avoid the duplication of this code many 767 * times in the function below. 768 */ 769 #define LDAP_CHECK_INVALID(arg, param) \ 770 if (arg) { \ 771 CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \ 772 "specified\n"), param); \ 773 usage(); \ 774 return (CLIENT_ERR_FAIL); \ 775 } 776 777 static int 778 client_manual(clientopts_t *arglist) 779 { 780 int counter; 781 int domain_fp; 782 ns_ldap_error_t *errorp; 783 int ret_copy; 784 int reset_ret; 785 int retcode = CLIENT_SUCCESS; 786 787 if (dname == NULL) { 788 CLIENT_FPUTS( 789 gettext("Manual failed: System domain not set and " 790 "no domainName specified.\n"), 791 stderr); 792 return (CLIENT_ERR_FAIL); 793 } 794 795 if (arglist->defaultSearchBase == NULL) { 796 CLIENT_FPUTS( 797 gettext("Manual failed: Missing required " 798 "defaultSearchBase attribute.\n"), 799 stderr); 800 return (CLIENT_ERR_FAIL); 801 } 802 803 if ((arglist->defaultServerList == NULL) && 804 (arglist->preferredServerList == NULL)) { 805 CLIENT_FPUTS( 806 gettext("Manual failed: Missing required " 807 "defaultServerList or preferredServerList " 808 "attribute.\n"), 809 stderr); 810 return (CLIENT_ERR_FAIL); 811 } 812 813 if (arglist->profileTTL != NULL) { 814 CLIENT_FPUTS( 815 gettext("Manual aborted: profileTTL is not supported " 816 "in manual mode.\n"), 817 stderr); 818 return (CLIENT_ERR_FAIL); 819 } 820 821 if (arglist->profileName != NULL) { 822 CLIENT_FPUTS( 823 gettext("Manual aborted: profileName is not supported " 824 "in manual mode.\n"), 825 stderr); 826 return (CLIENT_ERR_FAIL); 827 } 828 829 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN"); 830 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password"); 831 832 __ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */ 833 __ns_ldap_default_config(); 834 835 /* Set version to latest (not version 1) */ 836 LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P); 837 838 /* Set profileTTL to 0 since NO profile on manual */ 839 LDAP_SET_PARAM(CACHETTL_OFF, NS_LDAP_CACHETTL_P); 840 841 /* Set additional valid params from command line */ 842 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P); 843 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P); 844 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P); 845 LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P); 846 LDAP_SET_PARAM(arglist->enableShadowUpdate, 847 NS_LDAP_ENABLE_SHADOW_UPDATE_P); 848 LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P); 849 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P); 850 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P); 851 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P); 852 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P); 853 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P); 854 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P); 855 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P); 856 LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P); 857 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P); 858 LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P); 859 860 for (counter = 0; 861 counter < arglist->serviceAuthenticationMethod->count; 862 counter++) { 863 864 LDAP_SET_PARAM( 865 arglist->serviceAuthenticationMethod->optlist[counter], 866 NS_LDAP_SERVICE_AUTH_METHOD_P); 867 } 868 for (counter = 0; 869 counter < arglist->serviceCredentialLevel->count; 870 counter++) { 871 872 LDAP_SET_PARAM( 873 arglist->serviceCredentialLevel->optlist[counter], 874 NS_LDAP_SERVICE_CRED_LEVEL_P); 875 } 876 for (counter = 0; 877 counter < arglist->objectclassMap->count; 878 counter++) { 879 880 LDAP_SET_PARAM(arglist->objectclassMap->optlist[counter], 881 NS_LDAP_OBJECTCLASSMAP_P); 882 } 883 for (counter = 0; counter < arglist->attributeMap->count; counter++) { 884 LDAP_SET_PARAM(arglist->attributeMap->optlist[counter], 885 NS_LDAP_ATTRIBUTEMAP_P); 886 } 887 for (counter = 0; 888 counter < arglist->serviceSearchDescriptor->count; 889 counter++) { 890 891 LDAP_SET_PARAM( 892 arglist->serviceSearchDescriptor->optlist[counter], 893 NS_LDAP_SERVICE_SEARCH_DESC_P); 894 } 895 896 retcode = credCheck(arglist); 897 if (retcode == CLIENT_SUCCESS) 898 retcode = adminCredCheck(arglist); 899 if (retcode != CLIENT_SUCCESS) { 900 CLIENT_FPUTS( 901 gettext("Error in setting up credentials\n"), 902 stderr); 903 return (retcode); 904 } 905 906 if (mode_verbose) 907 CLIENT_FPUTS( 908 gettext("About to modify this machines " 909 "configuration by writing the files\n"), 910 stderr); 911 912 /* get ready to start playing with files */ 913 retcode = stop_services(STATE_SAVE); 914 if (retcode != CLIENT_SUCCESS) { 915 CLIENT_FPUTS( 916 gettext("Errors stopping network services.\n"), stderr); 917 return (CLIENT_ERR_FAIL); 918 } 919 920 /* Save orig versions of files */ 921 retcode = file_backup(); 922 if (retcode == CLIENT_ERR_RESTORE) { 923 CLIENT_FPUTS( 924 gettext("System not in state to enable ldap client.\n"), 925 stderr); 926 927 reset_ret = start_services(START_RESET); 928 if (reset_ret != CLIENT_SUCCESS) { 929 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 930 "starting services during reset\n"), 931 reset_ret); 932 } 933 return (retcode); 934 } else if (retcode != CLIENT_SUCCESS) { 935 CLIENT_FPUTS( 936 gettext("Save of system configuration failed! " 937 "Attempting recovery.\n"), 938 stderr); 939 retcode = recover(STATE_NOSAVE); 940 if (retcode != CLIENT_SUCCESS) { 941 CLIENT_FPUTS( 942 gettext("Recovery of systems configuration " 943 "failed. Manual intervention of " 944 "config files is required.\n"), 945 stderr); 946 return (retcode); 947 } 948 949 reset_ret = start_services(START_RESET); 950 if (reset_ret != CLIENT_SUCCESS) { 951 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 952 "starting services during reset\n"), 953 reset_ret); 954 } 955 956 return (retcode); 957 } 958 959 /* Dump new files */ 960 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE); 961 if (errorp != NULL) { 962 CLIENT_FPRINTF(stderr, 963 gettext("%s manual: errorp is not NULL; %s\n"), 964 cmd, errorp->message); 965 retcode = recover(STATE_NOSAVE); 966 if (retcode != CLIENT_SUCCESS) { 967 CLIENT_FPUTS( 968 gettext("Recovery of systems configuration " 969 "failed. Manual intervention of " 970 "config files is required.\n"), 971 stderr); 972 return (retcode); 973 } 974 reset_ret = start_services(START_RESET); 975 if (reset_ret != CLIENT_SUCCESS) { 976 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 977 "starting services during reset\n"), 978 reset_ret); 979 } 980 (void) __ns_ldap_freeError(&errorp); 981 return (CLIENT_ERR_FAIL); 982 } 983 984 /* if (credargs(arglist)) */ 985 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE); 986 if (errorp != NULL) { 987 CLIENT_FPRINTF(stderr, 988 gettext("%s init: errorp is not NULL; %s\n"), 989 cmd, errorp->message); 990 retcode = recover(STATE_NOSAVE); 991 if (retcode != CLIENT_SUCCESS) { 992 CLIENT_FPUTS( 993 gettext("Recovery of systems configuration " 994 "failed. Manual intervention of " 995 "config files is required.\n"), 996 stderr); 997 return (retcode); 998 } 999 reset_ret = start_services(START_RESET); 1000 if (reset_ret != CLIENT_SUCCESS) { 1001 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1002 "starting services during reset\n"), 1003 reset_ret); 1004 } 1005 (void) __ns_ldap_freeError(&errorp); 1006 return (CLIENT_ERR_FAIL); 1007 } 1008 1009 ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF); 1010 if (ret_copy != 0) { 1011 CLIENT_FPRINTF(stderr, 1012 gettext("Error %d copying (%s) -> (%s)\n"), 1013 ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF); 1014 retcode = recover(STATE_NOSAVE); 1015 if (retcode != CLIENT_SUCCESS) { 1016 CLIENT_FPUTS( 1017 gettext("Recovery of systems configuration " 1018 "failed. Manual intervention of " 1019 "config files is required.\n"), 1020 stderr); 1021 } 1022 reset_ret = start_services(START_RESET); 1023 if (reset_ret != CLIENT_SUCCESS) { 1024 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1025 "starting services during reset\n"), 1026 reset_ret); 1027 } 1028 return (CLIENT_ERR_FAIL); 1029 } 1030 1031 if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC, 1032 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */ 1033 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME); 1034 retcode = recover(STATE_NOSAVE); 1035 if (retcode != CLIENT_SUCCESS) { 1036 CLIENT_FPUTS( 1037 gettext("Recovery of systems configuration " 1038 "failed. Manual intervention of " 1039 "config files is required.\n"), 1040 stderr); 1041 return (CLIENT_ERR_FAIL); 1042 } 1043 reset_ret = start_services(START_RESET); 1044 if (reset_ret != CLIENT_SUCCESS) { 1045 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1046 "starting services during reset\n"), 1047 reset_ret); 1048 } 1049 return (CLIENT_ERR_FAIL); 1050 } 1051 (void) write(domain_fp, dname, strlen(dname)); 1052 (void) write(domain_fp, "\n", 1); 1053 (void) close(domain_fp); 1054 1055 retcode = start_services(START_INIT); 1056 1057 if (retcode == CLIENT_SUCCESS) { 1058 CLIENT_FPUTS(gettext("System successfully configured\n"), 1059 stderr); 1060 } else { 1061 CLIENT_FPUTS(gettext("Error resetting system.\n" 1062 "Recovering old system settings.\n"), stderr), 1063 1064 /* stop any started services for recover */ 1065 /* don't stomp on history of saved services state */ 1066 reset_ret = stop_services(STATE_NOSAVE); 1067 if (reset_ret != CLIENT_SUCCESS) { 1068 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1069 "stopping services during reset\n"), 1070 reset_ret); 1071 /* Coninue and try to recover what we can */ 1072 } 1073 reset_ret = recover(STATE_NOSAVE); 1074 if (reset_ret != CLIENT_SUCCESS) { 1075 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1076 "recovering service files during " 1077 "reset\n"), reset_ret); 1078 /* Continue and start what we can */ 1079 } 1080 reset_ret = start_services(START_RESET); 1081 if (reset_ret != CLIENT_SUCCESS) { 1082 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1083 "starting services during reset\n"), 1084 reset_ret); 1085 } 1086 } 1087 1088 return (retcode); 1089 } 1090 1091 static int 1092 client_mod(clientopts_t *arglist) 1093 { 1094 int counter; 1095 int domain_fp; 1096 ns_ldap_error_t *errorp; 1097 int reset_ret; 1098 int retcode = CLIENT_SUCCESS; 1099 1100 __ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */ 1101 if ((errorp = __ns_ldap_LoadConfiguration()) != NULL) { 1102 CLIENT_FPUTS(gettext("Cannot get load configuration\n"), 1103 stderr); 1104 CLIENT_FPUTS(errorp->message, stderr); 1105 CLIENT_FPUTC('\n', stderr); 1106 (void) __ns_ldap_freeError(&errorp); 1107 return (CLIENT_ERR_FAIL); 1108 } 1109 1110 if (arglist->profileTTL != NULL) { 1111 CLIENT_FPUTS( 1112 gettext("Mod aborted: profileTTL modification is " 1113 "not allowed in mod mode.\n"), 1114 stderr); 1115 return (CLIENT_ERR_FAIL); 1116 } 1117 1118 if (arglist->profileName != NULL) { 1119 CLIENT_FPUTS( 1120 gettext("Mod aborted: profileName modification is " 1121 "not allowed. If you want to use profiles " 1122 "generate one with genProfile and load it " 1123 "on the server with ldapadd.\n"), 1124 stderr); 1125 return (CLIENT_ERR_FAIL); 1126 } 1127 1128 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN"); 1129 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password"); 1130 1131 /* Set additional valid params from command line */ 1132 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P); 1133 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P); 1134 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P); 1135 LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P); 1136 LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P); 1137 LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P); 1138 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P); 1139 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P); 1140 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P); 1141 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P); 1142 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P); 1143 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P); 1144 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P); 1145 LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P); 1146 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P); 1147 LDAP_SET_PARAM(arglist->enableShadowUpdate, 1148 NS_LDAP_ENABLE_SHADOW_UPDATE_P); 1149 LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P); 1150 1151 for (counter = 0; 1152 counter < arglist->serviceAuthenticationMethod->count; 1153 counter++) { 1154 1155 LDAP_SET_PARAM( 1156 arglist->serviceAuthenticationMethod->optlist[counter], 1157 NS_LDAP_SERVICE_AUTH_METHOD_P); 1158 } 1159 for (counter = 0; 1160 counter < arglist->serviceCredentialLevel->count; 1161 counter++) { 1162 1163 LDAP_SET_PARAM( 1164 arglist->serviceCredentialLevel->optlist[counter], 1165 NS_LDAP_SERVICE_CRED_LEVEL_P); 1166 } 1167 for (counter = 0; 1168 counter < arglist->objectclassMap->count; 1169 counter++) { 1170 1171 LDAP_SET_PARAM( 1172 arglist->objectclassMap->optlist[counter], 1173 NS_LDAP_OBJECTCLASSMAP_P); 1174 } 1175 for (counter = 0; 1176 counter < arglist->attributeMap->count; 1177 counter++) { 1178 1179 LDAP_SET_PARAM( 1180 arglist->attributeMap->optlist[counter], 1181 NS_LDAP_ATTRIBUTEMAP_P); 1182 } 1183 for (counter = 0; 1184 counter < arglist->serviceSearchDescriptor->count; 1185 counter++) { 1186 1187 LDAP_SET_PARAM( 1188 arglist->serviceSearchDescriptor->optlist[counter], 1189 NS_LDAP_SERVICE_SEARCH_DESC_P); 1190 } 1191 1192 retcode = credCheck(arglist); 1193 if (retcode == CLIENT_SUCCESS) 1194 retcode = adminCredCheck(arglist); 1195 if (retcode != CLIENT_SUCCESS) { 1196 CLIENT_FPUTS( 1197 gettext("Error in setting up credentials\n"), 1198 stderr); 1199 return (retcode); 1200 } 1201 1202 if (mode_verbose) 1203 CLIENT_FPUTS( 1204 gettext("About to modify this machines configuration " 1205 "by writing the files\n"), 1206 stderr); 1207 1208 /* get ready to start playing with files */ 1209 retcode = stop_services(STATE_SAVE); 1210 if (retcode != CLIENT_SUCCESS) { 1211 CLIENT_FPUTS( 1212 gettext("Errors stopping network services.\n"), stderr); 1213 return (CLIENT_ERR_FAIL); 1214 } 1215 1216 /* Temporarily save orig versions of files */ 1217 retcode = mod_backup(); 1218 if (retcode != CLIENT_SUCCESS) { 1219 CLIENT_FPUTS( 1220 gettext("Unable to backup the ldap client files!\n"), 1221 stderr); 1222 1223 return (retcode); 1224 1225 } 1226 1227 /* Dump new files */ 1228 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE); 1229 if (errorp != NULL) { 1230 CLIENT_FPRINTF(stderr, 1231 gettext("%s mod: errorp is not NULL; %s\n"), 1232 cmd, errorp->message); 1233 retcode = mod_recover(); 1234 if (retcode != CLIENT_SUCCESS) { 1235 CLIENT_FPUTS( 1236 gettext("Recovery of systems configuration " 1237 "failed. Manual intervention of " 1238 "config files is required.\n"), 1239 stderr); 1240 } 1241 (void) __ns_ldap_freeError(&errorp); 1242 reset_ret = start_services(START_RESET); 1243 if (reset_ret != CLIENT_SUCCESS) { 1244 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1245 "starting services during reset\n"), 1246 reset_ret); 1247 } 1248 return (CLIENT_ERR_FAIL); 1249 } 1250 1251 /* if (credargs(arglist)) */ 1252 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE); 1253 if (errorp != NULL) { 1254 CLIENT_FPRINTF(stderr, 1255 gettext("%s mod: errorp is not NULL; %s\n"), 1256 cmd, errorp->message); 1257 retcode = mod_recover(); 1258 if (retcode != CLIENT_SUCCESS) { 1259 CLIENT_FPUTS( 1260 gettext("Recovery of systems configuration " 1261 "failed. Manual intervention of " 1262 "config files is required.\n"), 1263 stderr); 1264 } 1265 (void) __ns_ldap_freeError(&errorp); 1266 reset_ret = start_services(START_RESET); 1267 if (reset_ret != CLIENT_SUCCESS) { 1268 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1269 "starting services during reset\n"), 1270 reset_ret); 1271 } 1272 return (CLIENT_ERR_FAIL); 1273 } 1274 1275 if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC, 1276 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */ 1277 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME); 1278 retcode = mod_recover(); 1279 if (retcode != CLIENT_SUCCESS) { 1280 CLIENT_FPUTS( 1281 gettext("Recovery of systems configuration " 1282 "failed! Machine needs to be " 1283 "fixed!\n"), 1284 stderr); 1285 } 1286 reset_ret = start_services(START_RESET); 1287 if (reset_ret != CLIENT_SUCCESS) { 1288 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1289 "starting services during reset\n"), 1290 reset_ret); 1291 } 1292 return (CLIENT_ERR_FAIL); 1293 } 1294 (void) write(domain_fp, dname, strlen(dname)); 1295 (void) write(domain_fp, "\n", 1); 1296 (void) close(domain_fp); 1297 1298 retcode = start_services(START_INIT); 1299 1300 if (retcode == CLIENT_SUCCESS) { 1301 CLIENT_FPUTS(gettext("System successfully configured\n"), 1302 stderr); 1303 } else { 1304 CLIENT_FPUTS(gettext("Error resetting system.\n" 1305 "Recovering old system settings.\n"), stderr), 1306 1307 /* stop any started services for recover */ 1308 /* don't stomp on history of saved services state */ 1309 reset_ret = stop_services(STATE_NOSAVE); 1310 if (reset_ret != CLIENT_SUCCESS) { 1311 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1312 "stopping services during reset\n"), 1313 reset_ret); 1314 /* Coninue and try to recover what we can */ 1315 } 1316 reset_ret = mod_recover(); 1317 if (reset_ret != CLIENT_SUCCESS) { 1318 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1319 "recovering service files during " 1320 "reset\n"), reset_ret); 1321 /* Continue and start what we can */ 1322 } 1323 reset_ret = start_services(START_RESET); 1324 if (reset_ret != CLIENT_SUCCESS) { 1325 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1326 "starting services during reset\n"), 1327 reset_ret); 1328 } 1329 } 1330 1331 /* Cleanup temporary files created by mod_backup() */ 1332 mod_cleanup(); 1333 1334 return (retcode); 1335 } 1336 1337 1338 static int 1339 client_genProfile(clientopts_t *arglist) 1340 { 1341 int counter; 1342 int retcode; /* required for LDAP_SET_PARAM macro */ 1343 ns_ldap_error_t *errorp; 1344 1345 if (mode_verbose) 1346 CLIENT_FPUTS(gettext("About to generate a profile\n"), stderr); 1347 1348 /* *** Check for invalid args *** */ 1349 LDAP_CHECK_INVALID(arglist->proxyDN, "proxyDN"); 1350 LDAP_CHECK_INVALID(arglist->proxyPassword, "proxyPassword"); 1351 LDAP_CHECK_INVALID(arglist->enableShadowUpdate, 1352 "enableShadowUpdate"); 1353 LDAP_CHECK_INVALID(arglist->adminDN, "adminDN"); 1354 LDAP_CHECK_INVALID(arglist->adminPassword, "adminPassword"); 1355 LDAP_CHECK_INVALID(arglist->certificatePath, "certificatePath"); 1356 LDAP_CHECK_INVALID(arglist->domainName, "domainName"); 1357 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN"); 1358 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password"); 1359 /* *** End check for invalid args *** */ 1360 1361 if (arglist->profileName == NULL) { 1362 if (mode_verbose) 1363 CLIENT_FPUTS( 1364 gettext("No profile specified. " 1365 "Using \"default\"\n"), 1366 stderr); 1367 arglist->profileName = "default"; 1368 } 1369 1370 __ns_ldap_setServer(TRUE); 1371 __ns_ldap_default_config(); 1372 1373 /* Set version to latest (not version 1) */ 1374 LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P); 1375 1376 /* Set additional valid params from command line */ 1377 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P); 1378 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P); 1379 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P); 1380 LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P); 1381 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P); 1382 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P); 1383 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P); 1384 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P); 1385 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P); 1386 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P); 1387 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P); 1388 1389 for (counter = 0; 1390 counter < arglist->serviceAuthenticationMethod->count; 1391 counter++) { 1392 1393 LDAP_SET_PARAM( 1394 arglist->serviceAuthenticationMethod->optlist[counter], 1395 NS_LDAP_SERVICE_AUTH_METHOD_P); 1396 } 1397 for (counter = 0; 1398 counter < arglist->serviceCredentialLevel->count; 1399 counter++) { 1400 1401 LDAP_SET_PARAM( 1402 arglist->serviceCredentialLevel->optlist[counter], 1403 NS_LDAP_SERVICE_CRED_LEVEL_P); 1404 } 1405 for (counter = 0; 1406 counter < arglist->objectclassMap->count; 1407 counter++) { 1408 1409 LDAP_SET_PARAM( 1410 arglist->objectclassMap->optlist[counter], 1411 NS_LDAP_OBJECTCLASSMAP_P); 1412 } 1413 for (counter = 0; 1414 counter < arglist->attributeMap->count; 1415 counter++) { 1416 1417 LDAP_SET_PARAM( 1418 arglist->attributeMap->optlist[counter], 1419 NS_LDAP_ATTRIBUTEMAP_P); 1420 } 1421 for (counter = 0; 1422 counter < arglist->serviceSearchDescriptor->count; 1423 counter++) { 1424 1425 LDAP_SET_PARAM( 1426 arglist->serviceSearchDescriptor->optlist[counter], 1427 NS_LDAP_SERVICE_SEARCH_DESC_P); 1428 } 1429 1430 errorp = __ns_ldap_DumpLdif(NULL); 1431 if (errorp != NULL) { 1432 CLIENT_FPUTS(errorp->message, stderr); 1433 CLIENT_FPUTC('\n', stderr); 1434 (void) __ns_ldap_freeError(&errorp); 1435 return (CLIENT_ERR_FAIL); 1436 } 1437 1438 return (CLIENT_SUCCESS); 1439 } 1440 1441 /* INET6_ADDRSTRLEN + ":" + <5-digit port> + some round-up */ 1442 #define MAX_HOSTADDR_LEN (INET6_ADDRSTRLEN + 6 + 12) 1443 1444 static int 1445 client_init(clientopts_t *arglist) 1446 { 1447 int profile_fp; 1448 int retcode = CLIENT_SUCCESS; 1449 ns_ldap_error_t *errorp; 1450 int reset_ret; 1451 int ret_copy; 1452 ns_standalone_conf_t cfg = standaloneDefaults; 1453 ns_auth_t auth = {NS_LDAP_AUTH_NONE, 1454 NS_LDAP_TLS_NONE, 1455 NS_LDAP_SASL_NONE, 1456 NS_LDAP_SASLOPT_NONE}; 1457 char peer[MAX_HOSTADDR_LEN]; 1458 ns_auth_t **authMethod; 1459 int **credLevel, i; 1460 char *cred; 1461 1462 if (mode_verbose) 1463 CLIENT_FPUTS( 1464 gettext("About to configure machine by downloading " 1465 "a profile\n"), 1466 stderr); 1467 1468 if (dname == NULL) { 1469 CLIENT_FPUTS( 1470 gettext("Init failed: System domain not set and " 1471 "no domainName specified.\n"), 1472 stderr); 1473 return (CLIENT_ERR_FAIL); 1474 } 1475 1476 if (!arglist->defaultServerList) { 1477 CLIENT_FPUTS(gettext("Missing LDAP server address\n"), stderr); 1478 return (CLIENT_ERR_FAIL); 1479 } 1480 1481 /* *** Check for invalid args *** */ 1482 LDAP_CHECK_INVALID(arglist->defaultSearchBase, 1483 "defaultSearchBase"); 1484 LDAP_CHECK_INVALID(arglist->profileTTL, 1485 "profileTTL"); 1486 LDAP_CHECK_INVALID(arglist->searchTimeLimit, 1487 "searchTimeLimit"); 1488 LDAP_CHECK_INVALID(arglist->preferredServerList, 1489 "preferredServerList"); 1490 LDAP_CHECK_INVALID(arglist->followReferrals, 1491 "followReferrals"); 1492 LDAP_CHECK_INVALID(arglist->defaultSearchScope, 1493 "defaultSearchScope"); 1494 LDAP_CHECK_INVALID(arglist->bindTimeLimit, 1495 "bindTimeLimit"); 1496 1497 LDAP_CHECK_INVALID(arglist->objectclassMap->count, 1498 "objectclassMap"); 1499 LDAP_CHECK_INVALID(arglist->attributeMap->count, 1500 "attributeMap"); 1501 LDAP_CHECK_INVALID(arglist->serviceAuthenticationMethod->count, 1502 "serviceAuthenticationMethod"); 1503 LDAP_CHECK_INVALID(arglist->serviceCredentialLevel->count, 1504 "serviceCredentialLevel"); 1505 LDAP_CHECK_INVALID(arglist->serviceSearchDescriptor->count, 1506 "serviceSearchDescriptor"); 1507 /* *** End check for invalid args *** */ 1508 1509 if (arglist->profileName == NULL) { 1510 if (mode_verbose) 1511 CLIENT_FPUTS( 1512 gettext("No profile specified. " 1513 "Using \"default\"\n"), 1514 stderr); 1515 arglist->profileName = "default"; 1516 } 1517 1518 (void) strncpy(peer, arglist->defaultServerList, MAX_HOSTADDR_LEN - 1); 1519 if (separatePort(peer, &cfg.SA_SERVER, &cfg.SA_PORT) > 0) { 1520 return (CLIENT_ERR_FAIL); 1521 } 1522 1523 if (arglist->bindDN != NULL) { 1524 cfg.SA_CRED = "proxy"; 1525 /* 1526 * We don't want to force users to always specify authentication 1527 * method when we can infer it. If users want SSL, they would 1528 * have to specify appropriate -a though. 1529 */ 1530 auth.type = NS_LDAP_AUTH_SIMPLE; 1531 if (arglist->bindPasswd == NULL) { 1532 arglist->bindPasswd = 1533 getpassphrase("Bind Password:"); 1534 if (arglist->bindPasswd == NULL) { 1535 CLIENT_FPUTS(gettext("Get password failed\n"), 1536 stderr); 1537 1538 if (gStartLdap == START_RESET) 1539 (void) start_service(LDAP_FMRI, B_TRUE); 1540 1541 return (CLIENT_ERR_CREDENTIAL); 1542 } 1543 } 1544 } 1545 cfg.SA_BIND_DN = arglist->bindDN; 1546 cfg.SA_BIND_PWD = arglist->bindPasswd; 1547 1548 if (arglist->authenticationMethod != NULL) { 1549 if (__ns_ldap_initAuth(arglist->authenticationMethod, 1550 &auth, &errorp) != NS_LDAP_SUCCESS) { 1551 if (errorp != NULL) { 1552 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1553 (void) __ns_ldap_freeError(&errorp); 1554 } 1555 1556 if (gStartLdap == START_RESET) 1557 (void) start_service(LDAP_FMRI, B_TRUE); 1558 1559 return (CLIENT_ERR_FAIL); 1560 } 1561 cfg.SA_AUTH = &auth; 1562 } 1563 cfg.SA_CRED = arglist->credentialLevel; 1564 1565 cfg.SA_DOMAIN = arglist->domainName; 1566 cfg.SA_PROFILE_NAME = arglist->profileName; 1567 cfg.SA_CERT_PATH = arglist->certificatePath; 1568 1569 cfg.type = NS_LDAP_SERVER; 1570 1571 if (__ns_ldap_initStandalone(&cfg, &errorp) != NS_LDAP_SUCCESS) { 1572 if (errorp != NULL) { 1573 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1574 (void) __ns_ldap_freeError(&errorp); 1575 } 1576 1577 if (gStartLdap == START_RESET) 1578 (void) start_service(LDAP_FMRI, B_TRUE); 1579 1580 return (CLIENT_ERR_FAIL); 1581 } 1582 1583 if (arglist->proxyDN != NULL && arglist->proxyPassword == NULL) { 1584 arglist->proxyPassword = getpassphrase("Proxy Bind Password:"); 1585 if (arglist->proxyPassword == NULL) { 1586 CLIENT_FPUTS(gettext("Get password failed\n"), stderr); 1587 1588 if (gStartLdap == START_RESET) 1589 (void) start_service(LDAP_FMRI, B_TRUE); 1590 1591 return (CLIENT_ERR_CREDENTIAL); 1592 } 1593 } 1594 if (arglist->proxyDN != NULL && arglist->proxyPassword != NULL) { 1595 if (__ns_ldap_setParam(NS_LDAP_BINDDN_P, 1596 arglist->proxyDN, &errorp) != NS_LDAP_SUCCESS) { 1597 if (errorp != NULL) { 1598 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1599 (void) __ns_ldap_freeError(&errorp); 1600 } 1601 return (CLIENT_ERR_CREDENTIAL); 1602 } 1603 if (__ns_ldap_setParam(NS_LDAP_BINDPASSWD_P, 1604 arglist->proxyPassword, &errorp) != NS_LDAP_SUCCESS) { 1605 if (errorp != NULL) { 1606 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1607 (void) __ns_ldap_freeError(&errorp); 1608 } 1609 return (CLIENT_ERR_CREDENTIAL); 1610 } 1611 } 1612 1613 if (arglist->enableShadowUpdate != NULL) { 1614 LDAP_SET_PARAM(arglist->enableShadowUpdate, 1615 NS_LDAP_ENABLE_SHADOW_UPDATE_P); 1616 } 1617 1618 if (arglist->enableShadowUpdate && 1619 strcasecmp(arglist->enableShadowUpdate, "TRUE") == 0 && 1620 arglist->adminDN != NULL && arglist->adminPassword == NULL) { 1621 arglist->adminPassword = getpassphrase("admin Bind Password:"); 1622 if (arglist->adminPassword == NULL) { 1623 CLIENT_FPUTS(gettext("Get password failed\n"), stderr); 1624 1625 if (gStartLdap == START_RESET) 1626 (void) start_service(LDAP_FMRI, B_TRUE); 1627 1628 return (CLIENT_ERR_CREDENTIAL); 1629 } 1630 } 1631 if (arglist->adminDN != NULL && arglist->adminPassword != NULL) { 1632 if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDDN_P, 1633 arglist->adminDN, &errorp) != NS_LDAP_SUCCESS) { 1634 if (errorp != NULL) { 1635 CLIENT_FPRINTF(stderr, "%s\n", errorp->message); 1636 (void) __ns_ldap_freeError(&errorp); 1637 } 1638 return (CLIENT_ERR_CREDENTIAL); 1639 } 1640 if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDPASSWD_P, 1641 arglist->adminPassword, &errorp) != NS_LDAP_SUCCESS) { 1642 if (errorp != NULL) { 1643 CLIENT_FPRINTF(stderr, "%s\n", errorp->message); 1644 (void) __ns_ldap_freeError(&errorp); 1645 } 1646 return (CLIENT_ERR_CREDENTIAL); 1647 } 1648 } 1649 1650 if (arglist->authenticationMethod != NULL) { 1651 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, 1652 (void ***)&authMethod, &errorp) != NS_LDAP_SUCCESS) { 1653 if (errorp != NULL) { 1654 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1655 (void) __ns_ldap_freeError(&errorp); 1656 } 1657 return (CLIENT_ERR_CREDENTIAL); 1658 } 1659 1660 if (authMethod != NULL) { 1661 for (i = 0; authMethod[i] != NULL; ++i) { 1662 if (authMethod[i]->type == auth.type) { 1663 break; 1664 } 1665 } 1666 1667 if (authMethod[i] == NULL) { 1668 CLIENT_FPRINTF(stderr, gettext( 1669 "Warning: init authentication method " 1670 "not found in DUAConfigProfile.\n")); 1671 } else { 1672 if (i != 0) { 1673 CLIENT_FPRINTF(stderr, 1674 gettext( 1675 "Warning: init authentication" 1676 "method using secondary " 1677 "authentication method from " 1678 "DUAConfigProfile.\n")); 1679 } 1680 } 1681 (void) __ns_ldap_freeParam((void ***) &authMethod); 1682 } 1683 } 1684 1685 if (arglist->credentialLevel != NULL) { 1686 if (__ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P, 1687 (void ***)&credLevel, &errorp) != NS_LDAP_SUCCESS) { 1688 if (errorp != NULL) { 1689 CLIENT_FPRINTF(stderr, "%s", errorp->message); 1690 (void) __ns_ldap_freeError(&errorp); 1691 } 1692 return (CLIENT_ERR_CREDENTIAL); 1693 } 1694 if (credLevel != NULL) { 1695 for (i = 0; credLevel[i] != NULL; ++i) { 1696 switch (*credLevel[i]) { 1697 case NS_LDAP_CRED_ANON : 1698 cred = "none"; 1699 break; 1700 case NS_LDAP_CRED_PROXY : 1701 cred = "proxy"; 1702 break; 1703 case NS_LDAP_CRED_SELF : 1704 cred = "self"; 1705 break; 1706 default: 1707 continue; 1708 } 1709 if (strcmp(cred, 1710 arglist->credentialLevel) == 0) { 1711 break; 1712 } 1713 } 1714 if (credLevel[i] == NULL) { 1715 CLIENT_FPRINTF(stderr, gettext( 1716 "Warning: init credential level not found " 1717 "in DUAConfigProfile.\n")); 1718 } else { 1719 if (i != 0) { 1720 CLIENT_FPRINTF(stderr, 1721 gettext("Warning: " 1722 "init credential level using " 1723 "secondary credential level from " 1724 "DUAConfigProfile.\n")); 1725 } 1726 } 1727 (void) __ns_ldap_freeParam((void ***) &credLevel); 1728 } 1729 } 1730 1731 retcode = credCheck(arglist); 1732 if (retcode == CLIENT_SUCCESS) 1733 retcode = adminCredCheck(arglist); 1734 if (retcode != CLIENT_SUCCESS) { 1735 CLIENT_FPUTS( 1736 gettext("Error in setting up credentials\n"), stderr); 1737 1738 if (gStartLdap == START_RESET) 1739 (void) start_service(LDAP_FMRI, B_TRUE); 1740 1741 return (retcode); 1742 } 1743 1744 if (mode_verbose) 1745 CLIENT_FPUTS( 1746 gettext("About to modify this machines configuration " 1747 "by writing the files\n"), 1748 stderr); 1749 1750 /* get ready to start playing with files */ 1751 retcode = stop_services(STATE_SAVE); 1752 if (retcode != CLIENT_SUCCESS) { 1753 CLIENT_FPUTS( 1754 gettext("Errors stopping network services.\n"), stderr); 1755 1756 if (gStartLdap == START_RESET) 1757 (void) start_service(LDAP_FMRI, B_TRUE); 1758 1759 return (CLIENT_ERR_FAIL); 1760 } 1761 1762 /* Save orig versions of files */ 1763 retcode = file_backup(); 1764 if (retcode == CLIENT_ERR_RESTORE) { 1765 CLIENT_FPUTS( 1766 gettext("System not in state to enable ldap client.\n"), 1767 stderr); 1768 1769 return (retcode); 1770 1771 } else if (retcode != CLIENT_SUCCESS) { 1772 CLIENT_FPUTS( 1773 gettext("Save of system configuration failed. " 1774 "Attempting recovery.\n"), 1775 stderr); 1776 retcode = recover(STATE_NOSAVE); 1777 if (retcode != CLIENT_SUCCESS) { 1778 CLIENT_FPUTS( 1779 gettext("Recovery of systems configuration " 1780 "failed. Manual intervention of " 1781 "config files is required.\n"), 1782 stderr); 1783 } 1784 1785 reset_ret = start_services(START_RESET); 1786 if (reset_ret != CLIENT_SUCCESS) { 1787 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1788 "starting services during reset\n"), 1789 reset_ret); 1790 } 1791 1792 return (retcode); 1793 } 1794 1795 /* Dump new files */ 1796 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE); 1797 if (NULL != errorp) { 1798 CLIENT_FPRINTF(stderr, 1799 gettext("%s init: errorp is not NULL; %s\n"), 1800 cmd, errorp->message); 1801 retcode = recover(STATE_NOSAVE); 1802 if (retcode != CLIENT_SUCCESS) { 1803 CLIENT_FPUTS( 1804 gettext("Recovery of systems configuration " 1805 "failed. Manual intervention of " 1806 "config files is required.\n"), 1807 stderr); 1808 return (CLIENT_ERR_FAIL); 1809 } 1810 (void) __ns_ldap_freeError(&errorp); 1811 reset_ret = start_services(START_RESET); 1812 if (reset_ret != CLIENT_SUCCESS) { 1813 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1814 "starting services during reset\n"), 1815 reset_ret); 1816 } 1817 return (CLIENT_ERR_FAIL); 1818 } 1819 1820 /* if (credargs(arglist)) */ 1821 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE); 1822 if (NULL != errorp) { 1823 CLIENT_FPRINTF(stderr, 1824 gettext("%s init: errorp is not NULL; %s\n"), 1825 cmd, errorp->message); 1826 retcode = recover(STATE_NOSAVE); 1827 if (retcode != CLIENT_SUCCESS) { 1828 CLIENT_FPUTS( 1829 gettext("Recovery of systems configuration " 1830 "failed. Manual intervention of " 1831 "config files is required.\n"), 1832 stderr); 1833 return (CLIENT_ERR_FAIL); 1834 } 1835 (void) __ns_ldap_freeError(&errorp); 1836 reset_ret = start_services(START_RESET); 1837 if (reset_ret != CLIENT_SUCCESS) { 1838 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1839 "starting services during reset\n"), 1840 reset_ret); 1841 } 1842 return (CLIENT_ERR_FAIL); 1843 } 1844 1845 ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF); 1846 if (ret_copy != 0) { 1847 CLIENT_FPRINTF(stderr, 1848 gettext("Error %d copying (%s) -> (%s)\n"), 1849 ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF); 1850 retcode = recover(STATE_NOSAVE); 1851 if (retcode != CLIENT_SUCCESS) { 1852 CLIENT_FPUTS( 1853 gettext("Recovery of systems configuration " 1854 "failed. Manual intervention of " 1855 "config files is required.\n"), 1856 stderr); 1857 } 1858 reset_ret = start_services(START_RESET); 1859 if (reset_ret != CLIENT_SUCCESS) { 1860 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1861 "starting services during reset\n"), 1862 reset_ret); 1863 } 1864 return (CLIENT_ERR_FAIL); 1865 } 1866 1867 if ((profile_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC, 1868 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */ 1869 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME); 1870 retcode = recover(STATE_NOSAVE); 1871 if (retcode != CLIENT_SUCCESS) { 1872 CLIENT_FPUTS( 1873 gettext("Recovery of systems configuration " 1874 "failed. Manual intervention of " 1875 "config files is required.\n"), 1876 stderr); 1877 return (CLIENT_ERR_FAIL); 1878 } 1879 reset_ret = start_services(START_RESET); 1880 if (reset_ret != CLIENT_SUCCESS) { 1881 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1882 "starting services during reset\n"), 1883 reset_ret); 1884 } 1885 return (CLIENT_ERR_FAIL); 1886 } 1887 (void) write(profile_fp, dname, strlen(dname)); 1888 (void) write(profile_fp, "\n", 1); 1889 (void) close(profile_fp); 1890 1891 retcode = start_services(START_INIT); 1892 1893 if (retcode == CLIENT_SUCCESS) { 1894 CLIENT_FPUTS(gettext("System successfully configured\n"), 1895 stderr); 1896 } else { 1897 CLIENT_FPUTS(gettext("Error resetting system.\n" 1898 "Recovering old system settings.\n"), stderr), 1899 1900 /* stop any started services for recover */ 1901 /* don't stomp on history of saved services state */ 1902 reset_ret = stop_services(STATE_NOSAVE); 1903 if (reset_ret != CLIENT_SUCCESS) { 1904 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1905 "stopping services during reset\n"), 1906 reset_ret); 1907 /* Coninue and try to recover what we can */ 1908 } 1909 reset_ret = recover(STATE_NOSAVE); 1910 if (reset_ret != CLIENT_SUCCESS) { 1911 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1912 "recovering service files during " 1913 "reset\n"), reset_ret); 1914 /* Continue and start what we can */ 1915 } 1916 reset_ret = start_services(START_RESET); 1917 if (reset_ret != CLIENT_SUCCESS) { 1918 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 1919 "starting services during reset\n"), 1920 reset_ret); 1921 } 1922 } 1923 1924 return (retcode); 1925 } 1926 1927 1928 static void 1929 usage(void) 1930 { 1931 if (mode_quiet) 1932 return; 1933 1934 if (gen == 0) { 1935 CLIENT_FPRINTF(stderr, 1936 gettext("Usage: %s [-v | -q] init | manual | mod | " 1937 "list | uninit [<args>]\n"), 1938 cmd); 1939 1940 CLIENT_FPRINTF(stderr, 1941 gettext("\n %s [-v | -q] [-a authenticationMethod]" 1942 " [-D bindDN]\n\t[-w bindPassword] [-j passswdFile]" 1943 " [-y proxyPasswordFile]\n\t" 1944 "[-z adminPasswordFile] init [<args>]\n"), 1945 cmd); 1946 1947 CLIENT_FPUTS( 1948 gettext("\nSet up a server or workstation as a " 1949 "client of an LDAP namespace.\n"), 1950 stderr); 1951 } else { /* genprofile */ 1952 CLIENT_FPRINTF(stderr, 1953 gettext("Usage: %s [-v | -q] genprofile " 1954 "-a profileName=<name> " 1955 "-a defaultSearchBase=<base> <args>\n"), 1956 cmd); 1957 1958 CLIENT_FPUTS( 1959 gettext("\nGenerate a profile used to set up clients " 1960 "of an LDAP namespace.\n"), 1961 stderr); 1962 } 1963 CLIENT_FPUTS( 1964 gettext("<args> take the form of \'-a attrName=attrVal\' as " 1965 "described in the\n"), 1966 stderr); 1967 CLIENT_FPUTS(gettext("man page: ldapclient(8)\n"), stderr); 1968 } 1969 1970 1971 /* 1972 * stop_services is called to stop network services prior to their 1973 * config files being moved/changed. In case a later recovery is needed 1974 * (an error occurs during config), we detect whether the service is 1975 * running and store that info so that a reset will only start services 1976 * that were stopped here. 1977 * 1978 * In terms of SMF, this translates to disabling the services. So we 1979 * try to disable them if they are in any other state 1980 * 1981 * Stop order : 1982 * sendmail, nscd, autofs, ldap.client, nisd (rpc), inetinit(domainname) 1983 */ 1984 static int 1985 stop_services(int saveState) 1986 { 1987 int ret; 1988 1989 if (mode_verbose) { 1990 CLIENT_FPUTS(gettext("Stopping network services\n"), stderr); 1991 } 1992 1993 if (!is_service(SENDMAIL_FMRI, SCF_STATE_STRING_DISABLED)) { 1994 if (mode_verbose) 1995 CLIENT_FPUTS(gettext("Stopping sendmail\n"), stderr); 1996 ret = disable_service(SENDMAIL_FMRI, B_TRUE); 1997 if (ret != CLIENT_SUCCESS) { 1998 /* Not serious, but tell user what to do */ 1999 CLIENT_FPRINTF(stderr, gettext("Stopping sendmail " 2000 "failed with (%d). You may need to restart " 2001 "it manually for changes to take effect.\n"), 2002 ret); 2003 } else enableFlag |= SENDMAIL_ON; 2004 } else { 2005 if (mode_verbose) 2006 CLIENT_FPUTS(gettext("sendmail not running\n"), stderr); 2007 } 2008 2009 if (!is_service(NSCD_FMRI, SCF_STATE_STRING_DISABLED)) { 2010 if (mode_verbose) 2011 CLIENT_FPUTS(gettext("Stopping nscd\n"), stderr); 2012 ret = disable_service(NSCD_FMRI, B_TRUE); 2013 if (ret != CLIENT_SUCCESS) { 2014 CLIENT_FPRINTF(stderr, gettext("Stopping nscd " 2015 "failed with (%d)\n"), ret); 2016 return (CLIENT_ERR_FAIL); 2017 } else enableFlag |= NSCD_ON; 2018 } else { 2019 if (mode_verbose) 2020 CLIENT_FPUTS(gettext("nscd not running\n"), stderr); 2021 } 2022 2023 if (!is_service(AUTOFS_FMRI, SCF_STATE_STRING_DISABLED)) { 2024 if (mode_verbose) 2025 CLIENT_FPUTS(gettext("Stopping autofs\n"), stderr); 2026 ret = disable_service(AUTOFS_FMRI, B_TRUE); 2027 if (ret != CLIENT_SUCCESS) { 2028 /* Not serious, but tell user what to do */ 2029 CLIENT_FPRINTF(stderr, gettext("Stopping autofs " 2030 "failed with (%d). You may need to restart " 2031 "it manually for changes to take effect.\n"), 2032 ret); 2033 } else enableFlag |= AUTOFS_ON; 2034 } else { 2035 if (mode_verbose) 2036 CLIENT_FPUTS(gettext("autofs not running\n"), stderr); 2037 } 2038 2039 if (!is_service(LDAP_FMRI, SCF_STATE_STRING_DISABLED)) { 2040 if (saveState) 2041 gStartLdap = START_RESET; 2042 if (mode_verbose) 2043 CLIENT_FPUTS(gettext("Stopping ldap\n"), stderr); 2044 ret = disable_service(LDAP_FMRI, B_TRUE); 2045 if (ret != CLIENT_SUCCESS) { 2046 CLIENT_FPRINTF(stderr, gettext("Stopping ldap " 2047 "failed with (%d)\n"), ret); 2048 return (CLIENT_ERR_FAIL); 2049 } 2050 } else { 2051 if (mode_verbose) 2052 CLIENT_FPUTS(gettext("ldap not running\n"), 2053 stderr); 2054 } 2055 2056 if (!is_service(YP_FMRI, SCF_STATE_STRING_DISABLED)) { 2057 if (saveState) 2058 gStartYp = START_RESET; 2059 if (mode_verbose) 2060 CLIENT_FPUTS(gettext("Stopping nis(yp)\n"), stderr); 2061 ret = disable_service(YP_FMRI, B_TRUE); 2062 if (ret != 0) { 2063 CLIENT_FPRINTF(stderr, gettext("Stopping nis(yp) " 2064 "failed with (%d)\n"), ret); 2065 return (CLIENT_ERR_FAIL); 2066 } 2067 } else { 2068 if (mode_verbose) 2069 CLIENT_FPUTS(gettext("nis(yp) not running\n"), 2070 stderr); 2071 } 2072 2073 return (CLIENT_SUCCESS); 2074 } 2075 2076 /* 2077 * start_services is called to start up network services after config 2078 * files have all been setup or recovered. In the case of an error, the 2079 * files will be recovered and start_services will be called with the 2080 * "reset" flag set so that only those services that were earlier stopped 2081 * will be started. If it is not a reset, then the services associated 2082 * with files "recovered" will attempt to be started. 2083 */ 2084 static int 2085 start_services(int flag) 2086 { 2087 int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS; 2088 FILE *domain_fp; 2089 char domainname[BUFSIZ]; 2090 char cmd_domain_start[BUFSIZ]; 2091 int domainlen; 2092 ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE; 2093 ns_ldap_error_t *errorp = NULL; 2094 2095 if (mode_verbose) { 2096 CLIENT_FPUTS(gettext("Starting network services\n"), stderr); 2097 } 2098 2099 /* Read in current defaultdomain so we can set it */ 2100 domain_fp = fopen(DOMAINNAME, "r"); 2101 if (domain_fp == NULL) { 2102 CLIENT_FPRINTF(stderr, gettext("Error opening defaultdomain " 2103 "(%d)\n"), errno); 2104 /* if we did an ldap init, we must have domain */ 2105 if (flag == START_INIT) 2106 return (CLIENT_ERR_FAIL); 2107 } else { 2108 if (fgets(domainname, BUFSIZ, domain_fp) == NULL) { 2109 CLIENT_FPUTS(gettext("Error reading defaultdomain\n"), 2110 stderr); 2111 return (CLIENT_ERR_FAIL); 2112 } 2113 2114 if (fclose(domain_fp) != 0) { 2115 CLIENT_FPRINTF(stderr, 2116 gettext("Error closing defaultdomain (%d)\n"), 2117 errno); 2118 return (CLIENT_ERR_FAIL); 2119 } 2120 domainlen = strlen(domainname); 2121 /* sanity check to make sure sprintf will fit */ 2122 if (domainlen > (BUFSIZE - sizeof (CMD_DOMAIN_START) - 2123 sizeof (TO_DEV_NULL) - 3)) { 2124 CLIENT_FPUTS(gettext("Specified domainname is " 2125 "too large\n"), stderr); 2126 return (CLIENT_ERR_FAIL); 2127 } 2128 if (domainname[domainlen-1] == '\n') 2129 domainname[domainlen-1] = 0; 2130 /* buffer size is checked above */ 2131 (void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s", 2132 CMD_DOMAIN_START, domainname, TO_DEV_NULL); 2133 } 2134 2135 /* 2136 * We can be starting services after an init in which case 2137 * we want to start ldap and not start yp. 2138 */ 2139 if (flag == START_INIT) { 2140 sysret = system(cmd_domain_start); 2141 if (mode_verbose) 2142 CLIENT_FPRINTF(stderr, "start: %s %s... %s\n", 2143 CMD_DOMAIN_START, domainname, 2144 (sysret == 0) ? gettext("success") : 2145 gettext("failed")); 2146 if (sysret != 0) { 2147 CLIENT_FPRINTF(stderr, gettext("\"%s\" returned: %d\n"), 2148 CMD_DOMAIN_START, sysret); 2149 2150 retcode = CLIENT_ERR_FAIL; 2151 } 2152 2153 if ((rc = __ns_ldap_self_gssapi_config(&config)) != 2154 NS_LDAP_SUCCESS) { 2155 CLIENT_FPRINTF(stderr, gettext("Error (%d) while " 2156 "checking sasl/GSSAPI configuration\n"), 2157 rc); 2158 retcode = CLIENT_ERR_FAIL; 2159 } 2160 2161 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) { 2162 2163 rc = __ns_ldap_check_dns_preq( 2164 1, mode_verbose, mode_quiet, 2165 NSSWITCH_LDAP, config, &errorp); 2166 if (errorp) 2167 (void) __ns_ldap_freeError(&errorp); 2168 2169 if (rc != NS_LDAP_SUCCESS) 2170 retcode = CLIENT_ERR_FAIL; 2171 } 2172 2173 if (rc == NS_LDAP_SUCCESS && 2174 start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS) 2175 retcode = CLIENT_ERR_FAIL; 2176 2177 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE && 2178 rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) { 2179 rc = __ns_ldap_check_gssapi_preq( 2180 1, mode_verbose, mode_quiet, config, 2181 &errorp); 2182 if (errorp) 2183 (void) __ns_ldap_freeError(&errorp); 2184 2185 if (rc != NS_LDAP_SUCCESS) 2186 retcode = CLIENT_ERR_FAIL; 2187 2188 } 2189 /* No YP after init */ 2190 /* 2191 * Or we can be starting services after an uninit or error 2192 * recovery. We want to start whatever services were running 2193 * before. In the case of error recovery, it is the services 2194 * that were running before we stopped them (flags set in 2195 * stop_services). If it is an uninit then we determine 2196 * which services to start based on the files we recovered 2197 * (flags set in recover). 2198 */ 2199 } else { 2200 /* uninit and recover should set flags of what to start */ 2201 if (domain_fp) { 2202 sysret = system(cmd_domain_start); 2203 if (mode_verbose) 2204 CLIENT_FPRINTF(stderr, "start: %s %s... %s\n", 2205 CMD_DOMAIN_START, domainname, 2206 (sysret == 0) ? gettext("success") : 2207 gettext("failed")); 2208 if (sysret != 0) { 2209 CLIENT_FPRINTF(stderr, gettext("\"%s\" " 2210 "returned: %d\n"), 2211 CMD_DOMAIN_START, sysret); 2212 2213 retcode = CLIENT_ERR_FAIL; 2214 } 2215 } 2216 2217 if (gStartLdap == flag) { 2218 if (!(is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE))) 2219 if (start_service(LDAP_FMRI, B_TRUE) 2220 != CLIENT_SUCCESS) 2221 retcode = CLIENT_ERR_FAIL; 2222 } 2223 2224 if (gStartYp == flag) { 2225 if (!(is_service(YP_FMRI, SCF_STATE_STRING_ONLINE))) 2226 (void) start_service(YP_FMRI, B_TRUE); 2227 } 2228 } 2229 if ((enableFlag & AUTOFS_ON) && 2230 !(is_service(AUTOFS_FMRI, SCF_STATE_STRING_ONLINE))) 2231 (void) start_service(AUTOFS_FMRI, B_TRUE); 2232 2233 if ((enableFlag & NSCD_ON) && 2234 !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) 2235 (void) start_service(NSCD_FMRI, B_TRUE); 2236 2237 #if 0 2238 if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE && 2239 retcode == CLIENT_SUCCESS && 2240 !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) { 2241 CLIENT_FPRINTF(stderr, "start: %s\n", 2242 gettext("self/sasl/GSSAPI is configured" 2243 " but nscd is not online")); 2244 retcode = CLIENT_ERR_FAIL; 2245 } 2246 #endif 2247 2248 if ((enableFlag & SENDMAIL_ON) && 2249 !(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE))) 2250 (void) start_service(SENDMAIL_FMRI, B_TRUE); 2251 2252 /* 2253 * Restart name-service milestone so that any consumer 2254 * which depends on it will be restarted. 2255 */ 2256 (void) restart_service(NS_MILESTONE_FMRI, B_TRUE); 2257 return (retcode); 2258 } 2259 2260 /* 2261 * credCheck is called to check if credentials are required for this 2262 * configuration. Currently, this means that if any credentialLevel is 2263 * proxy and any authenticationMethod is something other than none, then 2264 * credential info is required (proxyDN and proxyPassword). 2265 */ 2266 static int 2267 credCheck(clientopts_t *arglist) 2268 { 2269 int counter; 2270 int **credLevel; 2271 ns_auth_t **authMethod; 2272 char **proxyDN, **proxyPassword; 2273 ns_ldap_error_t *errorp; 2274 int credProxy, authNotNone; 2275 int retcode; 2276 2277 /* If credentialLevel is proxy, make sure we have proxyDN and proxyPassword */ 2278 retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P, 2279 (void ***)&credLevel, &errorp); 2280 if (retcode != 0) { 2281 CLIENT_FPRINTF(stderr, 2282 gettext("Error %d while trying to retrieve " 2283 "credLevel\n"), 2284 retcode); 2285 return (CLIENT_ERR_FAIL); 2286 } 2287 retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P, 2288 (void ***)&authMethod, &errorp); 2289 if (retcode != 0) { 2290 CLIENT_FPRINTF(stderr, 2291 gettext("Error %d while trying to retrieve " 2292 "authMethod\n"), retcode); 2293 return (CLIENT_ERR_FAIL); 2294 } 2295 retcode = __ns_ldap_getParam(NS_LDAP_BINDDN_P, 2296 (void ***)&proxyDN, &errorp); 2297 if (retcode != 0) { 2298 CLIENT_FPRINTF(stderr, 2299 gettext("Error %d while trying to retrieve proxyDN\n"), 2300 retcode); 2301 return (CLIENT_ERR_FAIL); 2302 } 2303 retcode = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P, 2304 (void ***)&proxyPassword, &errorp); 2305 if (retcode != 0) { 2306 CLIENT_FPRINTF(stderr, 2307 gettext("Error %d while trying to retrieve " 2308 "proxyPassword\n"), retcode); 2309 return (CLIENT_ERR_FAIL); 2310 } 2311 2312 if (mode_verbose) { 2313 CLIENT_FPRINTF(stderr, 2314 gettext("Proxy DN: %s\n"), 2315 (proxyDN && proxyDN[0]) ? proxyDN[0] : "NULL"); 2316 CLIENT_FPRINTF(stderr, 2317 gettext("Proxy password: %s\n"), 2318 (proxyPassword && proxyPassword[0]) ? 2319 proxyPassword[0] : "NULL"); 2320 } 2321 2322 credProxy = 0; /* flag to indicate if we have a credLevel of proxy */ 2323 for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) { 2324 if (mode_verbose) 2325 CLIENT_FPRINTF(stderr, 2326 gettext("Credential level: %d\n"), 2327 *credLevel[counter]); 2328 if (*credLevel[counter] == NS_LDAP_CRED_PROXY) { 2329 credProxy = 1; 2330 break; 2331 } 2332 } 2333 2334 authNotNone = 0; /* flag for authMethod other than none */ 2335 for (counter = 0; 2336 authMethod && authMethod[counter] != NULL; 2337 counter++) { 2338 2339 if (mode_verbose) 2340 CLIENT_FPRINTF(stderr, 2341 gettext("Authentication method: %d\n"), 2342 authMethod[counter]->type); 2343 if (authMethod[counter]->type != NS_LDAP_AUTH_NONE && 2344 !(authMethod[counter]->type == NS_LDAP_AUTH_TLS && 2345 authMethod[counter]->tlstype == NS_LDAP_TLS_NONE)) { 2346 authNotNone = 1; 2347 break; 2348 } 2349 } 2350 2351 /* First, if we don't need proxyDN/Password then just return ok */ 2352 if (!(credProxy && authNotNone)) { 2353 if (mode_verbose) 2354 CLIENT_FPUTS( 2355 gettext("No proxyDN/proxyPassword required\n"), 2356 stderr); 2357 return (CLIENT_SUCCESS); 2358 } 2359 2360 /* Now let's check if we have the cred stuff we need */ 2361 if (!proxyDN || !proxyDN[0]) { 2362 CLIENT_FPUTS( 2363 gettext("credentialLevel is proxy and no proxyDN " 2364 "specified\n"), 2365 stderr); 2366 return (CLIENT_ERR_CREDENTIAL); 2367 } 2368 2369 /* If we need proxyPassword (prompt) */ 2370 if (!proxyPassword || !proxyPassword[0]) { 2371 CLIENT_FPUTS( 2372 gettext("credentialLevel requires proxyPassword\n"), 2373 stderr); 2374 arglist->proxyPassword = getpassphrase("Proxy Bind Password:"); 2375 if (arglist->proxyPassword == NULL) { 2376 CLIENT_FPUTS(gettext("Get password failed\n"), stderr); 2377 return (CLIENT_ERR_CREDENTIAL); 2378 } 2379 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P); 2380 if (retcode != 0) { 2381 CLIENT_FPUTS( 2382 gettext("setParam proxyPassword failed.\n"), 2383 stderr); 2384 return (CLIENT_ERR_CREDENTIAL); 2385 } 2386 } 2387 2388 return (CLIENT_SUCCESS); 2389 } 2390 2391 /* 2392 * adminCredCheck is called to check if the admin credential is required 2393 * for this configuration. This means that if enableShadowUpdate is set 2394 * to TRUE then credential info is required (adminDN and adminPassword). 2395 * One exception is that if there is a 'self' credentialLevel and 2396 * 'sasl/GSSAPI' authenticationMethod (i.e., possibly using Kerberos 2397 * host credential) then adminDN and adminPassword are not required. 2398 */ 2399 static int 2400 adminCredCheck(clientopts_t *arglist) 2401 { 2402 int counter; 2403 int **enabled = NULL; 2404 int **credLevel = NULL; 2405 char **adminDN = NULL; 2406 char **adminPassword = NULL; 2407 ns_auth_t **authMethod = NULL; 2408 ns_ldap_error_t *errorp = NULL; 2409 int credSelf, authSASLgss; 2410 int retcode, rc; 2411 2412 /* If shadow update not enabled, then no need to check */ 2413 retcode = __ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P, 2414 (void ***)&enabled, &errorp); 2415 if (retcode != 0) { 2416 CLIENT_FPRINTF(stderr, 2417 gettext("Error %d while trying to retrieve " 2418 "enableShadowUpdate\n"), retcode); 2419 rc = CLIENT_ERR_FAIL; 2420 goto out; 2421 } 2422 if (enabled == NULL || 2423 *enabled[0] != NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE) { 2424 if (mode_verbose) 2425 CLIENT_FPUTS( 2426 gettext("Shadow Update is not enabled, " 2427 "no adminDN/adminPassword is required.\n"), stderr); 2428 rc = CLIENT_SUCCESS; 2429 goto out; 2430 } 2431 2432 /* get credentialLevel */ 2433 retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P, 2434 (void ***)&credLevel, &errorp); 2435 if (retcode != 0) { 2436 CLIENT_FPRINTF(stderr, 2437 gettext("Error %d while trying to retrieve credLevel\n"), 2438 retcode); 2439 rc = CLIENT_ERR_FAIL; 2440 goto out; 2441 } 2442 2443 /* get AuthenticationMethod */ 2444 retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P, 2445 (void ***)&authMethod, &errorp); 2446 if (retcode != 0) { 2447 CLIENT_FPRINTF(stderr, 2448 gettext("Error %d while trying to retrieve authMethod\n"), 2449 retcode); 2450 rc = CLIENT_ERR_FAIL; 2451 goto out; 2452 } 2453 2454 /* get adminDN */ 2455 retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDDN_P, 2456 (void ***)&adminDN, &errorp); 2457 if (retcode != 0) { 2458 CLIENT_FPRINTF(stderr, 2459 gettext("Error %d while trying to retrieve adminDN\n"), 2460 retcode); 2461 rc = CLIENT_ERR_FAIL; 2462 goto out; 2463 } 2464 2465 /* get adminPassword */ 2466 retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P, 2467 (void ***)&adminPassword, &errorp); 2468 if (retcode != 0) { 2469 CLIENT_FPRINTF(stderr, 2470 gettext("Error %d while trying to retrieve " 2471 "adminPassword\n"), retcode); 2472 rc = CLIENT_ERR_FAIL; 2473 goto out; 2474 } 2475 2476 if (mode_verbose) { 2477 CLIENT_FPRINTF(stderr, 2478 gettext("admin DN: %s\n"), 2479 (adminDN && adminDN[0]) ? adminDN[0] : "NULL"); 2480 CLIENT_FPRINTF(stderr, 2481 gettext("admin password: %s\n"), 2482 (adminPassword && adminPassword[0]) ? 2483 adminPassword[0] : "NULL"); 2484 } 2485 2486 credSelf = 0; /* flag to indicate if we have a credLevel of self */ 2487 for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) { 2488 if (mode_verbose) 2489 CLIENT_FPRINTF(stderr, 2490 gettext("Credential level: %d\n"), 2491 *credLevel[counter]); 2492 if (*credLevel[counter] == NS_LDAP_CRED_SELF) { 2493 credSelf = 1; 2494 break; 2495 } 2496 } 2497 2498 authSASLgss = 0; /* flag for authMethod of SASL/gssapi */ 2499 for (counter = 0; 2500 authMethod && authMethod[counter] != NULL; 2501 counter++) { 2502 2503 if (mode_verbose) 2504 CLIENT_FPRINTF(stderr, 2505 gettext("Authentication sasl mechanism: %d\n"), 2506 authMethod[counter]->saslmech); 2507 if (authMethod[counter]->saslmech == NS_LDAP_SASL_GSSAPI) { 2508 authSASLgss = 1; 2509 break; 2510 } 2511 } 2512 2513 /* First, if we don't need adminDN/adminPassword then just return ok */ 2514 if (credSelf && authSASLgss) { 2515 if (mode_verbose) 2516 CLIENT_FPUTS( 2517 gettext("A credential Level of self and an " 2518 "authentication method of sasl/GSSAPI is " 2519 "configured, no adminDN/adminPassword " 2520 "is required.\n"), stderr); 2521 rc = CLIENT_SUCCESS; 2522 goto out; 2523 } 2524 2525 /* Now let's check if we have the cred stuff we need */ 2526 if (adminDN == NULL || adminDN[0] == NULL) { 2527 CLIENT_FPUTS( 2528 gettext("Shadow Update is enabled, but " 2529 "no adminDN is configured.\n"), stderr); 2530 rc = CLIENT_ERR_CREDENTIAL; 2531 goto out; 2532 } 2533 2534 /* If we need adminPassword (prompt) */ 2535 if (adminPassword == NULL || adminPassword[0] == NULL) { 2536 CLIENT_FPUTS( 2537 gettext("Shadow Update requires adminPassword\n"), 2538 stderr); 2539 arglist->adminPassword = getpassphrase("admin Password:"); 2540 if (arglist->adminPassword == NULL) { 2541 CLIENT_FPUTS(gettext("Unable to get admin password\n"), 2542 stderr); 2543 rc = CLIENT_ERR_CREDENTIAL; 2544 goto out; 2545 } 2546 LDAP_SET_PARAM(arglist->adminPassword, 2547 NS_LDAP_ADMIN_BINDPASSWD_P); 2548 if (retcode != 0) { 2549 CLIENT_FPUTS( 2550 gettext("setParam adminPassword failed.\n"), 2551 stderr); 2552 rc = CLIENT_ERR_CREDENTIAL; 2553 goto out; 2554 } 2555 } 2556 2557 rc = CLIENT_SUCCESS; 2558 2559 out: 2560 if (enabled != NULL) 2561 (void) __ns_ldap_freeParam((void ***)&enabled); 2562 if (credLevel != NULL) 2563 (void) __ns_ldap_freeParam((void ***)&credLevel); 2564 if (authMethod != NULL) 2565 (void) __ns_ldap_freeParam((void ***)&authMethod); 2566 if (adminDN != NULL) 2567 (void) __ns_ldap_freeParam((void ***)&adminDN); 2568 if (adminPassword != NULL) 2569 (void) __ns_ldap_freeParam((void ***)&adminPassword); 2570 2571 return (rc); 2572 } 2573 2574 /* 2575 * try to restore the previous name space on this machine 2576 */ 2577 static int 2578 recover(int saveState) 2579 { 2580 struct stat buf; 2581 int stat_ret, retcode, fd; 2582 int domain = 0, domainlen; 2583 char yp_dir[BUFSIZE], yp_dir_back[BUFSIZE]; 2584 char name[BUFSIZ]; 2585 char *ldap_conf_file, *ldap_cred_file; 2586 char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE]; 2587 2588 /* If running as Sysid Install become a no-op */ 2589 if (sysid_install == B_TRUE) 2590 return (CLIENT_SUCCESS); 2591 2592 stat_ret = stat(LDAP_RESTORE_DIR, &buf); 2593 if (stat_ret != 0) { 2594 CLIENT_FPUTS( 2595 gettext("Cannot recover. No backup files " 2596 "found.\n"), 2597 stderr); 2598 CLIENT_FPUTS( 2599 gettext("\t Either this machine was not initialized\n"), 2600 stderr); 2601 CLIENT_FPUTS( 2602 gettext("\t by ldapclient or the backup files " 2603 "have been\n"), 2604 stderr); 2605 CLIENT_FPUTS( 2606 gettext("\t removed manually or with an \"uninit\"\n"), 2607 stderr); 2608 return (CLIENT_ERR_RESTORE); /* invalid backup */ 2609 } 2610 2611 /* 2612 * Get domainname. Allow no domainname for the case where "files" 2613 * config was backed up. 2614 */ 2615 stat_ret = stat(DOMAINNAME_BACK, &buf); 2616 if (mode_verbose) 2617 CLIENT_FPRINTF(stderr, 2618 gettext("recover: stat(%s)=%d\n"), 2619 DOMAINNAME_BACK, stat_ret); 2620 if (stat_ret == 0) { 2621 if (mode_verbose) 2622 CLIENT_FPRINTF(stderr, 2623 gettext("recover: open(%s)\n"), 2624 DOMAINNAME_BACK); 2625 fd = open(DOMAINNAME_BACK, O_RDONLY); 2626 if (mode_verbose) 2627 CLIENT_FPRINTF(stderr, 2628 gettext("recover: read(%s)\n"), 2629 DOMAINNAME_BACK); 2630 domainlen = read(fd, &(name[0]), BUFSIZ-1); 2631 (void) close(fd); 2632 if (domainlen < 0) { 2633 CLIENT_FPUTS( 2634 gettext("Cannot recover. Cannot determine " 2635 "previous domain name.\n"), 2636 stderr); 2637 return (CLIENT_ERR_RESTORE); /* invalid backup */ 2638 } else { 2639 char *ptr; 2640 2641 ptr = strchr(&(name[0]), '\n'); 2642 if (ptr != NULL) 2643 *ptr = '\0'; 2644 else 2645 name[domainlen] = '\0'; 2646 2647 if (mode_verbose) 2648 CLIENT_FPRINTF(stderr, 2649 gettext("recover: old domainname " 2650 "\"%s\"\n"), name); 2651 2652 if (strlen(name) == 0) 2653 domain = 0; 2654 else 2655 domain = 1; /* flag that we have domain */ 2656 2657 } 2658 } 2659 2660 2661 /* 2662 * we can recover at this point 2663 * remove LDAP config files before restore 2664 */ 2665 (void) unlink(NSCONFIGFILE); 2666 (void) unlink(NSCREDFILE); 2667 2668 ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1; 2669 ldap_cred_file = strrchr(NSCREDFILE, '/') + 1; 2670 2671 (void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE); 2672 (void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE); 2673 2674 stat_ret = stat(ldap_file_back, &buf); 2675 if (mode_verbose) 2676 CLIENT_FPRINTF(stderr, 2677 gettext("recover: stat(%s)=%d\n"), 2678 ldap_file_back, stat_ret); 2679 if (stat_ret == 0) { 2680 if (saveState) 2681 gStartLdap = START_UNINIT; 2682 retcode = file_move(ldap_file_back, NSCONFIGFILE); 2683 if (mode_verbose) 2684 CLIENT_FPRINTF(stderr, 2685 gettext("recover: file_move(%s, %s)=%d\n"), 2686 ldap_file_back, NSCONFIGFILE, retcode); 2687 if (retcode != 0) 2688 CLIENT_FPRINTF(stderr, 2689 gettext("recover: file_move(%s, %s) failed\n"), 2690 ldap_file_back, NSCONFIGFILE); 2691 } 2692 2693 (void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE); 2694 (void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE); 2695 2696 stat_ret = stat(ldap_cred_back, &buf); 2697 if (mode_verbose) 2698 CLIENT_FPRINTF(stderr, 2699 gettext("recover: stat(%s)=%d\n"), 2700 ldap_cred_back, stat_ret); 2701 if (stat_ret == 0) { 2702 retcode = file_move(ldap_cred_back, NSCREDFILE); 2703 if (mode_verbose) 2704 CLIENT_FPRINTF(stderr, 2705 gettext("recover: file_move(%s, %s)=%d\n"), 2706 ldap_cred_back, NSCREDFILE, retcode); 2707 if (retcode != 0) 2708 CLIENT_FPRINTF(stderr, 2709 gettext("recover: file_move(%s, %s) failed\n"), 2710 ldap_cred_back, NSCREDFILE); 2711 } 2712 2713 /* Check for recovery of NIS(YP) if we have a domainname */ 2714 if (domain) { 2715 /* "name" would have to be huge for this, but just in case */ 2716 if (strlen(name) >= (BUFSIZE - strlen(LDAP_RESTORE_DIR))) 2717 return (CLIENT_ERR_FAIL); 2718 if (strlen(name) >= (BUFSIZE - strlen(YP_BIND_DIR))) 2719 return (CLIENT_ERR_FAIL); 2720 2721 (void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", BUFSIZE); 2722 (void) strlcat(yp_dir_back, name, BUFSIZE); 2723 stat_ret = stat(yp_dir_back, &buf); 2724 if (mode_verbose) 2725 CLIENT_FPRINTF(stderr, 2726 gettext("recover: stat(%s)=%d\n"), 2727 yp_dir_back, stat_ret); 2728 if (stat_ret == 0) { 2729 (void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE); 2730 (void) strlcat(yp_dir, name, BUFSIZE); 2731 retcode = file_move(yp_dir_back, yp_dir); 2732 if (mode_verbose) 2733 CLIENT_FPRINTF(stderr, 2734 gettext("recover: file_move(%s, " 2735 "%s)=%d\n"), 2736 yp_dir_back, yp_dir, retcode); 2737 if (retcode != 0) { 2738 CLIENT_FPRINTF(stderr, 2739 gettext("recover: file_move(%s, " 2740 "%s) failed!\n"), 2741 yp_dir_back, yp_dir); 2742 } else { 2743 if (saveState) 2744 gStartYp = START_UNINIT; 2745 } 2746 } 2747 } 2748 2749 /* restore machine configuration */ 2750 stat_ret = stat(NSSWITCH_BACK, &buf); 2751 if (mode_verbose) 2752 CLIENT_FPRINTF(stderr, 2753 gettext("recover: stat(%s)=%d\n"), 2754 NSSWITCH_BACK, stat_ret); 2755 if (stat_ret == 0) { 2756 retcode = file_move(NSSWITCH_BACK, NSSWITCH_CONF); 2757 if (mode_verbose) 2758 CLIENT_FPRINTF(stderr, 2759 gettext("recover: file_move(%s, %s)=%d\n"), 2760 NSSWITCH_BACK, NSSWITCH_CONF, retcode); 2761 if (retcode != 0) 2762 CLIENT_FPRINTF(stderr, 2763 gettext("recover: file_move(%s, %s) failed\n"), 2764 NSSWITCH_BACK, NSSWITCH_CONF); 2765 } 2766 2767 stat_ret = stat(DOMAINNAME_BACK, &buf); 2768 if (mode_verbose) 2769 CLIENT_FPRINTF(stderr, 2770 gettext("recover: stat(%s)=%d\n"), 2771 DOMAINNAME_BACK, stat_ret); 2772 if (stat_ret == 0) { 2773 retcode = file_move(DOMAINNAME_BACK, DOMAINNAME); 2774 if (mode_verbose) 2775 CLIENT_FPRINTF(stderr, 2776 gettext("recover: file_move(%s, %s)=%d\n"), 2777 DOMAINNAME_BACK, DOMAINNAME, retcode); 2778 if (retcode != 0) 2779 CLIENT_FPRINTF(stderr, 2780 gettext("recover: file_move(%s, %s) failed\n"), 2781 DOMAINNAME_BACK, DOMAINNAME); 2782 } 2783 2784 retcode = rmdir(LDAP_RESTORE_DIR); 2785 if (retcode != 0) { 2786 CLIENT_FPRINTF(stderr, 2787 gettext("Error removing \"%s\" directory.\n"), 2788 LDAP_RESTORE_DIR); 2789 } 2790 2791 return (CLIENT_SUCCESS); 2792 } 2793 2794 /* 2795 * try to save the current state of this machine. 2796 * this just overwrites any old saved configration files. 2797 * 2798 * This function should only be called after network services have been stopped. 2799 * 2800 * Returns 0 on successful save 2801 * Otherwise returns -1 2802 */ 2803 static int 2804 file_backup(void) 2805 { 2806 struct stat buf; 2807 int domain_stat, conf_stat, ldap_stat; 2808 int yp_stat, restore_stat; 2809 int retcode, namelen, ret; 2810 char yp_dir[BUFSIZ], yp_dir_back[BUFSIZ]; 2811 char name[BUFSIZ]; 2812 char *ldap_conf_file, *ldap_cred_file; 2813 char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE]; 2814 2815 ret = CLIENT_SUCCESS; 2816 /* If running as Sysid Install become a no-op */ 2817 if (sysid_install == B_TRUE) 2818 return (CLIENT_SUCCESS); 2819 2820 /* If existing backup files, clear for this run */ 2821 restore_stat = stat(LDAP_RESTORE_DIR, &buf); 2822 if (restore_stat == 0) { 2823 if (mode_verbose) { 2824 CLIENT_FPUTS( 2825 gettext("Removing existing restore " 2826 "directory\n"), 2827 stderr); 2828 } 2829 (void) system("/bin/rm -fr " LDAP_RESTORE_DIR); 2830 restore_stat = stat(LDAP_RESTORE_DIR, &buf); 2831 if (restore_stat == 0) { 2832 CLIENT_FPRINTF(stderr, 2833 gettext("Unable to remove backup " 2834 "directory (%s)\n"), 2835 LDAP_RESTORE_DIR); 2836 return (CLIENT_ERR_RESTORE); 2837 } 2838 } 2839 2840 retcode = mkdir(LDAP_RESTORE_DIR, 0755); 2841 if (retcode != 0) { 2842 CLIENT_FPRINTF(stderr, 2843 gettext("file_backup: Failed to make %s backup " 2844 "directory. mkdir=%d\n"), 2845 LDAP_RESTORE_DIR, retcode); 2846 return (CLIENT_ERR_FAIL); 2847 } 2848 2849 conf_stat = stat(NSSWITCH_CONF, &buf); 2850 if (mode_verbose) 2851 CLIENT_FPRINTF(stderr, 2852 gettext("file_backup: stat(%s)=%d\n"), 2853 NSSWITCH_CONF, conf_stat); 2854 if (conf_stat == 0) { 2855 if (mode_verbose) 2856 CLIENT_FPRINTF(stderr, 2857 gettext("file_backup: (%s -> %s)\n"), 2858 NSSWITCH_CONF, NSSWITCH_BACK); 2859 retcode = file_move(NSSWITCH_CONF, NSSWITCH_BACK); 2860 if (retcode != 0) { 2861 CLIENT_FPRINTF(stderr, 2862 gettext("file_backup: file_move(%s, %s) failed " 2863 "with %d\n"), 2864 NSSWITCH_CONF, NSSWITCH_BACK, retcode); 2865 ret = CLIENT_ERR_RENAME; 2866 } 2867 } else { 2868 if (mode_verbose) 2869 CLIENT_FPRINTF(stderr, 2870 gettext("file_backup: No %s file.\n"), 2871 NSSWITCH_CONF); 2872 } 2873 2874 domain_stat = stat(DOMAINNAME, &buf); 2875 if (mode_verbose) 2876 CLIENT_FPRINTF(stderr, 2877 gettext("file_backup: stat(%s)=%d\n"), 2878 DOMAINNAME, domain_stat); 2879 if ((domain_stat == 0) && (buf.st_size > 0)) { 2880 if (mode_verbose) 2881 CLIENT_FPRINTF(stderr, 2882 gettext("file_backup: (%s -> %s)\n"), 2883 DOMAINNAME, DOMAINNAME_BACK); 2884 retcode = file_move(DOMAINNAME, DOMAINNAME_BACK); 2885 if (retcode != 0) { 2886 CLIENT_FPRINTF(stderr, 2887 gettext("file_backup: file_move(%s, %s) failed " 2888 "with %d\n"), 2889 DOMAINNAME, DOMAINNAME_BACK, retcode); 2890 ret = CLIENT_ERR_RENAME; 2891 } 2892 } else { 2893 if (mode_verbose) 2894 if (domain_stat != 0) { 2895 CLIENT_FPRINTF(stderr, 2896 gettext("file_backup: No %s file.\n"), 2897 DOMAINNAME); 2898 } else { 2899 CLIENT_FPRINTF(stderr, 2900 gettext("file_backup: Empty %s " 2901 "file.\n"), 2902 DOMAINNAME); 2903 } 2904 } 2905 2906 namelen = BUFSIZ; 2907 (void) sysinfo(SI_SRPC_DOMAIN, &(name[0]), namelen); 2908 namelen = strlen(name); 2909 2910 if (mode_verbose) 2911 CLIENT_FPRINTF(stderr, 2912 gettext("file_backup: nis domain is \"%s\"\n"), 2913 (namelen > 0) ? name : "EMPTY"); 2914 /* check for domain name if not set cannot save NIS(YP) state */ 2915 if (namelen > 0) { 2916 /* moving /var/yp/binding will cause ypbind to core dump */ 2917 (void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE); 2918 (void) strlcat(yp_dir, name, BUFSIZE); 2919 yp_stat = stat(yp_dir, &buf); 2920 if (mode_verbose) 2921 CLIENT_FPRINTF(stderr, 2922 gettext("file_backup: stat(%s)=%d\n"), 2923 yp_dir, yp_stat); 2924 if (yp_stat == 0) { 2925 (void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", 2926 BUFSIZE); 2927 (void) strlcat(yp_dir_back, name, BUFSIZE); 2928 if (mode_verbose) 2929 CLIENT_FPRINTF(stderr, 2930 gettext("file_backup: (%s -> %s)\n"), 2931 yp_dir, yp_dir_back); 2932 retcode = file_move(yp_dir, yp_dir_back); 2933 if (retcode != 0) { 2934 CLIENT_FPRINTF(stderr, 2935 gettext("file_backup: file_move(%s, %s)" 2936 " failed with %d\n"), 2937 yp_dir, yp_dir_back, retcode); 2938 ret = CLIENT_ERR_RENAME; 2939 } 2940 } else { 2941 if (mode_verbose) 2942 CLIENT_FPRINTF(stderr, 2943 gettext("file_backup: No %s " 2944 "directory.\n"), yp_dir); 2945 } 2946 } 2947 2948 2949 /* point to file name, not path delim (/) */ 2950 ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1; 2951 ldap_cred_file = strrchr(NSCREDFILE, '/') + 1; 2952 2953 ldap_stat = stat(NSCONFIGFILE, &buf); 2954 if (mode_verbose) 2955 CLIENT_FPRINTF(stderr, 2956 gettext("file_backup: stat(%s)=%d\n"), 2957 NSCONFIGFILE, ldap_stat); 2958 if (ldap_stat == 0) { 2959 (void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE); 2960 (void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE); 2961 if (mode_verbose) 2962 CLIENT_FPRINTF(stderr, 2963 gettext("file_backup: (%s -> %s)\n"), 2964 NSCONFIGFILE, ldap_file_back); 2965 retcode = file_move(NSCONFIGFILE, ldap_file_back); 2966 if (retcode != 0) { 2967 CLIENT_FPRINTF(stderr, 2968 gettext("file_backup: file_move(%s, %s) failed " 2969 "with %d\n"), 2970 NSCONFIGFILE, ldap_file_back, retcode); 2971 ret = CLIENT_ERR_RENAME; 2972 } 2973 2974 (void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE); 2975 (void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE); 2976 if (mode_verbose) 2977 CLIENT_FPRINTF(stderr, 2978 gettext("file_backup: (%s -> %s)\n"), 2979 NSCREDFILE, ldap_cred_back); 2980 retcode = file_move(NSCREDFILE, ldap_cred_back); 2981 if (retcode != 0) { 2982 CLIENT_FPRINTF(stderr, 2983 gettext("file_backup: file_move(%s, %s) failed " 2984 "with %d\n"), 2985 NSCREDFILE, ldap_cred_back, retcode); 2986 ret = CLIENT_ERR_RENAME; 2987 } 2988 } else { 2989 if (mode_verbose) 2990 CLIENT_FPRINTF(stderr, 2991 gettext("file_backup: No %s file.\n"), 2992 NSCONFIGFILE); 2993 } 2994 2995 return (ret); 2996 } 2997 2998 /* 2999 * mod_backup() 3000 * 3001 * This function is used to temporily backup the LDAP client files in /var/ldap 3002 * that the "mod" operation needs to update. If an error occurs then the 3003 * function mod_recover() can be invoke to recover the unmodified files. 3004 */ 3005 static int 3006 mod_backup(void) 3007 { 3008 int rc; 3009 int retcode = CLIENT_SUCCESS; 3010 3011 rc = system(CMD_CP " " NSCONFIGFILE " " NSCONFIGFILE ".mod"); 3012 retcode += rc; 3013 if (mode_verbose) 3014 CLIENT_FPRINTF(stderr, 3015 gettext("mod_backup: backup %s for %s\n"), 3016 rc ? "failed" : "successful", NSCONFIGFILE); 3017 3018 rc = system(CMD_CP " " NSCREDFILE " " NSCREDFILE ".mod"); 3019 retcode += rc; 3020 if (mode_verbose) 3021 CLIENT_FPRINTF(stderr, 3022 gettext("mod_backup: backup %s for %s\n"), 3023 rc ? "failed" : "successful", NSCREDFILE); 3024 3025 rc = system(CMD_CP " " DOMAINNAME " " DOMAINNAME ".mod"); 3026 retcode += rc; 3027 if (mode_verbose) 3028 CLIENT_FPRINTF(stderr, 3029 gettext("mod_backup: backup %s for %s\n"), 3030 rc ? "failed" : "successful", DOMAINNAME); 3031 3032 if (retcode != CLIENT_SUCCESS) 3033 retcode = CLIENT_ERR_RENAME; 3034 return (retcode); 3035 } 3036 3037 /* 3038 * mod_recover() 3039 * 3040 * This function is used to recover the temporily backed up files by 3041 * the mod_backup() function if an error occurs during the "mod" 3042 * operation. 3043 */ 3044 static int 3045 mod_recover(void) 3046 { 3047 int rc; 3048 int retcode = CLIENT_SUCCESS; 3049 3050 rc = system(CMD_MV " " NSCONFIGFILE ".mod " NSCONFIGFILE); 3051 retcode += rc; 3052 if (mode_verbose) 3053 CLIENT_FPRINTF(stderr, 3054 gettext("mod_recover: recovery %s for %s\n"), 3055 rc ? "failed" : "successful", NSCONFIGFILE); 3056 3057 rc = system(CMD_MV " " NSCREDFILE ".mod " NSCREDFILE); 3058 retcode += rc; 3059 if (mode_verbose) 3060 CLIENT_FPRINTF(stderr, 3061 gettext("mod_recover: recovery %s for %s\n"), 3062 rc ? "failed" : "successful", NSCREDFILE); 3063 3064 rc = system(CMD_MV " " DOMAINNAME ".mod " DOMAINNAME); 3065 retcode += rc; 3066 if (mode_verbose) 3067 CLIENT_FPRINTF(stderr, 3068 gettext("mod_recover: recovery %s for %s\n"), 3069 rc ? "failed" : "successful", DOMAINNAME); 3070 3071 if (retcode != CLIENT_SUCCESS) 3072 retcode = CLIENT_ERR_RENAME; 3073 return (retcode); 3074 } 3075 3076 /* 3077 * mod_cleanup() 3078 * 3079 * This function removes the .mod files in /var/ldap. 3080 */ 3081 static void 3082 mod_cleanup(void) 3083 { 3084 (void) system(CMD_RM " " NSCONFIGFILE ".mod " TO_DEV_NULL); 3085 (void) system(CMD_RM " " NSCREDFILE ".mod " TO_DEV_NULL); 3086 (void) system(CMD_RM " " DOMAINNAME ".mod " TO_DEV_NULL); 3087 } 3088 3089 #define MAX_DN_ARRAY 100 3090 #define LDAP_NAMINGCONTEXTS "namingcontexts" 3091 3092 static multival_t * 3093 multival_new() 3094 { 3095 multival_t *hold; 3096 3097 hold = calloc(1, sizeof (multival_t)); 3098 if (hold == NULL) { 3099 CLIENT_FPUTS( 3100 gettext("multival_new: Memory allocation error\n"), 3101 stderr); 3102 } 3103 return (hold); /* NULL -> error */ 3104 } 3105 3106 static int 3107 multival_add(multival_t *list, char *opt) 3108 { 3109 if (opt == NULL) { 3110 CLIENT_FPUTS( 3111 gettext("Empty value passed to multival_add\n"), 3112 stderr); 3113 return (CLIENT_ERR_FAIL); 3114 } 3115 3116 if (list->count == 0) { 3117 list->optlist = (char **)malloc(sizeof (char **)); 3118 } else { 3119 list->optlist = (char **)realloc(list->optlist, 3120 (list->count + 1) * sizeof (char **)); 3121 } 3122 3123 if (list->optlist == NULL) { 3124 CLIENT_FPUTS(gettext("Error allocating memory\n"), stderr); 3125 return (CLIENT_ERR_MEMORY); /* 0 is success */ 3126 } 3127 3128 list->optlist[list->count] = opt; 3129 list->count++; 3130 3131 return (CLIENT_SUCCESS); 3132 } 3133 3134 static void 3135 multival_free(multival_t *list) 3136 { 3137 if (list == NULL) 3138 return; 3139 3140 if (list->optlist != NULL) 3141 free(list->optlist); 3142 free(list); 3143 } 3144 3145 static clientopts_t * 3146 clientopts_new() 3147 { 3148 clientopts_t *hold; 3149 3150 hold = calloc(1, sizeof (clientopts_t)); 3151 if (NULL == hold) { 3152 CLIENT_FPUTS(gettext("Error allocating memory for " 3153 "clientopts structure\n"), stderr); 3154 return (hold); /* NULL -> error */ 3155 } 3156 3157 hold->serviceAuthenticationMethod = multival_new(); 3158 if (NULL == hold->serviceAuthenticationMethod) { 3159 CLIENT_FPUTS(gettext("Error allocating memory for " 3160 "serviceAuthenticationMethod\n"), stderr); 3161 free(hold); 3162 return (NULL); /* NULL -> error */ 3163 } 3164 3165 hold->serviceCredentialLevel = multival_new(); 3166 if (NULL == hold->serviceCredentialLevel) { 3167 CLIENT_FPUTS(gettext("Error allocating memory for " 3168 "serviceCredentialLevel\n"), stderr); 3169 multival_free(hold->serviceAuthenticationMethod); 3170 free(hold); 3171 return (NULL); /* NULL -> error */ 3172 } 3173 3174 hold->objectclassMap = multival_new(); 3175 if (NULL == hold->objectclassMap) { 3176 CLIENT_FPUTS(gettext("Error allocating memory for " 3177 "objectclassMap\n"), stderr); 3178 multival_free(hold->serviceAuthenticationMethod); 3179 multival_free(hold->serviceCredentialLevel); 3180 free(hold); 3181 return (NULL); /* NULL -> error */ 3182 } 3183 3184 hold->attributeMap = multival_new(); 3185 if (NULL == hold->attributeMap) { 3186 CLIENT_FPUTS(gettext("Error allocating memory for " 3187 "attributeMap\n"), stderr); 3188 multival_free(hold->serviceAuthenticationMethod); 3189 multival_free(hold->serviceCredentialLevel); 3190 multival_free(hold->objectclassMap); 3191 free(hold); 3192 return (NULL); /* NULL -> error */ 3193 } 3194 3195 hold->serviceSearchDescriptor = multival_new(); 3196 if (NULL == hold->serviceSearchDescriptor) { 3197 CLIENT_FPUTS(gettext("Error allocating memory for " 3198 "serviceSearchDescriptor\n"), stderr); 3199 multival_free(hold->serviceAuthenticationMethod); 3200 multival_free(hold->serviceCredentialLevel); 3201 multival_free(hold->objectclassMap); 3202 multival_free(hold->attributeMap); 3203 free(hold); 3204 return (NULL); /* NULL -> error */ 3205 } 3206 3207 return (hold); 3208 } 3209 3210 static void 3211 clientopts_free(clientopts_t *list) 3212 { 3213 if (NULL == list) 3214 return; 3215 3216 multival_free(list->serviceAuthenticationMethod); 3217 multival_free(list->serviceCredentialLevel); 3218 multival_free(list->objectclassMap); 3219 multival_free(list->attributeMap); 3220 multival_free(list->serviceSearchDescriptor); 3221 3222 free(list); 3223 3224 } 3225 3226 static void 3227 multival_list(char *opt, multival_t *list) 3228 { 3229 int i; 3230 3231 if (list->count == 0) 3232 return; 3233 3234 (void) puts(opt); 3235 for (i = 0; i < list->count; i++) { 3236 (void) printf("\t\targ[%d]: %s\n", i, list->optlist[i]); 3237 } 3238 } 3239 3240 /* return the number of arguments specified in the command line */ 3241 static int 3242 num_args(clientopts_t *list) 3243 { 3244 int arg_count = 0; 3245 3246 arg_count += list->authenticationMethod ? 1 : 0; 3247 arg_count += list->serviceAuthenticationMethod->count; 3248 arg_count += list->defaultSearchBase ? 1 : 0; 3249 arg_count += list->credentialLevel ? 1 : 0; 3250 arg_count += list->serviceCredentialLevel->count; 3251 arg_count += list->domainName ? 1 : 0; 3252 arg_count += list->proxyDN ? 1 : 0; 3253 arg_count += list->enableShadowUpdate ? 1 : 0; 3254 arg_count += list->adminDN ? 1 : 0; 3255 arg_count += list->profileTTL ? 1 : 0; 3256 arg_count += list->objectclassMap->count; 3257 arg_count += list->searchTimeLimit ? 1 : 0; 3258 arg_count += list->preferredServerList ? 1 : 0; 3259 arg_count += list->profileName ? 1 : 0; 3260 arg_count += list->followReferrals ? 1 : 0; 3261 arg_count += list->attributeMap->count; 3262 arg_count += list->defaultSearchScope ? 1 : 0; 3263 arg_count += list->serviceSearchDescriptor->count; 3264 arg_count += list->bindTimeLimit ? 1 : 0; 3265 arg_count += list->proxyPassword ? 1 : 0; 3266 arg_count += list->adminPassword ? 1 : 0; 3267 arg_count += list->defaultServerList ? 1 : 0; 3268 arg_count += list->certificatePath ? 1 : 0; 3269 3270 return (arg_count); 3271 } 3272 3273 #define CLIENT_PRINT(opt, str) if (str) \ 3274 (void) printf("%s%s\n", (opt), (str)) 3275 3276 static void 3277 dumpargs(clientopts_t *list) 3278 { 3279 CLIENT_PRINT("\tauthenticationMethod: ", list->authenticationMethod); 3280 multival_list("\tserviceAuthenticationMethod: ", 3281 list->serviceAuthenticationMethod); 3282 CLIENT_PRINT("\tdefaultSearchBase: ", list->defaultSearchBase); 3283 CLIENT_PRINT("\tcredentialLevel: ", list->credentialLevel); 3284 multival_list("\tserviceCredentialLevel: ", 3285 list->serviceCredentialLevel); 3286 CLIENT_PRINT("\tdomainName: ", list->domainName); 3287 CLIENT_PRINT("\tproxyDN: ", list->proxyDN); 3288 CLIENT_PRINT("\tadminDN: ", list->adminDN); 3289 CLIENT_PRINT("\tenableShadowUpdate: ", list->enableShadowUpdate); 3290 CLIENT_PRINT("\tprofileTTL: ", list->profileTTL); 3291 multival_list("\tobjectclassMap: ", list->objectclassMap); 3292 CLIENT_PRINT("\tsearchTimeLimit: ", list->searchTimeLimit); 3293 CLIENT_PRINT("\tpreferredServerList: ", list->preferredServerList); 3294 CLIENT_PRINT("\tprofileName: ", list->profileName); 3295 CLIENT_PRINT("\tfollowReferrals: ", list->followReferrals); 3296 multival_list("\tattributeMap: ", list->attributeMap); 3297 CLIENT_PRINT("\tdefaultSearchScope: ", list->defaultSearchScope); 3298 multival_list("\tserviceSearchDescriptor: ", 3299 list->serviceSearchDescriptor); 3300 CLIENT_PRINT("\tbindTimeLimit: ", list->bindTimeLimit); 3301 CLIENT_PRINT("\tproxyPassword: ", list->proxyPassword); 3302 CLIENT_PRINT("\tadminPassword: ", list->adminPassword); 3303 CLIENT_PRINT("\tdefaultServerList: ", list->defaultServerList); 3304 CLIENT_PRINT("\tcertificatePath: ", list->certificatePath); 3305 } 3306 3307 3308 /* These definitions are only used in parseParam() below. */ 3309 struct param { 3310 char *name; 3311 int index; 3312 }; 3313 3314 static struct param paramArray[] = { 3315 {"proxyDN", NS_LDAP_BINDDN_P}, 3316 {"proxyPassword", NS_LDAP_BINDPASSWD_P}, 3317 {"defaultServerList", NS_LDAP_SERVERS_P}, 3318 {"defaultSearchBase", NS_LDAP_SEARCH_BASEDN_P}, 3319 {"authenticationMethod", NS_LDAP_AUTH_P}, 3320 {"followReferrals", NS_LDAP_SEARCH_REF_P}, 3321 {"profileTTL", NS_LDAP_CACHETTL_P}, 3322 {"certificatePath", NS_LDAP_HOST_CERTPATH_P}, 3323 {"defaultSearchScope", NS_LDAP_SEARCH_SCOPE_P}, 3324 {"bindTimeLimit", NS_LDAP_BIND_TIME_P}, 3325 {"searchTimeLimit", NS_LDAP_SEARCH_TIME_P}, 3326 {"preferredServerList", NS_LDAP_SERVER_PREF_P}, 3327 {"profileName", NS_LDAP_PROFILE_P}, 3328 {"credentialLevel", NS_LDAP_CREDENTIAL_LEVEL_P}, 3329 {"serviceSearchDescriptor", NS_LDAP_SERVICE_SEARCH_DESC_P}, 3330 {"attributeMap", NS_LDAP_ATTRIBUTEMAP_P}, 3331 {"objectclassMap", NS_LDAP_OBJECTCLASSMAP_P}, 3332 {"serviceAuthenticationMethod", NS_LDAP_SERVICE_AUTH_METHOD_P}, 3333 {"serviceCredentialLevel", NS_LDAP_SERVICE_CRED_LEVEL_P}, 3334 {"domainName", LOCAL_DOMAIN_P}, 3335 {"enableShadowUpdate", NS_LDAP_ENABLE_SHADOW_UPDATE_P}, 3336 {"adminDN", NS_LDAP_ADMIN_BINDDN_P}, 3337 {"adminPassword", NS_LDAP_ADMIN_BINDPASSWD_P}, 3338 {NULL, 0} 3339 }; 3340 3341 static int 3342 parseParam(char *param, char **paramVal) 3343 { 3344 char *val = NULL; 3345 int counter; 3346 3347 if (mode_verbose) { 3348 CLIENT_FPRINTF(stderr, gettext("Parsing %s\n"), param); 3349 } 3350 3351 val = strchr(param, '='); 3352 if (val == NULL) { 3353 CLIENT_FPUTS( 3354 gettext("Didn\'t find \'=\' character in string\n"), 3355 stderr); 3356 paramVal = NULL; 3357 return (CLIENT_ERR_PARSE); 3358 } 3359 3360 *val = '\0'; 3361 3362 for (counter = 0; paramArray[counter].name != NULL; counter++) { 3363 if (strcasecmp(paramArray[counter].name, param) == 0) { 3364 *paramVal = val+1; 3365 *val = '='; /* restore original param */ 3366 return (paramArray[counter].index); 3367 } 3368 } 3369 3370 /* Not found */ 3371 *val = '='; /* restore original param */ 3372 *paramVal = NULL; 3373 return (CLIENT_ERR_PARSE); 3374 } 3375 3376 /* 3377 * The following macro checks if an option has already been specified 3378 * and errs out with usage if so 3379 */ 3380 #define CLIENT_OPT_CHECK(opt, optarg) \ 3381 if (optarg) { \ 3382 CLIENT_FPUTS(gettext("Invalid use of option\n"), stderr); \ 3383 usage(); \ 3384 clientopts_free(optlist); \ 3385 return (CLIENT_ERR_FAIL); \ 3386 } 3387 3388 static int 3389 clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal) 3390 { 3391 int retcode = 0; 3392 int counter; 3393 3394 3395 switch (paramFlag) { 3396 case NS_LDAP_AUTH_P: 3397 CLIENT_OPT_CHECK(paramFlag, optlist->authenticationMethod); 3398 optlist->authenticationMethod = attrVal; 3399 break; 3400 3401 case NS_LDAP_SERVICE_AUTH_METHOD_P: /* multiple allowed */ 3402 retcode = multival_add(optlist->serviceAuthenticationMethod, 3403 attrVal); 3404 if (retcode != CLIENT_SUCCESS) { 3405 CLIENT_FPRINTF(stderr, 3406 gettext("Error processing attrVal %s\n"), 3407 attrVal?attrVal:"NULL"); 3408 usage(); 3409 clientopts_free(optlist); 3410 return (CLIENT_ERR_FAIL); 3411 } 3412 break; 3413 3414 case NS_LDAP_SEARCH_BASEDN_P: 3415 CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchBase); 3416 optlist->defaultSearchBase = attrVal; 3417 break; 3418 3419 case NS_LDAP_CREDENTIAL_LEVEL_P: 3420 CLIENT_OPT_CHECK(paramFlag, optlist->credentialLevel); 3421 optlist->credentialLevel = attrVal; 3422 break; 3423 3424 case NS_LDAP_SERVICE_CRED_LEVEL_P: /* multiple allowed */ 3425 retcode = multival_add(optlist->serviceCredentialLevel, 3426 attrVal); 3427 if (retcode != CLIENT_SUCCESS) { 3428 CLIENT_FPRINTF(stderr, 3429 gettext("Error processing attrVal %s\n"), 3430 attrVal?attrVal:"NULL"); 3431 usage(); 3432 clientopts_free(optlist); 3433 return (CLIENT_ERR_FAIL); 3434 } 3435 break; 3436 3437 case LOCAL_DOMAIN_P: 3438 CLIENT_OPT_CHECK(paramFlag, optlist->domainName); 3439 optlist->domainName = attrVal; 3440 dname = optlist->domainName; 3441 break; 3442 3443 case NS_LDAP_BINDDN_P: 3444 CLIENT_OPT_CHECK(paramFlag, optlist->proxyDN); 3445 optlist->proxyDN = attrVal; 3446 break; 3447 3448 case NS_LDAP_ENABLE_SHADOW_UPDATE_P: 3449 CLIENT_OPT_CHECK(paramFlag, optlist->enableShadowUpdate); 3450 optlist->enableShadowUpdate = attrVal; 3451 break; 3452 3453 case NS_LDAP_ADMIN_BINDDN_P: 3454 CLIENT_OPT_CHECK(paramFlag, optlist->adminDN); 3455 optlist->adminDN = attrVal; 3456 break; 3457 3458 case NS_LDAP_CACHETTL_P: 3459 CLIENT_OPT_CHECK(paramFlag, optlist->profileTTL); 3460 optlist->profileTTL = attrVal; 3461 break; 3462 3463 case NS_LDAP_OBJECTCLASSMAP_P: /* multiple allowed */ 3464 retcode = multival_add(optlist->objectclassMap, attrVal); 3465 if (retcode != CLIENT_SUCCESS) { 3466 CLIENT_FPRINTF(stderr, 3467 gettext("Error processing attrVal %s\n"), 3468 attrVal?attrVal:"NULL"); 3469 usage(); 3470 clientopts_free(optlist); 3471 return (CLIENT_ERR_FAIL); 3472 } 3473 break; 3474 3475 case NS_LDAP_SEARCH_TIME_P: 3476 CLIENT_OPT_CHECK(paramFlag, optlist->searchTimeLimit); 3477 optlist->searchTimeLimit = attrVal; 3478 break; 3479 3480 case NS_LDAP_SERVER_PREF_P: 3481 CLIENT_OPT_CHECK(paramFlag, optlist->preferredServerList); 3482 optlist->preferredServerList = attrVal; 3483 /* replace ',' chars with ' ' for proper syntax */ 3484 for (counter = 0; 3485 counter < strlen(optlist->preferredServerList); 3486 counter++) { 3487 3488 if (optlist->preferredServerList[counter] == ',') 3489 optlist->preferredServerList[counter] = ' '; 3490 } 3491 break; 3492 3493 case NS_LDAP_PROFILE_P: 3494 CLIENT_OPT_CHECK(paramFlag, optlist->profileName); 3495 optlist->profileName = attrVal; 3496 break; 3497 3498 case NS_LDAP_SEARCH_REF_P: 3499 CLIENT_OPT_CHECK(paramFlag, optlist->followReferrals); 3500 if (0 == strcasecmp(attrVal, "followref")) 3501 optlist->followReferrals = "TRUE"; 3502 else if (0 == strcasecmp(attrVal, "noref")) 3503 optlist->followReferrals = "FALSE"; 3504 else 3505 optlist->followReferrals = attrVal; 3506 break; 3507 3508 case NS_LDAP_ATTRIBUTEMAP_P: /* multiple allowed */ 3509 retcode = multival_add(optlist->attributeMap, attrVal); 3510 if (retcode != CLIENT_SUCCESS) { 3511 CLIENT_FPRINTF(stderr, 3512 gettext("Error processing attrVal %s\n"), 3513 attrVal?attrVal:"NULL"); 3514 usage(); 3515 clientopts_free(optlist); 3516 return (CLIENT_ERR_FAIL); 3517 } 3518 break; 3519 3520 case NS_LDAP_SEARCH_SCOPE_P: 3521 CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchScope); 3522 optlist->defaultSearchScope = attrVal; 3523 break; 3524 3525 case NS_LDAP_SERVICE_SEARCH_DESC_P: /* multiple allowed */ 3526 retcode = multival_add(optlist->serviceSearchDescriptor, 3527 attrVal); 3528 if (retcode != CLIENT_SUCCESS) { 3529 CLIENT_FPRINTF(stderr, 3530 gettext("Error processing attrVal %s\n"), 3531 attrVal?attrVal:"NULL"); 3532 usage(); 3533 clientopts_free(optlist); 3534 return (CLIENT_ERR_FAIL); 3535 } 3536 break; 3537 3538 case NS_LDAP_BIND_TIME_P: 3539 CLIENT_OPT_CHECK(paramFlag, optlist->bindTimeLimit); 3540 optlist->bindTimeLimit = attrVal; 3541 break; 3542 3543 case NS_LDAP_BINDPASSWD_P: 3544 CLIENT_OPT_CHECK(paramFlag, optlist->proxyPassword); 3545 optlist->proxyPassword = attrVal; 3546 break; 3547 3548 case NS_LDAP_ADMIN_BINDPASSWD_P: 3549 CLIENT_OPT_CHECK(paramFlag, optlist->adminPassword); 3550 optlist->adminPassword = attrVal; 3551 break; 3552 3553 case NS_LDAP_HOST_CERTPATH_P: 3554 CLIENT_OPT_CHECK(paramFlag, optlist->certificatePath); 3555 optlist->certificatePath = attrVal; 3556 break; 3557 3558 case NS_LDAP_SERVERS_P: 3559 CLIENT_OPT_CHECK(paramFlag, optlist->defaultServerList); 3560 optlist->defaultServerList = attrVal; 3561 break; 3562 3563 default: 3564 usage(); 3565 return (CLIENT_ERR_FAIL); 3566 /* break; lint doesn't like break before end of switch */ 3567 } 3568 3569 return (retcode); 3570 } 3571 3572 /* 3573 * file_move() - Used to move a config file (backup/restore). 3574 * 3575 * This function uses a system() call with /bin/mv to handle the 3576 * case where the backup directory (/var) is on a different file 3577 * system than the config file (typically /etc). 3578 */ 3579 static int 3580 file_move(const char *from, const char *to) 3581 { 3582 int retcode; 3583 char mvCommand[] = CMD_MV; 3584 char cmd_buffer[(2 * MAXPATHLEN) + sizeof (mvCommand) + 3]; 3585 3586 (void) snprintf(cmd_buffer, sizeof (cmd_buffer), "%s %s %s", 3587 mvCommand, from, to); 3588 3589 /* 3590 * This function should only be used internally to move 3591 * system files to/from the backup directory. For security 3592 * reasons (this is run as root), don't use this function 3593 * with arguments passed into the program. 3594 */ 3595 retcode = system(cmd_buffer); 3596 3597 return (retcode); 3598 } 3599 3600 3601 /* 3602 * Manipulate the service as instructed by "dowhat" 3603 */ 3604 static int 3605 do_service(const char *fmri, boolean_t waitflag, int dowhat, 3606 const char *state) { 3607 3608 int status; 3609 boolean_t is_maint; 3610 const char *what = gettext("not set"); 3611 useconds_t max; 3612 3613 /* Check if we are in maintenance */ 3614 is_maint = is_service(fmri, SCF_STATE_STRING_MAINT); 3615 3616 switch (dowhat) { 3617 case START_SERVICE: 3618 what = gettext("start"); 3619 status = smf_enable_instance(fmri, 3620 (sysid_install == B_TRUE)?SMF_TEMPORARY:0); 3621 break; 3622 case STOP_SERVICE: 3623 what = gettext("stop"); 3624 status = smf_disable_instance(fmri, 3625 (sysid_install == B_TRUE)?SMF_TEMPORARY:0); 3626 break; 3627 case RESTART_SERVICE: 3628 what = gettext("restart"); 3629 status = smf_restart_instance(fmri); 3630 break; 3631 default: 3632 /* coding error; will not happen */ 3633 assert(0); 3634 } 3635 3636 /* 3637 * If the service was previously in maintenance then we need to 3638 * clear it immediately. The "dowhat" action will set the 3639 * enabled property of the service as intended by the caller while 3640 * clear will actually cause it to be enabled/disabled. 3641 * We assume that the caller has called us after taking some 3642 * recovery action. Even if it's not the case, we don't lose 3643 * anything. 3644 */ 3645 if (status == 0 && is_maint == B_TRUE) { 3646 if (mode_verbose) 3647 CLIENT_FPRINTF(stderr, 3648 "%s: %s... %s\n", 3649 what, 3650 fmri, 3651 gettext("restoring from maintenance state")); 3652 status = smf_restore_instance(fmri); 3653 } 3654 3655 if (status == 0) { 3656 /* Check if we need to wait ? */ 3657 if (waitflag == B_FALSE) { 3658 if (mode_verbose) 3659 CLIENT_FPRINTF(stderr, 3660 "%s: %s... %s\n", 3661 what, 3662 fmri, 3663 gettext("success")); 3664 return (CLIENT_SUCCESS); 3665 } 3666 3667 /* Otherwise wait for max seconds (from the manifest) */ 3668 max = get_timeout_value(dowhat, fmri, DEFAULT_TIMEOUT); 3669 status = wait_till(fmri, state, max, what, !is_maint); 3670 if (status == CLIENT_SUCCESS) 3671 return (CLIENT_SUCCESS); 3672 /* For error fall through for corrective action */ 3673 } else { 3674 /* Well, service failed ... */ 3675 if (mode_verbose) 3676 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n", 3677 what, 3678 fmri, 3679 gettext("failed"), 3680 scf_strerror(scf_error())); 3681 status = CLIENT_ERR_FAIL; 3682 /* For error fall through for corrective action */ 3683 } 3684 3685 /* 3686 * If service is still offline after start/restart, then transitioning 3687 * failed and guess is restarter failed to apply the timeout as well. 3688 * So instead of leaving it offline, let's just disable it until we have 3689 * some other mechanism available from smf to handle such situation. 3690 */ 3691 if (dowhat != STOP_SERVICE) 3692 if (is_service(fmri, SCF_STATE_STRING_OFFLINE)) { 3693 if (mode_verbose) 3694 CLIENT_FPRINTF(stderr, 3695 "%s: %s... %s\n", 3696 what, 3697 fmri, 3698 gettext("offline to disable")); 3699 (void) disable_service(fmri, waitflag); 3700 } 3701 3702 return (status); 3703 } 3704 3705 3706 /* 3707 * Wait for "max" usecs for the service described by "fmri" to change 3708 * to "state". If check_maint is true then return immediately if 3709 * service goes into maintenance 3710 */ 3711 static int 3712 wait_till(const char *fmri, const char *state, useconds_t max, 3713 const char *what, boolean_t check_maint) { 3714 char *st; 3715 useconds_t usecs = INIT_WAIT_USECS; 3716 3717 for (; max > 0; max -= usecs) { 3718 /* incremental wait */ 3719 usecs *= 2; 3720 usecs = (usecs > max)?max:usecs; 3721 if (mode_verbose) 3722 CLIENT_FPRINTF(stderr, 3723 "%s: %s %u %s\n", 3724 what, gettext("sleep"), usecs, 3725 gettext("microseconds")); 3726 (void) usleep(usecs); 3727 3728 /* Check state after the wait */ 3729 if ((st = smf_get_state(fmri)) != NULL) { 3730 if (strcmp(st, state) == 0) { 3731 if (mode_verbose) 3732 CLIENT_FPRINTF(stderr, 3733 "%s: %s... %s\n", 3734 what, 3735 fmri, 3736 gettext("success")); 3737 free(st); 3738 return (CLIENT_SUCCESS); 3739 } 3740 3741 /* 3742 * If service has gone into maintenance then 3743 * we will time out anyway, so we are better 3744 * off returning now 3745 */ 3746 if (check_maint && 3747 strcmp(st, SCF_STATE_STRING_MAINT) == 0) { 3748 if (mode_verbose) 3749 CLIENT_FPRINTF(stderr, 3750 "%s: %s... %s\n", 3751 what, 3752 fmri, 3753 gettext("maintenance")); 3754 free(st); 3755 return (CLIENT_ERR_MAINTENANCE); 3756 } 3757 free(st); 3758 } else { 3759 if (mode_verbose) 3760 CLIENT_FPRINTF(stderr, 3761 "%s: %s... %s: %s\n", 3762 what, 3763 fmri, 3764 gettext("failed"), 3765 scf_strerror(scf_error())); 3766 return (CLIENT_ERR_FAIL); 3767 } 3768 } 3769 3770 /* Timed out waiting */ 3771 if (mode_verbose) 3772 CLIENT_FPRINTF(stderr, 3773 "%s: %s... %s\n", 3774 what, 3775 fmri, 3776 gettext("timed out")); 3777 return (CLIENT_ERR_TIMEDOUT); 3778 } 3779 3780 3781 static boolean_t 3782 is_service(const char *fmri, const char *state) { 3783 char *st; 3784 boolean_t result = B_FALSE; 3785 3786 if ((st = smf_get_state(fmri)) != NULL) { 3787 if (strcmp(st, state) == 0) 3788 result = B_TRUE; 3789 free(st); 3790 } 3791 return (result); 3792 } 3793 3794 3795 /* 3796 * 3797 * get_timeout_val : returns the timeout value set in fmri manifest 3798 * inputs : action(start/stop) 3799 * fmri(defined fmri string) 3800 * Returns default if error, the timeout val otherwise 3801 * 3802 */ 3803 3804 static useconds_t 3805 get_timeout_value(int dowhat, const char *fmri, useconds_t default_val) 3806 { 3807 scf_simple_prop_t *sp = NULL; 3808 uint64_t *cp = NULL; 3809 int timeout = default_val/1000000; 3810 char *action = NULL; 3811 const char *actionstr = NULL; 3812 3813 switch (dowhat) { 3814 case START_SERVICE: 3815 case RESTART_SERVICE: 3816 action = "start"; 3817 actionstr = gettext("start"); 3818 break; 3819 case STOP_SERVICE: 3820 action = "stop"; 3821 actionstr = gettext("stop"); 3822 break; 3823 default: 3824 assert(0); 3825 } 3826 3827 3828 sp = scf_simple_prop_get(NULL, fmri, action, SCF_PROPERTY_TIMEOUT); 3829 if (sp == NULL) { 3830 if (mode_verbose) 3831 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n", 3832 actionstr, 3833 fmri, 3834 gettext("failed to retrieve timeout property"), 3835 scf_strerror(scf_error())); 3836 return (default_val); 3837 } 3838 3839 cp = scf_simple_prop_next_count(sp); 3840 if (cp == NULL) { 3841 if (mode_verbose) 3842 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n", 3843 actionstr, 3844 fmri, 3845 gettext("failed to retrieve timeout value"), 3846 scf_strerror(scf_error())); 3847 scf_simple_prop_free(sp); 3848 return (default_val); 3849 } 3850 3851 if (*cp != 0) 3852 timeout = *cp; 3853 scf_simple_prop_free(sp); 3854 return (timeout * 1000000); 3855 } 3856