ldapclient.c revision e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ldapclient command. To make (initiailize) or uninitialize a machines as
* and LDAP client. This command MUST be run as root (or it will simply exit).
*
* -I Install. No file_backup/recover for installing only (no doc).
*
* init Initialze (create) an LDAP client from a profile stored
* in a directory-server.
* manual Initialze (create) an LDAP client by hand (-file option
* reads from file).
* mod Modify the LDAP client configuration on this machine by hand.
* list List the contents of the LDAP client cache files.
* uninit Uninitialize this machine.
*
* -v Verbose flag.
* -q Quiet flag (mutually exclusive with -v).
*
* -a attrName=attrVal
* <attrName> can be one of the following:
*
* attributeMap
* Attribute map. Can be multiple instances of this option.
* (no former option)
* authenticationMethod
* Authentication method (formerly -a)
* bindTimeLimit
* Bind time limit. (no former option)
* certificatePath
* Path to certificates used for secure bind (no former option)
* credentialLevel
* Client credential level (no former option)
* defaultServerList
* Default server (no former option) Refer to DUA Config
* Schema draft.
* defaultSearchBase
* Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b)
* defaultSearchScope
* Search scope. (formerly -s)
* domainName
* Hosts lookup domain (DNS) Ex. eng.sun.com (formerly -d)
* followReferrals
* Search dereference. followref or noref (default followref)
* (formerly -r)
* objectclassMap
* Objectclass map. Can be multiple instances of this option.
* (no former option)
* preferredServerList
* Server preference list. Comma ',' seperated list of IPaddr.
* (formerly -p)
* profileName
* Profile name to use for init (ldapclient) or
* generate (gen_profile). (formerly -P)
* profileTTL
* Client info TTL. If set to 0 this information will not be
* automatically updated by the ldap_cachemgr(1M).
* (formerly -e)
* proxyDN
* Binding DN. Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com
* (formerly -D)
* proxyPassword
* Client password not needed for authentication "none".
* (formerly -w)
* searchTimeLimit
* Timeout value. (formerly -o)
* serviceSearchDescriptor
* Service search scope. (no former option)
* serviceAuthenticationMethod
* Service authenticaion method (no former option)
* serviceCredentialLevel
* Service credential level (no former option)
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <time.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#include <fcntl.h>
#include <xti.h>
#include <strings.h>
#include <limits.h>
#include <locale.h>
#include <syslog.h>
#include <libscf.h>
#include <assert.h>
#include "standalone.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SUNW_OST_OSCMD"
#endif
/* error codes */
/* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */
#define CLIENT_SUCCESS 0
#define CLIENT_ERR_PARSE -1
#define CLIENT_ERR_FAIL 1
#define CLIENT_ERR_CREDENTIAL 2
#define CLIENT_ERR_MEMORY 3
#define CLIENT_ERR_RESTORE 4
#define CLIENT_ERR_RENAME 5
#define CLIENT_ERR_RECOVER 6
#define CLIENT_ERR_TIMEDOUT 7
#define CLIENT_ERR_MAINTENANCE 8
/* Reset flag for start_services() */
#define START_INIT 1
#define START_RESET 2
#define START_UNINIT 3
/* Reset flag for stop_services() */
#define STATE_NOSAVE 0
#define STATE_SAVE 1
/* files to (possibiliy) restore */
#define LDAP_RESTORE_DIR "/var/ldap/restore"
#define DOMAINNAME_DIR "/etc"
#define DOMAINNAME_FILE "defaultdomain"
#define DOMAINNAME DOMAINNAME_DIR "/" DOMAINNAME_FILE
#define DOMAINNAME_BACK LDAP_RESTORE_DIR "/" DOMAINNAME_FILE
#define NSSWITCH_DIR "/etc"
#define NSSWITCH_FILE "nsswitch.conf"
#define NSSWITCH_CONF NSSWITCH_DIR "/" NSSWITCH_FILE
#define NSSWITCH_BACK LDAP_RESTORE_DIR "/" NSSWITCH_FILE
#define NSSWITCH_LDAP "/etc/nsswitch.ldap"
#define NIS_COLDSTART_DIR "/var/nis"
#define NIS_COLDSTART_FILE "NIS_COLD_START"
#define NIS_COLDSTART NIS_COLDSTART_DIR "/" NIS_COLDSTART_FILE
#define NIS_COLDSTART_BACK LDAP_RESTORE_DIR "/" NIS_COLDSTART_FILE
#define YP_BIND_DIR "/var/yp/binding"
/* Define the service FMRIs */
#define SENDMAIL_FMRI "network/smtp:sendmail"
#define NSCD_FMRI "system/name-service-cache:default"
#define AUTOFS_FMRI "system/filesystem/autofs:default"
#define LDAP_FMRI "network/ldap/client:default"
#define NISD_FMRI "network/rpc/nisplus:default"
#define YP_FMRI "network/nis/client:default"
#define NS_MILESTONE_FMRI "milestone/name-services:default"
/* Define flags for checking if services were enabled */
#define SENDMAIL_ON 0x1
#define NSCD_ON 0x10
#define AUTOFS_ON 0x100
#define CMD_DOMAIN_START "/usr/bin/domainname"
/* Command to copy files */
#define CMD_CP "/bin/cp -f"
#define CMD_MV "/bin/mv -f"
#define CMD_RM "/bin/rm -f"
#define TO_DEV_NULL " >/dev/null 2>&1"
/* Files that need to be just removed */
#define NIS_PRIVATE_CACHE "/var/nis/.NIS_PRIVATE_DIRCACHE"
#define NIS_SHARED_CACHE "/var/nis/NIS_SHARED_DIRCACHE"
#define NIS_CLIENT_INFO "/var/nis/client_info"
#define LDAP_CACHE_LOG "/var/ldap/cachemgr.log"
/* Output defines to supress if quiet mode set */
#define CLIENT_FPUTS if (!mode_quiet) (void) fputs
#define CLIENT_FPRINTF if (!mode_quiet) (void) fprintf
#define CLIENT_FPUTC if (!mode_quiet) (void) fputc
#define restart_service(fmri, waitflag)\
do_service(fmri, waitflag, RESTART_SERVICE,\
SCF_STATE_STRING_ONLINE)
#define start_service(fmri, waitflag) \
do_service(fmri, waitflag, START_SERVICE,\
SCF_STATE_STRING_ONLINE)
#define disable_service(fmri, waitflag) \
do_service(fmri, waitflag, STOP_SERVICE,\
SCF_STATE_STRING_DISABLED)
/*
* There isn't a domainName defined as a param, so we set a value here
* (1001) should be big enough
*/
#define LOCAL_DOMAIN_P 1001
#define START_SERVICE 1
#define STOP_SERVICE 2
#define RESTART_SERVICE 3
#define DEFAULT_TIMEOUT 60000000
#define INIT_WAIT_USECS 50000
/* Used to turn off profile checking */
#define CACHETTL_OFF "0"
/* Globals */
static char *cmd;
static char *dname = NULL;
static char dname_buf[BUFSIZ];
static boolean_t sysid_install = B_FALSE;
static int mode_verbose = 0;
static int mode_quiet = 0;
static int gen = 0;
static int gStartLdap = 0;
static int gStartYp = 0;
static int gStartNisd = 0;
static int enableFlag = 0;
/* multival_t is used to hold params that can have more than one value */
typedef struct {
int count;
char **optlist;
} multival_t;
static multival_t *multival_new();
static int multival_add(multival_t *list, char *opt);
static void multival_free(multival_t *list);
/*
* clientopts_t is used to hold and pass around the param values from
* the cmd line
*/
typedef struct {
multival_t *attributeMap;
char *authenticationMethod;
char *bindTimeLimit;
char *certificatePath;
char *credentialLevel;
char *defaultSearchBase;
char *defaultServerList;
char *domainName;
char *followReferrals;
multival_t *objectclassMap;
char *preferredServerList;
char *profileName;
char *profileTTL;
char *proxyDN;
char *proxyPassword;
char *bindDN;
char *bindPasswd;
char *defaultSearchScope;
char *searchTimeLimit;
multival_t *serviceAuthenticationMethod;
multival_t *serviceCredentialLevel;
multival_t *serviceSearchDescriptor;
} clientopts_t;
static clientopts_t *clientopts_new();
static void clientopts_free(clientopts_t *list);
extern ns_ldap_error_t *__ns_ldap_print_config(int);
extern void __ns_ldap_default_config();
extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
/* Function prototypes (these could be static) */
static void usage(void);
static int credCheck(clientopts_t *arglist);
static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal);
static int parseParam(char *param, char **paramVal);
static void dumpargs(clientopts_t *arglist);
static int num_args(clientopts_t *arglist);
static int file_backup(void);
static int recover(int saveState);
static int mod_backup(void);
static int mod_recover(void);
static void mod_cleanup(void);
static int client_list(clientopts_t *arglist);
static int client_manual(clientopts_t *arglist);
static int client_mod(clientopts_t *arglist);
static int client_uninit(clientopts_t *arglist);
static int client_genProfile(clientopts_t *arglist);
static int client_init(clientopts_t *arglist);
static int file_move(const char *from, const char *to);
static int start_services(int flag);
static int stop_services(int saveState);
static boolean_t is_service(const char *fmri, const char *state);
static int wait_till(const char *fmri, const char *state, useconds_t max,
const char *what, boolean_t check_maint);
static int do_service(const char *fmri, boolean_t waitflag, int dowhat,
const char *state);
static useconds_t get_timeout_value(int dowhat, const char *fmri,
useconds_t default_val);
int
main(int argc, char **argv)
{
char *ret_locale, *ret_textdomain;
int retcode;
int paramFlag;
char *attrVal;
int sysinfostatus;
clientopts_t *optlist = NULL;
int op_manual = 0, op_mod = 0, op_uninit = 0;
int op_list = 0, op_init = 0, op_genprofile = 0;
extern char *optarg;
extern int optind;
int option;
ret_locale = setlocale(LC_ALL, "");
if (ret_locale == NULL) {
CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr);
}
ret_textdomain = textdomain(TEXT_DOMAIN);
if (ret_textdomain == NULL) {
CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr);
}
openlog("ldapclient", LOG_PID, LOG_USER);
/* get name that invoked us */
if (cmd = strrchr(argv[0], '/'))
++cmd;
else
cmd = argv[0];
sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ);
if (0 < sysinfostatus)
dname = &dname_buf[0];
optlist = clientopts_new();
if (optlist == NULL) {
CLIENT_FPUTS(
gettext("Error getting optlist (malloc fail)\n"),
stderr);
exit(CLIENT_ERR_FAIL);
}
optind = 1;
while (optind < argc) {
option = getopt(argc, argv, "vqa:ID:w:j:y:");
switch (option) {
case 'v':
mode_verbose = 1;
break;
case 'q':
mode_quiet = 1;
break;
case 'a':
attrVal = NULL;
paramFlag = parseParam(optarg, &attrVal);
if (paramFlag == CLIENT_ERR_PARSE) {
CLIENT_FPRINTF(stderr,
gettext("Unrecognized "
"parameter \"%s\"\n"),
optarg);
usage();
exit(CLIENT_ERR_FAIL);
}
if (paramFlag == NS_LDAP_BINDPASSWD_P &&
optlist->proxyPassword != NULL) {
(void) fprintf(stderr,
gettext("The -a proxyPassword option is "
"mutually exclusive of -y. "
"-a proxyPassword is ignored.\n"));
break;
}
retcode = clientSetParam(optlist, paramFlag, attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(
stderr,
gettext("Error (%d) setting "
"param \"%s\"\n"),
retcode, optarg);
usage();
exit(CLIENT_ERR_FAIL);
}
break;
case 'D':
optlist->bindDN = strdup(optarg);
break;
case 'w':
if (optlist->bindPasswd != NULL) {
CLIENT_FPRINTF(stderr,
gettext("The -w option is mutually "
"exclusive of -j. -w is ignored."));
break;
}
if (optarg[0] == '-' && optarg[1] == '\0') {
/* Ask for a password later */
break;
}
optlist->bindPasswd = strdup(optarg);
break;
case 'j':
if (optlist->bindPasswd != NULL) {
(void) fprintf(stderr,
gettext("The -w option is mutually "
"exclusive of -j. -w is ignored.\n"));
free(optlist->bindPasswd);
}
optlist->bindPasswd = readPwd(optarg);
if (optlist->bindPasswd == NULL) {
exit(CLIENT_ERR_FAIL);
}
break;
case 'y':
if (optlist->proxyPassword != NULL) {
(void) fprintf(stderr,
gettext("The -a proxyPassword option is "
"mutually exclusive of -y. "
"-a proxyPassword is ignored.\n"));
free(optlist->proxyPassword);
}
optlist->proxyPassword = readPwd(optarg);
if (optlist->proxyPassword == NULL) {
exit(CLIENT_ERR_FAIL);
}
break;
case EOF:
if (strcmp(argv[optind], "init") == 0) {
op_init = 1;
} else if (strcmp(argv[optind], "manual") == 0) {
op_manual = 1;
} else if (strcmp(argv[optind], "mod") == 0) {
op_mod = 1;
} else if (strcmp(argv[optind], "list") == 0) {
op_list = 1;
} else if (strcmp(argv[optind], "uninit") == 0) {
op_uninit = 1;
} else if (strcmp(argv[optind], "genprofile") == 0) {
gen = 1;
op_genprofile = 1;
} else if (optind == argc-1) {
retcode = clientSetParam(
optlist,
NS_LDAP_SERVERS_P,
argv[optind]); /* ipAddr */
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(
stderr,
gettext("Error (%d) setting "
"serverList param.\n"),
retcode);
usage();
exit(CLIENT_ERR_FAIL);
}
} else {
CLIENT_FPUTS(
gettext("Error parsing "
"command line\n"),
stderr);
usage();
exit(CLIENT_ERR_FAIL);
}
optind++; /* get past the verb and keep trying */
break;
/* Backwards compatibility to support system install */
case 'I':
sysid_install = B_TRUE;
op_init = 1;
mode_quiet = 1;
break;
case '?':
usage();
CLIENT_FPUTS(gettext("\nOr\n\n"), stderr);
gen = 1;
usage();
exit(CLIENT_ERR_FAIL);
break;
}
}
if ((getuid() != 0) && (!op_genprofile)) {
(void) puts(
"You must be root (SuperUser) to run this command.");
usage();
exit(CLIENT_ERR_FAIL);
}
/*
* All command line arguments are finished being parsed now
*/
/* *** Do semantic checking here *** */
/* if gen and no no searchBase then err */
if (gen && !optlist->defaultSearchBase) {
CLIENT_FPUTS(
gettext("ldapclient: Missing required attrName "
"defaultSearchBase\n"),
stderr);
usage();
clientopts_free(optlist);
exit(CLIENT_ERR_FAIL);
}
/* Only one verb can be specified */
if ((op_init + op_manual + op_mod + op_uninit +
op_list + op_genprofile) != 1) {
usage();
clientopts_free(optlist);
exit(CLIENT_ERR_FAIL);
}
/* *** We passed semantic checking, so now do the operation *** */
if (mode_verbose) {
CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr);
dumpargs(optlist);
}
/* handle "ldapclient list" here. err checking done in func */
if (op_list) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling list option\n"),
stderr);
retcode = client_list(optlist);
}
/* handle "ldapclient uninit" here */
if (op_uninit) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling uninit option\n"),
stderr);
retcode = client_uninit(optlist);
}
/* handle "ldapclient init" (profile) */
if (op_init) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling init option\n"),
stderr);
retcode = client_init(optlist);
}
/* handle "genprofile" here */
if (op_genprofile) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling genProfile\n"),
stderr);
retcode = client_genProfile(optlist);
}
/* handle "ldapclient manual" here */
if (op_manual) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling manual option\n"),
stderr);
retcode = client_manual(optlist);
}
/* handle "ldapclient mod" here */
if (op_mod) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("Handling mod option\n"),
stderr);
retcode = client_mod(optlist);
}
clientopts_free(optlist);
if ((retcode == CLIENT_SUCCESS) ||
(retcode == CLIENT_ERR_FAIL) ||
(retcode == CLIENT_ERR_CREDENTIAL))
return (retcode);
else
return (CLIENT_ERR_FAIL);
}
static int
client_list(clientopts_t *arglist)
{
ns_ldap_error_t *errorp;
int retcode = CLIENT_SUCCESS;
if (num_args(arglist) > 0) {
CLIENT_FPUTS(
gettext("No args supported with \"list\" option\n"),
stderr);
usage();
return (CLIENT_ERR_FAIL); /* exit code here ? */
}
if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) {
retcode = CLIENT_ERR_FAIL;
CLIENT_FPUTS(
gettext("Cannot get print configuration\n"),
stderr);
CLIENT_FPUTS(errorp->message, stderr);
(void) __ns_ldap_freeError(&errorp);
CLIENT_FPUTC('\n', stderr);
}
return (retcode);
}
static int
client_uninit(clientopts_t *arglist)
{
int retcode = CLIENT_SUCCESS;
ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
if (mode_verbose) {
CLIENT_FPUTS(
gettext("Restoring machine to previous "
"configuration state\n"),
stderr);
}
if (num_args(arglist) > 0) {
CLIENT_FPUTS(
gettext("No args supported with \"uninit\" option\n"),
stderr);
usage();
return (CLIENT_ERR_FAIL);
}
(void) __ns_ldap_self_gssapi_config(&config);
retcode = stop_services(STATE_SAVE);
if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
(void) system("/usr/sbin/cryptoadm enable metaslot");
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Errors stopping network services.\n"), stderr);
/* restart whatever services we can */
(void) start_services(START_RESET);
return (CLIENT_ERR_FAIL);
}
retcode = recover(STATE_SAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Cannot recover the configuration on "
"this machine.\n"),
stderr);
(void) start_services(START_RESET);
} else {
retcode = start_services(START_UNINIT);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Config restored but problems "
"encountered resetting network "
"services.\n"),
stderr);
}
}
if (retcode == CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("System successfully recovered\n"),
stderr);
}
return (retcode);
}
/*
* The following macro is used to do a __ns_ldap_setParam().
* On every call, the return code is checked, and if there was
* a problem then the error message is printed, the ldaperr
* is freed and we return from the function with the offending
* error return code. This macro keeps us from having to
* repeat this code for every call to setParam as was done
* in the previous incarnation of ldapclient.
*
* assumes a "retcode" variable is available for status
*/
#define LDAP_SET_PARAM(argval, argdef) \
retcode = 0; \
if (NULL != argval) { \
ns_ldap_error_t *ldaperr; \
retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr); \
if (retcode != NS_LDAP_SUCCESS) { \
if (NULL != ldaperr) { \
CLIENT_FPUTS(ldaperr->message, stderr); \
CLIENT_FPUTC('\n', stderr); \
(void) __ns_ldap_freeError(&ldaperr); \
} \
return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS); \
} \
}
/*
* The following macro is used to check if an arg has already been set
* and issues an error message, a usage message and then returns an error.
* This was made into a macro to avoid the duplication of this code many
* times in the function below.
*/
#define LDAP_CHECK_INVALID(arg, param) \
if (arg) { \
CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \
"specified\n"), param); \
usage(); \
return (CLIENT_ERR_FAIL); \
}
static int
client_manual(clientopts_t *arglist)
{
int counter;
int domain_fp;
ns_ldap_error_t *errorp;
int ret_copy;
int reset_ret;
int retcode = CLIENT_SUCCESS;
if (dname == NULL) {
CLIENT_FPUTS(
gettext("Manual failed: System domain not set and "
"no domainName specified.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (arglist->defaultSearchBase == NULL) {
CLIENT_FPUTS(
gettext("Manual failed: Missing required "
"defaultSearchBase attribute.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if ((arglist->defaultServerList == NULL) &&
(arglist->preferredServerList == NULL)) {
CLIENT_FPUTS(
gettext("Manual failed: Missing required "
"defaultServerList or preferredServerList "
"attribute.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (arglist->profileTTL != NULL) {
CLIENT_FPUTS(
gettext("Manual aborted: profileTTL is not supported "
"in manual mode.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (arglist->profileName != NULL) {
CLIENT_FPUTS(
gettext("Manual aborted: profileName is not supported "
"in manual mode.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
__ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */
__ns_ldap_default_config();
/* Set version to latest (not version 1) */
LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
/* Set profileTTL to 0 since NO profile on manual */
LDAP_SET_PARAM(CACHETTL_OFF, NS_LDAP_CACHETTL_P);
/* Set additional valid params from command line */
LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
for (counter = 0;
counter < arglist->serviceAuthenticationMethod->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceAuthenticationMethod->optlist[counter],
NS_LDAP_SERVICE_AUTH_METHOD_P);
}
for (counter = 0;
counter < arglist->serviceCredentialLevel->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceCredentialLevel->optlist[counter],
NS_LDAP_SERVICE_CRED_LEVEL_P);
}
for (counter = 0;
counter < arglist->objectclassMap->count;
counter++) {
LDAP_SET_PARAM(arglist->objectclassMap->optlist[counter],
NS_LDAP_OBJECTCLASSMAP_P);
}
for (counter = 0; counter < arglist->attributeMap->count; counter++) {
LDAP_SET_PARAM(arglist->attributeMap->optlist[counter],
NS_LDAP_ATTRIBUTEMAP_P);
}
for (counter = 0;
counter < arglist->serviceSearchDescriptor->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceSearchDescriptor->optlist[counter],
NS_LDAP_SERVICE_SEARCH_DESC_P);
}
retcode = credCheck(arglist);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Error in setting up credentials\n"),
stderr);
return (retcode);
}
if (mode_verbose)
CLIENT_FPUTS(
gettext("About to modify this machines "
"configuration by writing the files\n"),
stderr);
/* get ready to start playing with files */
retcode = stop_services(STATE_SAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Errors stopping network services.\n"), stderr);
return (CLIENT_ERR_FAIL);
}
/* Save orig versions of files */
retcode = file_backup();
if (retcode == CLIENT_ERR_RESTORE) {
CLIENT_FPUTS(
gettext("System not in state to enable ldap client.\n"),
stderr);
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (retcode);
} else if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Save of system configuration failed! "
"Attempting recovery.\n"),
stderr);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (retcode);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (retcode);
}
/* Dump new files */
errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
if (errorp != NULL) {
CLIENT_FPRINTF(stderr,
gettext("%s manual: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (retcode);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
(void) __ns_ldap_freeError(&errorp);
return (CLIENT_ERR_FAIL);
}
/* if (credargs(arglist)) */
errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
if (errorp != NULL) {
CLIENT_FPRINTF(stderr,
gettext("%s init: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (retcode);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
(void) __ns_ldap_freeError(&errorp);
return (CLIENT_ERR_FAIL);
}
ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
if (ret_copy != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d copying (%s) -> (%s)\n"),
ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
(void) write(domain_fp, dname, strlen(dname));
(void) write(domain_fp, "\n", 1);
(void) close(domain_fp);
retcode = start_services(START_INIT);
if (retcode == CLIENT_SUCCESS) {
CLIENT_FPUTS(gettext("System successfully configured\n"),
stderr);
} else {
CLIENT_FPUTS(gettext("Error resetting system.\n"
"Recovering old system settings.\n"), stderr),
/* stop any started services for recover */
/* don't stomp on history of saved services state */
reset_ret = stop_services(STATE_NOSAVE);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"stopping services during reset\n"),
reset_ret);
/* Coninue and try to recover what we can */
}
reset_ret = recover(STATE_NOSAVE);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"recovering service files during "
"reset\n"), reset_ret);
/* Continue and start what we can */
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
}
return (retcode);
}
static int
client_mod(clientopts_t *arglist)
{
int counter;
int domain_fp;
ns_ldap_error_t *errorp;
int reset_ret;
int retcode = CLIENT_SUCCESS;
__ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */
if ((errorp = __ns_ldap_LoadConfiguration()) != NULL) {
CLIENT_FPUTS(gettext("Cannot get load configuration\n"),
stderr);
CLIENT_FPUTS(errorp->message, stderr);
CLIENT_FPUTC('\n', stderr);
(void) __ns_ldap_freeError(&errorp);
return (CLIENT_ERR_FAIL);
}
if (arglist->profileTTL != NULL) {
CLIENT_FPUTS(
gettext("Mod aborted: profileTTL modification is "
"not allowed in mod mode.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (arglist->profileName != NULL) {
CLIENT_FPUTS(
gettext("Mod aborted: profileName modification is "
"not allowed. If you want to use profiles "
"generate one with genProfile and load it "
"on the server with ldapadd.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
/* Set additional valid params from command line */
LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
for (counter = 0;
counter < arglist->serviceAuthenticationMethod->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceAuthenticationMethod->optlist[counter],
NS_LDAP_SERVICE_AUTH_METHOD_P);
}
for (counter = 0;
counter < arglist->serviceCredentialLevel->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceCredentialLevel->optlist[counter],
NS_LDAP_SERVICE_CRED_LEVEL_P);
}
for (counter = 0;
counter < arglist->objectclassMap->count;
counter++) {
LDAP_SET_PARAM(
arglist->objectclassMap->optlist[counter],
NS_LDAP_OBJECTCLASSMAP_P);
}
for (counter = 0;
counter < arglist->attributeMap->count;
counter++) {
LDAP_SET_PARAM(
arglist->attributeMap->optlist[counter],
NS_LDAP_ATTRIBUTEMAP_P);
}
for (counter = 0;
counter < arglist->serviceSearchDescriptor->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceSearchDescriptor->optlist[counter],
NS_LDAP_SERVICE_SEARCH_DESC_P);
}
retcode = credCheck(arglist);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Error in setting up credentials\n"),
stderr);
return (retcode);
}
if (mode_verbose)
CLIENT_FPUTS(
gettext("About to modify this machines configuration "
"by writing the files\n"),
stderr);
/* get ready to start playing with files */
retcode = stop_services(STATE_SAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Errors stopping network services.\n"), stderr);
return (CLIENT_ERR_FAIL);
}
/* Temporarily save orig versions of files */
retcode = mod_backup();
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Unable to backup the ldap client files!\n"),
stderr);
return (retcode);
}
/* Dump new files */
errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
if (errorp != NULL) {
CLIENT_FPRINTF(stderr,
gettext("%s mod: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = mod_recover();
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
}
(void) __ns_ldap_freeError(&errorp);
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
/* if (credargs(arglist)) */
errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
if (errorp != NULL) {
CLIENT_FPRINTF(stderr,
gettext("%s mod: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = mod_recover();
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
}
(void) __ns_ldap_freeError(&errorp);
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
retcode = mod_recover();
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed! Machine needs to be "
"fixed!\n"),
stderr);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
(void) write(domain_fp, dname, strlen(dname));
(void) write(domain_fp, "\n", 1);
(void) close(domain_fp);
retcode = start_services(START_INIT);
if (retcode == CLIENT_SUCCESS) {
CLIENT_FPUTS(gettext("System successfully configured\n"),
stderr);
} else {
CLIENT_FPUTS(gettext("Error resetting system.\n"
"Recovering old system settings.\n"), stderr),
/* stop any started services for recover */
/* don't stomp on history of saved services state */
reset_ret = stop_services(STATE_NOSAVE);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"stopping services during reset\n"),
reset_ret);
/* Coninue and try to recover what we can */
}
reset_ret = mod_recover();
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"recovering service files during "
"reset\n"), reset_ret);
/* Continue and start what we can */
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
}
/* Cleanup temporary files created by mod_backup() */
mod_cleanup();
return (retcode);
}
static int
client_genProfile(clientopts_t *arglist)
{
int counter;
int retcode; /* required for LDAP_SET_PARAM macro */
ns_ldap_error_t *errorp;
if (mode_verbose)
CLIENT_FPUTS(gettext("About to generate a profile\n"), stderr);
/* *** Check for invalid args *** */
LDAP_CHECK_INVALID(arglist->proxyDN, "proxyDN");
LDAP_CHECK_INVALID(arglist->proxyPassword, "proxyPassword");
LDAP_CHECK_INVALID(arglist->certificatePath, "certificatePath");
LDAP_CHECK_INVALID(arglist->domainName, "domainName");
LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
/* *** End check for invalid args *** */
if (arglist->profileName == NULL) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("No profile specified. "
"Using \"default\"\n"),
stderr);
arglist->profileName = "default";
}
__ns_ldap_setServer(TRUE);
__ns_ldap_default_config();
/* Set version to latest (not version 1) */
LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
/* Set additional valid params from command line */
LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
for (counter = 0;
counter < arglist->serviceAuthenticationMethod->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceAuthenticationMethod->optlist[counter],
NS_LDAP_SERVICE_AUTH_METHOD_P);
}
for (counter = 0;
counter < arglist->serviceCredentialLevel->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceCredentialLevel->optlist[counter],
NS_LDAP_SERVICE_CRED_LEVEL_P);
}
for (counter = 0;
counter < arglist->objectclassMap->count;
counter++) {
LDAP_SET_PARAM(
arglist->objectclassMap->optlist[counter],
NS_LDAP_OBJECTCLASSMAP_P);
}
for (counter = 0;
counter < arglist->attributeMap->count;
counter++) {
LDAP_SET_PARAM(
arglist->attributeMap->optlist[counter],
NS_LDAP_ATTRIBUTEMAP_P);
}
for (counter = 0;
counter < arglist->serviceSearchDescriptor->count;
counter++) {
LDAP_SET_PARAM(
arglist->serviceSearchDescriptor->optlist[counter],
NS_LDAP_SERVICE_SEARCH_DESC_P);
}
errorp = __ns_ldap_DumpLdif(NULL);
if (errorp != NULL) {
CLIENT_FPUTS(errorp->message, stderr);
CLIENT_FPUTC('\n', stderr);
(void) __ns_ldap_freeError(&errorp);
return (CLIENT_ERR_FAIL);
}
return (CLIENT_SUCCESS);
}
/* INET6_ADDRSTRLEN + ":" + <5-digit port> + some round-up */
#define MAX_HOSTADDR_LEN (INET6_ADDRSTRLEN + 6 + 12)
static int
client_init(clientopts_t *arglist)
{
int profile_fp;
int retcode = CLIENT_SUCCESS;
ns_ldap_error_t *errorp;
int reset_ret;
int ret_copy;
ns_standalone_conf_t cfg = standaloneDefaults;
ns_auth_t auth = {NS_LDAP_AUTH_NONE,
NS_LDAP_TLS_NONE,
NS_LDAP_SASL_NONE,
NS_LDAP_SASLOPT_NONE};
char peer[MAX_HOSTADDR_LEN];
ns_auth_t **authMethod;
int **credLevel, i;
char *cred;
if (mode_verbose)
CLIENT_FPUTS(
gettext("About to configure machine by downloading "
"a profile\n"),
stderr);
if (dname == NULL) {
CLIENT_FPUTS(
gettext("Init failed: System domain not set and "
"no domainName specified.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (!arglist->defaultServerList) {
CLIENT_FPUTS(gettext("Missing LDAP server address\n"), stderr);
return (CLIENT_ERR_FAIL);
}
/* *** Check for invalid args *** */
LDAP_CHECK_INVALID(arglist->defaultSearchBase,
"defaultSearchBase");
LDAP_CHECK_INVALID(arglist->profileTTL,
"profileTTL");
LDAP_CHECK_INVALID(arglist->searchTimeLimit,
"searchTimeLimit");
LDAP_CHECK_INVALID(arglist->preferredServerList,
"preferredServerList");
LDAP_CHECK_INVALID(arglist->followReferrals,
"followReferrals");
LDAP_CHECK_INVALID(arglist->defaultSearchScope,
"defaultSearchScope");
LDAP_CHECK_INVALID(arglist->bindTimeLimit,
"bindTimeLimit");
LDAP_CHECK_INVALID(arglist->objectclassMap->count,
"objectclassMap");
LDAP_CHECK_INVALID(arglist->attributeMap->count,
"attributeMap");
LDAP_CHECK_INVALID(arglist->serviceAuthenticationMethod->count,
"serviceAuthenticationMethod");
LDAP_CHECK_INVALID(arglist->serviceCredentialLevel->count,
"serviceCredentialLevel");
LDAP_CHECK_INVALID(arglist->serviceSearchDescriptor->count,
"serviceSearchDescriptor");
/* *** End check for invalid args *** */
if (arglist->profileName == NULL) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("No profile specified. "
"Using \"default\"\n"),
stderr);
arglist->profileName = "default";
}
(void) strncpy(peer, arglist->defaultServerList, MAX_HOSTADDR_LEN - 1);
if (separatePort(peer, &cfg.SA_SERVER, &cfg.SA_PORT) > 0) {
return (CLIENT_ERR_FAIL);
}
if (arglist->bindDN != NULL) {
cfg.SA_CRED = "proxy";
/*
* We don't want to force users to always specify authentication
* method when we can infer it. If users wants SSL, he/she would
* have to specify appropriate -a though.
*/
auth.type = NS_LDAP_AUTH_SIMPLE;
if (arglist->bindPasswd == NULL) {
arglist->bindPasswd =
getpassphrase("Bind Password:");
if (arglist->bindPasswd == NULL) {
CLIENT_FPUTS(gettext("Get password failed\n"),
stderr);
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (CLIENT_ERR_CREDENTIAL);
}
}
}
cfg.SA_BIND_DN = arglist->bindDN;
cfg.SA_BIND_PWD = arglist->bindPasswd;
if (arglist->authenticationMethod != NULL) {
if (__ns_ldap_initAuth(arglist->authenticationMethod,
&auth, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (CLIENT_ERR_FAIL);
}
cfg.SA_AUTH = &auth;
}
cfg.SA_CRED = arglist->credentialLevel;
cfg.SA_DOMAIN = arglist->domainName;
cfg.SA_PROFILE_NAME = arglist->profileName;
cfg.SA_CERT_PATH = arglist->certificatePath;
cfg.type = NS_LDAP_SERVER;
if (__ns_ldap_initStandalone(&cfg, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (CLIENT_ERR_FAIL);
}
if (arglist->proxyDN != NULL && arglist->proxyPassword == NULL) {
arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
if (arglist->proxyPassword == NULL) {
CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (CLIENT_ERR_CREDENTIAL);
}
}
if (arglist->proxyDN != NULL && arglist->proxyPassword != NULL) {
if (__ns_ldap_setParam(NS_LDAP_BINDDN_P,
arglist->proxyDN, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
return (CLIENT_ERR_CREDENTIAL);
}
if (__ns_ldap_setParam(NS_LDAP_BINDPASSWD_P,
arglist->proxyPassword, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
return (CLIENT_ERR_CREDENTIAL);
}
}
if (arglist->authenticationMethod != NULL) {
if (__ns_ldap_getParam(NS_LDAP_AUTH_P,
(void ***)&authMethod, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
return (CLIENT_ERR_CREDENTIAL);
}
if (authMethod != NULL) {
for (i = 0; authMethod[i] != NULL; ++i) {
if (authMethod[i]->type == auth.type) {
break;
}
}
if (authMethod[i] == NULL) {
CLIENT_FPRINTF(stderr, gettext(
"Warning: init authentication method "
"not found in DUAConfigProfile.\n"));
} else {
if (i != 0) {
CLIENT_FPRINTF(stderr,
gettext(
"Warning: init authentication"
"method using secondary "
"authentication method from "
"DUAConfigProfile.\n"));
}
}
(void) __ns_ldap_freeParam((void ***) &authMethod);
}
}
if (arglist->credentialLevel != NULL) {
if (__ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
(void ***)&credLevel, &errorp) != NS_LDAP_SUCCESS) {
if (errorp != NULL) {
CLIENT_FPRINTF(stderr, "%s", errorp->message);
(void) __ns_ldap_freeError(&errorp);
}
return (CLIENT_ERR_CREDENTIAL);
}
if (credLevel != NULL) {
for (i = 0; credLevel[i] != NULL; ++i) {
switch (*credLevel[i]) {
case NS_LDAP_CRED_ANON :
cred = "none";
break;
case NS_LDAP_CRED_PROXY :
cred = "proxy";
break;
case NS_LDAP_CRED_SELF :
cred = "self";
break;
default:
continue;
break;
}
if (strcmp(cred,
arglist->credentialLevel) == 0) {
break;
}
}
if (credLevel[i] == NULL) {
CLIENT_FPRINTF(stderr, gettext(
"Warning: init credential level not found "
"in DUAConfigProfile.\n"));
} else {
if (i != 0) {
CLIENT_FPRINTF(stderr,
gettext("Warning: "
"init credential level using "
"secondary credential level from "
"DUAConfigProfile.\n"));
}
}
(void) __ns_ldap_freeParam((void ***) &credLevel);
}
}
retcode = credCheck(arglist);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Error in setting up credentials\n"), stderr);
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (retcode);
}
if (mode_verbose)
CLIENT_FPUTS(
gettext("About to modify this machines configuration "
"by writing the files\n"),
stderr);
/* get ready to start playing with files */
retcode = stop_services(STATE_SAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Errors stopping network services.\n"), stderr);
if (gStartLdap == START_RESET)
(void) start_service(LDAP_FMRI, B_TRUE);
return (CLIENT_ERR_FAIL);
}
/* Save orig versions of files */
retcode = file_backup();
if (retcode == CLIENT_ERR_RESTORE) {
CLIENT_FPUTS(
gettext("System not in state to enable ldap client.\n"),
stderr);
return (retcode);
} else if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Save of system configuration failed. "
"Attempting recovery.\n"),
stderr);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (retcode);
}
/* Dump new files */
errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
if (NULL != errorp) {
CLIENT_FPRINTF(stderr,
gettext("%s init: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
(void) __ns_ldap_freeError(&errorp);
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
/* if (credargs(arglist)) */
errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
if (NULL != errorp) {
CLIENT_FPRINTF(stderr,
gettext("%s init: errorp is not NULL; %s\n"),
cmd, errorp->message);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
(void) __ns_ldap_freeError(&errorp);
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
if (ret_copy != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d copying (%s) -> (%s)\n"),
ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
if ((profile_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
retcode = recover(STATE_NOSAVE);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPUTS(
gettext("Recovery of systems configuration "
"failed. Manual intervention of "
"config files is required.\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
return (CLIENT_ERR_FAIL);
}
(void) write(profile_fp, dname, strlen(dname));
(void) write(profile_fp, "\n", 1);
(void) close(profile_fp);
retcode = start_services(START_INIT);
if (retcode == CLIENT_SUCCESS) {
CLIENT_FPUTS(gettext("System successfully configured\n"),
stderr);
} else {
CLIENT_FPUTS(gettext("Error resetting system.\n"
"Recovering old system settings.\n"), stderr),
/* stop any started services for recover */
/* don't stomp on history of saved services state */
reset_ret = stop_services(STATE_NOSAVE);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"stopping services during reset\n"),
reset_ret);
/* Coninue and try to recover what we can */
}
reset_ret = recover(STATE_NOSAVE);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"recovering service files during "
"reset\n"), reset_ret);
/* Continue and start what we can */
}
reset_ret = start_services(START_RESET);
if (reset_ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"starting services during reset\n"),
reset_ret);
}
}
return (retcode);
}
static void
usage(void)
{
if (mode_quiet)
return;
if (gen == 0) {
CLIENT_FPRINTF(stderr,
gettext("Usage: %s [-v | -q] init | manual | mod | "
"list | uninit [<args>]\n"),
cmd);
CLIENT_FPRINTF(stderr,
gettext("\n %s [-v | -q] [-a authenticationMethod]"
" [-D bindDN]\n\t[-w bindPassword] [-j passswdFile]"
" [-y proxyPasswordFile] init [<args>]\n"),
cmd);
CLIENT_FPUTS(
gettext("\nSet up a server or workstation as a "
"client of an LDAP namespace.\n"),
stderr);
} else { /* genprofile */
CLIENT_FPRINTF(stderr,
gettext("Usage: %s [-v | -q] genprofile "
"-a profileName=<name> "
"-a defaultSearchBase=<base> <args>\n"),
cmd);
CLIENT_FPUTS(
gettext("\nGenerate a profile used to set up clients "
"of an LDAP namespace.\n"),
stderr);
}
CLIENT_FPUTS(
gettext("<args> take the form of \'-a attrName=attrVal\' as "
"described in the\n"),
stderr);
CLIENT_FPUTS(gettext("man page: ldapclient(1M)\n"), stderr);
}
/*
* stop_services is called to stop network services prior to their
* config files being moved/changed. In case a later recovery is needed
* (an error occurs during config), we detect whether the service is
* running and store that info so that a reset will only start services
* that were stopped here.
*
* In terms of SMF, this translates to disabling the services. So we
* try to disable them if they are in any other state
*
* Stop order :
* sendmail, nscd, autofs, ldap.client, nisd (rpc), inetinit(domainname)
*/
static int
stop_services(int saveState)
{
int ret;
if (mode_verbose) {
CLIENT_FPUTS(gettext("Stopping network services\n"), stderr);
}
if (!is_service(SENDMAIL_FMRI, SCF_STATE_STRING_DISABLED)) {
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping sendmail\n"), stderr);
ret = disable_service(SENDMAIL_FMRI, B_TRUE);
if (ret != CLIENT_SUCCESS) {
/* Not serious, but tell user what to do */
CLIENT_FPRINTF(stderr, gettext("Stopping sendmail "
"failed with (%d). You may need to restart "
"it manually for changes to take effect.\n"),
ret);
} else enableFlag |= SENDMAIL_ON;
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("sendmail not running\n"), stderr);
}
if (!is_service(NSCD_FMRI, SCF_STATE_STRING_DISABLED)) {
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping nscd\n"), stderr);
ret = disable_service(NSCD_FMRI, B_TRUE);
if (ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Stopping nscd "
"failed with (%d)\n"), ret);
return (CLIENT_ERR_FAIL);
} else enableFlag |= NSCD_ON;
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("nscd not running\n"), stderr);
}
if (!is_service(AUTOFS_FMRI, SCF_STATE_STRING_DISABLED)) {
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping autofs\n"), stderr);
ret = disable_service(AUTOFS_FMRI, B_TRUE);
if (ret != CLIENT_SUCCESS) {
/* Not serious, but tell user what to do */
CLIENT_FPRINTF(stderr, gettext("Stopping autofs "
"failed with (%d). You may need to restart "
"it manually for changes to take effect.\n"),
ret);
} else enableFlag |= AUTOFS_ON;
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("autofs not running\n"), stderr);
}
if (!is_service(LDAP_FMRI, SCF_STATE_STRING_DISABLED)) {
if (saveState)
gStartLdap = START_RESET;
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping ldap\n"), stderr);
ret = disable_service(LDAP_FMRI, B_TRUE);
if (ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Stopping ldap "
"failed with (%d)\n"), ret);
return (CLIENT_ERR_FAIL);
}
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("ldap not running\n"),
stderr);
}
if (!is_service(NISD_FMRI, SCF_STATE_STRING_DISABLED)) {
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping nisd\n"), stderr);
ret = disable_service(NISD_FMRI, B_TRUE);
if (ret != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Stopping nisd "
"failed with (%d)\n"), ret);
return (CLIENT_ERR_FAIL);
}
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("nisd not running\n"),
stderr);
}
if (!is_service(YP_FMRI, SCF_STATE_STRING_DISABLED)) {
if (saveState)
gStartYp = START_RESET;
if (mode_verbose)
CLIENT_FPUTS(gettext("Stopping nis(yp)\n"), stderr);
ret = disable_service(YP_FMRI, B_TRUE);
if (ret != 0) {
CLIENT_FPRINTF(stderr, gettext("Stopping nis(yp) "
"failed with (%d)\n"), ret);
return (CLIENT_ERR_FAIL);
}
} else {
if (mode_verbose)
CLIENT_FPUTS(gettext("nis(yp) not running\n"),
stderr);
}
return (CLIENT_SUCCESS);
}
/*
* start_services is called to start up network services after config
* files have all been setup or recovered. In the case of an error, the
* files will be recovered and start_services will be called with the
* "reset" flag set so that only those services that were earlier stopped
* will be started. If it is not a reset, then the services associated
* with files "recovered" will attempt to be started.
*/
static int
start_services(int flag)
{
int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS;
FILE *domain_fp;
char domainname[BUFSIZ];
char cmd_domain_start[BUFSIZ];
int domainlen;
ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
ns_ldap_error_t *errorp = NULL;
if (mode_verbose) {
CLIENT_FPUTS(gettext("Starting network services\n"), stderr);
}
/* Read in current defaultdomain so we can set it */
domain_fp = fopen(DOMAINNAME, "r");
if (domain_fp == NULL) {
CLIENT_FPRINTF(stderr, gettext("Error opening defaultdomain "
"(%d)\n"), errno);
/* if we did an ldap init, we must have domain */
if (flag == START_INIT)
return (CLIENT_ERR_FAIL);
} else {
if (fgets(domainname, BUFSIZ, domain_fp) == NULL) {
CLIENT_FPUTS(gettext("Error reading defaultdomain\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (fclose(domain_fp) != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error closing defaultdomain (%d)\n"),
errno);
return (CLIENT_ERR_FAIL);
}
domainlen = strlen(domainname);
/* sanity check to make sure sprintf will fit */
if (domainlen > (BUFSIZE - sizeof (CMD_DOMAIN_START) -
sizeof (TO_DEV_NULL) - 3)) {
CLIENT_FPUTS(gettext("Specified domainname is "
"too large\n"), stderr);
return (CLIENT_ERR_FAIL);
}
if (domainname[domainlen-1] == '\n')
domainname[domainlen-1] = 0;
/* buffer size is checked above */
(void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s",
CMD_DOMAIN_START, domainname, TO_DEV_NULL);
}
/*
* We can be starting services after an init in which case
* we want to start ldap and not start yp or nis+.
*/
if (flag == START_INIT) {
sysret = system(cmd_domain_start);
if (mode_verbose)
CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
CMD_DOMAIN_START, domainname,
(sysret == 0) ? gettext("success") :
gettext("failed"));
if (sysret != 0) {
CLIENT_FPRINTF(stderr, gettext("\"%s\" returned: %d\n"),
CMD_DOMAIN_START, sysret);
retcode = CLIENT_ERR_FAIL;
}
if ((rc = __ns_ldap_self_gssapi_config(&config)) !=
NS_LDAP_SUCCESS) {
CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
"checking sasl/GSSAPI configuration\n"),
rc);
retcode = CLIENT_ERR_FAIL;
}
if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
rc = __ns_ldap_check_dns_preq(
1, mode_verbose, mode_quiet,
NSSWITCH_LDAP, config, &errorp);
if (errorp)
(void) __ns_ldap_freeError(&errorp);
if (rc != NS_LDAP_SUCCESS)
retcode = CLIENT_ERR_FAIL;
}
if (rc == NS_LDAP_SUCCESS &&
start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
retcode = CLIENT_ERR_FAIL;
if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) {
rc = __ns_ldap_check_gssapi_preq(
1, mode_verbose, mode_quiet, config,
&errorp);
if (errorp)
(void) __ns_ldap_freeError(&errorp);
if (rc != NS_LDAP_SUCCESS)
retcode = CLIENT_ERR_FAIL;
}
/* No YP or NIS+ after init */
/*
* Or we can be starting services after an uninit or error
* recovery. We want to start whatever services were running
* before. In the case of error recovery, it is the services
* that were running before we stopped them (flags set in
* stop_services). If it is an uninit then we determine
* which services to start based on the files we recovered
* (flags set in recover).
*/
} else {
/* uninit and recover should set flags of what to start */
if (domain_fp) {
sysret = system(cmd_domain_start);
if (mode_verbose)
CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
CMD_DOMAIN_START, domainname,
(sysret == 0) ? gettext("success") :
gettext("failed"));
if (sysret != 0) {
CLIENT_FPRINTF(stderr, gettext("\"%s\" "
"returned: %d\n"),
CMD_DOMAIN_START, sysret);
retcode = CLIENT_ERR_FAIL;
}
}
if (gStartLdap == flag) {
if (!(is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE)))
if (start_service(LDAP_FMRI, B_TRUE)
!= CLIENT_SUCCESS)
retcode = CLIENT_ERR_FAIL;
}
if (gStartYp == flag) {
if (!(is_service(YP_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(YP_FMRI, B_TRUE);
}
if (gStartNisd == flag) {
if (!(is_service(NISD_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(NISD_FMRI, B_TRUE);
}
}
if ((enableFlag & AUTOFS_ON) &&
!(is_service(AUTOFS_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(AUTOFS_FMRI, B_TRUE);
if ((enableFlag & NSCD_ON) &&
!(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(NSCD_FMRI, B_TRUE);
#if 0
if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
retcode == CLIENT_SUCCESS &&
!(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) {
CLIENT_FPRINTF(stderr, "start: %s\n",
gettext("self/sasl/GSSAPI is configured"
" but nscd is not online"));
retcode = CLIENT_ERR_FAIL;
}
#endif
if ((enableFlag & SENDMAIL_ON) &&
!(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE)))
(void) start_service(SENDMAIL_FMRI, B_TRUE);
/*
* Restart name-service milestone so that any consumer
* which depends on it will be restarted.
*/
(void) restart_service(NS_MILESTONE_FMRI, B_TRUE);
return (retcode);
}
/*
* credCheck is called to check if credentials are required for this
* configuration. Currently, this means that if any credentialLevel is
* proxy and any authenticationMethod is something other than none, then
* credential info is required (proxyDN and proxyPassword).
*/
static int
credCheck(clientopts_t *arglist)
{
int counter;
int **credLevel;
ns_auth_t **authMethod;
char **proxyDN, **proxyPassword;
ns_ldap_error_t *errorp;
int credProxy, authNotNone;
int retcode;
/* If credentialLevel is proxy, make sure we have proxyDN and proxyPassword */
retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
(void ***)&credLevel, &errorp);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d while trying to retrieve "
"credLevel\n"),
retcode);
return (CLIENT_ERR_FAIL);
}
retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
(void ***)&authMethod, &errorp);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d while trying to retrieve "
"authMethod\n"), retcode);
return (CLIENT_ERR_FAIL);
}
retcode = __ns_ldap_getParam(NS_LDAP_BINDDN_P,
(void ***)&proxyDN, &errorp);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d while trying to retrieve proxyDN\n"),
retcode);
return (CLIENT_ERR_FAIL);
}
retcode = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P,
(void ***)&proxyPassword, &errorp);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error %d while trying to retrieve "
"proxyPassword\n"), retcode);
return (CLIENT_ERR_FAIL);
}
if (mode_verbose) {
CLIENT_FPRINTF(stderr,
gettext("Proxy DN: %s\n"),
(proxyDN && proxyDN[0]) ? proxyDN[0] : "NULL");
CLIENT_FPRINTF(stderr,
gettext("Proxy password: %s\n"),
(proxyPassword && proxyPassword[0]) ?
proxyPassword[0] : "NULL");
}
credProxy = 0; /* flag to indicate if we have a credLevel of proxy */
for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("Credential level: %d\n"),
*credLevel[counter]);
if (*credLevel[counter] == NS_LDAP_CRED_PROXY) {
credProxy = 1;
break;
}
}
authNotNone = 0; /* flag for authMethod other than none */
for (counter = 0;
authMethod && authMethod[counter] != NULL;
counter++) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("Authentication method: %d\n"),
authMethod[counter]->type);
if (authMethod[counter]->type != NS_LDAP_AUTH_NONE &&
!(authMethod[counter]->type == NS_LDAP_AUTH_TLS &&
authMethod[counter]->tlstype == NS_LDAP_TLS_NONE)) {
authNotNone = 1;
break;
}
}
/* First, if we don't need proxyDN/Password then just return ok */
if (!(credProxy && authNotNone)) {
if (mode_verbose)
CLIENT_FPUTS(
gettext("No proxyDN/proxyPassword required\n"),
stderr);
return (CLIENT_SUCCESS);
}
/* Now let's check if we have the cred stuff we need */
if (!proxyDN || !proxyDN[0]) {
CLIENT_FPUTS(
gettext("credentialLevel is proxy and no proxyDN "
"specified\n"),
stderr);
return (CLIENT_ERR_CREDENTIAL);
}
/* If we need proxyPassword (prompt) */
if (!proxyPassword || !proxyPassword[0]) {
CLIENT_FPUTS(
gettext("credentialLevel requires proxyPassword\n"),
stderr);
arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
if (arglist->proxyPassword == NULL) {
CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
return (CLIENT_ERR_CREDENTIAL);
}
LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
if (retcode != 0) {
CLIENT_FPUTS(
gettext("setParam proxyPassword failed.\n"),
stderr);
return (CLIENT_ERR_CREDENTIAL);
}
}
return (CLIENT_SUCCESS);
}
/*
* try to restore the previous name space on this machine
*/
static int
recover(int saveState)
{
struct stat buf;
int stat_ret, retcode, fd;
int domain = 0, domainlen;
char yp_dir[BUFSIZE], yp_dir_back[BUFSIZE];
char name[BUFSIZ];
char *ldap_conf_file, *ldap_cred_file;
char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
/* If running as Sysid Install become a no-op */
if (sysid_install == B_TRUE)
return (CLIENT_SUCCESS);
stat_ret = stat(LDAP_RESTORE_DIR, &buf);
if (stat_ret != 0) {
CLIENT_FPUTS(
gettext("Cannot recover. No backup files "
"found.\n"),
stderr);
CLIENT_FPUTS(
gettext("\t Either this machine was not initialized\n"),
stderr);
CLIENT_FPUTS(
gettext("\t by ldapclient or the backup files "
"have been\n"),
stderr);
CLIENT_FPUTS(
gettext("\t removed manually or with an \"uninit\"\n"),
stderr);
return (CLIENT_ERR_RESTORE); /* invalid backup */
}
/*
* Get domainname. Allow no domainname for the case where "files"
* config was backed up.
*/
stat_ret = stat(DOMAINNAME_BACK, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
DOMAINNAME_BACK, stat_ret);
if (stat_ret == 0) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: open(%s)\n"),
DOMAINNAME_BACK);
fd = open(DOMAINNAME_BACK, O_RDONLY);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: read(%s)\n"),
DOMAINNAME_BACK);
domainlen = read(fd, &(name[0]), BUFSIZ-1);
(void) close(fd);
if (domainlen < 0) {
CLIENT_FPUTS(
gettext("Cannot recover. Cannot determine "
"previous domain name.\n"),
stderr);
return (CLIENT_ERR_RESTORE); /* invalid backup */
} else {
char *ptr;
ptr = strchr(&(name[0]), '\n');
if (ptr != NULL)
*ptr = '\0';
else
name[domainlen] = '\0';
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: old domainname "
"\"%s\"\n"), name);
if (strlen(name) == 0)
domain = 0;
else
domain = 1; /* flag that we have domain */
}
}
/*
* we can recover at this point
* remove LDAP config files before restore
*/
(void) unlink(NSCONFIGFILE);
(void) unlink(NSCREDFILE);
ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
stat_ret = stat(ldap_file_back, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
ldap_file_back, stat_ret);
if (stat_ret == 0) {
if (saveState)
gStartLdap = START_UNINIT;
retcode = file_move(ldap_file_back, NSCONFIGFILE);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s)=%d\n"),
ldap_file_back, NSCONFIGFILE, retcode);
if (retcode != 0)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s) failed\n"),
ldap_file_back, NSCONFIGFILE);
}
(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
stat_ret = stat(ldap_cred_back, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
ldap_cred_back, stat_ret);
if (stat_ret == 0) {
retcode = file_move(ldap_cred_back, NSCREDFILE);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s)=%d\n"),
ldap_cred_back, NSCREDFILE, retcode);
if (retcode != 0)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s) failed\n"),
ldap_cred_back, NSCREDFILE);
}
/* Check for recovery of NIS+ */
stat_ret = stat(NIS_COLDSTART_BACK, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
NIS_COLDSTART_BACK, stat_ret);
if (stat_ret == 0) {
if (saveState) {
gStartNisd = START_UNINIT;
}
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s)\n"),
NIS_COLDSTART_BACK, NIS_COLDSTART);
retcode = file_move(NIS_COLDSTART_BACK, NIS_COLDSTART);
if (retcode != 0)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s) failed!\n"),
NIS_COLDSTART_BACK, NIS_COLDSTART);
}
/* Check for recovery of NIS(YP) if we have a domainname */
if (domain) {
/* "name" would have to be huge for this, but just in case */
if (strlen(name) >= (BUFSIZE - strlen(LDAP_RESTORE_DIR)))
return (CLIENT_ERR_FAIL);
if (strlen(name) >= (BUFSIZE - strlen(YP_BIND_DIR)))
return (CLIENT_ERR_FAIL);
(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", BUFSIZE);
(void) strlcat(yp_dir_back, name, BUFSIZE);
stat_ret = stat(yp_dir_back, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
yp_dir_back, stat_ret);
if (stat_ret == 0) {
(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
(void) strlcat(yp_dir, name, BUFSIZE);
retcode = file_move(yp_dir_back, yp_dir);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, "
"%s)=%d\n"),
yp_dir_back, yp_dir, retcode);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, "
"%s) failed!\n"),
yp_dir_back, yp_dir);
} else {
if (saveState)
gStartYp = START_UNINIT;
}
}
}
/* restore machine configuration */
stat_ret = stat(NSSWITCH_BACK, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
NSSWITCH_BACK, stat_ret);
if (stat_ret == 0) {
retcode = file_move(NSSWITCH_BACK, NSSWITCH_CONF);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s)=%d\n"),
NSSWITCH_BACK, NSSWITCH_CONF, retcode);
if (retcode != 0)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s) failed\n"),
NSSWITCH_BACK, NSSWITCH_CONF);
}
stat_ret = stat(DOMAINNAME_BACK, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: stat(%s)=%d\n"),
DOMAINNAME_BACK, stat_ret);
if (stat_ret == 0) {
retcode = file_move(DOMAINNAME_BACK, DOMAINNAME);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s)=%d\n"),
DOMAINNAME_BACK, DOMAINNAME, retcode);
if (retcode != 0)
CLIENT_FPRINTF(stderr,
gettext("recover: file_move(%s, %s) failed\n"),
DOMAINNAME_BACK, DOMAINNAME);
}
retcode = rmdir(LDAP_RESTORE_DIR);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("Error removing \"%s\" directory.\n"),
LDAP_RESTORE_DIR);
}
return (CLIENT_SUCCESS);
}
/*
* try to save the current state of this machine.
* this just overwrites any old saved configration files.
*
* This function should only be called after network services have been stopped.
*
* Returns 0 on successful save
* Otherwise returns -1
*/
static int
file_backup(void)
{
struct stat buf;
int domain_stat, conf_stat, ldap_stat;
int nis_stat, yp_stat, restore_stat;
int retcode, namelen, ret;
char yp_dir[BUFSIZ], yp_dir_back[BUFSIZ];
char name[BUFSIZ];
char *ldap_conf_file, *ldap_cred_file;
char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
ret = CLIENT_SUCCESS;
/* If running as Sysid Install become a no-op */
if (sysid_install == B_TRUE)
return (CLIENT_SUCCESS);
/* If existing backup files, clear for this run */
restore_stat = stat(LDAP_RESTORE_DIR, &buf);
if (restore_stat == 0) {
if (mode_verbose) {
CLIENT_FPUTS(
gettext("Removing existing restore "
"directory\n"),
stderr);
}
(void) system("/bin/rm -fr " LDAP_RESTORE_DIR);
restore_stat = stat(LDAP_RESTORE_DIR, &buf);
if (restore_stat == 0) {
CLIENT_FPRINTF(stderr,
gettext("Unable to remove backup "
"directory (%s)\n"),
LDAP_RESTORE_DIR);
return (CLIENT_ERR_RESTORE);
}
}
retcode = mkdir(LDAP_RESTORE_DIR, 0755);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: Failed to make %s backup "
"directory. mkdir=%d\n"),
LDAP_RESTORE_DIR, retcode);
return (CLIENT_ERR_FAIL);
}
conf_stat = stat(NSSWITCH_CONF, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: stat(%s)=%d\n"),
NSSWITCH_CONF, conf_stat);
if (conf_stat == 0) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
NSSWITCH_CONF, NSSWITCH_BACK);
retcode = file_move(NSSWITCH_CONF, NSSWITCH_BACK);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s) failed "
"with %d\n"),
NSSWITCH_CONF, NSSWITCH_BACK, retcode);
ret = CLIENT_ERR_RENAME;
}
} else {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: No %s file.\n"),
NSSWITCH_CONF);
}
domain_stat = stat(DOMAINNAME, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: stat(%s)=%d\n"),
DOMAINNAME, domain_stat);
if ((domain_stat == 0) && (buf.st_size > 0)) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
DOMAINNAME, DOMAINNAME_BACK);
retcode = file_move(DOMAINNAME, DOMAINNAME_BACK);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s) failed "
"with %d\n"),
DOMAINNAME, DOMAINNAME_BACK, retcode);
ret = CLIENT_ERR_RENAME;
}
} else {
if (mode_verbose)
if (domain_stat != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: No %s file.\n"),
DOMAINNAME);
} else {
CLIENT_FPRINTF(stderr,
gettext("file_backup: Empty %s "
"file.\n"),
DOMAINNAME);
}
}
nis_stat = stat(NIS_COLDSTART, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: stat(%s)=%d\n"),
NIS_COLDSTART, nis_stat);
if (nis_stat == 0) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
NIS_COLDSTART, NIS_COLDSTART_BACK);
retcode = file_move(NIS_COLDSTART, NIS_COLDSTART_BACK);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s) failed "
"with %d\n"),
NIS_COLDSTART, NIS_COLDSTART_BACK, retcode);
ret = CLIENT_ERR_RENAME;
}
} else {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: No %s file.\n"),
NIS_COLDSTART);
}
namelen = BUFSIZ;
(void) sysinfo(SI_SRPC_DOMAIN, &(name[0]), namelen);
namelen = strlen(name);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: nis domain is \"%s\"\n"),
(namelen > 0) ? name : "EMPTY");
/* check for domain name if not set cannot save NIS(YP) state */
if (namelen > 0) {
/* moving /var/yp/binding will cause ypbind to core dump */
(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
(void) strlcat(yp_dir, name, BUFSIZE);
yp_stat = stat(yp_dir, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: stat(%s)=%d\n"),
yp_dir, yp_stat);
if (yp_stat == 0) {
(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/",
BUFSIZE);
(void) strlcat(yp_dir_back, name, BUFSIZE);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
yp_dir, yp_dir_back);
retcode = file_move(yp_dir, yp_dir_back);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s)"
" failed with %d\n"),
yp_dir, yp_dir_back, retcode);
ret = CLIENT_ERR_RENAME;
}
} else {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: No %s "
"directory.\n"), yp_dir);
}
}
/* point to file name, not path delim (/) */
ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
ldap_stat = stat(NSCONFIGFILE, &buf);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: stat(%s)=%d\n"),
NSCONFIGFILE, ldap_stat);
if (ldap_stat == 0) {
(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
NSCONFIGFILE, ldap_file_back);
retcode = file_move(NSCONFIGFILE, ldap_file_back);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s) failed "
"with %d\n"),
NSCONFIGFILE, ldap_file_back, retcode);
ret = CLIENT_ERR_RENAME;
}
(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: (%s -> %s)\n"),
NSCREDFILE, ldap_cred_back);
retcode = file_move(NSCREDFILE, ldap_cred_back);
if (retcode != 0) {
CLIENT_FPRINTF(stderr,
gettext("file_backup: file_move(%s, %s) failed "
"with %d\n"),
NSCREDFILE, ldap_cred_back, retcode);
ret = CLIENT_ERR_RENAME;
}
} else {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("file_backup: No %s file.\n"),
NSCONFIGFILE);
}
return (ret);
}
/*
* mod_backup()
*
* This function is used to temporily backup the LDAP client files in /var/ldap
* that the "mod" operation needs to update. If an error occurs then the
* function mod_recover() can be invoke to recover the unmodified files.
*/
static int
mod_backup(void)
{
int rc;
int retcode = CLIENT_SUCCESS;
rc = system(CMD_CP " " NSCONFIGFILE " " NSCONFIGFILE ".mod");
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_backup: backup %s for %s\n"),
rc ? "failed" : "successful", NSCONFIGFILE);
rc = system(CMD_CP " " NSCREDFILE " " NSCREDFILE ".mod");
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_backup: backup %s for %s\n"),
rc ? "failed" : "successful", NSCREDFILE);
rc = system(CMD_CP " " DOMAINNAME " " DOMAINNAME ".mod");
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_backup: backup %s for %s\n"),
rc ? "failed" : "successful", DOMAINNAME);
if (retcode != CLIENT_SUCCESS)
retcode = CLIENT_ERR_RENAME;
return (retcode);
}
/*
* mod_recover()
*
* This function is used to recover the temporily backed up files by
* the mod_backup() function if an error occurs during the "mod"
* operation.
*/
static int
mod_recover(void)
{
int rc;
int retcode = CLIENT_SUCCESS;
rc = system(CMD_MV " " NSCONFIGFILE ".mod " NSCONFIGFILE);
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_recover: recovery %s for %s\n"),
rc ? "failed" : "successful", NSCONFIGFILE);
rc = system(CMD_MV " " NSCREDFILE ".mod " NSCREDFILE);
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_recover: recovery %s for %s\n"),
rc ? "failed" : "successful", NSCREDFILE);
rc = system(CMD_MV " " DOMAINNAME ".mod " DOMAINNAME);
retcode += rc;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
gettext("mod_recover: recovery %s for %s\n"),
rc ? "failed" : "successful", DOMAINNAME);
if (retcode != CLIENT_SUCCESS)
retcode = CLIENT_ERR_RENAME;
return (retcode);
}
/*
* mod_cleanup()
*
* This function removes the .mod files in /var/ldap.
*/
static void
mod_cleanup(void)
{
(void) system(CMD_RM " " NSCONFIGFILE ".mod " TO_DEV_NULL);
(void) system(CMD_RM " " NSCREDFILE ".mod " TO_DEV_NULL);
(void) system(CMD_RM " " DOMAINNAME ".mod " TO_DEV_NULL);
}
#define MAX_DN_ARRAY 100
#define LDAP_NAMINGCONTEXTS "namingcontexts"
static multival_t *
multival_new()
{
multival_t *hold;
hold = calloc(1, sizeof (multival_t));
if (hold == NULL) {
CLIENT_FPUTS(
gettext("multival_new: Memory allocation error\n"),
stderr);
}
return (hold); /* NULL -> error */
}
static int
multival_add(multival_t *list, char *opt)
{
if (opt == NULL) {
CLIENT_FPUTS(
gettext("Empty value passed to multival_add\n"),
stderr);
return (CLIENT_ERR_FAIL);
}
if (list->count == 0) {
list->optlist = (char **)malloc(sizeof (char **));
} else {
list->optlist = (char **)realloc(list->optlist,
(list->count + 1) * sizeof (char **));
}
if (list->optlist == NULL) {
CLIENT_FPUTS(gettext("Error allocating memory\n"), stderr);
return (CLIENT_ERR_MEMORY); /* 0 is success */
}
list->optlist[list->count] = opt;
list->count++;
return (CLIENT_SUCCESS);
}
static void
multival_free(multival_t *list)
{
if (list == NULL)
return;
if (list->optlist != NULL)
free(list->optlist);
free(list);
}
static clientopts_t *
clientopts_new()
{
clientopts_t *hold;
hold = calloc(1, sizeof (clientopts_t));
if (NULL == hold) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"clientopts structure\n"), stderr);
return (hold); /* NULL -> error */
}
hold->serviceAuthenticationMethod = multival_new();
if (NULL == hold->serviceAuthenticationMethod) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"serviceAuthenticationMethod\n"), stderr);
free(hold);
return (NULL); /* NULL -> error */
}
hold->serviceCredentialLevel = multival_new();
if (NULL == hold->serviceCredentialLevel) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"serviceCredentialLevel\n"), stderr);
multival_free(hold->serviceAuthenticationMethod);
free(hold);
return (NULL); /* NULL -> error */
}
hold->objectclassMap = multival_new();
if (NULL == hold->objectclassMap) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"objectclassMap\n"), stderr);
multival_free(hold->serviceAuthenticationMethod);
multival_free(hold->serviceCredentialLevel);
free(hold);
return (NULL); /* NULL -> error */
}
hold->attributeMap = multival_new();
if (NULL == hold->attributeMap) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"attributeMap\n"), stderr);
multival_free(hold->serviceAuthenticationMethod);
multival_free(hold->serviceCredentialLevel);
multival_free(hold->objectclassMap);
free(hold);
return (NULL); /* NULL -> error */
}
hold->serviceSearchDescriptor = multival_new();
if (NULL == hold->serviceSearchDescriptor) {
CLIENT_FPUTS(gettext("Error allocating memory for "
"serviceSearchDescriptor\n"), stderr);
multival_free(hold->serviceAuthenticationMethod);
multival_free(hold->serviceCredentialLevel);
multival_free(hold->objectclassMap);
multival_free(hold->attributeMap);
free(hold);
return (NULL); /* NULL -> error */
}
return (hold);
}
static void
clientopts_free(clientopts_t *list)
{
if (NULL == list)
return;
multival_free(list->serviceAuthenticationMethod);
multival_free(list->serviceCredentialLevel);
multival_free(list->objectclassMap);
multival_free(list->attributeMap);
multival_free(list->serviceSearchDescriptor);
free(list);
}
static void
multival_list(char *opt, multival_t *list)
{
int i;
if (list->count == 0)
return;
(void) puts(opt);
for (i = 0; i < list->count; i++) {
(void) printf("\t\targ[%d]: %s\n", i, list->optlist[i]);
}
}
/* return the number of arguments specified in the command line */
static int
num_args(clientopts_t *list)
{
int arg_count = 0;
arg_count += list->authenticationMethod ? 1 : 0;
arg_count += list->serviceAuthenticationMethod->count;
arg_count += list->defaultSearchBase ? 1 : 0;
arg_count += list->credentialLevel ? 1 : 0;
arg_count += list->serviceCredentialLevel->count;
arg_count += list->domainName ? 1 : 0;
arg_count += list->proxyDN ? 1 : 0;
arg_count += list->profileTTL ? 1 : 0;
arg_count += list->objectclassMap->count;
arg_count += list->searchTimeLimit ? 1 : 0;
arg_count += list->preferredServerList ? 1 : 0;
arg_count += list->profileName ? 1 : 0;
arg_count += list->followReferrals ? 1 : 0;
arg_count += list->attributeMap->count;
arg_count += list->defaultSearchScope ? 1 : 0;
arg_count += list->serviceSearchDescriptor->count;
arg_count += list->bindTimeLimit ? 1 : 0;
arg_count += list->proxyPassword ? 1 : 0;
arg_count += list->defaultServerList ? 1 : 0;
arg_count += list->certificatePath ? 1 : 0;
return (arg_count);
}
#define CLIENT_PRINT(opt, str) if (str) \
(void) printf("%s%s\n", (opt), (str))
static void
dumpargs(clientopts_t *list)
{
CLIENT_PRINT("\tauthenticationMethod: ", list->authenticationMethod);
multival_list("\tserviceAuthenticationMethod: ",
list->serviceAuthenticationMethod);
CLIENT_PRINT("\tdefaultSearchBase: ", list->defaultSearchBase);
CLIENT_PRINT("\tcredentialLevel: ", list->credentialLevel);
multival_list("\tserviceCredentialLevel: ",
list->serviceCredentialLevel);
CLIENT_PRINT("\tdomainName: ", list->domainName);
CLIENT_PRINT("\tproxyDN: ", list->proxyDN);
CLIENT_PRINT("\tprofileTTL: ", list->profileTTL);
multival_list("\tobjectclassMap: ", list->objectclassMap);
CLIENT_PRINT("\tsearchTimeLimit: ", list->searchTimeLimit);
CLIENT_PRINT("\tpreferredServerList: ", list->preferredServerList);
CLIENT_PRINT("\tprofileName: ", list->profileName);
CLIENT_PRINT("\tfollowReferrals: ", list->followReferrals);
multival_list("\tattributeMap: ", list->attributeMap);
CLIENT_PRINT("\tdefaultSearchScope: ", list->defaultSearchScope);
multival_list("\tserviceSearchDescriptor: ",
list->serviceSearchDescriptor);
CLIENT_PRINT("\tbindTimeLimit: ", list->bindTimeLimit);
CLIENT_PRINT("\tproxyPassword: ", list->proxyPassword);
CLIENT_PRINT("\tdefaultServerList: ", list->defaultServerList);
CLIENT_PRINT("\tcertificatePath: ", list->certificatePath);
}
/* These definitions are only used in parseParam() below. */
struct param {
char *name;
int index;
};
static struct param paramArray[] = {
{"proxyDN", NS_LDAP_BINDDN_P},
{"proxyPassword", NS_LDAP_BINDPASSWD_P},
{"defaultServerList", NS_LDAP_SERVERS_P},
{"defaultSearchBase", NS_LDAP_SEARCH_BASEDN_P},
{"authenticationMethod", NS_LDAP_AUTH_P},
{"followReferrals", NS_LDAP_SEARCH_REF_P},
{"profileTTL", NS_LDAP_CACHETTL_P},
{"certificatePath", NS_LDAP_HOST_CERTPATH_P},
{"defaultSearchScope", NS_LDAP_SEARCH_SCOPE_P},
{"bindTimeLimit", NS_LDAP_BIND_TIME_P},
{"searchTimeLimit", NS_LDAP_SEARCH_TIME_P},
{"preferredServerList", NS_LDAP_SERVER_PREF_P},
{"profileName", NS_LDAP_PROFILE_P},
{"credentialLevel", NS_LDAP_CREDENTIAL_LEVEL_P},
{"serviceSearchDescriptor", NS_LDAP_SERVICE_SEARCH_DESC_P},
{"attributeMap", NS_LDAP_ATTRIBUTEMAP_P},
{"objectclassMap", NS_LDAP_OBJECTCLASSMAP_P},
{"serviceAuthenticationMethod", NS_LDAP_SERVICE_AUTH_METHOD_P},
{"serviceCredentialLevel", NS_LDAP_SERVICE_CRED_LEVEL_P},
{"domainName", LOCAL_DOMAIN_P},
{NULL, 0}
};
static int
parseParam(char *param, char **paramVal)
{
char *val = NULL;
int counter;
if (mode_verbose) {
CLIENT_FPRINTF(stderr, gettext("Parsing %s\n"), param);
}
val = strchr(param, '=');
if (val == NULL) {
CLIENT_FPUTS(
gettext("Didn\'t find \'=\' character in string\n"),
stderr);
paramVal = NULL;
return (CLIENT_ERR_PARSE);
}
*val = '\0';
for (counter = 0; paramArray[counter].name != NULL; counter++) {
if (strcasecmp(paramArray[counter].name, param) == 0) {
*paramVal = val+1;
*val = '='; /* restore original param */
return (paramArray[counter].index);
}
}
/* Not found */
*val = '='; /* restore original param */
*paramVal = NULL;
return (CLIENT_ERR_PARSE);
}
/*
* The following macro checks if an option has already been specified
* and errs out with usage if so
*/
#define CLIENT_OPT_CHECK(opt, optarg) \
if (optarg) { \
CLIENT_FPUTS(gettext("Invalid use of option\n"), stderr); \
usage(); \
clientopts_free(optlist); \
return (CLIENT_ERR_FAIL); \
}
static int
clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal)
{
int retcode = 0;
int counter;
switch (paramFlag) {
case NS_LDAP_AUTH_P:
CLIENT_OPT_CHECK(paramFlag, optlist->authenticationMethod);
optlist->authenticationMethod = attrVal;
break;
case NS_LDAP_SERVICE_AUTH_METHOD_P: /* multiple allowed */
retcode = multival_add(optlist->serviceAuthenticationMethod,
attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr,
gettext("Error processing attrVal %s\n"),
attrVal?attrVal:"NULL");
usage();
clientopts_free(optlist);
return (CLIENT_ERR_FAIL);
}
break;
case NS_LDAP_SEARCH_BASEDN_P:
CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchBase);
optlist->defaultSearchBase = attrVal;
break;
case NS_LDAP_CREDENTIAL_LEVEL_P:
CLIENT_OPT_CHECK(paramFlag, optlist->credentialLevel);
optlist->credentialLevel = attrVal;
break;
case NS_LDAP_SERVICE_CRED_LEVEL_P: /* multiple allowed */
retcode = multival_add(optlist->serviceCredentialLevel,
attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr,
gettext("Error processing attrVal %s\n"),
attrVal?attrVal:"NULL");
usage();
clientopts_free(optlist);
return (CLIENT_ERR_FAIL);
}
break;
case LOCAL_DOMAIN_P:
CLIENT_OPT_CHECK(paramFlag, optlist->domainName);
optlist->domainName = attrVal;
dname = optlist->domainName;
break;
case NS_LDAP_BINDDN_P:
CLIENT_OPT_CHECK(paramFlag, optlist->proxyDN);
optlist->proxyDN = attrVal;
break;
case NS_LDAP_CACHETTL_P:
CLIENT_OPT_CHECK(paramFlag, optlist->profileTTL);
optlist->profileTTL = attrVal;
break;
case NS_LDAP_OBJECTCLASSMAP_P: /* multiple allowed */
retcode = multival_add(optlist->objectclassMap, attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr,
gettext("Error processing attrVal %s\n"),
attrVal?attrVal:"NULL");
usage();
clientopts_free(optlist);
return (CLIENT_ERR_FAIL);
}
break;
case NS_LDAP_SEARCH_TIME_P:
CLIENT_OPT_CHECK(paramFlag, optlist->searchTimeLimit);
optlist->searchTimeLimit = attrVal;
break;
case NS_LDAP_SERVER_PREF_P:
CLIENT_OPT_CHECK(paramFlag, optlist->preferredServerList);
optlist->preferredServerList = attrVal;
/* replace ',' chars with ' ' for proper syntax */
for (counter = 0;
counter < strlen(optlist->preferredServerList);
counter++) {
if (optlist->preferredServerList[counter] == ',')
optlist->preferredServerList[counter] = ' ';
}
break;
case NS_LDAP_PROFILE_P:
CLIENT_OPT_CHECK(paramFlag, optlist->profileName);
optlist->profileName = attrVal;
break;
case NS_LDAP_SEARCH_REF_P:
CLIENT_OPT_CHECK(paramFlag, optlist->followReferrals);
if (0 == strcasecmp(attrVal, "followref"))
optlist->followReferrals = "TRUE";
else if (0 == strcasecmp(attrVal, "noref"))
optlist->followReferrals = "FALSE";
else
optlist->followReferrals = attrVal;
break;
case NS_LDAP_ATTRIBUTEMAP_P: /* multiple allowed */
retcode = multival_add(optlist->attributeMap, attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr,
gettext("Error processing attrVal %s\n"),
attrVal?attrVal:"NULL");
usage();
clientopts_free(optlist);
return (CLIENT_ERR_FAIL);
}
break;
case NS_LDAP_SEARCH_SCOPE_P:
CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchScope);
optlist->defaultSearchScope = attrVal;
break;
case NS_LDAP_SERVICE_SEARCH_DESC_P: /* multiple allowed */
retcode = multival_add(optlist->serviceSearchDescriptor,
attrVal);
if (retcode != CLIENT_SUCCESS) {
CLIENT_FPRINTF(stderr,
gettext("Error processing attrVal %s\n"),
attrVal?attrVal:"NULL");
usage();
clientopts_free(optlist);
return (CLIENT_ERR_FAIL);
}
break;
case NS_LDAP_BIND_TIME_P:
CLIENT_OPT_CHECK(paramFlag, optlist->bindTimeLimit);
optlist->bindTimeLimit = attrVal;
break;
case NS_LDAP_BINDPASSWD_P:
CLIENT_OPT_CHECK(paramFlag, optlist->proxyPassword);
optlist->proxyPassword = attrVal;
break;
case NS_LDAP_HOST_CERTPATH_P:
CLIENT_OPT_CHECK(paramFlag, optlist->certificatePath);
optlist->certificatePath = attrVal;
break;
case NS_LDAP_SERVERS_P:
CLIENT_OPT_CHECK(paramFlag, optlist->defaultServerList);
optlist->defaultServerList = attrVal;
break;
default:
usage();
return (CLIENT_ERR_FAIL);
/* break; lint doesn't like break before end of switch */
}
return (retcode);
}
/*
* file_move() - Used to move a config file (backup/restore).
*
* This function uses a system() call with /bin/mv to handle the
* case where the backup directory (/var) is on a different file
* system than the config file (typically /etc).
*/
static int
file_move(const char *from, const char *to)
{
int retcode;
char mvCommand[] = CMD_MV;
char cmd_buffer[(2 * MAXPATHLEN) + sizeof (mvCommand) + 3];
(void) snprintf(cmd_buffer, sizeof (cmd_buffer), "%s %s %s",
mvCommand, from, to);
/*
* This function should only be used internally to move
* system files to/from the backup directory. For security
* reasons (this is run as root), don't use this function
* with arguments passed into the program.
*/
retcode = system(cmd_buffer);
return (retcode);
}
/*
* Manipulate the service as instructed by "dowhat"
*/
static int
do_service(const char *fmri, boolean_t waitflag, int dowhat,
const char *state) {
int status;
boolean_t is_maint;
const char *what = gettext("not set");
useconds_t max;
/* Check if we are in maintenance */
is_maint = is_service(fmri, SCF_STATE_STRING_MAINT);
switch (dowhat) {
case START_SERVICE:
what = gettext("start");
status = smf_enable_instance(fmri,
(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
break;
case STOP_SERVICE:
what = gettext("stop");
status = smf_disable_instance(fmri,
(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
break;
case RESTART_SERVICE:
what = gettext("restart");
status = smf_restart_instance(fmri);
break;
default:
/* coding error; will not happen */
assert(0);
}
/*
* If the service was previously in maintenance then we need to
* clear it immediately. The "dowhat" action will set the
* enabled property of the service as intended by the caller while
* clear will actually cause it to be enabled/disabled.
* We assume that the caller has called us after taking some
* recovery action. Even if it's not the case, we don't lose
* anything.
*/
if (status == 0 && is_maint == B_TRUE) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("restoring from maintenance state"));
status = smf_restore_instance(fmri);
}
if (status == 0) {
/* Check if we need to wait ? */
if (waitflag == B_FALSE) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("success"));
return (CLIENT_SUCCESS);
}
/* Otherwise wait for max seconds (from the manifest) */
max = get_timeout_value(dowhat, fmri, DEFAULT_TIMEOUT);
status = wait_till(fmri, state, max, what, !is_maint);
if (status == CLIENT_SUCCESS)
return (CLIENT_SUCCESS);
/* For error fall through for corrective action */
} else {
/* Well, service failed ... */
if (mode_verbose)
CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
what,
fmri,
gettext("failed"),
scf_strerror(scf_error()));
status = CLIENT_ERR_FAIL;
/* For error fall through for corrective action */
}
/*
* If service is still offline after start/restart, then transitioning
* failed and guess is restarter failed to apply the timeout as well.
* So instead of leaving it offline, let's just disable it until we have
* some other mechanism available from smf to handle such situation.
*/
if (dowhat != STOP_SERVICE)
if (is_service(fmri, SCF_STATE_STRING_OFFLINE)) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("offline to disable"));
(void) disable_service(fmri, waitflag);
}
return (status);
}
/*
* Wait for "max" usecs for the service described by "fmri" to change
* to "state". If check_maint is true then return immediately if
* service goes into maintenance
*/
static int
wait_till(const char *fmri, const char *state, useconds_t max,
const char *what, boolean_t check_maint) {
char *st;
useconds_t usecs = INIT_WAIT_USECS;
for (; max > 0; max -= usecs) {
/* incremental wait */
usecs *= 2;
usecs = (usecs > max)?max:usecs;
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s %u %s\n",
what, gettext("sleep"), usecs,
gettext("microseconds"));
(void) usleep(usecs);
/* Check state after the wait */
if ((st = smf_get_state(fmri)) != NULL) {
if (strcmp(st, state) == 0) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("success"));
free(st);
return (CLIENT_SUCCESS);
}
/*
* If service has gone into maintenance then
* we will time out anyway, so we are better
* off returning now
*/
if (check_maint &&
strcmp(st, SCF_STATE_STRING_MAINT) == 0) {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("maintenance"));
free(st);
return (CLIENT_ERR_MAINTENANCE);
}
free(st);
} else {
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s: %s\n",
what,
fmri,
gettext("failed"),
scf_strerror(scf_error()));
return (CLIENT_ERR_FAIL);
}
}
/* Timed out waiting */
if (mode_verbose)
CLIENT_FPRINTF(stderr,
"%s: %s... %s\n",
what,
fmri,
gettext("timed out"));
return (CLIENT_ERR_TIMEDOUT);
}
static boolean_t
is_service(const char *fmri, const char *state) {
char *st;
boolean_t result = B_FALSE;
if ((st = smf_get_state(fmri)) != NULL) {
if (strcmp(st, state) == 0)
result = B_TRUE;
free(st);
}
return (result);
}
/*
*
* get_timeout_val : returns the timeout value set in fmri manifest
* inputs : action(start/stop)
* fmri(defined fmri string)
* Returns default if error, the timeout val otherwise
*
*/
static useconds_t
get_timeout_value(int dowhat, const char *fmri, useconds_t default_val)
{
scf_simple_prop_t *sp = NULL;
uint64_t *cp = NULL;
int timeout = default_val/1000000;
char *action = NULL;
const char *actionstr = NULL;
switch (dowhat) {
case START_SERVICE:
case RESTART_SERVICE:
action = "start";
actionstr = gettext("start");
break;
case STOP_SERVICE:
action = "stop";
actionstr = gettext("stop");
break;
default:
assert(0);
}
sp = scf_simple_prop_get(NULL, fmri, action, SCF_PROPERTY_TIMEOUT);
if (sp == NULL) {
if (mode_verbose)
CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
actionstr,
fmri,
gettext("failed to retrieve timeout property"),
scf_strerror(scf_error()));
return (default_val);
}
cp = scf_simple_prop_next_count(sp);
if (cp == NULL) {
if (mode_verbose)
CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
actionstr,
fmri,
gettext("failed to retrieve timeout value"),
scf_strerror(scf_error()));
scf_simple_prop_free(sp);
return (default_val);
}
if (*cp != 0)
timeout = *cp;
scf_simple_prop_free(sp);
return (timeout * 1000000);
}