10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8821SMichen.Chang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * ldapclient command. To make (initiailize) or uninitialize a machines as
280Sstevel@tonic-gate  * and LDAP client.  This command MUST be run as root (or it will simply exit).
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  *	-I	Install. No file_backup/recover for installing only (no doc).
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  *	init	Initialze (create) an LDAP client from a profile stored
330Sstevel@tonic-gate  *		in a directory-server.
340Sstevel@tonic-gate  *	manual	Initialze (create) an LDAP client by hand (-file option
350Sstevel@tonic-gate  *		reads from file).
360Sstevel@tonic-gate  *	mod	Modify the LDAP client configuration on this machine by hand.
370Sstevel@tonic-gate  *	list	List the contents of the LDAP client cache files.
380Sstevel@tonic-gate  *	uninit	Uninitialize this machine.
390Sstevel@tonic-gate  *
400Sstevel@tonic-gate  *	-v	Verbose flag.
410Sstevel@tonic-gate  *	-q	Quiet flag (mutually exclusive with -v).
420Sstevel@tonic-gate  *
430Sstevel@tonic-gate  *	-a attrName=attrVal
440Sstevel@tonic-gate  *	<attrName> can be one of the following:
450Sstevel@tonic-gate  *
460Sstevel@tonic-gate  *	attributeMap
470Sstevel@tonic-gate  *		Attribute map.  Can be multiple instances of this option.
480Sstevel@tonic-gate  *		(no former option)
490Sstevel@tonic-gate  *	authenticationMethod
500Sstevel@tonic-gate  *		Authentication method (formerly -a)
510Sstevel@tonic-gate  *	bindTimeLimit
520Sstevel@tonic-gate  *		Bind time limit. (no former option)
530Sstevel@tonic-gate  *	certificatePath
540Sstevel@tonic-gate  *		Path to certificates used for secure bind (no former option)
550Sstevel@tonic-gate  *	credentialLevel
560Sstevel@tonic-gate  *		Client credential level (no former option)
570Sstevel@tonic-gate  *	defaultServerList
580Sstevel@tonic-gate  *		Default server (no former option) Refer to DUA Config
590Sstevel@tonic-gate  *		Schema draft.
600Sstevel@tonic-gate  *	defaultSearchBase
610Sstevel@tonic-gate  *		Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b)
620Sstevel@tonic-gate  *	defaultSearchScope
630Sstevel@tonic-gate  *		Search scope. (formerly -s)
640Sstevel@tonic-gate  *	domainName
650Sstevel@tonic-gate  *		Hosts lookup domain (DNS)  Ex. eng.sun.com (formerly -d)
660Sstevel@tonic-gate  *	followReferrals
670Sstevel@tonic-gate  *		Search dereference. followref or noref (default followref)
680Sstevel@tonic-gate  *		(formerly -r)
690Sstevel@tonic-gate  *	objectclassMap
700Sstevel@tonic-gate  *		Objectclass map.  Can be multiple instances of this option.
710Sstevel@tonic-gate  *		(no former option)
720Sstevel@tonic-gate  *	preferredServerList
730Sstevel@tonic-gate  *		Server preference list. Comma ',' seperated list of IPaddr.
740Sstevel@tonic-gate  *		(formerly -p)
750Sstevel@tonic-gate  *	profileName
760Sstevel@tonic-gate  *		Profile name to use for init (ldapclient) or
770Sstevel@tonic-gate  *		generate (gen_profile). (formerly -P)
780Sstevel@tonic-gate  *	profileTTL
790Sstevel@tonic-gate  *		Client info TTL.  If set to 0 this information will not be
800Sstevel@tonic-gate  *		automatically updated by the ldap_cachemgr(1M).
810Sstevel@tonic-gate  *		(formerly -e)
820Sstevel@tonic-gate  *	proxyDN
830Sstevel@tonic-gate  *		Binding DN.  Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com
840Sstevel@tonic-gate  *		(formerly -D)
850Sstevel@tonic-gate  *	proxyPassword
860Sstevel@tonic-gate  *		Client password not needed for authentication "none".
870Sstevel@tonic-gate  *		(formerly -w)
88*8821SMichen.Chang@Sun.COM  *	adminDN
89*8821SMichen.Chang@Sun.COM  *		Administrator DN for updating naming data.
90*8821SMichen.Chang@Sun.COM  *	adminPassword
91*8821SMichen.Chang@Sun.COM  *		Administrator password
92*8821SMichen.Chang@Sun.COM  *	enableShadowUpdate
93*8821SMichen.Chang@Sun.COM  *		Allow Administrator to change shadow data in LDAP
940Sstevel@tonic-gate  *	searchTimeLimit
950Sstevel@tonic-gate  *		Timeout value. (formerly -o)
960Sstevel@tonic-gate  *	serviceSearchDescriptor
970Sstevel@tonic-gate  *		Service search scope. (no former option)
980Sstevel@tonic-gate  *	serviceAuthenticationMethod
990Sstevel@tonic-gate  *		Service authenticaion method (no former option)
1000Sstevel@tonic-gate  *	serviceCredentialLevel
1010Sstevel@tonic-gate  *		Service credential level (no former option)
1020Sstevel@tonic-gate  *
1030Sstevel@tonic-gate  */
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #include <stdlib.h>
1060Sstevel@tonic-gate #include <stdio.h>
1070Sstevel@tonic-gate #include <unistd.h>
1080Sstevel@tonic-gate #include <errno.h>
1090Sstevel@tonic-gate #include <sys/types.h>
1100Sstevel@tonic-gate #include <time.h>
1110Sstevel@tonic-gate #include <sys/param.h>
1120Sstevel@tonic-gate #include <sys/stat.h>
1130Sstevel@tonic-gate #include <sys/systeminfo.h>
1140Sstevel@tonic-gate #include <fcntl.h>
1150Sstevel@tonic-gate #include <xti.h>
1160Sstevel@tonic-gate #include <strings.h>
1170Sstevel@tonic-gate #include <limits.h>
1180Sstevel@tonic-gate #include <locale.h>
1190Sstevel@tonic-gate #include <syslog.h>
1200Sstevel@tonic-gate #include <libscf.h>
1210Sstevel@tonic-gate #include <assert.h>
1226842Sth160488 
1236842Sth160488 #include "standalone.h"
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1260Sstevel@tonic-gate #define	TEXT_DOMAIN "SUNW_OST_OSCMD"
1270Sstevel@tonic-gate #endif
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate /* error codes */
1300Sstevel@tonic-gate /* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */
1310Sstevel@tonic-gate #define	CLIENT_SUCCESS		0
1320Sstevel@tonic-gate #define	CLIENT_ERR_PARSE	-1
1330Sstevel@tonic-gate #define	CLIENT_ERR_FAIL		1
1340Sstevel@tonic-gate #define	CLIENT_ERR_CREDENTIAL	2
1350Sstevel@tonic-gate #define	CLIENT_ERR_MEMORY	3
1360Sstevel@tonic-gate #define	CLIENT_ERR_RESTORE	4
1370Sstevel@tonic-gate #define	CLIENT_ERR_RENAME	5
1380Sstevel@tonic-gate #define	CLIENT_ERR_RECOVER	6
1390Sstevel@tonic-gate #define	CLIENT_ERR_TIMEDOUT	7
1400Sstevel@tonic-gate #define	CLIENT_ERR_MAINTENANCE	8
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /* Reset flag for start_services() */
1430Sstevel@tonic-gate #define	START_INIT	1
1440Sstevel@tonic-gate #define	START_RESET	2
1450Sstevel@tonic-gate #define	START_UNINIT	3
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate /* Reset flag for stop_services() */
1480Sstevel@tonic-gate #define	STATE_NOSAVE	0
1490Sstevel@tonic-gate #define	STATE_SAVE	1
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /* files to (possibiliy) restore */
1520Sstevel@tonic-gate #define	LDAP_RESTORE_DIR	"/var/ldap/restore"
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate #define	DOMAINNAME_DIR		"/etc"
1550Sstevel@tonic-gate #define	DOMAINNAME_FILE		"defaultdomain"
1560Sstevel@tonic-gate #define	DOMAINNAME		DOMAINNAME_DIR "/" DOMAINNAME_FILE
1570Sstevel@tonic-gate #define	DOMAINNAME_BACK		LDAP_RESTORE_DIR "/" DOMAINNAME_FILE
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate #define	NSSWITCH_DIR		"/etc"
1600Sstevel@tonic-gate #define	NSSWITCH_FILE		"nsswitch.conf"
1610Sstevel@tonic-gate #define	NSSWITCH_CONF		NSSWITCH_DIR "/" NSSWITCH_FILE
1620Sstevel@tonic-gate #define	NSSWITCH_BACK		LDAP_RESTORE_DIR "/" NSSWITCH_FILE
1630Sstevel@tonic-gate #define	NSSWITCH_LDAP		"/etc/nsswitch.ldap"
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate #define	NIS_COLDSTART_DIR	"/var/nis"
1660Sstevel@tonic-gate #define	NIS_COLDSTART_FILE	"NIS_COLD_START"
1670Sstevel@tonic-gate #define	NIS_COLDSTART		NIS_COLDSTART_DIR "/" NIS_COLDSTART_FILE
1680Sstevel@tonic-gate #define	NIS_COLDSTART_BACK	LDAP_RESTORE_DIR "/" NIS_COLDSTART_FILE
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate #define	YP_BIND_DIR		"/var/yp/binding"
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /* Define the service FMRIs */
1730Sstevel@tonic-gate #define	SENDMAIL_FMRI		"network/smtp:sendmail"
1740Sstevel@tonic-gate #define	NSCD_FMRI		"system/name-service-cache:default"
1750Sstevel@tonic-gate #define	AUTOFS_FMRI		"system/filesystem/autofs:default"
1760Sstevel@tonic-gate #define	LDAP_FMRI		"network/ldap/client:default"
1770Sstevel@tonic-gate #define	NISD_FMRI		"network/rpc/nisplus:default"
1780Sstevel@tonic-gate #define	YP_FMRI			"network/nis/client:default"
1790Sstevel@tonic-gate #define	NS_MILESTONE_FMRI	"milestone/name-services:default"
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /* Define flags for checking if services were enabled */
1820Sstevel@tonic-gate #define	SENDMAIL_ON	0x1
1830Sstevel@tonic-gate #define	NSCD_ON		0x10
1840Sstevel@tonic-gate #define	AUTOFS_ON	0x100
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate #define	CMD_DOMAIN_START	"/usr/bin/domainname"
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /* Command to copy files */
1890Sstevel@tonic-gate #define	CMD_CP			"/bin/cp -f"
1900Sstevel@tonic-gate #define	CMD_MV			"/bin/mv -f"
1910Sstevel@tonic-gate #define	CMD_RM			"/bin/rm -f"
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate #define	TO_DEV_NULL		" >/dev/null 2>&1"
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate /* Files that need to be just removed */
1960Sstevel@tonic-gate #define	NIS_PRIVATE_CACHE	"/var/nis/.NIS_PRIVATE_DIRCACHE"
1970Sstevel@tonic-gate #define	NIS_SHARED_CACHE	"/var/nis/NIS_SHARED_DIRCACHE"
1980Sstevel@tonic-gate #define	NIS_CLIENT_INFO		"/var/nis/client_info"
1990Sstevel@tonic-gate #define	LDAP_CACHE_LOG		"/var/ldap/cachemgr.log"
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /* Output defines to supress if quiet mode set */
2020Sstevel@tonic-gate #define	CLIENT_FPUTS if (!mode_quiet) (void) fputs
2030Sstevel@tonic-gate #define	CLIENT_FPRINTF if (!mode_quiet) (void) fprintf
2040Sstevel@tonic-gate #define	CLIENT_FPUTC if (!mode_quiet) (void) fputc
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate #define	restart_service(fmri, waitflag)\
2070Sstevel@tonic-gate 		do_service(fmri, waitflag, RESTART_SERVICE,\
2080Sstevel@tonic-gate 		SCF_STATE_STRING_ONLINE)
2090Sstevel@tonic-gate #define	start_service(fmri, waitflag)	\
2100Sstevel@tonic-gate 		do_service(fmri, waitflag, START_SERVICE,\
2110Sstevel@tonic-gate 		SCF_STATE_STRING_ONLINE)
2120Sstevel@tonic-gate #define	disable_service(fmri, waitflag)	\
2130Sstevel@tonic-gate 		do_service(fmri, waitflag, STOP_SERVICE,\
2140Sstevel@tonic-gate 		SCF_STATE_STRING_DISABLED)
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate  * There isn't a domainName defined as a param, so we set a value here
2180Sstevel@tonic-gate  * (1001) should be big enough
2190Sstevel@tonic-gate  */
2200Sstevel@tonic-gate #define	LOCAL_DOMAIN_P 1001
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate #define	START_SERVICE	1
2230Sstevel@tonic-gate #define	STOP_SERVICE	2
2240Sstevel@tonic-gate #define	RESTART_SERVICE	3
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate #define	DEFAULT_TIMEOUT	60000000
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate #define	INIT_WAIT_USECS	50000
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate /* Used to turn off profile checking */
2310Sstevel@tonic-gate #define	CACHETTL_OFF "0"
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate /* Globals */
2340Sstevel@tonic-gate static char *cmd;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate static char *dname = NULL;
2370Sstevel@tonic-gate static char dname_buf[BUFSIZ];
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate static boolean_t sysid_install = B_FALSE;
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate static int mode_verbose = 0;
2420Sstevel@tonic-gate static int mode_quiet = 0;
2430Sstevel@tonic-gate static int gen = 0;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate static int gStartLdap = 0;
2460Sstevel@tonic-gate static int gStartYp = 0;
2470Sstevel@tonic-gate static int gStartNisd = 0;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate static int enableFlag = 0;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate /* multival_t is used to hold params that can have more than one value */
2520Sstevel@tonic-gate typedef struct {
2530Sstevel@tonic-gate 	int count;
2540Sstevel@tonic-gate 	char **optlist;
2550Sstevel@tonic-gate } multival_t;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate static multival_t *multival_new();
2580Sstevel@tonic-gate static int multival_add(multival_t *list, char *opt);
2590Sstevel@tonic-gate static void multival_free(multival_t *list);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate  * clientopts_t is used to hold and pass around the param values from
2630Sstevel@tonic-gate  * the cmd line
2640Sstevel@tonic-gate  */
2650Sstevel@tonic-gate typedef struct {
2660Sstevel@tonic-gate 	multival_t	*attributeMap;
2670Sstevel@tonic-gate 	char		*authenticationMethod;
2680Sstevel@tonic-gate 	char		*bindTimeLimit;
2690Sstevel@tonic-gate 	char		*certificatePath;
2700Sstevel@tonic-gate 	char		*credentialLevel;
2710Sstevel@tonic-gate 	char		*defaultSearchBase;
2720Sstevel@tonic-gate 	char		*defaultServerList;
2730Sstevel@tonic-gate 	char		*domainName;
2740Sstevel@tonic-gate 	char		*followReferrals;
2750Sstevel@tonic-gate 	multival_t	*objectclassMap;
2760Sstevel@tonic-gate 	char		*preferredServerList;
2770Sstevel@tonic-gate 	char		*profileName;
2780Sstevel@tonic-gate 	char		*profileTTL;
2790Sstevel@tonic-gate 	char		*proxyDN;
2800Sstevel@tonic-gate 	char		*proxyPassword;
281*8821SMichen.Chang@Sun.COM 	char		*enableShadowUpdate;
282*8821SMichen.Chang@Sun.COM 	char		*adminDN;
283*8821SMichen.Chang@Sun.COM 	char		*adminPassword;
2846842Sth160488 	char		*bindDN;
2856842Sth160488 	char		*bindPasswd;
2860Sstevel@tonic-gate 	char		*defaultSearchScope;
2870Sstevel@tonic-gate 	char		*searchTimeLimit;
2880Sstevel@tonic-gate 	multival_t	*serviceAuthenticationMethod;
2890Sstevel@tonic-gate 	multival_t	*serviceCredentialLevel;
2900Sstevel@tonic-gate 	multival_t	*serviceSearchDescriptor;
2910Sstevel@tonic-gate } clientopts_t;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate static clientopts_t *clientopts_new();
2940Sstevel@tonic-gate static void clientopts_free(clientopts_t *list);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate extern ns_ldap_error_t *__ns_ldap_print_config(int);
2970Sstevel@tonic-gate extern void __ns_ldap_default_config();
2982830Sdjl extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate /* Function prototypes (these could be static) */
3010Sstevel@tonic-gate static void usage(void);
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate static int credCheck(clientopts_t *arglist);
304*8821SMichen.Chang@Sun.COM static int adminCredCheck(clientopts_t *arglist);
3050Sstevel@tonic-gate static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal);
3060Sstevel@tonic-gate static int parseParam(char *param, char **paramVal);
3070Sstevel@tonic-gate static void dumpargs(clientopts_t *arglist);
3080Sstevel@tonic-gate static int num_args(clientopts_t *arglist);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate static int file_backup(void);
3110Sstevel@tonic-gate static int recover(int saveState);
3120Sstevel@tonic-gate static int mod_backup(void);
3130Sstevel@tonic-gate static int mod_recover(void);
3140Sstevel@tonic-gate static void mod_cleanup(void);
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate static int client_list(clientopts_t *arglist);
3170Sstevel@tonic-gate static int client_manual(clientopts_t *arglist);
3180Sstevel@tonic-gate static int client_mod(clientopts_t *arglist);
3190Sstevel@tonic-gate static int client_uninit(clientopts_t *arglist);
3200Sstevel@tonic-gate static int client_genProfile(clientopts_t *arglist);
3210Sstevel@tonic-gate static int client_init(clientopts_t *arglist);
3220Sstevel@tonic-gate static int file_move(const char *from, const char *to);
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate static int start_services(int flag);
3250Sstevel@tonic-gate static int stop_services(int saveState);
3260Sstevel@tonic-gate static boolean_t is_service(const char *fmri, const char *state);
3270Sstevel@tonic-gate static int wait_till(const char *fmri, const char *state, useconds_t max,
3280Sstevel@tonic-gate 		const char *what, boolean_t check_maint);
3290Sstevel@tonic-gate static int do_service(const char *fmri, boolean_t waitflag, int dowhat,
3300Sstevel@tonic-gate 		const char *state);
3310Sstevel@tonic-gate static useconds_t get_timeout_value(int dowhat, const char *fmri,
3320Sstevel@tonic-gate 		useconds_t default_val);
3330Sstevel@tonic-gate 
334702Sth160488 int
335702Sth160488 main(int argc, char **argv)
3360Sstevel@tonic-gate {
3376842Sth160488 	char		*ret_locale, *ret_textdomain;
3386842Sth160488 	int		retcode;
3396842Sth160488 	int		paramFlag;
3406842Sth160488 	char		*attrVal;
3416842Sth160488 	int		sysinfostatus;
3426842Sth160488 	clientopts_t	*optlist = NULL;
3436842Sth160488 	int		op_manual = 0, op_mod = 0, op_uninit = 0;
3446842Sth160488 	int		op_list = 0, op_init = 0, op_genprofile = 0;
3456842Sth160488 	extern char	*optarg;
3466842Sth160488 	extern int	optind;
3476842Sth160488 	int		option;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	ret_locale = setlocale(LC_ALL, "");
3500Sstevel@tonic-gate 	if (ret_locale == NULL) {
3510Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr);
3520Sstevel@tonic-gate 	}
3530Sstevel@tonic-gate 	ret_textdomain = textdomain(TEXT_DOMAIN);
3540Sstevel@tonic-gate 	if (ret_textdomain == NULL) {
3550Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr);
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	openlog("ldapclient", LOG_PID, LOG_USER);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	/* get name that invoked us */
3610Sstevel@tonic-gate 	if (cmd = strrchr(argv[0], '/'))
3620Sstevel@tonic-gate 		++cmd;
3630Sstevel@tonic-gate 	else
3640Sstevel@tonic-gate 		cmd = argv[0];
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ);
3670Sstevel@tonic-gate 	if (0 < sysinfostatus)
3680Sstevel@tonic-gate 		dname = &dname_buf[0];
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	optlist = clientopts_new();
3710Sstevel@tonic-gate 	if (optlist == NULL) {
3720Sstevel@tonic-gate 		CLIENT_FPUTS(
3736842Sth160488 		    gettext("Error getting optlist (malloc fail)\n"),
3746842Sth160488 		    stderr);
3750Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	optind = 1;
3790Sstevel@tonic-gate 	while (optind < argc) {
380*8821SMichen.Chang@Sun.COM 		option = getopt(argc, argv, "vqa:ID:w:j:y:z:");
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 		switch (option) {
3830Sstevel@tonic-gate 		case 'v':
3840Sstevel@tonic-gate 			mode_verbose = 1;
3850Sstevel@tonic-gate 			break;
3860Sstevel@tonic-gate 		case 'q':
3870Sstevel@tonic-gate 			mode_quiet = 1;
3880Sstevel@tonic-gate 			break;
3890Sstevel@tonic-gate 		case 'a':
3900Sstevel@tonic-gate 			attrVal = NULL;
3910Sstevel@tonic-gate 			paramFlag = parseParam(optarg, &attrVal);
3920Sstevel@tonic-gate 			if (paramFlag == CLIENT_ERR_PARSE) {
3930Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
3946842Sth160488 				    gettext("Unrecognized "
3956842Sth160488 				    "parameter \"%s\"\n"),
3966842Sth160488 				    optarg);
3970Sstevel@tonic-gate 				usage();
3980Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
3990Sstevel@tonic-gate 			}
4006842Sth160488 			if (paramFlag == NS_LDAP_BINDPASSWD_P &&
4016842Sth160488 			    optlist->proxyPassword != NULL) {
4026842Sth160488 				(void) fprintf(stderr,
4036842Sth160488 				    gettext("The -a proxyPassword option is "
4046842Sth160488 				    "mutually exclusive of -y. "
4056842Sth160488 				    "-a proxyPassword is ignored.\n"));
4066842Sth160488 				break;
4076842Sth160488 			}
408*8821SMichen.Chang@Sun.COM 			if (paramFlag == NS_LDAP_ADMIN_BINDPASSWD_P &&
409*8821SMichen.Chang@Sun.COM 			    optlist->adminPassword != NULL) {
410*8821SMichen.Chang@Sun.COM 				(void) fprintf(stderr,
411*8821SMichen.Chang@Sun.COM 				    gettext("The -a adminPassword option is "
412*8821SMichen.Chang@Sun.COM 				    "mutually exclusive of -z. "
413*8821SMichen.Chang@Sun.COM 				    "-a adminPassword is ignored.\n"));
414*8821SMichen.Chang@Sun.COM 				break;
415*8821SMichen.Chang@Sun.COM 			}
4160Sstevel@tonic-gate 			retcode = clientSetParam(optlist, paramFlag, attrVal);
4170Sstevel@tonic-gate 			if (retcode != CLIENT_SUCCESS) {
4180Sstevel@tonic-gate 				CLIENT_FPRINTF(
4196842Sth160488 				    stderr,
4206842Sth160488 				    gettext("Error (%d) setting "
4216842Sth160488 				    "param \"%s\"\n"),
4226842Sth160488 				    retcode, optarg);
4230Sstevel@tonic-gate 				usage();
4240Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
4250Sstevel@tonic-gate 			}
4260Sstevel@tonic-gate 			break;
4276842Sth160488 		case 'D':
4286842Sth160488 			optlist->bindDN = strdup(optarg);
4296842Sth160488 			break;
4306842Sth160488 		case 'w':
4316842Sth160488 			if (optlist->bindPasswd != NULL) {
4326842Sth160488 				CLIENT_FPRINTF(stderr,
4336842Sth160488 				    gettext("The -w option is mutually "
4346842Sth160488 				    "exclusive of -j. -w is ignored."));
4356842Sth160488 				break;
4366842Sth160488 			}
4376842Sth160488 
4386842Sth160488 			if (optarg[0] == '-' && optarg[1] == '\0') {
4396842Sth160488 				/* Ask for a password later */
4406842Sth160488 				break;
4416842Sth160488 			}
4426842Sth160488 
4436842Sth160488 			optlist->bindPasswd = strdup(optarg);
4446842Sth160488 			break;
4456842Sth160488 		case 'j':
4466842Sth160488 			if (optlist->bindPasswd != NULL) {
4476842Sth160488 				(void) fprintf(stderr,
4486842Sth160488 				    gettext("The -w option is mutually "
4496842Sth160488 				    "exclusive of -j. -w is ignored.\n"));
4506842Sth160488 				free(optlist->bindPasswd);
4516842Sth160488 			}
4526842Sth160488 			optlist->bindPasswd = readPwd(optarg);
4536842Sth160488 			if (optlist->bindPasswd == NULL) {
4546842Sth160488 				exit(CLIENT_ERR_FAIL);
4556842Sth160488 			}
4566842Sth160488 			break;
4576842Sth160488 		case 'y':
4586842Sth160488 			if (optlist->proxyPassword != NULL) {
4596842Sth160488 				(void) fprintf(stderr,
4606842Sth160488 				    gettext("The -a proxyPassword option is "
4616842Sth160488 				    "mutually exclusive of -y. "
4626842Sth160488 				    "-a proxyPassword is ignored.\n"));
4636842Sth160488 			}
4646842Sth160488 			optlist->proxyPassword = readPwd(optarg);
4656842Sth160488 			if (optlist->proxyPassword == NULL) {
4666842Sth160488 				exit(CLIENT_ERR_FAIL);
4676842Sth160488 			}
4686842Sth160488 			break;
469*8821SMichen.Chang@Sun.COM 		case 'z':
470*8821SMichen.Chang@Sun.COM 			if (optlist->adminPassword != NULL) {
471*8821SMichen.Chang@Sun.COM 				(void) fprintf(stderr,
472*8821SMichen.Chang@Sun.COM 				    gettext("The -a adminPassword option is "
473*8821SMichen.Chang@Sun.COM 				    "mutually exclusive of -z. "
474*8821SMichen.Chang@Sun.COM 				    "-a adminPassword is ignored.\n"));
475*8821SMichen.Chang@Sun.COM 			}
476*8821SMichen.Chang@Sun.COM 			optlist->adminPassword = readPwd(optarg);
477*8821SMichen.Chang@Sun.COM 			if (optlist->adminPassword == NULL) {
478*8821SMichen.Chang@Sun.COM 				exit(CLIENT_ERR_FAIL);
479*8821SMichen.Chang@Sun.COM 			}
480*8821SMichen.Chang@Sun.COM 			break;
4810Sstevel@tonic-gate 		case EOF:
4820Sstevel@tonic-gate 			if (strcmp(argv[optind], "init") == 0) {
4830Sstevel@tonic-gate 				op_init = 1;
4840Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "manual") == 0) {
4850Sstevel@tonic-gate 				op_manual = 1;
4860Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "mod") == 0) {
4870Sstevel@tonic-gate 				op_mod = 1;
4880Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "list") == 0) {
4890Sstevel@tonic-gate 				op_list = 1;
4900Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "uninit") == 0) {
4910Sstevel@tonic-gate 				op_uninit = 1;
4920Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "genprofile") == 0) {
4930Sstevel@tonic-gate 				gen = 1;
4940Sstevel@tonic-gate 				op_genprofile = 1;
4950Sstevel@tonic-gate 			} else if (optind == argc-1) {
4960Sstevel@tonic-gate 				retcode = clientSetParam(
4976842Sth160488 				    optlist,
4986842Sth160488 				    NS_LDAP_SERVERS_P,
4996842Sth160488 				    argv[optind]);	/* ipAddr */
5000Sstevel@tonic-gate 				if (retcode != CLIENT_SUCCESS) {
5010Sstevel@tonic-gate 					CLIENT_FPRINTF(
5026842Sth160488 					    stderr,
5036842Sth160488 					    gettext("Error (%d) setting "
5046842Sth160488 					    "serverList param.\n"),
5056842Sth160488 					    retcode);
5060Sstevel@tonic-gate 					usage();
5070Sstevel@tonic-gate 					exit(CLIENT_ERR_FAIL);
5080Sstevel@tonic-gate 				}
5090Sstevel@tonic-gate 			} else {
5100Sstevel@tonic-gate 				CLIENT_FPUTS(
5116842Sth160488 				    gettext("Error parsing "
5126842Sth160488 				    "command line\n"),
5136842Sth160488 				    stderr);
5140Sstevel@tonic-gate 				usage();
5150Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
5160Sstevel@tonic-gate 			}
5170Sstevel@tonic-gate 			optind++;	/* get past the verb and keep trying */
5180Sstevel@tonic-gate 			break;
5190Sstevel@tonic-gate 		/* Backwards compatibility to support system install */
5200Sstevel@tonic-gate 		case 'I':
5210Sstevel@tonic-gate 			sysid_install = B_TRUE;
5220Sstevel@tonic-gate 			op_init = 1;
5230Sstevel@tonic-gate 			mode_quiet = 1;
5240Sstevel@tonic-gate 			break;
5250Sstevel@tonic-gate 		case '?':
5260Sstevel@tonic-gate 			usage();
5270Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("\nOr\n\n"), stderr);
5280Sstevel@tonic-gate 			gen = 1;
5290Sstevel@tonic-gate 			usage();
5300Sstevel@tonic-gate 			exit(CLIENT_ERR_FAIL);
5310Sstevel@tonic-gate 			break;
5320Sstevel@tonic-gate 		}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	if ((getuid() != 0) && (!op_genprofile)) {
5370Sstevel@tonic-gate 		(void) puts(
5386842Sth160488 		    "You must be root (SuperUser) to run this command.");
5390Sstevel@tonic-gate 		usage();
5400Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate /*
5440Sstevel@tonic-gate  *	All command line arguments are finished being parsed now
5450Sstevel@tonic-gate  */
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate /* *** Do semantic checking here *** */
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate /* if gen and no no searchBase then err */
5500Sstevel@tonic-gate 	if (gen && !optlist->defaultSearchBase) {
5510Sstevel@tonic-gate 		CLIENT_FPUTS(
5526842Sth160488 		    gettext("ldapclient: Missing required attrName "
5536842Sth160488 		    "defaultSearchBase\n"),
5546842Sth160488 		    stderr);
5550Sstevel@tonic-gate 		usage();
5560Sstevel@tonic-gate 		clientopts_free(optlist);
5570Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
560*8821SMichen.Chang@Sun.COM /*
561*8821SMichen.Chang@Sun.COM  * if init or manual, and if adminDN is specified then enableShadowUpdate
562*8821SMichen.Chang@Sun.COM  * must be set to TRUE.
563*8821SMichen.Chang@Sun.COM  */
564*8821SMichen.Chang@Sun.COM 	if ((op_init || op_manual) &&
565*8821SMichen.Chang@Sun.COM 	    (!optlist->enableShadowUpdate ||
566*8821SMichen.Chang@Sun.COM 	    strcasecmp(optlist->enableShadowUpdate, "TRUE") != 0) &&
567*8821SMichen.Chang@Sun.COM 	    (optlist->adminDN || optlist->adminPassword)) {
568*8821SMichen.Chang@Sun.COM 		CLIENT_FPUTS(
569*8821SMichen.Chang@Sun.COM 		    gettext("ldapclient: adminDN and adminPassword must not "
570*8821SMichen.Chang@Sun.COM 		    "be specified if enableShadowUpdate is not set to TRUE \n"),
571*8821SMichen.Chang@Sun.COM 		    stderr);
572*8821SMichen.Chang@Sun.COM 		usage();
573*8821SMichen.Chang@Sun.COM 		clientopts_free(optlist);
574*8821SMichen.Chang@Sun.COM 		exit(CLIENT_ERR_FAIL);
575*8821SMichen.Chang@Sun.COM 	}
576*8821SMichen.Chang@Sun.COM 
5770Sstevel@tonic-gate /* Only one verb can be specified */
5780Sstevel@tonic-gate 	if ((op_init + op_manual + op_mod + op_uninit +
5796842Sth160488 	    op_list + op_genprofile) != 1) {
5800Sstevel@tonic-gate 		usage();
5810Sstevel@tonic-gate 		clientopts_free(optlist);
5820Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate /* *** We passed semantic checking, so now do the operation *** */
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	if (mode_verbose) {
5880Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr);
5890Sstevel@tonic-gate 		dumpargs(optlist);
5900Sstevel@tonic-gate 	}
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate /* handle "ldapclient list" here.  err checking done in func */
5940Sstevel@tonic-gate 	if (op_list) {
5950Sstevel@tonic-gate 		if (mode_verbose)
5960Sstevel@tonic-gate 			CLIENT_FPUTS(
5976842Sth160488 			    gettext("Handling list option\n"),
5986842Sth160488 			    stderr);
5990Sstevel@tonic-gate 		retcode = client_list(optlist);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate /* handle "ldapclient uninit" here */
6030Sstevel@tonic-gate 	if (op_uninit) {
6040Sstevel@tonic-gate 		if (mode_verbose)
6050Sstevel@tonic-gate 			CLIENT_FPUTS(
6066842Sth160488 			    gettext("Handling uninit option\n"),
6076842Sth160488 			    stderr);
6080Sstevel@tonic-gate 		retcode = client_uninit(optlist);
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate /* handle "ldapclient init" (profile) */
6120Sstevel@tonic-gate 	if (op_init) {
6130Sstevel@tonic-gate 		if (mode_verbose)
6140Sstevel@tonic-gate 			CLIENT_FPUTS(
6156842Sth160488 			    gettext("Handling init option\n"),
6166842Sth160488 			    stderr);
6170Sstevel@tonic-gate 		retcode = client_init(optlist);
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate /* handle "genprofile" here */
6210Sstevel@tonic-gate 	if (op_genprofile) {
6220Sstevel@tonic-gate 		if (mode_verbose)
6230Sstevel@tonic-gate 			CLIENT_FPUTS(
6246842Sth160488 			    gettext("Handling genProfile\n"),
6256842Sth160488 			    stderr);
6260Sstevel@tonic-gate 		retcode = client_genProfile(optlist);
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate /* handle "ldapclient manual" here */
6300Sstevel@tonic-gate 	if (op_manual) {
6310Sstevel@tonic-gate 		if (mode_verbose)
6320Sstevel@tonic-gate 			CLIENT_FPUTS(
6336842Sth160488 			    gettext("Handling manual option\n"),
6346842Sth160488 			    stderr);
6350Sstevel@tonic-gate 		retcode = client_manual(optlist);
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate /* handle "ldapclient mod" here */
6390Sstevel@tonic-gate 	if (op_mod) {
6400Sstevel@tonic-gate 		if (mode_verbose)
6410Sstevel@tonic-gate 			CLIENT_FPUTS(
6426842Sth160488 			    gettext("Handling mod option\n"),
6436842Sth160488 			    stderr);
6440Sstevel@tonic-gate 		retcode = client_mod(optlist);
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	clientopts_free(optlist);
6480Sstevel@tonic-gate 	if ((retcode == CLIENT_SUCCESS) ||
6496842Sth160488 	    (retcode == CLIENT_ERR_FAIL) ||
6506842Sth160488 	    (retcode == CLIENT_ERR_CREDENTIAL))
6512830Sdjl 		return (retcode);
6520Sstevel@tonic-gate 	else
6532830Sdjl 		return (CLIENT_ERR_FAIL);
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate static int
6570Sstevel@tonic-gate client_list(clientopts_t *arglist)
6580Sstevel@tonic-gate {
6590Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
6600Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	if (num_args(arglist) > 0) {
6630Sstevel@tonic-gate 		CLIENT_FPUTS(
6646842Sth160488 		    gettext("No args supported with \"list\" option\n"),
6656842Sth160488 		    stderr);
6660Sstevel@tonic-gate 		usage();
6670Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);	/* exit code here ? */
6680Sstevel@tonic-gate 	}
6690Sstevel@tonic-gate 	if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) {
6700Sstevel@tonic-gate 		retcode = CLIENT_ERR_FAIL;
6710Sstevel@tonic-gate 		CLIENT_FPUTS(
6726842Sth160488 		    gettext("Cannot get print configuration\n"),
6736842Sth160488 		    stderr);
6740Sstevel@tonic-gate 		CLIENT_FPUTS(errorp->message, stderr);
6750Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
6760Sstevel@tonic-gate 		CLIENT_FPUTC('\n', stderr);
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	return (retcode);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate static int
6830Sstevel@tonic-gate client_uninit(clientopts_t *arglist)
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
6862830Sdjl 	ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	if (mode_verbose) {
6890Sstevel@tonic-gate 		CLIENT_FPUTS(
6906842Sth160488 		    gettext("Restoring machine to previous "
6916842Sth160488 		    "configuration state\n"),
6926842Sth160488 		    stderr);
6930Sstevel@tonic-gate 	}
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	if (num_args(arglist) > 0) {
6960Sstevel@tonic-gate 		CLIENT_FPUTS(
6976842Sth160488 		    gettext("No args supported with \"uninit\" option\n"),
6986842Sth160488 		    stderr);
6990Sstevel@tonic-gate 		usage();
7000Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
7010Sstevel@tonic-gate 	}
7020Sstevel@tonic-gate 
7032830Sdjl 	(void) __ns_ldap_self_gssapi_config(&config);
7042830Sdjl 
7050Sstevel@tonic-gate 	retcode = stop_services(STATE_SAVE);
7062830Sdjl 
7072830Sdjl 	if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
7082830Sdjl 		(void) system("/usr/sbin/cryptoadm enable metaslot");
7092830Sdjl 
7100Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
7110Sstevel@tonic-gate 		CLIENT_FPUTS(
7126842Sth160488 		    gettext("Errors stopping network services.\n"), stderr);
7130Sstevel@tonic-gate 		/* restart whatever services we can */
7140Sstevel@tonic-gate 		(void) start_services(START_RESET);
7150Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
7160Sstevel@tonic-gate 	}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	retcode = recover(STATE_SAVE);
7190Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
7200Sstevel@tonic-gate 		CLIENT_FPUTS(
7216842Sth160488 		    gettext("Cannot recover the configuration on "
7226842Sth160488 		    "this machine.\n"),
7236842Sth160488 		    stderr);
7240Sstevel@tonic-gate 		(void) start_services(START_RESET);
7250Sstevel@tonic-gate 	} else {
7260Sstevel@tonic-gate 		retcode = start_services(START_UNINIT);
7270Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
7280Sstevel@tonic-gate 			CLIENT_FPUTS(
7296842Sth160488 			    gettext("Config restored but problems "
7306842Sth160488 			    "encountered resetting network "
7316842Sth160488 			    "services.\n"),
7326842Sth160488 			    stderr);
7330Sstevel@tonic-gate 		}
7340Sstevel@tonic-gate 	}
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	if (retcode == CLIENT_SUCCESS) {
7370Sstevel@tonic-gate 		CLIENT_FPUTS(
7386842Sth160488 		    gettext("System successfully recovered\n"),
7396842Sth160488 		    stderr);
7400Sstevel@tonic-gate 	}
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	return (retcode);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate /*
7460Sstevel@tonic-gate  * The following macro is used to do a __ns_ldap_setParam().
7470Sstevel@tonic-gate  * On every call, the return code is checked, and if there was
7480Sstevel@tonic-gate  * a problem then the error message is printed, the ldaperr
7490Sstevel@tonic-gate  * is freed and we return from the function with the offending
7500Sstevel@tonic-gate  * error return code.  This macro keeps us from having to
7510Sstevel@tonic-gate  * repeat this code for every call to setParam as was done
7520Sstevel@tonic-gate  * in the previous incarnation of ldapclient.
7530Sstevel@tonic-gate  *
7540Sstevel@tonic-gate  * assumes a "retcode" variable is available for status
7550Sstevel@tonic-gate  */
7560Sstevel@tonic-gate #define	LDAP_SET_PARAM(argval, argdef)	\
7570Sstevel@tonic-gate retcode = 0;	\
7580Sstevel@tonic-gate if (NULL != argval) {	\
7590Sstevel@tonic-gate 	ns_ldap_error_t *ldaperr;	\
7600Sstevel@tonic-gate 	retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr);	\
7610Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {	\
7620Sstevel@tonic-gate 		if (NULL != ldaperr) {	\
7630Sstevel@tonic-gate 			CLIENT_FPUTS(ldaperr->message, stderr);	\
7640Sstevel@tonic-gate 			CLIENT_FPUTC('\n', stderr);	\
7650Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&ldaperr);	\
7660Sstevel@tonic-gate 		}	\
7670Sstevel@tonic-gate 		return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS);	\
7680Sstevel@tonic-gate 	}	\
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate 
7716842Sth160488 /*
7726842Sth160488  * The following macro is used to check if an arg has already been set
7736842Sth160488  * and issues an error message, a usage message and then returns an error.
7746842Sth160488  * This was made into a macro to avoid the duplication of this code many
7756842Sth160488  * times in the function below.
7766842Sth160488  */
7776842Sth160488 #define	LDAP_CHECK_INVALID(arg, param)	\
7786842Sth160488 if (arg) {	\
7796842Sth160488 	CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \
7806842Sth160488 	    "specified\n"), param);	\
7816842Sth160488 	usage();	\
7826842Sth160488 	return (CLIENT_ERR_FAIL);	\
7836842Sth160488 }
7846842Sth160488 
7850Sstevel@tonic-gate static int
7860Sstevel@tonic-gate client_manual(clientopts_t *arglist)
7870Sstevel@tonic-gate {
7880Sstevel@tonic-gate 	int counter;
7890Sstevel@tonic-gate 	int domain_fp;
7900Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
7910Sstevel@tonic-gate 	int ret_copy;
7920Sstevel@tonic-gate 	int reset_ret;
7930Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	if (dname == NULL) {
7960Sstevel@tonic-gate 		CLIENT_FPUTS(
7976842Sth160488 		    gettext("Manual failed: System domain not set and "
7986842Sth160488 		    "no domainName specified.\n"),
7996842Sth160488 		    stderr);
8000Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if (arglist->defaultSearchBase == NULL) {
8040Sstevel@tonic-gate 		CLIENT_FPUTS(
8056842Sth160488 		    gettext("Manual failed: Missing required "
8066842Sth160488 		    "defaultSearchBase attribute.\n"),
8076842Sth160488 		    stderr);
8080Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if ((arglist->defaultServerList == NULL) &&
8126842Sth160488 	    (arglist->preferredServerList == NULL)) {
8130Sstevel@tonic-gate 		CLIENT_FPUTS(
8146842Sth160488 		    gettext("Manual failed: Missing required "
8156842Sth160488 		    "defaultServerList or preferredServerList "
8166842Sth160488 		    "attribute.\n"),
8176842Sth160488 		    stderr);
8180Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8190Sstevel@tonic-gate 	}
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	if (arglist->profileTTL != NULL) {
8220Sstevel@tonic-gate 		CLIENT_FPUTS(
8236842Sth160488 		    gettext("Manual aborted: profileTTL is not supported "
8246842Sth160488 		    "in manual mode.\n"),
8256842Sth160488 		    stderr);
8260Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8270Sstevel@tonic-gate 	}
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	if (arglist->profileName != NULL) {
8300Sstevel@tonic-gate 		CLIENT_FPUTS(
8316842Sth160488 		    gettext("Manual aborted: profileName is not supported "
8326842Sth160488 		    "in manual mode.\n"),
8336842Sth160488 		    stderr);
8340Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8350Sstevel@tonic-gate 	}
8360Sstevel@tonic-gate 
8376842Sth160488 	LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
8386842Sth160488 	LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 	__ns_ldap_setServer(TRUE);	/* Need this for _ns_setParam() */
8410Sstevel@tonic-gate 	__ns_ldap_default_config();
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	/* Set version to latest (not version 1) */
8440Sstevel@tonic-gate 	LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	/* Set profileTTL to 0 since NO profile on manual */
8470Sstevel@tonic-gate 	LDAP_SET_PARAM(CACHETTL_OFF, NS_LDAP_CACHETTL_P);
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	/* Set additional valid params from command line */
8500Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
8510Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
8520Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
8530Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
854*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->enableShadowUpdate,
855*8821SMichen.Chang@Sun.COM 	    NS_LDAP_ENABLE_SHADOW_UPDATE_P);
856*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P);
8570Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
8580Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
8590Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
8600Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
8610Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
8620Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
8630Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
864*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P);
8650Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
8660Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	for (counter = 0;
8696842Sth160488 	    counter < arglist->serviceAuthenticationMethod->count;
8706842Sth160488 	    counter++) {
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 		LDAP_SET_PARAM(
8736842Sth160488 		    arglist->serviceAuthenticationMethod->optlist[counter],
8746842Sth160488 		    NS_LDAP_SERVICE_AUTH_METHOD_P);
8750Sstevel@tonic-gate 	}
8760Sstevel@tonic-gate 	for (counter = 0;
8776842Sth160488 	    counter < arglist->serviceCredentialLevel->count;
8786842Sth160488 	    counter++) {
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 		LDAP_SET_PARAM(
8816842Sth160488 		    arglist->serviceCredentialLevel->optlist[counter],
8826842Sth160488 		    NS_LDAP_SERVICE_CRED_LEVEL_P);
8830Sstevel@tonic-gate 	}
8840Sstevel@tonic-gate 	for (counter = 0;
8856842Sth160488 	    counter < arglist->objectclassMap->count;
8866842Sth160488 	    counter++) {
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 		LDAP_SET_PARAM(arglist->objectclassMap->optlist[counter],
8896842Sth160488 		    NS_LDAP_OBJECTCLASSMAP_P);
8900Sstevel@tonic-gate 	}
8910Sstevel@tonic-gate 	for (counter = 0; counter < arglist->attributeMap->count; counter++) {
8920Sstevel@tonic-gate 		LDAP_SET_PARAM(arglist->attributeMap->optlist[counter],
8936842Sth160488 		    NS_LDAP_ATTRIBUTEMAP_P);
8940Sstevel@tonic-gate 	}
8950Sstevel@tonic-gate 	for (counter = 0;
8966842Sth160488 	    counter < arglist->serviceSearchDescriptor->count;
8976842Sth160488 	    counter++) {
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 		LDAP_SET_PARAM(
9006842Sth160488 		    arglist->serviceSearchDescriptor->optlist[counter],
9016842Sth160488 		    NS_LDAP_SERVICE_SEARCH_DESC_P);
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	retcode = credCheck(arglist);
905*8821SMichen.Chang@Sun.COM 	if (retcode == CLIENT_SUCCESS)
906*8821SMichen.Chang@Sun.COM 		retcode = adminCredCheck(arglist);
9070Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
9080Sstevel@tonic-gate 		CLIENT_FPUTS(
9096842Sth160488 		    gettext("Error in setting up credentials\n"),
9106842Sth160488 		    stderr);
9110Sstevel@tonic-gate 		return (retcode);
9120Sstevel@tonic-gate 	}
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	if (mode_verbose)
9150Sstevel@tonic-gate 		CLIENT_FPUTS(
9166842Sth160488 		    gettext("About to modify this machines "
9176842Sth160488 		    "configuration by writing the files\n"),
9186842Sth160488 		    stderr);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	/* get ready to start playing with files */
9210Sstevel@tonic-gate 	retcode = stop_services(STATE_SAVE);
9220Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
9230Sstevel@tonic-gate 		CLIENT_FPUTS(
9246842Sth160488 		    gettext("Errors stopping network services.\n"), stderr);
9250Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	/* Save orig versions of files */
9290Sstevel@tonic-gate 	retcode = file_backup();
9300Sstevel@tonic-gate 	if (retcode == CLIENT_ERR_RESTORE) {
9310Sstevel@tonic-gate 		CLIENT_FPUTS(
9326842Sth160488 		    gettext("System not in state to enable ldap client.\n"),
9336842Sth160488 		    stderr);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
9360Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
9370Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
9386842Sth160488 			    "starting services during reset\n"),
9396842Sth160488 			    reset_ret);
9400Sstevel@tonic-gate 		}
9410Sstevel@tonic-gate 		return (retcode);
9420Sstevel@tonic-gate 	} else if (retcode != CLIENT_SUCCESS) {
9430Sstevel@tonic-gate 		CLIENT_FPUTS(
9446842Sth160488 		    gettext("Save of system configuration failed!  "
9456842Sth160488 		    "Attempting recovery.\n"),
9466842Sth160488 		    stderr);
9470Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
9480Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
9490Sstevel@tonic-gate 			CLIENT_FPUTS(
9506842Sth160488 			    gettext("Recovery of systems configuration "
9516842Sth160488 			    "failed.  Manual intervention of "
9526842Sth160488 			    "config files is required.\n"),
9536842Sth160488 			    stderr);
9540Sstevel@tonic-gate 			return (retcode);
9550Sstevel@tonic-gate 		}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
9580Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
9590Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
9606842Sth160488 			    "starting services during reset\n"),
9616842Sth160488 			    reset_ret);
9620Sstevel@tonic-gate 		}
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		return (retcode);
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	/* Dump new files */
9680Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
9690Sstevel@tonic-gate 	if (errorp != NULL) {
9700Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
9716842Sth160488 		    gettext("%s manual: errorp is not NULL; %s\n"),
9726842Sth160488 		    cmd, errorp->message);
9730Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
9740Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
9750Sstevel@tonic-gate 			CLIENT_FPUTS(
9766842Sth160488 			    gettext("Recovery of systems configuration "
9776842Sth160488 			    "failed.  Manual intervention of "
9786842Sth160488 			    "config files is required.\n"),
9796842Sth160488 			    stderr);
9800Sstevel@tonic-gate 			return (retcode);
9810Sstevel@tonic-gate 		}
9820Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
9830Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
9840Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
9856842Sth160488 			    "starting services during reset\n"),
9866842Sth160488 			    reset_ret);
9870Sstevel@tonic-gate 		}
9880Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
9890Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate 	/* if (credargs(arglist)) */
9930Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
9940Sstevel@tonic-gate 	if (errorp != NULL) {
9950Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
9966842Sth160488 		    gettext("%s init: errorp is not NULL; %s\n"),
9976842Sth160488 		    cmd, errorp->message);
9980Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
9990Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
10000Sstevel@tonic-gate 			CLIENT_FPUTS(
10016842Sth160488 			    gettext("Recovery of systems configuration "
10026842Sth160488 			    "failed.  Manual intervention of "
10036842Sth160488 			    "config files is required.\n"),
10046842Sth160488 			    stderr);
10050Sstevel@tonic-gate 			return (retcode);
10060Sstevel@tonic-gate 		}
10070Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
10080Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10090Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10106842Sth160488 			    "starting services during reset\n"),
10116842Sth160488 			    reset_ret);
10120Sstevel@tonic-gate 		}
10130Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
10140Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
10180Sstevel@tonic-gate 	if (ret_copy != 0) {
10190Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
10206842Sth160488 		    gettext("Error %d copying (%s) -> (%s)\n"),
10216842Sth160488 		    ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
10220Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
10230Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
10240Sstevel@tonic-gate 			CLIENT_FPUTS(
10256842Sth160488 			    gettext("Recovery of systems configuration "
10266842Sth160488 			    "failed.  Manual intervention of "
10276842Sth160488 			    "config files is required.\n"),
10286842Sth160488 			    stderr);
10290Sstevel@tonic-gate 		}
10300Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
10310Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10320Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10336842Sth160488 			    "starting services during reset\n"),
10346842Sth160488 			    reset_ret);
10350Sstevel@tonic-gate 		}
10360Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
10370Sstevel@tonic-gate 	}
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
10406842Sth160488 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
10410Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
10420Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
10430Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
10440Sstevel@tonic-gate 			CLIENT_FPUTS(
10456842Sth160488 			    gettext("Recovery of systems configuration "
10466842Sth160488 			    "failed.  Manual intervention of "
10476842Sth160488 			    "config files is required.\n"),
10486842Sth160488 			    stderr);
10490Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
10500Sstevel@tonic-gate 		}
10510Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
10520Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10530Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10546842Sth160488 			    "starting services during reset\n"),
10556842Sth160488 			    reset_ret);
10560Sstevel@tonic-gate 		}
10570Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 	(void) write(domain_fp, dname, strlen(dname));
10600Sstevel@tonic-gate 	(void) write(domain_fp, "\n", 1);
10610Sstevel@tonic-gate 	(void) close(domain_fp);
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	retcode = start_services(START_INIT);
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	if (retcode == CLIENT_SUCCESS) {
10660Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("System successfully configured\n"),
10676842Sth160488 		    stderr);
10680Sstevel@tonic-gate 	} else {
10690Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error resetting system.\n"
10706842Sth160488 		    "Recovering old system settings.\n"), stderr),
10716842Sth160488 
10726842Sth160488 		    /* stop any started services for recover */
10736842Sth160488 		    /* don't stomp on history of saved services state */
10746842Sth160488 		    reset_ret = stop_services(STATE_NOSAVE);
10750Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10760Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10776842Sth160488 			    "stopping services during reset\n"),
10786842Sth160488 			    reset_ret);
10790Sstevel@tonic-gate 			/* Coninue and try to recover what we can */
10800Sstevel@tonic-gate 		}
10810Sstevel@tonic-gate 		reset_ret = recover(STATE_NOSAVE);
10820Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10830Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10846842Sth160488 			    "recovering service files during "
10856842Sth160488 			    "reset\n"), reset_ret);
10860Sstevel@tonic-gate 			/* Continue and start what we can */
10870Sstevel@tonic-gate 		}
10880Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
10890Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
10900Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
10916842Sth160488 			    "starting services during reset\n"),
10926842Sth160488 			    reset_ret);
10930Sstevel@tonic-gate 		}
10940Sstevel@tonic-gate 	}
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	return (retcode);
10970Sstevel@tonic-gate }
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate static int
11000Sstevel@tonic-gate client_mod(clientopts_t *arglist)
11010Sstevel@tonic-gate {
11020Sstevel@tonic-gate 	int counter;
11030Sstevel@tonic-gate 	int domain_fp;
11040Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
11050Sstevel@tonic-gate 	int reset_ret;
11060Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	__ns_ldap_setServer(TRUE);	/* Need this for _ns_setParam() */
11090Sstevel@tonic-gate 	if ((errorp = __ns_ldap_LoadConfiguration()) != NULL) {
11100Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Cannot get load configuration\n"),
11116842Sth160488 		    stderr);
11120Sstevel@tonic-gate 		CLIENT_FPUTS(errorp->message, stderr);
11130Sstevel@tonic-gate 		CLIENT_FPUTC('\n', stderr);
11140Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
11150Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
11160Sstevel@tonic-gate 	}
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 	if (arglist->profileTTL != NULL) {
11190Sstevel@tonic-gate 		CLIENT_FPUTS(
11206842Sth160488 		    gettext("Mod aborted: profileTTL modification is "
11216842Sth160488 		    "not allowed in mod mode.\n"),
11226842Sth160488 		    stderr);
11230Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
11240Sstevel@tonic-gate 	}
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	if (arglist->profileName != NULL) {
11270Sstevel@tonic-gate 		CLIENT_FPUTS(
11286842Sth160488 		    gettext("Mod aborted: profileName modification is "
11296842Sth160488 		    "not allowed.  If you want to use profiles "
11306842Sth160488 		    "generate one with genProfile and load it "
11316842Sth160488 		    "on the server with ldapadd.\n"),
11326842Sth160488 		    stderr);
11330Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
11340Sstevel@tonic-gate 	}
11350Sstevel@tonic-gate 
11366842Sth160488 	LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
11376842Sth160488 	LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	/* Set additional valid params from command line */
11400Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
11410Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
11420Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
11430Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
1144*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P);
11450Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
11460Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
11470Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
11480Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
11490Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
11500Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
11510Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
11520Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
1153*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P);
11540Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1155*8821SMichen.Chang@Sun.COM 	LDAP_SET_PARAM(arglist->enableShadowUpdate,
1156*8821SMichen.Chang@Sun.COM 	    NS_LDAP_ENABLE_SHADOW_UPDATE_P);
11570Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	for (counter = 0;
11606842Sth160488 	    counter < arglist->serviceAuthenticationMethod->count;
11616842Sth160488 	    counter++) {
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 		LDAP_SET_PARAM(
11646842Sth160488 		    arglist->serviceAuthenticationMethod->optlist[counter],
11656842Sth160488 		    NS_LDAP_SERVICE_AUTH_METHOD_P);
11660Sstevel@tonic-gate 	}
11670Sstevel@tonic-gate 	for (counter = 0;
11686842Sth160488 	    counter < arglist->serviceCredentialLevel->count;
11696842Sth160488 	    counter++) {
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 		LDAP_SET_PARAM(
11726842Sth160488 		    arglist->serviceCredentialLevel->optlist[counter],
11736842Sth160488 		    NS_LDAP_SERVICE_CRED_LEVEL_P);
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 	for (counter = 0;
11766842Sth160488 	    counter < arglist->objectclassMap->count;
11776842Sth160488 	    counter++) {
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 		LDAP_SET_PARAM(
11806842Sth160488 		    arglist->objectclassMap->optlist[counter],
11816842Sth160488 		    NS_LDAP_OBJECTCLASSMAP_P);
11820Sstevel@tonic-gate 	}
11830Sstevel@tonic-gate 	for (counter = 0;
11846842Sth160488 	    counter < arglist->attributeMap->count;
11856842Sth160488 	    counter++) {
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 		LDAP_SET_PARAM(
11886842Sth160488 		    arglist->attributeMap->optlist[counter],
11896842Sth160488 		    NS_LDAP_ATTRIBUTEMAP_P);
11900Sstevel@tonic-gate 	}
11910Sstevel@tonic-gate 	for (counter = 0;
11926842Sth160488 	    counter < arglist->serviceSearchDescriptor->count;
11936842Sth160488 	    counter++) {
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 		LDAP_SET_PARAM(
11966842Sth160488 		    arglist->serviceSearchDescriptor->optlist[counter],
11976842Sth160488 		    NS_LDAP_SERVICE_SEARCH_DESC_P);
11980Sstevel@tonic-gate 	}
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	retcode = credCheck(arglist);
1201*8821SMichen.Chang@Sun.COM 	if (retcode == CLIENT_SUCCESS)
1202*8821SMichen.Chang@Sun.COM 		retcode = adminCredCheck(arglist);
12030Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
12040Sstevel@tonic-gate 		CLIENT_FPUTS(
12056842Sth160488 		    gettext("Error in setting up credentials\n"),
12066842Sth160488 		    stderr);
12070Sstevel@tonic-gate 		return (retcode);
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	if (mode_verbose)
12110Sstevel@tonic-gate 		CLIENT_FPUTS(
12126842Sth160488 		    gettext("About to modify this machines configuration "
12136842Sth160488 		    "by writing the files\n"),
12146842Sth160488 		    stderr);
12150Sstevel@tonic-gate 
12160Sstevel@tonic-gate 	/* get ready to start playing with files */
12170Sstevel@tonic-gate 	retcode = stop_services(STATE_SAVE);
12180Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
12190Sstevel@tonic-gate 		CLIENT_FPUTS(
12206842Sth160488 		    gettext("Errors stopping network services.\n"), stderr);
12210Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate 
12240Sstevel@tonic-gate 	/* Temporarily save orig versions of files */
12250Sstevel@tonic-gate 	retcode = mod_backup();
12260Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
12270Sstevel@tonic-gate 		CLIENT_FPUTS(
12286842Sth160488 		    gettext("Unable to backup the ldap client files!\n"),
12296842Sth160488 		    stderr);
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 		return (retcode);
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	}
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	/* Dump new files */
12360Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
12370Sstevel@tonic-gate 	if (errorp != NULL) {
12380Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
12396842Sth160488 		    gettext("%s mod: errorp is not NULL; %s\n"),
12406842Sth160488 		    cmd, errorp->message);
12410Sstevel@tonic-gate 		retcode = mod_recover();
12420Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
12430Sstevel@tonic-gate 			CLIENT_FPUTS(
12446842Sth160488 			    gettext("Recovery of systems configuration "
12456842Sth160488 			    "failed.  Manual intervention of "
12466842Sth160488 			    "config files is required.\n"),
12476842Sth160488 			    stderr);
12480Sstevel@tonic-gate 		}
12490Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
12500Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
12510Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
12520Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
12536842Sth160488 			    "starting services during reset\n"),
12546842Sth160488 			    reset_ret);
12550Sstevel@tonic-gate 		}
12560Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
12570Sstevel@tonic-gate 	}
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 	/* if (credargs(arglist)) */
12600Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
12610Sstevel@tonic-gate 	if (errorp != NULL) {
12620Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
12636842Sth160488 		    gettext("%s mod: errorp is not NULL; %s\n"),
12646842Sth160488 		    cmd, errorp->message);
12650Sstevel@tonic-gate 		retcode = mod_recover();
12660Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
12670Sstevel@tonic-gate 			CLIENT_FPUTS(
12686842Sth160488 			    gettext("Recovery of systems configuration "
12696842Sth160488 			    "failed.  Manual intervention of "
12706842Sth160488 			    "config files is required.\n"),
12716842Sth160488 			    stderr);
12720Sstevel@tonic-gate 		}
12730Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
12740Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
12750Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
12760Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
12776842Sth160488 			    "starting services during reset\n"),
12786842Sth160488 			    reset_ret);
12790Sstevel@tonic-gate 		}
12800Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
12810Sstevel@tonic-gate 	}
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate 	if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
12846842Sth160488 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
12850Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
12860Sstevel@tonic-gate 		retcode = mod_recover();
12870Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
12880Sstevel@tonic-gate 			CLIENT_FPUTS(
12896842Sth160488 			    gettext("Recovery of systems configuration "
12906842Sth160488 			    "failed!  Machine needs to be "
12916842Sth160488 			    "fixed!\n"),
12926842Sth160488 			    stderr);
12930Sstevel@tonic-gate 		}
12940Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
12950Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
12960Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
12976842Sth160488 			    "starting services during reset\n"),
12986842Sth160488 			    reset_ret);
12990Sstevel@tonic-gate 		}
13000Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
13010Sstevel@tonic-gate 	}
13020Sstevel@tonic-gate 	(void) write(domain_fp, dname, strlen(dname));
13030Sstevel@tonic-gate 	(void) write(domain_fp, "\n", 1);
13040Sstevel@tonic-gate 	(void) close(domain_fp);
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	retcode = start_services(START_INIT);
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 	if (retcode == CLIENT_SUCCESS) {
13090Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("System successfully configured\n"),
13106842Sth160488 		    stderr);
13110Sstevel@tonic-gate 	} else {
13120Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error resetting system.\n"
13136842Sth160488 		    "Recovering old system settings.\n"), stderr),
13146842Sth160488 
13156842Sth160488 		    /* stop any started services for recover */
13166842Sth160488 		    /* don't stomp on history of saved services state */
13176842Sth160488 		    reset_ret = stop_services(STATE_NOSAVE);
13180Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
13190Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
13206842Sth160488 			    "stopping services during reset\n"),
13216842Sth160488 			    reset_ret);
13220Sstevel@tonic-gate 			/* Coninue and try to recover what we can */
13230Sstevel@tonic-gate 		}
13240Sstevel@tonic-gate 		reset_ret = mod_recover();
13250Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
13260Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
13276842Sth160488 			    "recovering service files during "
13286842Sth160488 			    "reset\n"), reset_ret);
13290Sstevel@tonic-gate 			/* Continue and start what we can */
13300Sstevel@tonic-gate 		}
13310Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
13320Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
13330Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
13346842Sth160488 			    "starting services during reset\n"),
13356842Sth160488 			    reset_ret);
13360Sstevel@tonic-gate 		}
13370Sstevel@tonic-gate 	}
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 	/* Cleanup temporary files created by mod_backup() */
13400Sstevel@tonic-gate 	mod_cleanup();
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	return (retcode);
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate static int
13470Sstevel@tonic-gate client_genProfile(clientopts_t *arglist)
13480Sstevel@tonic-gate {
13490Sstevel@tonic-gate 	int counter;
13500Sstevel@tonic-gate 	int retcode;	/* required for LDAP_SET_PARAM macro */
13510Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	if (mode_verbose)
13540Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("About to generate a profile\n"), stderr);
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	/* *** Check for invalid args *** */
13570Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->proxyDN, "proxyDN");
13580Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->proxyPassword, "proxyPassword");
1359*8821SMichen.Chang@Sun.COM 	LDAP_CHECK_INVALID(arglist->enableShadowUpdate,
1360*8821SMichen.Chang@Sun.COM 	    "enableShadowUpdate");
1361*8821SMichen.Chang@Sun.COM 	LDAP_CHECK_INVALID(arglist->adminDN, "adminDN");
1362*8821SMichen.Chang@Sun.COM 	LDAP_CHECK_INVALID(arglist->adminPassword, "adminPassword");
13630Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->certificatePath, "certificatePath");
13640Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->domainName, "domainName");
13656842Sth160488 	LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
13666842Sth160488 	LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
13670Sstevel@tonic-gate 	/* *** End check for invalid args *** */
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	if (arglist->profileName == NULL) {
13700Sstevel@tonic-gate 		if (mode_verbose)
13710Sstevel@tonic-gate 			CLIENT_FPUTS(
13726842Sth160488 			    gettext("No profile specified. "
13736842Sth160488 			    "Using \"default\"\n"),
13746842Sth160488 			    stderr);
13750Sstevel@tonic-gate 		arglist->profileName = "default";
13760Sstevel@tonic-gate 	}
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 	__ns_ldap_setServer(TRUE);
13790Sstevel@tonic-gate 	__ns_ldap_default_config();
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	/* Set version to latest (not version 1) */
13820Sstevel@tonic-gate 	LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	/* Set additional valid params from command line */
13850Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
13860Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
13870Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
13880Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
13890Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
13900Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
13910Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
13920Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
13930Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
13940Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
13950Sstevel@tonic-gate 	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 	for (counter = 0;
13986842Sth160488 	    counter < arglist->serviceAuthenticationMethod->count;
13996842Sth160488 	    counter++) {
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 		LDAP_SET_PARAM(
14026842Sth160488 		    arglist->serviceAuthenticationMethod->optlist[counter],
14036842Sth160488 		    NS_LDAP_SERVICE_AUTH_METHOD_P);
14040Sstevel@tonic-gate 	}
14050Sstevel@tonic-gate 	for (counter = 0;
14066842Sth160488 	    counter < arglist->serviceCredentialLevel->count;
14076842Sth160488 	    counter++) {
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 		LDAP_SET_PARAM(
14106842Sth160488 		    arglist->serviceCredentialLevel->optlist[counter],
14116842Sth160488 		    NS_LDAP_SERVICE_CRED_LEVEL_P);
14120Sstevel@tonic-gate 	}
14130Sstevel@tonic-gate 	for (counter = 0;
14146842Sth160488 	    counter < arglist->objectclassMap->count;
14156842Sth160488 	    counter++) {
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate 		LDAP_SET_PARAM(
14186842Sth160488 		    arglist->objectclassMap->optlist[counter],
14196842Sth160488 		    NS_LDAP_OBJECTCLASSMAP_P);
14200Sstevel@tonic-gate 	}
14210Sstevel@tonic-gate 	for (counter = 0;
14226842Sth160488 	    counter < arglist->attributeMap->count;
14236842Sth160488 	    counter++) {
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 		LDAP_SET_PARAM(
14266842Sth160488 		    arglist->attributeMap->optlist[counter],
14276842Sth160488 		    NS_LDAP_ATTRIBUTEMAP_P);
14280Sstevel@tonic-gate 	}
14296842Sth160488 	for (counter = 0;
14306842Sth160488 	    counter < arglist->serviceSearchDescriptor->count;
14316842Sth160488 	    counter++) {
14326842Sth160488 
14336842Sth160488 		LDAP_SET_PARAM(
14346842Sth160488 		    arglist->serviceSearchDescriptor->optlist[counter],
14356842Sth160488 		    NS_LDAP_SERVICE_SEARCH_DESC_P);
14360Sstevel@tonic-gate 	}
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate 	errorp = __ns_ldap_DumpLdif(NULL);
14390Sstevel@tonic-gate 	if (errorp != NULL) {
14400Sstevel@tonic-gate 		CLIENT_FPUTS(errorp->message, stderr);
14410Sstevel@tonic-gate 		CLIENT_FPUTC('\n', stderr);
14420Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
14430Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
14440Sstevel@tonic-gate 	}
14450Sstevel@tonic-gate 
14460Sstevel@tonic-gate 	return (CLIENT_SUCCESS);
14470Sstevel@tonic-gate }
14480Sstevel@tonic-gate 
14496842Sth160488 /* INET6_ADDRSTRLEN + ":" + <5-digit port> + some round-up */
14506842Sth160488 #define	MAX_HOSTADDR_LEN (INET6_ADDRSTRLEN + 6 + 12)
14516842Sth160488 
14520Sstevel@tonic-gate static int
14530Sstevel@tonic-gate client_init(clientopts_t *arglist)
14540Sstevel@tonic-gate {
14556842Sth160488 	int			profile_fp;
14566842Sth160488 	int			retcode = CLIENT_SUCCESS;
14576842Sth160488 	ns_ldap_error_t		*errorp;
14586842Sth160488 	int			reset_ret;
14596842Sth160488 	int			ret_copy;
14606842Sth160488 	ns_standalone_conf_t	cfg = standaloneDefaults;
14616842Sth160488 	ns_auth_t		auth = {NS_LDAP_AUTH_NONE,
14626842Sth160488 					NS_LDAP_TLS_NONE,
14636842Sth160488 					NS_LDAP_SASL_NONE,
14646842Sth160488 					NS_LDAP_SASLOPT_NONE};
14656842Sth160488 	char			peer[MAX_HOSTADDR_LEN];
14666842Sth160488 	ns_auth_t		**authMethod;
14676842Sth160488 	int			**credLevel, i;
14686842Sth160488 	char			*cred;
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 	if (mode_verbose)
14710Sstevel@tonic-gate 		CLIENT_FPUTS(
14726842Sth160488 		    gettext("About to configure machine by downloading "
14736842Sth160488 		    "a profile\n"),
14746842Sth160488 		    stderr);
14750Sstevel@tonic-gate 
14760Sstevel@tonic-gate 	if (dname == NULL) {
14770Sstevel@tonic-gate 		CLIENT_FPUTS(
14786842Sth160488 		    gettext("Init failed: System domain not set and "
14796842Sth160488 		    "no domainName specified.\n"),
14806842Sth160488 		    stderr);
14810Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
14820Sstevel@tonic-gate 	}
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate 	if (!arglist->defaultServerList) {
14850Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Missing LDAP server address\n"), stderr);
14860Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
14870Sstevel@tonic-gate 	}
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 	/* *** Check for invalid args *** */
14900Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->defaultSearchBase,
14916842Sth160488 	    "defaultSearchBase");
14920Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->profileTTL,
14936842Sth160488 	    "profileTTL");
14940Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->searchTimeLimit,
14956842Sth160488 	    "searchTimeLimit");
14960Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->preferredServerList,
14976842Sth160488 	    "preferredServerList");
14980Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->followReferrals,
14996842Sth160488 	    "followReferrals");
15000Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->defaultSearchScope,
15016842Sth160488 	    "defaultSearchScope");
15020Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->bindTimeLimit,
15036842Sth160488 	    "bindTimeLimit");
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->objectclassMap->count,
15066842Sth160488 	    "objectclassMap");
15070Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->attributeMap->count,
15086842Sth160488 	    "attributeMap");
15090Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->serviceAuthenticationMethod->count,
15106842Sth160488 	    "serviceAuthenticationMethod");
15110Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->serviceCredentialLevel->count,
15126842Sth160488 	    "serviceCredentialLevel");
15130Sstevel@tonic-gate 	LDAP_CHECK_INVALID(arglist->serviceSearchDescriptor->count,
15146842Sth160488 	    "serviceSearchDescriptor");
15150Sstevel@tonic-gate 	/* *** End check for invalid args *** */
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	if (arglist->profileName == NULL) {
15180Sstevel@tonic-gate 		if (mode_verbose)
15190Sstevel@tonic-gate 			CLIENT_FPUTS(
15206842Sth160488 			    gettext("No profile specified. "
15216842Sth160488 			    "Using \"default\"\n"),
15226842Sth160488 			    stderr);
15230Sstevel@tonic-gate 		arglist->profileName = "default";
15240Sstevel@tonic-gate 	}
15250Sstevel@tonic-gate 
15266842Sth160488 	(void) strncpy(peer, arglist->defaultServerList, MAX_HOSTADDR_LEN - 1);
15276842Sth160488 	if (separatePort(peer, &cfg.SA_SERVER, &cfg.SA_PORT) > 0) {
15280Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
15290Sstevel@tonic-gate 	}
15306842Sth160488 
15316842Sth160488 	if (arglist->bindDN != NULL) {
15326842Sth160488 		cfg.SA_CRED = "proxy";
15336842Sth160488 		/*
15346842Sth160488 		 * We don't want to force users to always specify authentication
1535*8821SMichen.Chang@Sun.COM 		 * method when we can infer it. If users want SSL, he/she would
15366842Sth160488 		 * have to specify appropriate -a though.
15376842Sth160488 		 */
15386842Sth160488 		auth.type = NS_LDAP_AUTH_SIMPLE;
15396842Sth160488 		if (arglist->bindPasswd == NULL) {
15406842Sth160488 			arglist->bindPasswd =
15416842Sth160488 			    getpassphrase("Bind Password:");
15426842Sth160488 			if (arglist->bindPasswd == NULL) {
15436842Sth160488 				CLIENT_FPUTS(gettext("Get password failed\n"),
15446842Sth160488 				    stderr);
15456842Sth160488 
15466842Sth160488 				if (gStartLdap == START_RESET)
15476842Sth160488 					(void) start_service(LDAP_FMRI, B_TRUE);
15486842Sth160488 
15496842Sth160488 				return (CLIENT_ERR_CREDENTIAL);
15506842Sth160488 			}
15516842Sth160488 		}
15520Sstevel@tonic-gate 	}
15536842Sth160488 	cfg.SA_BIND_DN = arglist->bindDN;
15546842Sth160488 	cfg.SA_BIND_PWD = arglist->bindPasswd;
15556842Sth160488 
15566842Sth160488 	if (arglist->authenticationMethod != NULL) {
15576842Sth160488 		if (__ns_ldap_initAuth(arglist->authenticationMethod,
15586842Sth160488 		    &auth, &errorp) != NS_LDAP_SUCCESS) {
15596842Sth160488 			if (errorp != NULL) {
15606842Sth160488 				CLIENT_FPRINTF(stderr, "%s", errorp->message);
15616842Sth160488 				(void) __ns_ldap_freeError(&errorp);
15626842Sth160488 			}
15636842Sth160488 
15646842Sth160488 			if (gStartLdap == START_RESET)
15656842Sth160488 				(void) start_service(LDAP_FMRI, B_TRUE);
15666842Sth160488 
15676842Sth160488 			return (CLIENT_ERR_FAIL);
15686842Sth160488 		}
15696842Sth160488 		cfg.SA_AUTH = &auth;
15706842Sth160488 	}
15716842Sth160488 	cfg.SA_CRED = arglist->credentialLevel;
15726842Sth160488 
15736842Sth160488 	cfg.SA_DOMAIN = arglist->domainName;
15746842Sth160488 	cfg.SA_PROFILE_NAME = arglist->profileName;
15756842Sth160488 	cfg.SA_CERT_PATH = arglist->certificatePath;
15766842Sth160488 
15776842Sth160488 	cfg.type = NS_LDAP_SERVER;
15786842Sth160488 
15796842Sth160488 	if (__ns_ldap_initStandalone(&cfg, &errorp) != NS_LDAP_SUCCESS) {
15800Sstevel@tonic-gate 		if (errorp != NULL) {
15816842Sth160488 			CLIENT_FPRINTF(stderr, "%s", errorp->message);
15820Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&errorp);
15830Sstevel@tonic-gate 		}
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate 		if (gStartLdap == START_RESET)
15860Sstevel@tonic-gate 			(void) start_service(LDAP_FMRI, B_TRUE);
15870Sstevel@tonic-gate 
15880Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
15890Sstevel@tonic-gate 	}
15900Sstevel@tonic-gate 
15916842Sth160488 	if (arglist->proxyDN != NULL && arglist->proxyPassword == NULL) {
15926842Sth160488 		arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
15936842Sth160488 		if (arglist->proxyPassword == NULL) {
15946842Sth160488 			CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
15956842Sth160488 
15966842Sth160488 			if (gStartLdap == START_RESET)
15976842Sth160488 				(void) start_service(LDAP_FMRI, B_TRUE);
15986842Sth160488 
15996842Sth160488 			return (CLIENT_ERR_CREDENTIAL);
16006842Sth160488 		}
16016842Sth160488 	}
16026842Sth160488 	if (arglist->proxyDN != NULL && arglist->proxyPassword != NULL) {
16036842Sth160488 		if (__ns_ldap_setParam(NS_LDAP_BINDDN_P,
16046842Sth160488 		    arglist->proxyDN, &errorp) != NS_LDAP_SUCCESS) {
16056842Sth160488 			if (errorp != NULL) {
16066842Sth160488 				CLIENT_FPRINTF(stderr, "%s", errorp->message);
16076842Sth160488 				(void) __ns_ldap_freeError(&errorp);
16086842Sth160488 			}
16096842Sth160488 			return (CLIENT_ERR_CREDENTIAL);
16106842Sth160488 		}
16116842Sth160488 		if (__ns_ldap_setParam(NS_LDAP_BINDPASSWD_P,
16126842Sth160488 		    arglist->proxyPassword, &errorp) != NS_LDAP_SUCCESS) {
16136842Sth160488 			if (errorp != NULL) {
16146842Sth160488 				CLIENT_FPRINTF(stderr, "%s", errorp->message);
16156842Sth160488 				(void) __ns_ldap_freeError(&errorp);
16166842Sth160488 			}
16176842Sth160488 			return (CLIENT_ERR_CREDENTIAL);
16186842Sth160488 		}
16190Sstevel@tonic-gate 	}
16206842Sth160488 
1621*8821SMichen.Chang@Sun.COM 	if (arglist->enableShadowUpdate != NULL) {
1622*8821SMichen.Chang@Sun.COM 		LDAP_SET_PARAM(arglist->enableShadowUpdate,
1623*8821SMichen.Chang@Sun.COM 		    NS_LDAP_ENABLE_SHADOW_UPDATE_P);
1624*8821SMichen.Chang@Sun.COM 	}
1625*8821SMichen.Chang@Sun.COM 
1626*8821SMichen.Chang@Sun.COM 	if (arglist->enableShadowUpdate &&
1627*8821SMichen.Chang@Sun.COM 	    strcasecmp(arglist->enableShadowUpdate, "TRUE") == 0 &&
1628*8821SMichen.Chang@Sun.COM 	    arglist->adminDN != NULL && arglist->adminPassword == NULL) {
1629*8821SMichen.Chang@Sun.COM 		arglist->adminPassword = getpassphrase("admin Bind Password:");
1630*8821SMichen.Chang@Sun.COM 		if (arglist->adminPassword == NULL) {
1631*8821SMichen.Chang@Sun.COM 			CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
1632*8821SMichen.Chang@Sun.COM 
1633*8821SMichen.Chang@Sun.COM 			if (gStartLdap == START_RESET)
1634*8821SMichen.Chang@Sun.COM 				(void) start_service(LDAP_FMRI, B_TRUE);
1635*8821SMichen.Chang@Sun.COM 
1636*8821SMichen.Chang@Sun.COM 			return (CLIENT_ERR_CREDENTIAL);
1637*8821SMichen.Chang@Sun.COM 		}
1638*8821SMichen.Chang@Sun.COM 	}
1639*8821SMichen.Chang@Sun.COM 	if (arglist->adminDN != NULL && arglist->adminPassword != NULL) {
1640*8821SMichen.Chang@Sun.COM 		if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDDN_P,
1641*8821SMichen.Chang@Sun.COM 		    arglist->adminDN, &errorp) != NS_LDAP_SUCCESS) {
1642*8821SMichen.Chang@Sun.COM 			if (errorp != NULL) {
1643*8821SMichen.Chang@Sun.COM 				CLIENT_FPRINTF(stderr, "%s\n", errorp->message);
1644*8821SMichen.Chang@Sun.COM 				(void) __ns_ldap_freeError(&errorp);
1645*8821SMichen.Chang@Sun.COM 			}
1646*8821SMichen.Chang@Sun.COM 			return (CLIENT_ERR_CREDENTIAL);
1647*8821SMichen.Chang@Sun.COM 		}
1648*8821SMichen.Chang@Sun.COM 		if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1649*8821SMichen.Chang@Sun.COM 		    arglist->adminPassword, &errorp) != NS_LDAP_SUCCESS) {
1650*8821SMichen.Chang@Sun.COM 			if (errorp != NULL) {
1651*8821SMichen.Chang@Sun.COM 				CLIENT_FPRINTF(stderr, "%s\n", errorp->message);
1652*8821SMichen.Chang@Sun.COM 				(void) __ns_ldap_freeError(&errorp);
1653*8821SMichen.Chang@Sun.COM 			}
1654*8821SMichen.Chang@Sun.COM 			return (CLIENT_ERR_CREDENTIAL);
1655*8821SMichen.Chang@Sun.COM 		}
1656*8821SMichen.Chang@Sun.COM 	}
1657*8821SMichen.Chang@Sun.COM 
16586842Sth160488 	if (arglist->authenticationMethod != NULL) {
16596842Sth160488 		if (__ns_ldap_getParam(NS_LDAP_AUTH_P,
16606842Sth160488 		    (void ***)&authMethod, &errorp) != NS_LDAP_SUCCESS) {
16616842Sth160488 			if (errorp != NULL) {
16626842Sth160488 				CLIENT_FPRINTF(stderr, "%s", errorp->message);
16636842Sth160488 				(void) __ns_ldap_freeError(&errorp);
16646842Sth160488 			}
16656842Sth160488 			return (CLIENT_ERR_CREDENTIAL);
16666842Sth160488 		}
16676842Sth160488 
16686842Sth160488 		if (authMethod != NULL) {
16696842Sth160488 			for (i = 0; authMethod[i] != NULL; ++i) {
16706842Sth160488 				if (authMethod[i]->type == auth.type) {
16716842Sth160488 					break;
16726842Sth160488 				}
16736842Sth160488 			}
16746842Sth160488 
16756842Sth160488 			if (authMethod[i] == NULL) {
16766842Sth160488 				CLIENT_FPRINTF(stderr, gettext(
16776842Sth160488 				    "Warning: init authentication method "
16786842Sth160488 				    "not found in DUAConfigProfile.\n"));
16796842Sth160488 			} else {
16806842Sth160488 				if (i != 0) {
16816842Sth160488 					CLIENT_FPRINTF(stderr,
16826842Sth160488 					    gettext(
16836842Sth160488 					    "Warning: init authentication"
16846842Sth160488 					    "method using secondary "
16856842Sth160488 					    "authentication method from "
16866842Sth160488 					    "DUAConfigProfile.\n"));
16876842Sth160488 				}
16886842Sth160488 			}
16896842Sth160488 			(void) __ns_ldap_freeParam((void ***) &authMethod);
16906842Sth160488 		}
16910Sstevel@tonic-gate 	}
16926842Sth160488 
16936842Sth160488 	if (arglist->credentialLevel != NULL) {
16946842Sth160488 		if (__ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
16956842Sth160488 		    (void ***)&credLevel, &errorp) != NS_LDAP_SUCCESS) {
16966842Sth160488 			if (errorp != NULL) {
16976842Sth160488 				CLIENT_FPRINTF(stderr, "%s", errorp->message);
16986842Sth160488 				(void) __ns_ldap_freeError(&errorp);
16996842Sth160488 			}
17006842Sth160488 			return (CLIENT_ERR_CREDENTIAL);
17016842Sth160488 		}
17026842Sth160488 		if (credLevel != NULL) {
17036842Sth160488 			for (i = 0; credLevel[i] != NULL; ++i) {
17046842Sth160488 				switch (*credLevel[i]) {
17056842Sth160488 				case NS_LDAP_CRED_ANON :
17066842Sth160488 					cred = "none";
17076842Sth160488 					break;
17086842Sth160488 				case NS_LDAP_CRED_PROXY :
17096842Sth160488 					cred = "proxy";
17106842Sth160488 					break;
17116842Sth160488 				case NS_LDAP_CRED_SELF :
17126842Sth160488 					cred = "self";
17136842Sth160488 					break;
17146842Sth160488 				default:
17156842Sth160488 					continue;
17166842Sth160488 					break;
17176842Sth160488 				}
17186842Sth160488 				if (strcmp(cred,
17196842Sth160488 				    arglist->credentialLevel) == 0) {
17206842Sth160488 					break;
17216842Sth160488 				}
17226842Sth160488 			}
17236842Sth160488 			if (credLevel[i] == NULL) {
17246842Sth160488 				CLIENT_FPRINTF(stderr, gettext(
17256842Sth160488 				    "Warning: init credential level not found "
17266842Sth160488 				    "in DUAConfigProfile.\n"));
17276842Sth160488 			} else {
17286842Sth160488 				if (i != 0) {
17296842Sth160488 					CLIENT_FPRINTF(stderr,
17306842Sth160488 					    gettext("Warning: "
17316842Sth160488 					    "init credential level using "
17326842Sth160488 					    "secondary credential level from "
17336842Sth160488 					    "DUAConfigProfile.\n"));
17346842Sth160488 				}
17356842Sth160488 			}
17366842Sth160488 			(void) __ns_ldap_freeParam((void ***) &credLevel);
17376842Sth160488 		}
17386842Sth160488 	}
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate 	retcode = credCheck(arglist);
1741*8821SMichen.Chang@Sun.COM 	if (retcode == CLIENT_SUCCESS)
1742*8821SMichen.Chang@Sun.COM 		retcode = adminCredCheck(arglist);
17430Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
17440Sstevel@tonic-gate 		CLIENT_FPUTS(
17456842Sth160488 		    gettext("Error in setting up credentials\n"), stderr);
17460Sstevel@tonic-gate 
17470Sstevel@tonic-gate 		if (gStartLdap == START_RESET)
17480Sstevel@tonic-gate 			(void) start_service(LDAP_FMRI, B_TRUE);
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 		return (retcode);
17510Sstevel@tonic-gate 	}
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	if (mode_verbose)
17540Sstevel@tonic-gate 		CLIENT_FPUTS(
17556842Sth160488 		    gettext("About to modify this machines configuration "
17566842Sth160488 		    "by writing the files\n"),
17576842Sth160488 		    stderr);
17580Sstevel@tonic-gate 
17590Sstevel@tonic-gate 	/* get ready to start playing with files */
17600Sstevel@tonic-gate 	retcode = stop_services(STATE_SAVE);
17610Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
17620Sstevel@tonic-gate 		CLIENT_FPUTS(
17636842Sth160488 		    gettext("Errors stopping network services.\n"), stderr);
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 		if (gStartLdap == START_RESET)
17660Sstevel@tonic-gate 			(void) start_service(LDAP_FMRI, B_TRUE);
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
17690Sstevel@tonic-gate 	}
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate 	/* Save orig versions of files */
17720Sstevel@tonic-gate 	retcode = file_backup();
17730Sstevel@tonic-gate 	if (retcode == CLIENT_ERR_RESTORE) {
17740Sstevel@tonic-gate 		CLIENT_FPUTS(
17756842Sth160488 		    gettext("System not in state to enable ldap client.\n"),
17766842Sth160488 		    stderr);
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 		return (retcode);
17790Sstevel@tonic-gate 
17800Sstevel@tonic-gate 	} else if (retcode != CLIENT_SUCCESS) {
17810Sstevel@tonic-gate 		CLIENT_FPUTS(
17826842Sth160488 		    gettext("Save of system configuration failed.  "
17836842Sth160488 		    "Attempting recovery.\n"),
17846842Sth160488 		    stderr);
17850Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
17860Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
17870Sstevel@tonic-gate 			CLIENT_FPUTS(
17886842Sth160488 			    gettext("Recovery of systems configuration "
17896842Sth160488 			    "failed.  Manual intervention of "
17906842Sth160488 			    "config files is required.\n"),
17916842Sth160488 			    stderr);
17920Sstevel@tonic-gate 		}
17930Sstevel@tonic-gate 
17940Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
17950Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
17960Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
17976842Sth160488 			    "starting services during reset\n"),
17986842Sth160488 			    reset_ret);
17990Sstevel@tonic-gate 		}
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 		return (retcode);
18020Sstevel@tonic-gate 	}
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	/* Dump new files */
18050Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
18060Sstevel@tonic-gate 	if (NULL != errorp) {
18070Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
18086842Sth160488 		    gettext("%s init: errorp is not NULL; %s\n"),
18096842Sth160488 		    cmd, errorp->message);
18100Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
18110Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
18120Sstevel@tonic-gate 			CLIENT_FPUTS(
18136842Sth160488 			    gettext("Recovery of systems configuration "
18146842Sth160488 			    "failed.  Manual intervention of "
18156842Sth160488 			    "config files is required.\n"),
18166842Sth160488 			    stderr);
18170Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
18180Sstevel@tonic-gate 		}
18190Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
18200Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
18210Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
18220Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
18236842Sth160488 			    "starting services during reset\n"),
18246842Sth160488 			    reset_ret);
18250Sstevel@tonic-gate 		}
18260Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
18270Sstevel@tonic-gate 	}
18280Sstevel@tonic-gate 
18290Sstevel@tonic-gate 	/* if (credargs(arglist)) */
18300Sstevel@tonic-gate 	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
18310Sstevel@tonic-gate 	if (NULL != errorp) {
18320Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
18336842Sth160488 		    gettext("%s init: errorp is not NULL; %s\n"),
18346842Sth160488 		    cmd, errorp->message);
18350Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
18360Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
18370Sstevel@tonic-gate 			CLIENT_FPUTS(
18386842Sth160488 			    gettext("Recovery of systems configuration "
18396842Sth160488 			    "failed.  Manual intervention of "
18406842Sth160488 			    "config files is required.\n"),
18416842Sth160488 			    stderr);
18420Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
18430Sstevel@tonic-gate 		}
18440Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
18450Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
18460Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
18470Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
18486842Sth160488 			    "starting services during reset\n"),
18496842Sth160488 			    reset_ret);
18500Sstevel@tonic-gate 		}
18510Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
18520Sstevel@tonic-gate 	}
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 	ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
18550Sstevel@tonic-gate 	if (ret_copy != 0) {
18560Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
18576842Sth160488 		    gettext("Error %d copying (%s) -> (%s)\n"),
18586842Sth160488 		    ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
18590Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
18600Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
18610Sstevel@tonic-gate 			CLIENT_FPUTS(
18626842Sth160488 			    gettext("Recovery of systems configuration "
18636842Sth160488 			    "failed.  Manual intervention of "
18646842Sth160488 			    "config files is required.\n"),
18656842Sth160488 			    stderr);
18660Sstevel@tonic-gate 		}
18670Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
18680Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
18690Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
18706842Sth160488 			    "starting services during reset\n"),
18716842Sth160488 			    reset_ret);
18720Sstevel@tonic-gate 		}
18730Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
18740Sstevel@tonic-gate 	}
18750Sstevel@tonic-gate 
18760Sstevel@tonic-gate 	if ((profile_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
18776842Sth160488 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
18780Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
18790Sstevel@tonic-gate 		retcode = recover(STATE_NOSAVE);
18800Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
18810Sstevel@tonic-gate 			CLIENT_FPUTS(
18826842Sth160488 			    gettext("Recovery of systems configuration "
18836842Sth160488 			    "failed.  Manual intervention of "
18846842Sth160488 			    "config files is required.\n"),
18856842Sth160488 			    stderr);
18860Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
18870Sstevel@tonic-gate 		}
18880Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
18890Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
18900Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
18916842Sth160488 			    "starting services during reset\n"),
18926842Sth160488 			    reset_ret);
18930Sstevel@tonic-gate 		}
18940Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
18950Sstevel@tonic-gate 	}
18960Sstevel@tonic-gate 	(void) write(profile_fp, dname, strlen(dname));
18970Sstevel@tonic-gate 	(void) write(profile_fp, "\n", 1);
18980Sstevel@tonic-gate 	(void) close(profile_fp);
18990Sstevel@tonic-gate 
19000Sstevel@tonic-gate 	retcode = start_services(START_INIT);
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 	if (retcode == CLIENT_SUCCESS) {
19030Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("System successfully configured\n"),
19046842Sth160488 		    stderr);
19050Sstevel@tonic-gate 	} else {
19060Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error resetting system.\n"
19076842Sth160488 		    "Recovering old system settings.\n"), stderr),
19086842Sth160488 
19096842Sth160488 		    /* stop any started services for recover */
19106842Sth160488 		    /* don't stomp on history of saved services state */
19116842Sth160488 		    reset_ret = stop_services(STATE_NOSAVE);
19120Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
19130Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
19146842Sth160488 			    "stopping services during reset\n"),
19156842Sth160488 			    reset_ret);
19160Sstevel@tonic-gate 			/* Coninue and try to recover what we can */
19170Sstevel@tonic-gate 		}
19180Sstevel@tonic-gate 		reset_ret = recover(STATE_NOSAVE);
19190Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
19200Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
19216842Sth160488 			    "recovering service files during "
19226842Sth160488 			    "reset\n"), reset_ret);
19230Sstevel@tonic-gate 			/* Continue and start what we can */
19240Sstevel@tonic-gate 		}
19250Sstevel@tonic-gate 		reset_ret = start_services(START_RESET);
19260Sstevel@tonic-gate 		if (reset_ret != CLIENT_SUCCESS) {
19270Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
19286842Sth160488 			    "starting services during reset\n"),
19296842Sth160488 			    reset_ret);
19300Sstevel@tonic-gate 		}
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	return (retcode);
19340Sstevel@tonic-gate }
19350Sstevel@tonic-gate 
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate static void
19380Sstevel@tonic-gate usage(void)
19390Sstevel@tonic-gate {
19400Sstevel@tonic-gate 	if (mode_quiet)
19410Sstevel@tonic-gate 		return;
19420Sstevel@tonic-gate 
19430Sstevel@tonic-gate 	if (gen == 0) {
19440Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
19456842Sth160488 		    gettext("Usage: %s [-v | -q] init | manual | mod | "
19466842Sth160488 		    "list | uninit [<args>]\n"),
19476842Sth160488 		    cmd);
19486842Sth160488 
19496842Sth160488 		CLIENT_FPRINTF(stderr,
19506842Sth160488 		    gettext("\n       %s [-v | -q] [-a authenticationMethod]"
19516842Sth160488 		    " [-D bindDN]\n\t[-w bindPassword] [-j passswdFile]"
1952*8821SMichen.Chang@Sun.COM 		    " [-y proxyPasswordFile]\n\t"
1953*8821SMichen.Chang@Sun.COM 		    "[-z adminPasswordFile] init [<args>]\n"),
19546842Sth160488 		    cmd);
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 		CLIENT_FPUTS(
19576842Sth160488 		    gettext("\nSet up a server or workstation as a "
19586842Sth160488 		    "client of an LDAP namespace.\n"),
19596842Sth160488 		    stderr);
19600Sstevel@tonic-gate 	} else {	/* genprofile */
19610Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
19626842Sth160488 		    gettext("Usage: %s [-v | -q] genprofile "
19636842Sth160488 		    "-a profileName=<name> "
19646842Sth160488 		    "-a defaultSearchBase=<base> <args>\n"),
19656842Sth160488 		    cmd);
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 		CLIENT_FPUTS(
19686842Sth160488 		    gettext("\nGenerate a profile used to set up clients "
19696842Sth160488 		    "of an LDAP namespace.\n"),
19706842Sth160488 		    stderr);
19710Sstevel@tonic-gate 	}
19720Sstevel@tonic-gate 	CLIENT_FPUTS(
19736842Sth160488 	    gettext("<args> take the form of \'-a attrName=attrVal\' as "
19746842Sth160488 	    "described in the\n"),
19756842Sth160488 	    stderr);
19760Sstevel@tonic-gate 	CLIENT_FPUTS(gettext("man page: ldapclient(1M)\n"), stderr);
19770Sstevel@tonic-gate }
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 
19800Sstevel@tonic-gate /*
19810Sstevel@tonic-gate  * stop_services is called to stop network services prior to their
19820Sstevel@tonic-gate  * config files being moved/changed.  In case a later recovery is needed
19830Sstevel@tonic-gate  * (an error occurs during config), we detect whether the service is
19840Sstevel@tonic-gate  * running and store that info so that a reset will only start services
19850Sstevel@tonic-gate  * that were stopped here.
19860Sstevel@tonic-gate  *
19870Sstevel@tonic-gate  * In terms of SMF, this translates to disabling the services. So we
19880Sstevel@tonic-gate  * try to disable them if they are in any other state
19890Sstevel@tonic-gate  *
19900Sstevel@tonic-gate  * Stop order :
19910Sstevel@tonic-gate  * sendmail, nscd, autofs, ldap.client, nisd (rpc), inetinit(domainname)
19920Sstevel@tonic-gate  */
19930Sstevel@tonic-gate static int
19940Sstevel@tonic-gate stop_services(int saveState)
19950Sstevel@tonic-gate {
19960Sstevel@tonic-gate 	int ret;
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate 	if (mode_verbose) {
19990Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Stopping network services\n"), stderr);
20000Sstevel@tonic-gate 	}
20010Sstevel@tonic-gate 
20020Sstevel@tonic-gate 	if (!is_service(SENDMAIL_FMRI, SCF_STATE_STRING_DISABLED)) {
20030Sstevel@tonic-gate 		if (mode_verbose)
20040Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping sendmail\n"), stderr);
20050Sstevel@tonic-gate 		ret = disable_service(SENDMAIL_FMRI, B_TRUE);
20060Sstevel@tonic-gate 		if (ret != CLIENT_SUCCESS) {
20070Sstevel@tonic-gate 			/* Not serious, but tell user what to do */
20080Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping sendmail "
20096842Sth160488 			    "failed with (%d). You may need to restart "
20106842Sth160488 			    "it manually for changes to take effect.\n"),
20116842Sth160488 			    ret);
20120Sstevel@tonic-gate 		} else enableFlag |= SENDMAIL_ON;
20130Sstevel@tonic-gate 	} else {
20140Sstevel@tonic-gate 		if (mode_verbose)
20150Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("sendmail not running\n"), stderr);
20160Sstevel@tonic-gate 	}
20170Sstevel@tonic-gate 
20180Sstevel@tonic-gate 	if (!is_service(NSCD_FMRI, SCF_STATE_STRING_DISABLED)) {
20190Sstevel@tonic-gate 		if (mode_verbose)
20200Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping nscd\n"), stderr);
20210Sstevel@tonic-gate 		ret = disable_service(NSCD_FMRI, B_TRUE);
20220Sstevel@tonic-gate 		if (ret != CLIENT_SUCCESS) {
20230Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping nscd "
20240Sstevel@tonic-gate 			    "failed with (%d)\n"), ret);
20250Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
20260Sstevel@tonic-gate 		} else enableFlag |= NSCD_ON;
20270Sstevel@tonic-gate 	} else {
20280Sstevel@tonic-gate 		if (mode_verbose)
20290Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("nscd not running\n"), stderr);
20300Sstevel@tonic-gate 	}
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate 	if (!is_service(AUTOFS_FMRI, SCF_STATE_STRING_DISABLED)) {
20330Sstevel@tonic-gate 		if (mode_verbose)
20340Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping autofs\n"), stderr);
20350Sstevel@tonic-gate 		ret = disable_service(AUTOFS_FMRI, B_TRUE);
20360Sstevel@tonic-gate 		if (ret != CLIENT_SUCCESS) {
20370Sstevel@tonic-gate 			/* Not serious, but tell user what to do */
20380Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping autofs "
20396842Sth160488 			    "failed with (%d). You may need to restart "
20406842Sth160488 			    "it manually for changes to take effect.\n"),
20416842Sth160488 			    ret);
20420Sstevel@tonic-gate 		} else enableFlag |= AUTOFS_ON;
20430Sstevel@tonic-gate 	} else {
20440Sstevel@tonic-gate 		if (mode_verbose)
20450Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("autofs not running\n"), stderr);
20460Sstevel@tonic-gate 	}
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 	if (!is_service(LDAP_FMRI, SCF_STATE_STRING_DISABLED)) {
20490Sstevel@tonic-gate 		if (saveState)
20500Sstevel@tonic-gate 			gStartLdap = START_RESET;
20510Sstevel@tonic-gate 		if (mode_verbose)
20520Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping ldap\n"), stderr);
20530Sstevel@tonic-gate 		ret = disable_service(LDAP_FMRI, B_TRUE);
20540Sstevel@tonic-gate 		if (ret != CLIENT_SUCCESS) {
20550Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping ldap "
20560Sstevel@tonic-gate 			    "failed with (%d)\n"), ret);
20570Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
20580Sstevel@tonic-gate 		}
20590Sstevel@tonic-gate 	} else {
20600Sstevel@tonic-gate 		if (mode_verbose)
20610Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("ldap not running\n"),
20626842Sth160488 			    stderr);
20630Sstevel@tonic-gate 	}
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 	if (!is_service(NISD_FMRI, SCF_STATE_STRING_DISABLED)) {
20660Sstevel@tonic-gate 		if (mode_verbose)
20670Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping nisd\n"), stderr);
20680Sstevel@tonic-gate 		ret = disable_service(NISD_FMRI, B_TRUE);
20690Sstevel@tonic-gate 		if (ret != CLIENT_SUCCESS) {
20700Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping nisd "
20710Sstevel@tonic-gate 			    "failed with (%d)\n"), ret);
20720Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
20730Sstevel@tonic-gate 		}
20740Sstevel@tonic-gate 	} else {
20750Sstevel@tonic-gate 		if (mode_verbose)
20760Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("nisd not running\n"),
20776842Sth160488 			    stderr);
20780Sstevel@tonic-gate 	}
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate 	if (!is_service(YP_FMRI, SCF_STATE_STRING_DISABLED)) {
20810Sstevel@tonic-gate 		if (saveState)
20820Sstevel@tonic-gate 			gStartYp = START_RESET;
20830Sstevel@tonic-gate 		if (mode_verbose)
20840Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Stopping nis(yp)\n"), stderr);
20850Sstevel@tonic-gate 		ret = disable_service(YP_FMRI, B_TRUE);
20860Sstevel@tonic-gate 		if (ret != 0) {
20870Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("Stopping nis(yp) "
20880Sstevel@tonic-gate 			    "failed with (%d)\n"), ret);
20890Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
20900Sstevel@tonic-gate 		}
20910Sstevel@tonic-gate 	} else {
20920Sstevel@tonic-gate 		if (mode_verbose)
20930Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("nis(yp) not running\n"),
20946842Sth160488 			    stderr);
20950Sstevel@tonic-gate 	}
20960Sstevel@tonic-gate 
20970Sstevel@tonic-gate 	return (CLIENT_SUCCESS);
20980Sstevel@tonic-gate }
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate /*
21010Sstevel@tonic-gate  * start_services is called to start up network services after config
21020Sstevel@tonic-gate  * files have all been setup or recovered.  In the case of an error, the
21030Sstevel@tonic-gate  * files will be recovered and start_services will be called with the
21040Sstevel@tonic-gate  * "reset" flag set so that only those services that were earlier stopped
21050Sstevel@tonic-gate  * will be started.  If it is not a reset, then the services associated
21060Sstevel@tonic-gate  * with files "recovered" will attempt to be started.
21070Sstevel@tonic-gate  */
21080Sstevel@tonic-gate static int
21090Sstevel@tonic-gate start_services(int flag)
21100Sstevel@tonic-gate {
21112830Sdjl 	int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS;
21120Sstevel@tonic-gate 	FILE *domain_fp;
21130Sstevel@tonic-gate 	char domainname[BUFSIZ];
21140Sstevel@tonic-gate 	char cmd_domain_start[BUFSIZ];
21150Sstevel@tonic-gate 	int domainlen;
21162830Sdjl 	ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
21172830Sdjl 	ns_ldap_error_t		*errorp = NULL;
21180Sstevel@tonic-gate 
21190Sstevel@tonic-gate 	if (mode_verbose) {
21200Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Starting network services\n"), stderr);
21210Sstevel@tonic-gate 	}
21220Sstevel@tonic-gate 
21230Sstevel@tonic-gate 	/* Read in current defaultdomain so we can set it */
21240Sstevel@tonic-gate 	domain_fp = fopen(DOMAINNAME, "r");
21250Sstevel@tonic-gate 	if (domain_fp == NULL) {
21260Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr, gettext("Error opening defaultdomain "
21276842Sth160488 		    "(%d)\n"), errno);
21280Sstevel@tonic-gate 		/* if we did an ldap init, we must have domain */
21290Sstevel@tonic-gate 		if (flag == START_INIT)
21300Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
21310Sstevel@tonic-gate 	} else {
21320Sstevel@tonic-gate 		if (fgets(domainname, BUFSIZ, domain_fp) == NULL) {
21330Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Error reading defaultdomain\n"),
21346842Sth160488 			    stderr);
21350Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
21360Sstevel@tonic-gate 		}
21370Sstevel@tonic-gate 
21380Sstevel@tonic-gate 		if (fclose(domain_fp) != 0) {
21390Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
21406842Sth160488 			    gettext("Error closing defaultdomain (%d)\n"),
21416842Sth160488 			    errno);
21420Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
21430Sstevel@tonic-gate 		}
21440Sstevel@tonic-gate 		domainlen = strlen(domainname);
21450Sstevel@tonic-gate 		/* sanity check to make sure sprintf will fit */
21460Sstevel@tonic-gate 		if (domainlen > (BUFSIZE - sizeof (CMD_DOMAIN_START) -
21476842Sth160488 		    sizeof (TO_DEV_NULL) - 3)) {
21480Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Specified domainname is "
21496842Sth160488 			    "too large\n"), stderr);
21500Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
21510Sstevel@tonic-gate 		}
21520Sstevel@tonic-gate 		if (domainname[domainlen-1] == '\n')
21530Sstevel@tonic-gate 			domainname[domainlen-1] = 0;
21540Sstevel@tonic-gate 		/* buffer size is checked above */
21552830Sdjl 		(void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s",
21566842Sth160488 		    CMD_DOMAIN_START, domainname, TO_DEV_NULL);
21570Sstevel@tonic-gate 	}
21580Sstevel@tonic-gate 
21590Sstevel@tonic-gate 	/*
21600Sstevel@tonic-gate 	 * We can be starting services after an init in which case
21610Sstevel@tonic-gate 	 * we want to start ldap and not start yp or nis+.
21620Sstevel@tonic-gate 	 */
21630Sstevel@tonic-gate 	if (flag == START_INIT) {
21640Sstevel@tonic-gate 		sysret = system(cmd_domain_start);
21650Sstevel@tonic-gate 		if (mode_verbose)
21660Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
21676842Sth160488 			    CMD_DOMAIN_START, domainname,
21686842Sth160488 			    (sysret == 0) ? gettext("success") :
21696842Sth160488 			    gettext("failed"));
21700Sstevel@tonic-gate 		if (sysret != 0) {
21710Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, gettext("\"%s\" returned: %d\n"),
21726842Sth160488 			    CMD_DOMAIN_START, sysret);
21730Sstevel@tonic-gate 
21740Sstevel@tonic-gate 			retcode = CLIENT_ERR_FAIL;
21750Sstevel@tonic-gate 		}
21760Sstevel@tonic-gate 
21772830Sdjl 		if ((rc = __ns_ldap_self_gssapi_config(&config)) !=
21786842Sth160488 		    NS_LDAP_SUCCESS) {
21792830Sdjl 			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
21806842Sth160488 			    "checking sasl/GSSAPI configuration\n"),
21816842Sth160488 			    rc);
21820Sstevel@tonic-gate 			retcode = CLIENT_ERR_FAIL;
21832830Sdjl 		}
21842830Sdjl 
21852830Sdjl 		if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
21862830Sdjl 
21872830Sdjl 			rc = __ns_ldap_check_dns_preq(
21886842Sth160488 			    1, mode_verbose, mode_quiet,
21896842Sth160488 			    NSSWITCH_LDAP, config, &errorp);
21902830Sdjl 			if (errorp)
21912830Sdjl 				(void) __ns_ldap_freeError(&errorp);
21922830Sdjl 
21932830Sdjl 			if (rc != NS_LDAP_SUCCESS)
21942830Sdjl 				retcode = CLIENT_ERR_FAIL;
21952830Sdjl 		}
21962830Sdjl 
21972830Sdjl 		if (rc == NS_LDAP_SUCCESS &&
21986842Sth160488 		    start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
21992830Sdjl 			retcode = CLIENT_ERR_FAIL;
22002830Sdjl 
22012830Sdjl 		if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
22026842Sth160488 		    rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) {
22032830Sdjl 			rc = __ns_ldap_check_gssapi_preq(
22046842Sth160488 			    1, mode_verbose, mode_quiet, config,
22056842Sth160488 			    &errorp);
22062830Sdjl 			if (errorp)
22072830Sdjl 				(void) __ns_ldap_freeError(&errorp);
22082830Sdjl 
22092830Sdjl 			if (rc != NS_LDAP_SUCCESS)
22102830Sdjl 				retcode = CLIENT_ERR_FAIL;
22112830Sdjl 
22122830Sdjl 		}
22130Sstevel@tonic-gate 		/* No YP or NIS+ after init */
22140Sstevel@tonic-gate 	/*
22150Sstevel@tonic-gate 	 * Or we can be starting services after an uninit or error
22160Sstevel@tonic-gate 	 * recovery.  We want to start whatever services were running
22170Sstevel@tonic-gate 	 * before.  In the case of error recovery, it is the services
22180Sstevel@tonic-gate 	 * that were running before we stopped them (flags set in
22190Sstevel@tonic-gate 	 * stop_services).  If it is an uninit then we determine
22200Sstevel@tonic-gate 	 * which services to start based on the files we recovered
22210Sstevel@tonic-gate 	 * (flags set in recover).
22220Sstevel@tonic-gate 	 */
22230Sstevel@tonic-gate 	} else {
22240Sstevel@tonic-gate 		/* uninit and recover should set flags of what to start */
22250Sstevel@tonic-gate 		if (domain_fp) {
22260Sstevel@tonic-gate 			sysret = system(cmd_domain_start);
22270Sstevel@tonic-gate 			if (mode_verbose)
22280Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
22296842Sth160488 				    CMD_DOMAIN_START, domainname,
22306842Sth160488 				    (sysret == 0) ? gettext("success") :
22316842Sth160488 				    gettext("failed"));
22320Sstevel@tonic-gate 			if (sysret != 0) {
22330Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr, gettext("\"%s\" "
22346842Sth160488 				    "returned: %d\n"),
22356842Sth160488 				    CMD_DOMAIN_START, sysret);
22360Sstevel@tonic-gate 
22370Sstevel@tonic-gate 				retcode = CLIENT_ERR_FAIL;
22380Sstevel@tonic-gate 			}
22390Sstevel@tonic-gate 		}
22400Sstevel@tonic-gate 
22410Sstevel@tonic-gate 		if (gStartLdap == flag) {
22420Sstevel@tonic-gate 			if (!(is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE)))
22430Sstevel@tonic-gate 				if (start_service(LDAP_FMRI, B_TRUE)
22446842Sth160488 				    != CLIENT_SUCCESS)
22450Sstevel@tonic-gate 					retcode = CLIENT_ERR_FAIL;
22460Sstevel@tonic-gate 		}
22470Sstevel@tonic-gate 
22480Sstevel@tonic-gate 		if (gStartYp == flag) {
22490Sstevel@tonic-gate 			if (!(is_service(YP_FMRI, SCF_STATE_STRING_ONLINE)))
22500Sstevel@tonic-gate 				(void) start_service(YP_FMRI, B_TRUE);
22510Sstevel@tonic-gate 		}
22520Sstevel@tonic-gate 
22530Sstevel@tonic-gate 		if (gStartNisd == flag) {
22540Sstevel@tonic-gate 			if (!(is_service(NISD_FMRI, SCF_STATE_STRING_ONLINE)))
22550Sstevel@tonic-gate 				(void) start_service(NISD_FMRI, B_TRUE);
22560Sstevel@tonic-gate 		}
22570Sstevel@tonic-gate 
22580Sstevel@tonic-gate 	}
22590Sstevel@tonic-gate 	if ((enableFlag & AUTOFS_ON) &&
22600Sstevel@tonic-gate 	    !(is_service(AUTOFS_FMRI, SCF_STATE_STRING_ONLINE)))
22610Sstevel@tonic-gate 		(void) start_service(AUTOFS_FMRI, B_TRUE);
22620Sstevel@tonic-gate 
22630Sstevel@tonic-gate 	if ((enableFlag & NSCD_ON) &&
22640Sstevel@tonic-gate 	    !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE)))
22650Sstevel@tonic-gate 		(void) start_service(NSCD_FMRI, B_TRUE);
22660Sstevel@tonic-gate 
22672830Sdjl #if 0
22682830Sdjl 	if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
22692830Sdjl 	    retcode == CLIENT_SUCCESS &&
22702830Sdjl 	    !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) {
22712830Sdjl 		CLIENT_FPRINTF(stderr, "start: %s\n",
22726842Sth160488 		    gettext("self/sasl/GSSAPI is configured"
22736842Sth160488 		    " but nscd is not online"));
22742830Sdjl 		retcode = CLIENT_ERR_FAIL;
22752830Sdjl 	}
22762830Sdjl #endif
22772830Sdjl 
22780Sstevel@tonic-gate 	if ((enableFlag & SENDMAIL_ON) &&
22790Sstevel@tonic-gate 	    !(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE)))
22800Sstevel@tonic-gate 		(void) start_service(SENDMAIL_FMRI, B_TRUE);
22810Sstevel@tonic-gate 
22820Sstevel@tonic-gate 	/*
22830Sstevel@tonic-gate 	 * Restart name-service milestone so that any consumer
22840Sstevel@tonic-gate 	 * which depends on it will be restarted.
22850Sstevel@tonic-gate 	 */
22860Sstevel@tonic-gate 	(void) restart_service(NS_MILESTONE_FMRI, B_TRUE);
22870Sstevel@tonic-gate 	return (retcode);
22880Sstevel@tonic-gate }
22890Sstevel@tonic-gate 
22900Sstevel@tonic-gate /*
22910Sstevel@tonic-gate  * credCheck is called to check if credentials are required for this
22920Sstevel@tonic-gate  * configuration.  Currently, this means that if any credentialLevel is
22930Sstevel@tonic-gate  * proxy and any authenticationMethod is something other than none, then
22940Sstevel@tonic-gate  * credential info is required (proxyDN and proxyPassword).
22950Sstevel@tonic-gate  */
22960Sstevel@tonic-gate static int
22970Sstevel@tonic-gate credCheck(clientopts_t *arglist)
22980Sstevel@tonic-gate {
22990Sstevel@tonic-gate 	int counter;
23000Sstevel@tonic-gate 	int **credLevel;
23010Sstevel@tonic-gate 	ns_auth_t **authMethod;
23020Sstevel@tonic-gate 	char **proxyDN, **proxyPassword;
23030Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
23040Sstevel@tonic-gate 	int credProxy, authNotNone;
23050Sstevel@tonic-gate 	int retcode;
23060Sstevel@tonic-gate 
23070Sstevel@tonic-gate /* If credentialLevel is proxy, make sure we have proxyDN and proxyPassword */
23080Sstevel@tonic-gate 	retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
23096842Sth160488 	    (void ***)&credLevel, &errorp);
23100Sstevel@tonic-gate 	if (retcode != 0) {
23110Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23126842Sth160488 		    gettext("Error %d while trying to retrieve "
23136842Sth160488 		    "credLevel\n"),
23146842Sth160488 		    retcode);
23150Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
23160Sstevel@tonic-gate 	}
23170Sstevel@tonic-gate 	retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
23186842Sth160488 	    (void ***)&authMethod, &errorp);
23190Sstevel@tonic-gate 	if (retcode != 0) {
23200Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23216842Sth160488 		    gettext("Error %d while trying to retrieve "
23226842Sth160488 		    "authMethod\n"), retcode);
23230Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
23240Sstevel@tonic-gate 	}
23250Sstevel@tonic-gate 	retcode = __ns_ldap_getParam(NS_LDAP_BINDDN_P,
23266842Sth160488 	    (void ***)&proxyDN, &errorp);
23270Sstevel@tonic-gate 	if (retcode != 0) {
23280Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23296842Sth160488 		    gettext("Error %d while trying to retrieve proxyDN\n"),
23306842Sth160488 		    retcode);
23310Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
23320Sstevel@tonic-gate 	}
23330Sstevel@tonic-gate 	retcode = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P,
23346842Sth160488 	    (void ***)&proxyPassword, &errorp);
23350Sstevel@tonic-gate 	if (retcode != 0) {
23360Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23376842Sth160488 		    gettext("Error %d while trying to retrieve "
23386842Sth160488 		    "proxyPassword\n"), retcode);
23390Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
23400Sstevel@tonic-gate 	}
23410Sstevel@tonic-gate 
23420Sstevel@tonic-gate 	if (mode_verbose) {
23430Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23446842Sth160488 		    gettext("Proxy DN: %s\n"),
23456842Sth160488 		    (proxyDN && proxyDN[0]) ? proxyDN[0] : "NULL");
23460Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
23476842Sth160488 		    gettext("Proxy password: %s\n"),
23486842Sth160488 		    (proxyPassword && proxyPassword[0]) ?
23496842Sth160488 		    proxyPassword[0] : "NULL");
23500Sstevel@tonic-gate 	}
23510Sstevel@tonic-gate 
23520Sstevel@tonic-gate 	credProxy = 0;	/* flag to indicate if we have a credLevel of proxy */
23530Sstevel@tonic-gate 	for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
23540Sstevel@tonic-gate 		if (mode_verbose)
23550Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
23566842Sth160488 			    gettext("Credential level: %d\n"),
23576842Sth160488 			    *credLevel[counter]);
23580Sstevel@tonic-gate 		if (*credLevel[counter] == NS_LDAP_CRED_PROXY) {
23590Sstevel@tonic-gate 			credProxy = 1;
23600Sstevel@tonic-gate 			break;
23610Sstevel@tonic-gate 		}
23620Sstevel@tonic-gate 	}
23630Sstevel@tonic-gate 
23640Sstevel@tonic-gate 	authNotNone = 0;	/* flag for authMethod other than none */
23650Sstevel@tonic-gate 	for (counter = 0;
23666842Sth160488 	    authMethod && authMethod[counter] != NULL;
23676842Sth160488 	    counter++) {
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate 		if (mode_verbose)
23700Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
23716842Sth160488 			    gettext("Authentication method: %d\n"),
23726842Sth160488 			    authMethod[counter]->type);
23730Sstevel@tonic-gate 		if (authMethod[counter]->type != NS_LDAP_AUTH_NONE &&
23740Sstevel@tonic-gate 		    !(authMethod[counter]->type == NS_LDAP_AUTH_TLS &&
23750Sstevel@tonic-gate 		    authMethod[counter]->tlstype == NS_LDAP_TLS_NONE)) {
23760Sstevel@tonic-gate 			authNotNone = 1;
23770Sstevel@tonic-gate 			break;
23780Sstevel@tonic-gate 		}
23790Sstevel@tonic-gate 	}
23800Sstevel@tonic-gate 
23810Sstevel@tonic-gate 	/* First, if we don't need proxyDN/Password then just return ok */
23820Sstevel@tonic-gate 	if (!(credProxy && authNotNone)) {
23830Sstevel@tonic-gate 		if (mode_verbose)
23840Sstevel@tonic-gate 			CLIENT_FPUTS(
23856842Sth160488 			    gettext("No proxyDN/proxyPassword required\n"),
23866842Sth160488 			    stderr);
23870Sstevel@tonic-gate 		return (CLIENT_SUCCESS);
23880Sstevel@tonic-gate 	}
23890Sstevel@tonic-gate 
23900Sstevel@tonic-gate 	/* Now let's check if we have the cred stuff we need */
23910Sstevel@tonic-gate 	if (!proxyDN || !proxyDN[0]) {
23920Sstevel@tonic-gate 		CLIENT_FPUTS(
23936842Sth160488 		    gettext("credentialLevel is proxy and no proxyDN "
23946842Sth160488 		    "specified\n"),
23956842Sth160488 		    stderr);
23960Sstevel@tonic-gate 		return (CLIENT_ERR_CREDENTIAL);
23970Sstevel@tonic-gate 	}
23980Sstevel@tonic-gate 
23990Sstevel@tonic-gate 	/* If we need proxyPassword (prompt) */
24000Sstevel@tonic-gate 	if (!proxyPassword || !proxyPassword[0]) {
24010Sstevel@tonic-gate 		CLIENT_FPUTS(
24026842Sth160488 		    gettext("credentialLevel requires proxyPassword\n"),
24036842Sth160488 		    stderr);
24040Sstevel@tonic-gate 		arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
24050Sstevel@tonic-gate 		if (arglist->proxyPassword == NULL) {
24060Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
24070Sstevel@tonic-gate 			return (CLIENT_ERR_CREDENTIAL);
24080Sstevel@tonic-gate 		}
24090Sstevel@tonic-gate 		LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
24100Sstevel@tonic-gate 		if (retcode != 0) {
24110Sstevel@tonic-gate 			CLIENT_FPUTS(
24126842Sth160488 			    gettext("setParam proxyPassword failed.\n"),
24136842Sth160488 			    stderr);
24140Sstevel@tonic-gate 			return (CLIENT_ERR_CREDENTIAL);
24150Sstevel@tonic-gate 		}
24160Sstevel@tonic-gate 	}
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate 	return (CLIENT_SUCCESS);
24190Sstevel@tonic-gate }
24200Sstevel@tonic-gate 
24210Sstevel@tonic-gate /*
2422*8821SMichen.Chang@Sun.COM  * adminCredCheck is called to check if the admin credential is required
2423*8821SMichen.Chang@Sun.COM  * for this configuration. This means that if enableShadowUpdate is set
2424*8821SMichen.Chang@Sun.COM  * to TRUE then credential info is required (adminDN and adminPassword).
2425*8821SMichen.Chang@Sun.COM  * One exception is that if there is a 'self' credentialLevel and
2426*8821SMichen.Chang@Sun.COM  * 'sasl/GSSAPI' authenticationMethod (i.e., possibly using Kerberos
2427*8821SMichen.Chang@Sun.COM  * host credential) then adminDN and adminPassword are not required.
2428*8821SMichen.Chang@Sun.COM  */
2429*8821SMichen.Chang@Sun.COM static int
2430*8821SMichen.Chang@Sun.COM adminCredCheck(clientopts_t *arglist)
2431*8821SMichen.Chang@Sun.COM {
2432*8821SMichen.Chang@Sun.COM 	int counter;
2433*8821SMichen.Chang@Sun.COM 	int **enabled = NULL;
2434*8821SMichen.Chang@Sun.COM 	int **credLevel = NULL;
2435*8821SMichen.Chang@Sun.COM 	char **adminDN = NULL;
2436*8821SMichen.Chang@Sun.COM 	char **adminPassword = NULL;
2437*8821SMichen.Chang@Sun.COM 	ns_auth_t **authMethod = NULL;
2438*8821SMichen.Chang@Sun.COM 	ns_ldap_error_t *errorp = NULL;
2439*8821SMichen.Chang@Sun.COM 	int credSelf, authSASLgss;
2440*8821SMichen.Chang@Sun.COM 	int retcode, rc;
2441*8821SMichen.Chang@Sun.COM 
2442*8821SMichen.Chang@Sun.COM 	/* If shadow update not enabled, then no need to check */
2443*8821SMichen.Chang@Sun.COM 	retcode = __ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
2444*8821SMichen.Chang@Sun.COM 	    (void ***)&enabled, &errorp);
2445*8821SMichen.Chang@Sun.COM 	if (retcode != 0) {
2446*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2447*8821SMichen.Chang@Sun.COM 		    gettext("Error %d while trying to retrieve "
2448*8821SMichen.Chang@Sun.COM 		    "enableShadowUpdate\n"), retcode);
2449*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_FAIL;
2450*8821SMichen.Chang@Sun.COM 		goto out;
2451*8821SMichen.Chang@Sun.COM 	}
2452*8821SMichen.Chang@Sun.COM 	if (enabled == NULL ||
2453*8821SMichen.Chang@Sun.COM 	    *enabled[0] != NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE) {
2454*8821SMichen.Chang@Sun.COM 		if (mode_verbose)
2455*8821SMichen.Chang@Sun.COM 			CLIENT_FPUTS(
2456*8821SMichen.Chang@Sun.COM 			    gettext("Shadow Update is not enabled, "
2457*8821SMichen.Chang@Sun.COM 			    "no adminDN/adminPassword is required.\n"), stderr);
2458*8821SMichen.Chang@Sun.COM 		rc = CLIENT_SUCCESS;
2459*8821SMichen.Chang@Sun.COM 		goto out;
2460*8821SMichen.Chang@Sun.COM 	}
2461*8821SMichen.Chang@Sun.COM 
2462*8821SMichen.Chang@Sun.COM 	/* get credentialLevel */
2463*8821SMichen.Chang@Sun.COM 	retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
2464*8821SMichen.Chang@Sun.COM 	    (void ***)&credLevel, &errorp);
2465*8821SMichen.Chang@Sun.COM 	if (retcode != 0) {
2466*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2467*8821SMichen.Chang@Sun.COM 		    gettext("Error %d while trying to retrieve credLevel\n"),
2468*8821SMichen.Chang@Sun.COM 		    retcode);
2469*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_FAIL;
2470*8821SMichen.Chang@Sun.COM 		goto out;
2471*8821SMichen.Chang@Sun.COM 	}
2472*8821SMichen.Chang@Sun.COM 
2473*8821SMichen.Chang@Sun.COM 	/* get AuthenticationMethod */
2474*8821SMichen.Chang@Sun.COM 	retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
2475*8821SMichen.Chang@Sun.COM 	    (void ***)&authMethod, &errorp);
2476*8821SMichen.Chang@Sun.COM 	if (retcode != 0) {
2477*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2478*8821SMichen.Chang@Sun.COM 		    gettext("Error %d while trying to retrieve authMethod\n"),
2479*8821SMichen.Chang@Sun.COM 		    retcode);
2480*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_FAIL;
2481*8821SMichen.Chang@Sun.COM 		goto out;
2482*8821SMichen.Chang@Sun.COM 	}
2483*8821SMichen.Chang@Sun.COM 
2484*8821SMichen.Chang@Sun.COM 	/* get adminDN */
2485*8821SMichen.Chang@Sun.COM 	retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDDN_P,
2486*8821SMichen.Chang@Sun.COM 	    (void ***)&adminDN, &errorp);
2487*8821SMichen.Chang@Sun.COM 	if (retcode != 0) {
2488*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2489*8821SMichen.Chang@Sun.COM 		    gettext("Error %d while trying to retrieve adminDN\n"),
2490*8821SMichen.Chang@Sun.COM 		    retcode);
2491*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_FAIL;
2492*8821SMichen.Chang@Sun.COM 		goto out;
2493*8821SMichen.Chang@Sun.COM 	}
2494*8821SMichen.Chang@Sun.COM 
2495*8821SMichen.Chang@Sun.COM 	/* get adminPassword */
2496*8821SMichen.Chang@Sun.COM 	retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
2497*8821SMichen.Chang@Sun.COM 	    (void ***)&adminPassword, &errorp);
2498*8821SMichen.Chang@Sun.COM 	if (retcode != 0) {
2499*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2500*8821SMichen.Chang@Sun.COM 		    gettext("Error %d while trying to retrieve "
2501*8821SMichen.Chang@Sun.COM 		    "adminPassword\n"), retcode);
2502*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_FAIL;
2503*8821SMichen.Chang@Sun.COM 		goto out;
2504*8821SMichen.Chang@Sun.COM 	}
2505*8821SMichen.Chang@Sun.COM 
2506*8821SMichen.Chang@Sun.COM 	if (mode_verbose) {
2507*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2508*8821SMichen.Chang@Sun.COM 		    gettext("admin DN: %s\n"),
2509*8821SMichen.Chang@Sun.COM 		    (adminDN && adminDN[0]) ? adminDN[0] : "NULL");
2510*8821SMichen.Chang@Sun.COM 		CLIENT_FPRINTF(stderr,
2511*8821SMichen.Chang@Sun.COM 		    gettext("admin password: %s\n"),
2512*8821SMichen.Chang@Sun.COM 		    (adminPassword && adminPassword[0]) ?
2513*8821SMichen.Chang@Sun.COM 		    adminPassword[0] : "NULL");
2514*8821SMichen.Chang@Sun.COM 	}
2515*8821SMichen.Chang@Sun.COM 
2516*8821SMichen.Chang@Sun.COM 	credSelf = 0;	/* flag to indicate if we have a credLevel of self */
2517*8821SMichen.Chang@Sun.COM 	for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
2518*8821SMichen.Chang@Sun.COM 		if (mode_verbose)
2519*8821SMichen.Chang@Sun.COM 			CLIENT_FPRINTF(stderr,
2520*8821SMichen.Chang@Sun.COM 			    gettext("Credential level: %d\n"),
2521*8821SMichen.Chang@Sun.COM 			    *credLevel[counter]);
2522*8821SMichen.Chang@Sun.COM 		if (*credLevel[counter] == NS_LDAP_CRED_SELF) {
2523*8821SMichen.Chang@Sun.COM 			credSelf = 1;
2524*8821SMichen.Chang@Sun.COM 			break;
2525*8821SMichen.Chang@Sun.COM 		}
2526*8821SMichen.Chang@Sun.COM 	}
2527*8821SMichen.Chang@Sun.COM 
2528*8821SMichen.Chang@Sun.COM 	authSASLgss = 0;	/* flag for authMethod of SASL/gssapi */
2529*8821SMichen.Chang@Sun.COM 	for (counter = 0;
2530*8821SMichen.Chang@Sun.COM 	    authMethod && authMethod[counter] != NULL;
2531*8821SMichen.Chang@Sun.COM 	    counter++) {
2532*8821SMichen.Chang@Sun.COM 
2533*8821SMichen.Chang@Sun.COM 		if (mode_verbose)
2534*8821SMichen.Chang@Sun.COM 			CLIENT_FPRINTF(stderr,
2535*8821SMichen.Chang@Sun.COM 			    gettext("Authentication sasl mechanism: %d\n"),
2536*8821SMichen.Chang@Sun.COM 			    authMethod[counter]->saslmech);
2537*8821SMichen.Chang@Sun.COM 		if (authMethod[counter]->saslmech == NS_LDAP_SASL_GSSAPI) {
2538*8821SMichen.Chang@Sun.COM 			authSASLgss = 1;
2539*8821SMichen.Chang@Sun.COM 			break;
2540*8821SMichen.Chang@Sun.COM 		}
2541*8821SMichen.Chang@Sun.COM 	}
2542*8821SMichen.Chang@Sun.COM 
2543*8821SMichen.Chang@Sun.COM 	/* First, if we don't need adminDN/adminPassword then just return ok */
2544*8821SMichen.Chang@Sun.COM 	if (credSelf && authSASLgss) {
2545*8821SMichen.Chang@Sun.COM 		if (mode_verbose)
2546*8821SMichen.Chang@Sun.COM 			CLIENT_FPUTS(
2547*8821SMichen.Chang@Sun.COM 			    gettext("A credential Level of self and an "
2548*8821SMichen.Chang@Sun.COM 			    "authentication method of sasl/GSSAPI is "
2549*8821SMichen.Chang@Sun.COM 			    "configured, no adminDN/adminPassword "
2550*8821SMichen.Chang@Sun.COM 			    "is required.\n"), stderr);
2551*8821SMichen.Chang@Sun.COM 		rc = CLIENT_SUCCESS;
2552*8821SMichen.Chang@Sun.COM 		goto out;
2553*8821SMichen.Chang@Sun.COM 	}
2554*8821SMichen.Chang@Sun.COM 
2555*8821SMichen.Chang@Sun.COM 	/* Now let's check if we have the cred stuff we need */
2556*8821SMichen.Chang@Sun.COM 	if (adminDN == NULL || adminDN[0] == '\0') {
2557*8821SMichen.Chang@Sun.COM 		CLIENT_FPUTS(
2558*8821SMichen.Chang@Sun.COM 		    gettext("Shadow Update is enabled, but "
2559*8821SMichen.Chang@Sun.COM 		    "no adminDN is configured.\n"), stderr);
2560*8821SMichen.Chang@Sun.COM 		rc = CLIENT_ERR_CREDENTIAL;
2561*8821SMichen.Chang@Sun.COM 		goto out;
2562*8821SMichen.Chang@Sun.COM 	}
2563*8821SMichen.Chang@Sun.COM 
2564*8821SMichen.Chang@Sun.COM 	/* If we need adminPassword (prompt) */
2565*8821SMichen.Chang@Sun.COM 	if (adminPassword == NULL || adminPassword[0] == '\0') {
2566*8821SMichen.Chang@Sun.COM 		CLIENT_FPUTS(
2567*8821SMichen.Chang@Sun.COM 		    gettext("Shadow Update requires adminPassword\n"),
2568*8821SMichen.Chang@Sun.COM 		    stderr);
2569*8821SMichen.Chang@Sun.COM 		arglist->adminPassword = getpassphrase("admin Password:");
2570*8821SMichen.Chang@Sun.COM 		if (arglist->adminPassword == NULL) {
2571*8821SMichen.Chang@Sun.COM 			CLIENT_FPUTS(gettext("Unable to get admin password\n"),
2572*8821SMichen.Chang@Sun.COM 			    stderr);
2573*8821SMichen.Chang@Sun.COM 			rc = CLIENT_ERR_CREDENTIAL;
2574*8821SMichen.Chang@Sun.COM 			goto out;
2575*8821SMichen.Chang@Sun.COM 		}
2576*8821SMichen.Chang@Sun.COM 		LDAP_SET_PARAM(arglist->adminPassword,
2577*8821SMichen.Chang@Sun.COM 		    NS_LDAP_ADMIN_BINDPASSWD_P);
2578*8821SMichen.Chang@Sun.COM 		if (retcode != 0) {
2579*8821SMichen.Chang@Sun.COM 			CLIENT_FPUTS(
2580*8821SMichen.Chang@Sun.COM 			    gettext("setParam adminPassword failed.\n"),
2581*8821SMichen.Chang@Sun.COM 			    stderr);
2582*8821SMichen.Chang@Sun.COM 			rc = CLIENT_ERR_CREDENTIAL;
2583*8821SMichen.Chang@Sun.COM 			goto out;
2584*8821SMichen.Chang@Sun.COM 		}
2585*8821SMichen.Chang@Sun.COM 	}
2586*8821SMichen.Chang@Sun.COM 
2587*8821SMichen.Chang@Sun.COM 	rc = CLIENT_SUCCESS;
2588*8821SMichen.Chang@Sun.COM 
2589*8821SMichen.Chang@Sun.COM 	out:
2590*8821SMichen.Chang@Sun.COM 	if (enabled != NULL)
2591*8821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&enabled);
2592*8821SMichen.Chang@Sun.COM 	if (credLevel != NULL)
2593*8821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&credLevel);
2594*8821SMichen.Chang@Sun.COM 	if (authMethod != NULL)
2595*8821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&authMethod);
2596*8821SMichen.Chang@Sun.COM 	if (adminDN != NULL)
2597*8821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&adminDN);
2598*8821SMichen.Chang@Sun.COM 	if (adminPassword != NULL)
2599*8821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&adminPassword);
2600*8821SMichen.Chang@Sun.COM 
2601*8821SMichen.Chang@Sun.COM 	return (rc);
2602*8821SMichen.Chang@Sun.COM }
2603*8821SMichen.Chang@Sun.COM 
2604*8821SMichen.Chang@Sun.COM /*
26050Sstevel@tonic-gate  * try to restore the previous name space on this machine
26060Sstevel@tonic-gate  */
26070Sstevel@tonic-gate static int
26080Sstevel@tonic-gate recover(int saveState)
26090Sstevel@tonic-gate {
26100Sstevel@tonic-gate 	struct stat buf;
26110Sstevel@tonic-gate 	int stat_ret, retcode, fd;
26120Sstevel@tonic-gate 	int domain = 0, domainlen;
26130Sstevel@tonic-gate 	char yp_dir[BUFSIZE], yp_dir_back[BUFSIZE];
26140Sstevel@tonic-gate 	char name[BUFSIZ];
26150Sstevel@tonic-gate 	char *ldap_conf_file, *ldap_cred_file;
26160Sstevel@tonic-gate 	char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
26170Sstevel@tonic-gate 
26180Sstevel@tonic-gate 	/* If running as Sysid Install become a no-op */
26190Sstevel@tonic-gate 	if (sysid_install == B_TRUE)
26200Sstevel@tonic-gate 		return (CLIENT_SUCCESS);
26210Sstevel@tonic-gate 
26220Sstevel@tonic-gate 	stat_ret = stat(LDAP_RESTORE_DIR, &buf);
26230Sstevel@tonic-gate 	if (stat_ret != 0) {
26240Sstevel@tonic-gate 		CLIENT_FPUTS(
26256842Sth160488 		    gettext("Cannot recover.  No backup files "
26266842Sth160488 		    "found.\n"),
26276842Sth160488 		    stderr);
26280Sstevel@tonic-gate 		CLIENT_FPUTS(
26296842Sth160488 		    gettext("\t Either this machine was not initialized\n"),
26306842Sth160488 		    stderr);
26310Sstevel@tonic-gate 		CLIENT_FPUTS(
26326842Sth160488 		    gettext("\t by ldapclient or the backup files "
26336842Sth160488 		    "have been\n"),
26346842Sth160488 		    stderr);
26350Sstevel@tonic-gate 		CLIENT_FPUTS(
26366842Sth160488 		    gettext("\t removed manually or with an \"uninit\"\n"),
26376842Sth160488 		    stderr);
26380Sstevel@tonic-gate 		return (CLIENT_ERR_RESTORE);	/* invalid backup */
26390Sstevel@tonic-gate 	}
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 	/*
26420Sstevel@tonic-gate 	 * Get domainname.  Allow no domainname for the case where "files"
26430Sstevel@tonic-gate 	 * config was backed up.
26440Sstevel@tonic-gate 	 */
26450Sstevel@tonic-gate 	stat_ret = stat(DOMAINNAME_BACK, &buf);
26460Sstevel@tonic-gate 	if (mode_verbose)
26470Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
26486842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
26496842Sth160488 		    DOMAINNAME_BACK, stat_ret);
26500Sstevel@tonic-gate 	if (stat_ret == 0) {
26510Sstevel@tonic-gate 		if (mode_verbose)
26520Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
26536842Sth160488 			    gettext("recover: open(%s)\n"),
26546842Sth160488 			    DOMAINNAME_BACK);
26550Sstevel@tonic-gate 		fd = open(DOMAINNAME_BACK, O_RDONLY);
26560Sstevel@tonic-gate 		if (mode_verbose)
26570Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
26586842Sth160488 			    gettext("recover: read(%s)\n"),
26596842Sth160488 			    DOMAINNAME_BACK);
26600Sstevel@tonic-gate 		domainlen = read(fd, &(name[0]), BUFSIZ-1);
26610Sstevel@tonic-gate 		(void) close(fd);
26620Sstevel@tonic-gate 		if (domainlen < 0) {
26630Sstevel@tonic-gate 			CLIENT_FPUTS(
26646842Sth160488 			    gettext("Cannot recover.  Cannot determine "
26656842Sth160488 			    "previous domain name.\n"),
26666842Sth160488 			    stderr);
26670Sstevel@tonic-gate 			return (CLIENT_ERR_RESTORE);	/* invalid backup */
26680Sstevel@tonic-gate 		} else 	{
26690Sstevel@tonic-gate 			char *ptr;
26700Sstevel@tonic-gate 
26710Sstevel@tonic-gate 			ptr = strchr(&(name[0]), '\n');
26720Sstevel@tonic-gate 			if (ptr != NULL)
26730Sstevel@tonic-gate 				*ptr = '\0';
26740Sstevel@tonic-gate 			else
26750Sstevel@tonic-gate 				name[domainlen] = '\0';
26760Sstevel@tonic-gate 
26770Sstevel@tonic-gate 			if (mode_verbose)
26780Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
26796842Sth160488 				    gettext("recover: old domainname "
26806842Sth160488 				    "\"%s\"\n"), name);
26810Sstevel@tonic-gate 
26820Sstevel@tonic-gate 			if (strlen(name) == 0)
26830Sstevel@tonic-gate 				domain = 0;
26840Sstevel@tonic-gate 			else
26850Sstevel@tonic-gate 				domain = 1;	/* flag that we have domain */
26860Sstevel@tonic-gate 
26870Sstevel@tonic-gate 		}
26880Sstevel@tonic-gate 	}
26890Sstevel@tonic-gate 
26900Sstevel@tonic-gate 
26910Sstevel@tonic-gate 	/*
26920Sstevel@tonic-gate 	 * we can recover at this point
26930Sstevel@tonic-gate 	 * remove LDAP config files before restore
26940Sstevel@tonic-gate 	 */
26950Sstevel@tonic-gate 	(void) unlink(NSCONFIGFILE);
26960Sstevel@tonic-gate 	(void) unlink(NSCREDFILE);
26970Sstevel@tonic-gate 
26980Sstevel@tonic-gate 	ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
26990Sstevel@tonic-gate 	ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
27000Sstevel@tonic-gate 
27010Sstevel@tonic-gate 	(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
27020Sstevel@tonic-gate 	(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
27030Sstevel@tonic-gate 
27040Sstevel@tonic-gate 	stat_ret = stat(ldap_file_back, &buf);
27050Sstevel@tonic-gate 	if (mode_verbose)
27060Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
27076842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
27086842Sth160488 		    ldap_file_back, stat_ret);
27090Sstevel@tonic-gate 	if (stat_ret == 0) {
27100Sstevel@tonic-gate 		if (saveState)
27110Sstevel@tonic-gate 			gStartLdap = START_UNINIT;
27120Sstevel@tonic-gate 		retcode = file_move(ldap_file_back, NSCONFIGFILE);
27130Sstevel@tonic-gate 		if (mode_verbose)
27140Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27156842Sth160488 			    gettext("recover: file_move(%s, %s)=%d\n"),
27166842Sth160488 			    ldap_file_back, NSCONFIGFILE, retcode);
27170Sstevel@tonic-gate 		if (retcode != 0)
27180Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27196842Sth160488 			    gettext("recover: file_move(%s, %s) failed\n"),
27206842Sth160488 			    ldap_file_back, NSCONFIGFILE);
27210Sstevel@tonic-gate 	}
27220Sstevel@tonic-gate 
27230Sstevel@tonic-gate 	(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
27240Sstevel@tonic-gate 	(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
27250Sstevel@tonic-gate 
27260Sstevel@tonic-gate 	stat_ret = stat(ldap_cred_back, &buf);
27270Sstevel@tonic-gate 	if (mode_verbose)
27280Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
27296842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
27306842Sth160488 		    ldap_cred_back, stat_ret);
27310Sstevel@tonic-gate 	if (stat_ret == 0) {
27320Sstevel@tonic-gate 		retcode = file_move(ldap_cred_back, NSCREDFILE);
27330Sstevel@tonic-gate 		if (mode_verbose)
27340Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27356842Sth160488 			    gettext("recover: file_move(%s, %s)=%d\n"),
27366842Sth160488 			    ldap_cred_back, NSCREDFILE, retcode);
27370Sstevel@tonic-gate 		if (retcode != 0)
27380Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27396842Sth160488 			    gettext("recover: file_move(%s, %s) failed\n"),
27406842Sth160488 			    ldap_cred_back, NSCREDFILE);
27410Sstevel@tonic-gate 	}
27420Sstevel@tonic-gate 
27430Sstevel@tonic-gate 	/* Check for recovery of NIS+ */
27440Sstevel@tonic-gate 	stat_ret = stat(NIS_COLDSTART_BACK, &buf);
27450Sstevel@tonic-gate 	if (mode_verbose)
27460Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
27476842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
27486842Sth160488 		    NIS_COLDSTART_BACK, stat_ret);
27490Sstevel@tonic-gate 	if (stat_ret == 0) {
27500Sstevel@tonic-gate 		if (saveState) {
27510Sstevel@tonic-gate 			gStartNisd = START_UNINIT;
27520Sstevel@tonic-gate 		}
27530Sstevel@tonic-gate 		if (mode_verbose)
27540Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27556842Sth160488 			    gettext("recover: file_move(%s, %s)\n"),
27566842Sth160488 			    NIS_COLDSTART_BACK, NIS_COLDSTART);
27570Sstevel@tonic-gate 		retcode = file_move(NIS_COLDSTART_BACK, NIS_COLDSTART);
27580Sstevel@tonic-gate 		if (retcode != 0)
27590Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27606842Sth160488 			    gettext("recover: file_move(%s, %s) failed!\n"),
27616842Sth160488 			    NIS_COLDSTART_BACK, NIS_COLDSTART);
27620Sstevel@tonic-gate 	}
27630Sstevel@tonic-gate 
27640Sstevel@tonic-gate 	/* Check for recovery of NIS(YP) if we have a domainname */
27650Sstevel@tonic-gate 	if (domain) {
27660Sstevel@tonic-gate 		/* "name" would have to be huge for this, but just in case */
27670Sstevel@tonic-gate 		if (strlen(name) >= (BUFSIZE - strlen(LDAP_RESTORE_DIR)))
27680Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
27690Sstevel@tonic-gate 		if (strlen(name) >= (BUFSIZE - strlen(YP_BIND_DIR)))
27700Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
27710Sstevel@tonic-gate 
27720Sstevel@tonic-gate 		(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", BUFSIZE);
27730Sstevel@tonic-gate 		(void) strlcat(yp_dir_back, name, BUFSIZE);
27740Sstevel@tonic-gate 		stat_ret = stat(yp_dir_back, &buf);
27750Sstevel@tonic-gate 		if (mode_verbose)
27760Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
27776842Sth160488 			    gettext("recover: stat(%s)=%d\n"),
27786842Sth160488 			    yp_dir_back, stat_ret);
27790Sstevel@tonic-gate 		if (stat_ret == 0) {
27800Sstevel@tonic-gate 			(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
27810Sstevel@tonic-gate 			(void) strlcat(yp_dir, name, BUFSIZE);
27820Sstevel@tonic-gate 			retcode = file_move(yp_dir_back, yp_dir);
27830Sstevel@tonic-gate 			if (mode_verbose)
27840Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
27856842Sth160488 				    gettext("recover: file_move(%s, "
27866842Sth160488 				    "%s)=%d\n"),
27876842Sth160488 				    yp_dir_back, yp_dir, retcode);
27880Sstevel@tonic-gate 			if (retcode != 0) {
27890Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
27906842Sth160488 				    gettext("recover: file_move(%s, "
27916842Sth160488 				    "%s) failed!\n"),
27926842Sth160488 				    yp_dir_back, yp_dir);
27930Sstevel@tonic-gate 			} else {
27940Sstevel@tonic-gate 				if (saveState)
27950Sstevel@tonic-gate 					gStartYp = START_UNINIT;
27960Sstevel@tonic-gate 			}
27970Sstevel@tonic-gate 		}
27980Sstevel@tonic-gate 	}
27990Sstevel@tonic-gate 
28000Sstevel@tonic-gate 	/* restore machine configuration */
28010Sstevel@tonic-gate 	stat_ret = stat(NSSWITCH_BACK, &buf);
28020Sstevel@tonic-gate 	if (mode_verbose)
28030Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
28046842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
28056842Sth160488 		    NSSWITCH_BACK, stat_ret);
28060Sstevel@tonic-gate 	if (stat_ret == 0) {
28070Sstevel@tonic-gate 		retcode = file_move(NSSWITCH_BACK, NSSWITCH_CONF);
28080Sstevel@tonic-gate 		if (mode_verbose)
28090Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
28106842Sth160488 			    gettext("recover: file_move(%s, %s)=%d\n"),
28116842Sth160488 			    NSSWITCH_BACK, NSSWITCH_CONF, retcode);
28120Sstevel@tonic-gate 		if (retcode != 0)
28130Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
28146842Sth160488 			    gettext("recover: file_move(%s, %s) failed\n"),
28156842Sth160488 			    NSSWITCH_BACK, NSSWITCH_CONF);
28160Sstevel@tonic-gate 	}
28170Sstevel@tonic-gate 
28180Sstevel@tonic-gate 	stat_ret = stat(DOMAINNAME_BACK, &buf);
28190Sstevel@tonic-gate 	if (mode_verbose)
28200Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
28216842Sth160488 		    gettext("recover: stat(%s)=%d\n"),
28226842Sth160488 		    DOMAINNAME_BACK, stat_ret);
28230Sstevel@tonic-gate 	if (stat_ret == 0) {
28240Sstevel@tonic-gate 		retcode = file_move(DOMAINNAME_BACK, DOMAINNAME);
28250Sstevel@tonic-gate 		if (mode_verbose)
28260Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
28276842Sth160488 			    gettext("recover: file_move(%s, %s)=%d\n"),
28286842Sth160488 			    DOMAINNAME_BACK, DOMAINNAME, retcode);
28290Sstevel@tonic-gate 		if (retcode != 0)
28300Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
28316842Sth160488 			    gettext("recover: file_move(%s, %s) failed\n"),
28326842Sth160488 			    DOMAINNAME_BACK, DOMAINNAME);
28330Sstevel@tonic-gate 	}
28340Sstevel@tonic-gate 
28350Sstevel@tonic-gate 	retcode = rmdir(LDAP_RESTORE_DIR);
28360Sstevel@tonic-gate 	if (retcode != 0) {
28370Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
28386842Sth160488 		    gettext("Error removing \"%s\" directory.\n"),
28396842Sth160488 		    LDAP_RESTORE_DIR);
28400Sstevel@tonic-gate 	}
28410Sstevel@tonic-gate 
28420Sstevel@tonic-gate 	return (CLIENT_SUCCESS);
28430Sstevel@tonic-gate }
28440Sstevel@tonic-gate 
28450Sstevel@tonic-gate /*
28460Sstevel@tonic-gate  * try to save the current state of this machine.
28470Sstevel@tonic-gate  * this just overwrites any old saved configration files.
28480Sstevel@tonic-gate  *
28490Sstevel@tonic-gate  * This function should only be called after network services have been stopped.
28500Sstevel@tonic-gate  *
28510Sstevel@tonic-gate  * Returns 0 on successful save
28520Sstevel@tonic-gate  * Otherwise returns -1
28530Sstevel@tonic-gate  */
28540Sstevel@tonic-gate static int
28550Sstevel@tonic-gate file_backup(void)
28560Sstevel@tonic-gate {
28570Sstevel@tonic-gate 	struct stat buf;
28580Sstevel@tonic-gate 	int domain_stat, conf_stat, ldap_stat;
28590Sstevel@tonic-gate 	int nis_stat, yp_stat, restore_stat;
28600Sstevel@tonic-gate 	int retcode, namelen, ret;
28610Sstevel@tonic-gate 	char yp_dir[BUFSIZ], yp_dir_back[BUFSIZ];
28620Sstevel@tonic-gate 	char name[BUFSIZ];
28630Sstevel@tonic-gate 	char *ldap_conf_file, *ldap_cred_file;
28640Sstevel@tonic-gate 	char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
28650Sstevel@tonic-gate 
28660Sstevel@tonic-gate 	ret = CLIENT_SUCCESS;
28670Sstevel@tonic-gate 	/* If running as Sysid Install become a no-op */
28680Sstevel@tonic-gate 	if (sysid_install == B_TRUE)
28690Sstevel@tonic-gate 		return (CLIENT_SUCCESS);
28700Sstevel@tonic-gate 
28710Sstevel@tonic-gate 	/* If existing backup files, clear for this run */
28720Sstevel@tonic-gate 	restore_stat = stat(LDAP_RESTORE_DIR, &buf);
28730Sstevel@tonic-gate 	if (restore_stat == 0) {
28740Sstevel@tonic-gate 		if (mode_verbose) {
28750Sstevel@tonic-gate 			CLIENT_FPUTS(
28766842Sth160488 			    gettext("Removing existing restore "
28776842Sth160488 			    "directory\n"),
28786842Sth160488 			    stderr);
28790Sstevel@tonic-gate 		}
28800Sstevel@tonic-gate 		(void) system("/bin/rm -fr " LDAP_RESTORE_DIR);
28810Sstevel@tonic-gate 		restore_stat = stat(LDAP_RESTORE_DIR, &buf);
28820Sstevel@tonic-gate 		if (restore_stat == 0) {
28830Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
28846842Sth160488 			    gettext("Unable to remove backup "
28856842Sth160488 			    "directory (%s)\n"),
28866842Sth160488 			    LDAP_RESTORE_DIR);
28870Sstevel@tonic-gate 			return (CLIENT_ERR_RESTORE);
28880Sstevel@tonic-gate 		}
28890Sstevel@tonic-gate 	}
28900Sstevel@tonic-gate 
28910Sstevel@tonic-gate 	retcode = mkdir(LDAP_RESTORE_DIR, 0755);
28920Sstevel@tonic-gate 	if (retcode != 0) {
28930Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
28946842Sth160488 		    gettext("file_backup: Failed to make %s backup "
28956842Sth160488 		    "directory. mkdir=%d\n"),
28966842Sth160488 		    LDAP_RESTORE_DIR, retcode);
28970Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
28980Sstevel@tonic-gate 	}
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate 	conf_stat = stat(NSSWITCH_CONF, &buf);
29010Sstevel@tonic-gate 	if (mode_verbose)
29020Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
29036842Sth160488 		    gettext("file_backup: stat(%s)=%d\n"),
29046842Sth160488 		    NSSWITCH_CONF, conf_stat);
29050Sstevel@tonic-gate 	if (conf_stat == 0) {
29060Sstevel@tonic-gate 		if (mode_verbose)
29070Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29086842Sth160488 			    gettext("file_backup: (%s -> %s)\n"),
29096842Sth160488 			    NSSWITCH_CONF, NSSWITCH_BACK);
29100Sstevel@tonic-gate 		retcode = file_move(NSSWITCH_CONF, NSSWITCH_BACK);
29110Sstevel@tonic-gate 		if (retcode != 0) {
29120Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29136842Sth160488 			    gettext("file_backup: file_move(%s, %s) failed "
29146842Sth160488 			    "with %d\n"),
29156842Sth160488 			    NSSWITCH_CONF, NSSWITCH_BACK, retcode);
29160Sstevel@tonic-gate 			ret = CLIENT_ERR_RENAME;
29170Sstevel@tonic-gate 		}
29180Sstevel@tonic-gate 	} else {
29190Sstevel@tonic-gate 		if (mode_verbose)
29200Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29216842Sth160488 			    gettext("file_backup: No %s file.\n"),
29226842Sth160488 			    NSSWITCH_CONF);
29230Sstevel@tonic-gate 	}
29240Sstevel@tonic-gate 
29250Sstevel@tonic-gate 	domain_stat = stat(DOMAINNAME, &buf);
29260Sstevel@tonic-gate 	if (mode_verbose)
29270Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
29286842Sth160488 		    gettext("file_backup: stat(%s)=%d\n"),
29296842Sth160488 		    DOMAINNAME, domain_stat);
29300Sstevel@tonic-gate 	if ((domain_stat == 0) && (buf.st_size > 0)) {
29310Sstevel@tonic-gate 		if (mode_verbose)
29320Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29336842Sth160488 			    gettext("file_backup: (%s -> %s)\n"),
29346842Sth160488 			    DOMAINNAME, DOMAINNAME_BACK);
29350Sstevel@tonic-gate 		retcode = file_move(DOMAINNAME, DOMAINNAME_BACK);
29360Sstevel@tonic-gate 		if (retcode != 0) {
29370Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29386842Sth160488 			    gettext("file_backup: file_move(%s, %s) failed "
29396842Sth160488 			    "with %d\n"),
29406842Sth160488 			    DOMAINNAME, DOMAINNAME_BACK, retcode);
29410Sstevel@tonic-gate 			ret = CLIENT_ERR_RENAME;
29420Sstevel@tonic-gate 		}
29430Sstevel@tonic-gate 	} else {
29440Sstevel@tonic-gate 		if (mode_verbose)
29450Sstevel@tonic-gate 			if (domain_stat != 0) {
29460Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
29476842Sth160488 				    gettext("file_backup: No %s file.\n"),
29486842Sth160488 				    DOMAINNAME);
29490Sstevel@tonic-gate 			} else {
29500Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
29516842Sth160488 				    gettext("file_backup: Empty %s "
29526842Sth160488 				    "file.\n"),
29536842Sth160488 				    DOMAINNAME);
29540Sstevel@tonic-gate 			}
29550Sstevel@tonic-gate 	}
29560Sstevel@tonic-gate 
29570Sstevel@tonic-gate 	nis_stat = stat(NIS_COLDSTART, &buf);
29580Sstevel@tonic-gate 	if (mode_verbose)
29590Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
29606842Sth160488 		    gettext("file_backup: stat(%s)=%d\n"),
29616842Sth160488 		    NIS_COLDSTART, nis_stat);
29620Sstevel@tonic-gate 	if (nis_stat == 0) {
29630Sstevel@tonic-gate 		if (mode_verbose)
29640Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29656842Sth160488 			    gettext("file_backup: (%s -> %s)\n"),
29666842Sth160488 			    NIS_COLDSTART, NIS_COLDSTART_BACK);
29670Sstevel@tonic-gate 		retcode = file_move(NIS_COLDSTART, NIS_COLDSTART_BACK);
29680Sstevel@tonic-gate 		if (retcode != 0) {
29690Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29706842Sth160488 			    gettext("file_backup: file_move(%s, %s) failed "
29716842Sth160488 			    "with %d\n"),
29726842Sth160488 			    NIS_COLDSTART, NIS_COLDSTART_BACK, retcode);
29730Sstevel@tonic-gate 			ret = CLIENT_ERR_RENAME;
29740Sstevel@tonic-gate 		}
29750Sstevel@tonic-gate 	} else {
29760Sstevel@tonic-gate 		if (mode_verbose)
29770Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29786842Sth160488 			    gettext("file_backup: No %s file.\n"),
29796842Sth160488 			    NIS_COLDSTART);
29800Sstevel@tonic-gate 	}
29810Sstevel@tonic-gate 
29820Sstevel@tonic-gate 	namelen = BUFSIZ;
29830Sstevel@tonic-gate 	(void) sysinfo(SI_SRPC_DOMAIN, &(name[0]), namelen);
29840Sstevel@tonic-gate 	namelen = strlen(name);
29850Sstevel@tonic-gate 
29860Sstevel@tonic-gate 	if (mode_verbose)
29870Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
29886842Sth160488 		    gettext("file_backup: nis domain is \"%s\"\n"),
29896842Sth160488 		    (namelen > 0) ? name : "EMPTY");
29900Sstevel@tonic-gate 	/* check for domain name if not set cannot save NIS(YP) state */
29910Sstevel@tonic-gate 	if (namelen > 0) {
29920Sstevel@tonic-gate 		/* moving /var/yp/binding will cause ypbind to core dump */
29930Sstevel@tonic-gate 		(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
29940Sstevel@tonic-gate 		(void) strlcat(yp_dir, name, BUFSIZE);
29950Sstevel@tonic-gate 		yp_stat = stat(yp_dir, &buf);
29960Sstevel@tonic-gate 		if (mode_verbose)
29970Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
29986842Sth160488 			    gettext("file_backup: stat(%s)=%d\n"),
29996842Sth160488 			    yp_dir, yp_stat);
30000Sstevel@tonic-gate 		if (yp_stat == 0) {
30010Sstevel@tonic-gate 			(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/",
30026842Sth160488 			    BUFSIZE);
30030Sstevel@tonic-gate 			(void) strlcat(yp_dir_back, name, BUFSIZE);
30040Sstevel@tonic-gate 			if (mode_verbose)
30050Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
30066842Sth160488 				    gettext("file_backup: (%s -> %s)\n"),
30076842Sth160488 				    yp_dir, yp_dir_back);
30080Sstevel@tonic-gate 			retcode = file_move(yp_dir, yp_dir_back);
30090Sstevel@tonic-gate 			if (retcode != 0) {
30100Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
30116842Sth160488 				    gettext("file_backup: file_move(%s, %s)"
30126842Sth160488 				    " failed with %d\n"),
30136842Sth160488 				    yp_dir, yp_dir_back, retcode);
30140Sstevel@tonic-gate 				ret = CLIENT_ERR_RENAME;
30150Sstevel@tonic-gate 			}
30160Sstevel@tonic-gate 		} else {
30170Sstevel@tonic-gate 			if (mode_verbose)
30180Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
30196842Sth160488 				    gettext("file_backup: No %s "
30206842Sth160488 				    "directory.\n"), yp_dir);
30210Sstevel@tonic-gate 		}
30220Sstevel@tonic-gate 	}
30230Sstevel@tonic-gate 
30240Sstevel@tonic-gate 
30250Sstevel@tonic-gate 	/* point to file name, not path delim (/) */
30260Sstevel@tonic-gate 	ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
30270Sstevel@tonic-gate 	ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
30280Sstevel@tonic-gate 
30290Sstevel@tonic-gate 	ldap_stat = stat(NSCONFIGFILE, &buf);
30300Sstevel@tonic-gate 	if (mode_verbose)
30310Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
30326842Sth160488 		    gettext("file_backup: stat(%s)=%d\n"),
30336842Sth160488 		    NSCONFIGFILE, ldap_stat);
30340Sstevel@tonic-gate 	if (ldap_stat == 0) {
30350Sstevel@tonic-gate 		(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
30360Sstevel@tonic-gate 		(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
30370Sstevel@tonic-gate 		if (mode_verbose)
30380Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
30396842Sth160488 			    gettext("file_backup: (%s -> %s)\n"),
30406842Sth160488 			    NSCONFIGFILE, ldap_file_back);
30410Sstevel@tonic-gate 		retcode = file_move(NSCONFIGFILE, ldap_file_back);
30420Sstevel@tonic-gate 		if (retcode != 0) {
30430Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
30446842Sth160488 			    gettext("file_backup: file_move(%s, %s) failed "
30456842Sth160488 			    "with %d\n"),
30466842Sth160488 			    NSCONFIGFILE, ldap_file_back, retcode);
30470Sstevel@tonic-gate 			ret = CLIENT_ERR_RENAME;
30480Sstevel@tonic-gate 		}
30490Sstevel@tonic-gate 
30500Sstevel@tonic-gate 		(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
30510Sstevel@tonic-gate 		(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
30520Sstevel@tonic-gate 		if (mode_verbose)
30530Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
30546842Sth160488 			    gettext("file_backup: (%s -> %s)\n"),
30556842Sth160488 			    NSCREDFILE, ldap_cred_back);
30560Sstevel@tonic-gate 		retcode = file_move(NSCREDFILE, ldap_cred_back);
30570Sstevel@tonic-gate 		if (retcode != 0) {
30580Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
30596842Sth160488 			    gettext("file_backup: file_move(%s, %s) failed "
30606842Sth160488 			    "with %d\n"),
30616842Sth160488 			    NSCREDFILE, ldap_cred_back, retcode);
30620Sstevel@tonic-gate 			ret = CLIENT_ERR_RENAME;
30630Sstevel@tonic-gate 		}
30640Sstevel@tonic-gate 	} else {
30650Sstevel@tonic-gate 		if (mode_verbose)
30660Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
30676842Sth160488 			    gettext("file_backup: No %s file.\n"),
30686842Sth160488 			    NSCONFIGFILE);
30690Sstevel@tonic-gate 	}
30700Sstevel@tonic-gate 
30710Sstevel@tonic-gate 	return (ret);
30720Sstevel@tonic-gate }
30730Sstevel@tonic-gate 
30740Sstevel@tonic-gate /*
30750Sstevel@tonic-gate  * mod_backup()
30760Sstevel@tonic-gate  *
30770Sstevel@tonic-gate  * This function is used to temporily backup the LDAP client files in /var/ldap
30780Sstevel@tonic-gate  * that the "mod" operation needs to update.  If an error occurs then the
30790Sstevel@tonic-gate  * function mod_recover() can be invoke to recover the unmodified files.
30800Sstevel@tonic-gate  */
30810Sstevel@tonic-gate static int
30820Sstevel@tonic-gate mod_backup(void)
30830Sstevel@tonic-gate {
30840Sstevel@tonic-gate 	int rc;
30850Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
30860Sstevel@tonic-gate 
30870Sstevel@tonic-gate 	rc = system(CMD_CP " " NSCONFIGFILE " " NSCONFIGFILE ".mod");
30880Sstevel@tonic-gate 	retcode += rc;
30890Sstevel@tonic-gate 	if (mode_verbose)
30900Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
30910Sstevel@tonic-gate 		    gettext("mod_backup: backup %s for %s\n"),
30920Sstevel@tonic-gate 		    rc ? "failed" : "successful", NSCONFIGFILE);
30930Sstevel@tonic-gate 
30940Sstevel@tonic-gate 	rc = system(CMD_CP " " NSCREDFILE " " NSCREDFILE ".mod");
30950Sstevel@tonic-gate 	retcode += rc;
30960Sstevel@tonic-gate 	if (mode_verbose)
30970Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
30980Sstevel@tonic-gate 		    gettext("mod_backup: backup %s for %s\n"),
30990Sstevel@tonic-gate 		    rc ? "failed" : "successful", NSCREDFILE);
31000Sstevel@tonic-gate 
31010Sstevel@tonic-gate 	rc = system(CMD_CP " " DOMAINNAME " " DOMAINNAME ".mod");
31020Sstevel@tonic-gate 	retcode += rc;
31030Sstevel@tonic-gate 	if (mode_verbose)
31040Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
31050Sstevel@tonic-gate 		    gettext("mod_backup: backup %s for %s\n"),
31060Sstevel@tonic-gate 		    rc ? "failed" : "successful", DOMAINNAME);
31070Sstevel@tonic-gate 
31080Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS)
31090Sstevel@tonic-gate 		retcode = CLIENT_ERR_RENAME;
31100Sstevel@tonic-gate 	return (retcode);
31110Sstevel@tonic-gate }
31120Sstevel@tonic-gate 
31130Sstevel@tonic-gate /*
31140Sstevel@tonic-gate  * mod_recover()
31150Sstevel@tonic-gate  *
31160Sstevel@tonic-gate  * This function is used to recover the temporily backed up files by
31170Sstevel@tonic-gate  * the mod_backup() function if an error occurs during the "mod"
31180Sstevel@tonic-gate  * operation.
31190Sstevel@tonic-gate  */
31200Sstevel@tonic-gate static int
31210Sstevel@tonic-gate mod_recover(void)
31220Sstevel@tonic-gate {
31230Sstevel@tonic-gate 	int rc;
31240Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
31250Sstevel@tonic-gate 
31260Sstevel@tonic-gate 	rc = system(CMD_MV " " NSCONFIGFILE ".mod " NSCONFIGFILE);
31270Sstevel@tonic-gate 	retcode += rc;
31280Sstevel@tonic-gate 	if (mode_verbose)
31290Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
31300Sstevel@tonic-gate 		    gettext("mod_recover: recovery %s for %s\n"),
31310Sstevel@tonic-gate 		    rc ? "failed" : "successful", NSCONFIGFILE);
31320Sstevel@tonic-gate 
31330Sstevel@tonic-gate 	rc = system(CMD_MV " " NSCREDFILE ".mod " NSCREDFILE);
31340Sstevel@tonic-gate 	retcode += rc;
31350Sstevel@tonic-gate 	if (mode_verbose)
31360Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
31370Sstevel@tonic-gate 		    gettext("mod_recover: recovery %s for %s\n"),
31380Sstevel@tonic-gate 		    rc ? "failed" : "successful", NSCREDFILE);
31390Sstevel@tonic-gate 
31400Sstevel@tonic-gate 	rc = system(CMD_MV " " DOMAINNAME ".mod " DOMAINNAME);
31410Sstevel@tonic-gate 	retcode += rc;
31420Sstevel@tonic-gate 	if (mode_verbose)
31430Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
31440Sstevel@tonic-gate 		    gettext("mod_recover: recovery %s for %s\n"),
31450Sstevel@tonic-gate 		    rc ? "failed" : "successful", DOMAINNAME);
31460Sstevel@tonic-gate 
31470Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS)
31480Sstevel@tonic-gate 		retcode = CLIENT_ERR_RENAME;
31490Sstevel@tonic-gate 	return (retcode);
31500Sstevel@tonic-gate }
31510Sstevel@tonic-gate 
31520Sstevel@tonic-gate /*
31530Sstevel@tonic-gate  * mod_cleanup()
31540Sstevel@tonic-gate  *
31550Sstevel@tonic-gate  * This function removes the .mod files in /var/ldap.
31560Sstevel@tonic-gate  */
31570Sstevel@tonic-gate static void
31580Sstevel@tonic-gate mod_cleanup(void)
31590Sstevel@tonic-gate {
31600Sstevel@tonic-gate 	(void) system(CMD_RM " " NSCONFIGFILE ".mod " TO_DEV_NULL);
31610Sstevel@tonic-gate 	(void) system(CMD_RM " " NSCREDFILE ".mod " TO_DEV_NULL);
31620Sstevel@tonic-gate 	(void) system(CMD_RM " " DOMAINNAME ".mod " TO_DEV_NULL);
31630Sstevel@tonic-gate }
31640Sstevel@tonic-gate 
31650Sstevel@tonic-gate #define	MAX_DN_ARRAY 100
31660Sstevel@tonic-gate #define	LDAP_NAMINGCONTEXTS	"namingcontexts"
31670Sstevel@tonic-gate 
31680Sstevel@tonic-gate static multival_t *
31690Sstevel@tonic-gate multival_new()
31700Sstevel@tonic-gate {
31710Sstevel@tonic-gate 	multival_t *hold;
31720Sstevel@tonic-gate 
31730Sstevel@tonic-gate 	hold = calloc(1, sizeof (multival_t));
31740Sstevel@tonic-gate 	if (hold == NULL) {
31750Sstevel@tonic-gate 		CLIENT_FPUTS(
31766842Sth160488 		    gettext("multival_new: Memory allocation error\n"),
31776842Sth160488 		    stderr);
31780Sstevel@tonic-gate 	}
31790Sstevel@tonic-gate 	return (hold);	/* NULL -> error */
31800Sstevel@tonic-gate }
31810Sstevel@tonic-gate 
31820Sstevel@tonic-gate static int
31830Sstevel@tonic-gate multival_add(multival_t *list, char *opt)
31840Sstevel@tonic-gate {
31850Sstevel@tonic-gate 	if (opt == NULL) {
31860Sstevel@tonic-gate 		CLIENT_FPUTS(
31876842Sth160488 		    gettext("Empty value passed to multival_add\n"),
31886842Sth160488 		    stderr);
31890Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
31900Sstevel@tonic-gate 	}
31910Sstevel@tonic-gate 
31920Sstevel@tonic-gate 	if (list->count == 0) {
31930Sstevel@tonic-gate 		list->optlist = (char **)malloc(sizeof (char **));
31940Sstevel@tonic-gate 	} else {
31950Sstevel@tonic-gate 		list->optlist = (char **)realloc(list->optlist,
31966842Sth160488 		    (list->count + 1) * sizeof (char **));
31970Sstevel@tonic-gate 	}
31980Sstevel@tonic-gate 
31990Sstevel@tonic-gate 	if (list->optlist == NULL) {
32000Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory\n"), stderr);
32010Sstevel@tonic-gate 		return (CLIENT_ERR_MEMORY);	/* 0 is success */
32020Sstevel@tonic-gate 	}
32030Sstevel@tonic-gate 
32040Sstevel@tonic-gate 	list->optlist[list->count] = opt;
32050Sstevel@tonic-gate 	list->count++;
32060Sstevel@tonic-gate 
32070Sstevel@tonic-gate 	return (CLIENT_SUCCESS);
32080Sstevel@tonic-gate }
32090Sstevel@tonic-gate 
32100Sstevel@tonic-gate static void
32110Sstevel@tonic-gate multival_free(multival_t *list)
32120Sstevel@tonic-gate {
32130Sstevel@tonic-gate 	if (list == NULL)
32140Sstevel@tonic-gate 		return;
32150Sstevel@tonic-gate 
32160Sstevel@tonic-gate 	if (list->optlist != NULL)
32170Sstevel@tonic-gate 		free(list->optlist);
32180Sstevel@tonic-gate 	free(list);
32190Sstevel@tonic-gate }
32200Sstevel@tonic-gate 
32210Sstevel@tonic-gate static clientopts_t *
32220Sstevel@tonic-gate clientopts_new()
32230Sstevel@tonic-gate {
32240Sstevel@tonic-gate 	clientopts_t *hold;
32250Sstevel@tonic-gate 
32260Sstevel@tonic-gate 	hold = calloc(1, sizeof (clientopts_t));
32270Sstevel@tonic-gate 	if (NULL == hold) {
32280Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32296842Sth160488 		    "clientopts structure\n"), stderr);
32300Sstevel@tonic-gate 		return (hold);	/* NULL -> error */
32310Sstevel@tonic-gate 	}
32320Sstevel@tonic-gate 
32330Sstevel@tonic-gate 	hold->serviceAuthenticationMethod = multival_new();
32340Sstevel@tonic-gate 	if (NULL == hold->serviceAuthenticationMethod) {
32350Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32366842Sth160488 		    "serviceAuthenticationMethod\n"), stderr);
32370Sstevel@tonic-gate 		free(hold);
32380Sstevel@tonic-gate 		return (NULL);	/* NULL -> error */
32390Sstevel@tonic-gate 	}
32400Sstevel@tonic-gate 
32410Sstevel@tonic-gate 	hold->serviceCredentialLevel = multival_new();
32420Sstevel@tonic-gate 	if (NULL == hold->serviceCredentialLevel) {
32430Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32446842Sth160488 		    "serviceCredentialLevel\n"), stderr);
32450Sstevel@tonic-gate 		multival_free(hold->serviceAuthenticationMethod);
32460Sstevel@tonic-gate 		free(hold);
32470Sstevel@tonic-gate 		return (NULL);	/* NULL -> error */
32480Sstevel@tonic-gate 	}
32490Sstevel@tonic-gate 
32500Sstevel@tonic-gate 	hold->objectclassMap = multival_new();
32510Sstevel@tonic-gate 	if (NULL == hold->objectclassMap) {
32520Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32536842Sth160488 		    "objectclassMap\n"), stderr);
32540Sstevel@tonic-gate 		multival_free(hold->serviceAuthenticationMethod);
32550Sstevel@tonic-gate 		multival_free(hold->serviceCredentialLevel);
32560Sstevel@tonic-gate 		free(hold);
32570Sstevel@tonic-gate 		return (NULL);	/* NULL -> error */
32580Sstevel@tonic-gate 	}
32590Sstevel@tonic-gate 
32600Sstevel@tonic-gate 	hold->attributeMap = multival_new();
32610Sstevel@tonic-gate 	if (NULL == hold->attributeMap) {
32620Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32636842Sth160488 		    "attributeMap\n"), stderr);
32640Sstevel@tonic-gate 		multival_free(hold->serviceAuthenticationMethod);
32650Sstevel@tonic-gate 		multival_free(hold->serviceCredentialLevel);
32660Sstevel@tonic-gate 		multival_free(hold->objectclassMap);
32670Sstevel@tonic-gate 		free(hold);
32680Sstevel@tonic-gate 		return (NULL);	/* NULL -> error */
32690Sstevel@tonic-gate 	}
32700Sstevel@tonic-gate 
32710Sstevel@tonic-gate 	hold->serviceSearchDescriptor = multival_new();
32720Sstevel@tonic-gate 	if (NULL == hold->serviceSearchDescriptor) {
32730Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Error allocating memory for "
32746842Sth160488 		    "serviceSearchDescriptor\n"), stderr);
32750Sstevel@tonic-gate 		multival_free(hold->serviceAuthenticationMethod);
32760Sstevel@tonic-gate 		multival_free(hold->serviceCredentialLevel);
32770Sstevel@tonic-gate 		multival_free(hold->objectclassMap);
32780Sstevel@tonic-gate 		multival_free(hold->attributeMap);
32790Sstevel@tonic-gate 		free(hold);
32800Sstevel@tonic-gate 		return (NULL);	/* NULL -> error */
32810Sstevel@tonic-gate 	}
32820Sstevel@tonic-gate 
32830Sstevel@tonic-gate 	return (hold);
32840Sstevel@tonic-gate }
32850Sstevel@tonic-gate 
32860Sstevel@tonic-gate static void
32870Sstevel@tonic-gate clientopts_free(clientopts_t *list)
32880Sstevel@tonic-gate {
32890Sstevel@tonic-gate 	if (NULL == list)
32900Sstevel@tonic-gate 		return;
32910Sstevel@tonic-gate 
32920Sstevel@tonic-gate 	multival_free(list->serviceAuthenticationMethod);
32930Sstevel@tonic-gate 	multival_free(list->serviceCredentialLevel);
32940Sstevel@tonic-gate 	multival_free(list->objectclassMap);
32950Sstevel@tonic-gate 	multival_free(list->attributeMap);
32960Sstevel@tonic-gate 	multival_free(list->serviceSearchDescriptor);
32970Sstevel@tonic-gate 
32980Sstevel@tonic-gate 	free(list);
32990Sstevel@tonic-gate 
33000Sstevel@tonic-gate }
33010Sstevel@tonic-gate 
33020Sstevel@tonic-gate static void
33030Sstevel@tonic-gate multival_list(char *opt, multival_t *list)
33040Sstevel@tonic-gate {
33050Sstevel@tonic-gate 	int i;
33060Sstevel@tonic-gate 
33070Sstevel@tonic-gate 	if (list->count == 0)
33080Sstevel@tonic-gate 		return;
33090Sstevel@tonic-gate 
33100Sstevel@tonic-gate 	(void) puts(opt);
33110Sstevel@tonic-gate 	for (i = 0; i < list->count; i++) {
33120Sstevel@tonic-gate 		(void) printf("\t\targ[%d]: %s\n", i, list->optlist[i]);
33130Sstevel@tonic-gate 	}
33140Sstevel@tonic-gate }
33150Sstevel@tonic-gate 
33160Sstevel@tonic-gate /* return the number of arguments specified in the command line */
33170Sstevel@tonic-gate static int
33180Sstevel@tonic-gate num_args(clientopts_t *list)
33190Sstevel@tonic-gate {
33200Sstevel@tonic-gate 	int arg_count = 0;
33210Sstevel@tonic-gate 
33220Sstevel@tonic-gate 	arg_count += list->authenticationMethod ? 1 : 0;
33230Sstevel@tonic-gate 	arg_count += list->serviceAuthenticationMethod->count;
33240Sstevel@tonic-gate 	arg_count += list->defaultSearchBase ? 1 : 0;
33250Sstevel@tonic-gate 	arg_count += list->credentialLevel ? 1 : 0;
33260Sstevel@tonic-gate 	arg_count += list->serviceCredentialLevel->count;
33270Sstevel@tonic-gate 	arg_count += list->domainName ? 1 : 0;
33280Sstevel@tonic-gate 	arg_count += list->proxyDN ? 1 : 0;
3329*8821SMichen.Chang@Sun.COM 	arg_count += list->enableShadowUpdate ? 1 : 0;
3330*8821SMichen.Chang@Sun.COM 	arg_count += list->adminDN ? 1 : 0;
33310Sstevel@tonic-gate 	arg_count += list->profileTTL ? 1 : 0;
33320Sstevel@tonic-gate 	arg_count += list->objectclassMap->count;
33330Sstevel@tonic-gate 	arg_count += list->searchTimeLimit ? 1 : 0;
33340Sstevel@tonic-gate 	arg_count += list->preferredServerList ? 1 : 0;
33350Sstevel@tonic-gate 	arg_count += list->profileName ? 1 : 0;
33360Sstevel@tonic-gate 	arg_count += list->followReferrals ? 1 : 0;
33370Sstevel@tonic-gate 	arg_count += list->attributeMap->count;
33380Sstevel@tonic-gate 	arg_count += list->defaultSearchScope ? 1 : 0;
33390Sstevel@tonic-gate 	arg_count += list->serviceSearchDescriptor->count;
33400Sstevel@tonic-gate 	arg_count += list->bindTimeLimit ? 1 : 0;
33410Sstevel@tonic-gate 	arg_count += list->proxyPassword ? 1 : 0;
3342*8821SMichen.Chang@Sun.COM 	arg_count += list->adminPassword ? 1 : 0;
33430Sstevel@tonic-gate 	arg_count += list->defaultServerList ? 1 : 0;
33440Sstevel@tonic-gate 	arg_count += list->certificatePath ? 1 : 0;
33450Sstevel@tonic-gate 
33460Sstevel@tonic-gate 	return (arg_count);
33470Sstevel@tonic-gate }
33480Sstevel@tonic-gate 
33490Sstevel@tonic-gate #define	CLIENT_PRINT(opt, str) if (str) \
33500Sstevel@tonic-gate 		(void) printf("%s%s\n", (opt), (str))
33510Sstevel@tonic-gate 
33520Sstevel@tonic-gate static void
33530Sstevel@tonic-gate dumpargs(clientopts_t *list)
33540Sstevel@tonic-gate {
33550Sstevel@tonic-gate 	CLIENT_PRINT("\tauthenticationMethod: ", list->authenticationMethod);
33560Sstevel@tonic-gate 	multival_list("\tserviceAuthenticationMethod: ",
33576842Sth160488 	    list->serviceAuthenticationMethod);
33580Sstevel@tonic-gate 	CLIENT_PRINT("\tdefaultSearchBase: ", list->defaultSearchBase);
33590Sstevel@tonic-gate 	CLIENT_PRINT("\tcredentialLevel: ", list->credentialLevel);
33600Sstevel@tonic-gate 	multival_list("\tserviceCredentialLevel: ",
33616842Sth160488 	    list->serviceCredentialLevel);
33620Sstevel@tonic-gate 	CLIENT_PRINT("\tdomainName: ", list->domainName);
33630Sstevel@tonic-gate 	CLIENT_PRINT("\tproxyDN: ", list->proxyDN);
3364*8821SMichen.Chang@Sun.COM 	CLIENT_PRINT("\tadminDN: ", list->adminDN);
3365*8821SMichen.Chang@Sun.COM 	CLIENT_PRINT("\tenableShadowUpdate: ", list->enableShadowUpdate);
33660Sstevel@tonic-gate 	CLIENT_PRINT("\tprofileTTL: ", list->profileTTL);
33670Sstevel@tonic-gate 	multival_list("\tobjectclassMap: ", list->objectclassMap);
33680Sstevel@tonic-gate 	CLIENT_PRINT("\tsearchTimeLimit: ", list->searchTimeLimit);
33690Sstevel@tonic-gate 	CLIENT_PRINT("\tpreferredServerList: ", list->preferredServerList);
33700Sstevel@tonic-gate 	CLIENT_PRINT("\tprofileName: ", list->profileName);
33710Sstevel@tonic-gate 	CLIENT_PRINT("\tfollowReferrals: ", list->followReferrals);
33720Sstevel@tonic-gate 	multival_list("\tattributeMap: ", list->attributeMap);
33730Sstevel@tonic-gate 	CLIENT_PRINT("\tdefaultSearchScope: ", list->defaultSearchScope);
33740Sstevel@tonic-gate 	multival_list("\tserviceSearchDescriptor: ",
33756842Sth160488 	    list->serviceSearchDescriptor);
33760Sstevel@tonic-gate 	CLIENT_PRINT("\tbindTimeLimit: ", list->bindTimeLimit);
33770Sstevel@tonic-gate 	CLIENT_PRINT("\tproxyPassword: ", list->proxyPassword);
3378*8821SMichen.Chang@Sun.COM 	CLIENT_PRINT("\tadminPassword: ", list->adminPassword);
33790Sstevel@tonic-gate 	CLIENT_PRINT("\tdefaultServerList: ", list->defaultServerList);
33800Sstevel@tonic-gate 	CLIENT_PRINT("\tcertificatePath: ", list->certificatePath);
33810Sstevel@tonic-gate }
33820Sstevel@tonic-gate 
33830Sstevel@tonic-gate 
33840Sstevel@tonic-gate /* These definitions are only used in parseParam() below. */
33850Sstevel@tonic-gate struct param {
33860Sstevel@tonic-gate 	char	*name;
33870Sstevel@tonic-gate 	int	index;
33880Sstevel@tonic-gate };
33890Sstevel@tonic-gate 
33900Sstevel@tonic-gate static struct param paramArray[] = {
33910Sstevel@tonic-gate 	{"proxyDN", NS_LDAP_BINDDN_P},
33920Sstevel@tonic-gate 	{"proxyPassword", NS_LDAP_BINDPASSWD_P},
33930Sstevel@tonic-gate 	{"defaultServerList", NS_LDAP_SERVERS_P},
33940Sstevel@tonic-gate 	{"defaultSearchBase", NS_LDAP_SEARCH_BASEDN_P},
33950Sstevel@tonic-gate 	{"authenticationMethod", NS_LDAP_AUTH_P},
33960Sstevel@tonic-gate 	{"followReferrals", NS_LDAP_SEARCH_REF_P},
33970Sstevel@tonic-gate 	{"profileTTL", NS_LDAP_CACHETTL_P},
33980Sstevel@tonic-gate 	{"certificatePath", NS_LDAP_HOST_CERTPATH_P},
33990Sstevel@tonic-gate 	{"defaultSearchScope", NS_LDAP_SEARCH_SCOPE_P},
34000Sstevel@tonic-gate 	{"bindTimeLimit", NS_LDAP_BIND_TIME_P},
34010Sstevel@tonic-gate 	{"searchTimeLimit", NS_LDAP_SEARCH_TIME_P},
34020Sstevel@tonic-gate 	{"preferredServerList", NS_LDAP_SERVER_PREF_P},
34030Sstevel@tonic-gate 	{"profileName", NS_LDAP_PROFILE_P},
34040Sstevel@tonic-gate 	{"credentialLevel", NS_LDAP_CREDENTIAL_LEVEL_P},
34050Sstevel@tonic-gate 	{"serviceSearchDescriptor", NS_LDAP_SERVICE_SEARCH_DESC_P},
34060Sstevel@tonic-gate 	{"attributeMap", NS_LDAP_ATTRIBUTEMAP_P},
34070Sstevel@tonic-gate 	{"objectclassMap", NS_LDAP_OBJECTCLASSMAP_P},
34080Sstevel@tonic-gate 	{"serviceAuthenticationMethod", NS_LDAP_SERVICE_AUTH_METHOD_P},
34090Sstevel@tonic-gate 	{"serviceCredentialLevel", NS_LDAP_SERVICE_CRED_LEVEL_P},
34100Sstevel@tonic-gate 	{"domainName", LOCAL_DOMAIN_P},
3411*8821SMichen.Chang@Sun.COM 	{"enableShadowUpdate", NS_LDAP_ENABLE_SHADOW_UPDATE_P},
3412*8821SMichen.Chang@Sun.COM 	{"adminDN", NS_LDAP_ADMIN_BINDDN_P},
3413*8821SMichen.Chang@Sun.COM 	{"adminPassword", NS_LDAP_ADMIN_BINDPASSWD_P},
34140Sstevel@tonic-gate 	{NULL, 0}
34150Sstevel@tonic-gate };
34160Sstevel@tonic-gate 
34170Sstevel@tonic-gate static int
34180Sstevel@tonic-gate parseParam(char *param, char **paramVal)
34190Sstevel@tonic-gate {
34200Sstevel@tonic-gate 	char *val = NULL;
34210Sstevel@tonic-gate 	int counter;
34220Sstevel@tonic-gate 
34230Sstevel@tonic-gate 	if (mode_verbose) {
34240Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr, gettext("Parsing %s\n"), param);
34250Sstevel@tonic-gate 	}
34260Sstevel@tonic-gate 
34270Sstevel@tonic-gate 	val = strchr(param, '=');
34280Sstevel@tonic-gate 	if (val == NULL) {
34290Sstevel@tonic-gate 		CLIENT_FPUTS(
34306842Sth160488 		    gettext("Didn\'t find \'=\' character in string\n"),
34316842Sth160488 		    stderr);
34320Sstevel@tonic-gate 		paramVal = NULL;
34330Sstevel@tonic-gate 		return (CLIENT_ERR_PARSE);
34340Sstevel@tonic-gate 	}
34350Sstevel@tonic-gate 
34360Sstevel@tonic-gate 	*val = '\0';
34370Sstevel@tonic-gate 
34380Sstevel@tonic-gate 	for (counter = 0; paramArray[counter].name != NULL; counter++) {
34390Sstevel@tonic-gate 		if (strcasecmp(paramArray[counter].name, param) == 0) {
34400Sstevel@tonic-gate 			*paramVal = val+1;
34410Sstevel@tonic-gate 			*val = '=';	/* restore original param */
34420Sstevel@tonic-gate 			return (paramArray[counter].index);
34430Sstevel@tonic-gate 		}
34440Sstevel@tonic-gate 	}
34450Sstevel@tonic-gate 
34460Sstevel@tonic-gate 	/* Not found */
34470Sstevel@tonic-gate 	*val = '=';	/* restore original param */
34480Sstevel@tonic-gate 	*paramVal = NULL;
34490Sstevel@tonic-gate 	return (CLIENT_ERR_PARSE);
34500Sstevel@tonic-gate }
34510Sstevel@tonic-gate 
34520Sstevel@tonic-gate /*
34530Sstevel@tonic-gate  * The following macro checks if an option has already been specified
34540Sstevel@tonic-gate  * and errs out with usage if so
34550Sstevel@tonic-gate  */
34560Sstevel@tonic-gate #define	CLIENT_OPT_CHECK(opt, optarg)	\
34570Sstevel@tonic-gate if (optarg) {			\
34580Sstevel@tonic-gate 	CLIENT_FPUTS(gettext("Invalid use of option\n"), stderr);	\
34590Sstevel@tonic-gate 	usage();		\
34600Sstevel@tonic-gate 	clientopts_free(optlist); \
34610Sstevel@tonic-gate 	return (CLIENT_ERR_FAIL);		\
34620Sstevel@tonic-gate }
34630Sstevel@tonic-gate 
34640Sstevel@tonic-gate static int
34650Sstevel@tonic-gate clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal)
34660Sstevel@tonic-gate {
34670Sstevel@tonic-gate 	int retcode = 0;
34680Sstevel@tonic-gate 	int counter;
34690Sstevel@tonic-gate 
34700Sstevel@tonic-gate 
34710Sstevel@tonic-gate 	switch (paramFlag) {
34720Sstevel@tonic-gate 	case NS_LDAP_AUTH_P:
34730Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->authenticationMethod);
34740Sstevel@tonic-gate 		optlist->authenticationMethod = attrVal;
34750Sstevel@tonic-gate 		break;
34760Sstevel@tonic-gate 
34770Sstevel@tonic-gate 	case NS_LDAP_SERVICE_AUTH_METHOD_P:	/* multiple allowed */
34780Sstevel@tonic-gate 		retcode = multival_add(optlist->serviceAuthenticationMethod,
34796842Sth160488 		    attrVal);
34800Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
34810Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
34826842Sth160488 			    gettext("Error processing attrVal %s\n"),
34836842Sth160488 			    attrVal?attrVal:"NULL");
34840Sstevel@tonic-gate 			usage();
34850Sstevel@tonic-gate 			clientopts_free(optlist);
34860Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
34870Sstevel@tonic-gate 		}
34880Sstevel@tonic-gate 		break;
34890Sstevel@tonic-gate 
34900Sstevel@tonic-gate 	case NS_LDAP_SEARCH_BASEDN_P:
34910Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchBase);
34920Sstevel@tonic-gate 		optlist->defaultSearchBase = attrVal;
34930Sstevel@tonic-gate 		break;
34940Sstevel@tonic-gate 
34950Sstevel@tonic-gate 	case NS_LDAP_CREDENTIAL_LEVEL_P:
34960Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->credentialLevel);
34970Sstevel@tonic-gate 		optlist->credentialLevel = attrVal;
34980Sstevel@tonic-gate 		break;
34990Sstevel@tonic-gate 
35000Sstevel@tonic-gate 	case NS_LDAP_SERVICE_CRED_LEVEL_P:	/* multiple allowed */
35010Sstevel@tonic-gate 		retcode = multival_add(optlist->serviceCredentialLevel,
35026842Sth160488 		    attrVal);
35030Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
35040Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
35056842Sth160488 			    gettext("Error processing attrVal %s\n"),
35066842Sth160488 			    attrVal?attrVal:"NULL");
35070Sstevel@tonic-gate 			usage();
35080Sstevel@tonic-gate 			clientopts_free(optlist);
35090Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
35100Sstevel@tonic-gate 		}
35110Sstevel@tonic-gate 		break;
35120Sstevel@tonic-gate 
35130Sstevel@tonic-gate 	case LOCAL_DOMAIN_P:
35140Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->domainName);
35150Sstevel@tonic-gate 		optlist->domainName = attrVal;
35160Sstevel@tonic-gate 		dname = optlist->domainName;
35170Sstevel@tonic-gate 		break;
35180Sstevel@tonic-gate 
35190Sstevel@tonic-gate 	case NS_LDAP_BINDDN_P:
35200Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->proxyDN);
35210Sstevel@tonic-gate 		optlist->proxyDN = attrVal;
35220Sstevel@tonic-gate 		break;
35230Sstevel@tonic-gate 
3524*8821SMichen.Chang@Sun.COM 	case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
3525*8821SMichen.Chang@Sun.COM 		CLIENT_OPT_CHECK(paramFlag, optlist->enableShadowUpdate);
3526*8821SMichen.Chang@Sun.COM 		optlist->enableShadowUpdate = attrVal;
3527*8821SMichen.Chang@Sun.COM 		break;
3528*8821SMichen.Chang@Sun.COM 
3529*8821SMichen.Chang@Sun.COM 	case NS_LDAP_ADMIN_BINDDN_P:
3530*8821SMichen.Chang@Sun.COM 		CLIENT_OPT_CHECK(paramFlag, optlist->adminDN);
3531*8821SMichen.Chang@Sun.COM 		optlist->adminDN = attrVal;
3532*8821SMichen.Chang@Sun.COM 		break;
3533*8821SMichen.Chang@Sun.COM 
35340Sstevel@tonic-gate 	case NS_LDAP_CACHETTL_P:
35350Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->profileTTL);
35360Sstevel@tonic-gate 		optlist->profileTTL = attrVal;
35370Sstevel@tonic-gate 		break;
35380Sstevel@tonic-gate 
35390Sstevel@tonic-gate 	case NS_LDAP_OBJECTCLASSMAP_P:	/* multiple allowed */
35400Sstevel@tonic-gate 		retcode = multival_add(optlist->objectclassMap, attrVal);
35410Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
35420Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
35436842Sth160488 			    gettext("Error processing attrVal %s\n"),
35446842Sth160488 			    attrVal?attrVal:"NULL");
35450Sstevel@tonic-gate 			usage();
35460Sstevel@tonic-gate 			clientopts_free(optlist);
35470Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
35480Sstevel@tonic-gate 		}
35490Sstevel@tonic-gate 		break;
35500Sstevel@tonic-gate 
35510Sstevel@tonic-gate 	case NS_LDAP_SEARCH_TIME_P:
35520Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->searchTimeLimit);
35530Sstevel@tonic-gate 		optlist->searchTimeLimit = attrVal;
35540Sstevel@tonic-gate 		break;
35550Sstevel@tonic-gate 
35560Sstevel@tonic-gate 	case NS_LDAP_SERVER_PREF_P:
35570Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->preferredServerList);
35580Sstevel@tonic-gate 		optlist->preferredServerList = attrVal;
35590Sstevel@tonic-gate 		/* replace ',' chars with ' ' for proper syntax */
35600Sstevel@tonic-gate 		for (counter = 0;
35616842Sth160488 		    counter < strlen(optlist->preferredServerList);
35626842Sth160488 		    counter++) {
35630Sstevel@tonic-gate 
35640Sstevel@tonic-gate 			if (optlist->preferredServerList[counter] == ',')
35650Sstevel@tonic-gate 				optlist->preferredServerList[counter] = ' ';
35660Sstevel@tonic-gate 		}
35670Sstevel@tonic-gate 		break;
35680Sstevel@tonic-gate 
35690Sstevel@tonic-gate 	case NS_LDAP_PROFILE_P:
35700Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->profileName);
35710Sstevel@tonic-gate 		optlist->profileName = attrVal;
35720Sstevel@tonic-gate 		break;
35730Sstevel@tonic-gate 
35740Sstevel@tonic-gate 	case NS_LDAP_SEARCH_REF_P:
35750Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->followReferrals);
35760Sstevel@tonic-gate 		if (0 == strcasecmp(attrVal, "followref"))
35770Sstevel@tonic-gate 			optlist->followReferrals = "TRUE";
35780Sstevel@tonic-gate 		else if (0 == strcasecmp(attrVal, "noref"))
35790Sstevel@tonic-gate 			optlist->followReferrals = "FALSE";
35800Sstevel@tonic-gate 		else
35810Sstevel@tonic-gate 			optlist->followReferrals = attrVal;
35820Sstevel@tonic-gate 		break;
35830Sstevel@tonic-gate 
35840Sstevel@tonic-gate 	case NS_LDAP_ATTRIBUTEMAP_P:	/* multiple allowed */
35850Sstevel@tonic-gate 		retcode = multival_add(optlist->attributeMap, attrVal);
35860Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
35870Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
35886842Sth160488 			    gettext("Error processing attrVal %s\n"),
35896842Sth160488 			    attrVal?attrVal:"NULL");
35900Sstevel@tonic-gate 			usage();
35910Sstevel@tonic-gate 			clientopts_free(optlist);
35920Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
35930Sstevel@tonic-gate 		}
35940Sstevel@tonic-gate 		break;
35950Sstevel@tonic-gate 
35960Sstevel@tonic-gate 	case NS_LDAP_SEARCH_SCOPE_P:
35970Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchScope);
35980Sstevel@tonic-gate 		optlist->defaultSearchScope = attrVal;
35990Sstevel@tonic-gate 		break;
36000Sstevel@tonic-gate 
36010Sstevel@tonic-gate 	case NS_LDAP_SERVICE_SEARCH_DESC_P:	/* multiple allowed */
36020Sstevel@tonic-gate 		retcode = multival_add(optlist->serviceSearchDescriptor,
36036842Sth160488 		    attrVal);
36040Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
36050Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
36066842Sth160488 			    gettext("Error processing attrVal %s\n"),
36076842Sth160488 			    attrVal?attrVal:"NULL");
36080Sstevel@tonic-gate 			usage();
36090Sstevel@tonic-gate 			clientopts_free(optlist);
36100Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
36110Sstevel@tonic-gate 		}
36120Sstevel@tonic-gate 		break;
36130Sstevel@tonic-gate 
36140Sstevel@tonic-gate 	case NS_LDAP_BIND_TIME_P:
36150Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->bindTimeLimit);
36160Sstevel@tonic-gate 		optlist->bindTimeLimit = attrVal;
36170Sstevel@tonic-gate 		break;
36180Sstevel@tonic-gate 
36190Sstevel@tonic-gate 	case NS_LDAP_BINDPASSWD_P:
36200Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->proxyPassword);
36210Sstevel@tonic-gate 		optlist->proxyPassword = attrVal;
36220Sstevel@tonic-gate 		break;
36230Sstevel@tonic-gate 
3624*8821SMichen.Chang@Sun.COM 	case NS_LDAP_ADMIN_BINDPASSWD_P:
3625*8821SMichen.Chang@Sun.COM 		CLIENT_OPT_CHECK(paramFlag, optlist->adminPassword);
3626*8821SMichen.Chang@Sun.COM 		optlist->adminPassword = attrVal;
3627*8821SMichen.Chang@Sun.COM 		break;
3628*8821SMichen.Chang@Sun.COM 
36290Sstevel@tonic-gate 	case NS_LDAP_HOST_CERTPATH_P:
36300Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->certificatePath);
36310Sstevel@tonic-gate 		optlist->certificatePath = attrVal;
36320Sstevel@tonic-gate 		break;
36330Sstevel@tonic-gate 
36340Sstevel@tonic-gate 	case NS_LDAP_SERVERS_P:
36350Sstevel@tonic-gate 		CLIENT_OPT_CHECK(paramFlag, optlist->defaultServerList);
36360Sstevel@tonic-gate 		optlist->defaultServerList = attrVal;
36370Sstevel@tonic-gate 		break;
36380Sstevel@tonic-gate 
36390Sstevel@tonic-gate 	default:
36400Sstevel@tonic-gate 		usage();
36410Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
36420Sstevel@tonic-gate 		/* break;  lint doesn't like break before end of switch */
36430Sstevel@tonic-gate 	}
36440Sstevel@tonic-gate 
36450Sstevel@tonic-gate 	return (retcode);
36460Sstevel@tonic-gate }
36470Sstevel@tonic-gate 
36480Sstevel@tonic-gate /*
36490Sstevel@tonic-gate  * file_move() - Used to move a config file (backup/restore).
36500Sstevel@tonic-gate  *
36510Sstevel@tonic-gate  * This function uses a system() call with /bin/mv to handle the
36520Sstevel@tonic-gate  * case where the backup directory (/var) is on a different file
36530Sstevel@tonic-gate  * system than the config file (typically /etc).
36540Sstevel@tonic-gate  */
36550Sstevel@tonic-gate static int
36560Sstevel@tonic-gate file_move(const char *from, const char *to)
36570Sstevel@tonic-gate {
36580Sstevel@tonic-gate 	int retcode;
36590Sstevel@tonic-gate 	char mvCommand[] = CMD_MV;
36600Sstevel@tonic-gate 	char cmd_buffer[(2 * MAXPATHLEN) + sizeof (mvCommand) + 3];
36610Sstevel@tonic-gate 
36620Sstevel@tonic-gate 	(void) snprintf(cmd_buffer, sizeof (cmd_buffer), "%s %s %s",
36636842Sth160488 	    mvCommand, from, to);
36640Sstevel@tonic-gate 
36650Sstevel@tonic-gate 	/*
36660Sstevel@tonic-gate 	 * This function should only be used internally to move
36670Sstevel@tonic-gate 	 * system files to/from the backup directory.  For security
36680Sstevel@tonic-gate 	 * reasons (this is run as root), don't use this function
36690Sstevel@tonic-gate 	 * with arguments passed into the program.
36700Sstevel@tonic-gate 	 */
36710Sstevel@tonic-gate 	retcode = system(cmd_buffer);
36720Sstevel@tonic-gate 
36730Sstevel@tonic-gate 	return (retcode);
36740Sstevel@tonic-gate }
36750Sstevel@tonic-gate 
36760Sstevel@tonic-gate 
36770Sstevel@tonic-gate /*
36780Sstevel@tonic-gate  * Manipulate the service as instructed by "dowhat"
36790Sstevel@tonic-gate  */
36800Sstevel@tonic-gate static int
36810Sstevel@tonic-gate do_service(const char *fmri, boolean_t waitflag, int dowhat,
36820Sstevel@tonic-gate 		const char *state) {
36830Sstevel@tonic-gate 
36840Sstevel@tonic-gate 	int		status;
36850Sstevel@tonic-gate 	boolean_t	is_maint;
36860Sstevel@tonic-gate 	const char	*what = gettext("not set");
36870Sstevel@tonic-gate 	useconds_t	max;
36880Sstevel@tonic-gate 
36890Sstevel@tonic-gate 	/* Check if we are in maintenance */
36900Sstevel@tonic-gate 	is_maint = is_service(fmri, SCF_STATE_STRING_MAINT);
36910Sstevel@tonic-gate 
36920Sstevel@tonic-gate 	switch (dowhat) {
36930Sstevel@tonic-gate 	case START_SERVICE:
36940Sstevel@tonic-gate 		what = gettext("start");
36950Sstevel@tonic-gate 		status = smf_enable_instance(fmri,
36960Sstevel@tonic-gate 			(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
36970Sstevel@tonic-gate 		break;
36980Sstevel@tonic-gate 	case STOP_SERVICE:
36990Sstevel@tonic-gate 		what = gettext("stop");
37000Sstevel@tonic-gate 		status = smf_disable_instance(fmri,
37010Sstevel@tonic-gate 			(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
37020Sstevel@tonic-gate 		break;
37030Sstevel@tonic-gate 	case RESTART_SERVICE:
37040Sstevel@tonic-gate 		what = gettext("restart");
37050Sstevel@tonic-gate 		status = smf_restart_instance(fmri);
37060Sstevel@tonic-gate 		break;
37070Sstevel@tonic-gate 	default:
37080Sstevel@tonic-gate 		/* coding error; will not happen */
37090Sstevel@tonic-gate 		assert(0);
37100Sstevel@tonic-gate 	}
37110Sstevel@tonic-gate 
37120Sstevel@tonic-gate 	/*
37130Sstevel@tonic-gate 	 * If the service was previously in maintenance then we need to
37140Sstevel@tonic-gate 	 * clear it immediately.  The "dowhat" action will set the
37150Sstevel@tonic-gate 	 * enabled property of the service as intended by the caller while
37160Sstevel@tonic-gate 	 * clear will actually cause it to be enabled/disabled.
37170Sstevel@tonic-gate 	 * We assume that the caller has called us after taking some
37180Sstevel@tonic-gate 	 * recovery action. Even if it's not the case, we don't lose
37190Sstevel@tonic-gate 	 * anything.
37200Sstevel@tonic-gate 	 */
37210Sstevel@tonic-gate 	if (status == 0 && is_maint == B_TRUE) {
37220Sstevel@tonic-gate 		if (mode_verbose)
37230Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
37240Sstevel@tonic-gate 				"%s: %s... %s\n",
37250Sstevel@tonic-gate 				what,
37260Sstevel@tonic-gate 				fmri,
37270Sstevel@tonic-gate 				gettext("restoring from maintenance state"));
37280Sstevel@tonic-gate 		status = smf_restore_instance(fmri);
37290Sstevel@tonic-gate 	}
37300Sstevel@tonic-gate 
37310Sstevel@tonic-gate 	if (status == 0) {
37320Sstevel@tonic-gate 		/* Check if we need to wait ? */
37330Sstevel@tonic-gate 		if (waitflag == B_FALSE) {
37340Sstevel@tonic-gate 			if (mode_verbose)
37350Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
37360Sstevel@tonic-gate 					"%s: %s... %s\n",
37370Sstevel@tonic-gate 					what,
37380Sstevel@tonic-gate 					fmri,
37390Sstevel@tonic-gate 					gettext("success"));
37400Sstevel@tonic-gate 			return (CLIENT_SUCCESS);
37410Sstevel@tonic-gate 		}
37420Sstevel@tonic-gate 
37430Sstevel@tonic-gate 		/* Otherwise wait for max seconds (from the manifest) */
37440Sstevel@tonic-gate 		max = get_timeout_value(dowhat, fmri, DEFAULT_TIMEOUT);
37450Sstevel@tonic-gate 		status = wait_till(fmri, state, max, what, !is_maint);
37460Sstevel@tonic-gate 		if (status == CLIENT_SUCCESS)
37470Sstevel@tonic-gate 			return (CLIENT_SUCCESS);
37480Sstevel@tonic-gate 		/* For error fall through for corrective action */
37490Sstevel@tonic-gate 	} else {
37500Sstevel@tonic-gate 		/* Well, service failed ... */
37510Sstevel@tonic-gate 		if (mode_verbose)
37520Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
37530Sstevel@tonic-gate 				what,
37540Sstevel@tonic-gate 				fmri,
37550Sstevel@tonic-gate 				gettext("failed"),
37560Sstevel@tonic-gate 				scf_strerror(scf_error()));
37570Sstevel@tonic-gate 		status = CLIENT_ERR_FAIL;
37580Sstevel@tonic-gate 		/* For error fall through for corrective action */
37590Sstevel@tonic-gate 	}
37600Sstevel@tonic-gate 
37610Sstevel@tonic-gate 	/*
37620Sstevel@tonic-gate 	 * If service is still offline after start/restart, then transitioning
37630Sstevel@tonic-gate 	 * failed and guess is restarter failed to apply the timeout as well.
37640Sstevel@tonic-gate 	 * So instead of leaving it offline, let's just disable it until we have
37650Sstevel@tonic-gate 	 * some other mechanism available from smf to handle such situation.
37660Sstevel@tonic-gate 	 */
37670Sstevel@tonic-gate 	if (dowhat != STOP_SERVICE)
37680Sstevel@tonic-gate 		if (is_service(fmri, SCF_STATE_STRING_OFFLINE)) {
37690Sstevel@tonic-gate 			if (mode_verbose)
37700Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
37710Sstevel@tonic-gate 					"%s: %s... %s\n",
37720Sstevel@tonic-gate 					what,
37730Sstevel@tonic-gate 					fmri,
37740Sstevel@tonic-gate 					gettext("offline to disable"));
37750Sstevel@tonic-gate 			(void) disable_service(fmri, waitflag);
37760Sstevel@tonic-gate 		}
37770Sstevel@tonic-gate 
37780Sstevel@tonic-gate 	return (status);
37790Sstevel@tonic-gate }
37800Sstevel@tonic-gate 
37810Sstevel@tonic-gate 
37820Sstevel@tonic-gate /*
37830Sstevel@tonic-gate  * Wait for "max" usecs for the service described by "fmri" to change
37840Sstevel@tonic-gate  * to "state". If check_maint is true then return immediately if
37850Sstevel@tonic-gate  * service goes into maintenance
37860Sstevel@tonic-gate  */
37870Sstevel@tonic-gate static int
37880Sstevel@tonic-gate wait_till(const char *fmri, const char *state, useconds_t max,
37890Sstevel@tonic-gate 		const char *what, boolean_t check_maint) {
37900Sstevel@tonic-gate 	char *st;
37910Sstevel@tonic-gate 	useconds_t usecs = INIT_WAIT_USECS;
37920Sstevel@tonic-gate 
37930Sstevel@tonic-gate 	for (; max > 0; max -= usecs) {
37940Sstevel@tonic-gate 		/* incremental wait */
37950Sstevel@tonic-gate 		usecs *= 2;
37960Sstevel@tonic-gate 		usecs = (usecs > max)?max:usecs;
37970Sstevel@tonic-gate 		if (mode_verbose)
37980Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr,
37990Sstevel@tonic-gate 				"%s: %s %u %s\n",
38000Sstevel@tonic-gate 				what, gettext("sleep"), usecs,
38010Sstevel@tonic-gate 				gettext("microseconds"));
38020Sstevel@tonic-gate 		(void) usleep(usecs);
38030Sstevel@tonic-gate 
38040Sstevel@tonic-gate 		/* Check state after the wait */
38050Sstevel@tonic-gate 		if ((st = smf_get_state(fmri)) != NULL) {
38060Sstevel@tonic-gate 			if (strcmp(st, state) == 0) {
38070Sstevel@tonic-gate 				if (mode_verbose)
38080Sstevel@tonic-gate 					CLIENT_FPRINTF(stderr,
38090Sstevel@tonic-gate 						"%s: %s... %s\n",
38100Sstevel@tonic-gate 						what,
38110Sstevel@tonic-gate 						fmri,
38120Sstevel@tonic-gate 						gettext("success"));
38130Sstevel@tonic-gate 				free(st);
38140Sstevel@tonic-gate 				return (CLIENT_SUCCESS);
38150Sstevel@tonic-gate 			}
38160Sstevel@tonic-gate 
38170Sstevel@tonic-gate 			/*
38180Sstevel@tonic-gate 			 * If service has gone into maintenance then
38190Sstevel@tonic-gate 			 * we will time out anyway, so we are better
38200Sstevel@tonic-gate 			 * off returning now
38210Sstevel@tonic-gate 			 */
38220Sstevel@tonic-gate 			if (check_maint &&
38230Sstevel@tonic-gate 				strcmp(st, SCF_STATE_STRING_MAINT) == 0) {
38240Sstevel@tonic-gate 				if (mode_verbose)
38250Sstevel@tonic-gate 					CLIENT_FPRINTF(stderr,
38260Sstevel@tonic-gate 						"%s: %s... %s\n",
38270Sstevel@tonic-gate 						what,
38280Sstevel@tonic-gate 						fmri,
38290Sstevel@tonic-gate 						gettext("maintenance"));
38300Sstevel@tonic-gate 				free(st);
38310Sstevel@tonic-gate 				return (CLIENT_ERR_MAINTENANCE);
38320Sstevel@tonic-gate 			}
38330Sstevel@tonic-gate 			free(st);
38340Sstevel@tonic-gate 		} else {
38350Sstevel@tonic-gate 			if (mode_verbose)
38360Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
38370Sstevel@tonic-gate 						"%s: %s... %s: %s\n",
38380Sstevel@tonic-gate 						what,
38390Sstevel@tonic-gate 						fmri,
38400Sstevel@tonic-gate 						gettext("failed"),
38410Sstevel@tonic-gate 						scf_strerror(scf_error()));
38420Sstevel@tonic-gate 			return (CLIENT_ERR_FAIL);
38430Sstevel@tonic-gate 		}
38440Sstevel@tonic-gate 	}
38450Sstevel@tonic-gate 
38460Sstevel@tonic-gate 	/* Timed out waiting */
38470Sstevel@tonic-gate 	if (mode_verbose)
38480Sstevel@tonic-gate 		CLIENT_FPRINTF(stderr,
38490Sstevel@tonic-gate 			"%s: %s... %s\n",
38500Sstevel@tonic-gate 			what,
38510Sstevel@tonic-gate 			fmri,
38520Sstevel@tonic-gate 			gettext("timed out"));
38530Sstevel@tonic-gate 	return (CLIENT_ERR_TIMEDOUT);
38540Sstevel@tonic-gate }
38550Sstevel@tonic-gate 
38560Sstevel@tonic-gate 
38570Sstevel@tonic-gate static boolean_t
38580Sstevel@tonic-gate is_service(const char *fmri, const char *state) {
38590Sstevel@tonic-gate 	char		*st;
38600Sstevel@tonic-gate 	boolean_t	result = B_FALSE;
38610Sstevel@tonic-gate 
38620Sstevel@tonic-gate 	if ((st = smf_get_state(fmri)) != NULL) {
38630Sstevel@tonic-gate 		if (strcmp(st, state) == 0)
38640Sstevel@tonic-gate 			result = B_TRUE;
38650Sstevel@tonic-gate 		free(st);
38660Sstevel@tonic-gate 	}
38670Sstevel@tonic-gate 	return (result);
38680Sstevel@tonic-gate }
38690Sstevel@tonic-gate 
38700Sstevel@tonic-gate 
38710Sstevel@tonic-gate /*
38720Sstevel@tonic-gate  *
38730Sstevel@tonic-gate  * get_timeout_val : returns the timeout value set in fmri manifest
38740Sstevel@tonic-gate  * 	inputs	: action(start/stop)
38750Sstevel@tonic-gate  *	fmri(defined fmri string)
38760Sstevel@tonic-gate  *	Returns default if error, the timeout val otherwise
38770Sstevel@tonic-gate  *
38780Sstevel@tonic-gate  */
38790Sstevel@tonic-gate 
38800Sstevel@tonic-gate static useconds_t
38810Sstevel@tonic-gate get_timeout_value(int dowhat, const char *fmri, useconds_t default_val)
38820Sstevel@tonic-gate {
38830Sstevel@tonic-gate 	scf_simple_prop_t	*sp = NULL;
38840Sstevel@tonic-gate 	uint64_t		*cp = NULL;
38850Sstevel@tonic-gate 	int			timeout = default_val/1000000;
38860Sstevel@tonic-gate 	char			*action = NULL;
38870Sstevel@tonic-gate 	const char		*actionstr = NULL;
38880Sstevel@tonic-gate 
38890Sstevel@tonic-gate 	switch (dowhat)  {
38900Sstevel@tonic-gate 		case START_SERVICE:
38910Sstevel@tonic-gate 		case RESTART_SERVICE:
38920Sstevel@tonic-gate 				action = "start";
38930Sstevel@tonic-gate 				actionstr = gettext("start");
38940Sstevel@tonic-gate 				break;
38950Sstevel@tonic-gate 		case STOP_SERVICE:
38960Sstevel@tonic-gate 				action = "stop";
38970Sstevel@tonic-gate 				actionstr = gettext("stop");
38980Sstevel@tonic-gate 				break;
38990Sstevel@tonic-gate 		default:
39000Sstevel@tonic-gate 			assert(0);
39010Sstevel@tonic-gate 	}
39020Sstevel@tonic-gate 
39030Sstevel@tonic-gate 
39040Sstevel@tonic-gate 	sp = scf_simple_prop_get(NULL, fmri, action, SCF_PROPERTY_TIMEOUT);
39050Sstevel@tonic-gate 	if (sp == NULL) {
39060Sstevel@tonic-gate 		if (mode_verbose)
39070Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
39086842Sth160488 			    actionstr,
39096842Sth160488 			    fmri,
39106842Sth160488 			    gettext("failed to retrieve timeout property"),
39116842Sth160488 			    scf_strerror(scf_error()));
39120Sstevel@tonic-gate 		return (default_val);
39130Sstevel@tonic-gate 	}
39140Sstevel@tonic-gate 
39150Sstevel@tonic-gate 	cp = scf_simple_prop_next_count(sp);
39160Sstevel@tonic-gate 	if (cp == NULL) {
39170Sstevel@tonic-gate 		if (mode_verbose)
39180Sstevel@tonic-gate 			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
39196842Sth160488 			    actionstr,
39206842Sth160488 			    fmri,
39216842Sth160488 			    gettext("failed to retrieve timeout value"),
39226842Sth160488 			    scf_strerror(scf_error()));
39230Sstevel@tonic-gate 		scf_simple_prop_free(sp);
39240Sstevel@tonic-gate 		return (default_val);
39250Sstevel@tonic-gate 	}
39260Sstevel@tonic-gate 
39270Sstevel@tonic-gate 	if (*cp != 0)
39280Sstevel@tonic-gate 		timeout = *cp;
39290Sstevel@tonic-gate 	scf_simple_prop_free(sp);
39300Sstevel@tonic-gate 	return (timeout * 1000000);
39310Sstevel@tonic-gate }
3932