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
*** 19,28 ****
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 Joyent, Inc.
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
*** 3593,3699 ****
;
__ns_ldap_list_batch_release(batch);
return (rc);
}
/*
! * find_domainname performs one or more LDAP searches to
! * find the value of the nisdomain attribute associated with
! * the input DN (with no retry).
*/
-
static int
! find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
! ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
{
ns_ldap_cookie_t *cookie;
! ns_ldap_search_desc_t **sdlist;
! ns_ldap_search_desc_t *dptr;
! int rc;
! char **value;
int flags = 0;
- *domainname = NULL;
*errorp = NULL;
! /* Initialize State machine cookie */
cookie = init_search_state_machine();
! if (cookie == NULL) {
return (NS_LDAP_MEMORY);
- }
- cookie->conn_user = conn_user;
! /* see if need to follow referrals */
! rc = __s_api_toFollowReferrals(flags,
! &cookie->followRef, errorp);
! if (rc != NS_LDAP_SUCCESS) {
! delete_search_cookie(cookie);
! return (rc);
}
! /* Create default service Desc */
! sdlist = (ns_ldap_search_desc_t **)calloc(2,
! sizeof (ns_ldap_search_desc_t *));
! if (sdlist == NULL) {
! delete_search_cookie(cookie);
! cookie = NULL;
! return (NS_LDAP_MEMORY);
}
- dptr = (ns_ldap_search_desc_t *)
- calloc(1, sizeof (ns_ldap_search_desc_t));
- if (dptr == NULL) {
- free(sdlist);
- delete_search_cookie(cookie);
- cookie = NULL;
- return (NS_LDAP_MEMORY);
}
- sdlist[0] = dptr;
! /* search base is dn */
! dptr->basedn = strdup(dn);
!
! /* search scope is base */
! dptr->scope = NS_LDAP_SCOPE_BASE;
!
! /* search filter is "nisdomain=*" */
! dptr->filter = strdup(_NIS_FILTER);
!
! cookie->sdlist = sdlist;
! cookie->i_filter = strdup(dptr->filter);
! cookie->i_attr = nis_domain_attrs;
! cookie->i_auth = cred;
cookie->i_flags = 0;
! /* Process search */
! rc = search_state_machine(cookie, INIT, 0);
!
! /* Copy domain name if found */
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS) {
! if (conn_user != NULL && conn_user->ns_error != NULL) {
! *errorp = conn_user->ns_error;
! conn_user->ns_error = NULL;
} else {
*errorp = cookie->errorp;
}
! }
! if (cookie->result == NULL)
rc = NS_LDAP_NOTFOUND;
! if (rc == NS_LDAP_SUCCESS) {
! value = __ns_ldap_getAttr(cookie->result->entry,
! _NIS_DOMAIN);
! if (value[0])
*domainname = strdup(value[0]);
! else
rc = NS_LDAP_NOTFOUND;
}
! if (cookie->result != NULL)
! (void) __ns_ldap_freeResult(&cookie->result);
! cookie->errorp = NULL;
! delete_search_cookie(cookie);
! cookie = NULL;
return (rc);
}
/*
* __s_api_find_domainname performs one or more LDAP searches to
--- 3594,3769 ----
;
__ns_ldap_list_batch_release(batch);
return (rc);
}
+ typedef struct lookup_data {
+ const char *lkd_dn;
+ const char *lkd_service;
+ const char *lkd_filter;
+ const ns_cred_t *lkd_cred;
+ ns_conn_user_t *lkd_user;
+ } lookup_data_t;
+
/*
! * This creates a service search descriptor that can be used to
! * retrieve a specific DN by using the DN as the basedn with a search
! * scope of 'base'. We don't use any service SSDs in this instance since
! * they are intended to search specific locations/subtrees and filter the
! * results, while here we are wanting to retrieve a specific entry.
*/
static int
! lookup_create_ssd(lookup_data_t *dn_data, ns_ldap_search_desc_t **descpp)
{
+ ns_ldap_search_desc_t *dptr;
+ *descpp = NULL;
+
+ dptr = calloc(1, sizeof (ns_ldap_search_desc_t));
+ if (dptr == NULL)
+ return (NS_LDAP_MEMORY);
+
+ dptr->basedn = strdup(dn_data->lkd_dn);
+ dptr->scope = NS_LDAP_SCOPE_BASE;
+ dptr->filter = strdup(UIDFILTER);
+
+ if (dptr->basedn == NULL || dptr->filter == NULL) {
+ __ns_ldap_freeASearchDesc(dptr);
+ return (NS_LDAP_MEMORY);
+ }
+
+ *descpp = dptr;
+ return (NS_LDAP_SUCCESS);
+ }
+
+ static int
+ lookup_dn(lookup_data_t *dn_data, const char **attrs,
+ ns_ldap_result_t **resultp, ns_ldap_error_t **errorp)
+ {
ns_ldap_cookie_t *cookie;
! int rc = 0;
int flags = 0;
*errorp = NULL;
+ *resultp = NULL;
! if (dn_data == NULL || dn_data->lkd_dn == NULL ||
! dn_data->lkd_dn[0] == '\0' || dn_data->lkd_filter == NULL)
! return (NS_LDAP_INVALID_PARAM);
!
cookie = init_search_state_machine();
! if (cookie == NULL)
return (NS_LDAP_MEMORY);
! rc = __s_api_toFollowReferrals(flags, &cookie->followRef, errorp);
! if (rc != NS_LDAP_SUCCESS)
! goto out;
!
! /* 1 for SSD, 1 for terminating NULL */
! cookie->sdlist = calloc(2, sizeof (ns_ldap_search_desc_t *));
! if (cookie->sdlist == NULL) {
! rc = NS_LDAP_MEMORY;
! goto out;
}
! rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
! if (rc != NS_LDAP_SUCCESS)
! goto out;
!
! if (dn_data->lkd_service != NULL) {
! /*
! * If a service was specified, set that on the cookie so
! * that search_state_machine() will properly map
! * attributes and objectclasses.
! */
! cookie->service = strdup(dn_data->lkd_service);
! if (cookie->service == NULL) {
! rc = NS_LDAP_MEMORY;
! goto out;
}
}
! cookie->i_attr = attrs;
! cookie->i_auth = dn_data->lkd_cred;
cookie->i_flags = 0;
+ cookie->i_filter = strdup(dn_data->lkd_filter);
+ if (cookie->i_filter == NULL) {
+ rc = NS_LDAP_MEMORY;
+ goto out;
+ }
! /*
! * Actually perform the search. The return value is only used when
! * iterating through multiple results. Since we are searching with
! * a scope of base, we will always get at most one result entry,
! * we ignore the return value and look at err_rc to determine if
! * there were any errors.
! */
! (void) search_state_machine(cookie, INIT, 0);
rc = cookie->err_rc;
+
if (rc != NS_LDAP_SUCCESS) {
! ns_conn_user_t *user = dn_data->lkd_user;
!
! if (user != NULL && user->ns_error != NULL) {
! *errorp = user->ns_error;
! user->ns_error = NULL;
} else {
*errorp = cookie->errorp;
+ cookie->errorp = NULL;
}
! } else if (cookie->result != NULL) {
! *resultp = cookie->result;
! cookie->result = NULL;
! } else {
rc = NS_LDAP_NOTFOUND;
! }
!
! out:
! delete_search_cookie(cookie);
! return (rc);
! }
!
! /*
! * find_domainname performs one or more LDAP searches to
! * find the value of the nisdomain attribute associated with
! * the input DN (with no retry).
! */
!
! static int
! find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
! ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
! {
! lookup_data_t ldata;
! ns_ldap_result_t *result;
! char **value;
! int rc;
!
! *domainname = NULL;
! *errorp = NULL;
!
! ldata.lkd_dn = dn;
! ldata.lkd_service = NULL;
! ldata.lkd_filter = _NIS_FILTER;
! ldata.lkd_cred = cred;
! ldata.lkd_user = conn_user;
!
! rc = lookup_dn(&ldata, nis_domain_attrs, &result, errorp);
! if (rc != NS_LDAP_SUCCESS)
! return (rc);
!
! value = __ns_ldap_getAttr(result->entry, _NIS_DOMAIN);
!
! if (value != NULL && value[0] != NULL) {
*domainname = strdup(value[0]);
! if (*domainname == NULL)
! rc = NS_LDAP_MEMORY;
! } else {
rc = NS_LDAP_NOTFOUND;
}
!
! (void) __ns_ldap_freeResult(&result);
return (rc);
}
/*
* __s_api_find_domainname performs one or more LDAP searches to
*** 4237,4313 ****
_P_UID,
(char *)NULL
};
int
! __ns_ldap_dn2uid(const char *dn, char **userID, const ns_cred_t *cred,
ns_ldap_error_t **errorp)
{
! ns_ldap_result_t *result = NULL;
! char *filter, *userdata;
! char errstr[MAXERROR];
char **value;
! int rc = 0;
! size_t len;
*errorp = NULL;
! *userID = NULL;
if ((dn == NULL) || (dn[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
! len = strlen(UIDDNFILTER) + strlen(dn) + 1;
! filter = malloc(len);
! if (filter == NULL) {
! return (NS_LDAP_MEMORY);
! }
! (void) snprintf(filter, len, UIDDNFILTER, dn);
- len = strlen(UIDDNFILTER_SSD) + strlen(dn) + 1;
- userdata = malloc(len);
- if (userdata == NULL) {
- free(filter);
- return (NS_LDAP_MEMORY);
- }
- (void) snprintf(userdata, len, UIDDNFILTER_SSD, dn);
-
/*
! * Unlike uid2dn, we DO want attribute mapping, so that
! * "uid" is mapped to/from samAccountName, for example.
*/
! rc = __ns_ldap_list("passwd", filter,
! __s_api_merge_SSD_filter,
! dn2uid_attrs, cred, 0,
! &result, errorp, NULL,
! userdata);
! free(filter);
! filter = NULL;
! free(userdata);
! userdata = NULL;
if (rc != NS_LDAP_SUCCESS)
! goto out;
- if (result->entries_count > 1) {
- (void) sprintf(errstr,
- gettext("Too many entries are returned for %s"), dn);
- MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
- NS_LDAP_MEMORY);
- rc = NS_LDAP_INTERNAL;
- goto out;
- }
-
value = __ns_ldap_getAttr(result->entry, _P_UID);
! if (value == NULL || value[0] == NULL) {
rc = NS_LDAP_NOTFOUND;
- goto out;
}
- *userID = strdup(value[0]);
- rc = NS_LDAP_SUCCESS;
-
- out:
(void) __ns_ldap_freeResult(&result);
- result = NULL;
return (rc);
}
int
__ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
--- 4307,4361 ----
_P_UID,
(char *)NULL
};
int
! __ns_ldap_dn2uid(const char *dn, char **userIDp, const ns_cred_t *cred,
ns_ldap_error_t **errorp)
{
! lookup_data_t ldata;
! ns_ldap_result_t *result;
char **value;
! int rc;
*errorp = NULL;
! *userIDp = NULL;
if ((dn == NULL) || (dn[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
! /*
! * Many LDAP servers do not support using the dn in a search
! * filter. As a result, we unfortunately cannot use __ns_ldap_list()
! * to lookup the DN. Instead we perform a search with the baseDN
! * being the DN we are looking for with a scope of 'base' to
! * return the entry, as this should be supported by all LDAP servers.
! */
! ldata.lkd_dn = dn;
/*
! * Since we are looking up a user account by its DN, use the attribute
! * and objectclass mappings (if present) for the passwd service.
*/
! ldata.lkd_service = "passwd";
! ldata.lkd_filter = UIDDNFILTER;
! ldata.lkd_cred = cred;
! ldata.lkd_user = NULL;
!
! rc = lookup_dn(&ldata, dn2uid_attrs, &result, errorp);
if (rc != NS_LDAP_SUCCESS)
! return (rc);
value = __ns_ldap_getAttr(result->entry, _P_UID);
! if (value != NULL && value[0] != NULL) {
! *userIDp = strdup(value[0]);
! if (*userIDp == NULL)
! rc = NS_LDAP_MEMORY;
! } else {
rc = NS_LDAP_NOTFOUND;
}
(void) __ns_ldap_freeResult(&result);
return (rc);
}
int
__ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,