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 "torture/torture.h"
24 #include "lib/events/events.h"
25 #include "auth/auth.h"
26 #include "auth/gensec/gensec.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "torture/rpc/rpc.h"
29 #include "torture/rpc/netlogon.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_krb5pac.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "cluster/cluster.h"
37 #define TEST_MACHINE_NAME "torturepactest"
39 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
41 /* Also happens to be a really good one-step verfication of our Kerberos stack */
43 static bool test_PACVerify(struct torture_context
*tctx
,
44 struct dcerpc_pipe
*p
,
45 struct cli_credentials
*credentials
)
49 struct netr_LogonSamLogon r
;
51 union netr_LogonLevel logon
;
52 union netr_Validation validation
;
53 uint8_t authoritative
;
54 struct netr_Authenticator return_authenticator
;
56 struct netr_GenericInfo generic
;
57 struct netr_Authenticator auth
, auth2
;
60 struct creds_CredentialState
*creds
;
61 struct gensec_security
*gensec_client_context
;
62 struct gensec_security
*gensec_server_context
;
64 DATA_BLOB client_to_server
, server_to_client
, pac_wrapped
, payload
;
65 struct PAC_Validate pac_wrapped_struct
;
67 enum ndr_err_code ndr_err
;
69 struct auth_session_info
*session_info
;
73 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
75 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
77 if (!test_SetupCredentials2(p
, tctx
, NETLOGON_NEG_AUTH2_ADS_FLAGS
,
78 credentials
, SEC_CHAN_BDC
,
83 status
= torture_temp_dir(tctx
, "PACVerify", &tmp_dir
);
84 torture_assert_ntstatus_ok(tctx
, status
, "torture_temp_dir failed");
86 status
= gensec_client_start(tctx
, &gensec_client_context
, tctx
->ev
,
87 lp_gensec_settings(tctx
, tctx
->lp_ctx
));
88 torture_assert_ntstatus_ok(tctx
, status
, "gensec_client_start (client) failed");
90 status
= gensec_set_target_hostname(gensec_client_context
, TEST_MACHINE_NAME
);
92 status
= gensec_set_credentials(gensec_client_context
, cmdline_credentials
);
93 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (client) failed");
95 status
= gensec_start_mech_by_sasl_name(gensec_client_context
, "GSSAPI");
96 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (client) failed");
98 status
= gensec_server_start(tctx
, tctx
->ev
,
99 lp_gensec_settings(tctx
, tctx
->lp_ctx
),
100 NULL
, &gensec_server_context
);
101 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
103 status
= gensec_set_credentials(gensec_server_context
, credentials
);
104 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
106 status
= gensec_start_mech_by_sasl_name(gensec_server_context
, "GSSAPI");
107 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_sasl_name (server) failed");
109 server_to_client
= data_blob(NULL
, 0);
112 /* Do a client-server update dance */
113 status
= gensec_update(gensec_client_context
, tmp_ctx
, server_to_client
, &client_to_server
);
114 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
115 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (client) failed");
118 status
= gensec_update(gensec_server_context
, tmp_ctx
, client_to_server
, &server_to_client
);
119 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {;
120 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
123 if (NT_STATUS_IS_OK(status
)) {
128 /* Extract the PAC using Samba's code */
130 status
= gensec_session_info(gensec_server_context
, &session_info
);
131 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
133 pac_wrapped_struct
.ChecksumLength
= session_info
->server_info
->pac_srv_sig
.signature
.length
;
134 pac_wrapped_struct
.SignatureType
= session_info
->server_info
->pac_kdc_sig
.type
;
135 pac_wrapped_struct
.SignatureLength
= session_info
->server_info
->pac_kdc_sig
.signature
.length
;
136 pac_wrapped_struct
.ChecksumAndSignature
= payload
137 = data_blob_talloc(tmp_ctx
, NULL
,
138 pac_wrapped_struct
.ChecksumLength
139 + pac_wrapped_struct
.SignatureLength
);
140 memcpy(&payload
.data
[0],
141 session_info
->server_info
->pac_srv_sig
.signature
.data
,
142 pac_wrapped_struct
.ChecksumLength
);
143 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
144 session_info
->server_info
->pac_kdc_sig
.signature
.data
,
145 pac_wrapped_struct
.SignatureLength
);
147 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, lp_iconv_convenience(tctx
->lp_ctx
), &pac_wrapped_struct
,
148 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
149 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
151 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
152 creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
154 generic
.length
= pac_wrapped
.length
;
155 generic
.data
= pac_wrapped
.data
;
157 /* Validate it over the netlogon pipe */
159 generic
.identity_info
.parameter_control
= 0;
160 generic
.identity_info
.logon_id_high
= 0;
161 generic
.identity_info
.logon_id_low
= 0;
162 generic
.identity_info
.domain_name
.string
= session_info
->server_info
->domain_name
;
163 generic
.identity_info
.account_name
.string
= session_info
->server_info
->account_name
;
164 generic
.identity_info
.workstation
.string
= TEST_MACHINE_NAME
;
166 generic
.package_name
.string
= "Kerberos";
168 logon
.generic
= &generic
;
171 creds_client_authenticator(creds
, &auth
);
172 r
.in
.credential
= &auth
;
173 r
.in
.return_authenticator
= &auth2
;
175 r
.in
.logon_level
= NetlogonGenericInformation
;
176 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
177 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
178 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
179 r
.out
.validation
= &validation
;
180 r
.out
.authoritative
= &authoritative
;
181 r
.out
.return_authenticator
= &return_authenticator
;
183 status
= dcerpc_netr_LogonSamLogon(p
, tctx
, &r
);
185 torture_assert_ntstatus_ok(tctx
, status
, "LogonSamLogon failed");
187 /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
188 generic
.data
[generic
.length
-1]++;
190 logon
.generic
= &generic
;
193 creds_client_authenticator(creds
, &auth
);
194 r
.in
.credential
= &auth
;
195 r
.in
.return_authenticator
= &auth2
;
196 r
.in
.logon_level
= NetlogonGenericInformation
;
198 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
199 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
200 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
202 status
= dcerpc_netr_LogonSamLogon(p
, tctx
, &r
);
204 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
206 torture_assert(tctx
, creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
207 "Credential chaining failed");
209 /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
212 logon
.generic
= &generic
;
215 creds_client_authenticator(creds
, &auth
);
216 r
.in
.credential
= &auth
;
217 r
.in
.return_authenticator
= &auth2
;
218 r
.in
.logon_level
= NetlogonGenericInformation
;
220 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
221 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
222 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
224 status
= dcerpc_netr_LogonSamLogon(p
, tctx
, &r
);
226 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
228 torture_assert(tctx
, creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
229 "Credential chaining failed");
231 pac_wrapped_struct
.ChecksumLength
= session_info
->server_info
->pac_srv_sig
.signature
.length
;
232 pac_wrapped_struct
.SignatureType
= session_info
->server_info
->pac_kdc_sig
.type
;
234 /* Break the SignatureType */
235 pac_wrapped_struct
.SignatureType
++;
237 pac_wrapped_struct
.SignatureLength
= session_info
->server_info
->pac_kdc_sig
.signature
.length
;
238 pac_wrapped_struct
.ChecksumAndSignature
= payload
239 = data_blob_talloc(tmp_ctx
, NULL
,
240 pac_wrapped_struct
.ChecksumLength
241 + pac_wrapped_struct
.SignatureLength
);
242 memcpy(&payload
.data
[0],
243 session_info
->server_info
->pac_srv_sig
.signature
.data
,
244 pac_wrapped_struct
.ChecksumLength
);
245 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
246 session_info
->server_info
->pac_kdc_sig
.signature
.data
,
247 pac_wrapped_struct
.SignatureLength
);
249 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, lp_iconv_convenience(tctx
->lp_ctx
), &pac_wrapped_struct
,
250 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
251 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
253 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
254 creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
256 generic
.length
= pac_wrapped
.length
;
257 generic
.data
= pac_wrapped
.data
;
259 logon
.generic
= &generic
;
262 creds_client_authenticator(creds
, &auth
);
263 r
.in
.credential
= &auth
;
264 r
.in
.return_authenticator
= &auth2
;
265 r
.in
.logon_level
= NetlogonGenericInformation
;
267 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
268 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
269 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
271 status
= dcerpc_netr_LogonSamLogon(p
, tctx
, &r
);
273 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_LOGON_FAILURE
, "LogonSamLogon failed");
275 torture_assert(tctx
, creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
276 "Credential chaining failed");
278 pac_wrapped_struct
.ChecksumLength
= session_info
->server_info
->pac_srv_sig
.signature
.length
;
279 pac_wrapped_struct
.SignatureType
= session_info
->server_info
->pac_kdc_sig
.type
;
280 pac_wrapped_struct
.SignatureLength
= session_info
->server_info
->pac_kdc_sig
.signature
.length
;
282 pac_wrapped_struct
.ChecksumAndSignature
= payload
283 = data_blob_talloc(tmp_ctx
, NULL
,
284 pac_wrapped_struct
.ChecksumLength
285 + pac_wrapped_struct
.SignatureLength
);
286 memcpy(&payload
.data
[0],
287 session_info
->server_info
->pac_srv_sig
.signature
.data
,
288 pac_wrapped_struct
.ChecksumLength
);
289 memcpy(&payload
.data
[pac_wrapped_struct
.ChecksumLength
],
290 session_info
->server_info
->pac_kdc_sig
.signature
.data
,
291 pac_wrapped_struct
.SignatureLength
);
293 /* Break the signature length */
294 pac_wrapped_struct
.SignatureLength
++;
296 ndr_err
= ndr_push_struct_blob(&pac_wrapped
, tmp_ctx
, lp_iconv_convenience(tctx
->lp_ctx
), &pac_wrapped_struct
,
297 (ndr_push_flags_fn_t
)ndr_push_PAC_Validate
);
298 torture_assert(tctx
, NDR_ERR_CODE_IS_SUCCESS(ndr_err
), "ndr_push_struct_blob of PACValidate structure failed");
300 torture_assert(tctx
, (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
), "not willing to even try a PACValidate without RC4 encryption");
301 creds_arcfour_crypt(creds
, pac_wrapped
.data
, pac_wrapped
.length
);
303 generic
.length
= pac_wrapped
.length
;
304 generic
.data
= pac_wrapped
.data
;
306 logon
.generic
= &generic
;
309 creds_client_authenticator(creds
, &auth
);
310 r
.in
.credential
= &auth
;
311 r
.in
.return_authenticator
= &auth2
;
312 r
.in
.logon_level
= NetlogonGenericInformation
;
314 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
315 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
316 r
.in
.validation_level
= NetlogonValidationGenericInfo2
;
318 status
= dcerpc_netr_LogonSamLogon(p
, tctx
, &r
);
320 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_INVALID_PARAMETER
, "LogonSamLogon failed");
322 torture_assert(tctx
, creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
323 "Credential chaining failed");
327 struct torture_suite
*torture_rpc_remote_pac(TALLOC_CTX
*mem_ctx
)
329 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "PAC");
330 struct torture_rpc_tcase
*tcase
;
332 tcase
= torture_suite_add_machine_rpc_iface_tcase(suite
, "netlogon",
333 &ndr_table_netlogon
, TEST_MACHINE_NAME
);
334 torture_rpc_tcase_add_test_creds(tcase
, "verify", test_PACVerify
);