xref: /illumos-gate/usr/src/cmd/ldap/ns_ldap/ldaplist.c (revision b446700b)
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
5*b446700bSjanga  * Common Development and Distribution License (the "License").
6*b446700bSjanga  * 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 /*
22*b446700bSjanga  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <libintl.h>
317c478bd9Sstevel@tonic-gate #include <strings.h>
327c478bd9Sstevel@tonic-gate #include <locale.h>
337c478bd9Sstevel@tonic-gate #include <syslog.h>
347c478bd9Sstevel@tonic-gate #include "../../../lib/libsldap/common/ns_sldap.h"
357c478bd9Sstevel@tonic-gate 
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 *);
39*b446700bSjanga extern void printMapping();
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate int listflag = 0;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate void
447c478bd9Sstevel@tonic-gate usage(char *msg) {
457c478bd9Sstevel@tonic-gate 	if (msg)
46*b446700bSjanga 		(void) fprintf(stderr, "%s\n", msg);
477c478bd9Sstevel@tonic-gate 
48*b446700bSjanga 	(void) fprintf(stderr,
497c478bd9Sstevel@tonic-gate 	gettext(
507c478bd9Sstevel@tonic-gate 	"ldaplist [-lvh] [<database> [<key>] ...]\n"
517c478bd9Sstevel@tonic-gate 	"\tOptions:\n"
527c478bd9Sstevel@tonic-gate 	"\t    -l list all the attributes found in entry.\n"
537c478bd9Sstevel@tonic-gate 	"\t       By default, it lists only the DNs.\n"
547c478bd9Sstevel@tonic-gate 	"\t    -d list attributes for the database instead of its entries\n"
557c478bd9Sstevel@tonic-gate 	"\t    -v print out the LDAP search filter.\n"
567c478bd9Sstevel@tonic-gate 	"\t    -h list the database mappings.\n"
577c478bd9Sstevel@tonic-gate 	"\t<database> is the database to be searched in.  Standard system\n"
587c478bd9Sstevel@tonic-gate 	"\tdatabases are:\n"
597c478bd9Sstevel@tonic-gate 	"\t\tpassword, printers, group, hosts, ethers, networks, netmasks,\n"
607c478bd9Sstevel@tonic-gate 	"\t\trpc, bootparams, protocols, services, netgroup, auto_*.\n"
617c478bd9Sstevel@tonic-gate 	"\tNon-standard system databases can be specified as follows:\n"
627c478bd9Sstevel@tonic-gate 	"\t\tby specific container: ou=<dbname> or\n"
637c478bd9Sstevel@tonic-gate 	"\t\tby default container: <dbname>.  In this case, 'nismapname'\n"
647c478bd9Sstevel@tonic-gate 	"\t\twill be used, thus mapping this to nismapname=<dbname>.\n"
657c478bd9Sstevel@tonic-gate 	"\t<key> is the key to search in the database.  For the standard\n"
667c478bd9Sstevel@tonic-gate 	"\tdatabases, the search type for the key is predefined.  You can\n"
677c478bd9Sstevel@tonic-gate 	"\toverride this by specifying <type>=<key>.\n"));
687c478bd9Sstevel@tonic-gate 	exit(1);
697c478bd9Sstevel@tonic-gate }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * This is a generic filter call back function for
737c478bd9Sstevel@tonic-gate  * merging the filter from service search descriptor with
747c478bd9Sstevel@tonic-gate  * an existing search filter. This routine expects userdata
757c478bd9Sstevel@tonic-gate  * contain a format string with a single %s in it, and will
767c478bd9Sstevel@tonic-gate  * use the format string with sprintf() to insert the SSD filter.
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  * This routine is passed to the __ns_ldap_list() or
797c478bd9Sstevel@tonic-gate  * __ns_ldap_firstEntry() APIs as the filter call back
807c478bd9Sstevel@tonic-gate  * together with the userdata. For example,
817c478bd9Sstevel@tonic-gate  * the "ldaplist hosts sys1" processing may call __ns_ldap_list()
827c478bd9Sstevel@tonic-gate  * with "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
837c478bd9Sstevel@tonic-gate  * as the filter call back, and "(&(%s)(cn=sys1))" as the
847c478bd9Sstevel@tonic-gate  * userdata, this routine will in turn gets call to produce
857c478bd9Sstevel@tonic-gate  * "(&(department=sds)(cn=sys1))" as the real search
867c478bd9Sstevel@tonic-gate  * filter, if the input SSD contains a filter "department=sds".
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate static int
897c478bd9Sstevel@tonic-gate merge_SSD_filter(const ns_ldap_search_desc_t *desc,
907c478bd9Sstevel@tonic-gate 			char **realfilter,
917c478bd9Sstevel@tonic-gate 			const void *userdata)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	int	len;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/* sanity check */
967c478bd9Sstevel@tonic-gate 	if (realfilter == NULL)
977c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
987c478bd9Sstevel@tonic-gate 	*realfilter = NULL;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	if (desc == NULL || desc->filter == NULL ||
1017c478bd9Sstevel@tonic-gate 			userdata == NULL)
1027c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	len = strlen(userdata) + strlen(desc->filter) + 1;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	*realfilter = (char *)malloc(len);
1077c478bd9Sstevel@tonic-gate 	if (*realfilter == NULL)
1087c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	(void) sprintf(*realfilter, (char *)userdata,
1117c478bd9Sstevel@tonic-gate 			desc->filter);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /* returns 0=success, 1=error */
1177c478bd9Sstevel@tonic-gate int
1187c478bd9Sstevel@tonic-gate list(char *database, char *ldapfilter, char **ldapattribute,
1197c478bd9Sstevel@tonic-gate char **err, char *userdata)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result;
1227c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
1237c478bd9Sstevel@tonic-gate 	int		rc;
1247c478bd9Sstevel@tonic-gate 	char		buf[500];
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	*err = NULL;
1277c478bd9Sstevel@tonic-gate 	buf[0] = '\0';
1287c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_list(database, (const char *)ldapfilter,
1297c478bd9Sstevel@tonic-gate 		merge_SSD_filter, (const char **)ldapattribute, NULL,
1307c478bd9Sstevel@tonic-gate 		listflag, &result, &errorp, NULL, userdata);
1317c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
1327c478bd9Sstevel@tonic-gate 		char *p;
1337c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_err2str(rc, &p);
1347c478bd9Sstevel@tonic-gate 		if (errorp && errorp->message) {
135*b446700bSjanga 			(void) snprintf(buf, sizeof (buf), "%s (%s)",
136*b446700bSjanga 					p, errorp->message);
137*b446700bSjanga 			(void) __ns_ldap_freeError(&errorp);
1387c478bd9Sstevel@tonic-gate 		} else
139*b446700bSjanga 			(void) snprintf(buf, sizeof (buf), "%s", p);
1407c478bd9Sstevel@tonic-gate 		*err = strdup(buf);
1417c478bd9Sstevel@tonic-gate 		return (rc);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	_printResult(result);
145*b446700bSjanga 	(void) __ns_ldap_freeResult(&result);
1467c478bd9Sstevel@tonic-gate 	return (0);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate int
1517c478bd9Sstevel@tonic-gate switch_err(int rc)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	switch (rc) {
1547c478bd9Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:
1557c478bd9Sstevel@tonic-gate 		return (0);
1567c478bd9Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:
1577c478bd9Sstevel@tonic-gate 		return (1);
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 	return (2);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
162a506a34cSth int
1637c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	extern int optind;
1677c478bd9Sstevel@tonic-gate 	char	*database = NULL;
1687c478bd9Sstevel@tonic-gate 	char	*ldapfilter = NULL;
1697c478bd9Sstevel@tonic-gate 	char	*attribute = "dn";
1707c478bd9Sstevel@tonic-gate 	char	**key = NULL;
1717c478bd9Sstevel@tonic-gate 	char	**ldapattribute = NULL;
1727c478bd9Sstevel@tonic-gate 	char 	*buffer[100];
1737c478bd9Sstevel@tonic-gate 	char	*err = NULL;
1747c478bd9Sstevel@tonic-gate 	char	*p;
1757c478bd9Sstevel@tonic-gate 	int	index = 1;
176*b446700bSjanga 	int	c;
1777c478bd9Sstevel@tonic-gate 	int	rc;
1787c478bd9Sstevel@tonic-gate 	int	verbose = 0;
1797c478bd9Sstevel@tonic-gate 	char	*udata = NULL;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1827c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	openlog("ldaplist", LOG_PID, LOG_USER);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "dhvl")) != EOF) {
1877c478bd9Sstevel@tonic-gate 		switch (c) {
1887c478bd9Sstevel@tonic-gate 		case 'd':
1897c478bd9Sstevel@tonic-gate 			listflag |= NS_LDAP_SCOPE_BASE;
1907c478bd9Sstevel@tonic-gate 			break;
1917c478bd9Sstevel@tonic-gate 		case 'h':
1927c478bd9Sstevel@tonic-gate 			(void) printMapping();
1937c478bd9Sstevel@tonic-gate 			exit(0);
194*b446700bSjanga 			break; /* Never reached */
1957c478bd9Sstevel@tonic-gate 		case 'l':
1967c478bd9Sstevel@tonic-gate 			attribute = "NULL";
1977c478bd9Sstevel@tonic-gate 			break;
1987c478bd9Sstevel@tonic-gate 		case 'v':
1997c478bd9Sstevel@tonic-gate 			verbose = 1;
2007c478bd9Sstevel@tonic-gate 			break;
2017c478bd9Sstevel@tonic-gate 		default:
2027c478bd9Sstevel@tonic-gate 			usage(gettext("Invalid option"));
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 	if ((c = argc - optind) > 0)
2067c478bd9Sstevel@tonic-gate 		database = argv[optind++];
2077c478bd9Sstevel@tonic-gate 	if ((--c) > 0)
2087c478bd9Sstevel@tonic-gate 		key = &argv[optind];
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/*
2117c478bd9Sstevel@tonic-gate 	 * If dumpping a database,
2127c478bd9Sstevel@tonic-gate 	 * or all the containers,
2137c478bd9Sstevel@tonic-gate 	 * use page control just
2147c478bd9Sstevel@tonic-gate 	 * in case there are too many entries
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	if (!key && !(listflag & NS_LDAP_SCOPE_BASE))
2177c478bd9Sstevel@tonic-gate 		listflag |= NS_LDAP_PAGE_CTRL;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	/* build the attribute array */
2207c478bd9Sstevel@tonic-gate 	if (strncasecmp(attribute, "NULL", 4) == 0)
2217c478bd9Sstevel@tonic-gate 		ldapattribute = NULL;
2227c478bd9Sstevel@tonic-gate 	else {
2237c478bd9Sstevel@tonic-gate 		buffer[0] = strdup(attribute);
2247c478bd9Sstevel@tonic-gate 		while ((p = strchr(attribute, ',')) != NULL) {
2257c478bd9Sstevel@tonic-gate 			buffer[index++] = attribute = p + 1;
2267c478bd9Sstevel@tonic-gate 			*p = '\0';
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 		buffer[index] = NULL;
2297c478bd9Sstevel@tonic-gate 		ldapattribute = buffer;
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/* build the filter */
2337c478bd9Sstevel@tonic-gate 	if (database && (strcasecmp(database, "publickey") == NULL)) {
2347c478bd9Sstevel@tonic-gate 		/* user publickey lookup */
2357c478bd9Sstevel@tonic-gate 		char *err1 = NULL;
2367c478bd9Sstevel@tonic-gate 		int  rc1;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 		rc = rc1 = -1;
2397c478bd9Sstevel@tonic-gate 		ldapfilter = set_filter_publickey(key, database, 0, &udata);
2407c478bd9Sstevel@tonic-gate 		if (ldapfilter) {
2417c478bd9Sstevel@tonic-gate 			if (verbose) {
242*b446700bSjanga 				(void) fprintf(stdout,
243*b446700bSjanga 					gettext("+++ database=%s\n"),
2447c478bd9Sstevel@tonic-gate 					(database ? database : "NULL"));
245*b446700bSjanga 				(void) fprintf(stdout,
246*b446700bSjanga 					gettext("+++ filter=%s\n"),
2477c478bd9Sstevel@tonic-gate 					(ldapfilter ? ldapfilter : "NULL"));
248*b446700bSjanga 				(void) fprintf(stdout,
2497c478bd9Sstevel@tonic-gate 				gettext("+++ template for merging"
2507c478bd9Sstevel@tonic-gate 					"SSD filter=%s\n"),
2517c478bd9Sstevel@tonic-gate 					(udata ? udata : "NULL"));
2527c478bd9Sstevel@tonic-gate 			}
2537c478bd9Sstevel@tonic-gate 			rc = list("passwd", ldapfilter, ldapattribute,
2547c478bd9Sstevel@tonic-gate 				&err, udata);
2557c478bd9Sstevel@tonic-gate 			free(ldapfilter);
2567c478bd9Sstevel@tonic-gate 			free(udata);
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 		/* hosts publickey lookup */
2597c478bd9Sstevel@tonic-gate 		ldapfilter = set_filter_publickey(key, database, 1, &udata);
2607c478bd9Sstevel@tonic-gate 		if (ldapfilter) {
2617c478bd9Sstevel@tonic-gate 			if (verbose) {
262*b446700bSjanga 				(void) fprintf(stdout,
263*b446700bSjanga 					gettext("+++ database=%s\n"),
2647c478bd9Sstevel@tonic-gate 					(database ? database : "NULL"));
265*b446700bSjanga 				(void) fprintf(stdout,
266*b446700bSjanga 					gettext("+++ filter=%s\n"),
2677c478bd9Sstevel@tonic-gate 					(ldapfilter ? ldapfilter : "NULL"));
268*b446700bSjanga 				(void) fprintf(stdout,
2697c478bd9Sstevel@tonic-gate 				gettext("+++ template for merging"
2707c478bd9Sstevel@tonic-gate 					"SSD filter=%s\n"),
2717c478bd9Sstevel@tonic-gate 					(udata ? udata : "NULL"));
2727c478bd9Sstevel@tonic-gate 			}
2737c478bd9Sstevel@tonic-gate 			rc1 = list("hosts", ldapfilter, ldapattribute,
2747c478bd9Sstevel@tonic-gate 				&err1, udata);
2757c478bd9Sstevel@tonic-gate 			free(ldapfilter);
2767c478bd9Sstevel@tonic-gate 			free(udata);
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 		if (rc == -1 && rc1 == -1) {
2797c478bd9Sstevel@tonic-gate 			/* this should never happen */
280*b446700bSjanga 			(void) fprintf(stderr,
2817c478bd9Sstevel@tonic-gate 			    gettext("ldaplist: invalid publickey lookup\n"));
2827c478bd9Sstevel@tonic-gate 			rc = 2;
2837c478bd9Sstevel@tonic-gate 		} if (rc != 0 && rc1 != 0) {
284*b446700bSjanga 			(void) fprintf(stderr,
2857c478bd9Sstevel@tonic-gate 			gettext("ldaplist: %s\n"), (err ? err : err1));
2867c478bd9Sstevel@tonic-gate 			if (rc == -1)
2877c478bd9Sstevel@tonic-gate 				rc = rc1;
2887c478bd9Sstevel@tonic-gate 		} else
2897c478bd9Sstevel@tonic-gate 			rc = 0;
2907c478bd9Sstevel@tonic-gate 		exit(switch_err(rc));
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * we set the search filter to (objectclass=*) when we want
2957c478bd9Sstevel@tonic-gate 	 * to list the directory attribute instead of the entries
2967c478bd9Sstevel@tonic-gate 	 * (the -d option).
2977c478bd9Sstevel@tonic-gate 	 */
2987c478bd9Sstevel@tonic-gate 	if (((ldapfilter = set_filter(key, database, &udata)) == NULL) ||
2997c478bd9Sstevel@tonic-gate 			(listflag == NS_LDAP_SCOPE_BASE)) {
3007c478bd9Sstevel@tonic-gate 		ldapfilter = strdup("objectclass=*");
3017c478bd9Sstevel@tonic-gate 		udata = strdup("%s");
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	if (verbose) {
305*b446700bSjanga 		(void) fprintf(stdout, gettext("+++ database=%s\n"),
3067c478bd9Sstevel@tonic-gate 			(database ? database : "NULL"));
307*b446700bSjanga 		(void) fprintf(stdout, gettext("+++ filter=%s\n"),
3087c478bd9Sstevel@tonic-gate 			(ldapfilter ? ldapfilter : "NULL"));
309*b446700bSjanga 		(void) fprintf(stdout,
3107c478bd9Sstevel@tonic-gate 			gettext("+++ template for merging SSD filter=%s\n"),
3117c478bd9Sstevel@tonic-gate 			(udata ? udata : "NULL"));
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 	if (rc = list(database, ldapfilter, ldapattribute, &err, udata))
314*b446700bSjanga 		(void) fprintf(stderr, gettext("ldaplist: %s\n"), err);
3157c478bd9Sstevel@tonic-gate 	if (ldapfilter)
3167c478bd9Sstevel@tonic-gate 		free(ldapfilter);
3177c478bd9Sstevel@tonic-gate 	if (udata)
3187c478bd9Sstevel@tonic-gate 		free(udata);
3197c478bd9Sstevel@tonic-gate 	exit(switch_err(rc));
320*b446700bSjanga 	return (0); /* Never reached */
3217c478bd9Sstevel@tonic-gate }
322