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 /* A helper function which avoids touching the local databases to
46 * generate the session info, as we just want to verify the PAC
47 * details, not the full local token */
48 static NTSTATUS
test_generate_session_info_pac(struct auth4_context
*auth_ctx
,
50 struct smb_krb5_context
*smb_krb5_context
,
52 const char *principal_name
,
53 const struct tsocket_address
*remote_address
,
54 uint32_t session_info_flags
,
55 struct auth_session_info
**session_info
)
58 struct auth_user_info_dc
*user_info_dc
;
59 struct PAC_SIGNATURE_DATA
*pac_srv_sig
= NULL
;
60 struct PAC_SIGNATURE_DATA
*pac_kdc_sig
= NULL
;
63 tmp_ctx
= talloc_named(mem_ctx
, 0, "gensec_gssapi_session_info context");
64 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
66 pac_srv_sig
= talloc(tmp_ctx
, struct PAC_SIGNATURE_DATA
);
69 return NT_STATUS_NO_MEMORY
;
71 pac_kdc_sig
= talloc(tmp_ctx
, struct PAC_SIGNATURE_DATA
);
74 return NT_STATUS_NO_MEMORY
;
77 nt_status
= kerberos_pac_blob_to_user_info_dc(tmp_ctx
,
79 smb_krb5_context
->krb5_context
,
83 if (!NT_STATUS_IS_OK(nt_status
)) {
88 if (user_info_dc
->info
->authenticated
) {
89 session_info_flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
92 session_info_flags
|= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
;
93 nt_status
= auth_generate_session_info(mem_ctx
,
96 user_info_dc
, session_info_flags
,
98 if (!NT_STATUS_IS_OK(nt_status
)) {
103 if ((*session_info
)->torture
) {
104 (*session_info
)->torture
->pac_srv_sig
105 = talloc_steal((*session_info
)->torture
, pac_srv_sig
);
106 (*session_info
)->torture
->pac_kdc_sig
107 = talloc_steal((*session_info
)->torture
, pac_kdc_sig
);
110 talloc_free(tmp_ctx
);
114 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
116 /* Also happens to be a really good one-step verfication of our Kerberos stack */
118 static bool test_PACVerify(struct torture_context
*tctx
,
119 struct dcerpc_pipe
*p
,
120 struct cli_credentials
*credentials
,
121 enum netr_SchannelType secure_channel_type
,
122 const char *test_machine_name
)
126 struct netr_LogonSamLogon r
;
128 union netr_LogonLevel logon
;
129 union netr_Validation validation
;
130 uint8_t authoritative
;
131 struct netr_Authenticator return_authenticator
;
133 struct netr_GenericInfo generic
;
134 struct netr_Authenticator auth
, auth2
;
136 struct netlogon_creds_CredentialState
*creds
;
137 struct gensec_security
*gensec_client_context
;
138 struct gensec_security
*gensec_server_context
;
140 DATA_BLOB client_to_server
, server_to_client
, pac_wrapped
, payload
;
141 struct PAC_Validate pac_wrapped_struct
;
143 enum ndr_err_code ndr_err
;
145 struct auth4_context
*auth_context
;
146 struct auth_session_info
*session_info
;
148 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
149 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
150 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
152 if (!test_SetupCredentials2(p
, tctx
, NETLOGON_NEG_AUTH2_ADS_FLAGS
,
153 credentials
, secure_channel_type
,
158 auth_context
= talloc_zero(tmp_ctx
, struct auth4_context
);
159 torture_assert(tctx
, auth_context
!= NULL
, "talloc_new() failed");
161 auth_context
->generate_session_info_pac
= test_generate_session_info_pac
;
163 status
= gensec_client_start(tctx
, &gensec_client_context
,
164 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
165 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
167 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
169 status
= gensec_set_credentials(gensec_client_context
, cmdline_credentials
);
170 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
172 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
173 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
175 status
= gensec_server_start(tctx
,
176 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
177 auth_context
, &gensec_server_context
);
178 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
180 status
= gensec_set_credentials(gensec_server_context
, credentials
);
181 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
183 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
184 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
186 server_to_client
= data_blob(NULL
, 0);
189 /* Do a client-server update dance */
190 status
= gensec_update(gensec_client_context
, tmp_ctx
, tctx
->ev
, server_to_client
, &client_to_server
);
191 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
192 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
195 status
= gensec_update(gensec_server_context
, tmp_ctx
, tctx
->ev
, client_to_server
, &server_to_client
);
196 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
197 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
200 if (NT_STATUS_IS_OK(status
)) {
205 /* Extract the PAC using Samba's code */
207 status
= gensec_session_info(gensec_server_context
, gensec_server_context
, &session_info
);
208 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
209 torture_assert(tctx
, session_info
->torture
!= NULL
, "gensec_session_info failed to fill in torture sub struct");
210 torture_assert(tctx
, session_info
->torture
->pac_srv_sig
!= NULL
, "pac_srv_sig not present");
211 torture_assert(tctx
, session_info
->torture
->pac_kdc_sig
!= NULL
, "pac_kdc_sig not present");
213 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
214 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
215 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
216 pac_wrapped_struct
.ChecksumAndSignature
= payload
217 = data_blob_talloc(tmp_ctx
, NULL
,
218 pac_wrapped_struct
.ChecksumLength
219 + pac_wrapped_struct
.SignatureLength
);
220 memcpy(&payload
.data
[0],
221 session_info
->torture
->pac_srv_sig
->signature
.data
,
222 pac_wrapped_struct
.ChecksumLength
);
223 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
224 session_info
->torture
->pac_kdc_sig
->signature
.data
,
225 pac_wrapped_struct
.SignatureLength
);
227 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
228 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
229 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
231 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
232 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
234 generic
.length
= pac_wrapped
.length
;
235 generic
.data
= pac_wrapped
.data
;
237 /* Validate it over the netlogon pipe */
239 generic
.identity_info
.parameter_control
= 0;
240 generic
.identity_info
.logon_id_high
= 0;
241 generic
.identity_info
.logon_id_low
= 0;
242 generic
.identity_info
.domain_name
.string
= session_info
->info
->domain_name
;
243 generic
.identity_info
.account_name
.string
= session_info
->info
->account_name
;
244 generic
.identity_info
.workstation
.string
= test_machine_name
;
246 generic
.package_name
.string
= "Kerberos";
248 logon
.generic
= &generic
;
251 netlogon_creds_client_authenticator(creds
, &auth
);
252 r
.in
.credential
= &auth
;
253 r
.in
.return_authenticator
= &auth2
;
255 r
.in
.logon_level
= NetlogonGenericInformation
;
256 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
257 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
258 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
259 r
.out
.validation
= &validation
;
260 r
.out
.authoritative
= &authoritative
;
261 r
.out
.return_authenticator
= &return_authenticator
;
263 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
264 "LogonSamLogon failed");
266 torture_assert_ntstatus_ok(tctx
, r
.out
.result
, "LogonSamLogon failed");
268 /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
269 generic
.data
[generic
.length
-1]++;
271 logon
.generic
= &generic
;
274 netlogon_creds_client_authenticator(creds
, &auth
);
275 r
.in
.credential
= &auth
;
276 r
.in
.return_authenticator
= &auth2
;
277 r
.in
.logon_level
= NetlogonGenericInformation
;
279 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
280 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
281 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
283 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
284 "LogonSamLogon failed");
286 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
288 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
289 "Credential chaining failed");
291 /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
294 logon
.generic
= &generic
;
297 netlogon_creds_client_authenticator(creds
, &auth
);
298 r
.in
.credential
= &auth
;
299 r
.in
.return_authenticator
= &auth2
;
300 r
.in
.logon_level
= NetlogonGenericInformation
;
302 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
303 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
304 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
306 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
307 "LogonSamLogon failed");
309 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
311 torture_assert(tctx
, netlogon_creds_client_check(creds
,
312 &r
.out
.return_authenticator
->cred
),
313 "Credential chaining failed");
315 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
316 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
318 /* Break the SignatureType */
319 pac_wrapped_struct
.SignatureType
++;
321 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
322 pac_wrapped_struct
.ChecksumAndSignature
= payload
323 = data_blob_talloc(tmp_ctx
, NULL
,
324 pac_wrapped_struct
.ChecksumLength
325 + pac_wrapped_struct
.SignatureLength
);
326 memcpy(&payload
.data
[0],
327 session_info
->torture
->pac_srv_sig
->signature
.data
,
328 pac_wrapped_struct
.ChecksumLength
);
329 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
330 session_info
->torture
->pac_kdc_sig
->signature
.data
,
331 pac_wrapped_struct
.SignatureLength
);
333 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
334 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
335 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
337 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
338 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
340 generic
.length
= pac_wrapped
.length
;
341 generic
.data
= pac_wrapped
.data
;
343 logon
.generic
= &generic
;
346 netlogon_creds_client_authenticator(creds
, &auth
);
347 r
.in
.credential
= &auth
;
348 r
.in
.return_authenticator
= &auth2
;
349 r
.in
.logon_level
= NetlogonGenericInformation
;
351 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
352 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
353 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
355 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
356 "LogonSamLogon failed");
358 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
360 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
361 "Credential chaining failed");
363 pac_wrapped_struct
.ChecksumLength
= session_info
->torture
->pac_srv_sig
->signature
.length
;
364 pac_wrapped_struct
.SignatureType
= session_info
->torture
->pac_kdc_sig
->type
;
365 pac_wrapped_struct
.SignatureLength
= session_info
->torture
->pac_kdc_sig
->signature
.length
;
367 pac_wrapped_struct
.ChecksumAndSignature
= payload
368 = data_blob_talloc(tmp_ctx
, NULL
,
369 pac_wrapped_struct
.ChecksumLength
370 + pac_wrapped_struct
.SignatureLength
);
371 memcpy(&payload
.data
[0],
372 session_info
->torture
->pac_srv_sig
->signature
.data
,
373 pac_wrapped_struct
.ChecksumLength
);
374 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
375 session_info
->torture
->pac_kdc_sig
->signature
.data
,
376 pac_wrapped_struct
.SignatureLength
);
378 /* Break the signature length */
379 pac_wrapped_struct
.SignatureLength
++;
381 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, &pac_wrapped_struct
,
382 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
383 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
385 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
386 netlogon_creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
388 generic
.length
= pac_wrapped
.length
;
389 generic
.data
= pac_wrapped
.data
;
391 logon
.generic
= &generic
;
394 netlogon_creds_client_authenticator(creds
, &auth
);
395 r
.in
.credential
= &auth
;
396 r
.in
.return_authenticator
= &auth2
;
397 r
.in
.logon_level
= NetlogonGenericInformation
;
399 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
400 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
401 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
403 torture_assert_ntstatus_ok(tctx
, dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
),
404 "LogonSamLogon failed");
406 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
408 torture_assert(tctx
, netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
409 "Credential chaining failed");
414 static bool test_PACVerify_bdc(struct torture_context
*tctx
,
415 struct dcerpc_pipe
*p
,
416 struct cli_credentials
*credentials
)
418 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_BDC
, TEST_MACHINE_NAME_BDC
);
421 static bool test_PACVerify_workstation(struct torture_context
*tctx
,
422 struct dcerpc_pipe
*p
,
423 struct cli_credentials
*credentials
)
425 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_WKSTA
);
428 static bool test_PACVerify_workstation_des(struct torture_context
*tctx
,
429 struct dcerpc_pipe
*p
, struct cli_credentials
*credentials
, struct test_join
*join_ctx
)
431 struct samr_SetUserInfo r
;
432 union samr_UserInfo user_info
;
433 struct dcerpc_pipe
*samr_pipe
= torture_join_samr_pipe(join_ctx
);
434 struct smb_krb5_context
*smb_krb5_context
;
437 ret
= cli_credentials_get_krb5_context(cmdline_credentials
, tctx
->lp_ctx
, &smb_krb5_context
);
438 torture_assert_int_equal(tctx
, ret
, 0, "cli_credentials_get_krb5_context() failed");
440 if (krb5_config_get_bool_default(smb_krb5_context
->krb5_context
, NULL
, FALSE
,
442 "allow_weak_crypto", NULL
) == FALSE
) {
443 torture_skip(tctx
, "Cannot test DES without [libdefaults] allow_weak_crypto = yes");
446 /* Mark this workstation with DES-only */
447 user_info
.info16
.acct_flags
= ACB_USE_DES_KEY_ONLY
| ACB_WSTRUST
;
448 r
.in
.user_handle
= torture_join_samr_user_policy(join_ctx
);
450 r
.in
.info
= &user_info
;
452 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_SetUserInfo_r(samr_pipe
->binding_handle
, tctx
, &r
),
453 "failed to set DES info account flags");
454 torture_assert_ntstatus_ok(tctx
, r
.out
.result
,
455 "failed to set DES into account flags");
457 return test_PACVerify(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_WKSTA_DES
);
461 /* 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 */
462 static bool test_S2U4Self(struct torture_context
*tctx
,
463 struct dcerpc_pipe
*p
,
464 struct cli_credentials
*credentials
,
465 enum netr_SchannelType secure_channel_type
,
466 const char *test_machine_name
)
469 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
471 struct netr_LogonSamLogon r
;
473 union netr_LogonLevel logon
;
474 union netr_Validation validation
;
475 uint8_t authoritative
;
477 struct netr_Authenticator auth
, auth2
;
479 DATA_BLOB client_to_server
, server_to_client
;
481 struct netlogon_creds_CredentialState
*creds
;
482 struct gensec_security
*gensec_client_context
;
483 struct gensec_security
*gensec_server_context
;
485 struct auth4_context
*auth_context
;
486 struct auth_session_info
*kinit_session_info
;
487 struct auth_session_info
*s2u4self_session_info
;
488 struct auth_user_info_dc
*netlogon_user_info_dc
;
490 struct netr_NetworkInfo ninfo
;
491 DATA_BLOB names_blob
, chal
, lm_resp
, nt_resp
;
493 int flags
= CLI_CRED_NTLMv2_AUTH
;
495 struct dom_sid
*builtin_domain
;
497 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
499 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
501 auth_context
= talloc_zero(tmp_ctx
, struct auth4_context
);
502 torture_assert(tctx
, auth_context
!= NULL
, "talloc_new() failed");
504 auth_context
->generate_session_info_pac
= test_generate_session_info_pac
;
506 /* First, do a normal Kerberos connection */
508 status
= gensec_client_start(tctx
, &gensec_client_context
,
509 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
510 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
512 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
514 status
= gensec_set_credentials(gensec_client_context
, cmdline_credentials
);
515 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
517 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
518 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
520 status
= gensec_server_start(tctx
,
521 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
522 auth_context
, &gensec_server_context
);
523 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
525 status
= gensec_set_credentials(gensec_server_context
, credentials
);
526 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
528 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
529 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
531 server_to_client
= data_blob(NULL
, 0);
534 /* Do a client-server update dance */
535 status
= gensec_update(gensec_client_context
, tmp_ctx
, tctx
->ev
, server_to_client
, &client_to_server
);
536 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
537 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
540 status
= gensec_update(gensec_server_context
, tmp_ctx
, tctx
->ev
, client_to_server
, &server_to_client
);
541 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
542 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
545 if (NT_STATUS_IS_OK(status
)) {
550 /* Extract the PAC using Samba's code */
552 status
= gensec_session_info(gensec_server_context
, gensec_server_context
, &kinit_session_info
);
553 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
556 /* Now do the dance with S2U4Self */
558 /* Wipe out any existing ccache */
559 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
560 cli_credentials_set_impersonate_principal(credentials
,
561 cli_credentials_get_principal(cmdline_credentials
, tmp_ctx
),
562 talloc_asprintf(tmp_ctx
, "host/%s", test_machine_name
));
564 status
= gensec_client_start(tctx
, &gensec_client_context
,
565 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
566 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
568 status
= gensec_set_target_hostname(gensec_client_context
, test_machine_name
);
570 /* We now set the same credentials on both client and server contexts */
571 status
= gensec_set_credentials(gensec_client_context
, credentials
);
572 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
574 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
575 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
577 status
= gensec_server_start(tctx
,
578 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
579 auth_context
, &gensec_server_context
);
580 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
582 status
= gensec_set_credentials(gensec_server_context
, credentials
);
583 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
585 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
586 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
588 server_to_client
= data_blob(NULL
, 0);
591 /* Do a client-server update dance */
592 status
= gensec_update(gensec_client_context
, tmp_ctx
, tctx
->ev
, server_to_client
, &client_to_server
);
593 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
594 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
597 status
= gensec_update(gensec_server_context
, tmp_ctx
, tctx
->ev
, client_to_server
, &server_to_client
);
598 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
599 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
602 if (NT_STATUS_IS_OK(status
)) {
607 /* Don't pollute the remaining tests with the changed credentials */
608 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
609 cli_credentials_set_target_service(credentials
, NULL
);
610 cli_credentials_set_impersonate_principal(credentials
, NULL
, NULL
);
612 /* Extract the PAC using Samba's code */
614 status
= gensec_session_info(gensec_server_context
, gensec_server_context
, &s2u4self_session_info
);
615 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
617 cli_credentials_get_ntlm_username_domain(cmdline_credentials
, tctx
,
618 &ninfo
.identity_info
.account_name
.string
,
619 &ninfo
.identity_info
.domain_name
.string
);
621 /* Now try with SamLogon */
622 generate_random_buffer(ninfo
.challenge
,
623 sizeof(ninfo
.challenge
));
624 chal
= data_blob_const(ninfo
.challenge
,
625 sizeof(ninfo
.challenge
));
627 names_blob
= NTLMv2_generate_names_blob(tctx
, cli_credentials_get_workstation(credentials
),
628 cli_credentials_get_domain(credentials
));
630 status
= cli_credentials_get_ntlm_response(cmdline_credentials
, tctx
,
636 torture_assert_ntstatus_ok(tctx
, status
, "cli_credentials_get_ntlm_response failed");
638 ninfo
.lm
.data
= lm_resp
.data
;
639 ninfo
.lm
.length
= lm_resp
.length
;
641 ninfo
.nt
.data
= nt_resp
.data
;
642 ninfo
.nt
.length
= nt_resp
.length
;
644 ninfo
.identity_info
.parameter_control
= 0;
645 ninfo
.identity_info
.logon_id_low
= 0;
646 ninfo
.identity_info
.logon_id_high
= 0;
647 ninfo
.identity_info
.workstation
.string
= cli_credentials_get_workstation(credentials
);
649 logon
.network
= &ninfo
;
651 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
652 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
653 r
.in
.credential
= &auth
;
654 r
.in
.return_authenticator
= &auth2
;
655 r
.in
.logon_level
= 2;
657 r
.out
.validation
= &validation
;
658 r
.out
.authoritative
= &authoritative
;
660 if (!test_SetupCredentials2(p
, tctx
, NETLOGON_NEG_AUTH2_ADS_FLAGS
,
661 credentials
, secure_channel_type
,
667 netlogon_creds_client_authenticator(creds
, &auth
);
669 r
.in
.validation_level
= 3;
671 status
= dcerpc_netr_LogonSamLogon_r(b
, tctx
, &r
);
672 torture_assert_ntstatus_ok(tctx
, status
, "LogonSamLogon failed");
674 torture_assert(tctx
, netlogon_creds_client_check(creds
,
675 &r
.out
.return_authenticator
->cred
),
676 "Credential chaining failed");
678 status
= make_user_info_dc_netlogon_validation(tmp_ctx
,
679 ninfo
.identity_info
.account_name
.string
,
680 r
.in
.validation_level
,
682 true, /* This user was authenticated */
683 &netlogon_user_info_dc
);
685 torture_assert_ntstatus_ok(tctx
, status
, "make_user_info_dc_netlogon_validation failed");
687 torture_assert_str_equal(tctx
, netlogon_user_info_dc
->info
->account_name
== NULL
? "" : netlogon_user_info_dc
->info
->account_name
,
688 kinit_session_info
->info
->account_name
, "Account name differs for kinit-based PAC");
689 torture_assert_str_equal(tctx
,netlogon_user_info_dc
->info
->account_name
== NULL
? "" : netlogon_user_info_dc
->info
->account_name
,
690 s2u4self_session_info
->info
->account_name
, "Account name differs for S2U4Self");
691 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");
692 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");
693 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");
694 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");
696 builtin_domain
= dom_sid_parse_talloc(tmp_ctx
, SID_BUILTIN
);
698 for (i
= 0; i
< kinit_session_info
->torture
->num_dc_sids
; i
++) {
699 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");
700 torture_assert(tctx
, dom_sid_equal(&netlogon_user_info_dc
->sids
[i
], &s2u4self_session_info
->torture
->dc_sids
[i
]), "Different domain groups for S2U4Self");
701 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &s2u4self_session_info
->torture
->dc_sids
[i
]), "Returned BUILTIN domain in groups for S2U4Self");
702 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &kinit_session_info
->torture
->dc_sids
[i
]), "Returned BUILTIN domain in groups kinit-based PAC");
703 torture_assert(tctx
, !dom_sid_in_domain(builtin_domain
, &netlogon_user_info_dc
->sids
[i
]), "Returned BUILTIN domian in groups from NETLOGON SamLogon reply");
709 static bool test_S2U4Self_bdc(struct torture_context
*tctx
,
710 struct dcerpc_pipe
*p
,
711 struct cli_credentials
*credentials
)
713 return test_S2U4Self(tctx
, p
, credentials
, SEC_CHAN_BDC
, TEST_MACHINE_NAME_S2U4SELF_BDC
);
716 static bool test_S2U4Self_workstation(struct torture_context
*tctx
,
717 struct dcerpc_pipe
*p
,
718 struct cli_credentials
*credentials
)
720 return test_S2U4Self(tctx
, p
, credentials
, SEC_CHAN_WKSTA
, TEST_MACHINE_NAME_S2U4SELF_WKSTA
);
723 struct torture_suite
*torture_rpc_remote_pac(TALLOC_CTX
*mem_ctx
)
725 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "pac");
726 struct torture_rpc_tcase
*tcase
;
728 /* It is important to use different names, so that old entries in our credential cache are not used */
729 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "netlogon-bdc",
730 &ndr_table_netlogon
, TEST_MACHINE_NAME_BDC
);
731 torture_rpc_tcase_add_test_creds(tcase
, "verify-sig", test_PACVerify_bdc
);
733 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member",
734 &ndr_table_netlogon
, TEST_MACHINE_NAME_WKSTA
);
735 torture_rpc_tcase_add_test_creds(tcase
, "verify-sig", test_PACVerify_workstation
);
737 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member-des",
738 &ndr_table_netlogon
, TEST_MACHINE_NAME_WKSTA_DES
);
739 torture_rpc_tcase_add_test_join(tcase
, "verify-sig", test_PACVerify_workstation_des
);
741 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "netlogon-bdc",
742 &ndr_table_netlogon
, TEST_MACHINE_NAME_S2U4SELF_BDC
);
743 torture_rpc_tcase_add_test_creds(tcase
, "s2u4self", test_S2U4Self_bdc
);
745 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "netlogon-member",
746 &ndr_table_netlogon
, TEST_MACHINE_NAME_S2U4SELF_WKSTA
);
748 torture_rpc_tcase_add_test_creds(tcase
, "s2u4self", test_S2U4Self_workstation
);