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