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