r4758: - added async support to the session request code
[jelmer/samba4-debian.git] / source / torture / rpc / xplogin.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Test code to simulate an XP logon.
5
6    Copyright (C) Volker Lendecke 2004
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/auth/credentials.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "librpc/gen_ndr/ndr_samr.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "librpc/gen_ndr/ndr_srvsvc.h"
29
30 static int destroy_transport(void *ptr)
31 {
32         struct smbcli_transport *trans = ptr;
33         talloc_free(trans->socket);
34         return 0;
35 }
36
37 static NTSTATUS after_negprot(struct smbcli_transport **dst_transport,
38                               const char *dest_host, uint16_t port,
39                               const char *my_name)
40 {
41         struct smbcli_socket *sock;
42         struct smbcli_transport *transport;
43         NTSTATUS status;
44
45         sock = smbcli_sock_init(NULL);
46         if (sock == NULL)
47                 return NT_STATUS_NO_MEMORY;
48
49         if (!smbcli_sock_connect_byname(sock, dest_host, port)) {
50                 talloc_free(sock);
51                 DEBUG(2,("Failed to establish socket connection - %s\n",
52                          strerror(errno)));
53                 return NT_STATUS_UNSUCCESSFUL;
54         }
55
56         transport = smbcli_transport_init(sock);
57         talloc_free(sock);
58         if (transport == NULL)
59                 return NT_STATUS_NO_MEMORY;
60
61         talloc_set_destructor(transport, destroy_transport);
62
63         {
64                 struct nmb_name calling;
65                 struct nmb_name called;
66
67                 /* send a NBT session request, if applicable */
68                 make_nmb_name(&calling, my_name, 0x0);
69                 choose_called_name(&called, dest_host, 0x20);
70
71                 if (!smbcli_transport_connect(transport, &calling, &called)) {
72                         talloc_free(transport);
73                         return NT_STATUS_NO_MEMORY;
74                 }
75         }
76
77         /* negotiate protocol options with the server */
78         status = smb_raw_negotiate(transport, lp_maxprotocol());
79         if (!NT_STATUS_IS_OK(status)) {
80                 talloc_free(transport);
81                 return NT_STATUS_UNSUCCESSFUL;
82         }
83
84         *dst_transport = transport;
85
86         return NT_STATUS_OK;
87 }
88
89 static int destroy_session(void *ptr)
90 {
91         struct smbcli_session *session = ptr;
92         smb_raw_ulogoff(session);
93         return 0;
94 }
95
96 static int destroy_tree_and_session(void *ptr)
97 {
98         struct smbcli_tree *tree = ptr;
99         smb_tree_disconnect(tree);
100         talloc_free(tree->session);
101         return 0;
102 }
103
104 static NTSTATUS anon_ipc(struct smbcli_transport *transport,
105                          struct smbcli_tree **dst_tree)
106 {
107         struct smbcli_tree *tree;
108         struct smbcli_session *session;
109         union smb_sesssetup setup;
110         union smb_tcon tcon;
111         TALLOC_CTX *mem_ctx;
112         NTSTATUS status;
113
114         session = smbcli_session_init(transport);
115         if (session == NULL)
116                 return NT_STATUS_NO_MEMORY;
117
118         mem_ctx = talloc_init("session_init");
119         if (mem_ctx == NULL) {
120                 talloc_free(session);
121                 return NT_STATUS_NO_MEMORY;
122         }
123
124         /* prepare a session setup to establish a security context */
125         setup.generic.level = RAW_SESSSETUP_GENERIC;
126         setup.generic.in.sesskey = transport->negotiate.sesskey;
127         setup.generic.in.capabilities = transport->negotiate.capabilities;
128         setup.generic.in.password = NULL;
129         setup.generic.in.user = "";
130         setup.generic.in.domain = "";
131         setup.generic.in.capabilities &= ~CAP_EXTENDED_SECURITY;
132
133         status = smb_raw_session_setup(session, mem_ctx, &setup);
134         if (!NT_STATUS_IS_OK(status)) {
135                 talloc_free(session);
136                 talloc_free(mem_ctx);
137                 return NT_STATUS_UNSUCCESSFUL;
138         }
139
140         session->vuid = setup.generic.out.vuid;
141
142         talloc_set_destructor(session, destroy_session);
143
144         tree = smbcli_tree_init(session);
145         talloc_free(session);
146         if (tree == NULL) {
147                 talloc_free(mem_ctx);
148                 return NT_STATUS_NO_MEMORY;
149         }
150
151         tcon.generic.level = RAW_TCON_TCONX;
152         tcon.tconx.in.flags = 0;
153         tcon.tconx.in.password = data_blob(NULL, 0);
154         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\IPC$",
155                                             transport->called.name);
156         tcon.tconx.in.device = "IPC";
157
158         status = smb_tree_connect(tree, mem_ctx, &tcon);
159
160         if (!NT_STATUS_IS_OK(status)) {
161                 talloc_free(tree);
162                 talloc_free(mem_ctx);
163                 return NT_STATUS_UNSUCCESSFUL;
164         }
165
166         tree->tid = tcon.tconx.out.tid;
167
168         if (tcon.tconx.out.dev_type != NULL)
169                 tree->device = talloc_strdup(tree, tcon.tconx.out.dev_type);
170
171         if (tcon.tconx.out.fs_type != NULL)
172                 tree->fs_type = talloc_strdup(tree, tcon.tconx.out.fs_type);
173
174         talloc_set_destructor(tree, destroy_tree_and_session);
175
176         talloc_free(mem_ctx);
177
178         *dst_tree = tree;
179
180         return NT_STATUS_OK;
181 }
182
183 static NTSTATUS connect_to_pipe(struct dcerpc_pipe **pp,
184                                 TALLOC_CTX *mem_ctx,
185                                 struct smbcli_transport *transport,
186                                 const char *pipe_name,
187                                 const char *pipe_uuid,
188                                 uint32_t pipe_version)
189 {
190         const char *binding = lp_parm_string(-1, "torture", "binding");
191         struct dcerpc_binding b;
192         NTSTATUS status;
193         struct dcerpc_pipe *p;
194         TALLOC_CTX *tmp_ctx;
195         struct smbcli_tree *tree;
196         
197         if (!NT_STATUS_IS_OK(status = anon_ipc(transport, &tree)))
198                 return status;
199
200         if (binding == NULL)
201                 return NT_STATUS_INVALID_PARAMETER;
202
203         p = dcerpc_pipe_init(mem_ctx);
204         if (p == NULL) {
205                 return NT_STATUS_NO_MEMORY;
206         }
207         tmp_ctx = talloc_new(p);
208
209         status = dcerpc_parse_binding(tmp_ctx, binding, &b);
210         if (!NT_STATUS_IS_OK(status)) {
211                 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
212                 talloc_free(p);
213                 return status;
214         }
215
216         DEBUG(3,("Using binding %s\n", dcerpc_binding_string(tmp_ctx, &b)));
217
218         if (b.endpoint == NULL) {
219                 const struct dcerpc_interface_table *table =
220                         idl_iface_by_uuid(pipe_uuid);
221                 struct dcerpc_binding default_binding;
222                 int i;
223
224                 if (!table) {
225                         DEBUG(0,("Unknown interface endpoint '%s'\n",
226                                  pipe_uuid));
227                         talloc_free(tmp_ctx);
228                         return NT_STATUS_INVALID_PARAMETER;
229                 }
230
231                 /* Find one of the default pipes for this interface */
232                 for (i = 0; i < table->endpoints->count; i++) {
233                         const char * const *names = table->endpoints->names;
234                         status = dcerpc_parse_binding(tmp_ctx, names[i],
235                                                       &default_binding);
236
237                         if (NT_STATUS_IS_OK(status) &&
238                             default_binding.transport == NCACN_NP) {
239                                 pipe_name = default_binding.endpoint;   
240                                 break;
241                         }
242                 }
243         } else {
244                 pipe_name = b.endpoint;
245         }
246
247         if (!strncasecmp(pipe_name, "/pipe/", 6) || 
248                 !strncasecmp(pipe_name, "\\pipe\\", 6)) {
249                 pipe_name += 6;
250         }
251
252         if (pipe_name[0] != '\\') {
253                 pipe_name = talloc_asprintf(mem_ctx, "\\%s", pipe_name);
254         }
255         
256         status = dcerpc_pipe_open_smb(p->conn, tree, pipe_name);
257
258         if (!NT_STATUS_IS_OK(status)) {
259                 talloc_free(p);
260                 return status;
261         }
262
263         talloc_free(tmp_ctx);
264         (*pp) = p;
265         
266         return NT_STATUS_OK;
267 }
268
269 static NTSTATUS test_enumtrusts(struct smbcli_transport *transport)
270 {
271         struct policy_handle handle;
272         struct lsa_EnumTrustDom r2;
273         uint32_t resume_handle = 0;
274         struct lsa_ObjectAttribute attr;
275         struct lsa_OpenPolicy2 r1;
276         struct lsa_DomainList domains;
277         TALLOC_CTX *mem_ctx;
278         NTSTATUS status;
279         struct dcerpc_pipe *p;
280
281         mem_ctx = talloc_init("test_enumtrusts");
282         if (mem_ctx == NULL)
283                 return NT_STATUS_NO_MEMORY;
284
285         status = connect_to_pipe(&p, mem_ctx, transport, DCERPC_LSARPC_NAME,
286                                  DCERPC_LSARPC_UUID, 
287                                  DCERPC_LSARPC_VERSION);
288
289         if (!NT_STATUS_IS_OK(status)) {
290                 talloc_destroy(mem_ctx);
291                 return status;
292         }
293
294         status = dcerpc_bind_auth_none(p, DCERPC_LSARPC_UUID,
295                                        DCERPC_LSARPC_VERSION);
296
297         if (!NT_STATUS_IS_OK(status))
298                 return status;
299
300         printf("\ntesting OpenPolicy2\n");
301
302         attr.len = 0;
303         attr.root_dir = NULL;
304         attr.object_name = NULL;
305         attr.attributes = 0;
306         attr.sec_desc = NULL;
307         attr.sec_qos = NULL;
308
309         r1.in.system_name = talloc_asprintf(mem_ctx,
310                                             "\\\\%s", dcerpc_server_name(p));
311         r1.in.attr = &attr;
312         r1.in.access_mask = 1;
313         r1.out.handle = &handle;
314
315         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r1);
316         if (!NT_STATUS_IS_OK(status)) {
317                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
318                 return status;
319         }
320
321         printf("\nTesting EnumTrustDom\n");
322
323         r2.in.handle = &handle;
324         r2.in.resume_handle = &resume_handle;
325         r2.in.max_size = 1000;
326         r2.out.domains = &domains;
327         r2.out.resume_handle = &resume_handle;
328
329         status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r2);
330
331         if (!NT_STATUS_IS_OK(status) &&
332             !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES))
333                 return status;
334
335         talloc_free(p);
336
337         talloc_destroy(mem_ctx);
338
339         return NT_STATUS_OK;
340 }
341
342 static NTSTATUS test_lookupnames(struct smbcli_transport *transport,
343                                  const char *name)
344 {
345         struct policy_handle handle;
346         struct lsa_ObjectAttribute attr;
347         struct lsa_OpenPolicy2 r1;
348         TALLOC_CTX *mem_ctx;
349         NTSTATUS status;
350         struct dcerpc_pipe *p;
351
352         mem_ctx = talloc_init("test_lookupnames");
353         if (mem_ctx == NULL)
354                 return NT_STATUS_NO_MEMORY;
355
356         status = connect_to_pipe(&p, mem_ctx, transport, DCERPC_LSARPC_NAME,
357                                  DCERPC_LSARPC_UUID, 
358                                  DCERPC_LSARPC_VERSION);
359
360         if (!NT_STATUS_IS_OK(status)) {
361                 talloc_destroy(mem_ctx);
362                 return status;
363         }
364
365         status = dcerpc_bind_auth_none(p, DCERPC_LSARPC_UUID,
366                                        DCERPC_LSARPC_VERSION);
367
368         if (!NT_STATUS_IS_OK(status))
369                 return status;
370
371         attr.len = 0;
372         attr.root_dir = NULL;
373         attr.object_name = NULL;
374         attr.attributes = 0;
375         attr.sec_desc = NULL;
376         attr.sec_qos = NULL;
377
378         r1.in.system_name = talloc_asprintf(mem_ctx,
379                                             "\\\\%s", dcerpc_server_name(p));
380         r1.in.attr = &attr;
381         r1.in.access_mask = 0x801;
382         r1.out.handle = &handle;
383
384         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r1);
385         if (!NT_STATUS_IS_OK(status)) {
386                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
387                 return status;
388         }
389
390         {
391                 struct lsa_LookupNames l;
392                 struct lsa_TransSidArray sids;
393                 struct lsa_String lsaname;
394                 uint32_t count = 0;
395
396                 sids.count = 0;
397                 sids.sids = NULL;
398
399                 lsaname.string = name;
400
401                 l.in.handle = &handle;
402                 l.in.num_names = 1;
403                 l.in.names = &lsaname;
404                 l.in.sids = &sids;
405                 l.in.level = 2;
406                 l.in.count = &count;
407                 l.out.count = &count;
408                 l.out.sids = &sids;
409
410                 status = dcerpc_lsa_LookupNames(p, mem_ctx, &l);
411                 if (!NT_STATUS_IS_OK(status) &&
412                     !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
413                         printf("LookupNames failed - %s\n", nt_errstr(status));
414                         talloc_free(p);
415                         talloc_destroy(mem_ctx);
416                         return NT_STATUS_OK;
417                 }
418         }
419
420         {
421                 struct lsa_Close c;
422                 struct policy_handle handle2;
423
424                 c.in.handle = &handle;
425                 c.out.handle = &handle2;
426
427                 status = dcerpc_lsa_Close(p, mem_ctx, &c);
428                 if (!NT_STATUS_IS_OK(status)) {
429                         printf("Close failed - %s\n", nt_errstr(status));
430                         return status;
431                 }
432         }
433
434         talloc_free(p);
435
436         talloc_destroy(mem_ctx);
437
438         return NT_STATUS_OK;
439 }
440
441 static NTSTATUS setup_netlogon_creds(struct smbcli_transport *transport,
442                                      struct dcerpc_pipe **p,
443                                      const char *machine_name,
444                                      const char *domain,
445                                      const char *machine_pwd,
446                                      struct creds_CredentialState *creds)
447 {
448         NTSTATUS status;
449         TALLOC_CTX *mem_ctx;
450         struct netr_ServerReqChallenge r;
451         struct netr_ServerAuthenticate2 a;
452         struct netr_Credential credentials1, credentials2, credentials3;
453         const char *plain_pass;
454         struct samr_Password mach_password;
455         uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
456
457         
458         mem_ctx = talloc_init("torture_rpc_login");
459
460         if (mem_ctx == NULL)
461                 return NT_STATUS_NO_MEMORY;
462
463         status = connect_to_pipe(p, mem_ctx, transport, DCERPC_NETLOGON_NAME,
464                                  DCERPC_NETLOGON_UUID,
465                                  DCERPC_NETLOGON_VERSION);
466
467         if (!NT_STATUS_IS_OK(status)) {
468                 talloc_destroy(mem_ctx);
469                 return status;
470         }
471
472         status = dcerpc_bind_auth_none(*p, DCERPC_NETLOGON_UUID,
473                                        DCERPC_NETLOGON_VERSION);
474
475         if (!NT_STATUS_IS_OK(status))
476                 return status;
477
478         printf("Testing ServerReqChallenge\n");
479
480         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s",
481                                            dcerpc_server_name(*p));
482         r.in.computer_name = machine_name;
483         r.in.credentials = &credentials1;
484         r.out.credentials = &credentials2;
485
486         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
487
488         status = dcerpc_netr_ServerReqChallenge(*p, mem_ctx, &r);
489         if (!NT_STATUS_IS_OK(status)) {
490                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
491                 return status;
492         }
493
494         plain_pass = machine_pwd;
495         if (!plain_pass) {
496                 printf("Unable to fetch machine password!\n");
497                 return status;
498         }
499
500         E_md4hash(plain_pass, mach_password.hash);
501
502         a.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s",
503                                            dcerpc_server_name(*p));
504         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
505         a.in.secure_channel_type = SEC_CHAN_WKSTA;
506         a.in.computer_name = machine_name;
507         a.in.negotiate_flags = &negotiate_flags;
508         a.out.negotiate_flags = &negotiate_flags;
509         a.in.credentials = &credentials3;
510         a.out.credentials = &credentials3;
511
512         creds_client_init(creds, &credentials1, &credentials2,
513                           &mach_password, &credentials3, 
514                           negotiate_flags);
515
516         printf("Testing ServerAuthenticate2\n");
517
518         status = dcerpc_netr_ServerAuthenticate2(*p, mem_ctx, &a);
519         if (!NT_STATUS_IS_OK(status)) {
520                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
521                 return status;
522         }
523
524         if (!creds_client_check(creds, &credentials3)) {
525                 printf("Credential chaining failed\n");
526                 return status;
527         }
528
529         printf("negotiate_flags=0x%08x\n", negotiate_flags);
530
531         talloc_free(mem_ctx);
532         return NT_STATUS_OK;
533 }
534
535 static NTSTATUS torture_samlogon(struct dcerpc_pipe *p,
536                                  struct creds_CredentialState *netlogon_creds,
537                                  const char *workstation,
538                                  const char *domain,
539                                  const char *username,
540                                  const char *password)
541 {
542         TALLOC_CTX *mem_ctx;
543         struct netr_LogonSamLogon log;
544         struct netr_NetworkInfo ninfo;
545         struct netr_Authenticator auth, auth2;
546         uint8_t user_session_key[16];
547         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
548         DATA_BLOB lmv2_response = data_blob(NULL, 0);
549         DATA_BLOB names_blob;
550         DATA_BLOB chall;
551         NTSTATUS status;
552
553         mem_ctx = talloc_init("torture_samlogon");
554
555         ZERO_STRUCT(user_session_key);
556
557         printf("testing netr_LogonSamLogon\n");
558
559         log.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s",
560                                              dcerpc_server_name(p));
561         log.in.workstation = workstation;
562         log.in.credential = &auth;
563         log.in.return_authenticator = &auth2;
564         log.in.validation_level = 3;
565         log.in.logon_level = 2;
566         log.in.logon.network = &ninfo;
567
568         chall = data_blob_talloc(mem_ctx, NULL, 8);
569         generate_random_buffer(chall.data, 8);  
570
571         names_blob = NTLMv2_generate_names_blob(mem_ctx, workstation,
572                                                 lp_workgroup());
573         ZERO_STRUCT(user_session_key);
574
575         if (!SMBNTLMv2encrypt(username, domain, password,
576                               &chall, &names_blob,
577                               &lmv2_response, &ntlmv2_response, 
578                               NULL, NULL)) {
579                 data_blob_free(&names_blob);
580                 talloc_destroy(mem_ctx);
581                 return NT_STATUS_UNSUCCESSFUL;
582         }
583         data_blob_free(&names_blob);
584
585         ninfo.identity_info.domain_name.string = domain;
586         ninfo.identity_info.parameter_control = 0;
587         ninfo.identity_info.logon_id_low = 0;
588         ninfo.identity_info.logon_id_high = 0;
589         ninfo.identity_info.account_name.string = username;
590         ninfo.identity_info.workstation.string = workstation;
591         memcpy(ninfo.challenge, chall.data, 8);
592         ninfo.nt.data = ntlmv2_response.data;
593         ninfo.nt.length = ntlmv2_response.length;
594         ninfo.lm.data = NULL;
595         ninfo.lm.length = 0;
596
597         ZERO_STRUCT(auth2);
598         creds_client_authenticator(netlogon_creds, &auth);
599
600         log.out.return_authenticator = NULL;
601         status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &log);
602         talloc_destroy(mem_ctx);
603         data_blob_free(&lmv2_response);
604         data_blob_free(&ntlmv2_response);
605         return status;
606 }
607
608 static NTSTATUS test_getgroups(struct smbcli_transport *transport,
609                                const char *name)
610 {
611         TALLOC_CTX *mem_ctx;
612         NTSTATUS status;
613         struct dcerpc_pipe *p;
614
615         struct samr_Connect4 r4;
616         struct policy_handle connect_handle, domain_handle, user_handle;
617
618         mem_ctx = talloc_init("test_lookupnames");
619         if (mem_ctx == NULL)
620                 return NT_STATUS_NO_MEMORY;
621
622         status = connect_to_pipe(&p, mem_ctx, transport, DCERPC_SAMR_NAME,
623                                  DCERPC_SAMR_UUID, 
624                                  DCERPC_SAMR_VERSION);
625
626         if (!NT_STATUS_IS_OK(status)) {
627                 talloc_destroy(mem_ctx);
628                 return status;
629         }
630
631         status = dcerpc_bind_auth_none(p, DCERPC_SAMR_UUID,
632                                        DCERPC_SAMR_VERSION);
633
634         if (!NT_STATUS_IS_OK(status))
635                 return status;
636
637         r4.in.system_name = talloc_asprintf(mem_ctx, "\\\\%s",
638                                             dcerpc_server_name(p));
639         r4.in.unknown = 0;
640         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
641         r4.out.connect_handle = &connect_handle;
642
643         status = dcerpc_samr_Connect4(p, mem_ctx, &r4);
644         if (!NT_STATUS_IS_OK(status))
645                 return status;
646
647         {
648                 struct samr_EnumDomains e;
649                 uint32_t resume_handle = 0;
650                 int i;
651
652                 e.in.connect_handle = &connect_handle;
653                 e.in.resume_handle = &resume_handle;
654                 e.in.buf_size = (uint32_t)-1;
655                 e.out.resume_handle = &resume_handle;
656                 status = dcerpc_samr_EnumDomains(p, mem_ctx, &e);
657                 if (!NT_STATUS_IS_OK(status))
658                         return status;
659
660                 for (i=0; i<e.out.sam->count; i++) {
661
662                         struct samr_LookupDomain l;
663                         struct samr_OpenDomain o;
664
665                         if (strcmp(e.out.sam->entries[i].name.string,
666                                    "Builtin") == 0)
667                                 continue;
668
669                         l.in.connect_handle = &connect_handle;
670                         l.in.domain = &e.out.sam->entries[i].name;
671
672                         status = dcerpc_samr_LookupDomain(p, mem_ctx, &l);
673
674                         if (!NT_STATUS_IS_OK(status))
675                                 return status;
676
677                         o.in.connect_handle = &connect_handle;
678                         o.in.access_mask = 0x200;
679                         o.in.sid = l.out.sid;
680                         o.out.domain_handle = &domain_handle;
681
682                         status = dcerpc_samr_OpenDomain(p, mem_ctx, &o);
683
684                         if (!NT_STATUS_IS_OK(status))
685                                 return status;
686
687                         break;
688                 }
689         }
690
691         {
692                 struct samr_LookupNames l;
693                 struct samr_String samr_name;
694                 struct samr_OpenUser o;
695
696                 samr_name.string = name;
697
698                 l.in.domain_handle = &domain_handle;
699                 l.in.num_names = 1;
700                 l.in.names = &samr_name;
701
702                 status = dcerpc_samr_LookupNames(p, mem_ctx, &l);
703
704                 if (!NT_STATUS_IS_OK(status))
705                         return status;
706
707                 o.in.domain_handle = &domain_handle;
708                 o.in.rid = l.out.rids.ids[0];
709                 o.in.access_mask = 0x100;
710                 o.out.user_handle = &user_handle;
711
712                 status = dcerpc_samr_OpenUser(p, mem_ctx, &o);
713                 
714                 if (!NT_STATUS_IS_OK(status))
715                         return status;
716         }
717
718         {
719                 struct samr_GetGroupsForUser g;
720                 struct samr_LookupRids l;
721                 int i;
722
723                 g.in.user_handle = &user_handle;
724
725                 status = dcerpc_samr_GetGroupsForUser(p, mem_ctx, &g);
726                 if (!NT_STATUS_IS_OK(status))
727                         return status;
728
729                 l.in.domain_handle = &domain_handle;
730                 l.in.num_rids = g.out.rids->count;
731                 l.in.rids = talloc_array_p(mem_ctx, uint32_t, g.out.rids->count);
732
733                 for (i=0; i<g.out.rids->count; i++)
734                         l.in.rids[i] = g.out.rids->rid[i].rid;
735
736                 status = dcerpc_samr_LookupRids(p, mem_ctx, &l);
737                 if (!NT_STATUS_IS_OK(status)) {
738                         talloc_destroy(mem_ctx);
739                         return status;
740                 }
741         }
742
743         {
744                 struct samr_Close c;
745
746                 c.in.handle = &user_handle;
747                 c.out.handle = &user_handle;
748                 dcerpc_samr_Close(p, mem_ctx, &c);
749
750                 c.in.handle = &domain_handle;
751                 c.out.handle = &domain_handle;
752                 dcerpc_samr_Close(p, mem_ctx, &c);
753
754                 c.in.handle = &connect_handle;
755                 c.out.handle = &connect_handle;
756                 dcerpc_samr_Close(p, mem_ctx, &c);
757         }
758
759         talloc_free(p);
760         talloc_destroy(mem_ctx);
761
762         return NT_STATUS_OK;
763 }
764
765 static NTSTATUS test_getallsids(struct smbcli_transport *transport,
766                                 const char *name, BOOL includeDomain)
767 {
768         TALLOC_CTX *mem_ctx;
769         NTSTATUS status;
770         struct dcerpc_pipe *p;
771
772         struct samr_Connect4 r4;
773         struct policy_handle connect_handle, user_handle;
774         struct policy_handle builtin_handle, domain_handle;
775         struct dom_sid *domain_sid = NULL;
776
777         struct dom_sid *user_sid;
778         struct dom_sid *primary_group_sid;
779         struct samr_GetGroupsForUser g;
780
781
782         mem_ctx = talloc_init("test_getallsids");
783         if (mem_ctx == NULL)
784                 return NT_STATUS_NO_MEMORY;
785
786         status = connect_to_pipe(&p, mem_ctx, transport, DCERPC_SAMR_NAME,
787                                  DCERPC_SAMR_UUID, 
788                                  DCERPC_SAMR_VERSION);
789
790         if (!NT_STATUS_IS_OK(status)) {
791                 talloc_destroy(mem_ctx);
792                 return status;
793         }
794
795         status = dcerpc_bind_auth_none(p, DCERPC_SAMR_UUID,
796                                        DCERPC_SAMR_VERSION);
797
798         if (!NT_STATUS_IS_OK(status))
799                 return status;
800
801         r4.in.system_name = talloc_asprintf(mem_ctx, "\\\\%s",
802                                             dcerpc_server_name(p));
803         r4.in.unknown = 0;
804         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
805         r4.out.connect_handle = &connect_handle;
806
807         status = dcerpc_samr_Connect4(p, mem_ctx, &r4);
808         if (!NT_STATUS_IS_OK(status))
809                 return status;
810
811         {
812                 struct samr_EnumDomains e;
813                 struct samr_OpenDomain o;
814                 uint32_t resume_handle = 0;
815                 int i;
816
817                 e.in.connect_handle = &connect_handle;
818                 e.in.resume_handle = &resume_handle;
819                 e.in.buf_size = (uint32_t)-1;
820                 e.out.resume_handle = &resume_handle;
821                 status = dcerpc_samr_EnumDomains(p, mem_ctx, &e);
822                 if (!NT_STATUS_IS_OK(status))
823                         return status;
824
825                 for (i=0; i<e.out.sam->count; i++) {
826
827                         struct samr_LookupDomain l;
828
829                         if (strcmp(e.out.sam->entries[i].name.string,
830                                    "Builtin") == 0)
831                                 continue;
832
833                         l.in.connect_handle = &connect_handle;
834                         l.in.domain = &e.out.sam->entries[i].name;
835
836                         status = dcerpc_samr_LookupDomain(p, mem_ctx, &l);
837
838                         if (!NT_STATUS_IS_OK(status))
839                                 return status;
840
841                         o.in.connect_handle = &connect_handle;
842                         o.in.access_mask = 0x280;
843                         domain_sid = l.out.sid;
844                         o.in.sid = l.out.sid;
845                         o.out.domain_handle = &domain_handle;
846
847                         status = dcerpc_samr_OpenDomain(p, mem_ctx, &o);
848
849                         if (!NT_STATUS_IS_OK(status))
850                                 return status;
851                         break;
852                 }
853                 o.in.connect_handle = &connect_handle;
854                 o.in.access_mask = 0x280;
855                 o.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
856                 o.out.domain_handle = &builtin_handle;
857
858                 status = dcerpc_samr_OpenDomain(p, mem_ctx, &o);
859
860                 if (!NT_STATUS_IS_OK(status))
861                         return status;
862         }
863
864         {
865                 struct samr_LookupNames l;
866                 struct samr_String samr_name;
867                 struct samr_OpenUser o;
868
869                 samr_name.string = name;
870
871                 l.in.domain_handle = &domain_handle;
872                 l.in.num_names = 1;
873                 l.in.names = &samr_name;
874
875                 status = dcerpc_samr_LookupNames(p, mem_ctx, &l);
876
877                 if (!NT_STATUS_IS_OK(status))
878                         return status;
879
880                 o.in.domain_handle = &domain_handle;
881                 o.in.rid = l.out.rids.ids[0];
882                 o.in.access_mask = 0x100;
883                 o.out.user_handle = &user_handle;
884
885                 status = dcerpc_samr_OpenUser(p, mem_ctx, &o);
886                 
887                 if (!NT_STATUS_IS_OK(status))
888                         return status;
889         }
890
891         {
892                 struct samr_QueryUserInfo q;
893
894                 q.in.user_handle = &user_handle;
895                 q.in.level = 21;
896
897                 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
898
899                 if (!NT_STATUS_IS_OK(status))
900                         return status;
901
902                 user_sid = dom_sid_add_rid(mem_ctx, domain_sid,
903                                            q.out.info->info21.rid);
904                 primary_group_sid = dom_sid_add_rid(mem_ctx, domain_sid,
905                                                     q.out.info->info21.primary_gid);
906         }
907
908         g.in.user_handle = &user_handle;
909
910         status = dcerpc_samr_GetGroupsForUser(p, mem_ctx, &g);
911         if (!NT_STATUS_IS_OK(status))
912                 return status;
913
914         {
915                 struct lsa_SidArray sids;
916                 struct samr_Ids rids;
917                 struct samr_GetAliasMembership ga;
918                 int i;
919
920                 ga.in.domain_handle = &builtin_handle;
921
922                 sids.num_sids = g.out.rids->count+2;
923                 sids.sids = talloc_array_p(mem_ctx, struct lsa_SidPtr,
924                                            g.out.rids->count+2);
925                 sids.sids[0].sid = user_sid;
926                 sids.sids[1].sid = primary_group_sid;
927                 for (i=0; i<g.out.rids->count; i++) {
928                         sids.sids[i+2].sid = dom_sid_add_rid(mem_ctx,
929                                                              domain_sid,
930                                                              g.out.rids->rid[i].rid);
931                 }
932                 ga.in.sids = &sids;
933                 ga.out.rids = &rids;
934
935                 status = dcerpc_samr_GetAliasMembership(p, mem_ctx, &ga);
936                 if (!NT_STATUS_IS_OK(status))
937                         return status;
938
939                 if (includeDomain) {
940                         ga.in.domain_handle = &domain_handle;
941                         status = dcerpc_samr_GetAliasMembership(p, mem_ctx,
942                                                                 &ga);
943                         if (!NT_STATUS_IS_OK(status))
944                                 return status;
945                 }
946         }
947
948         {
949                 struct samr_Close c;
950
951                 c.in.handle = &user_handle;
952                 c.out.handle = &user_handle;
953                 dcerpc_samr_Close(p, mem_ctx, &c);
954
955                 c.in.handle = &domain_handle;
956                 c.out.handle = &domain_handle;
957                 dcerpc_samr_Close(p, mem_ctx, &c);
958
959                 c.in.handle = &builtin_handle;
960                 c.out.handle = &builtin_handle;
961                 dcerpc_samr_Close(p, mem_ctx, &c);
962
963                 c.in.handle = &connect_handle;
964                 c.out.handle = &connect_handle;
965                 dcerpc_samr_Close(p, mem_ctx, &c);
966         }
967
968         talloc_free(p);
969         talloc_destroy(mem_ctx);
970
971         return NT_STATUS_OK;
972 }
973
974 static NTSTATUS test_remoteTOD(struct smbcli_transport *transport)
975 {
976         TALLOC_CTX *mem_ctx;
977         NTSTATUS status;
978         struct dcerpc_pipe *p;
979         struct srvsvc_NetRemoteTOD r;
980
981         mem_ctx = talloc_init("test_lookupnames");
982         if (mem_ctx == NULL)
983                 return NT_STATUS_NO_MEMORY;
984
985         status = connect_to_pipe(&p, mem_ctx, transport, DCERPC_SRVSVC_NAME,
986                                  DCERPC_SRVSVC_UUID,
987                                  DCERPC_SRVSVC_VERSION);
988
989         if (!NT_STATUS_IS_OK(status)) {
990                 talloc_destroy(mem_ctx);
991                 return status;
992         }
993
994         status = dcerpc_bind_auth_none(p, DCERPC_SRVSVC_UUID,
995                                        DCERPC_SRVSVC_VERSION);
996
997         if (!NT_STATUS_IS_OK(status))
998                 return status;
999
1000         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
1001
1002         ZERO_STRUCT(r.out);
1003         status = dcerpc_srvsvc_NetRemoteTOD(p, mem_ctx, &r);
1004         talloc_destroy(mem_ctx);
1005         talloc_free(p);
1006         return status;
1007 }
1008
1009 static BOOL xp_login(const char *dcname, const char *wksname,
1010                      const char *domain, const char *wkspwd,
1011                      const char *user1name, const char *user1pw,
1012                      const char *user2name, const char *user2pw)
1013 {
1014         NTSTATUS status;
1015         TALLOC_CTX *mem_ctx;
1016         char *user1dom;
1017
1018         struct smbcli_transport *transport;
1019
1020         struct dcerpc_pipe *netlogon_pipe;
1021         struct creds_CredentialState *netlogon_creds;
1022
1023         struct dcerpc_pipe *netlogon_schannel_pipe;
1024
1025         talloc_enable_leak_report();
1026
1027         mem_ctx = talloc_init("rpc_login");
1028
1029         if (mem_ctx == NULL)
1030                 return False;
1031
1032         netlogon_creds = talloc_p(mem_ctx, struct creds_CredentialState);
1033         if (!netlogon_creds) {
1034                 return False;
1035         }
1036
1037         if (!NT_STATUS_IS_OK(after_negprot(&transport, dcname, 139,
1038                                            wksname)))
1039                 return False;
1040
1041         if (!NT_STATUS_IS_OK(setup_netlogon_creds(transport, &netlogon_pipe,
1042                                                   wksname, domain, wkspwd,
1043                                                   netlogon_creds)))
1044                 return False;
1045
1046         if (!NT_STATUS_IS_OK(test_enumtrusts(transport)))
1047                 return False;
1048
1049         user1dom = talloc_asprintf(mem_ctx, "%s\\%s", domain, user1name);
1050
1051         if (!NT_STATUS_IS_OK(test_lookupnames(transport, user1dom)))
1052                 return False;
1053
1054         status = connect_to_pipe(&netlogon_schannel_pipe,
1055                                  mem_ctx, transport, DCERPC_NETLOGON_NAME,
1056                                  DCERPC_NETLOGON_UUID,
1057                                  DCERPC_NETLOGON_VERSION);
1058
1059         if (!NT_STATUS_IS_OK(status))
1060                 return False;
1061
1062         netlogon_schannel_pipe->conn->flags |= DCERPC_SEAL;
1063
1064         status = dcerpc_bind_auth_schannel_withkey(netlogon_schannel_pipe,
1065                                                    DCERPC_NETLOGON_UUID,
1066                                                    DCERPC_NETLOGON_VERSION,
1067                                                    "", "", "",
1068                                                    netlogon_creds);
1069
1070         if (!NT_STATUS_IS_OK(status))
1071                 return False;
1072
1073         status = torture_samlogon(netlogon_schannel_pipe,
1074                                   netlogon_creds, wksname, domain,
1075                                   user1name, user1pw);
1076
1077         if (!NT_STATUS_IS_OK(status))
1078                 return False;
1079
1080         talloc_free(netlogon_pipe);
1081
1082         status = torture_samlogon(netlogon_schannel_pipe,
1083                                   netlogon_creds, wksname, domain,
1084                                   user2name, user2pw);
1085
1086         if (!NT_STATUS_IS_OK(status))
1087                 return False;
1088
1089         status = test_getgroups(transport, user2name);
1090         
1091         if (!NT_STATUS_IS_OK(status))
1092                 return False;
1093
1094         status = test_remoteTOD(transport);
1095         
1096         if (!NT_STATUS_IS_OK(status))
1097                 return False;
1098
1099         status = test_remoteTOD(transport);
1100         
1101         if (!NT_STATUS_IS_OK(status))
1102                 return False;
1103
1104         status = test_getallsids(transport, user2name, False);
1105         
1106         if (!NT_STATUS_IS_OK(status))
1107                 return False;
1108
1109         status = test_getgroups(transport, user2name);
1110         
1111         if (!NT_STATUS_IS_OK(status))
1112                 return False;
1113
1114         status = test_getallsids(transport, user2name, True);
1115         
1116         if (!NT_STATUS_IS_OK(status))
1117                 return False;
1118
1119         talloc_free(netlogon_schannel_pipe);
1120
1121         talloc_free(transport);
1122
1123         talloc_destroy(mem_ctx);
1124
1125         return True;
1126 }
1127
1128 struct user_pw {
1129         const char *username;
1130         const char *password;
1131 };
1132
1133 static const struct user_pw users[] = {
1134         { "username1", "password1" },
1135         { "username2", "password2" }
1136 };
1137
1138 static const struct user_pw machines[] = {
1139         { "machine1", "mpw1" },
1140         { "machine2", "mpw2" }
1141 };
1142
1143 BOOL torture_rpc_login(void)
1144 {
1145         const char *pdcname = "pdcname";
1146         const char *domainname = "domain";
1147
1148         int useridx1 = rand() % ARRAY_SIZE(users);
1149         int useridx2 = rand() % ARRAY_SIZE(users);
1150         int machidx = rand() % ARRAY_SIZE(machines);
1151         printf("machine: %s user1: %s user2: %s\n",
1152                machines[machidx].username,
1153                users[useridx1].username,
1154                users[useridx2].username);
1155
1156         return xp_login(pdcname, machines[machidx].username,
1157                         domainname, machines[machidx].password,
1158                         users[useridx1].username,
1159                         users[useridx1].password,
1160                         users[useridx2].username,
1161                         users[useridx2].password);
1162 }