LCOV - code coverage report
Current view: top level - source4/torture/ldap - netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 370 392 94.4 %
Date: 2021-09-23 10:06:22 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS Implementation.
       3             : 
       4             :    test CLDAP/LDAP netlogon operations
       5             :    
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    Copyright (C) Matthias Dieter Wallnöfer 2009
       8             :     
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             :    
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "libcli/cldap/cldap.h"
      26             : #include "libcli/ldap/ldap_client.h"
      27             : #include "libcli/ldap/ldap_ndr.h"
      28             : #include "libcli/resolve/resolve.h"
      29             : #include "librpc/gen_ndr/netlogon.h"
      30             : #include "param/param.h"
      31             : #include "../lib/tsocket/tsocket.h"
      32             : 
      33             : #include "torture/torture.h"
      34             : #include "torture/ldap/proto.h"
      35             : 
      36             : #undef strcasecmp
      37             : 
      38             : #define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
      39             : 
      40             : #define CHECK_VAL(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
      41             : 
      42             : #define CHECK_STRING(v, correct) torture_assert_str_equal(tctx, v, correct, "incorrect value");
      43             : 
      44             : typedef NTSTATUS (*request_netlogon_t)(void *con,
      45             :                                        TALLOC_CTX *mem_ctx,
      46             :                                        struct cldap_netlogon *io);
      47             : 
      48             : typedef NTSTATUS (*request_rootdse_t)(void *con,
      49             :                                      TALLOC_CTX *mem_ctx,
      50             :                                      struct cldap_search *io);
      51             : 
      52             : /*
      53             :   test netlogon operations
      54             : */
      55           2 : static bool test_ldap_netlogon(struct torture_context *tctx,
      56             :                                request_netlogon_t request_netlogon,
      57             :                                void *cldap,
      58             :                                const char *dest)
      59             : {
      60             :         NTSTATUS status;
      61             :         struct cldap_netlogon search, empty_search;
      62             :         struct netlogon_samlogon_response n1;
      63             :         struct GUID guid;
      64             :         int i;
      65             : 
      66           2 :         ZERO_STRUCT(search);
      67           2 :         search.in.dest_address = NULL;
      68           2 :         search.in.dest_port = 0;
      69           2 :         search.in.acct_control = -1;
      70           2 :         search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
      71           2 :         search.in.map_response = true;
      72             : 
      73           2 :         empty_search = search;
      74             : 
      75           2 :         printf("Trying without any attributes\n");
      76           2 :         search = empty_search;
      77           2 :         status = request_netlogon(cldap, tctx, &search);
      78           2 :         CHECK_STATUS(status, NT_STATUS_OK);
      79             : 
      80           2 :         n1 = search.out.netlogon;
      81             : 
      82           2 :         search.in.user         = "Administrator";
      83           2 :         search.in.realm        = n1.data.nt5_ex.dns_domain;
      84           2 :         search.in.host         = "__cldap_torture__";
      85             : 
      86           2 :         printf("Scanning for netlogon levels\n");
      87         514 :         for (i=0;i<256;i++) {
      88         512 :                 search.in.version = i;
      89         512 :                 printf("Trying netlogon level %d\n", i);
      90         512 :                 status = request_netlogon(cldap, tctx, &search);
      91         512 :                 CHECK_STATUS(status, NT_STATUS_OK);
      92             :         }
      93             : 
      94           2 :         printf("Scanning for netlogon level bits\n");
      95          64 :         for (i=0;i<31;i++) {
      96          62 :                 search.in.version = (1<<i);
      97          62 :                 printf("Trying netlogon level 0x%x\n", i);
      98          62 :                 status = request_netlogon(cldap, tctx, &search);
      99          62 :                 CHECK_STATUS(status, NT_STATUS_OK);
     100             :         }
     101             : 
     102           2 :         search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
     103           2 :         status = request_netlogon(cldap, tctx, &search);
     104           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     105             : 
     106           2 :         printf("Trying with User=NULL\n");
     107           2 :         search.in.user = NULL;
     108           2 :         status = request_netlogon(cldap, tctx, &search);
     109           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     110           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     111           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     112           2 :         torture_assert(tctx,
     113             :                        strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
     114             :                        "PDC name should not be in UNC form");
     115             : 
     116           2 :         printf("Trying with User=Administrator\n");
     117           2 :         search.in.user = "Administrator";
     118           2 :         status = request_netlogon(cldap, tctx, &search);
     119           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     120           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
     121           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
     122           2 :         torture_assert(tctx,
     123             :                        strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
     124             :                        "PDC name should not be in UNC form");
     125             : 
     126           2 :         search.in.version = NETLOGON_NT_VERSION_5;
     127           2 :         status = request_netlogon(cldap, tctx, &search);
     128           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     129             : 
     130           2 :         printf("Trying with User=NULL\n");
     131           2 :         search.in.user = NULL;
     132           2 :         status = request_netlogon(cldap, tctx, &search);
     133           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     134           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
     135           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     136           2 :         torture_assert(tctx,
     137             :                        strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     138             :                        "PDC name should be in UNC form");
     139             : 
     140           2 :         printf("Trying with User=Administrator\n");
     141           2 :         search.in.user = "Administrator";
     142           2 :         status = request_netlogon(cldap, tctx, &search);
     143           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     144           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN);
     145           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
     146           2 :         torture_assert(tctx,
     147             :                        strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     148             :                        "PDC name should be in UNC form");
     149             : 
     150           2 :         search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
     151             : 
     152           2 :         printf("Trying with a GUID\n");
     153           2 :         search.in.realm       = NULL;
     154           2 :         search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
     155           2 :         status = request_netlogon(cldap, tctx, &search);
     156           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     157           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
     158           2 :         CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid);
     159           2 :         torture_assert(tctx,
     160             :                        strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
     161             :                        "PDC name should not be in UNC form");
     162             : 
     163           2 :         printf("Trying with a incorrect GUID\n");
     164           2 :         guid = GUID_random();
     165           2 :         search.in.user        = NULL;
     166           2 :         search.in.domain_guid = GUID_string(tctx, &guid);
     167           2 :         status = request_netlogon(cldap, tctx, &search);
     168           2 :         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
     169             : 
     170           2 :         printf("Trying with a AAC\n");
     171           2 :         search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
     172           2 :         search.in.realm = n1.data.nt5_ex.dns_domain;
     173           2 :         status = request_netlogon(cldap, tctx, &search);
     174           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     175           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     176           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     177             : 
     178           2 :         printf("Trying with a zero AAC\n");
     179           2 :         search.in.acct_control = 0x0;
     180           2 :         search.in.realm = n1.data.nt5_ex.dns_domain;
     181           2 :         status = request_netlogon(cldap, tctx, &search);
     182           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     183           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     184           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     185             : 
     186           2 :         printf("Trying with a zero AAC and user=Administrator\n");
     187           2 :         search.in.acct_control = 0x0;
     188           2 :         search.in.user = "Administrator";
     189           2 :         search.in.realm = n1.data.nt5_ex.dns_domain;
     190           2 :         status = request_netlogon(cldap, tctx, &search);
     191           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     192           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
     193           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator");
     194             : 
     195           2 :         printf("Trying with a bad AAC\n");
     196           2 :         search.in.user = NULL;
     197           2 :         search.in.acct_control = 0xFF00FF00;
     198           2 :         search.in.realm = n1.data.nt5_ex.dns_domain;
     199           2 :         status = request_netlogon(cldap, tctx, &search);
     200           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     201           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     202           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     203             : 
     204           2 :         printf("Trying with a user only\n");
     205           2 :         search = empty_search;
     206           2 :         search.in.user = "Administrator";
     207           2 :         status = request_netlogon(cldap, tctx, &search);
     208           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     209           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     210           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     211           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     212           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     213           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
     214           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     215           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     216             : 
     217           2 :         printf("Trying with just a bad username\n");
     218           2 :         search.in.user = "___no_such_user___";
     219           2 :         status = request_netlogon(cldap, tctx, &search);
     220           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     221           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
     222           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     223           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     224           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     225           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     226           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
     227           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     228           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     229             : 
     230           2 :         printf("Trying with just a bad domain\n");
     231           2 :         search = empty_search;
     232           2 :         search.in.realm = "___no_such_domain___";
     233           2 :         status = request_netlogon(cldap, tctx, &search);
     234           2 :         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
     235             : 
     236           2 :         printf("Trying with a incorrect domain and correct guid\n");
     237           2 :         search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
     238           2 :         status = request_netlogon(cldap, tctx, &search);
     239           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     240           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     241           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     242           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     243           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     244           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     245           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     246           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     247           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     248             : 
     249           2 :         printf("Trying with a incorrect domain and incorrect guid\n");
     250           2 :         search.in.domain_guid = GUID_string(tctx, &guid);
     251           2 :         status = request_netlogon(cldap, tctx, &search);
     252           2 :         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
     253           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     254           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     255           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     256           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     257           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     258           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     259           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     260           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     261             : 
     262           2 :         printf("Trying with a incorrect GUID and correct domain\n");
     263           2 :         search.in.domain_guid = GUID_string(tctx, &guid);
     264           2 :         search.in.realm = n1.data.nt5_ex.dns_domain;
     265           2 :         status = request_netlogon(cldap, tctx, &search);
     266           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     267           2 :         CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
     268           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     269           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     270           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     271           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     272           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
     273           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     274           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     275             : 
     276           2 :         printf("Proof other results\n");
     277           2 :         search.in.user = "Administrator";
     278           2 :         status = request_netlogon(cldap, tctx, &search);
     279           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     280           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
     281           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
     282           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
     283           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
     284           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
     285           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
     286           2 :         CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
     287             : 
     288           2 :         return true;
     289             : }
     290             : 
     291             : /*
     292             :   test cldap netlogon server type flags
     293             : */
     294           2 : static bool test_ldap_netlogon_flags(struct torture_context *tctx,
     295             :                                      request_netlogon_t request_netlogon,
     296             :                                      void *cldap,
     297             :                                      const char *dest)
     298             : {
     299             :         NTSTATUS status;
     300             :         struct cldap_netlogon search;
     301             :         struct netlogon_samlogon_response n1;
     302           2 :         uint32_t server_type = 0;
     303             : 
     304           2 :         printf("Printing out netlogon server type flags: %s\n", dest);
     305             : 
     306           2 :         ZERO_STRUCT(search);
     307           2 :         search.in.dest_address = NULL;
     308           2 :         search.in.dest_port = 0;
     309           2 :         search.in.acct_control = -1;
     310           2 :         search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
     311           2 :         search.in.map_response = true;
     312             : 
     313           2 :         status = request_netlogon(cldap, tctx, &search);
     314           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     315             : 
     316           2 :         n1 = search.out.netlogon;
     317           2 :         if (n1.ntver == NETLOGON_NT_VERSION_5)
     318           0 :                 server_type = n1.data.nt5.server_type;
     319           2 :         else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
     320           2 :                 server_type = n1.data.nt5_ex.server_type;       
     321             : 
     322           2 :         printf("The word is: %i\n", server_type);
     323           2 :         if (server_type & NBT_SERVER_PDC)
     324           2 :                 printf("NBT_SERVER_PDC ");
     325           2 :         if (server_type & NBT_SERVER_GC)
     326           2 :                 printf("NBT_SERVER_GC ");
     327           2 :         if (server_type & NBT_SERVER_LDAP)
     328           2 :                 printf("NBT_SERVER_LDAP ");
     329           2 :         if (server_type & NBT_SERVER_DS)
     330           2 :                 printf("NBT_SERVER_DS ");
     331           2 :         if (server_type & NBT_SERVER_KDC)
     332           2 :                 printf("NBT_SERVER_KDC ");
     333           2 :         if (server_type & NBT_SERVER_TIMESERV)
     334           2 :                 printf("NBT_SERVER_TIMESERV ");
     335           2 :         if (server_type & NBT_SERVER_CLOSEST)
     336           2 :                 printf("NBT_SERVER_CLOSEST ");
     337           2 :         if (server_type & NBT_SERVER_WRITABLE)
     338           2 :                 printf("NBT_SERVER_WRITABLE ");
     339           2 :         if (server_type & NBT_SERVER_GOOD_TIMESERV)
     340           2 :                 printf("NBT_SERVER_GOOD_TIMESERV ");
     341           2 :         if (server_type & NBT_SERVER_NDNC)
     342           0 :                 printf("NBT_SERVER_NDNC ");
     343           2 :         if (server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6)
     344           0 :                 printf("NBT_SERVER_SELECT_SECRET_DOMAIN_6");
     345           2 :         if (server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6)
     346           2 :                 printf("NBT_SERVER_FULL_SECRET_DOMAIN_6");
     347           2 :         if (server_type & NBT_SERVER_ADS_WEB_SERVICE)
     348           0 :                 printf("NBT_SERVER_ADS_WEB_SERVICE ");
     349           2 :         if (server_type & NBT_SERVER_DS_8)
     350           0 :                 printf("NBT_SERVER_DS_8 ");
     351           2 :         if (server_type & DS_DNS_CONTROLLER)
     352           0 :                 printf("DS_DNS_CONTROLLER ");
     353           2 :         if (server_type & DS_DNS_DOMAIN)
     354           0 :                 printf("DS_DNS_DOMAIN ");
     355           2 :         if (server_type & DS_DNS_FOREST_ROOT)
     356           0 :                 printf("DS_DNS_FOREST_ROOT ");
     357             : 
     358           2 :         printf("\n");
     359             : 
     360           2 :         return true;
     361             : }
     362             : 
     363         311 : static NTSTATUS tcp_ldap_rootdse(void *data,
     364             :                                  TALLOC_CTX *mem_ctx,
     365             :                                  struct cldap_search *io)
     366             : {
     367         311 :         struct ldap_connection *conn = talloc_get_type(data,
     368             :                                                        struct ldap_connection);
     369             :         struct ldap_message *msg, *result;
     370             :         struct ldap_request *req;
     371             :         int i;
     372             :         NTSTATUS status;
     373             : 
     374         311 :         msg = new_ldap_message(mem_ctx);
     375         311 :         if (!msg) {
     376           0 :                 return NT_STATUS_NO_MEMORY;
     377             :         }
     378             : 
     379         311 :         msg->type = LDAP_TAG_SearchRequest;
     380         311 :         msg->r.SearchRequest.basedn = "";
     381         311 :         msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     382         311 :         msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
     383         311 :         msg->r.SearchRequest.timelimit = 0;
     384         311 :         msg->r.SearchRequest.sizelimit = 0;
     385         311 :         msg->r.SearchRequest.attributesonly = false;
     386         311 :         msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter);
     387         311 :         msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes);
     388         311 :         msg->r.SearchRequest.attributes = io->in.attributes;
     389             : 
     390         311 :         req = ldap_request_send(conn, msg);
     391         311 :         if (req == NULL) {
     392           0 :                 printf("Could not setup ldap search\n");
     393           0 :                 return NT_STATUS_UNSUCCESSFUL;
     394             :         }
     395             : 
     396         311 :         ZERO_STRUCT(io->out);
     397         618 :         for (i = 0; i < 2; ++i) {
     398         618 :                 status = ldap_result_n(req, i, &result);
     399         618 :                 if (!NT_STATUS_IS_OK(status)) {
     400           0 :                         return status;
     401             :                 }
     402         618 :                 switch (result->type) {
     403         307 :                 case LDAP_TAG_SearchResultEntry:
     404         307 :                         if (i != 0) {
     405           0 :                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
     406             :                         }
     407         307 :                         io->out.response = &result->r.SearchResultEntry;
     408         307 :                         break;
     409         311 :                 case LDAP_TAG_SearchResultDone:
     410         311 :                         io->out.result = &result->r.SearchResultDone;
     411         311 :                         if (io->out.result->resultcode != LDAP_SUCCESS) {
     412           0 :                                 return NT_STATUS_LDAP(io->out.result->resultcode);
     413             :                         }
     414             : 
     415         311 :                         return NT_STATUS_OK;
     416           0 :                 default:
     417           0 :                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
     418             :                 }
     419             :         }
     420             : 
     421           0 :         return NT_STATUS_OK;
     422             : }
     423             : 
     424         308 : static NTSTATUS tcp_ldap_netlogon(void *conn,
     425             :                                   TALLOC_CTX *mem_ctx,
     426             :                                   struct cldap_netlogon *io)
     427             : {
     428             :         struct cldap_search search;
     429             :         struct ldap_SearchResEntry *res;
     430             :         NTSTATUS status;
     431             :         DATA_BLOB *blob;
     432             : 
     433         308 :         ZERO_STRUCT(search);
     434         308 :         search.in.attributes = (const char *[]) { "netlogon", NULL };
     435         308 :         search.in.filter =  cldap_netlogon_create_filter(mem_ctx, io);
     436         308 :         if (search.in.filter == NULL) {
     437           0 :                 return NT_STATUS_NO_MEMORY;
     438             :         }
     439             : 
     440         308 :         status = tcp_ldap_rootdse(conn, mem_ctx, &search);
     441         308 :         if (!NT_STATUS_IS_OK(status)) {
     442           0 :                 return status;
     443             :         }
     444             : 
     445         308 :         res = search.out.response;
     446         308 :         if (res == NULL) {
     447           3 :                 return NT_STATUS_NOT_FOUND;
     448             :         }
     449             : 
     450         610 :         if (res->num_attributes != 1 ||
     451         610 :             strcasecmp(res->attributes[0].name, "netlogon") != 0 ||
     452         610 :             res->attributes[0].num_values != 1 ||
     453         305 :             res->attributes[0].values->length < 2) {
     454           0 :                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     455             :         }
     456             : 
     457         305 :         blob = res->attributes[0].values;
     458         305 :         status = pull_netlogon_samlogon_response(blob, mem_ctx,
     459             :                                                  &io->out.netlogon);
     460         305 :         if (!NT_STATUS_IS_OK(status)) {
     461           0 :                 return status;
     462             :         }
     463             : 
     464         305 :         if (io->in.map_response) {
     465         305 :                 map_netlogon_samlogon_response(&io->out.netlogon);
     466             :         }
     467             : 
     468         305 :         return NT_STATUS_OK;
     469             : }
     470             : 
     471           4 : static NTSTATUS udp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx,
     472             :                                  struct cldap_search *io)
     473             : {
     474           4 :         struct cldap_socket *cldap = talloc_get_type(data,
     475             :                                                      struct cldap_socket);
     476             : 
     477           4 :         return cldap_search(cldap, mem_ctx, io);
     478             : }
     479             : 
     480           2 : static bool test_netlogon_extra_attrs(struct torture_context *tctx,
     481             :                                       request_rootdse_t request_rootdse,
     482             :                                       void *conn)
     483             : {
     484             :         struct cldap_search io;
     485             :         NTSTATUS status;
     486           2 :         const char *attrs[] = {
     487             :                 "netlogon",
     488             :                 "supportedCapabilities",
     489             :                 NULL
     490             :         };
     491           2 :         const char *attrs2[] = { "netlogon", "*", NULL };
     492           2 :         struct ldb_message ldbmsg = { NULL, 0, NULL };
     493             : 
     494           2 :         ZERO_STRUCT(io);
     495           2 :         io.in.dest_address = NULL;
     496           2 :         io.in.dest_port = 0;
     497           2 :         io.in.timeout   = 2;
     498           2 :         io.in.retries   = 2;
     499             :         /* Additional attributes may be requested next to netlogon */
     500           2 :         torture_comment(tctx, "Requesting netlogon with additional attribute\n");
     501           2 :         io.in.filter =
     502           2 :                 talloc_asprintf(tctx, "(&"
     503             :                                 "(NtVer=%s)(AAC=%s)"
     504             :                                 /* Query for LDAP_CAP_ACTIVE_DIRECTORY_OID */
     505             :                                 "(supportedCapabilities=1.2.840.113556.1.4.800)"
     506             :                                 ")",
     507             :                                 ldap_encode_ndr_uint32(tctx,
     508             :                                                        NETLOGON_NT_VERSION_5EX),
     509             :                                 ldap_encode_ndr_uint32(tctx, 0));
     510           2 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     511           2 :         io.in.attributes = attrs;
     512           2 :         status = request_rootdse(conn, tctx, &io);
     513           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     514           2 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     515           2 :         CHECK_VAL(io.out.response->num_attributes, 2);
     516             : 
     517             :         /* netlogon + '*' attr return zero results */
     518           2 :         torture_comment(tctx, "Requesting netlogon and '*' attributes\n");
     519           2 :         io.in.attributes = attrs2;
     520           2 :         status = request_rootdse(conn, tctx, &io);
     521           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     522           2 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     523           2 :         ldbmsg.num_elements = io.out.response->num_attributes;
     524           2 :         ldbmsg.elements = io.out.response->attributes;
     525           2 :         torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
     526             :                        "Attribute netlogon not found in Result Entry\n");
     527             : 
     528             :         /* Wildcards are not allowed in filters when netlogon is requested. */
     529           2 :         torture_comment(tctx, "Requesting netlogon with invalid attr filter\n");
     530           2 :         io.in.filter =
     531           2 :                 talloc_asprintf(tctx,
     532             :                                 "(&(NtVer=%s)(AAC=%s)(supportedCapabilities=*))",
     533             :                                 ldap_encode_ndr_uint32(tctx,
     534             :                                                        NETLOGON_NT_VERSION_5EX),
     535             :                                 ldap_encode_ndr_uint32(tctx, 0));
     536           2 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     537           2 :         io.in.attributes = attrs;
     538           2 :         status = request_rootdse(conn, tctx, &io);
     539           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     540           2 :         torture_assert(tctx, io.out.response == NULL,
     541             :                        "A wildcard filter should return no entries.");
     542             : 
     543           2 :         return true;
     544             : }
     545             : 
     546             : /*
     547             :   Bug #11392: Huawei Unified Storage System S5500 V3 sends no NtVer
     548             :   [MS-ADTS] Section 7.3.3.2 "Domain Controller Response to an LDAP Ping"
     549             : */
     550           1 : static bool test_netlogon_huawei(struct torture_context *tctx,
     551             :                                       request_rootdse_t request_rootdse,
     552             :                                       void *conn)
     553             : {
     554             :         struct cldap_search io;
     555             :         struct netlogon_samlogon_response n1;
     556             :         NTSTATUS status;
     557           1 :         const char *attrs[] = {
     558             :                 "netlogon",
     559             :                 NULL
     560             :         };
     561           1 :         struct ldb_message ldbmsg = { NULL, 0, NULL };
     562             : 
     563           1 :         ZERO_STRUCT(io);
     564           1 :         io.in.dest_address = NULL;
     565           1 :         io.in.dest_port = 0;
     566           1 :         io.in.timeout   = 2;
     567           1 :         io.in.retries   = 2;
     568             : 
     569           1 :         torture_comment(tctx, "Requesting netlogon without NtVer filter\n");
     570           1 :         io.in.filter = talloc_asprintf(tctx, "(&(DnsDomain=%s))",
     571             :                                 lpcfg_dnsdomain(tctx->lp_ctx));
     572           1 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     573           1 :         io.in.attributes = attrs;
     574           1 :         status = request_rootdse(conn, tctx, &io);
     575           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     576           1 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     577           1 :         CHECK_VAL(io.out.response->num_attributes, 1);
     578             : 
     579           1 :         ldbmsg.num_elements = io.out.response->num_attributes;
     580           1 :         ldbmsg.elements = io.out.response->attributes;
     581           1 :         torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
     582             :                        "Attribute netlogon not found in Result Entry\n");
     583             : 
     584           1 :         status = pull_netlogon_samlogon_response(
     585           1 :                         io.out.response->attributes[0].values,
     586             :                         tctx,
     587             :                         &n1);
     588           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     589           1 :         CHECK_VAL(n1.ntver, NETLOGON_NT_VERSION_5);
     590             : 
     591           1 :         return true;
     592             : }
     593             : 
     594           1 : bool torture_netlogon_tcp(struct torture_context *tctx)
     595             : {
     596           1 :         const char *host = torture_setting_string(tctx, "host", NULL);
     597           1 :         bool ret = true;
     598             :         NTSTATUS status;
     599             :         struct ldap_connection *conn;
     600             :         TALLOC_CTX *mem_ctx;
     601             :         const char *url;
     602             : 
     603           1 :         mem_ctx = talloc_init("torture_ldap_netlogon");
     604             : 
     605           1 :         url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
     606             : 
     607           1 :         status = torture_ldap_connection(tctx, &conn, url);
     608           1 :         if (!NT_STATUS_IS_OK(status)) {
     609           0 :                 return false;
     610             :         }
     611             : 
     612           1 :         ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host);
     613           1 :         ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host);
     614           1 :         ret &= test_netlogon_extra_attrs(tctx, tcp_ldap_rootdse, conn);
     615             : 
     616           1 :         return ret;
     617             : }
     618             : 
     619         308 : static NTSTATUS udp_ldap_netlogon(void *data,
     620             :                                   TALLOC_CTX *mem_ctx,
     621             :                                   struct cldap_netlogon *io)
     622             : {
     623         308 :         struct cldap_socket *cldap = talloc_get_type(data,
     624             :                                                      struct cldap_socket);
     625             : 
     626         308 :         return cldap_netlogon(cldap, mem_ctx, io);
     627             : }
     628             : 
     629           1 : bool torture_netlogon_udp(struct torture_context *tctx)
     630             : {
     631           1 :         const char *host = torture_setting_string(tctx, "host", NULL);
     632             :         const char *ip;
     633             :         struct nbt_name nbt_name;
     634           1 :         bool ret = true;
     635             :         int r;
     636             :         struct cldap_socket *cldap;
     637             :         NTSTATUS status;
     638             :         struct tsocket_address *dest_addr;
     639             : 
     640           1 :         make_nbt_name_server(&nbt_name, host);
     641             : 
     642           1 :         status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
     643             :                                  0, 0, &nbt_name, tctx, &ip, tctx->ev);
     644           1 :         torture_assert_ntstatus_ok(tctx, status,
     645             :                         talloc_asprintf(tctx,"Failed to resolve %s: %s",
     646             :                                         nbt_name.name, nt_errstr(status)));
     647             : 
     648           1 :         r = tsocket_address_inet_from_strings(tctx, "ip",
     649             :                                               ip,
     650             :                                               lpcfg_cldap_port(tctx->lp_ctx),
     651             :                                               &dest_addr);
     652           1 :         CHECK_VAL(r, 0);
     653             : 
     654             :         /* cldap_socket_init should now know about the dest. address */
     655           1 :         status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
     656           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     657             : 
     658           1 :         ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host);
     659           1 :         ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host);
     660           1 :         ret &= test_netlogon_extra_attrs(tctx, udp_ldap_rootdse, cldap);
     661           1 :         ret &= test_netlogon_huawei(tctx, udp_ldap_rootdse, cldap);
     662             : 
     663           1 :         return ret;
     664             : }

Generated by: LCOV version 1.13