Dmitry Timoshkov : wldap32: Locally cache "supportedControl" rootDSE attribute, and check it in ldap_set_option(LDAP_OPT_SERVER_CONTROLS).

Alexandre Julliard julliard at winehq.org
Fri Apr 3 14:55:38 CDT 2020


Module: wine
Branch: master
Commit: 07b18a7672308ddc5124749603ea7f5c8b5ee254
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=07b18a7672308ddc5124749603ea7f5c8b5ee254

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Fri Apr  3 16:57:03 2020 +0800

wldap32: Locally cache "supportedControl" rootDSE attribute, and check it in ldap_set_option(LDAP_OPT_SERVER_CONTROLS).

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/adsldp/tests/ldap.c       |  3 ---
 dlls/wldap32/bind.c            |  4 +++
 dlls/wldap32/option.c          | 57 +++++++++++++++++++++++++++++++++++++++++-
 dlls/wldap32/tests/parse.c     |  2 --
 dlls/wldap32/winldap_private.h |  1 +
 5 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c
index 80815b07a0..208a9fa2fe 100644
--- a/dlls/adsldp/tests/ldap.c
+++ b/dlls/adsldp/tests/ldap.c
@@ -498,15 +498,12 @@ todo_wine
     pref[1].vValue.Integer = ADS_SECURITY_INFO_OWNER | ADS_SECURITY_INFO_GROUP | ADS_SECURITY_INFO_DACL;
     pref[1].dwStatus = 0xdeadbeef;
     hr = IDirectorySearch_SetSearchPreference(ds, pref, ARRAY_SIZE(pref));
-todo_wine
     ok(hr == S_ADS_ERRORSOCCURRED, "got %#x\n", hr);
     ok(pref[0].dwStatus == ADS_STATUS_S_OK, "got %d\n", pref[0].dwStatus);
     /* ldap.forumsys.com doesn't support NT security, real ADs DC - does  */
-todo_wine
     ok(pref[1].dwStatus == ADS_STATUS_INVALID_SEARCHPREF, "got %d\n", pref[1].dwStatus);
 
     hr = IDirectorySearch_ExecuteSearch(ds, (WCHAR *)L"(objectClass=*)", NULL, ~0, &sh);
-todo_wine
     ok(hr == S_OK, "got %#x\n", hr);
     if (hr != S_OK) goto fail;
 
diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c
index aedda13634..1498dc49fe 100644
--- a/dlls/wldap32/bind.c
+++ b/dlls/wldap32/bind.c
@@ -766,6 +766,8 @@ ULONG CDECL WLDAP32_ldap_unbind( WLDAP32_LDAP *ld )
     if (ld)
     {
         ret = map_error( ldap_unbind_ext( ld->ld, NULL, NULL ));
+        if ( ld->ld_server_ctrls )
+            ldap_value_free_len( ld->ld_server_ctrls );
         heap_free( ld );
     }
     else
@@ -797,6 +799,8 @@ ULONG CDECL WLDAP32_ldap_unbind_s( WLDAP32_LDAP *ld )
     if (ld)
     {
         ret = map_error( ldap_unbind_ext_s( ld->ld, NULL, NULL ));
+        if ( ld->ld_server_ctrls )
+            ldap_value_free_len( ld->ld_server_ctrls );
         heap_free( ld );
     }
     else
diff --git a/dlls/wldap32/option.c b/dlls/wldap32/option.c
index 8a8a86b579..87eb779953 100644
--- a/dlls/wldap32/option.c
+++ b/dlls/wldap32/option.c
@@ -398,6 +398,58 @@ ULONG CDECL ldap_set_optionA( WLDAP32_LDAP *ld, int option, void *value )
     return ret;
 }
 
+#ifdef HAVE_LDAP
+
+static BOOL query_supported_server_ctrls( WLDAP32_LDAP *ld )
+{
+    char *attrs[] = { (char *)"supportedControl", NULL };
+    LDAPMessage *res, *entry;
+
+    if ( ld->ld_server_ctrls ) return TRUE;
+
+    if (ldap_search_ext_s( ld->ld, (char *)"", LDAP_SCOPE_BASE, (char *)"(objectClass=*)", attrs, FALSE,
+                           NULL, NULL, NULL, 0, &res ) != LDAP_SUCCESS)
+        return FALSE;
+
+    entry = ldap_first_entry( ld->ld, res );
+    if (entry)
+    {
+        ULONG count, i;
+
+        ld->ld_server_ctrls = ldap_get_values_len( ld->ld, entry, attrs[0] );
+        count = ldap_count_values_len( ld->ld_server_ctrls );
+        for (i = 0; i < count; i++)
+            TRACE("%u: %s\n", i, debugstr_an( ld->ld_server_ctrls[i]->bv_val, ld->ld_server_ctrls[i]->bv_len ));
+    }
+
+    ldap_msgfree( res );
+
+    return ld->ld_server_ctrls != NULL;
+}
+
+static BOOL is_supported_server_ctrls( WLDAP32_LDAP *ld, LDAPControl **ctrls )
+{
+    ULONG user_count, server_count, i, n, supported = 0;
+
+    if (!query_supported_server_ctrls( ld ))
+        return TRUE; /* can't verify, let the server handle it on next query */
+
+    user_count = controlarraylenU( ctrls );
+    server_count = ldap_count_values_len( ld->ld_server_ctrls );
+
+    for (n = 0; n < user_count; n++)
+    {
+        for (i = 0; i < server_count; i++)
+        {
+            if (!strncmp( ctrls[n]->ldctl_oid, ld->ld_server_ctrls[i]->bv_val, ld->ld_server_ctrls[i]->bv_len))
+                supported++;
+        }
+    }
+
+    return supported == user_count;
+}
+#endif
+
 /***********************************************************************
  *      ldap_set_optionW     (WLDAP32.@)
  *
@@ -433,7 +485,10 @@ ULONG CDECL ldap_set_optionW( WLDAP32_LDAP *ld, int option, void *value )
         ctrlsU = controlarrayWtoU( value );
         if (!ctrlsU) return WLDAP32_LDAP_NO_MEMORY;
 
-        ret = map_error( ldap_set_option( ld->ld, option, ctrlsU ));
+        if (!is_supported_server_ctrls( ld, ctrlsU ))
+            ret = WLDAP32_LDAP_PARAM_ERROR;
+        else
+            ret = map_error( ldap_set_option( ld->ld, option, ctrlsU ));
         controlarrayfreeU( ctrlsU );
         return ret;
     }
diff --git a/dlls/wldap32/tests/parse.c b/dlls/wldap32/tests/parse.c
index c2435809d2..5a49b9c69d 100644
--- a/dlls/wldap32/tests/parse.c
+++ b/dlls/wldap32/tests/parse.c
@@ -201,12 +201,10 @@ static void test_ldap_server_control( void )
     ctrls[0] = &mask;
     ctrls[1] = NULL;
     ret = ldap_set_optionW(ld, LDAP_OPT_SERVER_CONTROLS, ctrls);
-todo_wine
     ok( ret == LDAP_PARAM_ERROR, "ldap_set_optionW should fail: 0x%x\n", ret );
 
     res = NULL;
     ret = ldap_search_sA( ld, (char *)"OU=scientists,DC=example,DC=com", LDAP_SCOPE_BASE, (char *)"(objectclass=*)", NULL, FALSE, &res );
-todo_wine
     ok( !ret, "ldap_search_sA failed 0x%x\n", ret );
     ok( res != NULL, "expected res != NULL\n" );
 
diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h
index 0332deafa2..30c12a909c 100644
--- a/dlls/wldap32/winldap_private.h
+++ b/dlls/wldap32/winldap_private.h
@@ -131,6 +131,7 @@ typedef struct wldap32
     ULONG ld_cldaptimeout;
     ULONG ld_refhoplimit;
     ULONG ld_options;
+    struct berval **ld_server_ctrls;
 } WLDAP32_LDAP, *WLDAP32_PLDAP;
 
 typedef struct ldapmodA {




More information about the wine-cvs mailing list