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