a4c8be888cf7fe90b019e6703518c8beea4cd02c
[gd/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                              struct socket_address *src)
43 {
44         NTSTATUS status;
45         struct nbt_netlogon_packet netlogon;
46         int *replies = (int *)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(struct torture_context *tctx)
65 {
66         struct dgram_mailslot_handler *dgmslot;
67         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL, 
68                                                                  lp_iconv_convenience(tctx->lp_ctx));
69         struct socket_address *dest;
70         const char *myaddress;
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         const char *address;
80         struct nbt_name name;
81
82         struct interface *ifaces;
83         
84         name.name = lp_workgroup(tctx->lp_ctx);
85         name.type = NBT_NAME_LOGON;
86         name.scope = NULL;
87
88         /* do an initial name resolution to find its IP */
89         torture_assert_ntstatus_ok(tctx, 
90                                    resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
91                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
92
93         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
94         myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
95
96
97         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
98                                                      myaddress, lp_dgram_port(tctx->lp_ctx));
99         torture_assert(tctx, socket_address != NULL, "Error getting address");
100
101         /* try receiving replies on port 138 first, which will only
102            work if we are root and smbd/nmbd are not running - fall
103            back to listening on any port, which means replies from
104            some windows versions won't be seen */
105         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
106         if (!NT_STATUS_IS_OK(status)) {
107                 talloc_free(socket_address);
108                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
109                                                              myaddress, 0);
110                 torture_assert(tctx, socket_address != NULL, "Error getting address");
111
112                 socket_listen(dgmsock->sock, socket_address, 0, 0);
113         }
114
115         /* setup a temporary mailslot listener for replies */
116         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
117                                       netlogon_handler, &replies);
118
119         ZERO_STRUCT(logon);
120         logon.command = NETLOGON_QUERY_FOR_PDC;
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, lp_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                                               &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, NULL,
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         
167         name.name = lp_workgroup(tctx->lp_ctx);
168         name.type = NBT_NAME_LOGON;
169         name.scope = NULL;
170
171         /* do an initial name resolution to find its IP */
172         torture_assert_ntstatus_ok(tctx, 
173                                    resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
174                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
175
176         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
177         myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
178
179         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
180                                                      myaddress, lp_dgram_port(tctx->lp_ctx));
181         torture_assert(tctx, socket_address != NULL, "Error getting address");
182
183         /* try receiving replies on port 138 first, which will only
184            work if we are root and smbd/nmbd are not running - fall
185            back to listening on any port, which means replies from
186            some windows versions won't be seen */
187         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
188         if (!NT_STATUS_IS_OK(status)) {
189                 talloc_free(socket_address);
190                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
191                                                              myaddress, 0);
192                 torture_assert(tctx, socket_address != NULL, "Error getting address");
193
194                 socket_listen(dgmsock->sock, socket_address, 0, 0);
195         }
196
197         /* setup a temporary mailslot listener for replies */
198         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
199                                       netlogon_handler, &replies);
200         
201
202         ZERO_STRUCT(logon);
203         logon.command = NETLOGON_QUERY_FOR_PDC2;
204         logon.req.pdc2.request_count = 0;
205         logon.req.pdc2.computer_name = TEST_NAME;
206         logon.req.pdc2.user_name     = "";
207         logon.req.pdc2.mailslot_name = dgmslot->mailslot_name;
208         logon.req.pdc2.nt_version    = 11;
209         logon.req.pdc2.lmnt_token    = 0xFFFF;
210         logon.req.pdc2.lm20_token    = 0xFFFF;
211
212         make_nbt_name_client(&myname, TEST_NAME);
213
214         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
215                                            address, lp_dgram_port(tctx->lp_ctx));
216
217         torture_assert(tctx, dest != NULL, "Error getting address");
218         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
219                                               &myname, &logon);
220         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
221
222         while (timeval_elapsed(&tv) < 5 && replies == 0) {
223                 event_loop_once(dgmsock->event_ctx);
224         }
225
226         return true;
227 }
228
229
230 /*
231   reply handler for ntlogon request
232 */
233 static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot, 
234                              struct nbt_dgram_packet *packet, 
235                              struct socket_address *src)
236 {
237         NTSTATUS status;
238         struct nbt_ntlogon_packet ntlogon;
239         int *replies = (int *)dgmslot->private;
240
241         printf("ntlogon reply from %s:%d\n", src->addr, src->port);
242
243         status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
244         if (!NT_STATUS_IS_OK(status)) {
245                 printf("Failed to parse ntlogon packet from %s:%d\n",
246                        src->addr, src->port);
247                 return;
248         }
249
250         NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
251
252         (*replies)++;
253 }
254
255
256 /* test UDP/138 ntlogon requests */
257 static bool nbt_test_ntlogon(struct torture_context *tctx)
258 {
259         struct dgram_mailslot_handler *dgmslot;
260         struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL,
261                                                                  lp_iconv_convenience(tctx->lp_ctx));
262         struct socket_address *dest;
263         struct test_join *join_ctx;
264         struct cli_credentials *machine_credentials;
265         const struct dom_sid *dom_sid;
266
267         const char *myaddress;
268         struct nbt_ntlogon_packet logon;
269         struct nbt_name myname;
270         NTSTATUS status;
271         struct timeval tv = timeval_current();
272         int replies = 0;
273
274         struct socket_address *socket_address;
275         const char *address;
276         struct nbt_name name;
277
278         struct interface *ifaces;
279         
280         name.name = lp_workgroup(tctx->lp_ctx);
281         name.type = NBT_NAME_LOGON;
282         name.scope = NULL;
283
284         /* do an initial name resolution to find its IP */
285         torture_assert_ntstatus_ok(tctx, 
286                                    resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
287                                    talloc_asprintf(tctx, "Failed to resolve %s", name.name));
288
289         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
290         myaddress = talloc_strdup(dgmsock, iface_best_ip(ifaces, address));
291
292         socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
293                                                      myaddress, lp_dgram_port(tctx->lp_ctx));
294         torture_assert(tctx, socket_address != NULL, "Error getting address");
295
296         /* try receiving replies on port 138 first, which will only
297            work if we are root and smbd/nmbd are not running - fall
298            back to listening on any port, which means replies from
299            some windows versions won't be seen */
300         status = socket_listen(dgmsock->sock, socket_address, 0, 0);
301         if (!NT_STATUS_IS_OK(status)) {
302                 talloc_free(socket_address);
303                 socket_address = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
304                                                              myaddress, 0);
305                 torture_assert(tctx, socket_address != NULL, "Error getting address");
306
307                 socket_listen(dgmsock->sock, socket_address, 0, 0);
308         }
309
310         join_ctx = torture_join_domain(tctx, TEST_NAME, 
311                                        ACB_WSTRUST, &machine_credentials);
312         torture_assert(tctx, join_ctx != NULL,
313                        talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
314                                        lp_workgroup(tctx->lp_ctx), TEST_NAME));
315
316         dom_sid = torture_join_sid(join_ctx);
317
318         /* setup a temporary mailslot listener for replies */
319         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
320                                       ntlogon_handler, &replies);
321         
322
323         ZERO_STRUCT(logon);
324         logon.command = NTLOGON_SAM_LOGON;
325         logon.req.logon.request_count = 0;
326         logon.req.logon.computer_name = TEST_NAME;
327         logon.req.logon.user_name     = TEST_NAME"$";
328         logon.req.logon.mailslot_name = dgmslot->mailslot_name;
329         logon.req.logon.acct_control  = ACB_WSTRUST;
330         logon.req.logon.sid           = *dom_sid;
331         logon.req.logon.nt_version    = 1;
332         logon.req.logon.lmnt_token    = 0xFFFF;
333         logon.req.logon.lm20_token    = 0xFFFF;
334
335         make_nbt_name_client(&myname, TEST_NAME);
336
337         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
338                                            address, lp_dgram_port(tctx->lp_ctx));
339         torture_assert(tctx, dest != NULL, "Error getting address");
340         status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
341                                              &name, dest, &myname, &logon);
342         torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
343
344         while (timeval_elapsed(&tv) < 5 && replies == 0) {
345                 event_loop_once(dgmsock->event_ctx);
346         }
347
348         torture_leave_domain(join_ctx);
349         return true;
350 }
351
352
353 /*
354   test nbt dgram operations
355 */
356 struct torture_suite *torture_nbt_dgram(TALLOC_CTX *mem_ctx)
357 {
358         struct torture_suite *suite = torture_suite_create(mem_ctx, "DGRAM");
359
360         torture_suite_add_simple_test(suite, "netlogon", nbt_test_netlogon);
361         torture_suite_add_simple_test(suite, "netlogon2", nbt_test_netlogon2);
362         torture_suite_add_simple_test(suite, "ntlogon", nbt_test_ntlogon);
363
364         return suite;
365 }