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