2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2005
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.
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.
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/>.
23 #include "libcli/dgram/libdgram.h"
24 #include "librpc/gen_ndr/samr.h"
25 #include "librpc/gen_ndr/ndr_nbt.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "lib/socket/socket.h"
28 #include "lib/events/events.h"
29 #include "torture/rpc/rpc.h"
30 #include "libcli/resolve/resolve.h"
31 #include "system/network.h"
32 #include "lib/socket/netif.h"
33 #include "param/param.h"
35 #define TEST_NAME "TORTURE_TEST"
38 reply handler for netlogon request
40 static void netlogon_handler(struct dgram_mailslot_handler *dgmslot,
41 struct nbt_dgram_packet *packet,
42 const char *mailslot_name,
43 struct socket_address *src)
46 struct nbt_netlogon_response netlogon;
47 int *replies = (int *)dgmslot->private;
49 printf("netlogon reply from %s:%d\n", src->addr, src->port);
51 status = dgram_mailslot_netlogon_parse_response(dgmslot, dgmslot, packet, &netlogon);
52 if (!NT_STATUS_IS_OK(status)) {
53 printf("Failed to parse netlogon packet from %s:%d\n",
54 src->addr, src->port);
62 /* test UDP/138 netlogon requests */
63 static bool nbt_test_netlogon(struct torture_context *tctx)
65 struct dgram_mailslot_handler *dgmslot;
66 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
67 lp_iconv_convenience(tctx->lp_ctx));
68 struct socket_address *dest;
69 const char *myaddress;
70 struct nbt_netlogon_packet logon;
71 struct nbt_name myname;
73 struct timeval tv = timeval_current();
76 struct socket_address *socket_address;
81 struct interface *ifaces;
83 name.name = lp_workgroup(tctx->lp_ctx);
84 name.type = NBT_NAME_LOGON;
87 /* do an initial name resolution to find its IP */
88 torture_assert_ntstatus_ok(tctx,
89 resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
90 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
92 load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
93 myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
96 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
97 myaddress, lp_dgram_port(tctx->lp_ctx));
98 torture_assert(tctx, socket_address != NULL, "Error getting address");
100 /* try receiving replies on port 138 first, which will only
101 work if we are root and smbd/nmbd are not running - fall
102 back to listening on any port, which means replies from
103 most windows versions won't be seen */
104 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
105 if (!NT_STATUS_IS_OK(status)) {
106 talloc_free(socket_address);
107 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
109 torture_assert(tctx, socket_address != NULL, "Error getting address");
111 socket_listen(dgmsock->sock, socket_address, 0, 0);
114 /* setup a temporary mailslot listener for replies */
115 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
116 netlogon_handler, &replies);
119 logon.command = LOGON_PRIMARY_QUERY;
120 logon.req.pdc.computer_name = TEST_NAME;
121 logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
122 logon.req.pdc.unicode_name = TEST_NAME;
123 logon.req.pdc.nt_version = 1;
124 logon.req.pdc.lmnt_token = 0xFFFF;
125 logon.req.pdc.lm20_token = 0xFFFF;
127 make_nbt_name_client(&myname, TEST_NAME);
129 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
130 address, lp_dgram_port(tctx->lp_ctx));
131 torture_assert(tctx, dest != NULL, "Error getting address");
133 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
134 NBT_MAILSLOT_NETLOGON,
136 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
138 while (timeval_elapsed(&tv) < 5 && replies == 0) {
139 event_loop_once(dgmsock->event_ctx);
146 /* test UDP/138 netlogon requests */
147 static bool nbt_test_netlogon2(struct torture_context *tctx)
149 struct dgram_mailslot_handler *dgmslot;
150 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
151 lp_iconv_convenience(tctx->lp_ctx));
152 struct socket_address *dest;
153 const char *myaddress;
154 struct nbt_netlogon_packet logon;
155 struct nbt_name myname;
157 struct timeval tv = timeval_current();
160 struct socket_address *socket_address;
163 struct nbt_name name;
165 struct interface *ifaces;
166 struct test_join *join_ctx;
167 struct cli_credentials *machine_credentials;
168 const struct dom_sid *dom_sid;
170 name.name = lp_workgroup(tctx->lp_ctx);
171 name.type = NBT_NAME_LOGON;
174 /* do an initial name resolution to find its IP */
175 torture_assert_ntstatus_ok(tctx,
176 resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
177 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
179 load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
180 myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
182 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
183 myaddress, lp_dgram_port(tctx->lp_ctx));
184 torture_assert(tctx, socket_address != NULL, "Error getting address");
186 /* try receiving replies on port 138 first, which will only
187 work if we are root and smbd/nmbd are not running - fall
188 back to listening on any port, which means replies from
189 some windows versions won't be seen */
190 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
191 if (!NT_STATUS_IS_OK(status)) {
192 talloc_free(socket_address);
193 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
195 torture_assert(tctx, socket_address != NULL, "Error getting address");
197 socket_listen(dgmsock->sock, socket_address, 0, 0);
200 /* setup a temporary mailslot listener for replies */
201 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
202 netlogon_handler, &replies);
206 logon.command = LOGON_SAM_LOGON_REQUEST;
207 logon.req.logon.request_count = 0;
208 logon.req.logon.computer_name = TEST_NAME;
209 logon.req.logon.user_name = "";
210 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
211 logon.req.logon.nt_version = 11;
212 logon.req.logon.lmnt_token = 0xFFFF;
213 logon.req.logon.lm20_token = 0xFFFF;
215 make_nbt_name_client(&myname, TEST_NAME);
217 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
218 address, lp_dgram_port(tctx->lp_ctx));
220 torture_assert(tctx, dest != NULL, "Error getting address");
221 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
222 NBT_MAILSLOT_NETLOGON,
224 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
226 while (timeval_elapsed(&tv) < 5 && replies == 0) {
227 event_loop_once(dgmsock->event_ctx);
231 logon.command = LOGON_SAM_LOGON_REQUEST;
232 logon.req.logon.request_count = 0;
233 logon.req.logon.computer_name = TEST_NAME;
234 logon.req.logon.user_name = TEST_NAME"$";
235 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
236 logon.req.logon.nt_version = 1;
237 logon.req.logon.lmnt_token = 0xFFFF;
238 logon.req.logon.lm20_token = 0xFFFF;
240 make_nbt_name_client(&myname, TEST_NAME);
242 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
243 address, lp_dgram_port(tctx->lp_ctx));
245 torture_assert(tctx, dest != NULL, "Error getting address");
246 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
247 NBT_MAILSLOT_NETLOGON,
249 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
251 while (timeval_elapsed(&tv) < 5 && replies == 0) {
252 event_loop_once(dgmsock->event_ctx);
255 join_ctx = torture_join_domain(tctx, TEST_NAME,
256 ACB_WSTRUST, &machine_credentials);
258 dom_sid = torture_join_sid(join_ctx);
261 logon.command = LOGON_SAM_LOGON_REQUEST;
262 logon.req.logon.request_count = 0;
263 logon.req.logon.computer_name = TEST_NAME;
264 logon.req.logon.user_name = TEST_NAME"$";
265 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
266 logon.req.logon.sid = *dom_sid;
267 logon.req.logon.nt_version = 1;
268 logon.req.logon.lmnt_token = 0xFFFF;
269 logon.req.logon.lm20_token = 0xFFFF;
271 make_nbt_name_client(&myname, TEST_NAME);
273 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
274 address, lp_dgram_port(tctx->lp_ctx));
276 torture_assert(tctx, dest != NULL, "Error getting address");
277 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
278 NBT_MAILSLOT_NETLOGON,
280 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
282 while (timeval_elapsed(&tv) < 5 && replies == 0) {
283 event_loop_once(dgmsock->event_ctx);
286 torture_leave_domain(join_ctx);
291 /* test UDP/138 ntlogon requests */
292 static bool nbt_test_ntlogon(struct torture_context *tctx)
294 struct dgram_mailslot_handler *dgmslot;
295 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
296 lp_iconv_convenience(tctx->lp_ctx));
297 struct socket_address *dest;
298 struct test_join *join_ctx;
299 struct cli_credentials *machine_credentials;
301 const char *myaddress;
302 struct nbt_netlogon_packet logon;
303 struct nbt_name myname;
305 struct timeval tv = timeval_current();
308 struct socket_address *socket_address;
310 struct nbt_name name;
312 struct interface *ifaces;
314 name.name = lp_workgroup(tctx->lp_ctx);
315 name.type = NBT_NAME_LOGON;
318 /* do an initial name resolution to find its IP */
319 torture_assert_ntstatus_ok(tctx,
320 resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
321 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
323 load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
324 myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
326 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
327 myaddress, lp_dgram_port(tctx->lp_ctx));
328 torture_assert(tctx, socket_address != NULL, "Error getting address");
330 /* try receiving replies on port 138 first, which will only
331 work if we are root and smbd/nmbd are not running - fall
332 back to listening on any port, which means replies from
333 most windows versions won't be seen */
334 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
335 if (!NT_STATUS_IS_OK(status)) {
336 talloc_free(socket_address);
337 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
339 torture_assert(tctx, socket_address != NULL, "Error getting address");
341 socket_listen(dgmsock->sock, socket_address, 0, 0);
344 join_ctx = torture_join_domain(tctx, TEST_NAME,
345 ACB_WSTRUST, &machine_credentials);
346 torture_assert(tctx, join_ctx != NULL,
347 talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
348 lp_workgroup(tctx->lp_ctx), TEST_NAME));
350 /* setup a temporary mailslot listener for replies */
351 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
352 netlogon_handler, &replies);
356 logon.command = LOGON_SAM_LOGON_REQUEST;
357 logon.req.logon.request_count = 0;
358 logon.req.logon.computer_name = TEST_NAME;
359 logon.req.logon.user_name = TEST_NAME"$";
360 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
361 logon.req.logon.acct_control = ACB_WSTRUST;
362 /* Leave sid as all zero */
363 logon.req.logon.nt_version = 1;
364 logon.req.logon.lmnt_token = 0xFFFF;
365 logon.req.logon.lm20_token = 0xFFFF;
367 make_nbt_name_client(&myname, TEST_NAME);
369 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
370 address, lp_dgram_port(tctx->lp_ctx));
371 torture_assert(tctx, dest != NULL, "Error getting address");
372 status = dgram_mailslot_netlogon_send(dgmsock,
374 NBT_MAILSLOT_NTLOGON,
376 torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
378 while (timeval_elapsed(&tv) < 5 && replies == 0) {
379 event_loop_once(dgmsock->event_ctx);
383 logon.command = LOGON_PRIMARY_QUERY;
384 logon.req.pdc.computer_name = TEST_NAME;
385 logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
386 logon.req.pdc.unicode_name = TEST_NAME;
387 logon.req.pdc.nt_version = 1;
388 logon.req.pdc.lmnt_token = 0xFFFF;
389 logon.req.pdc.lm20_token = 0xFFFF;
391 make_nbt_name_client(&myname, TEST_NAME);
393 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
394 address, lp_dgram_port(tctx->lp_ctx));
395 torture_assert(tctx, dest != NULL, "Error getting address");
396 status = dgram_mailslot_netlogon_send(dgmsock,
398 NBT_MAILSLOT_NTLOGON,
400 torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
402 while (timeval_elapsed(&tv) < 5 && replies == 0) {
403 event_loop_once(dgmsock->event_ctx);
406 torture_leave_domain(join_ctx);
412 test nbt dgram operations
414 struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
416 struct torture_suite *suite = torture_suite_create(mem_ctx, "DGRAM");
418 torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
419 torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
420 torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);