LCOV - code coverage report
Current view: top level - source4/torture/ldap - netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 375 427 87.8 %
Date: 2024-04-21 15:09:00 Functions: 10 10 100.0 %

          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           0 :         NTSTATUS status;
      61           0 :         struct cldap_netlogon search, empty_search;
      62           0 :         struct netlogon_samlogon_response n1;
      63           0 :         struct GUID guid;
      64           0 :         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           0 :         NTSTATUS status;
     300           0 :         struct cldap_netlogon search;
     301           0 :         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           2 :                 printf("NBT_SERVER_DS_8 ");
     351           2 :         if (server_type & NBT_SERVER_DS_9)
     352           2 :                 printf("NBT_SERVER_DS_9 ");
     353           2 :         if (server_type & NBT_SERVER_DS_10)
     354           2 :                 printf("NBT_SERVER_DS_10 ");
     355           2 :         if (server_type & NBT_SERVER_HAS_DNS_NAME)
     356           0 :                 printf("NBT_SERVER_HAS_DNS_NAME ");
     357           2 :         if (server_type & NBT_SERVER_IS_DEFAULT_NC)
     358           0 :                 printf("NBT_SERVER_IS_DEFAULT_NC ");
     359           2 :         if (server_type & NBT_SERVER_FOREST_ROOT)
     360           0 :                 printf("NBT_SERVER_FOREST_ROOT ");
     361             : 
     362           2 :         printf("\n");
     363             : 
     364           2 :         return true;
     365             : }
     366             : 
     367         311 : static NTSTATUS tcp_ldap_rootdse(void *data,
     368             :                                  TALLOC_CTX *mem_ctx,
     369             :                                  struct cldap_search *io)
     370             : {
     371         311 :         struct ldap_connection *conn = talloc_get_type(data,
     372             :                                                        struct ldap_connection);
     373           0 :         struct ldap_message *msg, *result;
     374           0 :         struct ldap_request *req;
     375           0 :         int i;
     376           0 :         NTSTATUS status;
     377             : 
     378         311 :         msg = new_ldap_message(mem_ctx);
     379         311 :         if (!msg) {
     380           0 :                 return NT_STATUS_NO_MEMORY;
     381             :         }
     382             : 
     383         311 :         msg->type = LDAP_TAG_SearchRequest;
     384         311 :         msg->r.SearchRequest.basedn = "";
     385         311 :         msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     386         311 :         msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
     387         311 :         msg->r.SearchRequest.timelimit = 0;
     388         311 :         msg->r.SearchRequest.sizelimit = 0;
     389         311 :         msg->r.SearchRequest.attributesonly = false;
     390         311 :         msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter);
     391         311 :         msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes);
     392         311 :         msg->r.SearchRequest.attributes = io->in.attributes;
     393             : 
     394         311 :         req = ldap_request_send(conn, msg);
     395         311 :         if (req == NULL) {
     396           0 :                 printf("Could not setup ldap search\n");
     397           0 :                 return NT_STATUS_UNSUCCESSFUL;
     398             :         }
     399             : 
     400         311 :         ZERO_STRUCT(io->out);
     401         618 :         for (i = 0; i < 2; ++i) {
     402         618 :                 status = ldap_result_n(req, i, &result);
     403         618 :                 if (!NT_STATUS_IS_OK(status)) {
     404           0 :                         return status;
     405             :                 }
     406         618 :                 switch (result->type) {
     407         307 :                 case LDAP_TAG_SearchResultEntry:
     408         307 :                         if (i != 0) {
     409           0 :                                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
     410             :                         }
     411         307 :                         io->out.response = &result->r.SearchResultEntry;
     412         307 :                         break;
     413         311 :                 case LDAP_TAG_SearchResultDone:
     414         311 :                         io->out.result = &result->r.SearchResultDone;
     415         311 :                         if (io->out.result->resultcode != LDAP_SUCCESS) {
     416           0 :                                 return NT_STATUS_LDAP(io->out.result->resultcode);
     417             :                         }
     418             : 
     419         311 :                         return NT_STATUS_OK;
     420           0 :                 default:
     421           0 :                         return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
     422             :                 }
     423             :         }
     424             : 
     425           0 :         return NT_STATUS_OK;
     426             : }
     427             : 
     428         308 : static NTSTATUS tcp_ldap_netlogon(void *conn,
     429             :                                   TALLOC_CTX *mem_ctx,
     430             :                                   struct cldap_netlogon *io)
     431             : {
     432           0 :         struct cldap_search search;
     433           0 :         struct ldap_SearchResEntry *res;
     434           0 :         NTSTATUS status;
     435           0 :         DATA_BLOB *blob;
     436             : 
     437         308 :         ZERO_STRUCT(search);
     438         308 :         search.in.attributes = (const char *[]) { "netlogon", NULL };
     439         308 :         search.in.filter =  cldap_netlogon_create_filter(mem_ctx, io);
     440         308 :         if (search.in.filter == NULL) {
     441           0 :                 return NT_STATUS_NO_MEMORY;
     442             :         }
     443             : 
     444         308 :         status = tcp_ldap_rootdse(conn, mem_ctx, &search);
     445         308 :         if (!NT_STATUS_IS_OK(status)) {
     446           0 :                 return status;
     447             :         }
     448             : 
     449         308 :         res = search.out.response;
     450         308 :         if (res == NULL) {
     451           3 :                 return NT_STATUS_NOT_FOUND;
     452             :         }
     453             : 
     454         305 :         if (res->num_attributes != 1 ||
     455         305 :             strcasecmp(res->attributes[0].name, "netlogon") != 0 ||
     456         305 :             res->attributes[0].num_values != 1 ||
     457         305 :             res->attributes[0].values->length < 2) {
     458           0 :                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     459             :         }
     460             : 
     461         305 :         blob = res->attributes[0].values;
     462         305 :         status = pull_netlogon_samlogon_response(blob, mem_ctx,
     463             :                                                  &io->out.netlogon);
     464         305 :         if (!NT_STATUS_IS_OK(status)) {
     465           0 :                 return status;
     466             :         }
     467             : 
     468         305 :         if (io->in.map_response) {
     469         305 :                 map_netlogon_samlogon_response(&io->out.netlogon);
     470             :         }
     471             : 
     472         305 :         return NT_STATUS_OK;
     473             : }
     474             : 
     475           4 : static NTSTATUS udp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx,
     476             :                                  struct cldap_search *io)
     477             : {
     478           4 :         struct cldap_socket *cldap = talloc_get_type(data,
     479             :                                                      struct cldap_socket);
     480             : 
     481           4 :         return cldap_search(cldap, mem_ctx, io);
     482             : }
     483             : 
     484           2 : static bool test_netlogon_extra_attrs(struct torture_context *tctx,
     485             :                                       request_rootdse_t request_rootdse,
     486             :                                       void *conn)
     487             : {
     488           0 :         struct cldap_search io;
     489           0 :         NTSTATUS status;
     490           2 :         const char *attrs[] = {
     491             :                 "netlogon",
     492             :                 "supportedCapabilities",
     493             :                 NULL
     494             :         };
     495           2 :         const char *attrs2[] = { "netlogon", "*", NULL };
     496           2 :         struct ldb_message ldbmsg = { NULL, 0, NULL };
     497             : 
     498           2 :         ZERO_STRUCT(io);
     499           2 :         io.in.dest_address = NULL;
     500           2 :         io.in.dest_port = 0;
     501           2 :         io.in.timeout   = 2;
     502           2 :         io.in.retries   = 2;
     503             :         /* Additional attributes may be requested next to netlogon */
     504           2 :         torture_comment(tctx, "Requesting netlogon with additional attribute\n");
     505           2 :         io.in.filter =
     506           2 :                 talloc_asprintf(tctx, "(&"
     507             :                                 "(NtVer=%s)(AAC=%s)"
     508             :                                 /* Query for LDAP_CAP_ACTIVE_DIRECTORY_OID */
     509             :                                 "(supportedCapabilities=1.2.840.113556.1.4.800)"
     510             :                                 ")",
     511             :                                 ldap_encode_ndr_uint32(tctx,
     512             :                                                        NETLOGON_NT_VERSION_5EX),
     513             :                                 ldap_encode_ndr_uint32(tctx, 0));
     514           2 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     515           2 :         io.in.attributes = attrs;
     516           2 :         status = request_rootdse(conn, tctx, &io);
     517           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     518           2 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     519           2 :         CHECK_VAL(io.out.response->num_attributes, 2);
     520             : 
     521             :         /* netlogon + '*' attr return zero results */
     522           2 :         torture_comment(tctx, "Requesting netlogon and '*' attributes\n");
     523           2 :         io.in.attributes = attrs2;
     524           2 :         status = request_rootdse(conn, tctx, &io);
     525           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     526           2 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     527           2 :         ldbmsg.num_elements = io.out.response->num_attributes;
     528           2 :         ldbmsg.elements = io.out.response->attributes;
     529           2 :         torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
     530             :                        "Attribute netlogon not found in Result Entry\n");
     531             : 
     532             :         /* Wildcards are not allowed in filters when netlogon is requested. */
     533           2 :         torture_comment(tctx, "Requesting netlogon with invalid attr filter\n");
     534           2 :         io.in.filter =
     535           2 :                 talloc_asprintf(tctx,
     536             :                                 "(&(NtVer=%s)(AAC=%s)(supportedCapabilities=*))",
     537             :                                 ldap_encode_ndr_uint32(tctx,
     538             :                                                        NETLOGON_NT_VERSION_5EX),
     539             :                                 ldap_encode_ndr_uint32(tctx, 0));
     540           2 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     541           2 :         io.in.attributes = attrs;
     542           2 :         status = request_rootdse(conn, tctx, &io);
     543           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     544           2 :         torture_assert(tctx, io.out.response == NULL,
     545             :                        "A wildcard filter should return no entries.");
     546             : 
     547           2 :         return true;
     548             : }
     549             : 
     550             : /*
     551             :   Bug #11392: Huawei Unified Storage System S5500 V3 sends no NtVer
     552             :   [MS-ADTS] Section 7.3.3.2 "Domain Controller Response to an LDAP Ping"
     553             : */
     554           1 : static bool test_netlogon_huawei(struct torture_context *tctx,
     555             :                                       request_rootdse_t request_rootdse,
     556             :                                       void *conn)
     557             : {
     558           0 :         struct cldap_search io;
     559           0 :         struct netlogon_samlogon_response n1;
     560           0 :         NTSTATUS status;
     561           1 :         const char *attrs[] = {
     562             :                 "netlogon",
     563             :                 NULL
     564             :         };
     565           1 :         struct ldb_message ldbmsg = { NULL, 0, NULL };
     566             : 
     567           1 :         ZERO_STRUCT(io);
     568           1 :         io.in.dest_address = NULL;
     569           1 :         io.in.dest_port = 0;
     570           1 :         io.in.timeout   = 2;
     571           1 :         io.in.retries   = 2;
     572             : 
     573           1 :         torture_comment(tctx, "Requesting netlogon without NtVer filter\n");
     574           1 :         io.in.filter = talloc_asprintf(tctx, "(&(DnsDomain=%s))",
     575             :                                 lpcfg_dnsdomain(tctx->lp_ctx));
     576           1 :         torture_assert(tctx, io.in.filter != NULL, "OOM");
     577           1 :         io.in.attributes = attrs;
     578           1 :         status = request_rootdse(conn, tctx, &io);
     579           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     580           1 :         torture_assert(tctx, io.out.response != NULL, "No Entries found.");
     581           1 :         CHECK_VAL(io.out.response->num_attributes, 1);
     582             : 
     583           1 :         ldbmsg.num_elements = io.out.response->num_attributes;
     584           1 :         ldbmsg.elements = io.out.response->attributes;
     585           1 :         torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
     586             :                        "Attribute netlogon not found in Result Entry\n");
     587             : 
     588           1 :         status = pull_netlogon_samlogon_response(
     589           1 :                         io.out.response->attributes[0].values,
     590             :                         tctx,
     591             :                         &n1);
     592           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     593           1 :         CHECK_VAL(n1.ntver, NETLOGON_NT_VERSION_5);
     594             : 
     595           1 :         return true;
     596             : }
     597             : 
     598           1 : bool torture_netlogon_tcp(struct torture_context *tctx)
     599             : {
     600           1 :         const char *host = torture_setting_string(tctx, "host", NULL);
     601           1 :         bool ret = true;
     602           0 :         NTSTATUS status;
     603           0 :         struct ldap_connection *conn;
     604           0 :         TALLOC_CTX *mem_ctx;
     605           0 :         const char *url;
     606             : 
     607           1 :         mem_ctx = talloc_init("torture_ldap_netlogon");
     608             : 
     609           1 :         url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
     610             : 
     611           1 :         status = torture_ldap_connection(tctx, &conn, url);
     612           1 :         if (!NT_STATUS_IS_OK(status)) {
     613           0 :                 return false;
     614             :         }
     615             : 
     616           1 :         ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host);
     617           1 :         ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host);
     618           1 :         ret &= test_netlogon_extra_attrs(tctx, tcp_ldap_rootdse, conn);
     619             : 
     620           1 :         return ret;
     621             : }
     622             : 
     623         308 : static NTSTATUS udp_ldap_netlogon(void *data,
     624             :                                   TALLOC_CTX *mem_ctx,
     625             :                                   struct cldap_netlogon *io)
     626             : {
     627         308 :         struct cldap_socket *cldap = talloc_get_type(data,
     628             :                                                      struct cldap_socket);
     629             : 
     630         308 :         return cldap_netlogon(cldap, mem_ctx, io);
     631             : }
     632             : 
     633           1 : bool torture_netlogon_udp(struct torture_context *tctx)
     634             : {
     635           1 :         const char *host = torture_setting_string(tctx, "host", NULL);
     636           0 :         const char *ip;
     637           0 :         struct nbt_name nbt_name;
     638           1 :         bool ret = true;
     639           0 :         int r;
     640           0 :         struct cldap_socket *cldap;
     641           0 :         NTSTATUS status;
     642           0 :         struct tsocket_address *dest_addr;
     643             : 
     644           1 :         make_nbt_name_server(&nbt_name, host);
     645             : 
     646           1 :         status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
     647             :                                  0, 0, &nbt_name, tctx, &ip, tctx->ev);
     648           1 :         torture_assert_ntstatus_ok(tctx, status,
     649             :                         talloc_asprintf(tctx,"Failed to resolve %s: %s",
     650             :                                         nbt_name.name, nt_errstr(status)));
     651             : 
     652           1 :         r = tsocket_address_inet_from_strings(tctx, "ip",
     653             :                                               ip,
     654             :                                               lpcfg_cldap_port(tctx->lp_ctx),
     655             :                                               &dest_addr);
     656           1 :         CHECK_VAL(r, 0);
     657             : 
     658             :         /* cldap_socket_init should now know about the dest. address */
     659           1 :         status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
     660           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     661             : 
     662           1 :         ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host);
     663           1 :         ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host);
     664           1 :         ret &= test_netlogon_extra_attrs(tctx, udp_ldap_rootdse, cldap);
     665           1 :         ret &= test_netlogon_huawei(tctx, udp_ldap_rootdse, cldap);
     666             : 
     667           1 :         return ret;
     668             : }

Generated by: LCOV version 1.14