r14720: Add torture_context argument to all torture tests
[bbaumbach/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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
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 "netif/netif.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                              struct socket_address *src)
43 {
44         NTSTATUS status;
45         struct nbt_netlogon_packet netlogon;
46         int *replies = dgmslot->private;
47
48         printf("netlogon reply from %s:%d\n", src->addr, src->port);
49
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);
54                 return;
55         }
56
57         NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);
58
59         (*replies)++;
60 }
61
62
63 /* test UDP/138 netlogon requests */
64 static BOOL nbt_test_netlogon(TALLOC_CTX *mem_ctx, 
65                               struct nbt_name name, const char *address)
66 {
67         struct dgram_mailslot_handler *dgmslot;
68         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, NULL);
69         struct socket_address *dest;
70         const char *myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
71         struct nbt_netlogon_packet logon;
72         struct nbt_name myname;
73         NTSTATUS status;
74         struct timeval tv = timeval_current();
75         int replies = 0;
76
77         struct socket_address *socket_address;
78
79         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
80                                                      myaddress, lp_dgram_port());
81         if (!socket_address) {
82                 return False;
83         }
84
85         /* try receiving replies on port 138 first, which will only
86            work if we are root and smbd/nmbd are not running - fall
87            back to listening on any port, which means replies from
88            some windows versions won't be seen */
89         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
90         if (!NT_STATUS_IS_OK(status)) {
91                 talloc_free(socket_address);
92                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
93                                                              myaddress, 0);
94                 if (!socket_address) {
95                         return False;
96                 }
97
98                 socket_listen(dgmsock->sock, socket_address, 0, 0);
99         }
100
101         /* setup a temporary mailslot listener for replies */
102         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
103                                       netlogon_handler, &replies);
104
105         ZERO_STRUCT(logon);
106         logon.command = NETLOGON_QUERY_FOR_PDC;
107         logon.req.pdc.computer_name = TEST_NAME;
108         logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
109         logon.req.pdc.unicode_name  = TEST_NAME;
110         logon.req.pdc.nt_version    = 1;
111         logon.req.pdc.lmnt_token    = 0xFFFF;
112         logon.req.pdc.lm20_token    = 0xFFFF;
113
114         make_nbt_name_client(&myname, TEST_NAME);
115
116         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
117                                            address, 0);
118         if (!dest) {
119                 return False;
120         }
121
122         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
123                                               &myname, &logon);
124         if (!NT_STATUS_IS_OK(status)) {
125                 printf("Failed to send netlogon request - %s\n", nt_errstr(status));
126                 goto failed;
127         }
128
129         while (timeval_elapsed(&tv) < 5 && replies == 0) {
130                 event_loop_once(dgmsock->event_ctx);
131         }
132
133         talloc_free(dgmsock);
134         return True;
135
136 failed:
137         talloc_free(dgmsock);
138         return False;
139 }
140
141
142 /* test UDP/138 netlogon requests */
143 static BOOL nbt_test_netlogon2(TALLOC_CTX *mem_ctx, 
144                               struct nbt_name name, const char *address)
145 {
146         struct dgram_mailslot_handler *dgmslot;
147         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, NULL);
148         struct socket_address *dest;
149         const char *myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
150         struct nbt_netlogon_packet logon;
151         struct nbt_name myname;
152         NTSTATUS status;
153         struct timeval tv = timeval_current();
154         int replies = 0;
155
156         struct socket_address *socket_address;
157
158         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
159                                                      myaddress, lp_dgram_port());
160         if (!socket_address) {
161                 return False;
162         }
163
164         /* try receiving replies on port 138 first, which will only
165            work if we are root and smbd/nmbd are not running - fall
166            back to listening on any port, which means replies from
167            some windows versions won't be seen */
168         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
169         if (!NT_STATUS_IS_OK(status)) {
170                 talloc_free(socket_address);
171                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
172                                                              myaddress, 0);
173                 if (!socket_address) {
174                         return False;
175                 }
176
177                 socket_listen(dgmsock->sock, socket_address, 0, 0);
178         }
179
180         /* setup a temporary mailslot listener for replies */
181         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
182                                       netlogon_handler, &replies);
183         
184
185         ZERO_STRUCT(logon);
186         logon.command = NETLOGON_QUERY_FOR_PDC2;
187         logon.req.pdc2.request_count = 0;
188         logon.req.pdc2.computer_name = TEST_NAME;
189         logon.req.pdc2.user_name     = "";
190         logon.req.pdc2.mailslot_name = dgmslot->mailslot_name;
191         logon.req.pdc2.nt_version    = 11;
192         logon.req.pdc2.lmnt_token    = 0xFFFF;
193         logon.req.pdc2.lm20_token    = 0xFFFF;
194
195         make_nbt_name_client(&myname, TEST_NAME);
196
197         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
198                                            address, 0);
199         if (!dest) {
200                 goto failed;
201         }
202         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
203                                               &myname, &logon);
204         if (!NT_STATUS_IS_OK(status)) {
205                 printf("Failed to send netlogon request - %s\n", nt_errstr(status));
206                 goto failed;
207         }
208
209
210         while (timeval_elapsed(&tv) < 5 && replies == 0) {
211                 event_loop_once(dgmsock->event_ctx);
212         }
213
214         talloc_free(dgmsock);
215         return True;
216
217 failed:
218         talloc_free(dgmsock);
219         return False;
220 }
221
222
223 /*
224   reply handler for ntlogon request
225 */
226 static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot, 
227                              struct nbt_dgram_packet *packet, 
228                              struct socket_address *src)
229 {
230         NTSTATUS status;
231         struct nbt_ntlogon_packet ntlogon;
232         int *replies = dgmslot->private;
233
234         printf("ntlogon reply from %s:%d\n", src->addr, src->port);
235
236         status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
237         if (!NT_STATUS_IS_OK(status)) {
238                 printf("Failed to parse ntlogon packet from %s:%d\n",
239                        src->addr, src->port);
240                 return;
241         }
242
243         NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
244
245         (*replies)++;
246 }
247
248
249 /* test UDP/138 ntlogon requests */
250 static BOOL nbt_test_ntlogon(TALLOC_CTX *mem_ctx, 
251                              struct nbt_name name, const char *address)
252 {
253         struct dgram_mailslot_handler *dgmslot;
254         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, 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;
259
260         const char *myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
261         struct nbt_ntlogon_packet logon;
262         struct nbt_name myname;
263         NTSTATUS status;
264         struct timeval tv = timeval_current();
265         int replies = 0;
266
267         struct socket_address *socket_address;
268
269         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
270                                                      myaddress, lp_dgram_port());
271         if (!socket_address) {
272                 return False;
273         }
274
275         /* try receiving replies on port 138 first, which will only
276            work if we are root and smbd/nmbd are not running - fall
277            back to listening on any port, which means replies from
278            some windows versions won't be seen */
279         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
280         if (!NT_STATUS_IS_OK(status)) {
281                 talloc_free(socket_address);
282                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
283                                                              myaddress, 0);
284                 if (!socket_address) {
285                         return False;
286                 }
287
288                 socket_listen(dgmsock->sock, socket_address, 0, 0);
289         }
290
291         join_ctx = torture_join_domain(TEST_NAME, 
292                                        ACB_WSTRUST, &machine_credentials);
293         if (join_ctx == NULL) {
294                 printf("Failed to join domain %s as %s\n", lp_workgroup(), TEST_NAME);
295                 talloc_free(dgmsock);
296                 return False;
297         }
298
299         dom_sid = torture_join_sid(join_ctx);
300
301         /* setup a temporary mailslot listener for replies */
302         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
303                                       ntlogon_handler, &replies);
304         
305
306         ZERO_STRUCT(logon);
307         logon.command = NTLOGON_SAM_LOGON;
308         logon.req.logon.request_count = 0;
309         logon.req.logon.computer_name = TEST_NAME;
310         logon.req.logon.user_name     = TEST_NAME"$";
311         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
312         logon.req.logon.acct_control  = ACB_WSTRUST;
313         logon.req.logon.sid           = *dom_sid;
314         logon.req.logon.nt_version    = 1;
315         logon.req.logon.lmnt_token    = 0xFFFF;
316         logon.req.logon.lm20_token    = 0xFFFF;
317
318         make_nbt_name_client(&myname, TEST_NAME);
319
320         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
321                                            address, 0);
322         if (!dest) {
323                 goto failed;
324         }
325         status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
326                                              &name, dest, &myname, &logon);
327         if (!NT_STATUS_IS_OK(status)) {
328                 printf("Failed to send ntlogon request - %s\n", nt_errstr(status));
329                 goto failed;
330         }
331
332
333         while (timeval_elapsed(&tv) < 5 && replies == 0) {
334                 event_loop_once(dgmsock->event_ctx);
335         }
336
337         torture_leave_domain(join_ctx);
338         talloc_free(dgmsock);
339         return True;
340
341 failed:
342         torture_leave_domain(join_ctx);
343         talloc_free(dgmsock);
344         return False;
345 }
346
347
348 /*
349   test nbt dgram operations
350 */
351 BOOL torture_nbt_dgram(struct torture_context *torture)
352 {
353         const char *address;
354         struct nbt_name name;
355         TALLOC_CTX *mem_ctx = talloc_new(NULL);
356         NTSTATUS status;
357         BOOL ret = True;
358         
359         name.name = lp_workgroup();
360         name.type = NBT_NAME_LOGON;
361         name.scope = NULL;
362
363         /* do an initial name resolution to find its IP */
364         status = resolve_name(&name, mem_ctx, &address, event_context_find(mem_ctx));
365         if (!NT_STATUS_IS_OK(status)) {
366                 printf("Failed to resolve %s - %s\n",
367                        name.name, nt_errstr(status));
368                 talloc_free(mem_ctx);
369                 return False;
370         }
371
372         ret &= nbt_test_netlogon(mem_ctx, name, address);
373         ret &= nbt_test_netlogon2(mem_ctx, name, address);
374         ret &= nbt_test_ntlogon(mem_ctx, name, address);
375
376         talloc_free(mem_ctx);
377
378         return ret;
379 }