xref: /illumos-gate/usr/src/cmd/ldap/ns_ldap/ldaplist.c (revision c59d9dff)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b446700bSjanga  * Common Development and Distribution License (the "License").
6b446700bSjanga  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
229f2fd570SJulian Pullen  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23528b7d8bSRichard Lowe  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <libintl.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include <locale.h>
327c478bd9Sstevel@tonic-gate #include <syslog.h>
34e1dd0a2fSth #include "standalone.h"
367c478bd9Sstevel@tonic-gate extern char *set_filter(char **, char *, char **);
377c478bd9Sstevel@tonic-gate extern char *set_filter_publickey(char **, char *, int, char **);
387c478bd9Sstevel@tonic-gate extern void _printResult(ns_ldap_result_t *);
39b446700bSjanga extern void printMapping();
417c478bd9Sstevel@tonic-gate int listflag = 0;
439f2fd570SJulian Pullen 
449f2fd570SJulian Pullen 
459f2fd570SJulian Pullen static struct database_t {
469f2fd570SJulian Pullen 	const char *database;
479f2fd570SJulian Pullen 	const char *sortattr;
489f2fd570SJulian Pullen }databaselist[] = {
499f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_HOSTS, "cn" },
509f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_IPNODES, "cn" },
519f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_RPC, "cn" },
529f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_PROTOCOLS, "cn" },
539f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_NETWORKS, "ipnetworknumber" },
549f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_SERVICES, "cn" },
559f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_GROUP, "gidnumber" },
569f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_NETMASKS, "ipnetworknumber"},
579f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_ETHERS, "cn" },
589f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_NETGROUP, "cn" },
599f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_BOOTPARAMS, "cn" },
609f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_PUBLICKEY, "cn" },
619f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_PASSWD, "uid" },
629f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_SHADOW, "uid" },
639f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_ALIASES, "cn" },
649f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_AUTOMOUNT, "automountKey" },
659f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_USERATTR, "uid" },
669f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_PROFILE, "cn" },
679f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_EXECATTR, "cn" },
689f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_AUTHATTR, "cn" },
699f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_AUUSER, "uid" },
709f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_TNRHDB, "ipTnetNumber" },
719f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_TNRHTP, "ipTnetTemplateName" },
729f2fd570SJulian Pullen 	{ NS_LDAP_TYPE_PROJECT, "SolarisProjectName" },
739f2fd570SJulian Pullen 	{ 0, 0 }
749f2fd570SJulian Pullen };
759f2fd570SJulian Pullen 
769f2fd570SJulian Pullen 
777c478bd9Sstevel@tonic-gate void
usage(char * msg)78*c59d9dffSToomas Soome usage(char *msg)
79*c59d9dffSToomas Soome {
807c478bd9Sstevel@tonic-gate 	if (msg)
81b446700bSjanga 		(void) fprintf(stderr, "%s\n", msg);
83*c59d9dffSToomas Soome 	(void) fprintf(stderr, gettext(
84e1dd0a2fSth 	"\n"
85e1dd0a2fSth 	"usage: ldaplist [-dlv] [-h LDAP_server[:serverPort] [-M domainName]\n"
86e1dd0a2fSth 	"[-N  profileName] [-a  authenticationMethod] [-P certifPath]\n"
87e1dd0a2fSth 	"[-D  bindDN] [-w bindPassword] [-j passwdFile]]\n"
88e1dd0a2fSth 	"[<database> [<key>] ...]\n\n"
89e1dd0a2fSth 	"usage: ldaplist -h\n"
90e1dd0a2fSth 	"\n"
91e1dd0a2fSth 	"usage: ldaplist -g\n\n"
927c478bd9Sstevel@tonic-gate 	"\tOptions:\n"
937c478bd9Sstevel@tonic-gate 	"\t    -l list all the attributes found in entry.\n"
947c478bd9Sstevel@tonic-gate 	"\t       By default, it lists only the DNs.\n"
957c478bd9Sstevel@tonic-gate 	"\t    -d list attributes for the database instead of its entries\n"
967c478bd9Sstevel@tonic-gate 	"\t    -v print out the LDAP search filter.\n"
97e1dd0a2fSth 	"\t    -g list the database mappings.\n"
98e1dd0a2fSth 	"\t    -h An address (or a name) and a port of the LDAP server in\n"
99e1dd0a2fSth 	"\t       which the entries will be stored. The default value for\n"
100e1dd0a2fSth 	"\t       the port is 389 (or 636 for TLS connections).\n"
101e1dd0a2fSth 	"\t    -M The name of a domain served by the specified server.\n"
102e1dd0a2fSth 	"\t       If not specified, the default domain name will be used.\n"
103e1dd0a2fSth 	"\t    -N Specifies a DUAProfile name.\n"
104e1dd0a2fSth 	"\t       The default value is \"default\".\n"
105e1dd0a2fSth 	"\t    -a Specifies an authentication method.\n"
106e1dd0a2fSth 	"\t    -P The certificate path for the location of the certificate\n"
107e1dd0a2fSth 	"\t       database.\n"
108e1dd0a2fSth 	"\t    -D Specifies an entry which has read permission to\n"
109e1dd0a2fSth 	"\t       the requested database.\n"
110e1dd0a2fSth 	"\t    -w Password to be used for authenticating the bindDN.\n"
111e1dd0a2fSth 	"\t    -j File containing the password for bindDN or SSL key db.\n"
1127c478bd9Sstevel@tonic-gate 	"\t<database> is the database to be searched in.  Standard system\n"
1137c478bd9Sstevel@tonic-gate 	"\tdatabases are:\n"
1147c478bd9Sstevel@tonic-gate 	"\t\tpassword, printers, group, hosts, ethers, networks, netmasks,\n"
1157c478bd9Sstevel@tonic-gate 	"\t\trpc, bootparams, protocols, services, netgroup, auto_*.\n"
1167c478bd9Sstevel@tonic-gate 	"\tNon-standard system databases can be specified as follows:\n"
1177c478bd9Sstevel@tonic-gate 	"\t\tby specific container: ou=<dbname> or\n"
1187c478bd9Sstevel@tonic-gate 	"\t\tby default container: <dbname>.  In this case, 'nismapname'\n"
1197c478bd9Sstevel@tonic-gate 	"\t\twill be used, thus mapping this to nismapname=<dbname>.\n"
1207c478bd9Sstevel@tonic-gate 	"\t<key> is the key to search in the database.  For the standard\n"
1217c478bd9Sstevel@tonic-gate 	"\tdatabases, the search type for the key is predefined.  You can\n"
122e1dd0a2fSth 	"\toverride this by specifying <type>=<key>.\n"
123e1dd0a2fSth 	"\nNOTE: The old -h option printing the mapping information is "
124e1dd0a2fSth 	"deprecated.\nFor backward compatibility the following mode is "
125e1dd0a2fSth 	"available:\nldaplist -h\n"));
1267c478bd9Sstevel@tonic-gate 	exit(1);
1277c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate  * This is a generic filter call back function for
1317c478bd9Sstevel@tonic-gate  * merging the filter from service search descriptor with
1327c478bd9Sstevel@tonic-gate  * an existing search filter. This routine expects userdata
1337c478bd9Sstevel@tonic-gate  * contain a format string with a single %s in it, and will
1347c478bd9Sstevel@tonic-gate  * use the format string with sprintf() to insert the SSD filter.
1357c478bd9Sstevel@tonic-gate  *
1367c478bd9Sstevel@tonic-gate  * This routine is passed to the __ns_ldap_list() or
1377c478bd9Sstevel@tonic-gate  * __ns_ldap_firstEntry() APIs as the filter call back
1387c478bd9Sstevel@tonic-gate  * together with the userdata. For example,
1397c478bd9Sstevel@tonic-gate  * the "ldaplist hosts sys1" processing may call __ns_ldap_list()
1407c478bd9Sstevel@tonic-gate  * with "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
1417c478bd9Sstevel@tonic-gate  * as the filter call back, and "(&(%s)(cn=sys1))" as the
1427c478bd9Sstevel@tonic-gate  * userdata, this routine will in turn gets call to produce
1437c478bd9Sstevel@tonic-gate  * "(&(department=sds)(cn=sys1))" as the real search
1447c478bd9Sstevel@tonic-gate  * filter, if the input SSD contains a filter "department=sds".
1457c478bd9Sstevel@tonic-gate  */
1467c478bd9Sstevel@tonic-gate static int
merge_SSD_filter(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata)147*c59d9dffSToomas Soome merge_SSD_filter(const ns_ldap_search_desc_t *desc, char **realfilter,
148*c59d9dffSToomas Soome     const void *userdata)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 	int	len;
151528b7d8bSRichard Lowe 	char *checker;
1537c478bd9Sstevel@tonic-gate 	/* sanity check */
1547c478bd9Sstevel@tonic-gate 	if (realfilter == NULL)
1557c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
1567c478bd9Sstevel@tonic-gate 	*realfilter = NULL;
1587c478bd9Sstevel@tonic-gate 	if (desc == NULL || desc->filter == NULL ||
159e1dd0a2fSth 	    userdata == NULL)
1607c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
162528b7d8bSRichard Lowe 	/* Parameter check.  We only want one %s here, otherwise bail. */
163528b7d8bSRichard Lowe 	len = 0;	/* Reuse 'len' as "Number of %s hits"... */
164528b7d8bSRichard Lowe 	checker = (char *)userdata;
165528b7d8bSRichard Lowe 	do {
166528b7d8bSRichard Lowe 		checker = strchr(checker, '%');
167528b7d8bSRichard Lowe 		if (checker != NULL) {
168528b7d8bSRichard Lowe 			if (len > 0 || *(checker + 1) != 's')
169528b7d8bSRichard Lowe 				return (NS_LDAP_INVALID_PARAM);
170528b7d8bSRichard Lowe 			len++;	/* Got our %s. */
171528b7d8bSRichard Lowe 			checker += 2;
172528b7d8bSRichard Lowe 		} else if (len != 1)
173528b7d8bSRichard Lowe 			return (NS_LDAP_INVALID_PARAM);
174528b7d8bSRichard Lowe 	} while (checker != NULL);
175528b7d8bSRichard Lowe 
1767c478bd9Sstevel@tonic-gate 	len = strlen(userdata) + strlen(desc->filter) + 1;
1787c478bd9Sstevel@tonic-gate 	*realfilter = (char *)malloc(len);
1797c478bd9Sstevel@tonic-gate 	if (*realfilter == NULL)
1807c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
1827c478bd9Sstevel@tonic-gate 	(void) sprintf(*realfilter, (char *)userdata,
183e1dd0a2fSth 	    desc->filter);
1857c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1867c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate /* returns 0=success, 1=error */
1897c478bd9Sstevel@tonic-gate int
list(char * database,char * ldapfilter,char ** ldapattribute,char ** err,char * userdata)1907c478bd9Sstevel@tonic-gate list(char *database, char *ldapfilter, char **ldapattribute,
191*c59d9dffSToomas Soome     char **err, char *userdata)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result;
1947c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
1957c478bd9Sstevel@tonic-gate 	int		rc;
1967c478bd9Sstevel@tonic-gate 	char		buf[500];
197*c59d9dffSToomas Soome 	const char	*sort = NULL;
1989f2fd570SJulian Pullen 	int		i;
1999f2fd570SJulian Pullen 
2009f2fd570SJulian Pullen 	if (database) {
2019f2fd570SJulian Pullen 		for (i = 0; databaselist[i].database; i++) {
2029f2fd570SJulian Pullen 			if (strcmp(databaselist[i].database, database) == 0) {
2039f2fd570SJulian Pullen 				sort = databaselist[i].sortattr;
2049f2fd570SJulian Pullen 				break;
2059f2fd570SJulian Pullen 			}
2069f2fd570SJulian Pullen 			if (strcmp(databaselist[i].database,
2079f2fd570SJulian Pullen 			    NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
2089f2fd570SJulian Pullen 			    strncmp(database, NS_LDAP_TYPE_AUTOMOUNT,
2099f2fd570SJulian Pullen 			    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
2109f2fd570SJulian Pullen 				sort = databaselist[i].sortattr;
2119f2fd570SJulian Pullen 				break;
2129f2fd570SJulian Pullen 			}
2139f2fd570SJulian Pullen 		}
2149f2fd570SJulian Pullen 	}
2167c478bd9Sstevel@tonic-gate 	*err = NULL;
2177c478bd9Sstevel@tonic-gate 	buf[0] = '\0';
2189f2fd570SJulian Pullen 	rc = __ns_ldap_list_sort(database, (const char *)ldapfilter,
2199f2fd570SJulian Pullen 	    sort, merge_SSD_filter, (const char **)ldapattribute, NULL,
220e1dd0a2fSth 	    listflag, &result, &errorp, NULL, userdata);
2217c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
2227c478bd9Sstevel@tonic-gate 		char *p;
2237c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_err2str(rc, &p);
2247c478bd9Sstevel@tonic-gate 		if (errorp && errorp->message) {
225b446700bSjanga 			(void) snprintf(buf, sizeof (buf), "%s (%s)",
226e1dd0a2fSth 			    p, errorp->message);
227b446700bSjanga 			(void) __ns_ldap_freeError(&errorp);
2287c478bd9Sstevel@tonic-gate 		} else
229e1dd0a2fSth 			(void) snprintf(buf, sizeof (buf), "%s\n", p);
2307c478bd9Sstevel@tonic-gate 		*err = strdup(buf);
2317c478bd9Sstevel@tonic-gate 		return (rc);
2327c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	_printResult(result);
235b446700bSjanga 	(void) __ns_ldap_freeResult(&result);
2367c478bd9Sstevel@tonic-gate 	return (0);
2377c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate int
switch_err(int rc)2417c478bd9Sstevel@tonic-gate switch_err(int rc)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	switch (rc) {
2447c478bd9Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:
2457c478bd9Sstevel@tonic-gate 		return (0);
2467c478bd9Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:
2477c478bd9Sstevel@tonic-gate 		return (1);
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 	return (2);
2507c478bd9Sstevel@tonic-gate }
252a506a34cSth int
main(int argc,char ** argv)2537c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2547c478bd9Sstevel@tonic-gate {
256e1dd0a2fSth 	extern int		optind;
257e1dd0a2fSth 	char			*database = NULL;
258e1dd0a2fSth 	char			*ldapfilter = NULL;
259e1dd0a2fSth 	char			*attribute = "dn";
260e1dd0a2fSth 	char			**key = NULL;
261e1dd0a2fSth 	char			**ldapattribute = NULL;
262*c59d9dffSToomas Soome 	char			*buffer[100];
263e1dd0a2fSth 	char			*err = NULL;
264e1dd0a2fSth 	char			*p;
265e1dd0a2fSth 	int			index = 1;
266e1dd0a2fSth 	int			c;
267e1dd0a2fSth 	int			rc;
268e1dd0a2fSth 	int			verbose = 0;
269e1dd0a2fSth 	char			*udata = NULL;
271e1dd0a2fSth 	ns_standalone_conf_t	standalone_cfg = standaloneDefaults;
272e1dd0a2fSth 	ns_ldap_error_t		*errorp = NULL;
273e1dd0a2fSth 	char			*authmech = NULL;
274e1dd0a2fSth 	ns_auth_t		auth = {NS_LDAP_AUTH_NONE,
275e1dd0a2fSth 					NS_LDAP_TLS_NONE,
276e1dd0a2fSth 					NS_LDAP_SASL_NONE,
277e1dd0a2fSth 					NS_LDAP_SASLOPT_NONE};
2797c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2807c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2827c478bd9Sstevel@tonic-gate 	openlog("ldaplist", LOG_PID, LOG_USER);
284e1dd0a2fSth 	if (argc == 2 &&
285e1dd0a2fSth 	    strlen(argv[1]) == 2 && strncmp(argv[1], "-h", 2) == 0) {
286e1dd0a2fSth 		/* preserve backwards compatability, support old -h option */
287e1dd0a2fSth 		(void) printMapping();
288e1dd0a2fSth 		exit(0);
289e1dd0a2fSth 	}
291e1dd0a2fSth 	while ((c = getopt(argc, argv, "h:M:N:P:r:a:D:w:j:dgvl")) != EOF) {
2927c478bd9Sstevel@tonic-gate 		switch (c) {
2937c478bd9Sstevel@tonic-gate 		case 'd':
2947c478bd9Sstevel@tonic-gate 			listflag |= NS_LDAP_SCOPE_BASE;
2957c478bd9Sstevel@tonic-gate 			break;
296e1dd0a2fSth 		case 'g':
2977c478bd9Sstevel@tonic-gate 			(void) printMapping();
2987c478bd9Sstevel@tonic-gate 			exit(0);
299b446700bSjanga 			break; /* Never reached */
3007c478bd9Sstevel@tonic-gate 		case 'l':
3017c478bd9Sstevel@tonic-gate 			attribute = "NULL";
3027c478bd9Sstevel@tonic-gate 			break;
3037c478bd9Sstevel@tonic-gate 		case 'v':
3047c478bd9Sstevel@tonic-gate 			verbose = 1;
3057c478bd9Sstevel@tonic-gate 			break;
306e1dd0a2fSth 		case 'M':
307e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
308e1dd0a2fSth 			standalone_cfg.SA_DOMAIN = optarg;
309e1dd0a2fSth 			break;
310e1dd0a2fSth 		case 'h':
311e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
312e1dd0a2fSth 			if (separatePort(optarg,
313e1dd0a2fSth 			    &standalone_cfg.SA_SERVER,
314e1dd0a2fSth 			    &standalone_cfg.SA_PORT) > 0) {
315e1dd0a2fSth 				exit(1);
316e1dd0a2fSth 			}
317e1dd0a2fSth 			break;
318e1dd0a2fSth 		case 'P':
319e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
320e1dd0a2fSth 			standalone_cfg.SA_CERT_PATH = optarg;
321e1dd0a2fSth 			break;
322e1dd0a2fSth 		case 'N':
323e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
324e1dd0a2fSth 			standalone_cfg.SA_PROFILE_NAME = optarg;
325e1dd0a2fSth 			break;
326e1dd0a2fSth 		case 'D':
327e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
328e1dd0a2fSth 			standalone_cfg.SA_BIND_DN = strdup(optarg);
329e1dd0a2fSth 			break;
330e1dd0a2fSth 		case 'w':
331e1dd0a2fSth 			if (standalone_cfg.SA_BIND_PWD != NULL) {
332e1dd0a2fSth 				(void) fprintf(stderr,
333e1dd0a2fSth 				    gettext("The -w option is mutually "
334e1dd0a2fSth 				    "exclusive of -j. -w is ignored.\n"));
335e1dd0a2fSth 				break;
336e1dd0a2fSth 			}
338e1dd0a2fSth 			if (optarg != NULL &&
339e1dd0a2fSth 			    optarg[0] == '-' && optarg[1] == '\0') {
340e1dd0a2fSth 				/* Ask for a password later */
341e1dd0a2fSth 				break;
342e1dd0a2fSth 			}
344e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
345e1dd0a2fSth 			standalone_cfg.SA_BIND_PWD = strdup(optarg);
346e1dd0a2fSth 			break;
347e1dd0a2fSth 		case 'j':
348e1dd0a2fSth 			if (standalone_cfg.SA_BIND_PWD != NULL) {
349e1dd0a2fSth 				(void) fprintf(stderr,
350e1dd0a2fSth 				    gettext("The -w option is mutually "
351e1dd0a2fSth 				    "exclusive of -j. -w is ignored.\n"));
352e1dd0a2fSth 				free(standalone_cfg.SA_BIND_PWD);
353e1dd0a2fSth 			}
354e1dd0a2fSth 			standalone_cfg.type = NS_LDAP_SERVER;
355e1dd0a2fSth 			standalone_cfg.SA_BIND_PWD = readPwd(optarg);
356e1dd0a2fSth 			if (standalone_cfg.SA_BIND_PWD == NULL) {
357e1dd0a2fSth 				exit(1);
358e1dd0a2fSth 			}
359e1dd0a2fSth 			break;
360e1dd0a2fSth 		case 'a':
361e1dd0a2fSth 			authmech = optarg;
362e1dd0a2fSth 			break;
3637c478bd9Sstevel@tonic-gate 		default:
3647c478bd9Sstevel@tonic-gate 			usage(gettext("Invalid option"));
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 	}
368e1dd0a2fSth 	if (standalone_cfg.type == NS_LDAP_SERVER &&
369e1dd0a2fSth 	    standalone_cfg.SA_SERVER == NULL) {
370e1dd0a2fSth 		(void) fprintf(stderr,
371e1dd0a2fSth 		    gettext("Please specify an LDAP server you want "
372e1dd0a2fSth 		    "to connect to. \n"));
373e1dd0a2fSth 		exit(1);
374e1dd0a2fSth 	}
3767c478bd9Sstevel@tonic-gate 	if ((c = argc - optind) > 0)
3777c478bd9Sstevel@tonic-gate 		database = argv[optind++];
3787c478bd9Sstevel@tonic-gate 	if ((--c) > 0)
3797c478bd9Sstevel@tonic-gate 		key = &argv[optind];
381e1dd0a2fSth 	if (authmech != NULL) {
382e1dd0a2fSth 		if (__ns_ldap_initAuth(authmech,
383e1dd0a2fSth 		    &auth,
384e1dd0a2fSth 		    &errorp) != NS_LDAP_SUCCESS) {
385e1dd0a2fSth 			if (errorp) {
386e1dd0a2fSth 				(void) fprintf(stderr, "%s", errorp->message);
387e1dd0a2fSth 				(void) __ns_ldap_freeError(&errorp);
388e1dd0a2fSth 			}
389e1dd0a2fSth 			exit(1);
390e1dd0a2fSth 		}
391e1dd0a2fSth 	}
393e1dd0a2fSth 	if (auth.saslmech != NS_LDAP_SASL_GSSAPI &&
394e1dd0a2fSth 	    standalone_cfg.SA_BIND_DN != NULL &&
395e1dd0a2fSth 	    standalone_cfg.SA_BIND_PWD == NULL) {
396e1dd0a2fSth 		/* If password is not specified, then prompt user for it. */
397e1dd0a2fSth 		standalone_cfg.SA_BIND_PWD =
398e1dd0a2fSth 		    strdup(getpassphrase("Enter password:"));
399e1dd0a2fSth 	}
401e1dd0a2fSth 	standalone_cfg.SA_AUTH = (authmech == NULL) ? NULL : &auth;
403e1dd0a2fSth 	if (__ns_ldap_initStandalone(&standalone_cfg,
404e1dd0a2fSth 	    &errorp) != NS_LDAP_SUCCESS) {
405e1dd0a2fSth 		if (errorp) {
406e1dd0a2fSth 			(void) fprintf(stderr, "%s\n", errorp->message);
407e1dd0a2fSth 			(void) __ns_ldap_freeError(&errorp);
408e1dd0a2fSth 		}
409e1dd0a2fSth 		exit(1);
410e1dd0a2fSth 	}
412e1dd0a2fSth 	if (authmech != NULL) {
413e1dd0a2fSth 		if (__ns_ldap_setParam(NS_LDAP_AUTH_P,
414e1dd0a2fSth 		    authmech, &errorp) != NS_LDAP_SUCCESS) {
415e1dd0a2fSth 			__ns_ldap_cancelStandalone();
416e1dd0a2fSth 			if (errorp != NULL) {
417e1dd0a2fSth 				(void) fprintf(stderr, "%s", errorp->message);
418e1dd0a2fSth 				(void) __ns_ldap_freeError(&errorp);
419e1dd0a2fSth 			}
420e1dd0a2fSth 			exit(1);
421e1dd0a2fSth 		}
422e1dd0a2fSth 	}
423e1dd0a2fSth 	if (standalone_cfg.SA_CRED != NULL) {
424e1dd0a2fSth 		if (__ns_ldap_setParam(NS_LDAP_CREDENTIAL_LEVEL_P,
425e1dd0a2fSth 		    standalone_cfg.SA_CRED, &errorp) != NS_LDAP_SUCCESS) {
426e1dd0a2fSth 			__ns_ldap_cancelStandalone();
427e1dd0a2fSth 			if (errorp != NULL) {
428e1dd0a2fSth 				(void) fprintf(stderr, "%s", errorp->message);
429e1dd0a2fSth 				(void) __ns_ldap_freeError(&errorp);
430e1dd0a2fSth 			}
431e1dd0a2fSth 			exit(1);
432e1dd0a2fSth 		}
433e1dd0a2fSth 	}
435e1dd0a2fSth 	if (standalone_cfg.type != NS_CACHEMGR &&
436e1dd0a2fSth 	    standalone_cfg.SA_BIND_DN != NULL) {
437e1dd0a2fSth 		ns_auth_t **authpp = NULL, **authp = NULL;
439e1dd0a2fSth 		if (__ns_ldap_getParam(NS_LDAP_AUTH_P,
440e1dd0a2fSth 		    (void ***)&authpp,
441e1dd0a2fSth 		    &errorp) != NS_LDAP_SUCCESS || authpp == NULL) {
442e1dd0a2fSth 			__ns_ldap_cancelStandalone();
443e1dd0a2fSth 			(void) __ns_ldap_freeParam((void ***)&authpp);
444e1dd0a2fSth 			if (errorp) {
445e1dd0a2fSth 				(void) fprintf(stderr,
446e1dd0a2fSth 				    gettext(errorp->message));
447e1dd0a2fSth 				(void) __ns_ldap_freeError(&errorp);
448e1dd0a2fSth 			}
449e1dd0a2fSth 			exit(1);
450e1dd0a2fSth 		}
451e1dd0a2fSth 		for (authp = authpp; *authp; authp++) {
452e1dd0a2fSth 			if ((*authp)->saslmech == NS_LDAP_SASL_GSSAPI) {
453e1dd0a2fSth 				/*
454e1dd0a2fSth 				 * For now we have no use for bindDN and
455e1dd0a2fSth 				 * bindPassword when using SASL/GSSAPI.
456e1dd0a2fSth 				 */
457e1dd0a2fSth 				(void) fprintf(stderr,
458e1dd0a2fSth 				    gettext("Warning: SASL/GSSAPI will be "
459e1dd0a2fSth 				    "used as an authentication method"
460e1dd0a2fSth 				    "The bind DN and password will "
461e1dd0a2fSth 				    "be ignored.\n"));
462e1dd0a2fSth 				break;
463e1dd0a2fSth 			}
464e1dd0a2fSth 		}
465e1dd0a2fSth 	}
4677c478bd9Sstevel@tonic-gate 	/*
4687c478bd9Sstevel@tonic-gate 	 * If dumpping a database,
4697c478bd9Sstevel@tonic-gate 	 * or all the containers,
4707c478bd9Sstevel@tonic-gate 	 * use page control just
4717c478bd9Sstevel@tonic-gate 	 * in case there are too many entries
4727c478bd9Sstevel@tonic-gate 	 */
4737c478bd9Sstevel@tonic-gate 	if (!key && !(listflag & NS_LDAP_SCOPE_BASE))
4747c478bd9Sstevel@tonic-gate 		listflag |= NS_LDAP_PAGE_CTRL;
4767c478bd9Sstevel@tonic-gate 	/* build the attribute array */
4777c478bd9Sstevel@tonic-gate 	if (strncasecmp(attribute, "NULL", 4) == 0)
4787c478bd9Sstevel@tonic-gate 		ldapattribute = NULL;
4797c478bd9Sstevel@tonic-gate 	else {
4807c478bd9Sstevel@tonic-gate 		buffer[0] = strdup(attribute);
4817c478bd9Sstevel@tonic-gate 		while ((p = strchr(attribute, ',')) != NULL) {
4827c478bd9Sstevel@tonic-gate 			buffer[index++] = attribute = p + 1;
4837c478bd9Sstevel@tonic-gate 			*p = '\0';
4847c478bd9Sstevel@tonic-gate 		}
4857c478bd9Sstevel@tonic-gate 		buffer[index] = NULL;
4867c478bd9Sstevel@tonic-gate 		ldapattribute = buffer;
4877c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 	/* build the filter */
490*c59d9dffSToomas Soome 	if (database && (strcasecmp(database, "publickey") == 0)) {
4917c478bd9Sstevel@tonic-gate 		/* user publickey lookup */
4927c478bd9Sstevel@tonic-gate 		char *err1 = NULL;
4937c478bd9Sstevel@tonic-gate 		int  rc1;
4957c478bd9Sstevel@tonic-gate 		rc = rc1 = -1;
4967c478bd9Sstevel@tonic-gate 		ldapfilter = set_filter_publickey(key, database, 0, &udata);
4977c478bd9Sstevel@tonic-gate 		if (ldapfilter) {
4987c478bd9Sstevel@tonic-gate 			if (verbose) {
499b446700bSjanga 				(void) fprintf(stdout,
500e1dd0a2fSth 				    gettext("+++ database=%s\n"),
501e1dd0a2fSth 				    (database ? database : "NULL"));
502b446700bSjanga 				(void) fprintf(stdout,
503e1dd0a2fSth 				    gettext("+++ filter=%s\n"),
504e1dd0a2fSth 				    (ldapfilter ? ldapfilter : "NULL"));
505b446700bSjanga 				(void) fprintf(stdout,
5067c478bd9Sstevel@tonic-gate 				gettext("+++ template for merging"
507e1dd0a2fSth 				    "SSD filter=%s\n"),
508e1dd0a2fSth 				    (udata ? udata : "NULL"));
5097c478bd9Sstevel@tonic-gate 			}
5107c478bd9Sstevel@tonic-gate 			rc = list("passwd", ldapfilter, ldapattribute,
511e1dd0a2fSth 			    &err, udata);
5127c478bd9Sstevel@tonic-gate 			free(ldapfilter);
5137c478bd9Sstevel@tonic-gate 			free(udata);
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 		/* hosts publickey lookup */
5167c478bd9Sstevel@tonic-gate 		ldapfilter = set_filter_publickey(key, database, 1, &udata);
5177c478bd9Sstevel@tonic-gate 		if (ldapfilter) {
5187c478bd9Sstevel@tonic-gate 			if (verbose) {
519b446700bSjanga 				(void) fprintf(stdout,
520e1dd0a2fSth 				    gettext("+++ database=%s\n"),
521e1dd0a2fSth 				    (database ? database : "NULL"));
522b446700bSjanga 				(void) fprintf(stdout,
523e1dd0a2fSth 				    gettext("+++ filter=%s\n"),
524e1dd0a2fSth 				    (ldapfilter ? ldapfilter : "NULL"));
525b446700bSjanga 				(void) fprintf(stdout,
5267c478bd9Sstevel@tonic-gate 				gettext("+++ template for merging"
527e1dd0a2fSth 				    "SSD filter=%s\n"),
528e1dd0a2fSth 				    (udata ? udata : "NULL"));
5297c478bd9Sstevel@tonic-gate 			}
5307c478bd9Sstevel@tonic-gate 			rc1 = list("hosts", ldapfilter, ldapattribute,
531e1dd0a2fSth 			    &err1, udata);
5327c478bd9Sstevel@tonic-gate 			free(ldapfilter);
5337c478bd9Sstevel@tonic-gate 			free(udata);
5347c478bd9Sstevel@tonic-gate 		}
5357c478bd9Sstevel@tonic-gate 		if (rc == -1 && rc1 == -1) {
5367c478bd9Sstevel@tonic-gate 			/* this should never happen */
537b446700bSjanga 			(void) fprintf(stderr,
5387c478bd9Sstevel@tonic-gate 			    gettext("ldaplist: invalid publickey lookup\n"));
5397c478bd9Sstevel@tonic-gate 			rc = 2;
5405aa2fb58SChin-Long Shu 		} else if (rc != 0 && rc1 != 0) {
541b446700bSjanga 			(void) fprintf(stderr,
5427c478bd9Sstevel@tonic-gate 			gettext("ldaplist: %s\n"), (err ? err : err1));
5437c478bd9Sstevel@tonic-gate 			if (rc == -1)
5447c478bd9Sstevel@tonic-gate 				rc = rc1;
5457c478bd9Sstevel@tonic-gate 		} else
5467c478bd9Sstevel@tonic-gate 			rc = 0;
5477c478bd9Sstevel@tonic-gate 		exit(switch_err(rc));
5487c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * we set the search filter to (objectclass=*) when we want
5527c478bd9Sstevel@tonic-gate 	 * to list the directory attribute instead of the entries
5537c478bd9Sstevel@tonic-gate 	 * (the -d option).
5547c478bd9Sstevel@tonic-gate 	 */
5557c478bd9Sstevel@tonic-gate 	if (((ldapfilter = set_filter(key, database, &udata)) == NULL) ||
556e1dd0a2fSth 	    (listflag == NS_LDAP_SCOPE_BASE)) {
5577c478bd9Sstevel@tonic-gate 		ldapfilter = strdup("objectclass=*");
5587c478bd9Sstevel@tonic-gate 		udata = strdup("%s");
5597c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 	if (verbose) {
562b446700bSjanga 		(void) fprintf(stdout, gettext("+++ database=%s\n"),
563e1dd0a2fSth 		    (database ? database : "NULL"));
564b446700bSjanga 		(void) fprintf(stdout, gettext("+++ filter=%s\n"),
565e1dd0a2fSth 		    (ldapfilter ? ldapfilter : "NULL"));
566b446700bSjanga 		(void) fprintf(stdout,
567e1dd0a2fSth 		    gettext("+++ template for merging SSD filter=%s\n"),
568e1dd0a2fSth 		    (udata ? udata : "NULL"));
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 	if (rc = list(database, ldapfilter, ldapattribute, &err, udata))
571b446700bSjanga 		(void) fprintf(stderr, gettext("ldaplist: %s\n"), err);
573e1dd0a2fSth 	__ns_ldap_cancelStandalone();
5757c478bd9Sstevel@tonic-gate 	if (ldapfilter)
5767c478bd9Sstevel@tonic-gate 		free(ldapfilter);
5777c478bd9Sstevel@tonic-gate 	if (udata)
5787c478bd9Sstevel@tonic-gate 		free(udata);
5797c478bd9Sstevel@tonic-gate 	exit(switch_err(rc));
580b446700bSjanga 	return (0); /* Never reached */
5817c478bd9Sstevel@tonic-gate }