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
main(int argc,char ** argv)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
client_list(clientopts_t * arglist)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
client_uninit(clientopts_t * arglist)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
client_manual(clientopts_t * arglist)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
client_mod(clientopts_t * arglist)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
client_genProfile(clientopts_t * arglist)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
client_init(clientopts_t * arglist)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
usage(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
stop_services(int saveState)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
start_services(int flag)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
credCheck(clientopts_t * arglist)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
adminCredCheck(clientopts_t * arglist)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
recover(int saveState)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
file_backup(void)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
mod_backup(void)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
mod_recover(void)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
mod_cleanup(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 *
multival_new()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
multival_add(multival_t * list,char * opt)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
multival_free(multival_t * list)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 *
clientopts_new()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
clientopts_free(clientopts_t * list)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
multival_list(char * opt,multival_t * list)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
num_args(clientopts_t * list)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
dumpargs(clientopts_t * list)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
parseParam(char * param,char ** paramVal)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
clientSetParam(clientopts_t * optlist,int paramFlag,char * attrVal)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
file_move(const char * from,const char * to)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
do_service(const char * fmri,boolean_t waitflag,int dowhat,const char * state)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
wait_till(const char * fmri,const char * state,useconds_t max,const char * what,boolean_t check_maint)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
is_service(const char * fmri,const char * state)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
get_timeout_value(int dowhat,const char * fmri,useconds_t default_val)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