Merge commit 'release-4-0-0alpha1' into v4-0-test
[kai/samba.git] / source / torture / ldap / cldap.c
index 2978419a2ae1260c0458e35b5f893a052f54e790..f258a1c32f67092e68a74b17d6287ffb9c210593 100644 (file)
@@ -7,7 +7,7 @@
     
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
 */
 
 #include "includes.h"
 #include "libcli/cldap/cldap.h"
 #include "libcli/ldap/ldap.h"
-#include "lib/events/events.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "torture/torture.h"
+#include "lib/ldb/include/ldb.h"
 
 #define CHECK_STATUS(status, correct) do { \
        if (!NT_STATUS_EQUAL(status, correct)) { \
                printf("(%s) Incorrect status %s - should be %s\n", \
                       __location__, nt_errstr(status), nt_errstr(correct)); \
-               ret = False; \
+               ret = false; \
                goto done; \
-       }} while (0)
-
+       } \
+} while (0)
 
 /*
   test netlogon operations
 */
-static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
+static bool test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
 {
        struct cldap_socket *cldap = cldap_socket_init(mem_ctx, NULL);
        NTSTATUS status;
@@ -46,7 +47,7 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
        union nbt_cldap_netlogon n1;
        struct GUID guid;
        int i;
-       BOOL ret = True;
+       bool ret = true;
 
        ZERO_STRUCT(search);
        search.in.dest_address = dest;
@@ -62,7 +63,8 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
 
        n1 = search.out.netlogon;
 
-       search.in.realm        = n1.logon4.dns_domain;
+       search.in.user         = "Administrator";
+       search.in.realm        = n1.logon5.dns_domain;
        search.in.host         = "__cldap_torture__";
 
        printf("Scanning for netlogon levels\n");
@@ -71,10 +73,6 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
                printf("Trying netlogon level %d\n", i);
                status = cldap_netlogon(cldap, mem_ctx, &search);
                CHECK_STATUS(status, NT_STATUS_OK);
-               if (DEBUGLVL(10)) {
-                       NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, i & 0xF, 
-                                             &search.out.netlogon);
-               }
        }
 
        printf("Scanning for netlogon level bits\n");
@@ -83,16 +81,18 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
                printf("Trying netlogon level 0x%x\n", i);
                status = cldap_netlogon(cldap, mem_ctx, &search);
                CHECK_STATUS(status, NT_STATUS_OK);
-               if (DEBUGLVL(10)) {
-                       NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, i & 0xF, 
-                                             &search.out.netlogon);
-               }
        }
 
        search.in.version = 6;
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
+       printf("Trying with User=NULL\n");
+
+       search.in.user = NULL;
+       status = cldap_netlogon(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
        printf("Trying with User=Administrator\n");
 
        search.in.user = "Administrator";
@@ -101,7 +101,7 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
 
        printf("Trying with a GUID\n");
        search.in.realm       = NULL;
-       search.in.domain_guid = GUID_string(mem_ctx, &n1.logon4.domain_uuid);
+       search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid);
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
@@ -114,13 +114,13 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
 
        printf("Trying with a AAC\n");
        search.in.acct_control = 0x180;
-       search.in.realm = n1.logon4.dns_domain;
+       search.in.realm = n1.logon5.dns_domain;
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        printf("Trying with a bad AAC\n");
        search.in.acct_control = 0xFF00FF00;
-       search.in.realm = n1.logon4.dns_domain;
+       search.in.realm = n1.logon5.dns_domain;
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
@@ -142,7 +142,7 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
        CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
 
        printf("Trying with a incorrect domain and correct guid\n");
-       search.in.domain_guid = GUID_string(mem_ctx, &n1.logon4.domain_uuid);
+       search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid);
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
@@ -153,7 +153,7 @@ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
 
        printf("Trying with a incorrect GUID and correct domain\n");
        search.in.domain_guid = GUID_string(mem_ctx, &guid);
-       search.in.realm = n1.logon4.dns_domain;
+       search.in.realm = n1.logon5.dns_domain;
        status = cldap_netlogon(cldap, mem_ctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
@@ -161,15 +161,125 @@ done:
        return ret;     
 }
 
-BOOL torture_cldap(void)
+/*
+  convert a ldap result message to a ldb message. This allows us to
+  use the convenient ldif dump routines in ldb to print out cldap
+  search results
+*/
+static struct ldb_message *ldap_msg_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldap_SearchResEntry *res)
+{
+       struct ldb_message *msg;
+
+       msg = ldb_msg_new(mem_ctx);
+       msg->dn = ldb_dn_new(msg, ldb, res->dn);
+       msg->num_elements = res->num_attributes;
+       msg->elements = talloc_steal(msg, res->attributes);
+       return msg;
+}
+
+/*
+  dump a set of cldap results
+*/
+static void cldap_dump_results(struct cldap_search *search)
+{
+       struct ldb_ldif ldif;
+       struct ldb_context *ldb;
+
+       if (!search || !(search->out.response)) {
+               return;
+       }
+
+       /* we need a ldb context to use ldb_ldif_write_file() */
+       ldb = ldb_init(NULL);
+
+       ZERO_STRUCT(ldif);
+       ldif.msg = ldap_msg_to_ldb(ldb, ldb, search->out.response);
+
+       ldb_ldif_write_file(ldb, stdout, &ldif);
+
+       talloc_free(ldb);
+}
+
+/*
+  test generic cldap operations
+*/
+static bool test_cldap_generic(TALLOC_CTX *mem_ctx, const char *dest)
+{
+       struct cldap_socket *cldap = cldap_socket_init(mem_ctx, NULL);
+       NTSTATUS status;
+       struct cldap_search search;
+       bool ret = true;
+       const char *attrs1[] = { "currentTime", "highestCommittedUSN", NULL };
+       const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
+       const char *attrs3[] = { "netlogon", NULL };
+
+       ZERO_STRUCT(search);
+       search.in.dest_address = dest;
+       search.in.timeout = 10;
+       search.in.retries = 3;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       printf("fetching whole rootDSE\n");
+       search.in.filter = "(objectclass=*)";
+       search.in.attributes = NULL;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       if (DEBUGLVL(3)) cldap_dump_results(&search);
+
+       printf("fetching currentTime and USN\n");
+       search.in.filter = "(objectclass=*)";
+       search.in.attributes = attrs1;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       
+       if (DEBUGLVL(3)) cldap_dump_results(&search);
+
+       printf("Testing currentTime, USN and netlogon\n");
+       search.in.filter = "(objectclass=*)";
+       search.in.attributes = attrs2;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       if (DEBUGLVL(3)) cldap_dump_results(&search);
+
+       printf("Testing objectClass=* and netlogon\n");
+       search.in.filter = "(objectclass2=*)";
+       search.in.attributes = attrs3;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       if (DEBUGLVL(3)) cldap_dump_results(&search);
+
+       printf("Testing a false expression\n");
+       search.in.filter = "(&(objectclass=*)(highestCommittedUSN=2))";
+       search.in.attributes = attrs1;
+
+       status = cldap_search(cldap, mem_ctx, &search);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       if (DEBUGLVL(3)) cldap_dump_results(&search);   
+
+done:
+       return ret;     
+}
+
+bool torture_cldap(struct torture_context *torture)
 {
        TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-       const char *host = lp_parm_string(-1, "torture", "host");
+       bool ret = true;
+       const char *host = torture_setting_string(torture, "host", NULL);
 
        mem_ctx = talloc_init("torture_cldap");
 
        ret &= test_cldap_netlogon(mem_ctx, host);
+       ret &= test_cldap_generic(mem_ctx, host);
 
        talloc_free(mem_ctx);