17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22dd1104fbSMichen Chang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2433f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
2548bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * ldapclient command. To make (initiailize) or uninitialize a machines as
307c478bd9Sstevel@tonic-gate  * and LDAP client.  This command MUST be run as root (or it will simply exit).
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  *	-I	Install. No file_backup/recover for installing only (no doc).
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  *	init	Initialze (create) an LDAP client from a profile stored
357c478bd9Sstevel@tonic-gate  *		in a directory-server.
367c478bd9Sstevel@tonic-gate  *	manual	Initialze (create) an LDAP client by hand (-file option
377c478bd9Sstevel@tonic-gate  *		reads from file).
387c478bd9Sstevel@tonic-gate  *	mod	Modify the LDAP client configuration on this machine by hand.
397c478bd9Sstevel@tonic-gate  *	list	List the contents of the LDAP client cache files.
407c478bd9Sstevel@tonic-gate  *	uninit	Uninitialize this machine.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  *	-v	Verbose flag.
437c478bd9Sstevel@tonic-gate  *	-q	Quiet flag (mutually exclusive with -v).
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  *	-a attrName=attrVal
467c478bd9Sstevel@tonic-gate  *	<attrName> can be one of the following:
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *	attributeMap
497c478bd9Sstevel@tonic-gate  *		Attribute map.  Can be multiple instances of this option.
507c478bd9Sstevel@tonic-gate  *		(no former option)
517c478bd9Sstevel@tonic-gate  *	authenticationMethod
527c478bd9Sstevel@tonic-gate  *		Authentication method (formerly -a)
537c478bd9Sstevel@tonic-gate  *	bindTimeLimit
547c478bd9Sstevel@tonic-gate  *		Bind time limit. (no former option)
557c478bd9Sstevel@tonic-gate  *	certificatePath
567c478bd9Sstevel@tonic-gate  *		Path to certificates used for secure bind (no former option)
577c478bd9Sstevel@tonic-gate  *	credentialLevel
587c478bd9Sstevel@tonic-gate  *		Client credential level (no former option)
597c478bd9Sstevel@tonic-gate  *	defaultServerList
607c478bd9Sstevel@tonic-gate  *		Default server (no former option) Refer to DUA Config
617c478bd9Sstevel@tonic-gate  *		Schema draft.
627c478bd9Sstevel@tonic-gate  *	defaultSearchBase
637c478bd9Sstevel@tonic-gate  *		Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b)
647c478bd9Sstevel@tonic-gate  *	defaultSearchScope
657c478bd9Sstevel@tonic-gate  *		Search scope. (formerly -s)
667c478bd9Sstevel@tonic-gate  *	domainName
677c478bd9Sstevel@tonic-gate  *		Hosts lookup domain (DNS)  Ex. eng.sun.com (formerly -d)
687c478bd9Sstevel@tonic-gate  *	followReferrals
697c478bd9Sstevel@tonic-gate  *		Search dereference. followref or noref (default followref)
707c478bd9Sstevel@tonic-gate  *		(formerly -r)
717c478bd9Sstevel@tonic-gate  *	objectclassMap
727c478bd9Sstevel@tonic-gate  *		Objectclass map.  Can be multiple instances of this option.
737c478bd9Sstevel@tonic-gate  *		(no former option)
747c478bd9Sstevel@tonic-gate  *	preferredServerList
757c478bd9Sstevel@tonic-gate  *		Server preference list. Comma ',' seperated list of IPaddr.
767c478bd9Sstevel@tonic-gate  *		(formerly -p)
777c478bd9Sstevel@tonic-gate  *	profileName
787c478bd9Sstevel@tonic-gate  *		Profile name to use for init (ldapclient) or
797c478bd9Sstevel@tonic-gate  *		generate (gen_profile). (formerly -P)
807c478bd9Sstevel@tonic-gate  *	profileTTL
817c478bd9Sstevel@tonic-gate  *		Client info TTL.  If set to 0 this information will not be
82*bbf21555SRichard Lowe  *		automatically updated by the ldap_cachemgr(8).
837c478bd9Sstevel@tonic-gate  *		(formerly -e)
847c478bd9Sstevel@tonic-gate  *	proxyDN
857c478bd9Sstevel@tonic-gate  *		Binding DN.  Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com
867c478bd9Sstevel@tonic-gate  *		(formerly -D)
877c478bd9Sstevel@tonic-gate  *	proxyPassword
887c478bd9Sstevel@tonic-gate  *		Client password not needed for authentication "none".
897c478bd9Sstevel@tonic-gate  *		(formerly -w)
90dd1104fbSMichen Chang  *	adminDN
91dd1104fbSMichen Chang  *		Administrator DN for updating naming data.
92dd1104fbSMichen Chang  *	adminPassword
93dd1104fbSMichen Chang  *		Administrator password
94dd1104fbSMichen Chang  *	enableShadowUpdate
95dd1104fbSMichen Chang  *		Allow Administrator to change shadow data in LDAP
967c478bd9Sstevel@tonic-gate  *	searchTimeLimit
977c478bd9Sstevel@tonic-gate  *		Timeout value. (formerly -o)
987c478bd9Sstevel@tonic-gate  *	serviceSearchDescriptor
997c478bd9Sstevel@tonic-gate  *		Service search scope. (no former option)
1007c478bd9Sstevel@tonic-gate  *	serviceAuthenticationMethod
1017c478bd9Sstevel@tonic-gate  *		Service authenticaion method (no former option)
1027c478bd9Sstevel@tonic-gate  *	serviceCredentialLevel
1037c478bd9Sstevel@tonic-gate  *		Service credential level (no former option)
1047c478bd9Sstevel@tonic-gate  *
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #include <stdlib.h>
1087c478bd9Sstevel@tonic-gate #include <stdio.h>
1097c478bd9Sstevel@tonic-gate #include <unistd.h>
1107c478bd9Sstevel@tonic-gate #include <errno.h>
1117c478bd9Sstevel@tonic-gate #include <sys/types.h>
1127c478bd9Sstevel@tonic-gate #include <time.h>
1137c478bd9Sstevel@tonic-gate #include <sys/param.h>
1147c478bd9Sstevel@tonic-gate #include <sys/stat.h>
1157c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
1167c478bd9Sstevel@tonic-gate #include <fcntl.h>
1177c478bd9Sstevel@tonic-gate #include <xti.h>
1187c478bd9Sstevel@tonic-gate #include <strings.h>
1197c478bd9Sstevel@tonic-gate #include <limits.h>
1207c478bd9Sstevel@tonic-gate #include <locale.h>
1217c478bd9Sstevel@tonic-gate #include <syslog.h>
1227c478bd9Sstevel@tonic-gate #include <libscf.h>
1237c478bd9Sstevel@tonic-gate #include <assert.h>
124e1dd0a2fSth 
125e1dd0a2fSth #include "standalone.h"
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1287c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SUNW_OST_OSCMD"
1297c478bd9Sstevel@tonic-gate #endif
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /* error codes */
1327c478bd9Sstevel@tonic-gate /* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */
1337c478bd9Sstevel@tonic-gate #define	CLIENT_SUCCESS		0
1347c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_PARSE	-1
1357c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_FAIL		1
1367c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_CREDENTIAL	2
1377c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_MEMORY	3
1387c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_RESTORE	4
1397c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_RENAME	5
1407c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_RECOVER	6
1417c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_TIMEDOUT	7
1427c478bd9Sstevel@tonic-gate #define	CLIENT_ERR_MAINTENANCE	8
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /* Reset flag for start_services() */
1457c478bd9Sstevel@tonic-gate #define	START_INIT	1
1467c478bd9Sstevel@tonic-gate #define	START_RESET	2
1477c478bd9Sstevel@tonic-gate #define	START_UNINIT	3
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /* Reset flag for stop_services() */
1507c478bd9Sstevel@tonic-gate #define	STATE_NOSAVE	0
1517c478bd9Sstevel@tonic-gate #define	STATE_SAVE	1
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /* files to (possibiliy) restore */
1547c478bd9Sstevel@tonic-gate #define	LDAP_RESTORE_DIR	"/var/ldap/restore"
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #define	DOMAINNAME_DIR		"/etc"
1577c478bd9Sstevel@tonic-gate #define	DOMAINNAME_FILE		"defaultdomain"
1587c478bd9Sstevel@tonic-gate #define	DOMAINNAME		DOMAINNAME_DIR "/" DOMAINNAME_FILE
1597c478bd9Sstevel@tonic-gate #define	DOMAINNAME_BACK		LDAP_RESTORE_DIR "/" DOMAINNAME_FILE
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #define	NSSWITCH_DIR		"/etc"
1627c478bd9Sstevel@tonic-gate #define	NSSWITCH_FILE		"nsswitch.conf"
1637c478bd9Sstevel@tonic-gate #define	NSSWITCH_CONF		NSSWITCH_DIR "/" NSSWITCH_FILE
1647c478bd9Sstevel@tonic-gate #define	NSSWITCH_BACK		LDAP_RESTORE_DIR "/" NSSWITCH_FILE
1657c478bd9Sstevel@tonic-gate #define	NSSWITCH_LDAP		"/etc/nsswitch.ldap"
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate #define	YP_BIND_DIR		"/var/yp/binding"
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /* Define the service FMRIs */
1707c478bd9Sstevel@tonic-gate #define	SENDMAIL_FMRI		"network/smtp:sendmail"
1717c478bd9Sstevel@tonic-gate #define	NSCD_FMRI		"system/name-service-cache:default"
1727c478bd9Sstevel@tonic-gate #define	AUTOFS_FMRI		"system/filesystem/autofs:default"
1737c478bd9Sstevel@tonic-gate #define	LDAP_FMRI		"network/ldap/client:default"
1747c478bd9Sstevel@tonic-gate #define	YP_FMRI			"network/nis/client:default"
1757c478bd9Sstevel@tonic-gate #define	NS_MILESTONE_FMRI	"milestone/name-services:default"
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /* Define flags for checking if services were enabled */
1787c478bd9Sstevel@tonic-gate #define	SENDMAIL_ON	0x1
1797c478bd9Sstevel@tonic-gate #define	NSCD_ON		0x10
1807c478bd9Sstevel@tonic-gate #define	AUTOFS_ON	0x100
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate #define	CMD_DOMAIN_START	"/usr/bin/domainname"
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /* Command to copy files */
1857c478bd9Sstevel@tonic-gate #define	CMD_CP			"/bin/cp -f"
1867c478bd9Sstevel@tonic-gate #define	CMD_MV			"/bin/mv -f"
1877c478bd9Sstevel@tonic-gate #define	CMD_RM			"/bin/rm -f"
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate #define	TO_DEV_NULL		" >/dev/null 2>&1"
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /* Files that need to be just removed */
1927c478bd9Sstevel@tonic-gate #define	LDAP_CACHE_LOG		"/var/ldap/cachemgr.log"
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /* Output defines to supress if quiet mode set */
1957c478bd9Sstevel@tonic-gate #define	CLIENT_FPUTS if (!mode_quiet) (void) fputs
1967c478bd9Sstevel@tonic-gate #define	CLIENT_FPRINTF if (!mode_quiet) (void) fprintf
1977c478bd9Sstevel@tonic-gate #define	CLIENT_FPUTC if (!mode_quiet) (void) fputc
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate #define	restart_service(fmri, waitflag)\
2007c478bd9Sstevel@tonic-gate 		do_service(fmri, waitflag, RESTART_SERVICE,\
2017c478bd9Sstevel@tonic-gate 		SCF_STATE_STRING_ONLINE)
2027c478bd9Sstevel@tonic-gate #define	start_service(fmri, waitflag)	\
2037c478bd9Sstevel@tonic-gate 		do_service(fmri, waitflag, START_SERVICE,\
2047c478bd9Sstevel@tonic-gate 		SCF_STATE_STRING_ONLINE)
2057c478bd9Sstevel@tonic-gate #define	disable_service(fmri, waitflag)	\
2067c478bd9Sstevel@tonic-gate 		do_service(fmri, waitflag, STOP_SERVICE,\
2077c478bd9Sstevel@tonic-gate 		SCF_STATE_STRING_DISABLED)
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  * There isn't a domainName defined as a param, so we set a value here
2117c478bd9Sstevel@tonic-gate  * (1001) should be big enough
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate #define	LOCAL_DOMAIN_P 1001
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate #define	START_SERVICE	1
2167c478bd9Sstevel@tonic-gate #define	STOP_SERVICE	2
2177c478bd9Sstevel@tonic-gate #define	RESTART_SERVICE	3
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate #define	DEFAULT_TIMEOUT	60000000
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #define	INIT_WAIT_USECS	50000
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate /* Used to turn off profile checking */
2247c478bd9Sstevel@tonic-gate #define	CACHETTL_OFF "0"
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate /* Globals */
2277c478bd9Sstevel@tonic-gate static char *cmd;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate static char *dname = NULL;
2307c478bd9Sstevel@tonic-gate static char dname_buf[BUFSIZ];
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate static boolean_t sysid_install = B_FALSE;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate static int mode_verbose = 0;
2357c478bd9Sstevel@tonic-gate static int mode_quiet = 0;
2367c478bd9Sstevel@tonic-gate static int gen = 0;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate static int gStartLdap = 0;
2397c478bd9Sstevel@tonic-gate static int gStartYp = 0;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate static int enableFlag = 0;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate /* multival_t is used to hold params that can have more than one value */
2447c478bd9Sstevel@tonic-gate typedef struct {
2457c478bd9Sstevel@tonic-gate 	int count;
2467c478bd9Sstevel@tonic-gate 	char **optlist;
2477c478bd9Sstevel@tonic-gate } multival_t;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate static multival_t *multival_new();
2507c478bd9Sstevel@tonic-gate static int multival_add(multival_t *list, char *opt);
2517c478bd9Sstevel@tonic-gate static void multival_free(multival_t *list);
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate  * clientopts_t is used to hold and pass around the param values from
2557c478bd9Sstevel@tonic-gate  * the cmd line
2567c478bd9Sstevel@tonic-gate  */
2577c478bd9Sstevel@tonic-gate typedef struct {
2587c478bd9Sstevel@tonic-gate 	multival_t	*attributeMap;
2597c478bd9Sstevel@tonic-gate 	char		*authenticationMethod;
2607c478bd9Sstevel@tonic-gate 	char		*bindTimeLimit;
2617c478bd9Sstevel@tonic-gate 	char		*certificatePath;
2627c478bd9Sstevel@tonic-gate 	char		*credentialLevel;
2637c478bd9Sstevel@tonic-gate 	char		*defaultSearchBase;
2647c478bd9Sstevel@tonic-gate 	char		*defaultServerList;
2657c478bd9Sstevel@tonic-gate 	char		*domainName;
2667c478bd9Sstevel@tonic-gate 	char		*followReferrals;
2677c478bd9Sstevel@tonic-gate 	multival_t	*objectclassMap;
2687c478bd9Sstevel@tonic-gate 	char		*preferredServerList;
2697c478bd9Sstevel@tonic-gate 	char		*profileName;
2707c478bd9Sstevel@tonic-gate 	char		*profileTTL;
2717c478bd9Sstevel@tonic-gate 	char		*proxyDN;
2727c478bd9Sstevel@tonic-gate 	char		*proxyPassword;
273dd1104fbSMichen Chang 	char		*enableShadowUpdate;
274dd1104fbSMichen Chang 	char		*adminDN;
275dd1104fbSMichen Chang 	char		*adminPassword;
276e1dd0a2fSth 	char		*bindDN;
277e1dd0a2fSth 	char		*bindPasswd;
2787c478bd9Sstevel@tonic-gate 	char		*defaultSearchScope;
2797c478bd9Sstevel@tonic-gate 	char		*searchTimeLimit;
2807c478bd9Sstevel@tonic-gate 	multival_t	*serviceAuthenticationMethod;
2817c478bd9Sstevel@tonic-gate 	multival_t	*serviceCredentialLevel;
2827c478bd9Sstevel@tonic-gate 	multival_t	*serviceSearchDescriptor;
2837c478bd9Sstevel@tonic-gate } clientopts_t;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate static clientopts_t *clientopts_new();
2867c478bd9Sstevel@tonic-gate static void clientopts_free(clientopts_t *list);
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate extern ns_ldap_error_t *__ns_ldap_print_config(int);
2897c478bd9Sstevel@tonic-gate extern void __ns_ldap_default_config();
290cb5caa98Sdjl extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /* Function prototypes (these could be static) */
2937c478bd9Sstevel@tonic-gate static void usage(void);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate static int credCheck(clientopts_t *arglist);
296dd1104fbSMichen Chang static int adminCredCheck(clientopts_t *arglist);
2977c478bd9Sstevel@tonic-gate static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal);
2987c478bd9Sstevel@tonic-gate static int parseParam(char *param, char **paramVal);
2997c478bd9Sstevel@tonic-gate static void dumpargs(clientopts_t *arglist);
3007c478bd9Sstevel@tonic-gate static int num_args(clientopts_t *arglist);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int file_backup(void);
3037c478bd9Sstevel@tonic-gate static int recover(int saveState);
3047c478bd9Sstevel@tonic-gate static int mod_backup(void);
3057c478bd9Sstevel@tonic-gate static int mod_recover(void);
3067c478bd9Sstevel@tonic-gate static void mod_cleanup(void);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate static int client_list(clientopts_t *arglist);
3097c478bd9Sstevel@tonic-gate static int client_manual(clientopts_t *arglist);
3107c478bd9Sstevel@tonic-gate static int client_mod(clientopts_t *arglist);
3117c478bd9Sstevel@tonic-gate static int client_uninit(clientopts_t *arglist);
3127c478bd9Sstevel@tonic-gate static int client_genProfile(clientopts_t *arglist);
3137c478bd9Sstevel@tonic-gate static int client_init(clientopts_t *arglist);
3147c478bd9Sstevel@tonic-gate static int file_move(const char *from, const char *to);
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate static int start_services(int flag);
3177c478bd9Sstevel@tonic-gate static int stop_services(int saveState);
3187c478bd9Sstevel@tonic-gate static boolean_t is_service(const char *fmri, const char *state);
3197c478bd9Sstevel@tonic-gate static int wait_till(const char *fmri, const char *state, useconds_t max,
3207c478bd9Sstevel@tonic-gate 		const char *what, boolean_t check_maint);
3217c478bd9Sstevel@tonic-gate static int do_service(const char *fmri, boolean_t waitflag, int dowhat,
3227c478bd9Sstevel@tonic-gate 		const char *state);
3237c478bd9Sstevel@tonic-gate static useconds_t get_timeout_value(int dowhat, const char *fmri,
3247c478bd9Sstevel@tonic-gate 		useconds_t default_val);
3257c478bd9Sstevel@tonic-gate 
326a506a34cSth int
main(int argc,char ** argv)327a506a34cSth main(int argc, char **argv)
3287c478bd9Sstevel@tonic-gate {
329e1dd0a2fSth 	char		*ret_locale, *ret_textdomain;
330e1dd0a2fSth 	int		retcode;
331e1dd0a2fSth 	int		paramFlag;
332e1dd0a2fSth 	char		*attrVal;
333e1dd0a2fSth 	int		sysinfostatus;
334e1dd0a2fSth 	clientopts_t	*optlist = NULL;
335e1dd0a2fSth 	int		op_manual = 0, op_mod = 0, op_uninit = 0;
336e1dd0a2fSth 	int		op_list = 0, op_init = 0, op_genprofile = 0;
337e1dd0a2fSth 	extern char	*optarg;
338e1dd0a2fSth 	extern int	optind;
339e1dd0a2fSth 	int		option;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	ret_locale = setlocale(LC_ALL, "");
3427c478bd9Sstevel@tonic-gate 	if (ret_locale == NULL) {
3437c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	ret_textdomain = textdomain(TEXT_DOMAIN);
3467c478bd9Sstevel@tonic-gate 	if (ret_textdomain == NULL) {
3477c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr);
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	openlog("ldapclient", LOG_PID, LOG_USER);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* get name that invoked us */
3537c478bd9Sstevel@tonic-gate 	if (cmd = strrchr(argv[0], '/'))
3547c478bd9Sstevel@tonic-gate 		++cmd;
3557c478bd9Sstevel@tonic-gate 	else
3567c478bd9Sstevel@tonic-gate 		cmd = argv[0];
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ);
3597c478bd9Sstevel@tonic-gate 	if (0 < sysinfostatus)
3607c478bd9Sstevel@tonic-gate 		dname = &dname_buf[0];
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	optlist = clientopts_new();
3637c478bd9Sstevel@tonic-gate 	if (optlist == NULL) {
3647c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
365e1dd0a2fSth 		    gettext("Error getting optlist (malloc fail)\n"),
366e1dd0a2fSth 		    stderr);
3677c478bd9Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	optind = 1;
3717c478bd9Sstevel@tonic-gate 	while (optind < argc) {
372dd1104fbSMichen Chang 		option = getopt(argc, argv, "vqa:ID:w:j:y:z:");
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 		switch (option) {
3757c478bd9Sstevel@tonic-gate 		case 'v':
3767c478bd9Sstevel@tonic-gate 			mode_verbose = 1;
3777c478bd9Sstevel@tonic-gate 			break;
3787c478bd9Sstevel@tonic-gate 		case 'q':
3797c478bd9Sstevel@tonic-gate 			mode_quiet = 1;
3807c478bd9Sstevel@tonic-gate 			break;
3817c478bd9Sstevel@tonic-gate 		case 'a':
3827c478bd9Sstevel@tonic-gate 			attrVal = NULL;
3837c478bd9Sstevel@tonic-gate 			paramFlag = parseParam(optarg, &attrVal);
3847c478bd9Sstevel@tonic-gate 			if (paramFlag == CLIENT_ERR_PARSE) {
3857c478bd9Sstevel@tonic-gate 				CLIENT_FPRINTF(stderr,
386e1dd0a2fSth 				    gettext("Unrecognized "
387e1dd0a2fSth 				    "parameter \"%s\"\n"),
388e1dd0a2fSth 				    optarg);
3897c478bd9Sstevel@tonic-gate 				usage();
3907c478bd9Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
3917c478bd9Sstevel@tonic-gate 			}
392e1dd0a2fSth 			if (paramFlag == NS_LDAP_BINDPASSWD_P &&
393e1dd0a2fSth 			    optlist->proxyPassword != NULL) {
394e1dd0a2fSth 				(void) fprintf(stderr,
395e1dd0a2fSth 				    gettext("The -a proxyPassword option is "
396e1dd0a2fSth 				    "mutually exclusive of -y. "
397e1dd0a2fSth 				    "-a proxyPassword is ignored.\n"));
398e1dd0a2fSth 				break;
399e1dd0a2fSth 			}
400dd1104fbSMichen Chang 			if (paramFlag == NS_LDAP_ADMIN_BINDPASSWD_P &&
401dd1104fbSMichen Chang 			    optlist->adminPassword != NULL) {
402dd1104fbSMichen Chang 				(void) fprintf(stderr,
403dd1104fbSMichen Chang 				    gettext("The -a adminPassword option is "
404dd1104fbSMichen Chang 				    "mutually exclusive of -z. "
405dd1104fbSMichen Chang 				    "-a adminPassword is ignored.\n"));
406dd1104fbSMichen Chang 				break;
407dd1104fbSMichen Chang 			}
4087c478bd9Sstevel@tonic-gate 			retcode = clientSetParam(optlist, paramFlag, attrVal);
4097c478bd9Sstevel@tonic-gate 			if (retcode != CLIENT_SUCCESS) {
4107c478bd9Sstevel@tonic-gate 				CLIENT_FPRINTF(
411e1dd0a2fSth 				    stderr,
412e1dd0a2fSth 				    gettext("Error (%d) setting "
413e1dd0a2fSth 				    "param \"%s\"\n"),
414e1dd0a2fSth 				    retcode, optarg);
4157c478bd9Sstevel@tonic-gate 				usage();
4167c478bd9Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
4177c478bd9Sstevel@tonic-gate 			}
4187c478bd9Sstevel@tonic-gate 			break;
419e1dd0a2fSth 		case 'D':
420e1dd0a2fSth 			optlist->bindDN = strdup(optarg);
421e1dd0a2fSth 			break;
422e1dd0a2fSth 		case 'w':
423e1dd0a2fSth 			if (optlist->bindPasswd != NULL) {
424e1dd0a2fSth 				CLIENT_FPRINTF(stderr,
425e1dd0a2fSth 				    gettext("The -w option is mutually "
426e1dd0a2fSth 				    "exclusive of -j. -w is ignored."));
427e1dd0a2fSth 				break;
428e1dd0a2fSth 			}
429e1dd0a2fSth 
430e1dd0a2fSth 			if (optarg[0] == '-' && optarg[1] == '\0') {
431e1dd0a2fSth 				/* Ask for a password later */
432e1dd0a2fSth 				break;
433e1dd0a2fSth 			}
434e1dd0a2fSth 
435e1dd0a2fSth 			optlist->bindPasswd = strdup(optarg);
436e1dd0a2fSth 			break;
437e1dd0a2fSth 		case 'j':
438e1dd0a2fSth 			if (optlist->bindPasswd != NULL) {
439e1dd0a2fSth 				(void) fprintf(stderr,
440e1dd0a2fSth 				    gettext("The -w option is mutually "
441e1dd0a2fSth 				    "exclusive of -j. -w is ignored.\n"));
442e1dd0a2fSth 				free(optlist->bindPasswd);
443e1dd0a2fSth 			}
444e1dd0a2fSth 			optlist->bindPasswd = readPwd(optarg);
445e1dd0a2fSth 			if (optlist->bindPasswd == NULL) {
446e1dd0a2fSth 				exit(CLIENT_ERR_FAIL);
447e1dd0a2fSth 			}
448e1dd0a2fSth 			break;
449e1dd0a2fSth 		case 'y':
450e1dd0a2fSth 			if (optlist->proxyPassword != NULL) {
451e1dd0a2fSth 				(void) fprintf(stderr,
452e1dd0a2fSth 				    gettext("The -a proxyPassword option is "
453e1dd0a2fSth 				    "mutually exclusive of -y. "
454e1dd0a2fSth 				    "-a proxyPassword is ignored.\n"));
455e1dd0a2fSth 			}
456e1dd0a2fSth 			optlist->proxyPassword = readPwd(optarg);
457e1dd0a2fSth 			if (optlist->proxyPassword == NULL) {
458e1dd0a2fSth 				exit(CLIENT_ERR_FAIL);
459e1dd0a2fSth 			}
460e1dd0a2fSth 			break;
461dd1104fbSMichen Chang 		case 'z':
462dd1104fbSMichen Chang 			if (optlist->adminPassword != NULL) {
463dd1104fbSMichen Chang 				(void) fprintf(stderr,
464dd1104fbSMichen Chang 				    gettext("The -a adminPassword option is "
465dd1104fbSMichen Chang 				    "mutually exclusive of -z. "
466dd1104fbSMichen Chang 				    "-a adminPassword is ignored.\n"));
467dd1104fbSMichen Chang 			}
468dd1104fbSMichen Chang 			optlist->adminPassword = readPwd(optarg);
469dd1104fbSMichen Chang 			if (optlist->adminPassword == NULL) {
470dd1104fbSMichen Chang 				exit(CLIENT_ERR_FAIL);
471dd1104fbSMichen Chang 			}
472dd1104fbSMichen Chang 			break;
4737c478bd9Sstevel@tonic-gate 		case EOF:
4747c478bd9Sstevel@tonic-gate 			if (strcmp(argv[optind], "init") == 0) {
4757c478bd9Sstevel@tonic-gate 				op_init = 1;
4767c478bd9Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "manual") == 0) {
4777c478bd9Sstevel@tonic-gate 				op_manual = 1;
4787c478bd9Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "mod") == 0) {
4797c478bd9Sstevel@tonic-gate 				op_mod = 1;
4807c478bd9Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "list") == 0) {
4817c478bd9Sstevel@tonic-gate 				op_list = 1;
4827c478bd9Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "uninit") == 0) {
4837c478bd9Sstevel@tonic-gate 				op_uninit = 1;
4847c478bd9Sstevel@tonic-gate 			} else if (strcmp(argv[optind], "genprofile") == 0) {
4857c478bd9Sstevel@tonic-gate 				gen = 1;
4867c478bd9Sstevel@tonic-gate 				op_genprofile = 1;
4877c478bd9Sstevel@tonic-gate 			} else if (optind == argc-1) {
4887c478bd9Sstevel@tonic-gate 				retcode = clientSetParam(
489e1dd0a2fSth 				    optlist,
490e1dd0a2fSth 				    NS_LDAP_SERVERS_P,
491e1dd0a2fSth 				    argv[optind]);	/* ipAddr */
4927c478bd9Sstevel@tonic-gate 				if (retcode != CLIENT_SUCCESS) {
4937c478bd9Sstevel@tonic-gate 					CLIENT_FPRINTF(
494e1dd0a2fSth 					    stderr,
495e1dd0a2fSth 					    gettext("Error (%d) setting "
496e1dd0a2fSth 					    "serverList param.\n"),
497e1dd0a2fSth 					    retcode);
4987c478bd9Sstevel@tonic-gate 					usage();
4997c478bd9Sstevel@tonic-gate 					exit(CLIENT_ERR_FAIL);
5007c478bd9Sstevel@tonic-gate 				}
5017c478bd9Sstevel@tonic-gate 			} else {
5027c478bd9Sstevel@tonic-gate 				CLIENT_FPUTS(
503e1dd0a2fSth 				    gettext("Error parsing "
504e1dd0a2fSth 				    "command line\n"),
505e1dd0a2fSth 				    stderr);
5067c478bd9Sstevel@tonic-gate 				usage();
5077c478bd9Sstevel@tonic-gate 				exit(CLIENT_ERR_FAIL);
5087c478bd9Sstevel@tonic-gate 			}
5097c478bd9Sstevel@tonic-gate 			optind++;	/* get past the verb and keep trying */
5107c478bd9Sstevel@tonic-gate 			break;
5117c478bd9Sstevel@tonic-gate 		/* Backwards compatibility to support system install */
5127c478bd9Sstevel@tonic-gate 		case 'I':
5137c478bd9Sstevel@tonic-gate 			sysid_install = B_TRUE;
5147c478bd9Sstevel@tonic-gate 			op_init = 1;
5157c478bd9Sstevel@tonic-gate 			mode_quiet = 1;
5167c478bd9Sstevel@tonic-gate 			break;
5177c478bd9Sstevel@tonic-gate 		case '?':
5187c478bd9Sstevel@tonic-gate 			usage();
5197c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(gettext("\nOr\n\n"), stderr);
5207c478bd9Sstevel@tonic-gate 			gen = 1;
5217c478bd9Sstevel@tonic-gate 			usage();
5227c478bd9Sstevel@tonic-gate 			exit(CLIENT_ERR_FAIL);
5237c478bd9Sstevel@tonic-gate 			break;
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	if ((getuid() != 0) && (!op_genprofile)) {
5297c478bd9Sstevel@tonic-gate 		(void) puts(
530e1dd0a2fSth 		    "You must be root (SuperUser) to run this command.");
5317c478bd9Sstevel@tonic-gate 		usage();
5327c478bd9Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate /*
5367c478bd9Sstevel@tonic-gate  *	All command line arguments are finished being parsed now
5377c478bd9Sstevel@tonic-gate  */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /* *** Do semantic checking here *** */
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate /* if gen and no no searchBase then err */
5427c478bd9Sstevel@tonic-gate 	if (gen && !optlist->defaultSearchBase) {
5437c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
544e1dd0a2fSth 		    gettext("ldapclient: Missing required attrName "
545e1dd0a2fSth 		    "defaultSearchBase\n"),
546e1dd0a2fSth 		    stderr);
5477c478bd9Sstevel@tonic-gate 		usage();
5487c478bd9Sstevel@tonic-gate 		clientopts_free(optlist);
5497c478bd9Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate 
552dd1104fbSMichen Chang /*
553dd1104fbSMichen Chang  * if init or manual, and if adminDN is specified then enableShadowUpdate
554dd1104fbSMichen Chang  * must be set to TRUE.
555dd1104fbSMichen Chang  */
556dd1104fbSMichen Chang 	if ((op_init || op_manual) &&
557dd1104fbSMichen Chang 	    (!optlist->enableShadowUpdate ||
558dd1104fbSMichen Chang 	    strcasecmp(optlist->enableShadowUpdate, "TRUE") != 0) &&
559dd1104fbSMichen Chang 	    (optlist->adminDN || optlist->adminPassword)) {
560dd1104fbSMichen Chang 		CLIENT_FPUTS(
561dd1104fbSMichen Chang 		    gettext("ldapclient: adminDN and adminPassword must not "
562dd1104fbSMichen Chang 		    "be specified if enableShadowUpdate is not set to TRUE \n"),
563dd1104fbSMichen Chang 		    stderr);
564dd1104fbSMichen Chang 		usage();
565dd1104fbSMichen Chang 		clientopts_free(optlist);
566dd1104fbSMichen Chang 		exit(CLIENT_ERR_FAIL);
567dd1104fbSMichen Chang 	}
568dd1104fbSMichen Chang 
5697c478bd9Sstevel@tonic-gate /* Only one verb can be specified */
5707c478bd9Sstevel@tonic-gate 	if ((op_init + op_manual + op_mod + op_uninit +
571e1dd0a2fSth 	    op_list + op_genprofile) != 1) {
5727c478bd9Sstevel@tonic-gate 		usage();
5737c478bd9Sstevel@tonic-gate 		clientopts_free(optlist);
5747c478bd9Sstevel@tonic-gate 		exit(CLIENT_ERR_FAIL);
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate /* *** We passed semantic checking, so now do the operation *** */
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	if (mode_verbose) {
5807c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr);
5817c478bd9Sstevel@tonic-gate 		dumpargs(optlist);
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate /* handle "ldapclient list" here.  err checking done in func */
5867c478bd9Sstevel@tonic-gate 	if (op_list) {
5877c478bd9Sstevel@tonic-gate 		if (mode_verbose)
5887c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
589e1dd0a2fSth 			    gettext("Handling list option\n"),
590e1dd0a2fSth 			    stderr);
5917c478bd9Sstevel@tonic-gate 		retcode = client_list(optlist);
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate /* handle "ldapclient uninit" here */
5957c478bd9Sstevel@tonic-gate 	if (op_uninit) {
5967c478bd9Sstevel@tonic-gate 		if (mode_verbose)
5977c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
598e1dd0a2fSth 			    gettext("Handling uninit option\n"),
599e1dd0a2fSth 			    stderr);
6007c478bd9Sstevel@tonic-gate 		retcode = client_uninit(optlist);
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate /* handle "ldapclient init" (profile) */
6047c478bd9Sstevel@tonic-gate 	if (op_init) {
6057c478bd9Sstevel@tonic-gate 		if (mode_verbose)
6067c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
607e1dd0a2fSth 			    gettext("Handling init option\n"),
608e1dd0a2fSth 			    stderr);
6097c478bd9Sstevel@tonic-gate 		retcode = client_init(optlist);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate /* handle "genprofile" here */
6137c478bd9Sstevel@tonic-gate 	if (op_genprofile) {
6147c478bd9Sstevel@tonic-gate 		if (mode_verbose)
6157c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
616e1dd0a2fSth 			    gettext("Handling genProfile\n"),
617e1dd0a2fSth 			    stderr);
6187c478bd9Sstevel@tonic-gate 		retcode = client_genProfile(optlist);
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate /* handle "ldapclient manual" here */
6227c478bd9Sstevel@tonic-gate 	if (op_manual) {
6237c478bd9Sstevel@tonic-gate 		if (mode_verbose)
6247c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
625e1dd0a2fSth 			    gettext("Handling manual option\n"),
626e1dd0a2fSth 			    stderr);
6277c478bd9Sstevel@tonic-gate 		retcode = client_manual(optlist);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate /* handle "ldapclient mod" here */
6317c478bd9Sstevel@tonic-gate 	if (op_mod) {
6327c478bd9Sstevel@tonic-gate 		if (mode_verbose)
6337c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
634e1dd0a2fSth 			    gettext("Handling mod option\n"),
635e1dd0a2fSth 			    stderr);
6367c478bd9Sstevel@tonic-gate 		retcode = client_mod(optlist);
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	clientopts_free(optlist);
6407c478bd9Sstevel@tonic-gate 	if ((retcode == CLIENT_SUCCESS) ||
641e1dd0a2fSth 	    (retcode == CLIENT_ERR_FAIL) ||
642e1dd0a2fSth 	    (retcode == CLIENT_ERR_CREDENTIAL))
643cb5caa98Sdjl 		return (retcode);
6447c478bd9Sstevel@tonic-gate 	else
645cb5caa98Sdjl 		return (CLIENT_ERR_FAIL);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate static int
client_list(clientopts_t * arglist)6497c478bd9Sstevel@tonic-gate client_list(clientopts_t *arglist)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
6527c478bd9Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	if (num_args(arglist) > 0) {
6557c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
656e1dd0a2fSth 		    gettext("No args supported with \"list\" option\n"),
657e1dd0a2fSth 		    stderr);
6587c478bd9Sstevel@tonic-gate 		usage();
6597c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);	/* exit code here ? */
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 	if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) {
6627c478bd9Sstevel@tonic-gate 		retcode = CLIENT_ERR_FAIL;
6637c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
664e1dd0a2fSth 		    gettext("Cannot get print configuration\n"),
665e1dd0a2fSth 		    stderr);
6667c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(errorp->message, stderr);
6677c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
6687c478bd9Sstevel@tonic-gate 		CLIENT_FPUTC('\n', stderr);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	return (retcode);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate static int
client_uninit(clientopts_t * arglist)6757c478bd9Sstevel@tonic-gate client_uninit(clientopts_t *arglist)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
678cb5caa98Sdjl 	ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	if (mode_verbose) {
6817c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
682e1dd0a2fSth 		    gettext("Restoring machine to previous "
683e1dd0a2fSth 		    "configuration state\n"),
684e1dd0a2fSth 		    stderr);
6857c478bd9Sstevel@tonic-gate 	}
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	if (num_args(arglist) > 0) {
6887c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
689e1dd0a2fSth 		    gettext("No args supported with \"uninit\" option\n"),
690e1dd0a2fSth 		    stderr);
6917c478bd9Sstevel@tonic-gate 		usage();
6927c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
695cb5caa98Sdjl 	(void) __ns_ldap_self_gssapi_config(&config);
696cb5caa98Sdjl 
6977c478bd9Sstevel@tonic-gate 	retcode = stop_services(STATE_SAVE);
698cb5caa98Sdjl 
699cb5caa98Sdjl 	if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
700cb5caa98Sdjl 		(void) system("/usr/sbin/cryptoadm enable metaslot");
701cb5caa98Sdjl 
7027c478bd9Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
7037c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
704e1dd0a2fSth 		    gettext("Errors stopping network services.\n"), stderr);
7057c478bd9Sstevel@tonic-gate 		/* restart whatever services we can */
7067c478bd9Sstevel@tonic-gate 		(void) start_services(START_RESET);
7077c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	retcode = recover(STATE_SAVE);
7117c478bd9Sstevel@tonic-gate 	if (retcode != CLIENT_SUCCESS) {
7127c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
713e1dd0a2fSth 		    gettext("Cannot recover the configuration on "
714e1dd0a2fSth 		    "this machine.\n"),
715e1dd0a2fSth 		    stderr);
7167c478bd9Sstevel@tonic-gate 		(void) start_services(START_RESET);
7177c478bd9Sstevel@tonic-gate 	} else {
7187c478bd9Sstevel@tonic-gate 		retcode = start_services(START_UNINIT);
7197c478bd9Sstevel@tonic-gate 		if (retcode != CLIENT_SUCCESS) {
7207c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(
721e1dd0a2fSth 			    gettext("Config restored but problems "
722e1dd0a2fSth 			    "encountered resetting network "
723e1dd0a2fSth 			    "services.\n"),
724e1dd0a2fSth 			    stderr);
7257c478bd9Sstevel@tonic-gate 		}
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	if (retcode == CLIENT_SUCCESS) {
7297c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
730e1dd0a2fSth 		    gettext("System successfully recovered\n"),
731e1dd0a2fSth 		    stderr);
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	return (retcode);
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate /*
7387c478bd9Sstevel@tonic-gate  * The following macro is used to do a __ns_ldap_setParam().
7397c478bd9Sstevel@tonic-gate  * On every call, the return code is checked, and if there was
7407c478bd9Sstevel@tonic-gate  * a problem then the error message is printed, the ldaperr
7417c478bd9Sstevel@tonic-gate  * is freed and we return from the function with the offending
7427c478bd9Sstevel@tonic-gate  * error return code.  This macro keeps us from having to
7437c478bd9Sstevel@tonic-gate  * repeat this code for every call to setParam as was done
7447c478bd9Sstevel@tonic-gate  * in the previous incarnation of ldapclient.
7457c478bd9Sstevel@tonic-gate  *
7467c478bd9Sstevel@tonic-gate  * assumes a "retcode" variable is available for status
7477c478bd9Sstevel@tonic-gate  */
7487c478bd9Sstevel@tonic-gate #define	LDAP_SET_PARAM(argval, argdef)	\
7497c478bd9Sstevel@tonic-gate retcode = 0;	\
7507c478bd9Sstevel@tonic-gate if (NULL != argval) {	\
7517c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *ldaperr;	\
7527c478bd9Sstevel@tonic-gate 	retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr);	\
7537c478bd9Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {	\
7547c478bd9Sstevel@tonic-gate 		if (NULL != ldaperr) {	\
7557c478bd9Sstevel@tonic-gate 			CLIENT_FPUTS(ldaperr->message, stderr);	\
7567c478bd9Sstevel@tonic-gate 			CLIENT_FPUTC('\n', stderr);	\
7577c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&ldaperr);	\
7587c478bd9Sstevel@tonic-gate 		}	\
7597c478bd9Sstevel@tonic-gate 		return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS);	\
7607c478bd9Sstevel@tonic-gate 	}	\
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
763e1dd0a2fSth /*
764e1dd0a2fSth  * The following macro is used to check if an arg has already been set
765e1dd0a2fSth  * and issues an error message, a usage message and then returns an error.
766e1dd0a2fSth  * This was made into a macro to avoid the duplication of this code many
767e1dd0a2fSth  * times in the function below.
768e1dd0a2fSth  */
769e1dd0a2fSth #define	LDAP_CHECK_INVALID(arg, param)	\
770e1dd0a2fSth if (arg) {	\
771e1dd0a2fSth 	CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \
772e1dd0a2fSth 	    "specified\n"), param);	\
773e1dd0a2fSth 	usage();	\
774e1dd0a2fSth 	return (CLIENT_ERR_FAIL);	\
775e1dd0a2fSth }
776e1dd0a2fSth 
7777c478bd9Sstevel@tonic-gate static int
client_manual(clientopts_t * arglist)7787c478bd9Sstevel@tonic-gate client_manual(clientopts_t *arglist)
7797c478bd9Sstevel@tonic-gate {
7807c478bd9Sstevel@tonic-gate 	int counter;
7817c478bd9Sstevel@tonic-gate 	int domain_fp;
7827c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
7837c478bd9Sstevel@tonic-gate 	int ret_copy;
7847c478bd9Sstevel@tonic-gate 	int reset_ret;
7857c478bd9Sstevel@tonic-gate 	int retcode = CLIENT_SUCCESS;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	if (dname == NULL) {
7887c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
789e1dd0a2fSth 		    gettext("Manual failed: System domain not set and "
790e1dd0a2fSth 		    "no domainName specified.\n"),
791e1dd0a2fSth 		    stderr);
7927c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	if (arglist->defaultSearchBase == NULL) {
7967c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
797e1dd0a2fSth 		    gettext("Manual failed: Missing required "
798e1dd0a2fSth 		    "defaultSearchBase attribute.\n"),
799e1dd0a2fSth 		    stderr);
8007c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8017c478bd9Sstevel@tonic-gate 	}
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	if ((arglist->defaultServerList == NULL) &&
804e1dd0a2fSth 	    (arglist->preferredServerList == NULL)) {
8057c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
806e1dd0a2fSth 		    gettext("Manual failed: Missing required "
807e1dd0a2fSth 		    "defaultServerList or preferredServerList "
808e1dd0a2fSth 		    "attribute.\n"),
809e1dd0a2fSth 		    stderr);
8107c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	if (arglist->profileTTL != NULL) {
8147c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
815e1dd0a2fSth 		    gettext("Manual aborted: profileTTL is not supported "
816e1dd0a2fSth 		    "in manual mode.\n"),
817e1dd0a2fSth 		    stderr);
8187c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8197c478bd9Sstevel@tonic-gate 	}
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	if (arglist->profileName != NULL) {
8227c478bd9Sstevel@tonic-gate 		CLIENT_FPUTS(
823e1dd0a2fSth 		    gettext("Manual aborted: profileName is not supported "
824e1dd0a2fSth 		    "in manual mode.\n"),
825e1dd0a2fSth 		    stderr);
8267c478bd9Sstevel@tonic-gate 		return (CLIENT_ERR_FAIL);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
829