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