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