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


   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  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.

  24  */
  25 
  26 #include <stdio.h>
  27 #include <sys/types.h>
  28 #include <stdlib.h>
  29 #include <libintl.h>
  30 #include <ctype.h>
  31 #include <syslog.h>
  32 #include <sys/stat.h>
  33 #include <fcntl.h>
  34 #include <unistd.h>
  35 #include <string.h>
  36 #include <strings.h>
  37 #include <priv.h>
  38 
  39 #include "ns_sldap.h"
  40 #include "ns_internal.h"
  41 #include "ns_cache_door.h"
  42 #include "ns_connmgmt.h"
  43 


3578 
3579         /* Return 0 if no more cookies left otherwise 1 */
3580         return ((batch->nactive > 0) ? 1 : 0);
3581 }
3582 
3583 
3584 /*
3585  * Process all the active cookies in the batch and when none
3586  * remains finalize the batch.
3587  */
3588 int
3589 __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
3590 {
3591         int rc = NS_LDAP_SUCCESS;
3592         while (__ns_ldap_list_batch_process(batch, &rc) > 0)
3593                 ;
3594         __ns_ldap_list_batch_release(batch);
3595         return (rc);
3596 }
3597 








3598 /*
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).


3602  */
3603 
3604 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)
3607 {

3608 























3609         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;
3614         int                     flags = 0;
3615 
3616         *domainname = NULL;
3617         *errorp = NULL;

3618 
3619         /* Initialize State machine cookie */



3620         cookie = init_search_state_machine();
3621         if (cookie == NULL) {
3622                 return (NS_LDAP_MEMORY);
3623         }
3624         cookie->conn_user = conn_user;
3625 
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         }
3633 
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);







3641         }
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 
3652         /* search base is dn */
3653         dptr->basedn = strdup(dn);
3654 
3655         /* search scope is base */
3656         dptr->scope = NS_LDAP_SCOPE_BASE;
3657 
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;
3665         cookie->i_flags = 0;





3666 
3667         /* Process search */
3668         rc = search_state_machine(cookie, INIT, 0);
3669 
3670         /* Copy domain name if found */




3671         rc = cookie->err_rc;

3672         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;


3676                 } else {
3677                         *errorp = cookie->errorp;

3678                 }
3679         }
3680         if (cookie->result == NULL)


3681                 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         }
3690         if (cookie->result != NULL)
3691                 (void) __ns_ldap_freeResult(&cookie->result);
3692         cookie->errorp = NULL;
3693         delete_search_cookie(cookie);
3694         cookie = NULL;
3695         return (rc);
3696 }
3697 
3698 /*
3699  * __s_api_find_domainname performs one or more LDAP searches to
3700  * find the value of the nisdomain attribute associated with
3701  * the input DN (with retry).
3702  */
3703 
3704 static int
3705 __s_api_find_domainname(const char *dn, char **domainname,
3706     const ns_cred_t *cred, ns_ldap_error_t **errorp)
3707 {
3708         ns_conn_user_t  *cu = NULL;
3709         int             try_cnt = 0;
3710         int             rc = NS_LDAP_SUCCESS;
3711 
3712         for (;;) {
3713                 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3714                     &try_cnt, &rc, errorp) == 0)


4222                 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4223                     NS_LDAP_MEMORY);
4224                 return (NS_LDAP_INTERNAL);
4225         }
4226 
4227         value = __ns_ldap_getAttr(result->entry, "dn");
4228         *userDN = strdup(value[0]);
4229         (void) __ns_ldap_freeResult(&result);
4230         result = NULL;
4231         return (NS_LDAP_SUCCESS);
4232 }
4233 
4234 #define _P_UID  "uid"
4235 static const char *dn2uid_attrs[] = {
4236         _P_CN,
4237         _P_UID,
4238         (char *)NULL
4239 };
4240 
4241 int
4242 __ns_ldap_dn2uid(const char *dn, char **userID, const ns_cred_t *cred,
4243     ns_ldap_error_t **errorp)
4244 {
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;
4251 
4252         *errorp = NULL;
4253         *userID = NULL;
4254         if ((dn == NULL) || (dn[0] == '\0'))
4255                 return (NS_LDAP_INVALID_PARAM);
4256 
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);


4263 
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         /*
4273          * Unlike uid2dn, we DO want attribute mapping, so that
4274          * "uid" is mapped to/from samAccountName, for example.
4275          */
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;
4285         if (rc != NS_LDAP_SUCCESS)
4286                 goto out;
4287 
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         value = __ns_ldap_getAttr(result->entry, _P_UID);
4298         if (value == NULL || value[0] == NULL) {




4299                 rc = NS_LDAP_NOTFOUND;
4300                 goto out;
4301         }
4302 
4303         *userID = strdup(value[0]);
4304         rc = NS_LDAP_SUCCESS;
4305 
4306 out:
4307         (void) __ns_ldap_freeResult(&result);
4308         result = NULL;
4309         return (rc);
4310 }
4311 
4312 int
4313 __ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
4314     const ns_cred_t *cred, ns_ldap_error_t **errorp)
4315 {
4316         ns_ldap_result_t        *result = NULL;
4317         char            *filter, *userdata;
4318         char            errstr[MAXERROR];
4319         char            **value;
4320         int             rc;
4321         size_t          len;
4322 
4323         /*
4324          * XXX
4325          * the domain parameter needs to be used in case domain is not local,
4326          * if this routine is to support multi domain setups, it needs lots
4327          * of work...
4328          */




   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  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright 2020 Joyent, Inc.
  25  */
  26 
  27 #include <stdio.h>
  28 #include <sys/types.h>
  29 #include <stdlib.h>
  30 #include <libintl.h>
  31 #include <ctype.h>
  32 #include <syslog.h>
  33 #include <sys/stat.h>
  34 #include <fcntl.h>
  35 #include <unistd.h>
  36 #include <string.h>
  37 #include <strings.h>
  38 #include <priv.h>
  39 
  40 #include "ns_sldap.h"
  41 #include "ns_internal.h"
  42 #include "ns_cache_door.h"
  43 #include "ns_connmgmt.h"
  44 


3579 
3580         /* Return 0 if no more cookies left otherwise 1 */
3581         return ((batch->nactive > 0) ? 1 : 0);
3582 }
3583 
3584 
3585 /*
3586  * Process all the active cookies in the batch and when none
3587  * remains finalize the batch.
3588  */
3589 int
3590 __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
3591 {
3592         int rc = NS_LDAP_SUCCESS;
3593         while (__ns_ldap_list_batch_process(batch, &rc) > 0)
3594                 ;
3595         __ns_ldap_list_batch_release(batch);
3596         return (rc);
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 
3607 /*
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.
3613  */

3614 static int
3615 lookup_create_ssd(lookup_data_t *dn_data, ns_ldap_search_desc_t **descpp)

3616 {
3617         ns_ldap_search_desc_t *dptr;
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 {
3642         ns_ldap_cookie_t        *cookie;
3643         int                     rc = 0;



3644         int                     flags = 0;
3645 

3646         *errorp = NULL;
3647         *resultp = NULL;
3648 
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 
3653         cookie = init_search_state_machine();
3654         if (cookie == NULL)
3655                 return (NS_LDAP_MEMORY);


3656 
3657         rc = __s_api_toFollowReferrals(flags, &cookie->followRef, errorp);
3658         if (rc != NS_LDAP_SUCCESS)
3659                 goto out;
3660 
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;
3666         }
3667 
3668         rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
3669         if (rc != NS_LDAP_SUCCESS)
3670                 goto out;
3671 
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         }

3684 
3685         cookie->i_attr = attrs;
3686         cookie->i_auth = dn_data->lkd_cred;











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         }
3693 
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);
3702         rc = cookie->err_rc;
3703 
3704         if (rc != NS_LDAP_SUCCESS) {
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;
3710                 } else {
3711                         *errorp = cookie->errorp;
3712                         cookie->errorp = NULL;
3713                 }
3714         } else if (cookie->result != NULL) {
3715                 *resultp = cookie->result;
3716                 cookie->result = NULL;
3717         } else {
3718                 rc = NS_LDAP_NOTFOUND;
3719         }
3720 
3721 out:
3722         delete_search_cookie(cookie);
3723         return (rc);
3724 }
3725 
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 /*
3769  * __s_api_find_domainname performs one or more LDAP searches to
3770  * find the value of the nisdomain attribute associated with
3771  * the input DN (with retry).
3772  */
3773 
3774 static int
3775 __s_api_find_domainname(const char *dn, char **domainname,
3776     const ns_cred_t *cred, ns_ldap_error_t **errorp)
3777 {
3778         ns_conn_user_t  *cu = NULL;
3779         int             try_cnt = 0;
3780         int             rc = NS_LDAP_SUCCESS;
3781 
3782         for (;;) {
3783                 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3784                     &try_cnt, &rc, errorp) == 0)


4292                 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
4293                     NS_LDAP_MEMORY);
4294                 return (NS_LDAP_INTERNAL);
4295         }
4296 
4297         value = __ns_ldap_getAttr(result->entry, "dn");
4298         *userDN = strdup(value[0]);
4299         (void) __ns_ldap_freeResult(&result);
4300         result = NULL;
4301         return (NS_LDAP_SUCCESS);
4302 }
4303 
4304 #define _P_UID  "uid"
4305 static const char *dn2uid_attrs[] = {
4306         _P_CN,
4307         _P_UID,
4308         (char *)NULL
4309 };
4310 
4311 int
4312 __ns_ldap_dn2uid(const char *dn, char **userIDp, const ns_cred_t *cred,
4313     ns_ldap_error_t **errorp)
4314 {
4315         lookup_data_t           ldata;
4316         ns_ldap_result_t        *result;

4317         char                    **value;
4318         int                     rc;

4319 
4320         *errorp = NULL;
4321         *userIDp = NULL;
4322         if ((dn == NULL) || (dn[0] == '\0'))
4323                 return (NS_LDAP_INVALID_PARAM);
4324 
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;
4333 








4334         /*
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.
4337          */
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);



4344         if (rc != NS_LDAP_SUCCESS)
4345                 return (rc);
4346 









4347         value = __ns_ldap_getAttr(result->entry, _P_UID);
4348         if (value != NULL && value[0] != NULL) {
4349                 *userIDp = strdup(value[0]);
4350                 if (*userIDp == NULL)
4351                         rc = NS_LDAP_MEMORY;
4352         } else {
4353                 rc = NS_LDAP_NOTFOUND;

4354         }
4355 




4356         (void) __ns_ldap_freeResult(&result);

4357         return (rc);
4358 }
4359 
4360 int
4361 __ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
4362     const ns_cred_t *cred, ns_ldap_error_t **errorp)
4363 {
4364         ns_ldap_result_t        *result = NULL;
4365         char            *filter, *userdata;
4366         char            errstr[MAXERROR];
4367         char            **value;
4368         int             rc;
4369         size_t          len;
4370 
4371         /*
4372          * XXX
4373          * the domain parameter needs to be used in case domain is not local,
4374          * if this routine is to support multi domain setups, it needs lots
4375          * of work...
4376          */