xref: /titanic_52/usr/src/cmd/ldap/ns_ldap/mapping.c (revision fb3fb4f3d76d55b64440afd0af72775dfad3bd1d)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <ctype.h>
30 #include <libintl.h>
31 #include <strings.h>
32 #include <stdio.h>
33 #include "../../../lib/libsldap/common/ns_sldap.h"
34 
35 
36 #define	MAXLINE	2000
37 #define	SAME	0
38 
39 struct mapping {
40 	char *database;
41 	char *def_type;
42 	char *objectclass;
43 	char *actual_db;
44 };
45 
46 #define	PUBLICKEY	0
47 
48 static struct mapping maplist[] = {
49 	{"publickey", "uidnumber", "niskeyobject", "passwd"},
50 	{"publickey", "cn", "niskeyobject", "host"},
51 	{"bootparams", "cn", "bootableDevice", NULL},
52 	{"ethers", "cn", "ieee802Device", NULL},
53 	{"group", "cn", "posixgroup", NULL},
54 	{"hosts", "cn", "iphost", NULL},
55 	{"ipnodes", "cn", "iphost", NULL},
56 	{"netgroup", "cn", "nisnetgroup", NULL},
57 	{"netmasks", "ipnetworknumber", "ipnetwork", NULL},
58 	{"networks", "ipnetworknumber", "ipnetwork", NULL},
59 	{"passwd", "uid", "posixaccount", NULL},
60 	{"protocols", "cn", "ipprotocol", NULL},
61 	{"rpc", "cn", "oncrpc", NULL},
62 	{"services", "cn", "ipservice", NULL},
63 	{"aliases", "cn", "mailGroup", NULL},
64 	{"project", "SolarisProjectID", "SolarisProject", NULL},
65 	{"printers", "printer-uri", "sunPrinter", NULL},
66 	{"shadow", "uid", "shadowaccount", NULL},
67 	{"auth_attr", "cn", "SolarisAuthAttr", NULL},
68 	{"prof_attr", "cn", "SolarisProfAttr", NULL},
69 	{"exec_attr", "cn", "SolarisExecAttr", NULL},
70 	{"user_attr", "uid", "SolarisUserAttr", NULL},
71 	{"audit_user", "uid", "SolarisAuditUser", NULL},
72 	{NULL, NULL, NULL, NULL}
73 };
74 
75 
76 void
77 printMapping()
78 {
79 	int	i;
80 
81 	fprintf(stdout,
82 		gettext("database       default type        objectclass\n"));
83 	fprintf(stdout,
84 		gettext("=============  =================   =============\n"));
85 	/* first dump auto_* and automount which are not in maplist[] */
86 	fprintf(stdout, "%-15s%-20s%s\n", "auto_*", "automountKey",
87 		"automount");
88 	fprintf(stdout, "%-15s%-20s%s\n", "automount", "automountMapName",
89 		"automountMap");
90 	for (i = 0; maplist[i].database != NULL; i++) {
91 	/* skip printing shadow */
92 	if (strcasecmp(maplist[i].database, "shadow") != 0)
93 		fprintf(stdout, "%-15s%-20s%s\n", maplist[i].database,
94 			maplist[i].def_type, maplist[i].objectclass);
95 	}
96 }
97 
98 
99 char *
100 set_keys(char **key, char *attrtype)
101 {
102 	char	*keyeq = NULL;
103 	static char	keyfilter[MAXLINE];
104 	char	typeeq[100];
105 	char	buf[100];
106 	char	*k, **karray;
107 
108 	if (!key || !key[0])	/* should never contain NULL string */
109 		return (NULL);
110 
111 	if (attrtype) {
112 		strcpy(typeeq, attrtype);
113 		strcat(typeeq, "=");
114 	}
115 
116 	keyfilter[0] = '\0';
117 	if (key[1])
118 		strcat(keyfilter, "(|");
119 	karray = key;
120 	while (k = *karray) {
121 		keyeq = strchr(k, '=');
122 		sprintf(buf, "(%s%s)", (keyeq ? "" : typeeq), k);
123 		if (strlen(buf) + strlen(keyfilter) >= MAXLINE) {
124 			fprintf(stdout,
125 				gettext("***ERROR: ldapfilter too long\n"));
126 			exit(2);
127 		}
128 		strcat(keyfilter, buf);
129 		karray++;
130 	}
131 	if (key[1])
132 		strcat(keyfilter, ")");
133 	return (keyfilter);
134 }
135 
136 
137 /*
138  * A special set_key routine for to handle public keys.
139  * If the key starts with a digiti, view it as a user id.
140  * Otherwise, view it as a hostname.
141  * It returns: -1 no keys defined, 0 key defined but none for type
142  *		specified, n>0 number of matches found.
143  */
144 int
145 set_keys_publickey(char **key, char *attrtype, int type, char **ret)
146 {
147 	char	*keyeq = NULL;
148 	static char	keyfilter[MAXLINE];
149 	char	pre_filter[MAXLINE];
150 	char	buf[100];
151 	char	*k, **karray;
152 	int	count = 0;
153 
154 	if (!key || !key[0]) {	/* should never contain NULL string */
155 		*ret = NULL;
156 		return (-1);
157 	}
158 
159 	keyfilter[0] = '\0';
160 	pre_filter[0] = '\0';
161 	karray = key;
162 	while (k = *karray) {
163 		keyeq = strchr(k, '=');
164 		if (keyeq)
165 			sprintf(buf, "(%s)", k);
166 		else {
167 			if (type == 0 && isdigit(*k)) {
168 				/* user type keys */
169 				sprintf(buf, "(%s=%s)", attrtype, k);
170 			} else if (type == 1 && (!isdigit(*k))) {
171 				/* hosts type keys */
172 				sprintf(buf, "(%s=%s)", attrtype, k);
173 			} else {
174 				karray++;
175 				continue;
176 			}
177 		}
178 		if (strlen(buf) + strlen(pre_filter) >= MAXLINE) {
179 			fprintf(stdout,
180 				gettext("***ERROR: ldapfilter too long\n"));
181 			exit(2);
182 		}
183 		strcat(pre_filter, buf);
184 		karray++;
185 		count++;
186 	}
187 	if (count > 1) {
188 		if (strlen(pre_filter) + 4 >= MAXLINE) {
189 			fprintf(stdout,
190 				gettext("***ERROR: ldapfilter too long\n"));
191 			exit(2);
192 		}
193 		strcat(keyfilter, "(|");
194 		strcat(keyfilter, pre_filter);
195 		strcat(keyfilter, ")");
196 		*ret = keyfilter;
197 	} else
198 		*ret = pre_filter;
199 	return (count);
200 }
201 
202 /*
203  * publickey specific set_filter
204  * type 0 -> check for user publickeys
205  * type 1 -> check for hosts publickeys
206  */
207 char *
208 set_filter_publickey(char **key, char *database, int type, char **udata)
209 {
210 	char 	*filter;
211 	char 	*userdata;
212 	char	*keyfilter;
213 	int	rc;
214 
215 	if (!database) {
216 		return (NULL);
217 	}
218 	if (!udata) {
219 		return (NULL);
220 	}
221 
222 	filter = (char *)malloc(MAXLINE);
223 	if (!filter) {
224 		return (NULL);
225 	}
226 	filter[0] = '\0';
227 
228 	userdata = (char *)malloc(MAXLINE);
229 	if (!userdata) {
230 		free(filter);
231 		return (NULL);
232 	}
233 	userdata[0] = '\0';
234 	*udata = userdata;
235 
236 	if (strcasecmp(database, maplist[PUBLICKEY].database) == SAME) {
237 		rc = set_keys_publickey(key,
238 				maplist[PUBLICKEY + type].def_type, type,
239 				&keyfilter);
240 		switch (rc) {
241 		case -1:
242 			sprintf(filter, "objectclass=%s",
243 				maplist[PUBLICKEY].objectclass);
244 			sprintf(userdata, "%%s");
245 			break;
246 		case 0:
247 			return (NULL);
248 		default:
249 			sprintf(filter, "(&(objectclass=%s)%s)",
250 				maplist[PUBLICKEY].objectclass, keyfilter);
251 			sprintf(userdata, "(&(%%s)%s)",
252 				keyfilter);
253 		}
254 	} else {
255 		if ((keyfilter = set_keys(key, "cn")) == NULL) {
256 			sprintf(filter, "objectclass=*");
257 			sprintf(userdata, "%%s");
258 		} else {
259 			sprintf(filter, "%s", keyfilter);
260 			sprintf(userdata, "(&(%%s)%s)", keyfilter);
261 		}
262 	}
263 #ifdef DEBUG
264 	fprintf(stdout, "set_filter: filter=\"%s\"\n", filter);
265 	fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata);
266 #endif /* DEBUG */
267 	return (filter);
268 }
269 
270 
271 /* generic set_filter, this function is not thread safe */
272 char *
273 set_filter(char **key, char *database, char **udata)
274 {
275 	char 		*filter;
276 	char 		*userdata;
277 	char		*keyfilter;
278 	int		i;
279 	int		rc, v2 = 1;
280 	void		**paramVal = NULL;
281 	ns_ldap_error_t	*errorp = NULL;
282 
283 	if (!database) {
284 		return (NULL);
285 	}
286 	if (!udata) {
287 		return (NULL);
288 	}
289 
290 	filter = (char *)malloc(MAXLINE);
291 	if (!filter) {
292 		return (NULL);
293 	}
294 	filter[0] = '\0';
295 
296 	userdata = (char *)malloc(MAXLINE);
297 	if (!userdata) {
298 		free(filter);
299 		return (NULL);
300 	}
301 	userdata[0] = '\0';
302 	*udata = userdata;
303 
304 	/*
305 	 * Check for version of the profile the client is using
306 	 *
307 	 * For version 1 profiles we do use nisMap and nisObject schema
308 	 * for backward compatibility with Solaris 8 clients.
309 	 *
310 	 * For version 2 profiles we use automountMap and automount as
311 	 * default attributes (which can then be overridden in libsldap
312 	 * if schema mapping is configured in the profile).
313 	 *
314 	 * If profile version is not available, use version 2 as default.
315 	 */
316 	rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, &errorp);
317 	if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
318 		/* should print a message here: using v2 defaults */
319 		(void) __ns_ldap_freeError(&errorp);
320 	} else {
321 		if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
322 			v2 = 0;
323 		(void) __ns_ldap_freeParam(&paramVal);
324 	}
325 
326 	/*
327 	 * starts at 2 to skip over publickey databases.
328 	 * These databases are handled separately.
329 	 */
330 	for (i = 2; maplist[i].database != NULL; i++) {
331 		if (strcasecmp(database, maplist[i].database) == SAME) {
332 			if ((keyfilter = set_keys(key, maplist[i].def_type))
333 							== NULL) {
334 				snprintf(filter, MAXLINE, "objectclass=%s",
335 					maplist[i].objectclass);
336 				sprintf(userdata, "%%s");
337 			} else {
338 				snprintf(filter, MAXLINE,
339 					"(&(objectclass=%s)%s)",
340 					maplist[i].objectclass, keyfilter);
341 				snprintf(userdata, MAXLINE, "(&(%%s)%s)",
342 					keyfilter);
343 #ifdef DEBUG
344 	fprintf(stdout, "set_filter: filter=\"%s\"\n", filter);
345 	fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata);
346 #endif /* DEBUG */
347 			}
348 			return (filter);
349 		}
350 	}
351 
352 	/* special cases for automounter and other services */
353 
354 	/* auto_* services */
355 	if (strncasecmp(database, "auto_", 5) == SAME) {
356 	    if (v2) {
357 		if ((keyfilter = set_keys(key, "automountKey"))
358 			!= NULL) {
359 			snprintf(filter, MAXLINE,
360 				"(&(objectclass=automount)%s)", keyfilter);
361 			snprintf(userdata, MAXLINE, "(&(%%s)%s)", keyfilter);
362 		} else {
363 			strcpy(filter, "objectclass=automount");
364 			strcpy(userdata, "%s");
365 		}
366 	    } else {
367 		if ((keyfilter = set_keys(key, "cn"))
368 			!= NULL) {
369 			snprintf(filter, MAXLINE,
370 				"(&(objectclass=nisObject)%s)", keyfilter);
371 			snprintf(userdata, MAXLINE, "(&(%%s)%s)", keyfilter);
372 		} else {
373 			strcpy(filter, "objectclass=nisObject");
374 			strcpy(userdata, "%s");
375 		}
376 	    }
377 	    goto done;
378 	}
379 
380 	/* automount service */
381 	if (strcasecmp(database, "automount") == SAME) {
382 	    if (v2) {
383 		if ((keyfilter = set_keys(key, "automountMapName"))
384 			!= NULL) {
385 			snprintf(filter, MAXLINE,
386 				"(&(objectclass=automountMap)%s)", keyfilter);
387 			snprintf(userdata, MAXLINE, "(&(%%s)%s)", keyfilter);
388 		} else {
389 			strcpy(filter, "objectclass=automountMap");
390 			strcpy(userdata, "%s");
391 		}
392 	    } else {
393 		if ((keyfilter = set_keys(key, "nisMapName"))
394 			!= NULL) {
395 			snprintf(filter, MAXLINE, "(&(objectclass=nisMap)%s)",
396 				keyfilter);
397 			snprintf(userdata, MAXLINE, "(&(%%s)%s)", keyfilter);
398 		} else {
399 			strcpy(filter, "objectclass=nisMap");
400 			strcpy(userdata, "%s");
401 		}
402 	    }
403 	    goto done;
404 	}
405 
406 	/* other services (catch all) */
407 	if ((keyfilter = set_keys(key, "cn")) == NULL) {
408 		snprintf(filter, MAXLINE, "objectclass=*");
409 		strcpy(userdata, "%s");
410 	} else {
411 		snprintf(filter, MAXLINE, "%s", keyfilter);
412 		snprintf(userdata, MAXLINE, "(&(%%s)(%s))", keyfilter);
413 	}
414 
415 done:
416 #ifdef DEBUG
417 	fprintf(stdout, "set_filter: filter=\"%s\"\n", filter);
418 	fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata);
419 #endif /* DEBUG */
420 	return (filter);
421 }
422