LCOV - code coverage report
Current view: top level - source4/torture/nbt - dgram.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 305 360 84.7 %
Date: 2024-02-28 12:06:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    NBT dgram testing
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/dgram/libdgram.h"
      24             : #include "lib/socket/socket.h"
      25             : #include "lib/events/events.h"
      26             : #include "torture/rpc/torture_rpc.h"
      27             : #include "torture/nbt/proto.h"
      28             : #include "libcli/resolve/resolve.h"
      29             : #include "system/network.h"
      30             : #include "lib/socket/netif.h"
      31             : #include "param/param.h"
      32             : 
      33             : #define TEST_NAME "TORTURE_TEST"
      34             : 
      35             : /*
      36             :   reply handler for netlogon request
      37             : */
      38          36 : static void netlogon_handler(struct dgram_mailslot_handler *dgmslot, 
      39             :                              struct nbt_dgram_packet *packet, 
      40             :                              struct socket_address *src)
      41             : {
      42           0 :         NTSTATUS status;
      43          36 :         struct nbt_netlogon_response *netlogon = dgmslot->private_data;
      44             : 
      45          36 :         dgmslot->private_data = netlogon = talloc(dgmslot, struct nbt_netlogon_response);
      46             : 
      47          36 :         if (!dgmslot->private_data) {
      48           0 :                 return;
      49             :         }
      50             :        
      51          36 :         printf("netlogon reply from %s:%d\n", src->addr, src->port);
      52             : 
      53             :         /* Fills in the netlogon pointer */
      54          36 :         status = dgram_mailslot_netlogon_parse_response(netlogon, packet,
      55             :                                                         netlogon);
      56          36 :         if (!NT_STATUS_IS_OK(status)) {
      57           0 :                 printf("Failed to parse netlogon packet from %s:%d\n",
      58             :                        src->addr, src->port);
      59           0 :                 return;
      60             :         }
      61             : 
      62             : }
      63             : 
      64             : 
      65             : /* test UDP/138 netlogon requests */
      66           5 : static bool nbt_test_netlogon(struct torture_context *tctx)
      67             : {
      68           0 :         struct dgram_mailslot_handler *dgmslot;
      69           5 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
      70           0 :         struct socket_address *dest;
      71           0 :         const char *myaddress;
      72           0 :         struct nbt_netlogon_packet logon;
      73           0 :         struct nbt_netlogon_response *response;
      74           0 :         struct nbt_name myname;
      75           0 :         NTSTATUS status;
      76           5 :         struct timeval tv = timeval_current();
      77             : 
      78           0 :         struct socket_address *socket_address;
      79             : 
      80           0 :         const char *address;
      81           0 :         struct nbt_name name;
      82             : 
      83           0 :         struct interface *ifaces;
      84             : 
      85           5 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
      86           5 :         name.type = NBT_NAME_LOGON;
      87           5 :         name.scope = NULL;
      88             : 
      89             :         /* do an initial name resolution to find its IP */
      90           5 :         torture_assert_ntstatus_ok(tctx, 
      91             :                                    resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
      92             :                                                    0, 0,
      93             :                                                    &name, tctx, &address, tctx->ev),
      94             :                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
      95             : 
      96           5 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
      97           5 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
      98             : 
      99             : 
     100           5 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     101             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     102           5 :         torture_assert(tctx, socket_address != NULL, "Error getting address");
     103             : 
     104             :         /* try receiving replies on port 138 first, which will only
     105             :            work if we are root and smbd/nmbd are not running - fall
     106             :            back to listening on any port, which means replies from
     107             :            most windows versions won't be seen */
     108           5 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     109           5 :         if (!NT_STATUS_IS_OK(status)) {
     110           0 :                 talloc_free(socket_address);
     111           0 :                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     112             :                                                              myaddress, 0);
     113           0 :                 torture_assert(tctx, socket_address != NULL, "Error getting address");
     114             : 
     115           0 :                 socket_listen(dgmsock->sock, socket_address, 0, 0);
     116             :         }
     117             : 
     118             :         /* setup a temporary mailslot listener for replies */
     119           5 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     120             :                                       netlogon_handler, NULL);
     121           5 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     122             : 
     123           5 :         ZERO_STRUCT(logon);
     124           5 :         logon.command = LOGON_PRIMARY_QUERY;
     125           5 :         logon.req.pdc.computer_name = TEST_NAME;
     126           5 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     127           5 :         logon.req.pdc.unicode_name  = TEST_NAME;
     128           5 :         logon.req.pdc.nt_version    = 1;
     129           5 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     130           5 :         logon.req.pdc.lm20_token    = 0xFFFF;
     131             : 
     132           5 :         make_nbt_name_client(&myname, TEST_NAME);
     133             : 
     134           5 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     135             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     136           5 :         torture_assert(tctx, dest != NULL, "Error getting address");
     137             : 
     138           5 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     139             :                                               NBT_MAILSLOT_NETLOGON, 
     140             :                                               &myname, &logon);
     141           5 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     142             : 
     143          15 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     144          10 :                 tevent_loop_once(dgmsock->event_ctx);
     145             :         }
     146             : 
     147           5 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     148             : 
     149           5 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     150             : 
     151           5 :         torture_assert(tctx, response->response_type == NETLOGON_GET_PDC, "Got incorrect type of netlogon response");
     152           5 :         torture_assert(tctx, response->data.get_pdc.command == NETLOGON_RESPONSE_FROM_PDC, "Got incorrect netlogon response command");
     153             : 
     154           5 :         return true;
     155             : }
     156             : 
     157             : 
     158             : /* test UDP/138 netlogon requests */
     159           5 : static bool nbt_test_netlogon2(struct torture_context *tctx)
     160             : {
     161           0 :         struct dgram_mailslot_handler *dgmslot;
     162           5 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
     163           0 :         struct socket_address *dest;
     164           0 :         const char *myaddress;
     165           0 :         struct nbt_netlogon_packet logon;
     166           0 :         struct nbt_netlogon_response *response;
     167           0 :         struct nbt_name myname;
     168           0 :         NTSTATUS status;
     169           5 :         struct timeval tv = timeval_current();
     170             : 
     171           0 :         struct socket_address *socket_address;
     172             : 
     173           0 :         const char *address;
     174           0 :         struct nbt_name name;
     175             : 
     176           0 :         struct interface *ifaces;
     177           0 :         struct test_join *join_ctx;
     178           0 :         struct cli_credentials *machine_credentials;
     179           0 :         const struct dom_sid *dom_sid;
     180             :         
     181           5 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
     182           5 :         name.type = NBT_NAME_LOGON;
     183           5 :         name.scope = NULL;
     184             : 
     185             :         /* do an initial name resolution to find its IP */
     186           5 :         torture_assert_ntstatus_ok(tctx, 
     187             :                                    resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
     188             :                                                    0, 0,
     189             :                                                    &name, tctx, &address, tctx->ev),
     190             :                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
     191             : 
     192           5 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
     193           5 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
     194             : 
     195           5 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     196             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     197           5 :         torture_assert(tctx, socket_address != NULL, "Error getting address");
     198             : 
     199             :         /* try receiving replies on port 138 first, which will only
     200             :            work if we are root and smbd/nmbd are not running - fall
     201             :            back to listening on any port, which means replies from
     202             :            some windows versions won't be seen */
     203           5 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     204           5 :         if (!NT_STATUS_IS_OK(status)) {
     205           0 :                 talloc_free(socket_address);
     206           0 :                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     207             :                                                              myaddress, 0);
     208           0 :                 torture_assert(tctx, socket_address != NULL, "Error getting address");
     209             : 
     210           0 :                 socket_listen(dgmsock->sock, socket_address, 0, 0);
     211             :         }
     212             : 
     213             :         /* setup a temporary mailslot listener for replies */
     214           5 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     215             :                                       netlogon_handler, NULL);
     216           5 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     217             : 
     218           5 :         ZERO_STRUCT(logon);
     219           5 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     220           5 :         logon.req.logon.request_count = 0;
     221           5 :         logon.req.logon.computer_name = TEST_NAME;
     222           5 :         logon.req.logon.user_name     = "";
     223           5 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     224           5 :         logon.req.logon.nt_version    = NETLOGON_NT_VERSION_5EX_WITH_IP|NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_1;
     225           5 :         logon.req.logon.lmnt_token    = 0xFFFF;
     226           5 :         logon.req.logon.lm20_token    = 0xFFFF;
     227             : 
     228           5 :         make_nbt_name_client(&myname, TEST_NAME);
     229             : 
     230           5 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     231             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     232             : 
     233           5 :         torture_assert(tctx, dest != NULL, "Error getting address");
     234           5 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     235             :                                               NBT_MAILSLOT_NETLOGON, 
     236             :                                               &myname, &logon);
     237           5 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     238             : 
     239          15 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     240          10 :                 tevent_loop_once(dgmsock->event_ctx);
     241             :         }
     242             : 
     243           5 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     244             : 
     245           5 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     246             : 
     247           5 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     248           5 :         map_netlogon_samlogon_response(&response->data.samlogon);
     249             : 
     250           5 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX, "Got incorrect netlogon response command");
     251             : 
     252           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.nt_version, NETLOGON_NT_VERSION_5EX_WITH_IP|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_1, "Got incorrect netlogon response command");
     253             : 
     254           3 :         torture_assert(tctx,
     255             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
     256             :                        "PDC name should not be in UNC form");
     257             : 
     258             :         /* setup (another) temporary mailslot listener for replies */
     259           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     260             :                                       netlogon_handler, NULL);
     261           3 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     262             :         
     263           3 :         ZERO_STRUCT(logon);
     264           3 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     265           3 :         logon.req.logon.request_count = 0;
     266           3 :         logon.req.logon.computer_name = TEST_NAME;
     267           3 :         logon.req.logon.user_name     = TEST_NAME"$";
     268           3 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     269           3 :         logon.req.logon.nt_version    = 1;
     270           3 :         logon.req.logon.lmnt_token    = 0xFFFF;
     271           3 :         logon.req.logon.lm20_token    = 0xFFFF;
     272             : 
     273           3 :         make_nbt_name_client(&myname, TEST_NAME);
     274             : 
     275           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     276             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     277             : 
     278           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     279           3 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     280             :                                               NBT_MAILSLOT_NETLOGON, 
     281             :                                               &myname, &logon);
     282           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     283             : 
     284           9 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     285           6 :                 tevent_loop_once(dgmsock->event_ctx);
     286             :         }
     287             : 
     288           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     289             : 
     290           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     291             : 
     292           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     293           3 :         map_netlogon_samlogon_response(&response->data.samlogon);
     294             : 
     295           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     296             : 
     297           3 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     298             : 
     299           3 :         torture_assert(tctx,
     300             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     301             :                        "PDC name should be in UNC form");
     302             : 
     303           3 :         join_ctx = torture_join_domain(tctx, TEST_NAME, 
     304             :                                        ACB_WSTRUST, &machine_credentials);
     305             : 
     306           3 :         torture_assert(tctx, join_ctx != NULL,
     307             :                        talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
     308             :                                        lpcfg_workgroup(tctx->lp_ctx), TEST_NAME));
     309             : 
     310           3 :         dom_sid = torture_join_sid(join_ctx);
     311             : 
     312             :         /* setup (another) temporary mailslot listener for replies */
     313           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     314             :                                       netlogon_handler, NULL);
     315           3 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     316             :         
     317           3 :         ZERO_STRUCT(logon);
     318           3 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     319           3 :         logon.req.logon.request_count = 0;
     320           3 :         logon.req.logon.computer_name = TEST_NAME;
     321           3 :         logon.req.logon.user_name     = TEST_NAME"$";
     322           3 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     323           3 :         logon.req.logon.sid           = *dom_sid;
     324           3 :         logon.req.logon.nt_version    = 1;
     325           3 :         logon.req.logon.lmnt_token    = 0xFFFF;
     326           3 :         logon.req.logon.lm20_token    = 0xFFFF;
     327             : 
     328           3 :         make_nbt_name_client(&myname, TEST_NAME);
     329             : 
     330           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     331             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     332             : 
     333           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     334           3 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     335             :                                               NBT_MAILSLOT_NETLOGON, 
     336             :                                               &myname, &logon);
     337           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     338             : 
     339             : 
     340           9 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     341           6 :                 tevent_loop_once(dgmsock->event_ctx);
     342             :         }
     343             : 
     344           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     345             : 
     346           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     347             : 
     348           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     349           3 :         map_netlogon_samlogon_response(&response->data.samlogon);
     350             : 
     351           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     352             : 
     353           3 :         torture_assert(tctx,
     354             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     355             :                        "PDC name should be in UNC form");
     356             : 
     357             :         /* setup (another) temporary mailslot listener for replies */
     358           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     359             :                                       netlogon_handler, NULL);
     360           3 :         torture_assert(tctx, dgmslot != NULL, "Error getting a Mailslot for GetDC reply");
     361             : 
     362           3 :         ZERO_STRUCT(logon);
     363           3 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     364           3 :         logon.req.logon.request_count = 0;
     365           3 :         logon.req.logon.computer_name = TEST_NAME;
     366           3 :         logon.req.logon.user_name     = TEST_NAME"$";
     367           3 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     368           3 :         logon.req.logon.sid           = *dom_sid;
     369           3 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     370           3 :         logon.req.logon.nt_version    = 1;
     371           3 :         logon.req.logon.lmnt_token    = 0xFFFF;
     372           3 :         logon.req.logon.lm20_token    = 0xFFFF;
     373             : 
     374           3 :         make_nbt_name_client(&myname, TEST_NAME);
     375             : 
     376           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     377             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     378             : 
     379           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     380           3 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     381             :                                               NBT_MAILSLOT_NETLOGON, 
     382             :                                               &myname, &logon);
     383           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     384             : 
     385             : 
     386           9 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     387           6 :                 tevent_loop_once(dgmsock->event_ctx);
     388             :         }
     389             : 
     390           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     391             : 
     392           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     393             : 
     394           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     395           3 :         map_netlogon_samlogon_response(&response->data.samlogon);
     396             : 
     397           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     398             : 
     399           3 :         torture_assert(tctx,
     400             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     401             :                        "PDC name should be in UNC form");
     402             : 
     403           3 :         dgmslot->private_data = NULL;
     404             : 
     405           3 :         ZERO_STRUCT(logon);
     406           3 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     407           3 :         logon.req.logon.request_count = 0;
     408           3 :         logon.req.logon.computer_name = TEST_NAME;
     409           3 :         logon.req.logon.user_name     = TEST_NAME"$";
     410           3 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     411           3 :         logon.req.logon.sid           = *dom_sid;
     412           3 :         logon.req.logon.acct_control  = ACB_NORMAL;
     413           3 :         logon.req.logon.nt_version    = 1;
     414           3 :         logon.req.logon.lmnt_token    = 0xFFFF;
     415           3 :         logon.req.logon.lm20_token    = 0xFFFF;
     416             : 
     417           3 :         make_nbt_name_client(&myname, TEST_NAME);
     418             : 
     419           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     420             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     421             : 
     422           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     423           3 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     424             :                                               NBT_MAILSLOT_NETLOGON, 
     425             :                                               &myname, &logon);
     426           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     427             : 
     428             : 
     429           9 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     430           6 :                 tevent_loop_once(dgmsock->event_ctx);
     431             :         }
     432             : 
     433           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     434             : 
     435           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     436             : 
     437           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     438           3 :         map_netlogon_samlogon_response(&response->data.samlogon);
     439             : 
     440           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     441             : 
     442           3 :         torture_assert(tctx,
     443             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     444             :                        "PDC name should be in UNC form");
     445             : 
     446           3 :         torture_leave_domain(tctx, join_ctx);
     447           3 :         return true;
     448             : }
     449             : 
     450             : 
     451             : /* test UDP/138 ntlogon requests */
     452           5 : static bool nbt_test_ntlogon(struct torture_context *tctx)
     453             : {
     454           0 :         struct dgram_mailslot_handler *dgmslot;
     455           5 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
     456           0 :         struct socket_address *dest;
     457           0 :         struct test_join *join_ctx;
     458           0 :         const struct dom_sid *dom_sid;
     459           0 :         struct cli_credentials *machine_credentials;
     460             : 
     461           0 :         const char *myaddress;
     462           0 :         struct nbt_netlogon_packet logon;
     463           0 :         struct nbt_netlogon_response *response;
     464           0 :         struct nbt_name myname;
     465           0 :         NTSTATUS status;
     466           5 :         struct timeval tv = timeval_current();
     467             : 
     468           0 :         struct socket_address *socket_address;
     469           0 :         const char *address;
     470           0 :         struct nbt_name name;
     471             : 
     472           0 :         struct interface *ifaces;
     473             :         
     474           5 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
     475           5 :         name.type = NBT_NAME_LOGON;
     476           5 :         name.scope = NULL;
     477             : 
     478             :         /* do an initial name resolution to find its IP */
     479           5 :         torture_assert_ntstatus_ok(tctx, 
     480             :                                    resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
     481             :                                                    0, 0, &name, tctx, &address, tctx->ev),
     482             :                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
     483             : 
     484           5 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
     485           5 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
     486             : 
     487           5 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     488             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     489           5 :         torture_assert(tctx, socket_address != NULL, "Error getting address");
     490             : 
     491             :         /* try receiving replies on port 138 first, which will only
     492             :            work if we are root and smbd/nmbd are not running - fall
     493             :            back to listening on any port, which means replies from
     494             :            most windows versions won't be seen */
     495           5 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     496           5 :         if (!NT_STATUS_IS_OK(status)) {
     497           0 :                 talloc_free(socket_address);
     498           0 :                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     499             :                                                              myaddress, 0);
     500           0 :                 torture_assert(tctx, socket_address != NULL, "Error getting address");
     501             : 
     502           0 :                 socket_listen(dgmsock->sock, socket_address, 0, 0);
     503             :         }
     504             : 
     505           5 :         join_ctx = torture_join_domain(tctx, TEST_NAME, 
     506             :                                        ACB_WSTRUST, &machine_credentials);
     507             : 
     508           5 :         torture_assert(tctx, join_ctx != NULL,
     509             :                        talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
     510             :                                        lpcfg_workgroup(tctx->lp_ctx), TEST_NAME));
     511           5 :         dom_sid = torture_join_sid(join_ctx);
     512             : 
     513             :         /* setup a temporary mailslot listener for replies */
     514           5 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     515             :                                       netlogon_handler, NULL);
     516           5 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     517             : 
     518           5 :         ZERO_STRUCT(logon);
     519           5 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     520           5 :         logon.req.logon.request_count = 0;
     521           5 :         logon.req.logon.computer_name = TEST_NAME;
     522           5 :         logon.req.logon.user_name     = TEST_NAME"$";
     523           5 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     524           5 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     525             :         /* Try with a SID this time */
     526           5 :         logon.req.logon.sid           = *dom_sid;
     527           5 :         logon.req.logon.nt_version    = 1;
     528           5 :         logon.req.logon.lmnt_token    = 0xFFFF;
     529           5 :         logon.req.logon.lm20_token    = 0xFFFF;
     530             : 
     531           5 :         make_nbt_name_client(&myname, TEST_NAME);
     532             : 
     533           5 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     534             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     535           5 :         torture_assert(tctx, dest != NULL, "Error getting address");
     536           5 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     537             :                                               &name, dest, 
     538             :                                               NBT_MAILSLOT_NTLOGON, 
     539             :                                               &myname, &logon);
     540           5 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     541             : 
     542          15 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     543          10 :                 tevent_loop_once(dgmsock->event_ctx);
     544             :         }
     545             : 
     546           5 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     547             : 
     548           5 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     549             : 
     550           5 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     551           5 :         map_netlogon_samlogon_response(&response->data.samlogon);
     552             : 
     553           5 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     554             : 
     555           3 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     556             : 
     557           3 :         torture_assert(tctx,
     558             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     559             :                        "PDC name should be in UNC form");
     560             : 
     561             :         /* setup a temporary mailslot listener for replies */
     562           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     563             :                                       netlogon_handler, NULL);
     564           3 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     565             : 
     566           3 :         ZERO_STRUCT(logon);
     567           3 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     568           3 :         logon.req.logon.request_count = 0;
     569           3 :         logon.req.logon.computer_name = TEST_NAME;
     570           3 :         logon.req.logon.user_name     = TEST_NAME"$";
     571           3 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     572           3 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     573             :         /* Leave sid as all zero */
     574           3 :         logon.req.logon.nt_version    = 1;
     575           3 :         logon.req.logon.lmnt_token    = 0xFFFF;
     576           3 :         logon.req.logon.lm20_token    = 0xFFFF;
     577             : 
     578           3 :         make_nbt_name_client(&myname, TEST_NAME);
     579             : 
     580           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     581             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     582           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     583           3 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     584             :                                               &name, dest, 
     585             :                                               NBT_MAILSLOT_NTLOGON, 
     586             :                                               &myname, &logon);
     587           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     588             : 
     589           9 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     590           6 :                 tevent_loop_once(dgmsock->event_ctx);
     591             :         }
     592             : 
     593           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     594             : 
     595           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     596             : 
     597           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     598           3 :         map_netlogon_samlogon_response(&response->data.samlogon);
     599             : 
     600           3 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     601             : 
     602           3 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     603             : 
     604           3 :         torture_assert(tctx,
     605             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     606             :                        "PDC name should be in UNC form");
     607             : 
     608             :         /* setup (another) temporary mailslot listener for replies */
     609           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     610             :                                       netlogon_handler, NULL);
     611           3 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     612             :         
     613           3 :         ZERO_STRUCT(logon);
     614           3 :         logon.command = LOGON_PRIMARY_QUERY;
     615           3 :         logon.req.pdc.computer_name = TEST_NAME;
     616           3 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     617           3 :         logon.req.pdc.unicode_name  = TEST_NAME;
     618           3 :         logon.req.pdc.nt_version    = 1;
     619           3 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     620           3 :         logon.req.pdc.lm20_token    = 0xFFFF;
     621             : 
     622           3 :         make_nbt_name_client(&myname, TEST_NAME);
     623             : 
     624           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     625             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     626           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     627           3 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     628             :                                               &name, dest, 
     629             :                                               NBT_MAILSLOT_NTLOGON, 
     630             :                                               &myname, &logon);
     631           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     632             : 
     633           9 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     634           6 :                 tevent_loop_once(dgmsock->event_ctx);
     635             :         }
     636             : 
     637           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     638             : 
     639           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     640             : 
     641           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
     642           3 :         torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
     643             : 
     644           3 :         torture_leave_domain(tctx, join_ctx);
     645             : 
     646             :         /* setup (another) temporary mailslot listener for replies */
     647           3 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     648             :                                       netlogon_handler, NULL);
     649           3 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     650             :         
     651           3 :         ZERO_STRUCT(logon);
     652           3 :         logon.command = LOGON_PRIMARY_QUERY;
     653           3 :         logon.req.pdc.computer_name = TEST_NAME;
     654           3 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     655           3 :         logon.req.pdc.unicode_name  = TEST_NAME;
     656           3 :         logon.req.pdc.nt_version    = 1;
     657           3 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     658           3 :         logon.req.pdc.lm20_token    = 0xFFFF;
     659             : 
     660           3 :         make_nbt_name_client(&myname, TEST_NAME);
     661             : 
     662           3 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     663             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     664           3 :         torture_assert(tctx, dest != NULL, "Error getting address");
     665           3 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     666             :                                               &name, dest, 
     667             :                                               NBT_MAILSLOT_NTLOGON, 
     668             :                                               &myname, &logon);
     669           3 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     670             : 
     671           9 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     672           6 :                 tevent_loop_once(dgmsock->event_ctx);
     673             :         }
     674             : 
     675           3 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     676             : 
     677           3 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     678             : 
     679           3 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
     680           3 :         torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
     681             : 
     682             : 
     683           3 :         return true;
     684             : }
     685             : 
     686             : 
     687             : /*
     688             :   test nbt dgram operations
     689             : */
     690        2379 : struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
     691             : {
     692        2379 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "dgram");
     693             : 
     694        2379 :         torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
     695        2379 :         torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
     696        2379 :         torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);
     697             : 
     698        2379 :         return suite;
     699             : }

Generated by: LCOV version 1.14