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 /*
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <ctype.h>
27 #include <libintl.h>
28 #include <strings.h>
29 #include <stdio.h>
30 #include <tsol/label.h>
31 #include "../../../lib/libsldap/common/ns_sldap.h"
32
33
34 #define SAME 0
35
36 struct mapping {
37 char *database;
38 char *def_type;
39 char *objectclass;
40 char *actual_db;
41 };
42
43 #define PUBLICKEY 0
44
45 static struct mapping maplist[] = {
46 {"publickey", "uidnumber", "niskeyobject", "passwd"},
47 {"publickey", "cn", "niskeyobject", "host"},
48 {"bootparams", "cn", "bootableDevice", NULL},
49 {"ethers", "cn", "ieee802Device", NULL},
50 {"group", "cn", "posixgroup", NULL},
51 {"hosts", "cn", "iphost", NULL},
52 {"ipnodes", "cn", "iphost", NULL},
53 {"netgroup", "cn", "nisnetgroup", NULL},
54 {"netmasks", "ipnetworknumber", "ipnetwork", NULL},
55 {"networks", "ipnetworknumber", "ipnetwork", NULL},
56 {"passwd", "uid", "posixaccount", NULL},
57 {"protocols", "cn", "ipprotocol", NULL},
58 {"rpc", "cn", "oncrpc", NULL},
59 {"services", "cn", "ipservice", NULL},
60 {"aliases", "cn", "mailGroup", NULL},
61 {"project", "SolarisProjectID", "SolarisProject", NULL},
62 {"printers", "printer-uri", "sunPrinter", NULL},
63 {"shadow", "uid", "shadowaccount", NULL},
64 {"auth_attr", "cn", "SolarisAuthAttr", NULL},
65 {"prof_attr", "cn", "SolarisProfAttr", NULL},
66 {"exec_attr", "cn", "SolarisExecAttr", NULL},
67 {"user_attr", "uid", "SolarisUserAttr", NULL},
68 {"tnrhtp", "ipTnetTemplateName", "ipTnetTemplate", NULL},
69 {"tnrhdb", "ipTnetNumber", "ipTnetHost", NULL},
70 {NULL, NULL, NULL, NULL}
71 };
72
73 #define PROF_ATTR_FILTER \
74 "(&(objectclass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*))%s)"
75 #define TNRHTP_FILTER \
76 "(&(objectclass=ipTnetTemplate)(!(objectclass=ipTnetHost))%s)"
77 #define OC_FILTER "objectclass=%s"
78 #define OC_FLEN 15
79 #define OC_FILTER2 "(&(objectclass=%s)%s)"
80 #define OC_FLEN2 22
81
82 /* Malloc and print error message in case of failure */
83 #define MALLOC(ptr, len) \
84 if ((ptr = (char *)malloc(len)) == NULL) { \
85 (void) fprintf(stderr, gettext("out of memory\n")); \
86 }
87
88 /*
89 * Allocate memory for filter and user data. Set
90 * error to 1 if either of the mallocs fail.
91 * In addition, free the memory allocated for filter,
92 * if memory allocation for user data fails.
93 */
94 #define MALLOC_FILTER_UDATA(ptr1, len1, ptr2, len2, error) \
95 error = 0; \
96 MALLOC(ptr1, len1); \
97 if (!ptr1) { \
98 error = 1; \
99 } \
100 else { \
101 MALLOC(ptr2, len2); \
102 if (!ptr2) { \
103 error = 1; \
104 free(ptr1); \
105 } \
106 }
107
108 void
printMapping()109 printMapping()
110 {
111 int i;
112
113 (void) fprintf(stdout,
114 gettext("database default type objectclass\n"));
115 (void) fprintf(stdout,
116 gettext("============= ================= =============\n"));
117 /* first dump auto_* and automount which are not in maplist[] */
118 (void) fprintf(stdout, "%-15s%-20s%s\n", "auto_*", "automountKey",
119 "automount");
120 (void) fprintf(stdout, "%-15s%-20s%s\n", "automount",
121 "automountMapName", "automountMap");
122 for (i = 0; maplist[i].database != NULL; i++) {
123 /* skip printing shadow */
124 if (strcasecmp(maplist[i].database, "shadow") == 0)
125 continue;
126 if (!is_system_labeled()) {
127 /*
128 * do not print tnrhdb and tnrhtp if system is
129 * not configured with Trusted Extensions
130 */
131 if ((strcasecmp(maplist[i].database, "tnrhdb") == 0) ||
132 (strcasecmp(maplist[i].database, "tnrhtp") == 0))
133 continue;
134 }
135 (void) fprintf(stdout, "%-15s%-20s%s\n", maplist[i].database,
136 maplist[i].def_type, maplist[i].objectclass);
137 }
138 }
139
140 /*
141 * set_key routine to handle user specified keys.
142 * A key can be of the form: attribute=value or value.
143 * A filter is constructed from a set of keys specified in
144 * the form (|(key1)(key2)...(keyn))
145 * It returns: NULL if no keys are defined or
146 * the keyfilter as constructed above.
147 */
148
149 char *
set_keys(char ** key,char * attrtype)150 set_keys(char **key, char *attrtype)
151 {
152 char *keyeq = NULL;
153 char *keyfilter = NULL;
154 int len, totlen = 1; /* Terminating NULL byte */
155 char *k, **karray;
156 char *tmpptr;
157
158 if (!key || !key[0]) /* should never contain NULL string */
159 return (NULL);
160
161 if (key[1]) {
162 totlen += 3;
163 /* Allocate memory for '(|)' */
164 MALLOC(keyfilter, totlen);
165 if (!keyfilter)
166 exit(2);
167 (void) snprintf(keyfilter, totlen, "(|");
168 }
169
170 karray = key;
171 while ((k = *karray) != 0) {
172 keyeq = strchr(k, '=');
173 if (keyeq) {
174 /* make enough room for (%s) */
175 totlen += strlen(k) + 2;
176 } else {
177 /* make enough room for (%s=%s) */
178 totlen += strlen(attrtype) + strlen(k) + 3;
179 }
180
181 len = keyfilter ? strlen(keyfilter) : 0;
182
183 if (!(tmpptr = (char *)realloc(keyfilter, totlen))) {
184 if (keyfilter)
185 free(keyfilter);
186 (void) fprintf(stderr, gettext("out of memory\n"));
187 exit(2);
188 }
189 keyfilter = tmpptr;
190
191 if (keyeq) {
192 (void) snprintf(keyfilter + len, totlen - len,
193 "(%s)", k);
194 } else {
195 (void) snprintf(keyfilter + len, totlen - len,
196 "(%s=%s)", attrtype, k);
197 }
198 karray++;
199 }
200
201 if (key[1]) {
202 /* We allocated memory for this earlier */
203 (void) strlcat(keyfilter, ")", totlen);
204 }
205
206 return (keyfilter);
207 }
208
209
210 /*
211 * A special set_key routine for to handle public keys.
212 * If the key starts with a digiti, view it as a user id.
213 * Otherwise, view it as a hostname.
214 * It returns: -1 no keys defined, 0 key defined but none for type
215 * specified, n>0 number of matches found.
216 */
217 int
set_keys_publickey(char ** key,char * attrtype,int type,char ** ret)218 set_keys_publickey(char **key, char *attrtype, int type, char **ret)
219 {
220 char *keyeq = NULL;
221 char *keyfilter = NULL;
222 char *pre_filter = NULL;
223 char *k, **karray;
224 int count = 0;
225 int len, totlen = 1; /* Terminating NULL byte */
226 char *tmpptr;
227
228 if (!key || !key[0]) { /* should never contain NULL string */
229 *ret = NULL;
230 return (-1);
231 }
232
233 karray = key;
234 while ((k = *karray) != 0) {
235 keyeq = strchr(k, '=');
236 if (keyeq) {
237 /* make enough room for (%s) */
238 totlen += strlen(k) + 2;
239 } else {
240 if ((type == 0 && isdigit(*k)) ||
241 /* user type keys */
242 (type == 1 && (!isdigit(*k)))) {
243 /* hosts type keys */
244 /* make enough room for (%s=%s) */
245 totlen += strlen(k) + strlen(attrtype) + 3;
246 } else {
247 karray++;
248 continue;
249 }
250 }
251
252 len = pre_filter ? strlen(pre_filter) : 0;
253
254 if (!(tmpptr = (char *)realloc(pre_filter, totlen))) {
255 if (pre_filter)
256 free(pre_filter);
257 (void) fprintf(stderr, gettext("out of memory\n"));
258 exit(2);
259 }
260 pre_filter = tmpptr;
261
262 if (keyeq) {
263 (void) snprintf(pre_filter + len, totlen - len,
264 "(%s)", k);
265 } else {
266 (void) snprintf(pre_filter + len, totlen - len,
267 "(%s=%s)", attrtype, k);
268 }
269 karray++;
270 count++;
271 }
272 if (count > 1) {
273 len = strlen(pre_filter) + 4;
274 if (!(keyfilter = (char *)malloc(len))) {
275 (void) fprintf(stderr, gettext("out of memory\n"));
276 free(pre_filter);
277 exit(2);
278 }
279 (void) snprintf(keyfilter, len, "(|%s)", pre_filter);
280 free(pre_filter);
281 *ret = keyfilter;
282 } else
283 *ret = pre_filter;
284 return (count);
285 }
286
287 /*
288 * publickey specific set_filter
289 * type 0 -> check for user publickeys
290 * type 1 -> check for hosts publickeys
291 */
292 char *
set_filter_publickey(char ** key,char * database,int type,char ** udata)293 set_filter_publickey(char **key, char *database, int type, char **udata)
294 {
295 char *filter = NULL;
296 char *userdata;
297 char *keyfilter = NULL;
298 int rc;
299 int filterlen, udatalen;
300 short nomem = 0;
301
302 if (!database || !udata) {
303 return (NULL);
304 }
305
306 if (strcasecmp(database, maplist[PUBLICKEY].database) == SAME) {
307 rc = set_keys_publickey(key,
308 maplist[PUBLICKEY + type].def_type, type, &keyfilter);
309 switch (rc) {
310 case -1:
311 filterlen = strlen(maplist[PUBLICKEY].objectclass) + 13;
312 udatalen = 3;
313 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
314 udatalen, nomem);
315 if (!nomem) {
316 (void) snprintf(filter, filterlen,
317 "objectclass=%s",
318 maplist[PUBLICKEY].objectclass);
319 (void) snprintf(userdata, udatalen, "%%s");
320 }
321 break;
322 case 0:
323 return (NULL);
324 default:
325 filterlen = strlen(maplist[PUBLICKEY].objectclass) +
326 strlen(keyfilter) + 18;
327 udatalen = strlen(keyfilter) + 8;
328 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
329 udatalen, nomem);
330 if (!nomem) {
331 (void) snprintf(filter, filterlen,
332 "(&(objectclass=%s)%s)",
333 maplist[PUBLICKEY].objectclass, keyfilter);
334 (void) snprintf(userdata, udatalen,
335 "(&(%%s)%s)", keyfilter);
336 }
337 }
338 } else {
339 if ((keyfilter = set_keys(key, "cn")) == NULL) {
340 filterlen = 14;
341 udatalen = 3;
342 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
343 udatalen, nomem);
344 if (!nomem) {
345 (void) snprintf(filter, filterlen,
346 "objectclass=*");
347 (void) snprintf(userdata, udatalen, "%%s");
348 }
349 } else {
350 filterlen = strlen(keyfilter) + 1;
351 udatalen = strlen(keyfilter) + 8;
352 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
353 udatalen, nomem);
354 if (!nomem) {
355 (void) snprintf(filter, filterlen, "%s",
356 keyfilter);
357 (void) snprintf(userdata, udatalen,
358 "(&(%%s)%s)", keyfilter);
359 }
360 }
361 }
362 #ifdef DEBUG
363 (void) fprintf(stdout, "set_filter: filter=\"%s\"\n", filter);
364 (void) fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata);
365 #endif /* DEBUG */
366 if (keyfilter)
367 free(keyfilter);
368 if (nomem)
369 exit(2);
370 *udata = userdata;
371 return (filter);
372 }
373
374
375 /* generic set_filter, this function is not thread safe */
376 char *
set_filter(char ** key,char * database,char ** udata)377 set_filter(char **key, char *database, char **udata)
378 {
379 char *filter = NULL;
380 char *userdata = NULL;
381 char *keyfilter;
382 int i, filterlen, udatalen;
383 int rc, v2 = 1;
384 int dbpf, dbtp;
385 void **paramVal = NULL;
386 ns_ldap_error_t *errorp = NULL;
387 short nomem;
388
389 if (!database || !udata) {
390 return (NULL);
391 }
392
393
394 /*
395 * Check for version of the profile the client is using
396 *
397 * For version 1 profiles we do use nisMap and nisObject schema
398 * for backward compatibility with Solaris 8 clients.
399 *
400 * For version 2 profiles we use automountMap and automount as
401 * default attributes (which can then be overridden in libsldap
402 * if schema mapping is configured in the profile).
403 *
404 * If profile version is not available, use version 2 as default.
405 */
406 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, &errorp);
407 if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
408 /* should print a message here: using v2 defaults */
409 (void) __ns_ldap_freeError(&errorp);
410 } else {
411 if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
412 v2 = 0;
413 (void) __ns_ldap_freeParam(¶mVal);
414 }
415
416 /*
417 * starts at 2 to skip over publickey databases.
418 * These databases are handled separately.
419 */
420 for (i = 2; maplist[i].database != NULL; i++) {
421 if (strcasecmp(database, maplist[i].database) == SAME) {
422 dbpf = 0, dbtp = 0;
423 if (strcasecmp(database, "prof_attr") == 0)
424 dbpf = 1;
425 else if (strcasecmp(database, "tnrhtp") == 0)
426 dbtp = 1;
427 if ((keyfilter = set_keys(key, maplist[i].def_type))
428 == NULL) {
429 filterlen = strlen(maplist[i].objectclass);
430 udatalen = 3;
431 if (dbpf)
432 filterlen += strlen(PROF_ATTR_FILTER)
433 + 1;
434 else if (dbtp)
435 filterlen += strlen(TNRHTP_FILTER) + 1;
436 else
437 filterlen += OC_FLEN;
438
439 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
440 udatalen, nomem);
441 if (nomem)
442 goto done;
443 if (dbpf)
444 (void) snprintf(filter, filterlen,
445 PROF_ATTR_FILTER, "");
446 else if (dbtp)
447 (void) snprintf(filter, filterlen,
448 TNRHTP_FILTER, "");
449 else
450 (void) snprintf(filter, filterlen,
451 OC_FILTER,
452 maplist[i].objectclass);
453
454 (void) snprintf(userdata, udatalen, "%%s");
455 } else {
456 filterlen = strlen(maplist[i].objectclass) +
457 strlen(keyfilter);
458 if (dbpf)
459 filterlen += strlen(PROF_ATTR_FILTER)
460 + 1;
461 else if (dbtp)
462 filterlen += strlen(TNRHTP_FILTER) + 1;
463 else
464 filterlen += OC_FLEN2;
465
466 udatalen = strlen(keyfilter) + 8;
467 MALLOC_FILTER_UDATA(filter, filterlen, userdata,
468 udatalen, nomem);
469 if (nomem)
470 goto done;
471 if (dbpf)
472 (void) snprintf(filter, filterlen,
473 PROF_ATTR_FILTER, keyfilter);
474 else if (dbtp)
475 (void) snprintf(filter, filterlen,
476 TNRHTP_FILTER, keyfilter);
477 else
478 (void) snprintf(filter, filterlen,
479 OC_FILTER2,
480 maplist[i].objectclass, keyfilter);
481
482 (void) snprintf(userdata, udatalen,
483 "(&(%%s)%s)", keyfilter);
484 }
485 goto done;
486 }
487 }
488
489 /* special cases for automounter and other services */
490
491 /* auto_* services */
492 if (strncasecmp(database, "auto_", 5) == SAME) {
493 if (v2) {
494 if ((keyfilter = set_keys(key, "automountKey"))
495 != NULL) {
496 filterlen = strlen(keyfilter) + 27;
497 udatalen = strlen(keyfilter) + 8;
498 MALLOC_FILTER_UDATA(filter, filterlen,
499 userdata, udatalen, nomem);
500 if (!nomem) {
501 (void) snprintf(filter, filterlen,
502 "(&(objectclass=automount)%s)",
503 keyfilter);
504 (void) snprintf(userdata, udatalen,
505 "(&(%%s)%s)", keyfilter);
506 }
507 } else {
508 filterlen = 22;
509 udatalen = 3;
510 MALLOC_FILTER_UDATA(filter, filterlen,
511 userdata, udatalen, nomem);
512 if (!nomem) {
513 (void) strlcpy(filter,
514 "objectclass=automount", filterlen);
515 (void) strlcpy(userdata, "%s",
516 udatalen);
517 }
518 }
519 } else {
520 if ((keyfilter = set_keys(key, "cn")) != NULL) {
521 filterlen = strlen(keyfilter) + 27;
522 udatalen = strlen(keyfilter) + 8;
523 MALLOC_FILTER_UDATA(filter, filterlen,
524 userdata, udatalen, nomem);
525 if (!nomem) {
526 (void) snprintf(filter, filterlen,
527 "(&(objectclass=nisObject)%s)",
528 keyfilter);
529 (void) snprintf(userdata, udatalen,
530 "(&(%%s)%s)", keyfilter);
531 }
532 } else {
533 filterlen = 22;
534 udatalen = 3;
535 MALLOC_FILTER_UDATA(filter, filterlen,
536 userdata, udatalen, nomem);
537 if (!nomem) {
538 (void) strlcpy(filter,
539 "objectclass=nisObject", filterlen);
540 (void) strlcpy(userdata, "%s",
541 udatalen);
542 }
543 }
544 }
545 goto done;
546 }
547
548 /* automount service */
549 if (strcasecmp(database, "automount") == SAME) {
550 if (v2) {
551 if ((keyfilter = set_keys(key, "automountMapName"))
552 != NULL) {
553 filterlen = strlen(keyfilter) + 30;
554 udatalen = strlen(keyfilter) + 8;
555 MALLOC_FILTER_UDATA(filter, filterlen,
556 userdata, udatalen, nomem);
557 if (!nomem) {
558 (void) snprintf(filter, filterlen,
559 "(&(objectclass=automountMap)%s)",
560 keyfilter);
561 (void) snprintf(userdata, udatalen,
562 "(&(%%s)%s)", keyfilter);
563 }
564 } else {
565 filterlen = 25;
566 udatalen = 3;
567 MALLOC_FILTER_UDATA(filter, filterlen,
568 userdata, udatalen, nomem);
569 if (!nomem) {
570 (void) strlcpy(filter,
571 "objectclass=automountMap",
572 filterlen);
573 (void) strlcpy(userdata, "%s",
574 udatalen);
575 }
576 }
577 } else {
578 if ((keyfilter = set_keys(key, "nisMapName"))
579 != NULL) {
580 filterlen = strlen(keyfilter) + 24;
581 udatalen = strlen(keyfilter) + 8;
582 MALLOC_FILTER_UDATA(filter, filterlen,
583 userdata, udatalen, nomem);
584 if (!nomem) {
585 (void) snprintf(filter, filterlen,
586 "(&(objectclass=nisMap)%s)",
587 keyfilter);
588 (void) snprintf(userdata, udatalen,
589 "(&(%%s)%s)", keyfilter);
590 }
591 } else {
592 filterlen = 19;
593 udatalen = 3;
594 MALLOC_FILTER_UDATA(filter, filterlen,
595 userdata, udatalen, nomem);
596 if (!nomem) {
597 (void) strlcpy(filter,
598 "objectclass=nisMap", filterlen);
599 (void) strlcpy(userdata, "%s",
600 udatalen);
601 }
602 }
603 }
604 goto done;
605 }
606
607 /* other services (catch all) */
608 if ((keyfilter = set_keys(key, "cn")) == NULL) {
609 filterlen = 14;
610 udatalen = 3;
611 MALLOC_FILTER_UDATA(filter, filterlen, userdata, udatalen,
612 nomem);
613 if (!nomem) {
614 (void) snprintf(filter, filterlen, "objectclass=*");
615 (void) strlcpy(userdata, "%s", udatalen);
616 }
617 } else {
618 filterlen = strlen(keyfilter) + 1;
619 udatalen = strlen(keyfilter) + 8;
620 MALLOC_FILTER_UDATA(filter, filterlen, userdata, udatalen,
621 nomem);
622 if (!nomem) {
623 (void) snprintf(filter, filterlen, "%s", keyfilter);
624 (void) snprintf(userdata, udatalen, "(&(%%s)%s)",
625 keyfilter);
626 }
627 }
628
629 done:
630 #ifdef DEBUG
631 (void) fprintf(stdout, "set_filter: filter=\"%s\"\n", filter);
632 (void) fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata);
633 #endif /* DEBUG */
634 if (keyfilter)
635 free(keyfilter);
636 if (nomem)
637 exit(2);
638 *udata = userdata;
639 return (filter);
640 }
641