Merge commit 'origin/v4-0-test' into vfs_smb2
[sfrench/samba-autobuild/.git] / source4 / torture / nbt / dgram.c
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 "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"
34
35 #define TEST_NAME "TORTURE_TEST"
36
37 /*
38   reply handler for netlogon request
39 */
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)
44 {
45         NTSTATUS status;
46         struct nbt_netlogon_response netlogon;
47         int *replies = (int *)dgmslot->private;
48
49         printf("netlogon reply from %s:%d\n", src->addr, src->port);
50
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);
55                 return;
56         }
57
58         (*replies)++;
59 }
60
61
62 /* test UDP/138 netlogon requests */
63 static bool nbt_test_netlogon(struct torture_context *tctx)
64 {
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;
72         NTSTATUS status;
73         struct timeval tv = timeval_current();
74         int replies = 0;
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 = lp_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(lp_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, lp_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, lp_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, &replies);
117
118         ZERO_STRUCT(logon);
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;
126
127         make_nbt_name_client(&myname, TEST_NAME);
128
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");
132
133         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
134                                               NBT_MAILSLOT_NETLOGON, 
135                                               &myname, &logon);
136         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
137
138         while (timeval_elapsed(&tv) < 5 && replies == 0) {
139                 event_loop_once(dgmsock->event_ctx);
140         }
141
142         return true;
143 }
144
145
146 /* test UDP/138 netlogon requests */
147 static bool nbt_test_netlogon2(struct torture_context *tctx)
148 {
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;
156         NTSTATUS status;
157         struct timeval tv = timeval_current();
158         int replies = 0;
159
160         struct socket_address *socket_address;
161
162         const char *address;
163         struct nbt_name name;
164
165         struct interface *ifaces;
166         struct test_join *join_ctx;
167         struct cli_credentials *machine_credentials;
168         const struct dom_sid *dom_sid;
169         
170         name.name = lp_workgroup(tctx->lp_ctx);
171         name.type = NBT_NAME_LOGON;
172         name.scope = NULL;
173
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));
178
179         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
180         myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
181
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");
185
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,
194                                                              myaddress, 0);
195                 torture_assert(tctx, socket_address != NULL, "Error getting address");
196
197                 socket_listen(dgmsock->sock, socket_address, 0, 0);
198         }
199
200         /* setup a temporary mailslot listener for replies */
201         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
202                                       netlogon_handler, &replies);
203         
204
205         ZERO_STRUCT(logon);
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;
214
215         make_nbt_name_client(&myname, TEST_NAME);
216
217         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
218                                            address, lp_dgram_port(tctx->lp_ctx));
219
220         torture_assert(tctx, dest != NULL, "Error getting address");
221         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
222                                               NBT_MAILSLOT_NETLOGON, 
223                                               &myname, &logon);
224         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
225
226         while (timeval_elapsed(&tv) < 5 && replies == 0) {
227                 event_loop_once(dgmsock->event_ctx);
228         }
229
230         ZERO_STRUCT(logon);
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;
239
240         make_nbt_name_client(&myname, TEST_NAME);
241
242         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
243                                            address, lp_dgram_port(tctx->lp_ctx));
244
245         torture_assert(tctx, dest != NULL, "Error getting address");
246         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
247                                               NBT_MAILSLOT_NETLOGON, 
248                                               &myname, &logon);
249         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
250
251         while (timeval_elapsed(&tv) < 5 && replies == 0) {
252                 event_loop_once(dgmsock->event_ctx);
253         }
254
255         join_ctx = torture_join_domain(tctx, TEST_NAME, 
256                                        ACB_WSTRUST, &machine_credentials);
257
258         dom_sid = torture_join_sid(join_ctx);
259
260         ZERO_STRUCT(logon);
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;
270
271         make_nbt_name_client(&myname, TEST_NAME);
272
273         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
274                                            address, lp_dgram_port(tctx->lp_ctx));
275
276         torture_assert(tctx, dest != NULL, "Error getting address");
277         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
278                                               NBT_MAILSLOT_NETLOGON, 
279                                               &myname, &logon);
280         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
281
282         while (timeval_elapsed(&tv) < 5 && replies == 0) {
283                 event_loop_once(dgmsock->event_ctx);
284         }
285
286         torture_leave_domain(join_ctx);
287         return true;
288 }
289
290
291 /* test UDP/138 ntlogon requests */
292 static bool nbt_test_ntlogon(struct torture_context *tctx)
293 {
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;
300
301         const char *myaddress;
302         struct nbt_netlogon_packet logon;
303         struct nbt_name myname;
304         NTSTATUS status;
305         struct timeval tv = timeval_current();
306         int replies = 0;
307
308         struct socket_address *socket_address;
309         const char *address;
310         struct nbt_name name;
311
312         struct interface *ifaces;
313         
314         name.name = lp_workgroup(tctx->lp_ctx);
315         name.type = NBT_NAME_LOGON;
316         name.scope = NULL;
317
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));
322
323         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
324         myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
325
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");
329
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,
338                                                              myaddress, 0);
339                 torture_assert(tctx, socket_address != NULL, "Error getting address");
340
341                 socket_listen(dgmsock->sock, socket_address, 0, 0);
342         }
343
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));
349
350         /* setup a temporary mailslot listener for replies */
351         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
352                                       netlogon_handler, &replies);
353         
354
355         ZERO_STRUCT(logon);
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;
366
367         make_nbt_name_client(&myname, TEST_NAME);
368
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, 
373                                               &name, dest, 
374                                               NBT_MAILSLOT_NTLOGON, 
375                                               &myname, &logon);
376         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
377
378         while (timeval_elapsed(&tv) < 5 && replies == 0) {
379                 event_loop_once(dgmsock->event_ctx);
380         }
381
382         ZERO_STRUCT(logon);
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;
390
391         make_nbt_name_client(&myname, TEST_NAME);
392
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, 
397                                               &name, dest, 
398                                               NBT_MAILSLOT_NTLOGON, 
399                                               &myname, &logon);
400         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
401
402         while (timeval_elapsed(&tv) < 5 && replies == 0) {
403                 event_loop_once(dgmsock->event_ctx);
404         }
405
406         torture_leave_domain(join_ctx);
407         return true;
408 }
409
410
411 /*
412   test nbt dgram operations
413 */
414 struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
415 {
416         struct torture_suite *suite = torture_suite_create(mem_ctx, "DGRAM");
417
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);
421
422         return suite;
423 }