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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/dgram/libdgram.h"
25 #include "librpc/gen_ndr/samr.h"
26 #include "librpc/gen_ndr/ndr_nbt.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "lib/socket/socket.h"
29 #include "lib/events/events.h"
30 #include "torture/rpc/rpc.h"
31 #include "libcli/resolve/resolve.h"
32 #include "system/network.h"
33 #include "lib/socket/netif.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 struct socket_address *src)
45 struct nbt_netlogon_packet netlogon;
46 int *replies = dgmslot->private;
48 printf("netlogon reply from %s:%d\n", src->addr, src->port);
50 status = dgram_mailslot_netlogon_parse(dgmslot, dgmslot, packet, &netlogon);
51 if (!NT_STATUS_IS_OK(status)) {
52 printf("Failed to parse netlogon packet from %s:%d\n",
53 src->addr, src->port);
57 NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);
63 /* test UDP/138 netlogon requests */
64 static bool nbt_test_netlogon(struct torture_context *tctx)
66 struct dgram_mailslot_handler *dgmslot;
67 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL);
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 name.name = lp_workgroup();
82 name.type = NBT_NAME_LOGON;
85 /* do an initial name resolution to find its IP */
86 torture_assert_ntstatus_ok(tctx,
87 resolve_name(&name, tctx, &address, event_context_find(tctx)),
88 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
90 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
93 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
94 myaddress, lp_dgram_port());
95 torture_assert(tctx, socket_address != NULL,
96 "Error getting address");
98 /* try receiving replies on port 138 first, which will only
99 work if we are root and smbd/nmbd are not running - fall
100 back to listening on any port, which means replies from
101 some windows versions won't be seen */
102 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
103 if (!NT_STATUS_IS_OK(status)) {
104 talloc_free(socket_address);
105 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
107 torture_assert(tctx, socket_address != NULL, "Error getting address");
109 socket_listen(dgmsock->sock, socket_address, 0, 0);
112 /* setup a temporary mailslot listener for replies */
113 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
114 netlogon_handler, &replies);
117 logon.command = NETLOGON_QUERY_FOR_PDC;
118 logon.req.pdc.computer_name = TEST_NAME;
119 logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
120 logon.req.pdc.unicode_name = TEST_NAME;
121 logon.req.pdc.nt_version = 1;
122 logon.req.pdc.lmnt_token = 0xFFFF;
123 logon.req.pdc.lm20_token = 0xFFFF;
125 make_nbt_name_client(&myname, TEST_NAME);
127 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
129 torture_assert(tctx, dest != NULL, "Error getting address");
131 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
133 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
135 while (timeval_elapsed(&tv) < 5 && replies == 0) {
136 event_loop_once(dgmsock->event_ctx);
143 /* test UDP/138 netlogon requests */
144 static bool nbt_test_netlogon2(struct torture_context *tctx)
146 struct dgram_mailslot_handler *dgmslot;
147 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL);
148 struct socket_address *dest;
149 const char *myaddress;
150 struct nbt_netlogon_packet logon;
151 struct nbt_name myname;
153 struct timeval tv = timeval_current();
156 struct socket_address *socket_address;
159 struct nbt_name name;
161 name.name = lp_workgroup();
162 name.type = NBT_NAME_LOGON;
165 /* do an initial name resolution to find its IP */
166 torture_assert_ntstatus_ok(tctx,
167 resolve_name(&name, tctx, &address, event_context_find(tctx)),
168 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
170 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
172 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
173 myaddress, lp_dgram_port());
174 torture_assert(tctx, socket_address != NULL, "Error getting address");
176 /* try receiving replies on port 138 first, which will only
177 work if we are root and smbd/nmbd are not running - fall
178 back to listening on any port, which means replies from
179 some windows versions won't be seen */
180 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
181 if (!NT_STATUS_IS_OK(status)) {
182 talloc_free(socket_address);
183 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
186 torture_assert(tctx, socket_address != NULL, "Error getting address");
188 socket_listen(dgmsock->sock, socket_address, 0, 0);
191 /* setup a temporary mailslot listener for replies */
192 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
193 netlogon_handler, &replies);
197 logon.command = NETLOGON_QUERY_FOR_PDC2;
198 logon.req.pdc2.request_count = 0;
199 logon.req.pdc2.computer_name = TEST_NAME;
200 logon.req.pdc2.user_name = "";
201 logon.req.pdc2.mailslot_name = dgmslot->mailslot_name;
202 logon.req.pdc2.nt_version = 11;
203 logon.req.pdc2.lmnt_token = 0xFFFF;
204 logon.req.pdc2.lm20_token = 0xFFFF;
206 make_nbt_name_client(&myname, TEST_NAME);
208 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
211 torture_assert(tctx, dest != NULL, "Error getting address");
212 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
214 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
216 while (timeval_elapsed(&tv) < 5 && replies == 0) {
217 event_loop_once(dgmsock->event_ctx);
225 reply handler for ntlogon request
227 static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
228 struct nbt_dgram_packet *packet,
229 struct socket_address *src)
232 struct nbt_ntlogon_packet ntlogon;
233 int *replies = dgmslot->private;
235 printf("ntlogon reply from %s:%d\n", src->addr, src->port);
237 status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
238 if (!NT_STATUS_IS_OK(status)) {
239 printf("Failed to parse ntlogon packet from %s:%d\n",
240 src->addr, src->port);
244 NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
250 /* test UDP/138 ntlogon requests */
251 static bool nbt_test_ntlogon(struct torture_context *tctx)
253 struct dgram_mailslot_handler *dgmslot;
254 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL);
255 struct socket_address *dest;
256 struct test_join *join_ctx;
257 struct cli_credentials *machine_credentials;
258 const struct dom_sid *dom_sid;
260 const char *myaddress;
261 struct nbt_ntlogon_packet logon;
262 struct nbt_name myname;
264 struct timeval tv = timeval_current();
267 struct socket_address *socket_address;
269 struct nbt_name name;
271 name.name = lp_workgroup();
272 name.type = NBT_NAME_LOGON;
275 /* do an initial name resolution to find its IP */
276 torture_assert_ntstatus_ok(tctx,
277 resolve_name(&name, tctx, &address, event_context_find(tctx)),
278 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
280 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
282 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
283 myaddress, lp_dgram_port());
284 torture_assert(tctx, socket_address != NULL, "Error getting address");
286 /* try receiving replies on port 138 first, which will only
287 work if we are root and smbd/nmbd are not running - fall
288 back to listening on any port, which means replies from
289 some windows versions won't be seen */
290 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
291 if (!NT_STATUS_IS_OK(status)) {
292 talloc_free(socket_address);
293 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
295 torture_assert(tctx, socket_address != NULL, "Error getting address");
297 socket_listen(dgmsock->sock, socket_address, 0, 0);
300 join_ctx = torture_join_domain(TEST_NAME,
301 ACB_WSTRUST, &machine_credentials);
302 torture_assert(tctx, join_ctx != NULL,
303 talloc_asprintf(tctx, "Failed to join domain %s as %s\n", lp_workgroup(), TEST_NAME));
305 dom_sid = torture_join_sid(join_ctx);
307 /* setup a temporary mailslot listener for replies */
308 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
309 ntlogon_handler, &replies);
313 logon.command = NTLOGON_SAM_LOGON;
314 logon.req.logon.request_count = 0;
315 logon.req.logon.computer_name = TEST_NAME;
316 logon.req.logon.user_name = TEST_NAME"$";
317 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
318 logon.req.logon.acct_control = ACB_WSTRUST;
319 logon.req.logon.sid = *dom_sid;
320 logon.req.logon.nt_version = 1;
321 logon.req.logon.lmnt_token = 0xFFFF;
322 logon.req.logon.lm20_token = 0xFFFF;
324 make_nbt_name_client(&myname, TEST_NAME);
326 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
328 torture_assert(tctx, dest != NULL, "Error getting address");
329 status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
330 &name, dest, &myname, &logon);
331 torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
333 while (timeval_elapsed(&tv) < 5 && replies == 0) {
334 event_loop_once(dgmsock->event_ctx);
337 torture_leave_domain(join_ctx);
343 test nbt dgram operations
345 struct torture_suite *torture_nbt_dgram(void)
347 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(),
350 torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
351 torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
352 torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);