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