r16123: Samba3 in the buildfarm will happily create (faked(!!)) users anonymously...
[ira/wip.git] / source4 / torture / rpc / samba3rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc torture tests, designed to walk Samba3 code paths
5
6    Copyright (C) Volker Lendecke 2006
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 "torture/torture.h"
25 #include "librpc/gen_ndr/ndr_lsa.h"
26 #include "librpc/gen_ndr/ndr_lsa_c.h"
27 #include "librpc/gen_ndr/ndr_samr.h"
28 #include "librpc/gen_ndr/ndr_samr_c.h"
29 #include "librpc/gen_ndr/ndr_netlogon.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "lib/cmdline/popt_common.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "torture/rpc/rpc.h"
34 #include "libcli/libcli.h"
35 #include "libcli/composite/composite.h"
36 #include "libcli/smb_composite/smb_composite.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "libcli/auth/credentials.h"
39 #include "lib/crypto/crypto.h"
40
41 /*
42  * This tests a RPC call using an invalid vuid
43  */
44
45 BOOL torture_bind_authcontext(struct torture_context *torture) 
46 {
47         TALLOC_CTX *mem_ctx;
48         NTSTATUS status;
49         BOOL ret = False;
50         struct lsa_ObjectAttribute objectattr;
51         struct lsa_OpenPolicy2 openpolicy;
52         struct policy_handle handle;
53         struct lsa_Close close;
54         struct smbcli_session *tmp;
55         struct smbcli_session *session2;
56         struct smbcli_state *cli;
57         struct dcerpc_pipe *lsa_pipe;
58         struct cli_credentials *anon_creds;
59         struct smb_composite_sesssetup setup;
60
61         mem_ctx = talloc_init("torture_bind_authcontext");
62
63         if (mem_ctx == NULL) {
64                 d_printf("talloc_init failed\n");
65                 return False;
66         }
67
68         status = smbcli_full_connection(mem_ctx, &cli,
69                                         lp_parm_string(-1, "torture", "host"),
70                                         "IPC$", NULL, cmdline_credentials,
71                                         NULL);
72         if (!NT_STATUS_IS_OK(status)) {
73                 d_printf("smbcli_full_connection failed: %s\n",
74                          nt_errstr(status));
75                 goto done;
76         }
77
78         lsa_pipe = dcerpc_pipe_init(mem_ctx, cli->transport->socket->event.ctx);
79         if (lsa_pipe == NULL) {
80                 d_printf("dcerpc_pipe_init failed\n");
81                 goto done;
82         }
83
84         status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
85         if (!NT_STATUS_IS_OK(status)) {
86                 d_printf("dcerpc_pipe_open_smb failed: %s\n",
87                          nt_errstr(status));
88                 goto done;
89         }
90
91         status = dcerpc_bind_auth_none(lsa_pipe, &dcerpc_table_lsarpc);
92         if (!NT_STATUS_IS_OK(status)) {
93                 d_printf("dcerpc_bind_auth_none failed: %s\n",
94                          nt_errstr(status));
95                 goto done;
96         }
97
98         openpolicy.in.system_name =talloc_asprintf(
99                 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
100         ZERO_STRUCT(objectattr);
101         openpolicy.in.attr = &objectattr;
102         openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
103         openpolicy.out.handle = &handle;
104
105         status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
106
107         if (!NT_STATUS_IS_OK(status)) {
108                 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
109                          nt_errstr(status));
110                 goto done;
111         }
112
113         close.in.handle = &handle;
114         close.out.handle = &handle;
115
116         status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close);
117         if (!NT_STATUS_IS_OK(status)) {
118                 d_printf("dcerpc_lsa_Close failed: %s\n",
119                          nt_errstr(status));
120                 goto done;
121         }
122
123         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
124         if (session2 == NULL) {
125                 d_printf("smbcli_session_init failed\n");
126                 goto done;
127         }
128
129         anon_creds = cli_credentials_init(mem_ctx);
130         if (anon_creds == NULL) {
131                 d_printf("cli_credentials_init failed\n");
132                 goto done;
133         }
134
135         cli_credentials_set_conf(anon_creds);
136         cli_credentials_set_anonymous(anon_creds);
137
138         setup.in.sesskey = cli->transport->negotiate.sesskey;
139         setup.in.capabilities = cli->transport->negotiate.capabilities;
140         setup.in.workgroup = "";
141         setup.in.credentials = anon_creds;
142
143         status = smb_composite_sesssetup(session2, &setup);
144         if (!NT_STATUS_IS_OK(status)) {
145                 d_printf("anon session setup failed: %s\n",
146                          nt_errstr(status));
147                 goto done;
148         }
149
150         tmp = cli->tree->session;
151         cli->tree->session = session2;
152
153         status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
154
155         cli->tree->session = tmp;
156         talloc_free(lsa_pipe);
157         lsa_pipe = NULL;
158
159         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
160                 d_printf("dcerpc_lsa_OpenPolicy2 with wrong vuid gave %s, "
161                          "expected NT_STATUS_INVALID_HANDLE\n",
162                          nt_errstr(status));
163                 goto done;
164         }
165
166         ret = True;
167  done:
168         talloc_free(mem_ctx);
169         return ret;
170 }
171
172 /*
173  * Bind to lsa using a specific auth method
174  */
175
176 static BOOL bindtest(struct smbcli_state *cli,
177                      struct cli_credentials *credentials,
178                      uint8_t auth_type, uint8_t auth_level)
179 {
180         TALLOC_CTX *mem_ctx;
181         BOOL ret = False;
182         NTSTATUS status;
183
184         struct dcerpc_pipe *lsa_pipe;
185         struct lsa_ObjectAttribute objectattr;
186         struct lsa_OpenPolicy2 openpolicy;
187         struct lsa_QueryInfoPolicy query;
188         struct policy_handle handle;
189         struct lsa_Close close;
190
191         if ((mem_ctx = talloc_init("bindtest")) == NULL) {
192                 d_printf("talloc_init failed\n");
193                 return False;
194         }
195
196         lsa_pipe = dcerpc_pipe_init(mem_ctx,
197                                     cli->transport->socket->event.ctx);
198         if (lsa_pipe == NULL) {
199                 d_printf("dcerpc_pipe_init failed\n");
200                 goto done;
201         }
202
203         status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
204         if (!NT_STATUS_IS_OK(status)) {
205                 d_printf("dcerpc_pipe_open_smb failed: %s\n",
206                          nt_errstr(status));
207                 goto done;
208         }
209
210         status = dcerpc_bind_auth(lsa_pipe, &dcerpc_table_lsarpc,
211                                   credentials, auth_type, auth_level,
212                                   NULL);
213         if (!NT_STATUS_IS_OK(status)) {
214                 d_printf("dcerpc_bind_auth failed: %s\n", nt_errstr(status));
215                 goto done;
216         }
217
218         openpolicy.in.system_name =talloc_asprintf(
219                 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
220         ZERO_STRUCT(objectattr);
221         openpolicy.in.attr = &objectattr;
222         openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
223         openpolicy.out.handle = &handle;
224
225         status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
226
227         if (!NT_STATUS_IS_OK(status)) {
228                 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
229                          nt_errstr(status));
230                 goto done;
231         }
232
233         query.in.handle = &handle;
234         query.in.level = LSA_POLICY_INFO_DOMAIN;
235
236         status = dcerpc_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx, &query);
237         if (!NT_STATUS_IS_OK(status)) {
238                 d_printf("dcerpc_lsa_QueryInfoPolicy failed: %s\n",
239                          nt_errstr(status));
240                 goto done;
241         }
242
243         close.in.handle = &handle;
244         close.out.handle = &handle;
245
246         status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close);
247         if (!NT_STATUS_IS_OK(status)) {
248                 d_printf("dcerpc_lsa_Close failed: %s\n",
249                          nt_errstr(status));
250                 goto done;
251         }
252
253         ret = True;
254  done:
255         talloc_free(mem_ctx);
256         return ret;
257 }
258
259 /*
260  * test authenticated RPC binds with the variants Samba3 does support
261  */
262
263 BOOL torture_bind_samba3(struct torture_context *torture) 
264 {
265         TALLOC_CTX *mem_ctx;
266         NTSTATUS status;
267         BOOL ret = False;
268         struct smbcli_state *cli;
269
270         mem_ctx = talloc_init("torture_bind_authcontext");
271
272         if (mem_ctx == NULL) {
273                 d_printf("talloc_init failed\n");
274                 return False;
275         }
276
277         status = smbcli_full_connection(mem_ctx, &cli,
278                                         lp_parm_string(-1, "torture", "host"),
279                                         "IPC$", NULL, cmdline_credentials,
280                                         NULL);
281         if (!NT_STATUS_IS_OK(status)) {
282                 d_printf("smbcli_full_connection failed: %s\n",
283                          nt_errstr(status));
284                 goto done;
285         }
286
287         ret = True;
288
289         ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
290                         DCERPC_AUTH_LEVEL_INTEGRITY);
291         ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
292                         DCERPC_AUTH_LEVEL_PRIVACY);
293         ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
294                         DCERPC_AUTH_LEVEL_INTEGRITY);
295         ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
296                         DCERPC_AUTH_LEVEL_PRIVACY);
297
298  done:
299         talloc_free(mem_ctx);
300         return ret;
301 }
302
303 /*
304  * Lookup or create a user and return all necessary info
305  */
306
307 static NTSTATUS get_usr_handle(struct smbcli_state *cli,
308                                TALLOC_CTX *mem_ctx,
309                                struct cli_credentials *admin_creds,
310                                uint8_t auth_type,
311                                uint8_t auth_level,
312                                const char *wks_name,
313                                char **domain,
314                                struct dcerpc_pipe **result_pipe,
315                                struct policy_handle **result_handle)
316 {
317         struct dcerpc_pipe *samr_pipe;
318         NTSTATUS status;
319         struct policy_handle conn_handle;
320         struct policy_handle domain_handle;
321         struct policy_handle *user_handle;
322         struct samr_Connect2 conn;
323         struct samr_EnumDomains enumdom;
324         uint32_t resume_handle = 0;
325         struct samr_LookupDomain l;
326         int dom_idx;
327         struct lsa_String domain_name;
328         struct lsa_String user_name;
329         struct samr_OpenDomain o;
330         struct samr_CreateUser2 c;
331         uint32_t user_rid,access_granted;
332
333         samr_pipe = dcerpc_pipe_init(mem_ctx,
334                                      cli->transport->socket->event.ctx);
335         if (samr_pipe == NULL) {
336                 d_printf("dcerpc_pipe_init failed\n");
337                 status = NT_STATUS_NO_MEMORY;
338                 goto fail;
339         }
340
341         status = dcerpc_pipe_open_smb(samr_pipe->conn, cli->tree, "\\samr");
342         if (!NT_STATUS_IS_OK(status)) {
343                 d_printf("dcerpc_pipe_open_smb failed: %s\n",
344                          nt_errstr(status));
345                 goto fail;
346         }
347
348         if (admin_creds != NULL) {
349                 status = dcerpc_bind_auth(samr_pipe, &dcerpc_table_samr,
350                                           admin_creds, auth_type, auth_level,
351                                           NULL);
352                 if (!NT_STATUS_IS_OK(status)) {
353                         d_printf("dcerpc_bind_auth failed: %s\n",
354                                  nt_errstr(status));
355                         goto fail;
356                 }
357         } else {
358                 /* We must have an authenticated SMB connection */
359                 status = dcerpc_bind_auth_none(samr_pipe, &dcerpc_table_samr);
360                 if (!NT_STATUS_IS_OK(status)) {
361                         d_printf("dcerpc_bind_auth_none failed: %s\n",
362                                  nt_errstr(status));
363                         goto fail;
364                 }
365         }
366
367         conn.in.system_name = talloc_asprintf(
368                 mem_ctx, "\\\\%s", dcerpc_server_name(samr_pipe));
369         conn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
370         conn.out.connect_handle = &conn_handle;
371
372         status = dcerpc_samr_Connect2(samr_pipe, mem_ctx, &conn);
373         if (!NT_STATUS_IS_OK(status)) {
374                 d_printf("samr_Connect2 failed: %s\n", nt_errstr(status));
375                 goto fail;
376         }
377
378         enumdom.in.connect_handle = &conn_handle;
379         enumdom.in.resume_handle = &resume_handle;
380         enumdom.in.buf_size = (uint32_t)-1;
381         enumdom.out.resume_handle = &resume_handle;
382
383         status = dcerpc_samr_EnumDomains(samr_pipe, mem_ctx, &enumdom);
384         if (!NT_STATUS_IS_OK(status)) {
385                 d_printf("samr_EnumDomains failed: %s\n", nt_errstr(status));
386                 goto fail;
387         }
388
389         if (enumdom.out.num_entries != 2) {
390                 d_printf("samr_EnumDomains returned %d entries, expected 2\n",
391                          enumdom.out.num_entries);
392                 status = NT_STATUS_UNSUCCESSFUL;
393                 goto fail;
394         }
395
396         dom_idx = strequal(enumdom.out.sam->entries[0].name.string,
397                            "builtin") ? 1:0;
398
399         l.in.connect_handle = &conn_handle;
400         domain_name.string = enumdom.out.sam->entries[0].name.string;
401         *domain = talloc_strdup(mem_ctx, domain_name.string);
402         l.in.domain_name = &domain_name;
403
404         status = dcerpc_samr_LookupDomain(samr_pipe, mem_ctx, &l);
405         if (!NT_STATUS_IS_OK(status)) {
406                 d_printf("samr_LookupDomain failed: %s\n", nt_errstr(status));
407                 goto fail;
408         }
409
410         o.in.connect_handle = &conn_handle;
411         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
412         o.in.sid = l.out.sid;
413         o.out.domain_handle = &domain_handle;
414
415         status = dcerpc_samr_OpenDomain(samr_pipe, mem_ctx, &o);
416         if (!NT_STATUS_IS_OK(status)) {
417                 d_printf("samr_OpenDomain failed: %s\n", nt_errstr(status));
418                 goto fail;
419         }
420
421         c.in.domain_handle = &domain_handle;
422         user_name.string = talloc_asprintf(mem_ctx, "%s$", wks_name);
423         c.in.account_name = &user_name;
424         c.in.acct_flags = ACB_WSTRUST;
425         c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
426         user_handle = talloc(mem_ctx, struct policy_handle);
427         c.out.user_handle = user_handle;
428         c.out.access_granted = &access_granted;
429         c.out.rid = &user_rid;
430
431         status = dcerpc_samr_CreateUser2(samr_pipe, mem_ctx, &c);
432
433         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
434                 struct samr_LookupNames ln;
435                 struct samr_OpenUser ou;
436
437                 ln.in.domain_handle = &domain_handle;
438                 ln.in.num_names = 1;
439                 ln.in.names = &user_name;
440
441                 status = dcerpc_samr_LookupNames(samr_pipe, mem_ctx, &ln);
442                 if (!NT_STATUS_IS_OK(status)) {
443                         d_printf("samr_LookupNames failed: %s\n",
444                                  nt_errstr(status));
445                         goto fail;
446                 }
447
448                 ou.in.domain_handle = &domain_handle;
449                 ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
450                 ou.in.rid = ln.out.rids.ids[0];
451                 ou.out.user_handle = user_handle;
452
453                 status = dcerpc_samr_OpenUser(samr_pipe, mem_ctx, &ou);
454                 if (!NT_STATUS_IS_OK(status)) {
455                         d_printf("samr_OpenUser failed: %s\n",
456                                  nt_errstr(status));
457                         goto fail;
458                 }
459         }
460
461         if (!NT_STATUS_IS_OK(status)) {
462                 d_printf("samr_CreateUser failed: %s\n", nt_errstr(status));
463                 goto fail;
464         }
465
466         *result_pipe = samr_pipe;
467         *result_handle = user_handle;
468         return NT_STATUS_OK;
469
470  fail:
471         return status;
472 }
473
474 /*
475  * Do a Samba3-style join
476  */
477
478 static BOOL join3(struct smbcli_state *cli,
479                   BOOL use_level25,
480                   struct cli_credentials *admin_creds,
481                   struct cli_credentials *wks_creds)
482 {
483         TALLOC_CTX *mem_ctx;
484         NTSTATUS status;
485         char *dom_name;
486         struct dcerpc_pipe *samr_pipe;
487         struct policy_handle *wks_handle;
488         BOOL ret = False;
489
490         if ((mem_ctx = talloc_init("join3")) == NULL) {
491                 d_printf("talloc_init failed\n");
492                 return False;
493         }
494
495         status = get_usr_handle(cli, mem_ctx, admin_creds,
496                                 DCERPC_AUTH_TYPE_NTLMSSP,
497                                 DCERPC_AUTH_LEVEL_PRIVACY,
498                                 cli_credentials_get_workstation(wks_creds),
499                                 &dom_name, &samr_pipe, &wks_handle);
500
501         if (!NT_STATUS_IS_OK(status)) {
502                 d_printf("get_wks_handle failed: %s\n", nt_errstr(status));
503                 goto done;
504         }
505
506         cli_credentials_set_domain(wks_creds, dom_name, CRED_SPECIFIED);
507
508         if (use_level25) {
509                 struct samr_SetUserInfo2 sui2;
510                 union samr_UserInfo u_info;
511                 struct samr_UserInfo21 *i21 = &u_info.info25.info;
512                 DATA_BLOB session_key;
513                 DATA_BLOB confounded_session_key = data_blob_talloc(
514                         mem_ctx, NULL, 16);
515                 struct MD5Context ctx;
516                 uint8_t confounder[16];
517
518                 ZERO_STRUCT(u_info);
519
520                 i21->full_name.string = talloc_asprintf(
521                         mem_ctx, "%s$",
522                         cli_credentials_get_workstation(wks_creds));
523                 i21->acct_flags = ACB_WSTRUST;
524                 i21->fields_present = SAMR_FIELD_FULL_NAME |
525                         SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_PASSWORD;
526
527                 encode_pw_buffer(u_info.info25.password.data,
528                                  cli_credentials_get_password(wks_creds),
529                                  STR_UNICODE);
530                 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
531                 if (!NT_STATUS_IS_OK(status)) {
532                         d_printf("dcerpc_fetch_session_key failed: %s\n",
533                                  nt_errstr(status));
534                         goto done;
535                 }
536                 generate_random_buffer((uint8_t *)confounder, 16);
537
538                 MD5Init(&ctx);
539                 MD5Update(&ctx, confounder, 16);
540                 MD5Update(&ctx, session_key.data, session_key.length);
541                 MD5Final(confounded_session_key.data, &ctx);
542
543                 arcfour_crypt_blob(u_info.info25.password.data, 516,
544                                    &confounded_session_key);
545                 memcpy(&u_info.info25.password.data[516], confounder, 16);
546
547                 sui2.in.user_handle = wks_handle;
548                 sui2.in.level = 25;
549                 sui2.in.info = &u_info;
550
551                 status = dcerpc_samr_SetUserInfo2(samr_pipe, mem_ctx, &sui2);
552                 if (!NT_STATUS_IS_OK(status)) {
553                         d_printf("samr_SetUserInfo2(25) failed: %s\n",
554                                  nt_errstr(status));
555                         goto done;
556                 }
557         } else {
558                 struct samr_SetUserInfo2 sui2;
559                 struct samr_SetUserInfo sui;
560                 union samr_UserInfo u_info;
561                 DATA_BLOB session_key;
562
563                 encode_pw_buffer(u_info.info24.password.data,
564                                  cli_credentials_get_password(wks_creds),
565                                  STR_UNICODE);
566                 u_info.info24.pw_len =
567                         strlen_m(cli_credentials_get_password(wks_creds))*2;
568
569                 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
570                 if (!NT_STATUS_IS_OK(status)) {
571                         d_printf("dcerpc_fetch_session_key failed\n");
572                         goto done;
573                 }
574                 arcfour_crypt_blob(u_info.info24.password.data, 516,
575                                    &session_key);
576                 sui2.in.user_handle = wks_handle;
577                 sui2.in.info = &u_info;
578                 sui2.in.level = 24;
579
580                 status = dcerpc_samr_SetUserInfo2(samr_pipe, mem_ctx, &sui2);
581                 if (!NT_STATUS_IS_OK(status)) {
582                         d_printf("samr_SetUserInfo(24) failed\n");
583                         goto done;
584                 }
585
586                 u_info.info16.acct_flags = ACB_WSTRUST;
587                 sui.in.user_handle = wks_handle;
588                 sui.in.info = &u_info;
589                 sui.in.level = 16;
590
591                 status = dcerpc_samr_SetUserInfo(samr_pipe, mem_ctx, &sui);
592                 if (!NT_STATUS_IS_OK(status)) {
593                         d_printf("samr_SetUserInfo(16) failed\n");
594                         goto done;
595                 }
596         }
597
598         ret = True;
599
600  done:
601         talloc_free(mem_ctx);
602         return ret;
603 }
604
605 /*
606  * Do a ReqChallenge/Auth2 and get the wks creds
607  */
608
609 static BOOL auth2(struct smbcli_state *cli,
610                   struct cli_credentials *wks_cred)
611 {
612         TALLOC_CTX *mem_ctx;
613         struct dcerpc_pipe *net_pipe;
614         BOOL result = False;
615         NTSTATUS status;
616         struct netr_ServerReqChallenge r;
617         struct netr_Credential netr_cli_creds;
618         struct netr_Credential netr_srv_creds;
619         uint32_t negotiate_flags;
620         struct netr_ServerAuthenticate2 a;
621         struct creds_CredentialState *creds_state;
622         struct netr_Credential netr_cred;
623         struct samr_Password mach_pw;
624
625         mem_ctx = talloc_new(NULL);
626         if (mem_ctx == NULL) {
627                 d_printf("talloc_new failed\n");
628                 return False;
629         }
630
631         net_pipe = dcerpc_pipe_init(mem_ctx,
632                                     cli->transport->socket->event.ctx);
633         if (net_pipe == NULL) {
634                 d_printf("dcerpc_pipe_init failed\n");
635                 goto done;
636         }
637
638         status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
639         if (!NT_STATUS_IS_OK(status)) {
640                 d_printf("dcerpc_pipe_open_smb failed: %s\n",
641                          nt_errstr(status));
642                 goto done;
643         }
644
645         status = dcerpc_bind_auth_none(net_pipe, &dcerpc_table_netlogon);
646         if (!NT_STATUS_IS_OK(status)) {
647                 d_printf("dcerpc_bind_auth_none failed: %s\n",
648                          nt_errstr(status));
649                 goto done;
650         }
651
652         r.in.computer_name = cli_credentials_get_workstation(wks_cred);
653         r.in.server_name = talloc_asprintf(
654                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
655         if (r.in.server_name == NULL) {
656                 d_printf("talloc_asprintf failed\n");
657                 goto done;
658         }
659         generate_random_buffer(netr_cli_creds.data,
660                                sizeof(netr_cli_creds.data));
661         r.in.credentials = &netr_cli_creds;
662         r.out.credentials = &netr_srv_creds;
663
664         status = dcerpc_netr_ServerReqChallenge(net_pipe, mem_ctx, &r);
665         if (!NT_STATUS_IS_OK(status)) {
666                 d_printf("netr_ServerReqChallenge failed: %s\n",
667                          nt_errstr(status));
668                 goto done;
669         }
670
671         negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
672         E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash);
673
674         creds_state = talloc(mem_ctx, struct creds_CredentialState);
675         creds_client_init(creds_state, r.in.credentials,
676                           r.out.credentials, &mach_pw,
677                           &netr_cred, negotiate_flags);
678
679         a.in.server_name = talloc_asprintf(
680                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
681         a.in.account_name = talloc_asprintf(
682                 mem_ctx, "%s$", cli_credentials_get_workstation(wks_cred));
683         a.in.computer_name = cli_credentials_get_workstation(wks_cred);
684         a.in.secure_channel_type = SEC_CHAN_WKSTA;
685         a.in.negotiate_flags = &negotiate_flags;
686         a.out.negotiate_flags = &negotiate_flags;
687         a.in.credentials = &netr_cred;
688         a.out.credentials = &netr_cred;
689
690         status = dcerpc_netr_ServerAuthenticate2(net_pipe, mem_ctx, &a);
691         if (!NT_STATUS_IS_OK(status)) {
692                 d_printf("netr_ServerServerAuthenticate2 failed: %s\n",
693                          nt_errstr(status));
694                 goto done;
695         }
696
697         if (!creds_client_check(creds_state, a.out.credentials)) {
698                 d_printf("creds_client_check failed\n");
699                 goto done;
700         }
701
702         cli_credentials_set_netlogon_creds(wks_cred, creds_state);
703
704         result = True;
705
706  done:
707         talloc_free(mem_ctx);
708         return result;
709 }
710
711 /*
712  * Do a couple of channel protected Netlogon ops: Interactive and Network
713  * login, and change the wks password
714  */
715
716 static BOOL schan(struct smbcli_state *cli,
717                   struct cli_credentials *wks_creds,
718                   struct cli_credentials *user_creds)
719 {
720         TALLOC_CTX *mem_ctx;
721         NTSTATUS status;
722         BOOL ret = False;
723         struct dcerpc_pipe *net_pipe;
724         int i;
725         
726         mem_ctx = talloc_new(NULL);
727         if (mem_ctx == NULL) {
728                 d_printf("talloc_new failed\n");
729                 return False;
730         }
731
732         net_pipe = dcerpc_pipe_init(mem_ctx,
733                                     cli->transport->socket->event.ctx);
734         if (net_pipe == NULL) {
735                 d_printf("dcerpc_pipe_init failed\n");
736                 goto done;
737         }
738
739         status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
740         if (!NT_STATUS_IS_OK(status)) {
741                 d_printf("dcerpc_pipe_open_smb failed: %s\n",
742                          nt_errstr(status));
743                 goto done;
744         }
745
746 #if 0
747         net_pipe->conn->flags |= DCERPC_DEBUG_PRINT_IN |
748                 DCERPC_DEBUG_PRINT_OUT;
749 #endif
750 #if 1
751         net_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
752         status = dcerpc_bind_auth(net_pipe, &dcerpc_table_netlogon,
753                                   wks_creds, DCERPC_AUTH_TYPE_SCHANNEL,
754                                   DCERPC_AUTH_LEVEL_PRIVACY,
755                                   NULL);
756 #else
757         status = dcerpc_bind_auth_none(net_pipe, &dcerpc_table_netlogon);
758 #endif
759         if (!NT_STATUS_IS_OK(status)) {
760                 d_printf("schannel bind failed: %s\n", nt_errstr(status));
761                 goto done;
762         }
763
764
765         for (i=2; i<4; i++) {
766                 int flags;
767                 DATA_BLOB chal, nt_resp, lm_resp, names_blob, session_key;
768                 struct creds_CredentialState *creds_state;
769                 struct netr_Authenticator netr_auth, netr_auth2;
770                 struct netr_NetworkInfo ninfo;
771                 struct netr_PasswordInfo pinfo;
772                 struct netr_LogonSamLogon r;
773
774                 flags = CLI_CRED_LANMAN_AUTH | CLI_CRED_NTLM_AUTH |
775                         CLI_CRED_NTLMv2_AUTH;
776
777                 chal = data_blob_talloc(mem_ctx, NULL, 8);
778                 if (chal.data == NULL) {
779                         d_printf("data_blob_talloc failed\n");
780                         goto done;
781                 }
782
783                 generate_random_buffer(chal.data, chal.length);
784                 names_blob = NTLMv2_generate_names_blob(
785                         mem_ctx, cli_credentials_get_workstation(user_creds),
786                         cli_credentials_get_domain(user_creds));
787                 status = cli_credentials_get_ntlm_response(
788                         user_creds, mem_ctx, &flags, chal, names_blob,
789                         &lm_resp, &nt_resp, NULL, NULL);
790                 if (!NT_STATUS_IS_OK(status)) {
791                         d_printf("cli_credentials_get_ntlm_response failed:"
792                                  " %s\n", nt_errstr(status));
793                         goto done;
794                 }
795
796                 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
797                 creds_client_authenticator(creds_state, &netr_auth);
798
799                 ninfo.identity_info.account_name.string =
800                         cli_credentials_get_username(user_creds);
801                 ninfo.identity_info.domain_name.string =
802                         cli_credentials_get_domain(user_creds);
803                 ninfo.identity_info.parameter_control = 0;
804                 ninfo.identity_info.logon_id_low = 0;
805                 ninfo.identity_info.logon_id_high = 0;
806                 ninfo.identity_info.workstation.string =
807                         cli_credentials_get_workstation(user_creds);
808                 memcpy(ninfo.challenge, chal.data, sizeof(ninfo.challenge));
809                 ninfo.nt.length = nt_resp.length;
810                 ninfo.nt.data = nt_resp.data;
811                 ninfo.lm.length = lm_resp.length;
812                 ninfo.lm.data = lm_resp.data;
813
814                 r.in.server_name = talloc_asprintf(
815                         mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
816                 ZERO_STRUCT(netr_auth2);
817                 r.in.computer_name =
818                         cli_credentials_get_workstation(wks_creds);
819                 r.in.credential = &netr_auth;
820                 r.in.return_authenticator = &netr_auth2;
821                 r.in.logon_level = 2;
822                 r.in.validation_level = i;
823                 r.in.logon.network = &ninfo;
824                 r.out.return_authenticator = NULL;
825
826                 status = dcerpc_netr_LogonSamLogon(net_pipe, mem_ctx, &r);
827                 if (!NT_STATUS_IS_OK(status)) {
828                         d_printf("netr_LogonSamLogon failed: %s\n",
829                                  nt_errstr(status));
830                         goto done;
831                 }
832
833                 if ((r.out.return_authenticator == NULL) ||
834                     (!creds_client_check(creds_state,
835                                          &r.out.return_authenticator->cred))) {
836                         d_printf("Credentials check failed!\n");
837                         goto done;
838                 }
839
840                 creds_client_authenticator(creds_state, &netr_auth);
841
842                 pinfo.identity_info = ninfo.identity_info;
843                 ZERO_STRUCT(pinfo.lmpassword.hash);
844                 E_md4hash(cli_credentials_get_password(user_creds),
845                           pinfo.ntpassword.hash);
846                 session_key = data_blob_talloc(mem_ctx,
847                                                creds_state->session_key, 16);
848                 arcfour_crypt_blob(pinfo.ntpassword.hash,
849                                    sizeof(pinfo.ntpassword.hash),
850                                    &session_key);
851
852                 r.in.logon_level = 1;
853                 r.in.logon.password = &pinfo;
854                 r.out.return_authenticator = NULL;
855
856                 status = dcerpc_netr_LogonSamLogon(net_pipe, mem_ctx, &r);
857                 if (!NT_STATUS_IS_OK(status)) {
858                         d_printf("netr_LogonSamLogon failed: %s\n",
859                                  nt_errstr(status));
860                         goto done;
861                 }
862
863                 if ((r.out.return_authenticator == NULL) ||
864                     (!creds_client_check(creds_state,
865                                          &r.out.return_authenticator->cred))) {
866                         d_printf("Credentials check failed!\n");
867                         goto done;
868                 }
869         }
870
871         {
872                 struct netr_ServerPasswordSet s;
873                 char *password = generate_random_str(wks_creds, 8);
874                 struct creds_CredentialState *creds_state;
875
876                 s.in.server_name = talloc_asprintf(
877                         mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
878                 s.in.computer_name = cli_credentials_get_workstation(wks_creds);
879                 s.in.account_name = talloc_asprintf(
880                         mem_ctx, "%s$", s.in.computer_name);
881                 s.in.secure_channel_type = SEC_CHAN_WKSTA;
882                 E_md4hash(password, s.in.new_password.hash);
883                 creds_des_encrypt(creds_state, &s.in.new_password);
884
885                 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
886                 creds_client_authenticator(creds_state, &s.in.credential);
887
888                 status = dcerpc_netr_ServerPasswordSet(net_pipe, mem_ctx, &s);
889                 if (!NT_STATUS_IS_OK(status)) {
890                         printf("ServerPasswordSet - %s\n", nt_errstr(status));
891                         goto done;
892                 }
893
894                 if (!creds_client_check(creds_state,
895                                         &s.out.return_authenticator.cred)) {
896                         printf("Credential chaining failed\n");
897                 }
898
899                 cli_credentials_set_password(wks_creds, password,
900                                              CRED_SPECIFIED);
901         }
902
903         ret = True;
904  done:
905         talloc_free(mem_ctx);
906         return ret;
907 }
908
909 /*
910  * Delete the wks account again
911  */
912
913 static BOOL leave(struct smbcli_state *cli,
914                   struct cli_credentials *admin_creds,
915                   struct cli_credentials *wks_creds)
916 {
917         TALLOC_CTX *mem_ctx;
918         NTSTATUS status;
919         char *dom_name;
920         struct dcerpc_pipe *samr_pipe;
921         struct policy_handle *wks_handle;
922         BOOL ret = False;
923
924         if ((mem_ctx = talloc_init("leave")) == NULL) {
925                 d_printf("talloc_init failed\n");
926                 return False;
927         }
928
929         status = get_usr_handle(cli, mem_ctx, admin_creds,
930                                 DCERPC_AUTH_TYPE_NTLMSSP,
931                                 DCERPC_AUTH_LEVEL_PRIVACY,
932                                 cli_credentials_get_workstation(wks_creds),
933                                 &dom_name, &samr_pipe, &wks_handle);
934
935         if (!NT_STATUS_IS_OK(status)) {
936                 d_printf("get_wks_handle failed: %s\n", nt_errstr(status));
937                 goto done;
938         }
939
940         {
941                 struct samr_DeleteUser d;
942
943                 d.in.user_handle = wks_handle;
944                 d.out.user_handle = wks_handle;
945
946                 status = dcerpc_samr_DeleteUser(samr_pipe, mem_ctx, &d);
947                 if (!NT_STATUS_IS_OK(status)) {
948                         d_printf("samr_DeleteUser failed\n");
949                         goto done;
950                 }
951         }
952
953         ret = True;
954
955  done:
956         talloc_free(mem_ctx);
957         return ret;
958 }
959
960 /*
961  * Test the Samba3 DC code a bit. Join, do some schan netlogon ops, leave
962  */
963
964 BOOL torture_netlogon_samba3(struct torture_context *torture)
965 {
966         TALLOC_CTX *mem_ctx;
967         NTSTATUS status;
968         BOOL ret = False;
969         struct smbcli_state *cli;
970         struct cli_credentials *anon_creds;
971         struct cli_credentials *wks_creds;
972         const char *wks_name;
973         int i;
974
975         wks_name = lp_parm_string(-1, "torture", "wksname");
976         if (wks_name == NULL) {
977                 wks_name = get_myname();
978         }
979
980         mem_ctx = talloc_init("torture_bind_authcontext");
981
982         if (mem_ctx == NULL) {
983                 d_printf("talloc_init failed\n");
984                 return False;
985         }
986
987         anon_creds = cli_credentials_init(mem_ctx);
988         if (anon_creds == NULL) {
989                 d_printf("cli_credentials_init failed\n");
990                 goto done;
991         }
992
993         cli_credentials_set_conf(anon_creds);
994         cli_credentials_set_anonymous(anon_creds);
995
996         status = smbcli_full_connection(mem_ctx, &cli,
997                                         lp_parm_string(-1, "torture", "host"),
998                                         "IPC$", NULL, anon_creds, NULL);
999         if (!NT_STATUS_IS_OK(status)) {
1000                 d_printf("smbcli_full_connection failed: %s\n",
1001                          nt_errstr(status));
1002                 goto done;
1003         }
1004
1005         wks_creds = cli_credentials_init(mem_ctx);
1006         if (wks_creds == NULL) {
1007                 d_printf("cli_credentials_init failed\n");
1008                 goto done;
1009         }
1010
1011         cli_credentials_set_conf(wks_creds);
1012         cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1013         cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1014         cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1015         cli_credentials_set_password(wks_creds, "", CRED_SPECIFIED);
1016
1017         if (!join3(cli, False, cmdline_credentials, wks_creds)) {
1018                 d_printf("join failed\n");
1019                 goto done;
1020         }
1021
1022         cli_credentials_set_domain(
1023                 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1024                 CRED_SPECIFIED);
1025
1026         for (i=0; i<2; i++) {
1027
1028                 /* Do this more than once, the routine "schan" changes
1029                  * the workstation password using the netlogon
1030                  * password change routine */
1031
1032                 int j;
1033
1034                 if (!auth2(cli, wks_creds)) {
1035                         d_printf("auth2 failed\n");
1036                         goto done;
1037                 }
1038
1039                 for (j=0; j<2; j++) {
1040                         if (!schan(cli, wks_creds, cmdline_credentials)) {
1041                                 d_printf("schan failed\n");
1042                                 goto done;
1043                         }
1044                 }
1045         }
1046
1047         if (!leave(cli, cmdline_credentials, wks_creds)) {
1048                 d_printf("leave failed\n");
1049                 goto done;
1050         }
1051
1052         ret = True;
1053
1054  done:
1055         talloc_free(mem_ctx);
1056         return ret;
1057 }
1058
1059 /*
1060  * Do a simple join, testjoin and leave using specified smb and samr
1061  * credentials
1062  */
1063
1064 static BOOL test_join3(TALLOC_CTX *mem_ctx,
1065                        BOOL use_level25,
1066                        struct cli_credentials *smb_creds,
1067                        struct cli_credentials *samr_creds,
1068                        const char *wks_name)
1069 {
1070         NTSTATUS status;
1071         BOOL ret = False;
1072         struct smbcli_state *cli;
1073         struct cli_credentials *wks_creds;
1074
1075         status = smbcli_full_connection(mem_ctx, &cli,
1076                                         lp_parm_string(-1, "torture", "host"),
1077                                         "IPC$", NULL, smb_creds, NULL);
1078         if (!NT_STATUS_IS_OK(status)) {
1079                 d_printf("smbcli_full_connection failed: %s\n",
1080                          nt_errstr(status));
1081                 goto done;
1082         }
1083
1084         wks_creds = cli_credentials_init(cli);
1085         if (wks_creds == NULL) {
1086                 d_printf("cli_credentials_init failed\n");
1087                 goto done;
1088         }
1089
1090         cli_credentials_set_conf(wks_creds);
1091         cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1092         cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1093         cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1094         cli_credentials_set_password(wks_creds,
1095                                      generate_random_str(wks_creds, 8),
1096                                      CRED_SPECIFIED);
1097
1098         if (!join3(cli, use_level25, samr_creds, wks_creds)) {
1099                 d_printf("join failed\n");
1100                 goto done;
1101         }
1102
1103         cli_credentials_set_domain(
1104                 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1105                 CRED_SPECIFIED);
1106
1107         if (!auth2(cli, wks_creds)) {
1108                 d_printf("auth2 failed\n");
1109                 goto done;
1110         }
1111
1112         if (!leave(cli, samr_creds, wks_creds)) {
1113                 d_printf("leave failed\n");
1114                 goto done;
1115         }
1116
1117         talloc_free(cli);
1118
1119         ret = True;
1120
1121  done:
1122         return ret;
1123 }
1124
1125 /*
1126  * Test the different session key variants. Do it by joining, this uses the
1127  * session key in the setpassword routine. Test the join by doing the auth2.
1128  */
1129
1130 BOOL torture_samba3_sessionkey(struct torture_context *torture)
1131 {
1132         TALLOC_CTX *mem_ctx;
1133         BOOL ret = False;
1134         struct cli_credentials *anon_creds;
1135         const char *wks_name;
1136
1137         wks_name = lp_parm_string(-1, "torture", "wksname");
1138         if (wks_name == NULL) {
1139                 wks_name = get_myname();
1140         }
1141
1142         mem_ctx = talloc_init("torture_bind_authcontext");
1143
1144         if (mem_ctx == NULL) {
1145                 d_printf("talloc_init failed\n");
1146                 return False;
1147         }
1148
1149         anon_creds = cli_credentials_init(mem_ctx);
1150         if (anon_creds == NULL) {
1151                 d_printf("cli_credentials_init failed\n");
1152                 goto done;
1153         }
1154
1155         cli_credentials_set_conf(anon_creds);
1156         cli_credentials_set_anonymous(anon_creds);
1157
1158         ret = True;
1159
1160         if (!lp_parm_bool(-1, "target", "samba3", False)) {
1161
1162                 /* Samba3 in the build farm right now does this happily. Need
1163                  * to fix :-) */
1164
1165                 if (test_join3(mem_ctx, False, anon_creds, NULL, wks_name)) {
1166                         d_printf("join using anonymous bind on an anonymous smb "
1167                                  "connection succeeded -- HUH??\n");
1168                         ret = False;
1169                 }
1170         }
1171
1172         if (!test_join3(mem_ctx, False, anon_creds, cmdline_credentials,
1173                         wks_name)) {
1174                 d_printf("join using ntlmssp bind on an anonymous smb "
1175                          "connection failed\n");
1176                 ret = False;
1177         }
1178
1179         if (!test_join3(mem_ctx, False, cmdline_credentials, NULL, wks_name)) {
1180                 d_printf("join using anonymous bind on an authenticated smb "
1181                          "connection failed\n");
1182                 ret = False;
1183         }
1184
1185         if (!test_join3(mem_ctx, False, cmdline_credentials,
1186                         cmdline_credentials,
1187                         wks_name)) {
1188                 d_printf("join using ntlmssp bind on an authenticated smb "
1189                          "connection failed\n");
1190                 ret = False;
1191         }
1192
1193         /*
1194          * The following two are tests for setuserinfolevel 25
1195          */
1196
1197         if (!test_join3(mem_ctx, True, anon_creds, cmdline_credentials,
1198                         wks_name)) {
1199                 d_printf("join using ntlmssp bind on an anonymous smb "
1200                          "connection failed\n");
1201                 ret = False;
1202         }
1203
1204         if (!test_join3(mem_ctx, True, cmdline_credentials, NULL, wks_name)) {
1205                 d_printf("join using anonymous bind on an authenticated smb "
1206                          "connection failed\n");
1207                 ret = False;
1208         }
1209
1210  done:
1211
1212         return ret;
1213 }