libcli/security Use common security.h
[idra/samba.git] / source4 / torture / rpc / remote_pac.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon PAC operations
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "auth/auth_sam_reply.h"
25 #include "auth/gensec/gensec.h"
26 #include "lib/cmdline/popt_common.h"
27 #include "torture/rpc/torture_rpc.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "libcli/security/security.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "param/param.h"
32
33 #define TEST_MACHINE_NAME_BDC "torturepacbdc"
34 #define TEST_MACHINE_NAME_WKSTA "torturepacwksta"
35 #define TEST_MACHINE_NAME_S2U4SELF_BDC "tests2u4selfbdc"
36 #define TEST_MACHINE_NAME_S2U4SELF_WKSTA "tests2u4selfwk"
37
38 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
39
40 /* Also happens to be a really good one-step verfication of our Kerberos stack */
41
42 static bool test_PACVerify(struct torture_context *tctx, 
43                            struct dcerpc_pipe *p,
44                            struct cli_credentials *credentials,
45                            enum netr_SchannelType secure_channel_type,
46                            const char *test_machine_name)
47 {
48         NTSTATUS status;
49
50         struct netr_LogonSamLogon r;
51
52         union netr_LogonLevel logon;
53         union netr_Validation validation;
54         uint8_t authoritative;
55         struct netr_Authenticator return_authenticator;
56
57         struct netr_GenericInfo generic;
58         struct netr_Authenticator auth, auth2;
59         
60
61         struct netlogon_creds_CredentialState *creds;
62         struct gensec_security *gensec_client_context;
63         struct gensec_security *gensec_server_context;
64
65         DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload;
66         struct PAC_Validate pac_wrapped_struct;
67         
68         enum ndr_err_code ndr_err;
69
70         struct auth_session_info *session_info;
71
72         char *tmp_dir;
73         struct dcerpc_binding_handle *b = p->binding_handle;
74
75         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
76         
77         torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
78
79         if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
80                                     credentials, secure_channel_type,
81                                     &creds)) {
82                 return false;
83         }
84
85         status = torture_temp_dir(tctx, "PACVerify", &tmp_dir);
86         torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed");
87
88         status = gensec_client_start(tctx, &gensec_client_context, tctx->ev, 
89                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx));
90         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
91
92         status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
93
94         status = gensec_set_credentials(gensec_client_context, cmdline_credentials);
95         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
96
97         status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
98         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
99
100         status = gensec_server_start(tctx, tctx->ev, 
101                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
102                                      NULL, &gensec_server_context);
103         torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
104
105         status = gensec_set_credentials(gensec_server_context, credentials);
106         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
107
108         status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
109         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
110
111         server_to_client = data_blob(NULL, 0);
112         
113         do {
114                 /* Do a client-server update dance */
115                 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
116                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
117                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
118                 }
119
120                 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
121                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
122                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
123                 }
124
125                 if (NT_STATUS_IS_OK(status)) {
126                         break;
127                 }
128         } while (1);
129
130         /* Extract the PAC using Samba's code */
131
132         status = gensec_session_info(gensec_server_context, &session_info);
133         torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
134         
135         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
136         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
137         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
138         pac_wrapped_struct.ChecksumAndSignature = payload
139                 = data_blob_talloc(tmp_ctx, NULL, 
140                                    pac_wrapped_struct.ChecksumLength
141                                    + pac_wrapped_struct.SignatureLength);
142         memcpy(&payload.data[0], 
143                session_info->server_info->pac_srv_sig.signature.data, 
144                pac_wrapped_struct.ChecksumLength);
145         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
146                session_info->server_info->pac_kdc_sig.signature.data, 
147                pac_wrapped_struct.SignatureLength);
148
149         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, &pac_wrapped_struct,
150                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
151         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
152                 
153         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
154         netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
155
156         generic.length = pac_wrapped.length;
157         generic.data = pac_wrapped.data;
158
159         /* Validate it over the netlogon pipe */
160
161         generic.identity_info.parameter_control = 0;
162         generic.identity_info.logon_id_high = 0;
163         generic.identity_info.logon_id_low = 0;
164         generic.identity_info.domain_name.string = session_info->server_info->domain_name;
165         generic.identity_info.account_name.string = session_info->server_info->account_name;
166         generic.identity_info.workstation.string = test_machine_name;
167
168         generic.package_name.string = "Kerberos";
169
170         logon.generic = &generic;
171
172         ZERO_STRUCT(auth2);
173         netlogon_creds_client_authenticator(creds, &auth);
174         r.in.credential = &auth;
175         r.in.return_authenticator = &auth2;
176         r.in.logon = &logon;
177         r.in.logon_level = NetlogonGenericInformation;
178         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
179         r.in.computer_name = cli_credentials_get_workstation(credentials);
180         r.in.validation_level = NetlogonValidationGenericInfo2;
181         r.out.validation = &validation;
182         r.out.authoritative = &authoritative;
183         r.out.return_authenticator = &return_authenticator;
184
185         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
186                 "LogonSamLogon failed");
187
188         torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogon failed");
189         
190         /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
191         generic.data[generic.length-1]++;
192
193         logon.generic = &generic;
194
195         ZERO_STRUCT(auth2);
196         netlogon_creds_client_authenticator(creds, &auth);
197         r.in.credential = &auth;
198         r.in.return_authenticator = &auth2;
199         r.in.logon_level = NetlogonGenericInformation;
200         r.in.logon = &logon;
201         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
202         r.in.computer_name = cli_credentials_get_workstation(credentials);
203         r.in.validation_level = NetlogonValidationGenericInfo2;
204
205         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
206                 "LogonSamLogon failed");
207
208         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
209         
210         torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), 
211                        "Credential chaining failed");
212
213         /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
214         generic.length--;
215
216         logon.generic = &generic;
217
218         ZERO_STRUCT(auth2);
219         netlogon_creds_client_authenticator(creds, &auth);
220         r.in.credential = &auth;
221         r.in.return_authenticator = &auth2;
222         r.in.logon_level = NetlogonGenericInformation;
223         r.in.logon = &logon;
224         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
225         r.in.computer_name = cli_credentials_get_workstation(credentials);
226         r.in.validation_level = NetlogonValidationGenericInfo2;
227
228         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
229                 "LogonSamLogon failed");
230
231         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
232         
233         torture_assert(tctx, netlogon_creds_client_check(creds, 
234                                                          &r.out.return_authenticator->cred), 
235                        "Credential chaining failed");
236
237         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
238         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
239         
240         /* Break the SignatureType */
241         pac_wrapped_struct.SignatureType++;
242
243         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
244         pac_wrapped_struct.ChecksumAndSignature = payload
245                 = data_blob_talloc(tmp_ctx, NULL, 
246                                    pac_wrapped_struct.ChecksumLength
247                                    + pac_wrapped_struct.SignatureLength);
248         memcpy(&payload.data[0], 
249                session_info->server_info->pac_srv_sig.signature.data, 
250                pac_wrapped_struct.ChecksumLength);
251         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
252                session_info->server_info->pac_kdc_sig.signature.data, 
253                pac_wrapped_struct.SignatureLength);
254         
255         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, &pac_wrapped_struct,
256                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
257         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
258         
259         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
260         netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
261         
262         generic.length = pac_wrapped.length;
263         generic.data = pac_wrapped.data;
264
265         logon.generic = &generic;
266
267         ZERO_STRUCT(auth2);
268         netlogon_creds_client_authenticator(creds, &auth);
269         r.in.credential = &auth;
270         r.in.return_authenticator = &auth2;
271         r.in.logon_level = NetlogonGenericInformation;
272         r.in.logon = &logon;
273         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
274         r.in.computer_name = cli_credentials_get_workstation(credentials);
275         r.in.validation_level = NetlogonValidationGenericInfo2;
276         
277         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
278                 "LogonSamLogon failed");
279         
280         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
281         
282         torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), 
283                        "Credential chaining failed");
284
285         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
286         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
287         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
288
289         pac_wrapped_struct.ChecksumAndSignature = payload
290                 = data_blob_talloc(tmp_ctx, NULL, 
291                                    pac_wrapped_struct.ChecksumLength
292                                    + pac_wrapped_struct.SignatureLength);
293         memcpy(&payload.data[0], 
294                session_info->server_info->pac_srv_sig.signature.data, 
295                pac_wrapped_struct.ChecksumLength);
296         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
297                session_info->server_info->pac_kdc_sig.signature.data, 
298                pac_wrapped_struct.SignatureLength);
299         
300         /* Break the signature length */
301         pac_wrapped_struct.SignatureLength++;
302
303         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, &pac_wrapped_struct,
304                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
305         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
306         
307         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
308         netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
309         
310         generic.length = pac_wrapped.length;
311         generic.data = pac_wrapped.data;
312
313         logon.generic = &generic;
314
315         ZERO_STRUCT(auth2);
316         netlogon_creds_client_authenticator(creds, &auth);
317         r.in.credential = &auth;
318         r.in.return_authenticator = &auth2;
319         r.in.logon_level = NetlogonGenericInformation;
320         r.in.logon = &logon;
321         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
322         r.in.computer_name = cli_credentials_get_workstation(credentials);
323         r.in.validation_level = NetlogonValidationGenericInfo2;
324         
325         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
326                 "LogonSamLogon failed");
327         
328         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
329         
330         torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), 
331                        "Credential chaining failed");
332
333         return true;
334 }
335
336 static bool test_PACVerify_bdc(struct torture_context *tctx,
337                                struct dcerpc_pipe *p,
338                                struct cli_credentials *credentials)
339 {
340         return test_PACVerify(tctx, p, credentials, SEC_CHAN_BDC, TEST_MACHINE_NAME_BDC);
341 }
342
343 static bool test_PACVerify_workstation(struct torture_context *tctx,
344                                   struct dcerpc_pipe *p,
345                                   struct cli_credentials *credentials)
346 {
347         return test_PACVerify(tctx, p, credentials, SEC_CHAN_WKSTA, TEST_MACHINE_NAME_WKSTA);
348 }
349
350
351 /* Check various ways to get the PAC, in particular check the group membership and other details between the PAC from a normal kinit, S2U4Self and a SamLogon */
352 static bool test_S2U4Self(struct torture_context *tctx,
353                           struct dcerpc_pipe *p,
354                           struct cli_credentials *credentials,
355                           enum netr_SchannelType secure_channel_type,
356                           const char *test_machine_name)
357 {
358         NTSTATUS status;
359         struct dcerpc_binding_handle *b = p->binding_handle;
360
361         struct netr_LogonSamLogon r;
362
363         union netr_LogonLevel logon;
364         union netr_Validation validation;
365         uint8_t authoritative;
366
367         struct netr_Authenticator auth, auth2;
368
369         DATA_BLOB client_to_server, server_to_client;
370
371         struct netlogon_creds_CredentialState *creds;
372         struct gensec_security *gensec_client_context;
373         struct gensec_security *gensec_server_context;
374
375         struct auth_session_info *kinit_session_info;
376         struct auth_session_info *s2u4self_session_info;
377         struct auth_serversupplied_info *netlogon_server_info;
378
379         struct netr_NetworkInfo ninfo;
380         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
381         size_t i;
382         int flags = CLI_CRED_NTLMv2_AUTH;
383
384         struct dom_sid *builtin_domain;
385
386         char *tmp_dir;
387
388         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
389
390         torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
391
392         /* First, do a normal Kerberos connection */
393
394         status = torture_temp_dir(tctx, "S2U4Self", &tmp_dir);
395         torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed");
396
397         status = gensec_client_start(tctx, &gensec_client_context, tctx->ev,
398                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx));
399         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
400
401         status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
402
403         status = gensec_set_credentials(gensec_client_context, cmdline_credentials);
404         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
405
406         status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
407         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
408
409         status = gensec_server_start(tctx, tctx->ev,
410                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
411                                      NULL, &gensec_server_context);
412         torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
413
414         status = gensec_set_credentials(gensec_server_context, credentials);
415         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
416
417         status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
418         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
419
420         server_to_client = data_blob(NULL, 0);
421
422         do {
423                 /* Do a client-server update dance */
424                 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
425                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
426                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
427                 }
428
429                 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
430                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
431                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
432                 }
433
434                 if (NT_STATUS_IS_OK(status)) {
435                         break;
436                 }
437         } while (1);
438
439         /* Extract the PAC using Samba's code */
440
441         status = gensec_session_info(gensec_server_context, &kinit_session_info);
442         torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
443
444
445         /* Now do the dance with S2U4Self */
446
447         /* Wipe out any existing ccache */
448         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
449         cli_credentials_set_target_service(credentials, talloc_asprintf(tmp_ctx, "host/%s", test_machine_name));
450         cli_credentials_set_impersonate_principal(credentials, cli_credentials_get_principal(cmdline_credentials, tmp_ctx));
451
452         status = gensec_client_start(tctx, &gensec_client_context, tctx->ev,
453                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx));
454         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
455
456         status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
457
458         /* We now set the same credentials on both client and server contexts */
459         status = gensec_set_credentials(gensec_client_context, credentials);
460         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
461
462         status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
463         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
464
465         status = gensec_server_start(tctx, tctx->ev,
466                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
467                                      NULL, &gensec_server_context);
468         torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
469
470         status = gensec_set_credentials(gensec_server_context, credentials);
471         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
472
473         status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
474         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
475
476         server_to_client = data_blob(NULL, 0);
477
478         do {
479                 /* Do a client-server update dance */
480                 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
481                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
482                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
483                 }
484
485                 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
486                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
487                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
488                 }
489
490                 if (NT_STATUS_IS_OK(status)) {
491                         break;
492                 }
493         } while (1);
494
495         /* Don't pollute the remaining tests with the changed credentials */
496         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
497         cli_credentials_set_target_service(credentials, NULL);
498         cli_credentials_set_impersonate_principal(credentials, NULL);
499
500         /* Extract the PAC using Samba's code */
501
502         status = gensec_session_info(gensec_server_context, &s2u4self_session_info);
503         torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
504
505         cli_credentials_get_ntlm_username_domain(cmdline_credentials, tctx,
506                                                  &ninfo.identity_info.account_name.string,
507                                                  &ninfo.identity_info.domain_name.string);
508
509         /* Now try with SamLogon */
510         generate_random_buffer(ninfo.challenge,
511                                sizeof(ninfo.challenge));
512         chal = data_blob_const(ninfo.challenge,
513                                sizeof(ninfo.challenge));
514
515         names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(credentials),
516                                                 cli_credentials_get_domain(credentials));
517
518         status = cli_credentials_get_ntlm_response(cmdline_credentials, tctx,
519                                                    &flags,
520                                                    chal,
521                                                    names_blob,
522                                                    &lm_resp, &nt_resp,
523                                                    NULL, NULL);
524         torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
525
526         ninfo.lm.data = lm_resp.data;
527         ninfo.lm.length = lm_resp.length;
528
529         ninfo.nt.data = nt_resp.data;
530         ninfo.nt.length = nt_resp.length;
531
532         ninfo.identity_info.parameter_control = 0;
533         ninfo.identity_info.logon_id_low = 0;
534         ninfo.identity_info.logon_id_high = 0;
535         ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
536
537         logon.network = &ninfo;
538
539         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
540         r.in.computer_name = cli_credentials_get_workstation(credentials);
541         r.in.credential = &auth;
542         r.in.return_authenticator = &auth2;
543         r.in.logon_level = 2;
544         r.in.logon = &logon;
545         r.out.validation = &validation;
546         r.out.authoritative = &authoritative;
547
548         if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
549                                     credentials, secure_channel_type,
550                                     &creds)) {
551                 return false;
552         }
553
554         ZERO_STRUCT(auth2);
555         netlogon_creds_client_authenticator(creds, &auth);
556
557         r.in.validation_level = 3;
558
559         status = dcerpc_netr_LogonSamLogon_r(b, tctx, &r);
560         torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
561
562         torture_assert(tctx, netlogon_creds_client_check(creds,
563                                                          &r.out.return_authenticator->cred),
564                        "Credential chaining failed");
565
566         status = make_server_info_netlogon_validation(tmp_ctx,
567                                                       ninfo.identity_info.account_name.string,
568                                                       r.in.validation_level,
569                                                       r.out.validation,
570                                                       &netlogon_server_info);
571
572         torture_assert_ntstatus_ok(tctx, status, "make_server_info_netlogon_validation failed");
573
574         torture_assert_str_equal(tctx, netlogon_server_info->account_name == NULL ? "" : netlogon_server_info->account_name,
575                                  kinit_session_info->server_info->account_name, "Account name differs for kinit-based PAC");
576         torture_assert_str_equal(tctx,netlogon_server_info->account_name == NULL ? "" : netlogon_server_info->account_name,
577                                  s2u4self_session_info->server_info->account_name, "Account name differs for S2U4Self");
578         torture_assert_str_equal(tctx, netlogon_server_info->full_name == NULL ? "" : netlogon_server_info->full_name, kinit_session_info->server_info->full_name, "Full name differs for kinit-based PAC");
579         torture_assert_str_equal(tctx, netlogon_server_info->full_name == NULL ? "" : netlogon_server_info->full_name, s2u4self_session_info->server_info->full_name, "Full name differs for S2U4Self");
580         torture_assert(tctx, dom_sid_equal(netlogon_server_info->account_sid, kinit_session_info->server_info->account_sid), "Account SID differs for kinit-based PAC");
581         torture_assert(tctx, dom_sid_equal(netlogon_server_info->primary_group_sid, kinit_session_info->server_info->primary_group_sid), "Primary Group SID differs for kinit-based PAC");
582         torture_assert(tctx, dom_sid_equal(netlogon_server_info->account_sid, s2u4self_session_info->server_info->account_sid), "Account SID differs for S2U4Self");
583         torture_assert(tctx, dom_sid_equal(netlogon_server_info->primary_group_sid, s2u4self_session_info->server_info->primary_group_sid), "Primary Group SID differs for S2U4Self");
584         torture_assert_int_equal(tctx, netlogon_server_info->n_domain_groups, kinit_session_info->server_info->n_domain_groups, "Different numbers of domain groups for kinit-based PAC");
585         torture_assert_int_equal(tctx, netlogon_server_info->n_domain_groups, s2u4self_session_info->server_info->n_domain_groups, "Different numbers of domain groups for S2U4Self");
586
587         builtin_domain = dom_sid_parse_talloc(tmp_ctx, SID_BUILTIN);
588
589         for (i = 0; i < kinit_session_info->server_info->n_domain_groups; i++) {
590                 torture_assert(tctx, dom_sid_equal(netlogon_server_info->domain_groups[i], kinit_session_info->server_info->domain_groups[i]), "Different domain groups for kinit-based PAC");
591                 torture_assert(tctx, dom_sid_equal(netlogon_server_info->domain_groups[i], s2u4self_session_info->server_info->domain_groups[i]), "Different domain groups for S2U4Self");
592                 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, s2u4self_session_info->server_info->domain_groups[i]), "Returned BUILTIN domain in groups for S2U4Self");
593                 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, kinit_session_info->server_info->domain_groups[i]), "Returned BUILTIN domain in groups kinit-based PAC");
594                 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, netlogon_server_info->domain_groups[i]), "Returned BUILTIN domian in groups from NETLOGON SamLogon reply");
595         }
596
597         return true;
598 }
599
600 static bool test_S2U4Self_bdc(struct torture_context *tctx,
601                                struct dcerpc_pipe *p,
602                                struct cli_credentials *credentials)
603 {
604         return test_S2U4Self(tctx, p, credentials, SEC_CHAN_BDC, TEST_MACHINE_NAME_S2U4SELF_BDC);
605 }
606
607 static bool test_S2U4Self_workstation(struct torture_context *tctx,
608                                   struct dcerpc_pipe *p,
609                                   struct cli_credentials *credentials)
610 {
611         return test_S2U4Self(tctx, p, credentials, SEC_CHAN_WKSTA, TEST_MACHINE_NAME_S2U4SELF_WKSTA);
612 }
613
614 struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
615 {
616         struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
617         struct torture_rpc_tcase *tcase;
618
619         /* It is important to use different names, so that old entries in our credential cache are not used */
620         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netlogon-bdc",
621                                                               &ndr_table_netlogon, TEST_MACHINE_NAME_BDC);
622         torture_rpc_tcase_add_test_creds(tcase, "verify-sig", test_PACVerify_bdc);
623
624         tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netlogon-member",
625                                                                       &ndr_table_netlogon, TEST_MACHINE_NAME_WKSTA);
626         torture_rpc_tcase_add_test_creds(tcase, "verify-sig", test_PACVerify_workstation);
627
628         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netlogon-bdc",
629                                                               &ndr_table_netlogon, TEST_MACHINE_NAME_S2U4SELF_BDC);
630         torture_rpc_tcase_add_test_creds(tcase, "s2u4self", test_S2U4Self_bdc);
631
632         tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netlogon-member",
633                                                                       &ndr_table_netlogon, TEST_MACHINE_NAME_S2U4SELF_WKSTA);
634
635         torture_rpc_tcase_add_test_creds(tcase, "s2u4self", test_S2U4Self_workstation);
636         return suite;
637 }