10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*5402Sjbeck * Common Development and Distribution License (the "License").
6*5402Sjbeck * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*5402Sjbeck
220Sstevel@tonic-gate /*
23*5402Sjbeck * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <libintl.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include "ns_sldap.h"
350Sstevel@tonic-gate #include "ns_internal.h"
360Sstevel@tonic-gate
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate * getldaplaliasbyname() retrieves the aliases information from the LDAP server.
390Sstevel@tonic-gate * This is requires that the LDAP naming information (ie. LDAP_CLIENT_CACHE
400Sstevel@tonic-gate * file) is configured properly on the client machine.
410Sstevel@tonic-gate *
420Sstevel@tonic-gate * Return value:
430Sstevel@tonic-gate * 0 = success;
440Sstevel@tonic-gate * 1 = alias not found;
450Sstevel@tonic-gate * -1 = other failure. Contents in answer are undefined.
460Sstevel@tonic-gate */
470Sstevel@tonic-gate
480Sstevel@tonic-gate #define ALIAS_FILTER "(&(objectclass=mailgroup)(|(cn=%s)(mail=%s)))"
490Sstevel@tonic-gate #define ALIAS_FILTER_SSD "(&(%%s)(|(cn=%s)(mail=%s)))"
500Sstevel@tonic-gate #define MAIL_CN "cn"
510Sstevel@tonic-gate #define MAIL_ATTRIBUTE "mail"
520Sstevel@tonic-gate #define MAIL_MEMBER "mgrpRFC822MailMember"
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * This is a generic filter call back function for
560Sstevel@tonic-gate * merging the filter from service search descriptor with
570Sstevel@tonic-gate * an existing search filter. This routine expects userdata
580Sstevel@tonic-gate * contain a format string with a single %s in it, and will
590Sstevel@tonic-gate * use the format string with sprintf() to insert the SSD filter.
600Sstevel@tonic-gate *
610Sstevel@tonic-gate * This routine is passed to the __ns_ldap_list() API as the
620Sstevel@tonic-gate * filter call back together with filter and userdata. For example,
630Sstevel@tonic-gate * "(&(objectclass=mailgroup)(|(cn=abc)(mail=abc)))" as filter
640Sstevel@tonic-gate * and "(&(%s)(|(cn=abc)(mail=abc)))" as userdata.
650Sstevel@tonic-gate * This routine will then be called by __ns_ldap_list() to output
660Sstevel@tonic-gate * "(&(dept=sds)(|(cn=abc)(mail=abc)))" as the real search
670Sstevel@tonic-gate * filter, if the input SSD contains a filter "dpet=sds".
680Sstevel@tonic-gate */
690Sstevel@tonic-gate int
__s_api_merge_SSD_filter(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata)700Sstevel@tonic-gate __s_api_merge_SSD_filter(const ns_ldap_search_desc_t *desc,
710Sstevel@tonic-gate char **realfilter,
720Sstevel@tonic-gate const void *userdata)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate int len;
750Sstevel@tonic-gate
760Sstevel@tonic-gate /* sanity check */
770Sstevel@tonic-gate if (realfilter == NULL)
780Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
790Sstevel@tonic-gate *realfilter = NULL;
800Sstevel@tonic-gate
810Sstevel@tonic-gate if (desc == NULL || desc->filter == NULL ||
820Sstevel@tonic-gate userdata == NULL)
830Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
840Sstevel@tonic-gate
850Sstevel@tonic-gate len = strlen(userdata) + strlen(desc->filter) + 1;
860Sstevel@tonic-gate
870Sstevel@tonic-gate *realfilter = (char *)malloc(len);
880Sstevel@tonic-gate if (*realfilter == NULL)
890Sstevel@tonic-gate return (NS_LDAP_MEMORY);
900Sstevel@tonic-gate
910Sstevel@tonic-gate (void) sprintf(*realfilter, (char *)userdata,
920Sstevel@tonic-gate desc->filter);
930Sstevel@tonic-gate
940Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
950Sstevel@tonic-gate }
96*5402Sjbeck char *
__getldapaliasbyname(char * alias,int * retval)97*5402Sjbeck __getldapaliasbyname(char *alias, int *retval)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate char *service = "aliases";
1000Sstevel@tonic-gate char filter[BUFSIZE];
1010Sstevel@tonic-gate char userdata[BUFSIZE];
1020Sstevel@tonic-gate char *attribute[2];
1030Sstevel@tonic-gate ns_ldap_result_t *result = NULL;
1040Sstevel@tonic-gate ns_ldap_error_t *errorp = NULL;
1050Sstevel@tonic-gate int rc, i, j, len, comma;
1060Sstevel@tonic-gate ns_ldap_entry_t *entry = NULL;
1070Sstevel@tonic-gate char **attr_value = NULL;
108*5402Sjbeck char *answer, *new_answer;
109*5402Sjbeck size_t ans_size = BUFSIZE;
1100Sstevel@tonic-gate
111*5402Sjbeck if (!alias || !*alias) {
1120Sstevel@tonic-gate errno = EINVAL;
113*5402Sjbeck *retval = -1;
114*5402Sjbeck return (NULL);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
117*5402Sjbeck answer = malloc(ans_size);
118*5402Sjbeck if (answer == NULL) {
119*5402Sjbeck errno = ENOMEM;
120*5402Sjbeck *retval = -1;
121*5402Sjbeck return (NULL);
122*5402Sjbeck }
1230Sstevel@tonic-gate answer[0] = '\0';
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /* get the aliases */
1260Sstevel@tonic-gate if (snprintf(filter, sizeof (filter), ALIAS_FILTER, alias, alias) < 0) {
1270Sstevel@tonic-gate errno = EINVAL;
128*5402Sjbeck *retval = -1;
129*5402Sjbeck return (NULL);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* get the userdata for __ns_ldap_list filter call back */
1330Sstevel@tonic-gate if (snprintf(userdata, sizeof (userdata), ALIAS_FILTER_SSD,
1340Sstevel@tonic-gate alias, alias) < 0) {
1350Sstevel@tonic-gate errno = EINVAL;
136*5402Sjbeck *retval = -1;
137*5402Sjbeck return (NULL);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate attribute[0] = MAIL_MEMBER;
1410Sstevel@tonic-gate attribute[1] = NULL;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* should we do hardlookup */
1440Sstevel@tonic-gate rc = __ns_ldap_list(service, (const char *)filter,
1450Sstevel@tonic-gate __s_api_merge_SSD_filter,
1460Sstevel@tonic-gate (const char **)attribute, NULL, 0, &result,
1470Sstevel@tonic-gate &errorp, NULL, userdata);
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate if (rc == NS_LDAP_NOTFOUND) {
1500Sstevel@tonic-gate errno = ENOENT;
151*5402Sjbeck *retval = 1;
152*5402Sjbeck return (NULL);
1530Sstevel@tonic-gate } else if (rc != NS_LDAP_SUCCESS) {
1540Sstevel@tonic-gate #ifdef DEBUG
1550Sstevel@tonic-gate char *p;
1560Sstevel@tonic-gate (void) __ns_ldap_err2str(rc, &p);
1570Sstevel@tonic-gate if (errorp) {
1580Sstevel@tonic-gate if (errorp->message)
1590Sstevel@tonic-gate (void) fprintf(stderr, "%s (%s)\n", p,
1600Sstevel@tonic-gate errorp->message);
1610Sstevel@tonic-gate } else
1620Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", p);
1630Sstevel@tonic-gate #endif /* DEBUG */
1640Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp);
165*5402Sjbeck *retval = -1;
166*5402Sjbeck return (NULL);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /* build the return value */
1700Sstevel@tonic-gate answer[0] = '\0';
1710Sstevel@tonic-gate len = 0;
1720Sstevel@tonic-gate comma = 0;
1730Sstevel@tonic-gate entry = result->entry;
1740Sstevel@tonic-gate for (i = 0; i < result->entries_count; i++) {
1750Sstevel@tonic-gate attr_value = __ns_ldap_getAttr(entry, MAIL_MEMBER);
1760Sstevel@tonic-gate if (attr_value == NULL) {
1770Sstevel@tonic-gate errno = ENOENT;
178*5402Sjbeck *retval = -1;
179*5402Sjbeck return (NULL);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate for (j = 0; attr_value[j]; j++) {
1820Sstevel@tonic-gate char *tmp, *newhead;
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate tmp = attr_value[j];
1850Sstevel@tonic-gate while (*tmp == ' ' || *tmp == '\t' && *tmp != '\0')
1860Sstevel@tonic-gate tmp++;
1870Sstevel@tonic-gate newhead = tmp;
1880Sstevel@tonic-gate while (*tmp != '\0') tmp++;
1890Sstevel@tonic-gate while (*tmp == ' ' || *tmp == '\t' || *tmp == '\0' &&
1900Sstevel@tonic-gate tmp != newhead) {
1910Sstevel@tonic-gate *tmp-- = '\0';
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate len = len + comma + strlen(newhead);
194*5402Sjbeck if ((len + 1) > ans_size) {
195*5402Sjbeck ans_size += BUFSIZE;
196*5402Sjbeck new_answer = realloc(answer, ans_size);
197*5402Sjbeck if (new_answer == NULL) {
198*5402Sjbeck (void) __ns_ldap_freeResult(&result);
199*5402Sjbeck errno = ENOMEM;
200*5402Sjbeck *retval = -1;
201*5402Sjbeck free(answer);
202*5402Sjbeck return (NULL);
203*5402Sjbeck }
204*5402Sjbeck answer = new_answer;
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate if (comma)
2070Sstevel@tonic-gate (void) strcat(answer, ",");
2080Sstevel@tonic-gate else
2090Sstevel@tonic-gate comma = 1;
2100Sstevel@tonic-gate (void) strcat(answer, newhead);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
2150Sstevel@tonic-gate errno = 0;
216*5402Sjbeck *retval = 0;
217*5402Sjbeck return (answer);
2180Sstevel@tonic-gate }
219