~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/rpc/remote_pac.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "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"
 
36
 
 
37
#define TEST_MACHINE_NAME "torturepactest"
 
38
 
 
39
/* Check to see if we can pass the PAC across to the NETLOGON server for validation */
 
40
 
 
41
/* Also happens to be a really good one-step verfication of our Kerberos stack */
 
42
 
 
43
static bool test_PACVerify(struct torture_context *tctx, 
 
44
                           struct dcerpc_pipe *p,
 
45
                           struct cli_credentials *credentials)
 
46
{
 
47
        NTSTATUS status;
 
48
 
 
49
        struct netr_LogonSamLogon r;
 
50
 
 
51
        union netr_LogonLevel logon;
 
52
        union netr_Validation validation;
 
53
        uint8_t authoritative;
 
54
        struct netr_Authenticator return_authenticator;
 
55
 
 
56
        struct netr_GenericInfo generic;
 
57
        struct netr_Authenticator auth, auth2;
 
58
        
 
59
 
 
60
        struct creds_CredentialState *creds;
 
61
        struct gensec_security *gensec_client_context;
 
62
        struct gensec_security *gensec_server_context;
 
63
 
 
64
        DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload;
 
65
        struct PAC_Validate pac_wrapped_struct;
 
66
        
 
67
        enum ndr_err_code ndr_err;
 
68
 
 
69
        struct auth_session_info *session_info;
 
70
 
 
71
        char *tmp_dir;
 
72
 
 
73
        TALLOC_CTX *tmp_ctx = talloc_new(tctx);
 
74
        
 
75
        torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
 
76
 
 
77
        if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
 
78
                                    credentials, SEC_CHAN_BDC, 
 
79
                                    &creds)) {
 
80
                return false;
 
81
        }
 
82
 
 
83
        status = torture_temp_dir(tctx, "PACVerify", &tmp_dir);
 
84
        torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed");
 
85
 
 
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");
 
89
 
 
90
        status = gensec_set_target_hostname(gensec_client_context, TEST_MACHINE_NAME);
 
91
 
 
92
        status = gensec_set_credentials(gensec_client_context, cmdline_credentials);
 
93
        torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
 
94
 
 
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");
 
97
 
 
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");
 
102
 
 
103
        status = gensec_set_credentials(gensec_server_context, credentials);
 
104
        torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
 
105
 
 
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");
 
108
 
 
109
        server_to_client = data_blob(NULL, 0);
 
110
        
 
111
        do {
 
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");
 
116
                }
 
117
 
 
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");
 
121
                }
 
122
 
 
123
                if (NT_STATUS_IS_OK(status)) {
 
124
                        break;
 
125
                }
 
126
        } while (1);
 
127
 
 
128
        /* Extract the PAC using Samba's code */
 
129
 
 
130
        status = gensec_session_info(gensec_server_context, &session_info);
 
131
        torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
 
132
        
 
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);
 
146
 
 
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");
 
150
                
 
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);
 
153
 
 
154
        generic.length = pac_wrapped.length;
 
155
        generic.data = pac_wrapped.data;
 
156
 
 
157
        /* Validate it over the netlogon pipe */
 
158
 
 
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;
 
165
 
 
166
        generic.package_name.string = "Kerberos";
 
167
 
 
168
        logon.generic = &generic;
 
169
 
 
170
        ZERO_STRUCT(auth2);
 
171
        creds_client_authenticator(creds, &auth);
 
172
        r.in.credential = &auth;
 
173
        r.in.return_authenticator = &auth2;
 
174
        r.in.logon = &logon;
 
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;
 
182
 
 
183
        status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 
184
 
 
185
        torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
 
186
        
 
187
        /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
 
188
        generic.data[generic.length-1]++;
 
189
 
 
190
        logon.generic = &generic;
 
191
 
 
192
        ZERO_STRUCT(auth2);
 
193
        creds_client_authenticator(creds, &auth);
 
194
        r.in.credential = &auth;
 
195
        r.in.return_authenticator = &auth2;
 
196
        r.in.logon_level = NetlogonGenericInformation;
 
197
        r.in.logon = &logon;
 
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;
 
201
 
 
202
        status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 
203
 
 
204
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
 
205
        
 
206
        torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 
207
                       "Credential chaining failed");
 
208
 
 
209
        /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
 
210
        generic.length--;
 
211
 
 
212
        logon.generic = &generic;
 
213
 
 
214
        ZERO_STRUCT(auth2);
 
215
        creds_client_authenticator(creds, &auth);
 
216
        r.in.credential = &auth;
 
217
        r.in.return_authenticator = &auth2;
 
218
        r.in.logon_level = NetlogonGenericInformation;
 
219
        r.in.logon = &logon;
 
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;
 
223
 
 
224
        status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 
225
 
 
226
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
 
227
        
 
228
        torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 
229
                       "Credential chaining failed");
 
230
 
 
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;
 
233
        
 
234
        /* Break the SignatureType */
 
235
        pac_wrapped_struct.SignatureType++;
 
236
 
 
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);
 
248
        
 
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");
 
252
        
 
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);
 
255
        
 
256
        generic.length = pac_wrapped.length;
 
257
        generic.data = pac_wrapped.data;
 
258
 
 
259
        logon.generic = &generic;
 
260
 
 
261
        ZERO_STRUCT(auth2);
 
262
        creds_client_authenticator(creds, &auth);
 
263
        r.in.credential = &auth;
 
264
        r.in.return_authenticator = &auth2;
 
265
        r.in.logon_level = NetlogonGenericInformation;
 
266
        r.in.logon = &logon;
 
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;
 
270
        
 
271
        status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 
272
        
 
273
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
 
274
        
 
275
        torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 
276
                       "Credential chaining failed");
 
277
 
 
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;
 
281
 
 
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);
 
292
        
 
293
        /* Break the signature length */
 
294
        pac_wrapped_struct.SignatureLength++;
 
295
 
 
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");
 
299
        
 
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);
 
302
        
 
303
        generic.length = pac_wrapped.length;
 
304
        generic.data = pac_wrapped.data;
 
305
 
 
306
        logon.generic = &generic;
 
307
 
 
308
        ZERO_STRUCT(auth2);
 
309
        creds_client_authenticator(creds, &auth);
 
310
        r.in.credential = &auth;
 
311
        r.in.return_authenticator = &auth2;
 
312
        r.in.logon_level = NetlogonGenericInformation;
 
313
        r.in.logon = &logon;
 
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;
 
317
        
 
318
        status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 
319
        
 
320
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
 
321
        
 
322
        torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 
323
                       "Credential chaining failed");
 
324
        return true;
 
325
}
 
326
 
 
327
struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
 
328
{
 
329
        struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
 
330
        struct torture_rpc_tcase *tcase;
 
331
 
 
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);
 
335
 
 
336
        return suite;
 
337
}