Print this page
12236 getmembers_DN doesn't properly handle errors from __ns_ldap_dn2uid
12240 nss_ldap does not properly look up group members by distinguished name

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libsldap/common/ns_reads.c
          +++ new/usr/src/lib/libsldap/common/ns_reads.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2020 Joyent, Inc.
  24   25   */
  25   26  
  26   27  #include <stdio.h>
  27   28  #include <sys/types.h>
  28   29  #include <stdlib.h>
  29   30  #include <libintl.h>
  30   31  #include <ctype.h>
  31   32  #include <syslog.h>
  32   33  #include <sys/stat.h>
  33   34  #include <fcntl.h>
↓ open down ↓ 3554 lines elided ↑ open up ↑
3588 3589  int
3589 3590  __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
3590 3591  {
3591 3592          int rc = NS_LDAP_SUCCESS;
3592 3593          while (__ns_ldap_list_batch_process(batch, &rc) > 0)
3593 3594                  ;
3594 3595          __ns_ldap_list_batch_release(batch);
3595 3596          return (rc);
3596 3597  }
3597 3598  
     3599 +typedef struct lookup_data {
     3600 +        const char *lkd_dn;
     3601 +        const char *lkd_service;
     3602 +        const char *lkd_filter;
     3603 +        const ns_cred_t *lkd_cred;
     3604 +        ns_conn_user_t *lkd_user;
     3605 +} lookup_data_t;
     3606 +
3598 3607  /*
3599      - * find_domainname performs one or more LDAP searches to
3600      - * find the value of the nisdomain attribute associated with
3601      - * the input DN (with no retry).
     3608 + * This creates a service search descriptor that can be used to
     3609 + * retrieve a specific DN by using the DN as the basedn with a search
     3610 + * scope of 'base'. We don't use any service SSDs in this instance since
     3611 + * they are intended to search specific locations/subtrees and filter the
     3612 + * results, while here we are wanting to retrieve a specific entry.
3602 3613   */
3603      -
3604 3614  static int
3605      -find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
3606      -    ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
     3615 +lookup_create_ssd(lookup_data_t *dn_data, ns_ldap_search_desc_t **descpp)
3607 3616  {
     3617 +        ns_ldap_search_desc_t *dptr;
3608 3618  
     3619 +        *descpp = NULL;
     3620 +
     3621 +        dptr = calloc(1, sizeof (ns_ldap_search_desc_t));
     3622 +        if (dptr == NULL)
     3623 +                return (NS_LDAP_MEMORY);
     3624 +
     3625 +        dptr->basedn = strdup(dn_data->lkd_dn);
     3626 +        dptr->scope = NS_LDAP_SCOPE_BASE;
     3627 +        dptr->filter = strdup(UIDFILTER);
     3628 +
     3629 +        if (dptr->basedn == NULL || dptr->filter == NULL) {
     3630 +                __ns_ldap_freeASearchDesc(dptr);
     3631 +                return (NS_LDAP_MEMORY);
     3632 +        }
     3633 +
     3634 +        *descpp = dptr;
     3635 +        return (NS_LDAP_SUCCESS);
     3636 +}
     3637 +
     3638 +static int
     3639 +lookup_dn(lookup_data_t *dn_data, const char **attrs,
     3640 +    ns_ldap_result_t **resultp, ns_ldap_error_t **errorp)
     3641 +{
3609 3642          ns_ldap_cookie_t        *cookie;
3610      -        ns_ldap_search_desc_t   **sdlist;
3611      -        ns_ldap_search_desc_t   *dptr;
3612      -        int                     rc;
3613      -        char                    **value;
     3643 +        int                     rc = 0;
3614 3644          int                     flags = 0;
3615 3645  
3616      -        *domainname = NULL;
3617 3646          *errorp = NULL;
     3647 +        *resultp = NULL;
3618 3648  
3619      -        /* Initialize State machine cookie */
     3649 +        if (dn_data == NULL || dn_data->lkd_dn == NULL ||
     3650 +            dn_data->lkd_dn[0] == '\0' || dn_data->lkd_filter == NULL)
     3651 +                return (NS_LDAP_INVALID_PARAM);
     3652 +
3620 3653          cookie = init_search_state_machine();
3621      -        if (cookie == NULL) {
     3654 +        if (cookie == NULL)
3622 3655                  return (NS_LDAP_MEMORY);
3623      -        }
3624      -        cookie->conn_user = conn_user;
3625 3656  
3626      -        /* see if need to follow referrals */
3627      -        rc = __s_api_toFollowReferrals(flags,
3628      -            &cookie->followRef, errorp);
3629      -        if (rc != NS_LDAP_SUCCESS) {
3630      -                delete_search_cookie(cookie);
3631      -                return (rc);
3632      -        }
     3657 +        rc = __s_api_toFollowReferrals(flags, &cookie->followRef, errorp);
     3658 +        if (rc != NS_LDAP_SUCCESS)
     3659 +                goto out;
3633 3660  
3634      -        /* Create default service Desc */
3635      -        sdlist = (ns_ldap_search_desc_t **)calloc(2,
3636      -            sizeof (ns_ldap_search_desc_t *));
3637      -        if (sdlist == NULL) {
3638      -                delete_search_cookie(cookie);
3639      -                cookie = NULL;
3640      -                return (NS_LDAP_MEMORY);
     3661 +        /* 1 for SSD, 1 for terminating NULL */
     3662 +        cookie->sdlist = calloc(2, sizeof (ns_ldap_search_desc_t *));
     3663 +        if (cookie->sdlist == NULL) {
     3664 +                rc = NS_LDAP_MEMORY;
     3665 +                goto out;
3641 3666          }
3642      -        dptr = (ns_ldap_search_desc_t *)
3643      -            calloc(1, sizeof (ns_ldap_search_desc_t));
3644      -        if (dptr == NULL) {
3645      -                free(sdlist);
3646      -                delete_search_cookie(cookie);
3647      -                cookie = NULL;
3648      -                return (NS_LDAP_MEMORY);
3649      -        }
3650      -        sdlist[0] = dptr;
3651 3667  
3652      -        /* search base is dn */
3653      -        dptr->basedn = strdup(dn);
     3668 +        rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
     3669 +        if (rc != NS_LDAP_SUCCESS)
     3670 +                goto out;
3654 3671  
3655      -        /* search scope is base */
3656      -        dptr->scope = NS_LDAP_SCOPE_BASE;
     3672 +        if (dn_data->lkd_service != NULL) {
     3673 +                /*
     3674 +                 * If a service was specified, set that on the cookie so
     3675 +                 * that search_state_machine() will properly map
     3676 +                 * attributes and objectclasses.
     3677 +                 */
     3678 +                cookie->service = strdup(dn_data->lkd_service);
     3679 +                if (cookie->service == NULL) {
     3680 +                        rc = NS_LDAP_MEMORY;
     3681 +                        goto out;
     3682 +                }
     3683 +        }
3657 3684  
3658      -        /* search filter is "nisdomain=*" */
3659      -        dptr->filter = strdup(_NIS_FILTER);
3660      -
3661      -        cookie->sdlist = sdlist;
3662      -        cookie->i_filter = strdup(dptr->filter);
3663      -        cookie->i_attr = nis_domain_attrs;
3664      -        cookie->i_auth = cred;
     3685 +        cookie->i_attr = attrs;
     3686 +        cookie->i_auth = dn_data->lkd_cred;
3665 3687          cookie->i_flags = 0;
     3688 +        cookie->i_filter = strdup(dn_data->lkd_filter);
     3689 +        if (cookie->i_filter == NULL) {
     3690 +                rc = NS_LDAP_MEMORY;
     3691 +                goto out;
     3692 +        }
3666 3693  
3667      -        /* Process search */
3668      -        rc = search_state_machine(cookie, INIT, 0);
3669      -
3670      -        /* Copy domain name if found */
     3694 +        /*
     3695 +         * Actually perform the search. The return value is only used when
     3696 +         * iterating through multiple results. Since we are searching with
     3697 +         * a scope of base, we will always get at most one result entry,
     3698 +         * we ignore the return value and look at err_rc to determine if
     3699 +         * there were any errors.
     3700 +         */
     3701 +        (void) search_state_machine(cookie, INIT, 0);
3671 3702          rc = cookie->err_rc;
     3703 +
3672 3704          if (rc != NS_LDAP_SUCCESS) {
3673      -                if (conn_user != NULL && conn_user->ns_error != NULL) {
3674      -                        *errorp = conn_user->ns_error;
3675      -                        conn_user->ns_error = NULL;
     3705 +                ns_conn_user_t *user = dn_data->lkd_user;
     3706 +
     3707 +                if (user != NULL && user->ns_error != NULL) {
     3708 +                        *errorp = user->ns_error;
     3709 +                        user->ns_error = NULL;
3676 3710                  } else {
3677 3711                          *errorp = cookie->errorp;
     3712 +                        cookie->errorp = NULL;
3678 3713                  }
3679      -        }
3680      -        if (cookie->result == NULL)
     3714 +        } else if (cookie->result != NULL) {
     3715 +                *resultp = cookie->result;
     3716 +                cookie->result = NULL;
     3717 +        } else {
3681 3718                  rc = NS_LDAP_NOTFOUND;
3682      -        if (rc == NS_LDAP_SUCCESS) {
3683      -                value = __ns_ldap_getAttr(cookie->result->entry,
3684      -                    _NIS_DOMAIN);
3685      -                if (value[0])
3686      -                        *domainname = strdup(value[0]);
3687      -                else
3688      -                        rc = NS_LDAP_NOTFOUND;
3689 3719          }
3690      -        if (cookie->result != NULL)
3691      -                (void) __ns_ldap_freeResult(&cookie->result);
3692      -        cookie->errorp = NULL;
     3720 +
     3721 +out:
3693 3722          delete_search_cookie(cookie);
3694      -        cookie = NULL;
3695 3723          return (rc);
3696 3724  }
3697 3725  
3698 3726  /*
     3727 + * find_domainname performs one or more LDAP searches to
     3728 + * find the value of the nisdomain attribute associated with
     3729 + * the input DN (with no retry).
     3730 + */
     3731 +
     3732 +static int
     3733 +find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
     3734 +    ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
     3735 +{
     3736 +        lookup_data_t           ldata;
     3737 +        ns_ldap_result_t        *result;
     3738 +        char                    **value;
     3739 +        int                     rc;
     3740 +
     3741 +        *domainname = NULL;
     3742 +        *errorp = NULL;
     3743 +
     3744 +        ldata.lkd_dn = dn;
     3745 +        ldata.lkd_service = NULL;
     3746 +        ldata.lkd_filter = _NIS_FILTER;
     3747 +        ldata.lkd_cred = cred;
     3748 +        ldata.lkd_user = conn_user;
     3749 +
     3750 +        rc = lookup_dn(&ldata, nis_domain_attrs, &result, errorp);
     3751 +        if (rc != NS_LDAP_SUCCESS)
     3752 +                return (rc);
     3753 +
     3754 +        value = __ns_ldap_getAttr(result->entry, _NIS_DOMAIN);
     3755 +
     3756 +        if (value != NULL && value[0] != NULL) {
     3757 +                *domainname = strdup(value[0]);
     3758 +                if (*domainname == NULL)
     3759 +                        rc = NS_LDAP_MEMORY;
     3760 +        } else {
     3761 +                rc = NS_LDAP_NOTFOUND;
     3762 +        }
     3763 +
     3764 +        (void) __ns_ldap_freeResult(&result);
     3765 +        return (rc);
     3766 +}
     3767 +
     3768 +/*
3699 3769   * __s_api_find_domainname performs one or more LDAP searches to
3700 3770   * find the value of the nisdomain attribute associated with
3701 3771   * the input DN (with retry).
3702 3772   */
3703 3773  
3704 3774  static int
3705 3775  __s_api_find_domainname(const char *dn, char **domainname,
3706 3776      const ns_cred_t *cred, ns_ldap_error_t **errorp)
3707 3777  {
3708 3778          ns_conn_user_t  *cu = NULL;
↓ open down ↓ 523 lines elided ↑ open up ↑
4232 4302  }
4233 4303  
4234 4304  #define _P_UID  "uid"
4235 4305  static const char *dn2uid_attrs[] = {
4236 4306          _P_CN,
4237 4307          _P_UID,
4238 4308          (char *)NULL
4239 4309  };
4240 4310  
4241 4311  int
4242      -__ns_ldap_dn2uid(const char *dn, char **userID, const ns_cred_t *cred,
     4312 +__ns_ldap_dn2uid(const char *dn, char **userIDp, const ns_cred_t *cred,
4243 4313      ns_ldap_error_t **errorp)
4244 4314  {
4245      -        ns_ldap_result_t        *result = NULL;
4246      -        char            *filter, *userdata;
4247      -        char            errstr[MAXERROR];
4248      -        char            **value;
4249      -        int             rc = 0;
4250      -        size_t          len;
     4315 +        lookup_data_t           ldata;
     4316 +        ns_ldap_result_t        *result;
     4317 +        char                    **value;
     4318 +        int                     rc;
4251 4319  
4252 4320          *errorp = NULL;
4253      -        *userID = NULL;
     4321 +        *userIDp = NULL;
4254 4322          if ((dn == NULL) || (dn[0] == '\0'))
4255 4323                  return (NS_LDAP_INVALID_PARAM);
4256 4324  
4257      -        len = strlen(UIDDNFILTER) + strlen(dn) + 1;
4258      -        filter = malloc(len);
4259      -        if (filter == NULL) {
4260      -                return (NS_LDAP_MEMORY);
4261      -        }
4262      -        (void) snprintf(filter, len, UIDDNFILTER, dn);
     4325 +        /*
     4326 +         * Many LDAP servers do not support using the dn in a search
     4327 +         * filter. As a result, we unfortunately cannot  use __ns_ldap_list()
     4328 +         * to lookup the DN. Instead we perform a search with the baseDN
     4329 +         * being the DN we are looking for with a scope of 'base' to
     4330 +         * return the entry, as this should be supported by all LDAP servers.
     4331 +         */
     4332 +        ldata.lkd_dn = dn;
4263 4333  
4264      -        len = strlen(UIDDNFILTER_SSD) + strlen(dn) + 1;
4265      -        userdata = malloc(len);
4266      -        if (userdata == NULL) {
4267      -                free(filter);
4268      -                return (NS_LDAP_MEMORY);
4269      -        }
4270      -        (void) snprintf(userdata, len, UIDDNFILTER_SSD, dn);
4271      -
4272 4334          /*
4273      -         * Unlike uid2dn, we DO want attribute mapping, so that
4274      -         * "uid" is mapped to/from samAccountName, for example.
     4335 +         * Since we are looking up a user account by its DN, use the attribute
     4336 +         * and objectclass mappings (if present) for the passwd service.
4275 4337           */
4276      -        rc = __ns_ldap_list("passwd", filter,
4277      -            __s_api_merge_SSD_filter,
4278      -            dn2uid_attrs, cred, 0,
4279      -            &result, errorp, NULL,
4280      -            userdata);
4281      -        free(filter);
4282      -        filter = NULL;
4283      -        free(userdata);
4284      -        userdata = NULL;
     4338 +        ldata.lkd_service = "passwd";
     4339 +        ldata.lkd_filter = UIDDNFILTER;
     4340 +        ldata.lkd_cred = cred;
     4341 +        ldata.lkd_user = NULL;
     4342 +
     4343 +        rc = lookup_dn(&ldata, dn2uid_attrs, &result, errorp);
4285 4344          if (rc != NS_LDAP_SUCCESS)
4286      -                goto out;
     4345 +                return (rc);
4287 4346  
4288      -        if (result->entries_count > 1) {
4289      -                (void) sprintf(errstr,
4290      -                    gettext("Too many entries are returned for %s"), dn);
4291      -                MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4292      -                    NS_LDAP_MEMORY);
4293      -                rc = NS_LDAP_INTERNAL;
4294      -                goto out;
4295      -        }
4296      -
4297 4347          value = __ns_ldap_getAttr(result->entry, _P_UID);
4298      -        if (value == NULL || value[0] == NULL) {
     4348 +        if (value != NULL && value[0] != NULL) {
     4349 +                *userIDp = strdup(value[0]);
     4350 +                if (*userIDp == NULL)
     4351 +                        rc = NS_LDAP_MEMORY;
     4352 +        } else {
4299 4353                  rc = NS_LDAP_NOTFOUND;
4300      -                goto out;
4301 4354          }
4302 4355  
4303      -        *userID = strdup(value[0]);
4304      -        rc = NS_LDAP_SUCCESS;
4305      -
4306      -out:
4307 4356          (void) __ns_ldap_freeResult(&result);
4308      -        result = NULL;
4309 4357          return (rc);
4310 4358  }
4311 4359  
4312 4360  int
4313 4361  __ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
4314 4362      const ns_cred_t *cred, ns_ldap_error_t **errorp)
4315 4363  {
4316 4364          ns_ldap_result_t        *result = NULL;
4317 4365          char            *filter, *userdata;
4318 4366          char            errstr[MAXERROR];
↓ open down ↓ 1559 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX