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"
34 #define TEST_NAME "TORTURE_TEST"
37 reply handler for netlogon request
39 static void netlogon_handler(struct dgram_mailslot_handler *dgmslot,
40 struct nbt_dgram_packet *packet,
41 struct socket_address *src)
44 struct nbt_netlogon_packet netlogon;
45 int *replies = (int *)dgmslot->private;
47 printf("netlogon reply from %s:%d\n", src->addr, src->port);
49 status = dgram_mailslot_netlogon_parse(dgmslot, dgmslot, packet, &netlogon);
50 if (!NT_STATUS_IS_OK(status)) {
51 printf("Failed to parse netlogon packet from %s:%d\n",
52 src->addr, src->port);
56 NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);
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, NULL);
67 struct socket_address *dest;
68 const char *myaddress;
69 struct nbt_netlogon_packet logon;
70 struct nbt_name myname;
72 struct timeval tv = timeval_current();
75 struct socket_address *socket_address;
80 name.name = lp_workgroup();
81 name.type = NBT_NAME_LOGON;
84 /* do an initial name resolution to find its IP */
85 torture_assert_ntstatus_ok(tctx,
86 resolve_name(&name, tctx, &address, event_context_find(tctx)),
87 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
89 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
92 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
93 myaddress, lp_dgram_port());
94 torture_assert(tctx, socket_address != NULL, "Error getting address");
96 /* try receiving replies on port 138 first, which will only
97 work if we are root and smbd/nmbd are not running - fall
98 back to listening on any port, which means replies from
99 some windows versions won't be seen */
100 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
101 if (!NT_STATUS_IS_OK(status)) {
102 talloc_free(socket_address);
103 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
105 torture_assert(tctx, socket_address != NULL, "Error getting address");
107 socket_listen(dgmsock->sock, socket_address, 0, 0);
110 /* setup a temporary mailslot listener for replies */
111 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
112 netlogon_handler, &replies);
115 logon.command = NETLOGON_QUERY_FOR_PDC;
116 logon.req.pdc.computer_name = TEST_NAME;
117 logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
118 logon.req.pdc.unicode_name = TEST_NAME;
119 logon.req.pdc.nt_version = 1;
120 logon.req.pdc.lmnt_token = 0xFFFF;
121 logon.req.pdc.lm20_token = 0xFFFF;
123 make_nbt_name_client(&myname, TEST_NAME);
125 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
127 torture_assert(tctx, dest != NULL, "Error getting address");
129 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
131 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
133 while (timeval_elapsed(&tv) < 5 && replies == 0) {
134 event_loop_once(dgmsock->event_ctx);
141 /* test UDP/138 netlogon requests */
142 static bool nbt_test_netlogon2(struct torture_context *tctx)
144 struct dgram_mailslot_handler *dgmslot;
145 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL);
146 struct socket_address *dest;
147 const char *myaddress;
148 struct nbt_netlogon_packet logon;
149 struct nbt_name myname;
151 struct timeval tv = timeval_current();
154 struct socket_address *socket_address;
157 struct nbt_name name;
159 name.name = lp_workgroup();
160 name.type = NBT_NAME_LOGON;
163 /* do an initial name resolution to find its IP */
164 torture_assert_ntstatus_ok(tctx,
165 resolve_name(&name, tctx, &address, event_context_find(tctx)),
166 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
168 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
170 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
171 myaddress, lp_dgram_port());
172 torture_assert(tctx, socket_address != NULL, "Error getting address");
174 /* try receiving replies on port 138 first, which will only
175 work if we are root and smbd/nmbd are not running - fall
176 back to listening on any port, which means replies from
177 some windows versions won't be seen */
178 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
179 if (!NT_STATUS_IS_OK(status)) {
180 talloc_free(socket_address);
181 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
183 torture_assert(tctx, socket_address != NULL, "Error getting address");
185 socket_listen(dgmsock->sock, socket_address, 0, 0);
188 /* setup a temporary mailslot listener for replies */
189 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
190 netlogon_handler, &replies);
194 logon.command = NETLOGON_QUERY_FOR_PDC2;
195 logon.req.pdc2.request_count = 0;
196 logon.req.pdc2.computer_name = TEST_NAME;
197 logon.req.pdc2.user_name = "";
198 logon.req.pdc2.mailslot_name = dgmslot->mailslot_name;
199 logon.req.pdc2.nt_version = 11;
200 logon.req.pdc2.lmnt_token = 0xFFFF;
201 logon.req.pdc2.lm20_token = 0xFFFF;
203 make_nbt_name_client(&myname, TEST_NAME);
205 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
208 torture_assert(tctx, dest != NULL, "Error getting address");
209 status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
211 torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
213 while (timeval_elapsed(&tv) < 5 && replies == 0) {
214 event_loop_once(dgmsock->event_ctx);
222 reply handler for ntlogon request
224 static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
225 struct nbt_dgram_packet *packet,
226 struct socket_address *src)
229 struct nbt_ntlogon_packet ntlogon;
230 int *replies = (int *)dgmslot->private;
232 printf("ntlogon reply from %s:%d\n", src->addr, src->port);
234 status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
235 if (!NT_STATUS_IS_OK(status)) {
236 printf("Failed to parse ntlogon packet from %s:%d\n",
237 src->addr, src->port);
241 NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
247 /* test UDP/138 ntlogon requests */
248 static bool nbt_test_ntlogon(struct torture_context *tctx)
250 struct dgram_mailslot_handler *dgmslot;
251 struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL);
252 struct socket_address *dest;
253 struct test_join *join_ctx;
254 struct cli_credentials *machine_credentials;
255 const struct dom_sid *dom_sid;
257 const char *myaddress;
258 struct nbt_ntlogon_packet logon;
259 struct nbt_name myname;
261 struct timeval tv = timeval_current();
264 struct socket_address *socket_address;
266 struct nbt_name name;
268 name.name = lp_workgroup();
269 name.type = NBT_NAME_LOGON;
272 /* do an initial name resolution to find its IP */
273 torture_assert_ntstatus_ok(tctx,
274 resolve_name(&name, tctx, &address, event_context_find(tctx)),
275 talloc_asprintf(tctx, "Failed to resolve %s", name.name));
277 myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
279 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
280 myaddress, lp_dgram_port());
281 torture_assert(tctx, socket_address != NULL, "Error getting address");
283 /* try receiving replies on port 138 first, which will only
284 work if we are root and smbd/nmbd are not running - fall
285 back to listening on any port, which means replies from
286 some windows versions won't be seen */
287 status = socket_listen(dgmsock->sock, socket_address, 0, 0);
288 if (!NT_STATUS_IS_OK(status)) {
289 talloc_free(socket_address);
290 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
292 torture_assert(tctx, socket_address != NULL, "Error getting address");
294 socket_listen(dgmsock->sock, socket_address, 0, 0);
297 join_ctx = torture_join_domain(TEST_NAME,
298 ACB_WSTRUST, &machine_credentials);
299 torture_assert(tctx, join_ctx != NULL,
300 talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
301 lp_workgroup(), TEST_NAME));
303 dom_sid = torture_join_sid(join_ctx);
305 /* setup a temporary mailslot listener for replies */
306 dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
307 ntlogon_handler, &replies);
311 logon.command = NTLOGON_SAM_LOGON;
312 logon.req.logon.request_count = 0;
313 logon.req.logon.computer_name = TEST_NAME;
314 logon.req.logon.user_name = TEST_NAME"$";
315 logon.req.logon.mailslot_name = dgmslot->mailslot_name;
316 logon.req.logon.acct_control = ACB_WSTRUST;
317 logon.req.logon.sid = *dom_sid;
318 logon.req.logon.nt_version = 1;
319 logon.req.logon.lmnt_token = 0xFFFF;
320 logon.req.logon.lm20_token = 0xFFFF;
322 make_nbt_name_client(&myname, TEST_NAME);
324 dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
326 torture_assert(tctx, dest != NULL, "Error getting address");
327 status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
328 &name, dest, &myname, &logon);
329 torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
331 while (timeval_elapsed(&tv) < 5 && replies == 0) {
332 event_loop_once(dgmsock->event_ctx);
335 torture_leave_domain(join_ctx);
341 test nbt dgram operations
343 struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
345 struct torture_suite *suite = torture_suite_create(mem_ctx, "DGRAM");
347 torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
348 torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
349 torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);