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