added netr_LogonControl() and netr_GetAnyDCName()
[ira/wip.git] / source4 / torture / rpc / netlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon rpc operations
5
6    Copyright (C) Andrew Tridgell 2003
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
25
26 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
27 {
28         NTSTATUS status;
29         struct netr_LogonUasLogon r;
30
31         r.in.server_name = NULL;
32         r.in.username = lp_parm_string(-1, "torture", "username");
33         r.in.workstation = lp_netbios_name();
34
35         printf("Testing LogonUasLogon\n");
36
37         status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
38         if (!NT_STATUS_IS_OK(status)) {
39                 printf("LogonUasLogon - %s\n", nt_errstr(status));
40                 return False;
41         }
42
43         return True;
44         
45 }
46
47 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
48 {
49         NTSTATUS status;
50         struct netr_LogonUasLogoff r;
51
52         r.in.server_name = NULL;
53         r.in.username = lp_parm_string(-1, "torture", "username");
54         r.in.workstation = lp_netbios_name();
55
56         printf("Testing LogonUasLogoff\n");
57
58         status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
59         if (!NT_STATUS_IS_OK(status)) {
60                 printf("LogonUasLogoff - %s\n", nt_errstr(status));
61                 return False;
62         }
63
64         return True;
65         
66 }
67
68 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
69                                   struct netr_CredentialState *creds)
70 {
71         NTSTATUS status;
72         struct netr_ServerReqChallenge r;
73         struct netr_ServerAuthenticate a;
74         const char *plain_pass;
75         uint8 mach_pwd[16];
76
77         printf("Testing ServerReqChallenge\n");
78
79         r.in.server_name = NULL;
80         r.in.computer_name = lp_netbios_name();
81         generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
82
83         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
84         if (!NT_STATUS_IS_OK(status)) {
85                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
86                 return False;
87         }
88
89         plain_pass = secrets_fetch_machine_password();
90         if (!plain_pass) {
91                 printf("Unable to fetch machine password!\n");
92                 return False;
93         }
94
95         E_md4hash(plain_pass, mach_pwd);
96
97         creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
98                           &a.in.credentials);
99
100         a.in.server_name = NULL;
101         a.in.username = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name());
102         a.in.secure_challenge_type = SEC_CHAN_BDC;
103         a.in.computer_name = lp_netbios_name();
104
105         printf("Testing ServerAuthenticate\n");
106
107         status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
108         if (!NT_STATUS_IS_OK(status)) {
109                 printf("ServerAuthenticate - %s\n", nt_errstr(status));
110                 return False;
111         }
112
113         if (!creds_client_check(creds, &a.out.credentials)) {
114                 printf("Credential chaining failed\n");
115                 return False;
116         }
117
118         return True;
119 }
120
121 /*
122   try a netlogon SamLogon
123 */
124 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
125 {
126         NTSTATUS status;
127         struct netr_LogonSamLogon r;
128         struct netr_Authenticator auth, auth2;
129         struct netr_NetworkInfo ninfo;
130         const char *username = lp_parm_string(-1, "torture", "username");
131         const char *password = lp_parm_string(-1, "torture", "password");
132         struct netr_CredentialState creds;
133
134         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
135                 return False;
136         }
137
138         ninfo.logon_info.domain_name.string = lp_workgroup();
139         ninfo.logon_info.parameter_control = 0;
140         ninfo.logon_info.logon_id_low = 0;
141         ninfo.logon_info.logon_id_high = 0;
142         ninfo.logon_info.username.string = username;
143         ninfo.logon_info.workstation.string = lp_netbios_name();
144         generate_random_buffer(ninfo.challenge, 
145                                sizeof(ninfo.challenge), False);
146         ninfo.nt.length = 24;
147         ninfo.nt.data = talloc(mem_ctx, 24);
148         SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
149         ninfo.lm.length = 24;
150         ninfo.lm.data = talloc(mem_ctx, 24);
151         SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
152
153         ZERO_STRUCT(auth2);
154
155         creds_client_authenticator(&creds, &auth);
156
157         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
158         r.in.workstation = lp_netbios_name();
159         r.in.credential = &auth;
160         r.in.authenticator = &auth2;
161         r.in.logon_level = 2;
162         r.in.logon.network = &ninfo;
163         r.in.validation_level = 2;
164
165         printf("Testing SamLogon\n");
166
167         status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
168         if (!NT_STATUS_IS_OK(status)) {
169                 printf("LogonSamLogon - %s\n", nt_errstr(status));
170                 return False;
171         }
172
173         if (!creds_client_check(&creds, &r.out.authenticator->cred)) {
174                 printf("Credential chaining failed\n");
175         }
176
177         return True;
178 }
179
180
181 /*
182   try a change password for our machine account
183 */
184 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
185 {
186         NTSTATUS status;
187         struct netr_ServerPasswordSet r;
188         const char *password;
189         struct netr_CredentialState creds;
190
191         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
192                 return False;
193         }
194
195         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
196         r.in.username = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name());
197         r.in.secure_challenge_type = SEC_CHAN_BDC;
198         r.in.computer_name = lp_netbios_name();
199
200         password = generate_random_str(8);
201         E_md4hash(password, r.in.new_password.data);
202
203         creds_client_encrypt(&creds, &r.in.new_password);
204
205         printf("Testing ServerPasswordSet on machine account\n");
206
207         creds_client_authenticator(&creds, &r.in.credential);
208
209         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
210         if (!NT_STATUS_IS_OK(status)) {
211                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
212                 return False;
213         }
214
215         if (!secrets_store_machine_password(password)) {
216                 printf("Failed to save machine password\n");
217         }
218
219         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
220                 printf("Credential chaining failed\n");
221         }
222
223         /* by changing the machine password twice we test the credentials
224            chaining fully */
225         printf("Testing a second ServerPasswordSet on machine account\n");
226
227         creds_client_authenticator(&creds, &r.in.credential);
228
229         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
230         if (!NT_STATUS_IS_OK(status)) {
231                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
232                 return False;
233         }
234
235         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
236                 printf("Credential chaining failed\n");
237         }
238
239         return True;
240 }
241
242
243 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
244 static struct ULONG8 sequence_nums[3];
245
246 /*
247   try a netlogon DatabaseSync
248 */
249 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
250 {
251         NTSTATUS status;
252         struct netr_DatabaseSync r;
253         struct netr_CredentialState creds;
254         const uint32 database_ids[] = {0, 1, 2}; 
255         int i;
256         BOOL ret = True;
257
258         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
259                 return False;
260         }
261
262         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
263         r.in.computername = lp_netbios_name();
264         r.in.preferredmaximumlength = (uint32)-1;
265         ZERO_STRUCT(r.in.return_authenticator);
266
267         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
268                 r.in.sync_context = 0;
269                 r.in.database_id = database_ids[i];
270
271                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
272
273                 do {
274                         creds_client_authenticator(&creds, &r.in.credential);
275
276                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
277                         if (!NT_STATUS_IS_OK(status) &&
278                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
279                                 printf("DatabaseSync - %s\n", nt_errstr(status));
280                                 ret = False;
281                                 break;
282                         }
283
284                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
285                                 printf("Credential chaining failed\n");
286                         }
287
288                         r.in.sync_context = r.out.sync_context;
289
290                         if (r.out.delta_enum_array &&
291                             r.out.delta_enum_array->num_deltas > 0 &&
292                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
293                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
294                                 sequence_nums[r.in.database_id] = 
295                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
296                                 printf("\tsequence_nums[%d]=0x%08x%08x\n",
297                                        r.in.database_id, 
298                                        sequence_nums[r.in.database_id].high,
299                                        sequence_nums[r.in.database_id].low);
300                         }
301                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
302         }
303
304         return ret;
305 }
306
307
308 /*
309   try a netlogon DatabaseDeltas
310 */
311 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
312 {
313         NTSTATUS status;
314         struct netr_DatabaseDeltas r;
315         struct netr_CredentialState creds;
316         const uint32 database_ids[] = {0, 1, 2}; 
317         int i;
318         BOOL ret = True;
319
320         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
321                 return False;
322         }
323
324         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
325         r.in.computername = lp_netbios_name();
326         r.in.preferredmaximumlength = (uint32)-1;
327         ZERO_STRUCT(r.in.return_authenticator);
328
329         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
330                 r.in.database_id = database_ids[i];
331                 r.in.sequence_num = sequence_nums[r.in.database_id];
332                 r.in.sequence_num.low -= 1;
333
334                 printf("Testing DatabaseDeltas of id %d at %d\n", 
335                        r.in.database_id, r.in.sequence_num.low);
336
337                 do {
338                         creds_client_authenticator(&creds, &r.in.credential);
339
340                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
341                         if (!NT_STATUS_IS_OK(status) &&
342                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
343                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
344                                 ret = False;
345                                 break;
346                         }
347
348                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
349                                 printf("Credential chaining failed\n");
350                         }
351
352                         r.in.sequence_num.low++;
353                         r.in.sequence_num.high = 0;
354                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
355         }
356
357         return ret;
358 }
359
360
361 /*
362   try a netlogon AccountDeltas
363 */
364 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
365 {
366         NTSTATUS status;
367         struct netr_AccountDeltas r;
368         struct netr_CredentialState creds;
369         BOOL ret = True;
370
371         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
372                 return False;
373         }
374
375         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
376         r.in.computername = lp_netbios_name();
377         ZERO_STRUCT(r.in.return_authenticator);
378         creds_client_authenticator(&creds, &r.in.credential);
379         ZERO_STRUCT(r.in.uas);
380         r.in.count=10;
381         r.in.level=0;
382         r.in.buffersize=100;
383
384         printf("Testing AccountDeltas\n");
385
386         /* w2k3 returns "NOT IMPLEMENTED" for this call */
387         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
388         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
389                 printf("AccountDeltas - %s\n", nt_errstr(status));
390                 ret = False;
391         }
392
393         return ret;
394 }
395
396 /*
397   try a netlogon AccountSync
398 */
399 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
400 {
401         NTSTATUS status;
402         struct netr_AccountSync r;
403         struct netr_CredentialState creds;
404         BOOL ret = True;
405
406         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
407                 return False;
408         }
409
410         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
411         r.in.computername = lp_netbios_name();
412         ZERO_STRUCT(r.in.return_authenticator);
413         creds_client_authenticator(&creds, &r.in.credential);
414         ZERO_STRUCT(r.in.recordid);
415         r.in.reference=0;
416         r.in.level=0;
417         r.in.buffersize=100;
418
419         printf("Testing AccountSync\n");
420
421         /* w2k3 returns "NOT IMPLEMENTED" for this call */
422         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
423         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
424                 printf("AccountSync - %s\n", nt_errstr(status));
425                 ret = False;
426         }
427
428         return ret;
429 }
430
431 /*
432   try a netlogon GetDcName
433 */
434 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
435 {
436         NTSTATUS status;
437         struct netr_GetDcName r;
438
439         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
440         r.in.domainname = lp_workgroup();
441
442         printf("Testing GetDcName\n");
443
444         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
445         if (!NT_STATUS_IS_OK(status)) {
446                 printf("GetDcName - %s\n", nt_errstr(status));
447                 return False;
448         }
449
450         printf("\tDC is at '%s'\n", r.out.dcname);
451
452         return True;
453 }
454
455 /*
456   try a netlogon LogonControl 
457 */
458 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
459 {
460         NTSTATUS status;
461         struct netr_LogonControl r;
462         BOOL ret = True;
463         int i;
464
465         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
466         r.in.function_code = 1;
467
468         for (i=1;i<4;i++) {
469                 r.in.level = i;
470
471                 printf("Testing LogonControl level %d\n", i);
472
473                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
474                 if (!NT_STATUS_IS_OK(status)) {
475                         printf("LogonControl - %s\n", nt_errstr(status));
476                         ret = False;
477                 }
478         }
479
480         return ret;
481 }
482
483
484 /*
485   try a netlogon GetAnyDCName
486 */
487 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
488 {
489         NTSTATUS status;
490         struct netr_GetAnyDCName r;
491
492         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
493         r.in.domainname = lp_workgroup();
494
495         printf("Testing GetAnyDCName\n");
496
497         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
498         if (!NT_STATUS_IS_OK(status)) {
499                 printf("GetAnyDCName - %s\n", nt_errstr(status));
500                 return False;
501         }
502
503         if (r.out.dcname) {
504                 printf("\tDC is at '%s'\n", r.out.dcname);
505         }
506
507         return True;
508 }
509
510
511 BOOL torture_rpc_netlogon(int dummy)
512 {
513         NTSTATUS status;
514         struct dcerpc_pipe *p;
515         TALLOC_CTX *mem_ctx;
516         BOOL ret = True;
517
518         mem_ctx = talloc_init("torture_rpc_netlogon");
519
520         status = torture_rpc_connection(&p, 
521                                         DCERPC_NETLOGON_NAME,
522                                         DCERPC_NETLOGON_UUID,
523                                         DCERPC_NETLOGON_VERSION);
524         if (!NT_STATUS_IS_OK(status)) {
525                 return False;
526         }
527         
528         p->flags |= DCERPC_DEBUG_PRINT_BOTH;
529
530         if (!test_LogonUasLogon(p, mem_ctx)) {
531                 ret = False;
532         }
533
534         if (!test_LogonUasLogoff(p, mem_ctx)) {
535                 ret = False;
536         }
537
538         if (!test_SetPassword(p, mem_ctx)) {
539                 ret = False;
540         }
541
542         if (!test_SamLogon(p, mem_ctx)) {
543                 ret = False;
544         }
545
546         if (!test_DatabaseSync(p, mem_ctx)) {
547                 ret = False;
548         }
549
550         if (!test_DatabaseDeltas(p, mem_ctx)) {
551                 ret = False;
552         }
553
554         if (!test_AccountDeltas(p, mem_ctx)) {
555                 ret = False;
556         }
557
558         if (!test_AccountSync(p, mem_ctx)) {
559                 ret = False;
560         }
561
562         if (!test_GetDcName(p, mem_ctx)) {
563                 ret = False;
564         }
565
566         if (!test_LogonControl(p, mem_ctx)) {
567                 ret = False;
568         }
569
570         if (!test_GetAnyDCName(p, mem_ctx)) {
571                 ret = False;
572         }
573
574         torture_rpc_close(p);
575
576         return ret;
577 }