LCOV - code coverage report
Current view: top level - source4/torture/nbt - dgram.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 305 320 95.3 %
Date: 2024-06-13 04:01:37 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          10 : static void netlogon_handler(struct dgram_mailslot_handler *dgmslot, 
      39             :                              struct nbt_dgram_packet *packet, 
      40             :                              struct socket_address *src)
      41             : {
      42             :         NTSTATUS status;
      43          10 :         struct nbt_netlogon_response *netlogon = dgmslot->private_data;
      44             : 
      45          10 :         dgmslot->private_data = netlogon = talloc(dgmslot, struct nbt_netlogon_response);
      46             : 
      47          10 :         if (!dgmslot->private_data) {
      48           0 :                 return;
      49             :         }
      50             :        
      51          10 :         printf("netlogon reply from %s:%d\n", src->addr, src->port);
      52             : 
      53             :         /* Fills in the netlogon pointer */
      54          10 :         status = dgram_mailslot_netlogon_parse_response(netlogon, packet,
      55             :                                                         netlogon);
      56          10 :         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           1 : static bool nbt_test_netlogon(struct torture_context *tctx)
      67             : {
      68             :         struct dgram_mailslot_handler *dgmslot;
      69           1 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
      70             :         struct socket_address *dest;
      71             :         const char *myaddress;
      72             :         struct nbt_netlogon_packet logon;
      73             :         struct nbt_netlogon_response *response;
      74             :         struct nbt_name myname;
      75             :         NTSTATUS status;
      76           1 :         struct timeval tv = timeval_current();
      77             : 
      78             :         struct socket_address *socket_address;
      79             : 
      80             :         const char *address;
      81             :         struct nbt_name name;
      82             : 
      83             :         struct interface *ifaces;
      84             : 
      85           1 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
      86           1 :         name.type = NBT_NAME_LOGON;
      87           1 :         name.scope = NULL;
      88             : 
      89             :         /* do an initial name resolution to find its IP */
      90           1 :         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           1 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
      97           1 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
      98             : 
      99             : 
     100           1 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     101             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     102           1 :         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           1 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     109           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     120             :                                       netlogon_handler, NULL);
     121           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     122             : 
     123           1 :         ZERO_STRUCT(logon);
     124           1 :         logon.command = LOGON_PRIMARY_QUERY;
     125           1 :         logon.req.pdc.computer_name = TEST_NAME;
     126           1 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     127           1 :         logon.req.pdc.unicode_name  = TEST_NAME;
     128           1 :         logon.req.pdc.nt_version    = 1;
     129           1 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     130           1 :         logon.req.pdc.lm20_token    = 0xFFFF;
     131             : 
     132           1 :         make_nbt_name_client(&myname, TEST_NAME);
     133             : 
     134           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     135             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     136           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     137             : 
     138           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     139             :                                               NBT_MAILSLOT_NETLOGON, 
     140             :                                               &myname, &logon);
     141           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     142             : 
     143           4 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     144           2 :                 tevent_loop_once(dgmsock->event_ctx);
     145             :         }
     146             : 
     147           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     148             : 
     149           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     150             : 
     151           1 :         torture_assert(tctx, response->response_type == NETLOGON_GET_PDC, "Got incorrect type of netlogon response");
     152           1 :         torture_assert(tctx, response->data.get_pdc.command == NETLOGON_RESPONSE_FROM_PDC, "Got incorrect netlogon response command");
     153             : 
     154           1 :         return true;
     155             : }
     156             : 
     157             : 
     158             : /* test UDP/138 netlogon requests */
     159           1 : static bool nbt_test_netlogon2(struct torture_context *tctx)
     160             : {
     161             :         struct dgram_mailslot_handler *dgmslot;
     162           1 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
     163             :         struct socket_address *dest;
     164             :         const char *myaddress;
     165             :         struct nbt_netlogon_packet logon;
     166             :         struct nbt_netlogon_response *response;
     167             :         struct nbt_name myname;
     168             :         NTSTATUS status;
     169           1 :         struct timeval tv = timeval_current();
     170             : 
     171             :         struct socket_address *socket_address;
     172             : 
     173             :         const char *address;
     174             :         struct nbt_name name;
     175             : 
     176             :         struct interface *ifaces;
     177             :         struct test_join *join_ctx;
     178             :         struct cli_credentials *machine_credentials;
     179             :         const struct dom_sid *dom_sid;
     180             :         
     181           1 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
     182           1 :         name.type = NBT_NAME_LOGON;
     183           1 :         name.scope = NULL;
     184             : 
     185             :         /* do an initial name resolution to find its IP */
     186           1 :         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           1 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
     193           1 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
     194             : 
     195           1 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     196             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     197           1 :         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           1 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     204           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     215             :                                       netlogon_handler, NULL);
     216           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     217             : 
     218           1 :         ZERO_STRUCT(logon);
     219           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     220           1 :         logon.req.logon.request_count = 0;
     221           1 :         logon.req.logon.computer_name = TEST_NAME;
     222           1 :         logon.req.logon.user_name     = "";
     223           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     224           1 :         logon.req.logon.nt_version    = NETLOGON_NT_VERSION_5EX_WITH_IP|NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_1;
     225           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     226           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     227             : 
     228           1 :         make_nbt_name_client(&myname, TEST_NAME);
     229             : 
     230           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     231             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     232             : 
     233           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     234           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     235             :                                               NBT_MAILSLOT_NETLOGON, 
     236             :                                               &myname, &logon);
     237           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     238             : 
     239           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     240           2 :                 tevent_loop_once(dgmsock->event_ctx);
     241             :         }
     242             : 
     243           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     244             : 
     245           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     246             : 
     247           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     248           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     249             : 
     250           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX, "Got incorrect netlogon response command");
     251             : 
     252           1 :         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           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     260             :                                       netlogon_handler, NULL);
     261           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     262             :         
     263           1 :         ZERO_STRUCT(logon);
     264           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     265           1 :         logon.req.logon.request_count = 0;
     266           1 :         logon.req.logon.computer_name = TEST_NAME;
     267           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     268           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     269           1 :         logon.req.logon.nt_version    = 1;
     270           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     271           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     272             : 
     273           1 :         make_nbt_name_client(&myname, TEST_NAME);
     274             : 
     275           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     276             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     277             : 
     278           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     279           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     280             :                                               NBT_MAILSLOT_NETLOGON, 
     281             :                                               &myname, &logon);
     282           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     283             : 
     284           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     285           2 :                 tevent_loop_once(dgmsock->event_ctx);
     286             :         }
     287             : 
     288           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     289             : 
     290           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     291             : 
     292           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     293           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     294             : 
     295           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     296             : 
     297           1 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     298             : 
     299           1 :         torture_assert(tctx,
     300             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     301             :                        "PDC name should be in UNC form");
     302             : 
     303           1 :         join_ctx = torture_join_domain(tctx, TEST_NAME, 
     304             :                                        ACB_WSTRUST, &machine_credentials);
     305             : 
     306           1 :         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           1 :         dom_sid = torture_join_sid(join_ctx);
     311             : 
     312             :         /* setup (another) temporary mailslot listener for replies */
     313           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     314             :                                       netlogon_handler, NULL);
     315           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     316             :         
     317           1 :         ZERO_STRUCT(logon);
     318           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     319           1 :         logon.req.logon.request_count = 0;
     320           1 :         logon.req.logon.computer_name = TEST_NAME;
     321           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     322           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     323           1 :         logon.req.logon.sid           = *dom_sid;
     324           1 :         logon.req.logon.nt_version    = 1;
     325           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     326           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     327             : 
     328           1 :         make_nbt_name_client(&myname, TEST_NAME);
     329             : 
     330           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     331             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     332             : 
     333           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     334           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     335             :                                               NBT_MAILSLOT_NETLOGON, 
     336             :                                               &myname, &logon);
     337           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     338             : 
     339             : 
     340           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     341           2 :                 tevent_loop_once(dgmsock->event_ctx);
     342             :         }
     343             : 
     344           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     345             : 
     346           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     347             : 
     348           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     349           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     350             : 
     351           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     352             : 
     353           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     359             :                                       netlogon_handler, NULL);
     360           1 :         torture_assert(tctx, dgmslot != NULL, "Error getting a Mailslot for GetDC reply");
     361             : 
     362           1 :         ZERO_STRUCT(logon);
     363           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     364           1 :         logon.req.logon.request_count = 0;
     365           1 :         logon.req.logon.computer_name = TEST_NAME;
     366           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     367           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     368           1 :         logon.req.logon.sid           = *dom_sid;
     369           1 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     370           1 :         logon.req.logon.nt_version    = 1;
     371           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     372           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     373             : 
     374           1 :         make_nbt_name_client(&myname, TEST_NAME);
     375             : 
     376           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     377             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     378             : 
     379           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     380           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     381             :                                               NBT_MAILSLOT_NETLOGON, 
     382             :                                               &myname, &logon);
     383           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     384             : 
     385             : 
     386           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     387           2 :                 tevent_loop_once(dgmsock->event_ctx);
     388             :         }
     389             : 
     390           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     391             : 
     392           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     393             : 
     394           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     395           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     396             : 
     397           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     398             : 
     399           1 :         torture_assert(tctx,
     400             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     401             :                        "PDC name should be in UNC form");
     402             : 
     403           1 :         dgmslot->private_data = NULL;
     404             : 
     405           1 :         ZERO_STRUCT(logon);
     406           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     407           1 :         logon.req.logon.request_count = 0;
     408           1 :         logon.req.logon.computer_name = TEST_NAME;
     409           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     410           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     411           1 :         logon.req.logon.sid           = *dom_sid;
     412           1 :         logon.req.logon.acct_control  = ACB_NORMAL;
     413           1 :         logon.req.logon.nt_version    = 1;
     414           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     415           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     416             : 
     417           1 :         make_nbt_name_client(&myname, TEST_NAME);
     418             : 
     419           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     420             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     421             : 
     422           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     423           1 :         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
     424             :                                               NBT_MAILSLOT_NETLOGON, 
     425             :                                               &myname, &logon);
     426           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
     427             : 
     428             : 
     429           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     430           2 :                 tevent_loop_once(dgmsock->event_ctx);
     431             :         }
     432             : 
     433           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     434             : 
     435           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     436             : 
     437           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     438           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     439             : 
     440           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
     441             : 
     442           1 :         torture_assert(tctx,
     443             :                        strstr(response->data.samlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
     444             :                        "PDC name should be in UNC form");
     445             : 
     446           1 :         torture_leave_domain(tctx, join_ctx);
     447           1 :         return true;
     448             : }
     449             : 
     450             : 
     451             : /* test UDP/138 ntlogon requests */
     452           1 : static bool nbt_test_ntlogon(struct torture_context *tctx)
     453             : {
     454             :         struct dgram_mailslot_handler *dgmslot;
     455           1 :         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev);
     456             :         struct socket_address *dest;
     457             :         struct test_join *join_ctx;
     458             :         const struct dom_sid *dom_sid;
     459             :         struct cli_credentials *machine_credentials;
     460             : 
     461             :         const char *myaddress;
     462             :         struct nbt_netlogon_packet logon;
     463             :         struct nbt_netlogon_response *response;
     464             :         struct nbt_name myname;
     465             :         NTSTATUS status;
     466           1 :         struct timeval tv = timeval_current();
     467             : 
     468             :         struct socket_address *socket_address;
     469             :         const char *address;
     470             :         struct nbt_name name;
     471             : 
     472             :         struct interface *ifaces;
     473             :         
     474           1 :         name.name = lpcfg_workgroup(tctx->lp_ctx);
     475           1 :         name.type = NBT_NAME_LOGON;
     476           1 :         name.scope = NULL;
     477             : 
     478             :         /* do an initial name resolution to find its IP */
     479           1 :         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           1 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
     485           1 :         myaddress = talloc_strdup(dgmsock, iface_list_best_ip(ifaces, address));
     486             : 
     487           1 :         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
     488             :                                                      myaddress, lpcfg_dgram_port(tctx->lp_ctx));
     489           1 :         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           1 :         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
     496           1 :         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           1 :         join_ctx = torture_join_domain(tctx, TEST_NAME, 
     506             :                                        ACB_WSTRUST, &machine_credentials);
     507             : 
     508           1 :         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           1 :         dom_sid = torture_join_sid(join_ctx);
     512             : 
     513             :         /* setup a temporary mailslot listener for replies */
     514           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     515             :                                       netlogon_handler, NULL);
     516           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     517             : 
     518           1 :         ZERO_STRUCT(logon);
     519           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     520           1 :         logon.req.logon.request_count = 0;
     521           1 :         logon.req.logon.computer_name = TEST_NAME;
     522           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     523           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     524           1 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     525             :         /* Try with a SID this time */
     526           1 :         logon.req.logon.sid           = *dom_sid;
     527           1 :         logon.req.logon.nt_version    = 1;
     528           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     529           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     530             : 
     531           1 :         make_nbt_name_client(&myname, TEST_NAME);
     532             : 
     533           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     534             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     535           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     536           1 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     537             :                                               &name, dest, 
     538             :                                               NBT_MAILSLOT_NTLOGON, 
     539             :                                               &myname, &logon);
     540           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     541             : 
     542           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     543           2 :                 tevent_loop_once(dgmsock->event_ctx);
     544             :         }
     545             : 
     546           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     547             : 
     548           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     549             : 
     550           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     551           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     552             : 
     553           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     554             : 
     555           1 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     556             : 
     557           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     563             :                                       netlogon_handler, NULL);
     564           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     565             : 
     566           1 :         ZERO_STRUCT(logon);
     567           1 :         logon.command = LOGON_SAM_LOGON_REQUEST;
     568           1 :         logon.req.logon.request_count = 0;
     569           1 :         logon.req.logon.computer_name = TEST_NAME;
     570           1 :         logon.req.logon.user_name     = TEST_NAME"$";
     571           1 :         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
     572           1 :         logon.req.logon.acct_control  = ACB_WSTRUST;
     573             :         /* Leave sid as all zero */
     574           1 :         logon.req.logon.nt_version    = 1;
     575           1 :         logon.req.logon.lmnt_token    = 0xFFFF;
     576           1 :         logon.req.logon.lm20_token    = 0xFFFF;
     577             : 
     578           1 :         make_nbt_name_client(&myname, TEST_NAME);
     579             : 
     580           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     581             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     582           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     583           1 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     584             :                                               &name, dest, 
     585             :                                               NBT_MAILSLOT_NTLOGON, 
     586             :                                               &myname, &logon);
     587           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     588             : 
     589           4 :         while (timeval_elapsed(&tv) < 5 && dgmslot->private_data == NULL) {
     590           2 :                 tevent_loop_once(dgmsock->event_ctx);
     591             :         }
     592             : 
     593           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     594             : 
     595           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     596             : 
     597           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
     598           1 :         map_netlogon_samlogon_response(&response->data.samlogon);
     599             : 
     600           1 :         torture_assert_int_equal(tctx, response->data.samlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
     601             : 
     602           1 :         torture_assert_str_equal(tctx, response->data.samlogon.data.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
     603             : 
     604           1 :         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           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     610             :                                       netlogon_handler, NULL);
     611           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     612             :         
     613           1 :         ZERO_STRUCT(logon);
     614           1 :         logon.command = LOGON_PRIMARY_QUERY;
     615           1 :         logon.req.pdc.computer_name = TEST_NAME;
     616           1 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     617           1 :         logon.req.pdc.unicode_name  = TEST_NAME;
     618           1 :         logon.req.pdc.nt_version    = 1;
     619           1 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     620           1 :         logon.req.pdc.lm20_token    = 0xFFFF;
     621             : 
     622           1 :         make_nbt_name_client(&myname, TEST_NAME);
     623             : 
     624           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     625             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     626           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     627           1 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     628             :                                               &name, dest, 
     629             :                                               NBT_MAILSLOT_NTLOGON, 
     630             :                                               &myname, &logon);
     631           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     632             : 
     633           4 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     634           2 :                 tevent_loop_once(dgmsock->event_ctx);
     635             :         }
     636             : 
     637           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     638             : 
     639           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     640             : 
     641           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
     642           1 :         torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
     643             : 
     644           1 :         torture_leave_domain(tctx, join_ctx);
     645             : 
     646             :         /* setup (another) temporary mailslot listener for replies */
     647           1 :         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
     648             :                                       netlogon_handler, NULL);
     649           1 :         torture_assert(tctx, dgmslot != NULL, "Error temporary mailslot for GetDC");
     650             :         
     651           1 :         ZERO_STRUCT(logon);
     652           1 :         logon.command = LOGON_PRIMARY_QUERY;
     653           1 :         logon.req.pdc.computer_name = TEST_NAME;
     654           1 :         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
     655           1 :         logon.req.pdc.unicode_name  = TEST_NAME;
     656           1 :         logon.req.pdc.nt_version    = 1;
     657           1 :         logon.req.pdc.lmnt_token    = 0xFFFF;
     658           1 :         logon.req.pdc.lm20_token    = 0xFFFF;
     659             : 
     660           1 :         make_nbt_name_client(&myname, TEST_NAME);
     661             : 
     662           1 :         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
     663             :                                            address, lpcfg_dgram_port(tctx->lp_ctx));
     664           1 :         torture_assert(tctx, dest != NULL, "Error getting address");
     665           1 :         status = dgram_mailslot_netlogon_send(dgmsock, 
     666             :                                               &name, dest, 
     667             :                                               NBT_MAILSLOT_NTLOGON, 
     668             :                                               &myname, &logon);
     669           1 :         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
     670             : 
     671           4 :         while (timeval_elapsed(&tv) < 5 && !dgmslot->private_data) {
     672           2 :                 tevent_loop_once(dgmsock->event_ctx);
     673             :         }
     674             : 
     675           1 :         response = talloc_get_type(dgmslot->private_data, struct nbt_netlogon_response);
     676             : 
     677           1 :         torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
     678             : 
     679           1 :         torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
     680           1 :         torture_assert_int_equal(tctx, response->data.get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
     681             : 
     682             : 
     683           1 :         return true;
     684             : }
     685             : 
     686             : 
     687             : /*
     688             :   test nbt dgram operations
     689             : */
     690         964 : struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
     691             : {
     692         964 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "dgram");
     693             : 
     694         964 :         torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
     695         964 :         torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
     696         964 :         torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);
     697             : 
     698         964 :         return suite;
     699             : }

Generated by: LCOV version 1.13