2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdlib.h>
2N/A#include <libintl.h>
2N/A#include <stdio.h>
2N/A#include <errno.h>
2N/A#include <strings.h>
2N/A#include "ns_sldap.h"
2N/A#include "ns_internal.h"
2N/A
2N/A/*
2N/A * getldaplaliasbyname() retrieves the aliases information from the LDAP server.
2N/A * This is requires that the LDAP naming information (ie. LDAP_CLIENT_CACHE
2N/A * file) is configured properly on the client machine.
2N/A *
2N/A * Return value:
2N/A * 0 = success;
2N/A * 1 = alias not found;
2N/A * -1 = other failure. Contents in answer are undefined.
2N/A */
2N/A
2N/A#define ALIAS_FILTER "(&(objectclass=mailgroup)(|(cn=%s)(mail=%s)))"
2N/A#define ALIAS_FILTER_SSD "(&(%%s)(|(cn=%s)(mail=%s)))"
2N/A#define MAIL_CN "cn"
2N/A#define MAIL_ATTRIBUTE "mail"
2N/A#define MAIL_MEMBER "mgrpRFC822MailMember"
2N/A
2N/A/*
2N/A * This function builds a new string, as identified by realfilter, by
2N/A * replacing the first occurrence of '%s' in userdata with the string
2N/A * filter provided in the Service Search Descriptor (SSD).
2N/A *
2N/A * It is used as a call back function by __ns_ldap_list() API.
2N/A *
2N/A * As an example, lets assume the caller of __ns_ldap_list() is
2N/A * accessing password information. The userdata filter would previously
2N/A * have been constructed to contain "(&(%s)(userid=fred))". And the SSD
2N/A * filter consists of "dept=sds". The new filter would result in
2N/A * "(&(dept=sds)(userid=fred))".
2N/A */
2N/Aint
2N/A__s_api_merge_SSD_filter(const ns_ldap_search_desc_t *desc,
2N/A char **realfilter,
2N/A const void *userdata)
2N/A{
2N/A int filterlen;
2N/A int merged = 0;
2N/A char *realfilterp;
2N/A char *userdatap = (char *)userdata;
2N/A
2N/A /* sanity check */
2N/A if (realfilter == NULL)
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A *realfilter = NULL;
2N/A
2N/A if (desc == NULL || desc->filter == NULL || userdata == NULL)
2N/A return (NS_LDAP_INVALID_PARAM);
2N/A
2N/A filterlen = strlen(desc->filter);
2N/A *realfilter = (char *)malloc(strlen(userdata) + filterlen + 1);
2N/A if (*realfilter == NULL)
2N/A return (NS_LDAP_MEMORY);
2N/A
2N/A realfilterp = *realfilter;
2N/A while (*userdatap != '\0') {
2N/A if (!merged && *userdatap == '%' && *(userdatap + 1) == 's') {
2N/A userdatap += 2; /* step over "%s" */
2N/A (void) memcpy(realfilterp, desc->filter, filterlen);
2N/A realfilterp += filterlen;
2N/A merged = 1; /* Continue to copy rest of userdata only */
2N/A } else {
2N/A *realfilterp++ = *userdatap++; /* Copy and advance */
2N/A }
2N/A }
2N/A *realfilterp = '\0';
2N/A return (NS_LDAP_SUCCESS);
2N/A}
2N/Achar *
2N/A__getldapaliasbyname(char *alias, int *retval)
2N/A{
2N/A char *service = "aliases";
2N/A char filter[BUFSIZE];
2N/A char userdata[BUFSIZE];
2N/A char *attribute[2];
2N/A ns_ldap_result_t *result = NULL;
2N/A ns_ldap_error_t *errorp = NULL;
2N/A int rc, i, j, len, comma;
2N/A ns_ldap_entry_t *entry = NULL;
2N/A char **attr_value = NULL;
2N/A char *answer, *new_answer;
2N/A size_t ans_size = BUFSIZE;
2N/A
2N/A if (!alias || !*alias) {
2N/A errno = EINVAL;
2N/A *retval = -1;
2N/A return (NULL);
2N/A }
2N/A
2N/A answer = malloc(ans_size);
2N/A if (answer == NULL) {
2N/A errno = ENOMEM;
2N/A *retval = -1;
2N/A return (NULL);
2N/A }
2N/A answer[0] = '\0';
2N/A
2N/A /* get the aliases */
2N/A if (snprintf(filter, sizeof (filter), ALIAS_FILTER, alias, alias) < 0) {
2N/A errno = EINVAL;
2N/A *retval = -1;
2N/A free(answer);
2N/A return (NULL);
2N/A }
2N/A
2N/A /* get the userdata for __ns_ldap_list filter call back */
2N/A if (snprintf(userdata, sizeof (userdata), ALIAS_FILTER_SSD,
2N/A alias, alias) < 0) {
2N/A errno = EINVAL;
2N/A *retval = -1;
2N/A free(answer);
2N/A return (NULL);
2N/A }
2N/A
2N/A attribute[0] = MAIL_MEMBER;
2N/A attribute[1] = NULL;
2N/A
2N/A /* should we do hardlookup */
2N/A rc = __ns_ldap_list(service, (const char *)filter,
2N/A __s_api_merge_SSD_filter,
2N/A (const char **)attribute, NULL, 0, &result,
2N/A &errorp, NULL, userdata);
2N/A
2N/A if (rc == NS_LDAP_NOTFOUND) {
2N/A errno = ENOENT;
2N/A *retval = 1;
2N/A free(answer);
2N/A return (NULL);
2N/A } else if (rc != NS_LDAP_SUCCESS) {
2N/A#ifdef DEBUG
2N/A char *p;
2N/A (void) __ns_ldap_err2str(rc, &p);
2N/A if (errorp) {
2N/A if (errorp->message)
2N/A (void) fprintf(stderr, "%s (%s)\n", p,
2N/A errorp->message);
2N/A } else
2N/A (void) fprintf(stderr, "%s\n", p);
2N/A#endif /* DEBUG */
2N/A (void) __ns_ldap_freeError(&errorp);
2N/A *retval = -1;
2N/A free(answer);
2N/A return (NULL);
2N/A }
2N/A
2N/A /* build the return value */
2N/A answer[0] = '\0';
2N/A len = 0;
2N/A comma = 0;
2N/A entry = result->entry;
2N/A for (i = 0; i < result->entries_count; i++) {
2N/A attr_value = __ns_ldap_getAttr(entry, MAIL_MEMBER);
2N/A if (attr_value == NULL) {
2N/A errno = ENOENT;
2N/A *retval = -1;
2N/A free(answer);
2N/A return (NULL);
2N/A }
2N/A for (j = 0; attr_value[j]; j++) {
2N/A char *tmp, *newhead;
2N/A
2N/A tmp = attr_value[j];
2N/A while (*tmp == ' ' || *tmp == '\t' && *tmp != '\0')
2N/A tmp++;
2N/A newhead = tmp;
2N/A while (*tmp != '\0') tmp++;
2N/A while (*tmp == ' ' || *tmp == '\t' || *tmp == '\0' &&
2N/A tmp != newhead) {
2N/A *tmp-- = '\0';
2N/A }
2N/A len = len + comma + strlen(newhead);
2N/A if ((len + 1) > ans_size) {
2N/A ans_size += BUFSIZE;
2N/A new_answer = realloc(answer, ans_size);
2N/A if (new_answer == NULL) {
2N/A (void) __ns_ldap_freeResult(&result);
2N/A errno = ENOMEM;
2N/A *retval = -1;
2N/A free(answer);
2N/A return (NULL);
2N/A }
2N/A answer = new_answer;
2N/A }
2N/A if (comma)
2N/A (void) strcat(answer, ",");
2N/A else
2N/A comma = 1;
2N/A (void) strcat(answer, newhead);
2N/A }
2N/A }
2N/A
2N/A (void) __ns_ldap_freeResult(&result);
2N/A errno = 0;
2N/A *retval = 0;
2N/A return (answer);
2N/A}