2 Unix SMB/CIFS implementation.
4 test suite for netlogon PAC operations
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
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.
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.
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/>.
23 #include "auth/auth.h"
24 #include "auth/auth_sam_reply.h"
25 #include "auth/gensec/gensec.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/credentials/credentials_krb5.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "torture/rpc/torture_rpc.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "libcli/security/security.h"
34 #include "librpc/gen_ndr/ndr_netlogon_c.h"
35 #include "librpc/gen_ndr/ndr_krb5pac.h"
36 #include "librpc/gen_ndr/ndr_samr_c.h"
37 #include "param/param.h"
39 #define TEST_MACHINE_NAME_BDC "torturepacbdc"
40 #define TEST_MACHINE_NAME_WKSTA "torturepacwksta"
41 #define TEST_MACHINE_NAME_WKSTA_DES "torturepacwkdes"
42 #define TEST_MACHINE_NAME_S2U4SELF_BDC "tests2u4selfbdc"
43 #define TEST_MACHINE_NAME_S2U4SELF_WKSTA "tests2u4selfwk"
45 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
47 /* Also happens to be a really good one-step verfication of our Kerberos stack */
49 static bool test_PACVerify(struct torture_context
*tctx
,
50 struct dcerpc_pipe
*p
,
51 struct cli_credentials
*credentials
,
52 enum netr_SchannelType secure_channel_type
,
53 const char *test_machine_name
)
57 struct netr_LogonSamLogon r
;
59 union netr_LogonLevel logon
;
60 union netr_Validation validation
;
61 uint8_t authoritative
;
62 struct netr_Authenticator return_authenticator
;
64 struct netr_GenericInfo generic
;
65 struct netr_Authenticator auth
, auth2
;
67 struct netlogon_creds_CredentialState
*creds
;
68 struct gensec_security
*gensec_client_context
;
69 struct gensec_security
*gensec_server_context
;
71 DATA_BLOB client_to_server
, server_to_client
, pac_wrapped
, payload
;
72 struct PAC_Validate pac_wrapped_struct
;
74 enum ndr_err_code ndr_err
;
76 struct auth_session_info
*session_info
;
78 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
79 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
80 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
82 if (!test_SetupCredentials2(p
, tctx
, NETLOGON_NEG_AUTH2_ADS_FLAGS
,
83 credentials
, secure_channel_type
,
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");
92 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
94 status
= gensec_set_credentials(gensec_client_context
, cmdline_credentials
);
95 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
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");
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");
105 status
= gensec_set_credentials(gensec_server_context
, credentials
);
106 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
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");
111 server_to_client
= data_blob(NULL
, 0);
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");
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");
125 if (NT_STATUS_IS_OK(status
)) {
130 /* Extract the PAC using Samba's code */
132 status
= gensec_session_info(gensec_server_context
, &session_info
);
133 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
134 torture_assert(tctx
, session_info
->torture
!= NULL
, "gensec_session_info failed to fill in torture sub struct");
135 torture_assert(tctx
, session_info
->torture
->pac_srv_sig
!= NULL
, "pac_srv_sig not present");
136 torture_assert(tctx
, session_info
->torture
->pac_kdc_sig
!= NULL
, "pac_kdc_sig not present");
138 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
139 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
140 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
141 pac_wrapped_struct
.ChecksumAndSignature
= payload
142 = data_blob_talloc(tmp_ctx
, NULL
,
143 pac_wrapped_struct
.ChecksumLength
144 + pac_wrapped_struct
.SignatureLength
);
145 memcpy(&payload
.data
[0],
146 session_info
->torture
->pac_srv_sig
->signature
.data
,
147 pac_wrapped_struct
.ChecksumLength
);
148 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
149 session_info
->torture
->pac_kdc_sig
->signature
.data
,
150 pac_wrapped_struct
.SignatureLength
);
152 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
153 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
154 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
156 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
157 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
159 generic
.length
= pac_wrapped
.length
;
160 generic
.data
= pac_wrapped
.data
;
162 /* Validate it over the netlogon pipe */
164 generic
.identity_info
.parameter_control
= 0;
165 generic
.identity_info
.logon_id_high
= 0;
166 generic
.identity_info
.logon_id_low
= 0;
167 generic
.identity_info
.domain_name
.string
= session_info
->info
->domain_name
;
168 generic
.identity_info
.account_name
.string
= session_info
->info
->account_name
;
169 generic
.identity_info
.workstation
.string
= test_machine_name
;
171 generic
.package_name
.string
= "Kerberos";
173 logon
.generic
= &generic
;
176 netlogon_creds_client_authenticator(creds
, &auth
);
177 r
.in
.credential
= &auth
;
178 r
.in
.return_authenticator
= &auth2
;
180 r
.in
.logon_level
= NetlogonGenericInformation
;
181 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
182 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
183 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
184 r
.out
.validation
= &validation
;
185 r
.out
.authoritative
= &authoritative
;
186 r
.out
.return_authenticator
= &return_authenticator
;
188 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
189 "LogonSamLogon failed");
191 torture_assert_ntstatus_ok(tctx
, r
.out
.result
, "LogonSamLogon failed");
193 /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
194 generic
.data
[generic
.length
-1]++;
196 logon
.generic
= &generic
;
199 netlogon_creds_client_authenticator(creds
, &auth
);
200 r
.in
.credential
= &auth
;
201 r
.in
.return_authenticator
= &auth2
;
202 r
.in
.logon_level
= NetlogonGenericInformation
;
204 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
205 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
206 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
208 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
209 "LogonSamLogon failed");
211 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
213 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
214 "Credential chaining failed");
216 /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
219 logon
.generic
= &generic
;
222 netlogon_creds_client_authenticator(creds
, &auth
);
223 r
.in
.credential
= &auth
;
224 r
.in
.return_authenticator
= &auth2
;
225 r
.in
.logon_level
= NetlogonGenericInformation
;
227 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
228 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
229 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
231 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
232 "LogonSamLogon failed");
234 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
236 torture_assert(tctx
, netlogon_creds_client_check(creds
,
237 &r
.out
.return_authenticator
->cred
),
238 "Credential chaining failed");
240 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
241 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
243 /* Break the SignatureType */
244 pac_wrapped_struct
.SignatureType
++;
246 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
247 pac_wrapped_struct
.ChecksumAndSignature
= payload
248 = data_blob_talloc(tmp_ctx
, NULL
,
249 pac_wrapped_struct
.ChecksumLength
250 + pac_wrapped_struct
.SignatureLength
);
251 memcpy(&payload
.data
[0],
252 session_info
->torture
->pac_srv_sig
->signature
.data
,
253 pac_wrapped_struct
.ChecksumLength
);
254 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
255 session_info
->torture
->pac_kdc_sig
->signature
.data
,
256 pac_wrapped_struct
.SignatureLength
);
258 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
259 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
260 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
262 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
263 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
265 generic
.length
= pac_wrapped
.length
;
266 generic
.data
= pac_wrapped
.data
;
268 logon
.generic
= &generic
;
271 netlogon_creds_client_authenticator(creds
, &auth
);
272 r
.in
.credential
= &auth
;
273 r
.in
.return_authenticator
= &auth2
;
274 r
.in
.logon_level
= NetlogonGenericInformation
;
276 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
277 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
278 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
280 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
281 "LogonSamLogon failed");
283 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
285 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
286 "Credential chaining failed");
288 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
289 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
290 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
292 pac_wrapped_struct
.ChecksumAndSignature
= payload
293 = data_blob_talloc(tmp_ctx
, NULL
,
294 pac_wrapped_struct
.ChecksumLength
295 + pac_wrapped_struct
.SignatureLength
);
296 memcpy(&payload
.data
[0],
297 session_info
->torture
->pac_srv_sig
->signature
.data
,
298 pac_wrapped_struct
.ChecksumLength
);
299 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
300 session_info
->torture
->pac_kdc_sig
->signature
.data
,
301 pac_wrapped_struct
.SignatureLength
);
303 /* Break the signature length */
304 pac_wrapped_struct
.SignatureLength
++;
306 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
307 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
308 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
310 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
311 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
313 generic
.length
= pac_wrapped
.length
;
314 generic
.data
= pac_wrapped
.data
;
316 logon
.generic
= &generic
;
319 netlogon_creds_client_authenticator(creds
, &auth
);
320 r
.in
.credential
= &auth
;
321 r
.in
.return_authenticator
= &auth2
;
322 r
.in
.logon_level
= NetlogonGenericInformation
;
324 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
325 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
326 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
328 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
329 "LogonSamLogon failed");
331 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
333 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
334 "Credential chaining failed");
339 static bool test_PACVerify_bdc(struct torture_context
*tctx
,
340 struct dcerpc_pipe
*p
,
341 struct cli_credentials
*credentials
)
343 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_BDC
, TEST_MACHINE_NAME_BDC
);
346 static bool test_PACVerify_workstation(struct torture_context
*tctx
,
347 struct dcerpc_pipe
*p
,
348 struct cli_credentials
*credentials
)
350 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_WKSTA
);
353 static bool test_PACVerify_workstation_des(struct torture_context
*tctx
,
354 struct dcerpc_pipe
*p
, struct cli_credentials
*credentials
, struct test_join
*join_ctx
)
356 struct samr_SetUserInfo r
;
357 union samr_UserInfo user_info
;
358 struct dcerpc_pipe
*samr_pipe
= torture_join_samr_pipe(join_ctx
);
359 struct smb_krb5_context
*smb_krb5_context
;
362 ret
= cli_credentials_get_krb5_context(cmdline_credentials
, tctx
->lp_ctx
, &smb_krb5_context
);
363 torture_assert_int_equal(tctx
, ret
, 0, "cli_credentials_get_krb5_context() failed");
365 if (krb5_config_get_bool_default(smb_krb5_context
->krb5_context
, NULL
, FALSE
,
367 "allow_weak_crypto", NULL
) == FALSE
) {
368 torture_skip(tctx
, "Cannot test DES without [libdefaults] allow_weak_crypto = yes");
371 /* Mark this workstation with DES-only */
372 user_info
.info16
.acct_flags
= ACB_USE_DES_KEY_ONLY
| ACB_WSTRUST
;
373 r
.in
.user_handle
= torture_join_samr_user_policy(join_ctx
);
375 r
.in
.info
= &user_info
;
377 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_SetUserInfo_r(samr_pipe
->binding_handle
, tctx
, &r
),
378 "failed to set DES info account flags");
379 torture_assert_ntstatus_ok(tctx
, r
.out
.result
,
380 "failed to set DES into account flags");
382 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_WKSTA_DES
);
386 /* 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 */
387 static bool test_S2U4Self(struct torture_context
*tctx
,
388 struct dcerpc_pipe
*p
,
389 struct cli_credentials
*credentials
,
390 enum netr_SchannelType secure_channel_type
,
391 const char *test_machine_name
)
394 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
396 struct netr_LogonSamLogon r
;
398 union netr_LogonLevel logon
;
399 union netr_Validation validation
;
400 uint8_t authoritative
;
402 struct netr_Authenticator auth
, auth2
;
404 DATA_BLOB client_to_server
, server_to_client
;
406 struct netlogon_creds_CredentialState
*creds
;
407 struct gensec_security
*gensec_client_context
;
408 struct gensec_security
*gensec_server_context
;
410 struct auth_session_info
*kinit_session_info
;
411 struct auth_session_info
*s2u4self_session_info
;
412 struct auth_user_info_dc
*netlogon_user_info_dc
;
414 struct netr_NetworkInfo ninfo
;
415 DATA_BLOB names_blob
, chal
, lm_resp
, nt_resp
;
417 int flags
= CLI_CRED_NTLMv2_AUTH
;
419 struct dom_sid
*builtin_domain
;
421 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
423 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
425 /* First, do a normal Kerberos connection */
427 status
= gensec_client_start(tctx
, &gensec_client_context
, tctx
->ev
,
428 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
429 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
431 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
433 status
= gensec_set_credentials(gensec_client_context
, cmdline_credentials
);
434 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
436 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
437 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
439 status
= gensec_server_start(tctx
, tctx
->ev
,
440 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
441 NULL
, &gensec_server_context
);
442 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
444 status
= gensec_set_credentials(gensec_server_context
, credentials
);
445 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
447 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
448 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
450 server_to_client
= data_blob(NULL
, 0);
453 /* Do a client-server update dance */
454 status
= gensec_update(gensec_client_context
, tmp_ctx
, server_to_client
, &client_to_server
);
455 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
456 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
459 status
= gensec_update(gensec_server_context
, tmp_ctx
, client_to_server
, &server_to_client
);
460 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
461 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
464 if (NT_STATUS_IS_OK(status
)) {
469 /* Extract the PAC using Samba's code */
471 status
= gensec_session_info(gensec_server_context
, &kinit_session_info
);
472 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
475 /* Now do the dance with S2U4Self */
477 /* Wipe out any existing ccache */
478 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
479 cli_credentials_set_target_service(credentials
, talloc_asprintf(tmp_ctx
, "host/%s", test_machine_name
));
480 cli_credentials_set_impersonate_principal(credentials
, cli_credentials_get_principal(cmdline_credentials
, tmp_ctx
));
482 status
= gensec_client_start(tctx
, &gensec_client_context
, tctx
->ev
,
483 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
484 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
486 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
488 /* We now set the same credentials on both client and server contexts */
489 status
= gensec_set_credentials(gensec_client_context
, credentials
);
490 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
492 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
493 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
495 status
= gensec_server_start(tctx
, tctx
->ev
,
496 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
497 NULL
, &gensec_server_context
);
498 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
500 status
= gensec_set_credentials(gensec_server_context
, credentials
);
501 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
503 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
504 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
506 server_to_client
= data_blob(NULL
, 0);
509 /* Do a client-server update dance */
510 status
= gensec_update(gensec_client_context
, tmp_ctx
, server_to_client
, &client_to_server
);
511 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
512 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
515 status
= gensec_update(gensec_server_context
, tmp_ctx
, client_to_server
, &server_to_client
);
516 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
517 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
520 if (NT_STATUS_IS_OK(status
)) {
525 /* Don't pollute the remaining tests with the changed credentials */
526 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
527 cli_credentials_set_target_service(credentials
, NULL
);
528 cli_credentials_set_impersonate_principal(credentials
, NULL
);
530 /* Extract the PAC using Samba's code */
532 status
= gensec_session_info(gensec_server_context
, &s2u4self_session_info
);
533 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
535 cli_credentials_get_ntlm_username_domain(cmdline_credentials
, tctx
,
536 &ninfo
.identity_info
.account_name
.string
,
537 &ninfo
.identity_info
.domain_name
.string
);
539 /* Now try with SamLogon */
540 generate_random_buffer(ninfo
.challenge
,
541 sizeof(ninfo
.challenge
));
542 chal
= data_blob_const(ninfo
.challenge
,
543 sizeof(ninfo
.challenge
));
545 names_blob
= NTLMv2_generate_names_blob(tctx
, cli_credentials_get_workstation(credentials
),
546 cli_credentials_get_domain(credentials
));
548 status
= cli_credentials_get_ntlm_response(cmdline_credentials
, tctx
,
554 torture_assert_ntstatus_ok(tctx
, status
, "cli_credentials_get_ntlm_response failed");
556 ninfo
.lm
.data
= lm_resp
.data
;
557 ninfo
.lm
.length
= lm_resp
.length
;
559 ninfo
.nt
.data
= nt_resp
.data
;
560 ninfo
.nt
.length
= nt_resp
.length
;
562 ninfo
.identity_info
.parameter_control
= 0;
563 ninfo
.identity_info
.logon_id_low
= 0;
564 ninfo
.identity_info
.logon_id_high
= 0;
565 ninfo
.identity_info
.workstation
.string
= cli_credentials_get_workstation(credentials
);
567 logon
.network
= &ninfo
;
569 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
570 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
571 r
.in
.credential
= &auth
;
572 r
.in
.return_authenticator
= &auth2
;
573 r
.in
.logon_level
= 2;
575 r
.out
.validation
= &validation
;
576 r
.out
.authoritative
= &authoritative
;
578 if (!test_SetupCredentials2(p
, tctx
, NETLOGON_NEG_AUTH2_ADS_FLAGS
,
579 credentials
, secure_channel_type
,
585 netlogon_creds_client_authenticator(creds
, &auth
);
587 r
.in
.validation_level
= 3;
589 status
= dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
);
590 torture_assert_ntstatus_ok(tctx
, status
, "LogonSamLogon failed");
592 torture_assert(tctx
, netlogon_creds_client_check(creds
,
593 &r
.out
.return_authenticator
->cred
),
594 "Credential chaining failed");
596 status
= make_user_info_dc_netlogon_validation(tmp_ctx
,
597 ninfo
.identity_info
.account_name
.string
,
598 r
.in
.validation_level
,
600 &netlogon_user_info_dc
);
602 torture_assert_ntstatus_ok(tctx
, status
, "make_user_info_dc_netlogon_validation failed");
604 torture_assert_str_equal(tctx
, netlogon_user_info_dc
->info
->account_name
== NULL
? "" : netlogon_user_info_dc
->info
->account_name
,
605 kinit_session_info
->info
->account_name
, "Account name differs for kinit-based PAC");
606 torture_assert_str_equal(tctx
,netlogon_user_info_dc
->info
->account_name
== NULL
? "" : netlogon_user_info_dc
->info
->account_name
,
607 s2u4self_session_info
->info
->account_name
, "Account name differs for S2U4Self");
608 torture_assert_str_equal(tctx
, netlogon_user_info_dc
->info
->full_name
== NULL
? "" : netlogon_user_info_dc
->info
->full_name
, kinit_session_info
->info
->full_name
, "Full name differs for kinit-based PAC");
609 torture_assert_str_equal(tctx
, netlogon_user_info_dc
->info
->full_name
== NULL
? "" : netlogon_user_info_dc
->info
->full_name
, s2u4self_session_info
->info
->full_name
, "Full name differs for S2U4Self");
610 torture_assert_int_equal(tctx
, netlogon_user_info_dc
->num_sids
, kinit_session_info
->torture
->num_dc_sids
, "Different numbers of domain groups for kinit-based PAC");
611 torture_assert_int_equal(tctx
, netlogon_user_info_dc
->num_sids
, s2u4self_session_info
->torture
->num_dc_sids
, "Different numbers of domain groups for S2U4Self");
613 builtin_domain
= dom_sid_parse_talloc(tmp_ctx
, SID_BUILTIN
);
615 for (i
= 0; i
< kinit_session_info
->torture
->num_dc_sids
; i
++) {
616 torture_assert(tctx
, dom_sid_equal(&netlogon_user_info_dc
->sids
[i
], &kinit_session_info
->torture
->dc_sids
[i
]), "Different domain groups for kinit-based PAC");
617 torture_assert(tctx
, dom_sid_equal(&netlogon_user_info_dc
->sids
[i
], &s2u4self_session_info
->torture
->dc_sids
[i
]), "Different domain groups for S2U4Self");
618 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &s2u4self_session_info
->torture
->dc_sids
[i
]), "Returned BUILTIN domain in groups for S2U4Self");
619 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &kinit_session_info
->torture
->dc_sids
[i
]), "Returned BUILTIN domain in groups kinit-based PAC");
620 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &netlogon_user_info_dc
->sids
[i
]), "Returned BUILTIN domian in groups from NETLOGON SamLogon reply");
626 static bool test_S2U4Self_bdc(struct torture_context
*tctx
,
627 struct dcerpc_pipe
*p
,
628 struct cli_credentials
*credentials
)
630 return test_S2U4Self(tctx
, p
, credentials
, SEC_CHAN_BDC
, TEST_MACHINE_NAME_S2U4SELF_BDC
);
633 static bool test_S2U4Self_workstation(struct torture_context
*tctx
,
634 struct dcerpc_pipe
*p
,
635 struct cli_credentials
*credentials
)
637 return test_S2U4Self(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_S2U4SELF_WKSTA
);
640 struct torture_suite
*torture_rpc_remote_pac(TALLOC_CTX
*mem_ctx
)
642 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "pac");
643 struct torture_rpc_tcase
*tcase
;
645 /* It is important to use different names, so that old entries in our credential cache are not used */
646 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "netlogon-bdc",
647 &ndr_table_netlogon
, TEST_MACHINE_NAME_BDC
);
648 torture_rpc_tcase_add_test_creds(tcase
, "verify-sig", test_PACVerify_bdc
);
650 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member",
651 &ndr_table_netlogon
, TEST_MACHINE_NAME_WKSTA
);
652 torture_rpc_tcase_add_test_creds(tcase
, "verify-sig", test_PACVerify_workstation
);
654 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member-des",
655 &ndr_table_netlogon
, TEST_MACHINE_NAME_WKSTA_DES
);
656 torture_rpc_tcase_add_test_join(tcase
, "verify-sig", test_PACVerify_workstation_des
);
658 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "netlogon-bdc",
659 &ndr_table_netlogon
, TEST_MACHINE_NAME_S2U4SELF_BDC
);
660 torture_rpc_tcase_add_test_creds(tcase
, "s2u4self", test_S2U4Self_bdc
);
662 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member",
663 &ndr_table_netlogon
, TEST_MACHINE_NAME_S2U4SELF_WKSTA
);
665 torture_rpc_tcase_add_test_creds(tcase
, "s2u4self", test_S2U4Self_workstation
);