r25000: Fix some more C++ compatibility warnings.
[metze/samba/wip.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
34 #define TEST_NAME "TORTURE_TEST"
35
36 /*
37   reply handler for netlogon request
38 */
39 static void netlogon_handler(struct dgram_mailslot_handler *dgmslot, 
40                              struct nbt_dgram_packet *packet, 
41                              struct socket_address *src)
42 {
43         NTSTATUS status;
44         struct nbt_netlogon_packet netlogon;
45         int *replies = (int *)dgmslot->private;
46
47         printf("netlogon reply from %s:%d\n", src->addr, src->port);
48
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);
53                 return;
54         }
55
56         NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);
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, NULL);
67         struct socket_address *dest;
68         const char *myaddress;
69         struct nbt_netlogon_packet logon;
70         struct nbt_name myname;
71         NTSTATUS status;
72         struct timeval tv = timeval_current();
73         int replies = 0;
74
75         struct socket_address *socket_address;
76
77         const char *address;
78         struct nbt_name name;
79         
80         name.name = lp_workgroup();
81         name.type = NBT_NAME_LOGON;
82         name.scope = NULL;
83
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));
88
89         myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
90
91
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");
95
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,
104                                                              myaddress, 0);
105                 torture_assert(tctx, socket_address != NULL, "Error getting address");
106
107                 socket_listen(dgmsock->sock, socket_address, 0, 0);
108         }
109
110         /* setup a temporary mailslot listener for replies */
111         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
112                                       netlogon_handler, &replies);
113
114         ZERO_STRUCT(logon);
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;
122
123         make_nbt_name_client(&myname, TEST_NAME);
124
125         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
126                                            address, 0);
127         torture_assert(tctx, dest != NULL, "Error getting address");
128
129         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
130                                               &myname, &logon);
131         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
132
133         while (timeval_elapsed(&tv) < 5 && replies == 0) {
134                 event_loop_once(dgmsock->event_ctx);
135         }
136
137         return true;
138 }
139
140
141 /* test UDP/138 netlogon requests */
142 static bool nbt_test_netlogon2(struct torture_context *tctx)
143 {
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;
150         NTSTATUS status;
151         struct timeval tv = timeval_current();
152         int replies = 0;
153
154         struct socket_address *socket_address;
155
156         const char *address;
157         struct nbt_name name;
158         
159         name.name = lp_workgroup();
160         name.type = NBT_NAME_LOGON;
161         name.scope = NULL;
162
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));
167
168         myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
169
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");
173
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,
182                                                              myaddress, 0);
183                 torture_assert(tctx, socket_address != NULL, "Error getting address");
184
185                 socket_listen(dgmsock->sock, socket_address, 0, 0);
186         }
187
188         /* setup a temporary mailslot listener for replies */
189         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
190                                       netlogon_handler, &replies);
191         
192
193         ZERO_STRUCT(logon);
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;
202
203         make_nbt_name_client(&myname, TEST_NAME);
204
205         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
206                                            address, 0);
207
208         torture_assert(tctx, dest != NULL, "Error getting address");
209         status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
210                                               &myname, &logon);
211         torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
212
213         while (timeval_elapsed(&tv) < 5 && replies == 0) {
214                 event_loop_once(dgmsock->event_ctx);
215         }
216
217         return true;
218 }
219
220
221 /*
222   reply handler for ntlogon request
223 */
224 static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot, 
225                              struct nbt_dgram_packet *packet, 
226                              struct socket_address *src)
227 {
228         NTSTATUS status;
229         struct nbt_ntlogon_packet ntlogon;
230         int *replies = (int *)dgmslot->private;
231
232         printf("ntlogon reply from %s:%d\n", src->addr, src->port);
233
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);
238                 return;
239         }
240
241         NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
242
243         (*replies)++;
244 }
245
246
247 /* test UDP/138 ntlogon requests */
248 static bool nbt_test_ntlogon(struct torture_context *tctx)
249 {
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;
256
257         const char *myaddress;
258         struct nbt_ntlogon_packet logon;
259         struct nbt_name myname;
260         NTSTATUS status;
261         struct timeval tv = timeval_current();
262         int replies = 0;
263
264         struct socket_address *socket_address;
265         const char *address;
266         struct nbt_name name;
267         
268         name.name = lp_workgroup();
269         name.type = NBT_NAME_LOGON;
270         name.scope = NULL;
271
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));
276
277         myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
278
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");
282
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,
291                                                              myaddress, 0);
292                 torture_assert(tctx, socket_address != NULL, "Error getting address");
293
294                 socket_listen(dgmsock->sock, socket_address, 0, 0);
295         }
296
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));
302
303         dom_sid = torture_join_sid(join_ctx);
304
305         /* setup a temporary mailslot listener for replies */
306         dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
307                                       ntlogon_handler, &replies);
308         
309
310         ZERO_STRUCT(logon);
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;
321
322         make_nbt_name_client(&myname, TEST_NAME);
323
324         dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name, 
325                                            address, 0);
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");
330
331         while (timeval_elapsed(&tv) < 5 && replies == 0) {
332                 event_loop_once(dgmsock->event_ctx);
333         }
334
335         torture_leave_domain(join_ctx);
336         return true;
337 }
338
339
340 /*
341   test nbt dgram operations
342 */
343 struct torture_suite *torture_nbt_dgram(void)
344 {
345         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "DGRAM");
346
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);
350
351         return suite;
352 }