xref: /illumos-gate/usr/src/cmd/ldap/ns_ldap/ldaplist.c (revision 1a220b56b93ff1dc80855691548503117af4cc10)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <libintl.h>
31 #include <strings.h>
32 #include <locale.h>
33 #include <syslog.h>
34 #include "../../../lib/libsldap/common/ns_sldap.h"
35 
36 extern char *set_filter(char **, char *, char **);
37 extern char *set_filter_publickey(char **, char *, int, char **);
38 extern void _printResult(ns_ldap_result_t *);
39 extern void printMapping();
40 
41 int listflag = 0;
42 
43 void
44 usage(char *msg) {
45 	if (msg)
46 		(void) fprintf(stderr, "%s\n", msg);
47 
48 	(void) fprintf(stderr,
49 	gettext(
50 	"ldaplist [-lvh] [<database> [<key>] ...]\n"
51 	"\tOptions:\n"
52 	"\t    -l list all the attributes found in entry.\n"
53 	"\t       By default, it lists only the DNs.\n"
54 	"\t    -d list attributes for the database instead of its entries\n"
55 	"\t    -v print out the LDAP search filter.\n"
56 	"\t    -h list the database mappings.\n"
57 	"\t<database> is the database to be searched in.  Standard system\n"
58 	"\tdatabases are:\n"
59 	"\t\tpassword, printers, group, hosts, ethers, networks, netmasks,\n"
60 	"\t\trpc, bootparams, protocols, services, netgroup, auto_*.\n"
61 	"\tNon-standard system databases can be specified as follows:\n"
62 	"\t\tby specific container: ou=<dbname> or\n"
63 	"\t\tby default container: <dbname>.  In this case, 'nismapname'\n"
64 	"\t\twill be used, thus mapping this to nismapname=<dbname>.\n"
65 	"\t<key> is the key to search in the database.  For the standard\n"
66 	"\tdatabases, the search type for the key is predefined.  You can\n"
67 	"\toverride this by specifying <type>=<key>.\n"));
68 	exit(1);
69 }
70 
71 /*
72  * This is a generic filter call back function for
73  * merging the filter from service search descriptor with
74  * an existing search filter. This routine expects userdata
75  * contain a format string with a single %s in it, and will
76  * use the format string with sprintf() to insert the SSD filter.
77  *
78  * This routine is passed to the __ns_ldap_list() or
79  * __ns_ldap_firstEntry() APIs as the filter call back
80  * together with the userdata. For example,
81  * the "ldaplist hosts sys1" processing may call __ns_ldap_list()
82  * with "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
83  * as the filter call back, and "(&(%s)(cn=sys1))" as the
84  * userdata, this routine will in turn gets call to produce
85  * "(&(department=sds)(cn=sys1))" as the real search
86  * filter, if the input SSD contains a filter "department=sds".
87  */
88 static int
89 merge_SSD_filter(const ns_ldap_search_desc_t *desc,
90 			char **realfilter,
91 			const void *userdata)
92 {
93 	int	len;
94 
95 	/* sanity check */
96 	if (realfilter == NULL)
97 		return (NS_LDAP_INVALID_PARAM);
98 	*realfilter = NULL;
99 
100 	if (desc == NULL || desc->filter == NULL ||
101 			userdata == NULL)
102 		return (NS_LDAP_INVALID_PARAM);
103 
104 	len = strlen(userdata) + strlen(desc->filter) + 1;
105 
106 	*realfilter = (char *)malloc(len);
107 	if (*realfilter == NULL)
108 		return (NS_LDAP_MEMORY);
109 
110 	(void) sprintf(*realfilter, (char *)userdata,
111 			desc->filter);
112 
113 	return (NS_LDAP_SUCCESS);
114 }
115 
116 /* returns 0=success, 1=error */
117 int
118 list(char *database, char *ldapfilter, char **ldapattribute,
119 char **err, char *userdata)
120 {
121 	ns_ldap_result_t	*result;
122 	ns_ldap_error_t	*errorp;
123 	int		rc;
124 	char		buf[500];
125 
126 	*err = NULL;
127 	buf[0] = '\0';
128 	rc = __ns_ldap_list(database, (const char *)ldapfilter,
129 		merge_SSD_filter, (const char **)ldapattribute, NULL,
130 		listflag, &result, &errorp, NULL, userdata);
131 	if (rc != NS_LDAP_SUCCESS) {
132 		char *p;
133 		(void) __ns_ldap_err2str(rc, &p);
134 		if (errorp && errorp->message) {
135 			(void) snprintf(buf, sizeof (buf), "%s (%s)",
136 					p, errorp->message);
137 			(void) __ns_ldap_freeError(&errorp);
138 		} else
139 			(void) snprintf(buf, sizeof (buf), "%s", p);
140 		*err = strdup(buf);
141 		return (rc);
142 	}
143 
144 	_printResult(result);
145 	(void) __ns_ldap_freeResult(&result);
146 	return (0);
147 }
148 
149 
150 int
151 switch_err(int rc)
152 {
153 	switch (rc) {
154 	case NS_LDAP_SUCCESS:
155 		return (0);
156 	case NS_LDAP_NOTFOUND:
157 		return (1);
158 	}
159 	return (2);
160 }
161 
162 int
163 main(int argc, char **argv)
164 {
165 
166 	extern int optind;
167 	char	*database = NULL;
168 	char	*ldapfilter = NULL;
169 	char	*attribute = "dn";
170 	char	**key = NULL;
171 	char	**ldapattribute = NULL;
172 	char 	*buffer[100];
173 	char	*err = NULL;
174 	char	*p;
175 	int	index = 1;
176 	int	c;
177 	int	rc;
178 	int	verbose = 0;
179 	char	*udata = NULL;
180 
181 	(void) setlocale(LC_ALL, "");
182 	(void) textdomain(TEXT_DOMAIN);
183 
184 	openlog("ldaplist", LOG_PID, LOG_USER);
185 
186 	while ((c = getopt(argc, argv, "dhvl")) != EOF) {
187 		switch (c) {
188 		case 'd':
189 			listflag |= NS_LDAP_SCOPE_BASE;
190 			break;
191 		case 'h':
192 			(void) printMapping();
193 			exit(0);
194 			break; /* Never reached */
195 		case 'l':
196 			attribute = "NULL";
197 			break;
198 		case 'v':
199 			verbose = 1;
200 			break;
201 		default:
202 			usage(gettext("Invalid option"));
203 		}
204 	}
205 	if ((c = argc - optind) > 0)
206 		database = argv[optind++];
207 	if ((--c) > 0)
208 		key = &argv[optind];
209 
210 	/*
211 	 * If dumpping a database,
212 	 * or all the containers,
213 	 * use page control just
214 	 * in case there are too many entries
215 	 */
216 	if (!key && !(listflag & NS_LDAP_SCOPE_BASE))
217 		listflag |= NS_LDAP_PAGE_CTRL;
218 
219 	/* build the attribute array */
220 	if (strncasecmp(attribute, "NULL", 4) == 0)
221 		ldapattribute = NULL;
222 	else {
223 		buffer[0] = strdup(attribute);
224 		while ((p = strchr(attribute, ',')) != NULL) {
225 			buffer[index++] = attribute = p + 1;
226 			*p = '\0';
227 		}
228 		buffer[index] = NULL;
229 		ldapattribute = buffer;
230 	}
231 
232 	/* build the filter */
233 	if (database && (strcasecmp(database, "publickey") == NULL)) {
234 		/* user publickey lookup */
235 		char *err1 = NULL;
236 		int  rc1;
237 
238 		rc = rc1 = -1;
239 		ldapfilter = set_filter_publickey(key, database, 0, &udata);
240 		if (ldapfilter) {
241 			if (verbose) {
242 				(void) fprintf(stdout,
243 					gettext("+++ database=%s\n"),
244 					(database ? database : "NULL"));
245 				(void) fprintf(stdout,
246 					gettext("+++ filter=%s\n"),
247 					(ldapfilter ? ldapfilter : "NULL"));
248 				(void) fprintf(stdout,
249 				gettext("+++ template for merging"
250 					"SSD filter=%s\n"),
251 					(udata ? udata : "NULL"));
252 			}
253 			rc = list("passwd", ldapfilter, ldapattribute,
254 				&err, udata);
255 			free(ldapfilter);
256 			free(udata);
257 		}
258 		/* hosts publickey lookup */
259 		ldapfilter = set_filter_publickey(key, database, 1, &udata);
260 		if (ldapfilter) {
261 			if (verbose) {
262 				(void) fprintf(stdout,
263 					gettext("+++ database=%s\n"),
264 					(database ? database : "NULL"));
265 				(void) fprintf(stdout,
266 					gettext("+++ filter=%s\n"),
267 					(ldapfilter ? ldapfilter : "NULL"));
268 				(void) fprintf(stdout,
269 				gettext("+++ template for merging"
270 					"SSD filter=%s\n"),
271 					(udata ? udata : "NULL"));
272 			}
273 			rc1 = list("hosts", ldapfilter, ldapattribute,
274 				&err1, udata);
275 			free(ldapfilter);
276 			free(udata);
277 		}
278 		if (rc == -1 && rc1 == -1) {
279 			/* this should never happen */
280 			(void) fprintf(stderr,
281 			    gettext("ldaplist: invalid publickey lookup\n"));
282 			rc = 2;
283 		} if (rc != 0 && rc1 != 0) {
284 			(void) fprintf(stderr,
285 			gettext("ldaplist: %s\n"), (err ? err : err1));
286 			if (rc == -1)
287 				rc = rc1;
288 		} else
289 			rc = 0;
290 		exit(switch_err(rc));
291 	}
292 
293 	/*
294 	 * we set the search filter to (objectclass=*) when we want
295 	 * to list the directory attribute instead of the entries
296 	 * (the -d option).
297 	 */
298 	if (((ldapfilter = set_filter(key, database, &udata)) == NULL) ||
299 			(listflag == NS_LDAP_SCOPE_BASE)) {
300 		ldapfilter = strdup("objectclass=*");
301 		udata = strdup("%s");
302 	}
303 
304 	if (verbose) {
305 		(void) fprintf(stdout, gettext("+++ database=%s\n"),
306 			(database ? database : "NULL"));
307 		(void) fprintf(stdout, gettext("+++ filter=%s\n"),
308 			(ldapfilter ? ldapfilter : "NULL"));
309 		(void) fprintf(stdout,
310 			gettext("+++ template for merging SSD filter=%s\n"),
311 			(udata ? udata : "NULL"));
312 	}
313 	if (rc = list(database, ldapfilter, ldapattribute, &err, udata))
314 		(void) fprintf(stderr, gettext("ldaplist: %s\n"), err);
315 	if (ldapfilter)
316 		free(ldapfilter);
317 	if (udata)
318 		free(udata);
319 	exit(switch_err(rc));
320 	return (0); /* Never reached */
321 }
322