4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-06 22:40:36 +08:00

* autoload.cc (ldap_search_sW): Replace ldap_search_stW.

(LdapMapErrorToWin32): Import.
	* fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate
	change to cyg_ldap::open.
	* ldap.cc (CYG_LDAP_TIMEOUT): Remove.
	(CYG_LDAP_ENUM_TIMEOUT): Remove.
	(def_tv): Remove.
	(enum_tv): Remove.
	(cyg_ldap::map_ldaperr_to_errno): New method to map LDAP error codes to
	POSIX errno codes.  Explicitly map LDAP_NO_RESULTS_RETURNED to ENMFILE.
	(cyg_ldap::wait): Ditto.
	(struct cyg_ldap_init): New struct.
	(cyg_ldap::connect_ssl): Return ULONG.  Drop setting LDAP_OPT_TIMELIMIT.
	Add call to ldap_search_sW to fetch root DSE.
	(cyg_ldap::connect_non_ssl): Ditto.
	(ldap_init_thr): New static thread function.
	(cyg_ldap::connect): New method to call connect_ssl/connect_non_ssl in
	an interruptible cygthread.
	(struct cyg_ldap_search): New struct.
	(cyg_ldap::search_s): New method to perform generic synchronous search.
	(ldap_search_thr): New static thread function.
	(cyg_ldap::search): New method to call search_s in an interruptible
	cygthread.
	(struct cyg_ldap_next_page): New struct.
	(cyg_ldap::next_page_s): New method to perform generic synchronous
	paged search.
	(ldap_next_page_thr): New static thread function.
	(cyg_ldap::next_page): New method to call next_page_s in an
	interruptible cygthread.
	(cyg_ldap::open): Return POSIX errno.  Call connect method.
	(cyg_ldap::fetch_ad_account): Call search method rather than
	ldap_search_stW.
	(cyg_ldap::enumerate_ad_accounts): Return POSIX errno.  Use infinite
	timeout in call to ldap_search_init_pageW.
	(cyg_ldap::next_account): Return POSIX errno.  Call next_page method
	rather than ldap_get_next_page_s.
	(cyg_ldap::fetch_posix_offset_for_domain): Call search method rather
	than ldap_search_stW.
	(cyg_ldap::fetch_unix_sid_from_ad): Ditto.
	(cyg_ldap::fetch_unix_name_from_rfc2307): Ditto.
	* ldap.h (class cyg_ldap): Accommodate aforementioned changes.
	* passwd.cc (pg_ent::enumerate_ad): Ditto.  Break search if one of
	cyg_ldap::enumerate_ad_accounts or cldap.next_account returns with
	an error code other than ENMFILE.
	* sec_helper.cc (cygpsid::get_id): Accommodate change to cyg_ldap::open.
	* uinfo.cc (fetch_posix_offset): Ditto.
This commit is contained in:
Corinna Vinschen 2014-06-25 09:10:50 +00:00
parent 4491d189ae
commit e35b92c202
8 changed files with 307 additions and 127 deletions

View File

@ -1,3 +1,52 @@
2014-06-25 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (ldap_search_sW): Replace ldap_search_stW.
(LdapMapErrorToWin32): Import.
* fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate
change to cyg_ldap::open.
* ldap.cc (CYG_LDAP_TIMEOUT): Remove.
(CYG_LDAP_ENUM_TIMEOUT): Remove.
(def_tv): Remove.
(enum_tv): Remove.
(cyg_ldap::map_ldaperr_to_errno): New method to map LDAP error codes to
POSIX errno codes. Explicitly map LDAP_NO_RESULTS_RETURNED to ENMFILE.
(cyg_ldap::wait): Ditto.
(struct cyg_ldap_init): New struct.
(cyg_ldap::connect_ssl): Return ULONG. Drop setting LDAP_OPT_TIMELIMIT.
Add call to ldap_search_sW to fetch root DSE.
(cyg_ldap::connect_non_ssl): Ditto.
(ldap_init_thr): New static thread function.
(cyg_ldap::connect): New method to call connect_ssl/connect_non_ssl in
an interruptible cygthread.
(struct cyg_ldap_search): New struct.
(cyg_ldap::search_s): New method to perform generic synchronous search.
(ldap_search_thr): New static thread function.
(cyg_ldap::search): New method to call search_s in an interruptible
cygthread.
(struct cyg_ldap_next_page): New struct.
(cyg_ldap::next_page_s): New method to perform generic synchronous
paged search.
(ldap_next_page_thr): New static thread function.
(cyg_ldap::next_page): New method to call next_page_s in an
interruptible cygthread.
(cyg_ldap::open): Return POSIX errno. Call connect method.
(cyg_ldap::fetch_ad_account): Call search method rather than
ldap_search_stW.
(cyg_ldap::enumerate_ad_accounts): Return POSIX errno. Use infinite
timeout in call to ldap_search_init_pageW.
(cyg_ldap::next_account): Return POSIX errno. Call next_page method
rather than ldap_get_next_page_s.
(cyg_ldap::fetch_posix_offset_for_domain): Call search method rather
than ldap_search_stW.
(cyg_ldap::fetch_unix_sid_from_ad): Ditto.
(cyg_ldap::fetch_unix_name_from_rfc2307): Ditto.
* ldap.h (class cyg_ldap): Accommodate aforementioned changes.
* passwd.cc (pg_ent::enumerate_ad): Ditto. Break search if one of
cyg_ldap::enumerate_ad_accounts or cldap.next_account returns with
an error code other than ENMFILE.
* sec_helper.cc (cygpsid::get_id): Accommodate change to cyg_ldap::open.
* uinfo.cc (fetch_posix_offset): Ditto.
2014-06-23 Corinna Vinschen <corinna@vinschen.de> 2014-06-23 Corinna Vinschen <corinna@vinschen.de>
* spawn.cc (find_exec): Initialize err (CID 60111). * spawn.cc (find_exec): Initialize err (CID 60111).

View File

@ -597,13 +597,14 @@ LoadDLLfunc (ldap_msgfree, 0, wldap32)
LoadDLLfunc (ldap_next_entry, 0, wldap32) LoadDLLfunc (ldap_next_entry, 0, wldap32)
LoadDLLfunc (ldap_search_abandon_page, 0, wldap32) LoadDLLfunc (ldap_search_abandon_page, 0, wldap32)
LoadDLLfunc (ldap_search_init_pageW, 0, wldap32) LoadDLLfunc (ldap_search_init_pageW, 0, wldap32)
LoadDLLfunc (ldap_search_stW, 0, wldap32) LoadDLLfunc (ldap_search_sW, 0, wldap32)
LoadDLLfunc (ldap_set_option, 0, wldap32) LoadDLLfunc (ldap_set_option, 0, wldap32)
LoadDLLfunc (ldap_sslinitW, 0, wldap32) LoadDLLfunc (ldap_sslinitW, 0, wldap32)
LoadDLLfunc (ldap_unbind, 0, wldap32) LoadDLLfunc (ldap_unbind, 0, wldap32)
LoadDLLfunc (ldap_value_freeW, 0, wldap32) LoadDLLfunc (ldap_value_freeW, 0, wldap32)
LoadDLLfunc (ldap_value_free_len, 0, wldap32) LoadDLLfunc (ldap_value_free_len, 0, wldap32)
LoadDLLfunc (LdapGetLastError, 0, wldap32) LoadDLLfunc (LdapGetLastError, 0, wldap32)
LoadDLLfunc (LdapMapErrorToWin32, 0, wldap32)
#pragma pop_macro ("mangle") #pragma pop_macro ("mangle")
LoadDLLfunc (WNetCloseEnum, 4, mpr) LoadDLLfunc (WNetCloseEnum, 4, mpr)

View File

@ -354,7 +354,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
uid_t map_uid = ILLEGAL_UID; uid_t map_uid = ILLEGAL_UID;
domain = cygheap->dom.get_rfc2307_domain (); domain = cygheap->dom.get_rfc2307_domain ();
if ((ldap_open = cldap.open (domain))) if ((ldap_open = (cldap.open (domain) == NO_ERROR)))
map_uid = cldap.remap_uid (nfs_attr->uid); map_uid = cldap.remap_uid (nfs_attr->uid);
if (map_uid == ILLEGAL_UID) if (map_uid == ILLEGAL_UID)
map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid); map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid);
@ -366,7 +366,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
gid_t map_gid = ILLEGAL_GID; gid_t map_gid = ILLEGAL_GID;
domain = cygheap->dom.get_rfc2307_domain (); domain = cygheap->dom.get_rfc2307_domain ();
if ((ldap_open || cldap.open (domain))) if ((ldap_open || cldap.open (domain) == NO_ERROR))
map_gid = cldap.remap_gid (nfs_attr->gid); map_gid = cldap.remap_gid (nfs_attr->gid);
if (map_gid == ILLEGAL_GID) if (map_gid == ILLEGAL_GID)
map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid); map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid);

View File

@ -22,14 +22,8 @@ details. */
#include "dsgetdc.h" #include "dsgetdc.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#define CYG_LDAP_TIMEOUT 5 /* seconds */
#define CYG_LDAP_ENUM_TIMEOUT 60 /* seconds */
#define CYG_LDAP_ENUM_PAGESIZE 100 /* entries per page */ #define CYG_LDAP_ENUM_PAGESIZE 100 /* entries per page */
static LDAP_TIMEVAL def_tv = { CYG_LDAP_TIMEOUT, 0 };
static LDAP_TIMEVAL enum_tv = { CYG_LDAP_ENUM_TIMEOUT, 0 };
static PWCHAR rootdse_attr[] = static PWCHAR rootdse_attr[] =
{ {
(PWCHAR) L"defaultNamingContext", (PWCHAR) L"defaultNamingContext",
@ -78,38 +72,84 @@ PWCHAR rfc2307_gid_attr[] =
NULL NULL
}; };
bool /* ================================================================= */
/* Helper methods. */
/* ================================================================= */
inline int
cyg_ldap::map_ldaperr_to_errno (ULONG lerr)
{
switch (lerr)
{
case LDAP_SUCCESS:
return NO_ERROR;
case LDAP_NO_RESULTS_RETURNED:
/* LdapMapErrorToWin32 maps LDAP_NO_RESULTS_RETURNED to ERROR_MORE_DATA,
which in turn is mapped to EMSGSIZE by geterrno_from_win_error. This
is SO wrong, especially considering that LDAP_MORE_RESULTS_TO_RETURN
is mapped to ERROR_MORE_DATA as well :-P */
return ENMFILE;
default:
break;
}
return geterrno_from_win_error (LdapMapErrorToWin32 (lerr));
}
inline int
cyg_ldap::wait (cygthread *thr)
{
if (!thr)
return EIO;
if (cygwait (*thr, INFINITE, cw_sig | cw_sig_eintr) != WAIT_OBJECT_0)
{
thr->terminate_thread ();
_my_tls.call_signal_handler ();
return EINTR;
}
thr->detach ();
return 0;
}
/* ================================================================= */
/* Helper struct and functions for interruptible LDAP initalization. */
/* ================================================================= */
struct cyg_ldap_init {
cyg_ldap *that;
PCWSTR domain;
bool ssl;
ULONG ret;
};
ULONG
cyg_ldap::connect_ssl (PCWSTR domain) cyg_ldap::connect_ssl (PCWSTR domain)
{ {
ULONG ret, timelimit = CYG_LDAP_TIMEOUT; ULONG ret;
if (!(lh = ldap_sslinitW ((PWCHAR) domain, LDAP_SSL_PORT, 1))) if (!(lh = ldap_sslinitW ((PWCHAR) domain, LDAP_SSL_PORT, 1)))
{ {
debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ()); debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ());
return false; return LdapGetLastError ();
} }
if ((ret = ldap_set_option (lh, LDAP_OPT_TIMELIMIT, &timelimit))
!= LDAP_SUCCESS)
debug_printf ("ldap_set_option(LDAP_OPT_TIMELIMIT) error 0x%02x", ret);
if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS) if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS)
{
debug_printf ("ldap_bind(%W) 0x%02x", domain, ret); debug_printf ("ldap_bind(%W) 0x%02x", domain, ret);
ldap_unbind (lh); else if ((ret = ldap_search_sW (lh, NULL, LDAP_SCOPE_BASE,
lh = NULL; (PWCHAR) L"(objectclass=*)", rootdse_attr,
return false; 0, &msg))
} != LDAP_SUCCESS)
return true; debug_printf ("ldap_search(%W, ROOTDSE) error 0x%02x", domain, ret);
return ret;
} }
bool ULONG
cyg_ldap::connect_non_ssl (PCWSTR domain) cyg_ldap::connect_non_ssl (PCWSTR domain)
{ {
ULONG ret, timelimit = CYG_LDAP_TIMEOUT; ULONG ret;
if (!(lh = ldap_initW ((PWCHAR) domain, LDAP_PORT))) if (!(lh = ldap_initW ((PWCHAR) domain, LDAP_PORT)))
{ {
debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ()); debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ());
return false; return LdapGetLastError ();
} }
if ((ret = ldap_set_option (lh, LDAP_OPT_SIGN, LDAP_OPT_ON)) if ((ret = ldap_set_option (lh, LDAP_OPT_SIGN, LDAP_OPT_ON))
!= LDAP_SUCCESS) != LDAP_SUCCESS)
@ -117,40 +157,133 @@ cyg_ldap::connect_non_ssl (PCWSTR domain)
if ((ret = ldap_set_option (lh, LDAP_OPT_ENCRYPT, LDAP_OPT_ON)) if ((ret = ldap_set_option (lh, LDAP_OPT_ENCRYPT, LDAP_OPT_ON))
!= LDAP_SUCCESS) != LDAP_SUCCESS)
debug_printf ("ldap_set_option(LDAP_OPT_ENCRYPT) error 0x%02x", ret); debug_printf ("ldap_set_option(LDAP_OPT_ENCRYPT) error 0x%02x", ret);
if ((ret = ldap_set_option (lh, LDAP_OPT_TIMELIMIT, &timelimit))
!= LDAP_SUCCESS)
debug_printf ("ldap_set_option(LDAP_OPT_TIMELIMIT) error 0x%02x", ret);
if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS) if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS)
{
debug_printf ("ldap_bind(%W) 0x%02x", domain, ret); debug_printf ("ldap_bind(%W) 0x%02x", domain, ret);
ldap_unbind (lh); else if ((ret = ldap_search_sW (lh, NULL, LDAP_SCOPE_BASE,
lh = NULL; (PWCHAR) L"(objectclass=*)", rootdse_attr,
return false; 0, &msg))
} != LDAP_SUCCESS)
return true; debug_printf ("ldap_search(%W, ROOTDSE) error 0x%02x", domain, ret);
return ret;
} }
bool static DWORD WINAPI
cyg_ldap::open (PCWSTR domain) ldap_init_thr (LPVOID param)
{
cyg_ldap_init *cl = (cyg_ldap_init *) param;
cl->ret = cl->ssl ? cl->that->connect_ssl (cl->domain)
: cl->that->connect_non_ssl (cl->domain);
return 0;
}
inline int
cyg_ldap::connect (PCWSTR domain)
{
/* FIXME? connect_ssl can take ages even when failing, so we're trying to
do everything the non-SSL (but still encrypted) way. */
cyg_ldap_init cl = { this, domain, false, NO_ERROR };
cygthread *thr = new cygthread (ldap_init_thr, &cl, "ldap_init");
return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
}
/* ================================================================= */
/* Helper struct and functions for interruptible LDAP search. */
/* ================================================================= */
struct cyg_ldap_search {
cyg_ldap *that;
PWCHAR base;
PWCHAR filter;
PWCHAR *attrs;
ULONG ret;
};
ULONG
cyg_ldap::search_s (PWCHAR base, PWCHAR filter, PWCHAR *attrs)
{ {
ULONG ret; ULONG ret;
if ((ret = ldap_search_sW (lh, base, LDAP_SCOPE_SUBTREE, filter,
attrs, 0, &msg)) != LDAP_SUCCESS)
debug_printf ("ldap_search_sW(%W,%W) error 0x%02x", base, filter, ret);
return ret;
}
static DWORD WINAPI
ldap_search_thr (LPVOID param)
{
cyg_ldap_search *cl = (cyg_ldap_search *) param;
cl->ret = cl->that->search_s (cl->base, cl->filter, cl->attrs);
return 0;
}
inline int
cyg_ldap::search (PWCHAR base, PWCHAR filter, PWCHAR *attrs)
{
cyg_ldap_search cl = { this, base, filter, attrs, NO_ERROR };
cygthread *thr = new cygthread (ldap_search_thr, &cl, "ldap_search");
return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
}
/* ================================================================= */
/* Helper struct and functions for interruptible LDAP page search. */
/* ================================================================= */
struct cyg_ldap_next_page {
cyg_ldap *that;
ULONG ret;
};
ULONG
cyg_ldap::next_page_s ()
{
ULONG total;
ULONG ret;
do
{
ret = ldap_get_next_page_s (lh, srch_id, NULL, CYG_LDAP_ENUM_PAGESIZE,
&total, &srch_msg);
}
while (ret == LDAP_SUCCESS && ldap_count_entries (lh, srch_msg) == 0);
if (ret && ret != LDAP_NO_RESULTS_RETURNED)
debug_printf ("ldap_result() error 0x%02x", ret);
return ret;
}
static DWORD WINAPI
ldap_next_page_thr (LPVOID param)
{
cyg_ldap_next_page *cl = (cyg_ldap_next_page *) param;
cl->ret = cl->that->next_page_s ();
return 0;
}
inline int
cyg_ldap::next_page ()
{
cyg_ldap_next_page cl = { this, NO_ERROR };
cygthread *thr = new cygthread (ldap_next_page_thr, &cl, "ldap_next_page");
return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
}
/* ================================================================= */
/* Public methods. */
/* ================================================================= */
int
cyg_ldap::open (PCWSTR domain)
{
int ret = 0;
/* Already open? */ /* Already open? */
if (lh) if (lh)
return true; return 0;
/* FIXME? connect_ssl can take ages even when failing, so we're trying to if ((ret = connect (domain)) != NO_ERROR)
do everything the non-SSL (but still encrypted) way. */
if (/*!connect_ssl (NULL) && */ !connect_non_ssl (domain))
return false;
if ((ret = ldap_search_stW (lh, NULL, LDAP_SCOPE_BASE,
(PWCHAR) L"(objectclass=*)", rootdse_attr,
0, &def_tv, &msg))
!= LDAP_SUCCESS)
{
debug_printf ("ldap_search(%W, ROOTDSE) error 0x%02x", domain, ret);
goto err; goto err;
} /* Prime `ret' and fetch ROOTDSE search result. */
ret = EIO;
if (!(entry = ldap_first_entry (lh, msg))) if (!(entry = ldap_first_entry (lh, msg)))
{ {
debug_printf ("No ROOTDSE entry for %W", domain); debug_printf ("No ROOTDSE entry for %W", domain);
@ -179,10 +312,11 @@ cyg_ldap::open (PCWSTR domain)
ldap_value_freeW (val); ldap_value_freeW (val);
val = NULL; val = NULL;
ldap_msgfree (msg); ldap_msgfree (msg);
msg = entry = NULL; return true; msg = entry = NULL;
return 0;
err: err:
close (); close ();
return false; return ret;
} }
void void
@ -215,7 +349,6 @@ cyg_ldap::fetch_ad_account (PSID sid, bool group, PCWSTR domain)
LONG len = (LONG) RtlLengthSid (sid); LONG len = (LONG) RtlLengthSid (sid);
PBYTE s = (PBYTE) sid; PBYTE s = (PBYTE) sid;
static WCHAR hex_wchars[] = L"0123456789abcdef"; static WCHAR hex_wchars[] = L"0123456789abcdef";
ULONG ret;
tmp_pathbuf tp; tmp_pathbuf tp;
if (msg) if (msg)
@ -256,13 +389,8 @@ cyg_ldap::fetch_ad_account (PSID sid, bool group, PCWSTR domain)
} }
} }
attr = group ? group_attr : user_attr; attr = group ? group_attr : user_attr;
if ((ret = ldap_search_stW (lh, rdse, LDAP_SCOPE_SUBTREE, filter, if (search (rdse, filter, attr) != 0)
attr, 0, &def_tv, &msg)) != LDAP_SUCCESS)
{
debug_printf ("ldap_search_stW(%W,%W) error 0x%02x",
rdse, filter, ret);
return false; return false;
}
if (!(entry = ldap_first_entry (lh, msg))) if (!(entry = ldap_first_entry (lh, msg)))
{ {
debug_printf ("No entry for %W in rootdse %W", filter, rdse); debug_printf ("No entry for %W in rootdse %W", filter, rdse);
@ -271,15 +399,16 @@ cyg_ldap::fetch_ad_account (PSID sid, bool group, PCWSTR domain)
return true; return true;
} }
bool int
cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group) cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group)
{ {
int ret;
tmp_pathbuf tp; tmp_pathbuf tp;
PCWSTR filter; PCWSTR filter;
close (); close ();
if (!open (domain)) if ((ret = open (domain)) != NO_ERROR)
return false; return ret;
if (!group) if (!group)
filter = L"(&(objectClass=User)" filter = L"(&(objectClass=User)"
@ -296,26 +425,23 @@ cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group)
"(!(groupType:" LDAP_MATCHING_RULE_BIT_AND ":=1))" "(!(groupType:" LDAP_MATCHING_RULE_BIT_AND ":=1))"
"(objectSid=*))"; "(objectSid=*))";
srch_id = ldap_search_init_pageW (lh, rootdse, LDAP_SCOPE_SUBTREE, srch_id = ldap_search_init_pageW (lh, rootdse, LDAP_SCOPE_SUBTREE,
(PWCHAR) filter, sid_attr, 0, (PWCHAR) filter, sid_attr, 0, NULL, NULL,
NULL, NULL, CYG_LDAP_ENUM_TIMEOUT, INFINITE, CYG_LDAP_ENUM_PAGESIZE, NULL);
CYG_LDAP_ENUM_PAGESIZE, NULL);
if (srch_id == NULL) if (srch_id == NULL)
{ {
debug_printf ("ldap_search_init_pageW(%W,%W) error 0x%02x", debug_printf ("ldap_search_init_pageW(%W,%W) error 0x%02x",
rootdse, filter, LdapGetLastError ()); rootdse, filter, LdapGetLastError ());
return false; return map_ldaperr_to_errno (LdapGetLastError ());
} }
return true; return NO_ERROR;
} }
bool int
cyg_ldap::next_account (cygsid &sid) cyg_ldap::next_account (cygsid &sid)
{ {
ULONG ret; ULONG ret;
PLDAP_BERVAL *bval; PLDAP_BERVAL *bval;
ULONG total;
if (srch_entry) if (srch_entry)
{ {
if ((srch_entry = ldap_next_entry (lh, srch_entry)) if ((srch_entry = ldap_next_entry (lh, srch_entry))
@ -323,38 +449,32 @@ cyg_ldap::next_account (cygsid &sid)
{ {
sid = (PSID) bval[0]->bv_val; sid = (PSID) bval[0]->bv_val;
ldap_value_free_len (bval); ldap_value_free_len (bval);
return true; return NO_ERROR;
} }
ldap_msgfree (srch_msg); ldap_msgfree (srch_msg);
srch_msg = srch_entry = NULL; srch_msg = srch_entry = NULL;
} }
do ret = next_page ();
if (ret == NO_ERROR)
{ {
ret = ldap_get_next_page_s (lh, srch_id, &enum_tv, CYG_LDAP_ENUM_PAGESIZE, if ((srch_entry = ldap_first_entry (lh, srch_msg))
&total, &srch_msg);
}
while (ret == LDAP_SUCCESS && ldap_count_entries (lh, srch_msg) == 0);
if (ret == LDAP_NO_RESULTS_RETURNED)
;
else if (ret != LDAP_SUCCESS)
debug_printf ("ldap_result() error 0x%02x", ret);
else if ((srch_entry = ldap_first_entry (lh, srch_msg))
&& (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0]))) && (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0])))
{ {
sid = (PSID) bval[0]->bv_val; sid = (PSID) bval[0]->bv_val;
ldap_value_free_len (bval); ldap_value_free_len (bval);
return true; return NO_ERROR;
}
ret = EIO;
} }
ldap_search_abandon_page (lh, srch_id); ldap_search_abandon_page (lh, srch_id);
srch_id = NULL; srch_id = NULL;
return false; return ret;
} }
uint32_t uint32_t
cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain) cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain)
{ {
WCHAR filter[300]; WCHAR filter[300];
ULONG ret;
if (msg) if (msg)
{ {
@ -370,14 +490,8 @@ cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain)
by flatName rather than by name. */ by flatName rather than by name. */
__small_swprintf (filter, L"(&(objectClass=trustedDomain)(%W=%W))", __small_swprintf (filter, L"(&(objectClass=trustedDomain)(%W=%W))",
wcschr (domain, L'.') ? L"name" : L"flatName", domain); wcschr (domain, L'.') ? L"name" : L"flatName", domain);
if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter, if (search (rootdse, filter, attr = tdom_attr) != 0)
attr = tdom_attr, 0, &def_tv, &msg))
!= LDAP_SUCCESS)
{
debug_printf ("ldap_search_stW(%W,%W) error 0x%02x",
rootdse, filter, ret);
return 0; return 0;
}
if (!(entry = ldap_first_entry (lh, msg))) if (!(entry = ldap_first_entry (lh, msg)))
{ {
debug_printf ("No entry for %W in rootdse %W", filter, rootdse); debug_printf ("No entry for %W in rootdse %W", filter, rootdse);
@ -410,7 +524,6 @@ bool
cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group) cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group)
{ {
WCHAR filter[48]; WCHAR filter[48];
ULONG ret;
PLDAP_BERVAL *bval; PLDAP_BERVAL *bval;
if (msg) if (msg)
@ -422,13 +535,8 @@ cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group)
__small_swprintf (filter, L"(&(objectClass=Group)(gidNumber=%u))", id); __small_swprintf (filter, L"(&(objectClass=Group)(gidNumber=%u))", id);
else else
__small_swprintf (filter, L"(&(objectClass=User)(uidNumber=%u))", id); __small_swprintf (filter, L"(&(objectClass=User)(uidNumber=%u))", id);
if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter, if (search (rootdse, filter, sid_attr) != 0)
sid_attr, 0, &def_tv, &msg)) != LDAP_SUCCESS)
{
debug_printf ("ldap_search_stW(%W,%W) error 0x%02x",
rootdse, filter, ret);
return false; return false;
}
if ((entry = ldap_first_entry (lh, msg)) if ((entry = ldap_first_entry (lh, msg))
&& (bval = ldap_get_values_lenW (lh, entry, sid_attr[0]))) && (bval = ldap_get_values_lenW (lh, entry, sid_attr[0])))
{ {
@ -443,7 +551,6 @@ PWCHAR
cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group) cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group)
{ {
WCHAR filter[52]; WCHAR filter[52];
ULONG ret;
if (msg) if (msg)
{ {
@ -461,13 +568,8 @@ cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group)
else else
__small_swprintf (filter, L"(&(objectClass=posixAccount)(uidNumber=%u))", __small_swprintf (filter, L"(&(objectClass=posixAccount)(uidNumber=%u))",
id); id);
if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter, attr, if (search (rootdse, filter, attr) != 0)
0, &def_tv, &msg)) != LDAP_SUCCESS)
{
debug_printf ("ldap_search_stW(%W,%W) error 0x%02x",
rootdse, filter, ret);
return NULL; return NULL;
}
if (!(entry = ldap_first_entry (lh, msg))) if (!(entry = ldap_first_entry (lh, msg)))
{ {
debug_printf ("No entry for %W in rootdse %W", filter, rootdse); debug_printf ("No entry for %W in rootdse %W", filter, rootdse);

View File

@ -36,8 +36,11 @@ class cyg_ldap {
PLDAPSearch srch_id; PLDAPSearch srch_id;
PLDAPMessage srch_msg, srch_entry; PLDAPMessage srch_msg, srch_entry;
bool connect_ssl (PCWSTR domain); inline int map_ldaperr_to_errno (ULONG lerr);
bool connect_non_ssl (PCWSTR domain); inline int wait (cygthread *thr);
inline int connect (PCWSTR domain);
inline int search (PWCHAR base, PWCHAR filter, PWCHAR *attrs);
inline int next_page ();
bool fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group); bool fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group);
PWCHAR fetch_unix_name_from_rfc2307 (uint32_t id, bool group); PWCHAR fetch_unix_name_from_rfc2307 (uint32_t id, bool group);
PWCHAR get_string_attribute (int idx); PWCHAR get_string_attribute (int idx);
@ -49,12 +52,17 @@ public:
{} {}
~cyg_ldap () { close (); } ~cyg_ldap () { close (); }
ULONG connect_ssl (PCWSTR domain);
ULONG connect_non_ssl (PCWSTR domain);
ULONG search_s (PWCHAR base, PWCHAR filter, PWCHAR *attrs);
ULONG next_page_s ();
operator PLDAP () const { return lh; } operator PLDAP () const { return lh; }
bool open (PCWSTR in_domain); int open (PCWSTR in_domain);
void close (); void close ();
bool fetch_ad_account (PSID sid, bool group, PCWSTR domain = NULL); bool fetch_ad_account (PSID sid, bool group, PCWSTR domain = NULL);
bool enumerate_ad_accounts (PCWSTR domain, bool group); int enumerate_ad_accounts (PCWSTR domain, bool group);
bool next_account (cygsid &sid); int next_account (cygsid &sid);
uint32_t fetch_posix_offset_for_domain (PCWSTR domain); uint32_t fetch_posix_offset_for_domain (PCWSTR domain);
uid_t remap_uid (uid_t uid); uid_t remap_uid (uid_t uid);
gid_t remap_gid (gid_t gid); gid_t remap_gid (gid_t gid);

View File

@ -593,13 +593,19 @@ pg_ent::enumerate_ad ()
if (!cnt) if (!cnt)
{ {
PDS_DOMAIN_TRUSTSW td; PDS_DOMAIN_TRUSTSW td;
int ret;
if (!resume) if (!resume)
{ {
++resume; ++resume;
if (!nss_db_enum_primary () if (!nss_db_enum_primary ())
|| !cldap.enumerate_ad_accounts (NULL, group))
continue; continue;
if ((ret = cldap.enumerate_ad_accounts (NULL, group)) != NO_ERROR)
{
cldap.close ();
set_errno (ret);
return NULL;
}
} }
else if ((td = cygheap->dom.trusted_domain (resume - 1))) else if ((td = cygheap->dom.trusted_domain (resume - 1)))
{ {
@ -612,9 +618,15 @@ pg_ent::enumerate_ad ()
if (((enums & ENUM_TDOMS_ALL) && td->Flags & DS_DOMAIN_PRIMARY) if (((enums & ENUM_TDOMS_ALL) && td->Flags & DS_DOMAIN_PRIMARY)
|| !td->DomainSid || !td->DomainSid
|| (!nss_db_enum_tdom (td->NetbiosDomainName) || (!nss_db_enum_tdom (td->NetbiosDomainName)
&& !nss_db_enum_tdom (td->DnsDomainName)) && !nss_db_enum_tdom (td->DnsDomainName)))
|| !cldap.enumerate_ad_accounts (td->DnsDomainName, group))
continue; continue;
if ((ret = cldap.enumerate_ad_accounts (td->DnsDomainName, group))
!= NO_ERROR)
{
cldap.close ();
set_errno (ret);
return NULL;
}
} }
else else
{ {
@ -624,7 +636,8 @@ pg_ent::enumerate_ad ()
} }
++cnt; ++cnt;
cygsid sid; cygsid sid;
if (cldap.next_account (sid)) int ret = cldap.next_account (sid);
if (ret == NO_ERROR)
{ {
fetch_user_arg_t arg; fetch_user_arg_t arg;
arg.type = SID_arg; arg.type = SID_arg;
@ -632,6 +645,13 @@ pg_ent::enumerate_ad ()
char *line = pg.fetch_account_from_windows (arg, &cldap); char *line = pg.fetch_account_from_windows (arg, &cldap);
if (line) if (line)
return pg.add_account_post_fetch (line, false); return pg.add_account_post_fetch (line, false);
ret = EIO;
}
if (ret != ENMFILE)
{
cldap.close ();
set_errno (ret);
return NULL;
} }
cnt = 0; cnt = 0;
} }

View File

@ -122,7 +122,7 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
gid_t map_gid = cygheap->ugid_cache.get_gid (gid); gid_t map_gid = cygheap->ugid_cache.get_gid (gid);
if (map_gid == ILLEGAL_GID) if (map_gid == ILLEGAL_GID)
{ {
if (pldap->open (cygheap->dom.get_rfc2307_domain ())) if (pldap->open (cygheap->dom.get_rfc2307_domain ()) == NO_ERROR)
map_gid = pldap->remap_gid (gid); map_gid = pldap->remap_gid (gid);
if (map_gid == ILLEGAL_GID) if (map_gid == ILLEGAL_GID)
map_gid = MAP_UNIX_TO_CYGWIN_ID (gid); map_gid = MAP_UNIX_TO_CYGWIN_ID (gid);
@ -151,7 +151,7 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
uid_t map_uid = cygheap->ugid_cache.get_uid (uid); uid_t map_uid = cygheap->ugid_cache.get_uid (uid);
if (map_uid == ILLEGAL_UID) if (map_uid == ILLEGAL_UID)
{ {
if (pldap->open (cygheap->dom.get_rfc2307_domain ())) if (pldap->open (cygheap->dom.get_rfc2307_domain ()) == NO_ERROR)
map_uid = pldap->remap_uid (uid); map_uid = pldap->remap_uid (uid);
if (map_uid == ILLEGAL_UID) if (map_uid == ILLEGAL_UID)
map_uid = MAP_UNIX_TO_CYGWIN_ID (uid); map_uid = MAP_UNIX_TO_CYGWIN_ID (uid);

View File

@ -1141,7 +1141,7 @@ fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, cyg_ldap *cldap)
if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY) && td->DomainSid) if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY) && td->DomainSid)
{ {
if (!cldap->open (NULL)) if (cldap->open (NULL) != NO_ERROR)
{ {
/* We're probably running under a local account, so we're not allowed /* We're probably running under a local account, so we're not allowed
to fetch any information from AD beyond the most obvious. Never to fetch any information from AD beyond the most obvious. Never
@ -1241,7 +1241,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
DC for some weird reason. Use LDAP instead. */ DC for some weird reason. Use LDAP instead. */
PWCHAR val; PWCHAR val;
if (cldap->open (NULL) if (cldap->open (NULL) == NO_ERROR
&& cldap->fetch_ad_account (sid, is_group ()) && cldap->fetch_ad_account (sid, is_group ())
&& (val = cldap->get_group_name ())) && (val = cldap->get_group_name ()))
{ {
@ -1598,7 +1598,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
if (is_domain_account) if (is_domain_account)
{ {
/* Use LDAP to fetch domain account infos. */ /* Use LDAP to fetch domain account infos. */
if (!cldap->open (NULL)) if (cldap->open (NULL) != NO_ERROR)
break; break;
if (cldap->fetch_ad_account (sid, is_group (), domain)) if (cldap->fetch_ad_account (sid, is_group (), domain))
{ {