Project

General

Profile

Bug #12240 ยป 0001-12240-nss_ldap-does-not-properly-look-up-group-membe.patch

First attempt at fix - Jason King, 2020-01-23 10:53 PM

View differences:

usr/src/lib/libsldap/common/ns_internal.h
22 22
/*
23 23
 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 24
 * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
25
 * Copyright 2020 Joyent, Inc.
25 26
 */
26 27

  
27 28

  
......
67 68
#define	UIDNUMFILTER_SSD	"(&(%%s)(uidnumber=%s))"
68 69
#define	UIDFILTER		"(&(objectclass=posixAccount)(uid=%s))"
69 70
#define	UIDFILTER_SSD		"(&(%%s)(uid=%s))"
70
#define	UIDDNFILTER	"(&(objectclass=posixAccount)(distinguishedName=%s))"
71
#define	UIDDNFILTER_SSD		"(&(%%s)(distinguishedName=%s))"
71
#define	UIDDNFILTER		"(objectclass=posixAccount)"
72 72

  
73 73
#define	HOSTFILTER		"(&(objectclass=ipHost)(cn=%s))"
74 74
#define	HOSTFILTER_SSD		"(&(%%s)(cn=%s))"
......
765 765

  
766 766
/* ************ internal sldap-api functions *********** */
767 767
void	__ns_ldap_freeEntry(ns_ldap_entry_t *ep);
768
void	__ns_ldap_freeASearchDesc(ns_ldap_search_desc_t *);
768 769
void	__s_api_split_key_value(char *buffer, char **name, char **value);
769 770
int	__s_api_printResult(ns_ldap_result_t *);
770 771
int	__s_api_getSearchScope(int *, ns_ldap_error_t **);
usr/src/lib/libsldap/common/ns_mapping.c
20 20
 */
21 21
/*
22 22
 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
23
 * Copyright 2020 Joyent, Inc.
23 24
 */
24 25

  
25 26
#include <stdlib.h>
......
295 296
}
296 297

  
297 298

  
298
static void
299
void
299 300
__ns_ldap_freeASearchDesc(ns_ldap_search_desc_t *ptr)
300 301
{
301 302
	if (ptr == NULL)
usr/src/lib/libsldap/common/ns_reads.c
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>
......
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;
3618

  
3619
	*descpp = NULL;
3608 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;
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);
3618 3652

  
3619
	/* Initialize State machine cookie */
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);
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);
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;
3649 3666
	}
3650
	sdlist[0] = dptr;
3651 3667

  
3652
	/* search base is dn */
3653
	dptr->basedn = strdup(dn);
3654

  
3655
	/* search scope is base */
3656
	dptr->scope = NS_LDAP_SCOPE_BASE;
3668
	rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
3669
	if (rc != NS_LDAP_SUCCESS)
3670
		goto out;
3657 3671

  
3658
	/* search filter is "nisdomain=*" */
3659
	dptr->filter = strdup(_NIS_FILTER);
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
	}
3660 3684

  
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;
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[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);
3695 3765
	return (rc);
3696 3766
}
3697 3767

  
......
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);
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);
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;
4271 4333

  
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;
4285
	if (rc != NS_LDAP_SUCCESS)
4286
		goto out;
4338
	ldata.lkd_service = "passwd";
4339
	ldata.lkd_filter = UIDDNFILTER;
4340
	ldata.lkd_cred = cred;
4341
	ldata.lkd_user = NULL;
4287 4342

  
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
	}
4343
	rc = lookup_dn(&ldata, dn2uid_attrs, &result, errorp);
4344
	if (rc != NS_LDAP_SUCCESS)
4345
		return (rc);
4296 4346

  
4297 4347
	value = __ns_ldap_getAttr(result->entry, _P_UID);
4298
	if (value == NULL || value[0] == NULL) {
4348
	if (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

  
    (1-1/1)