~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/auth/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
   Validate the krb5 pac generation routines
 
5
   
 
6
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
 
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
   
 
19
   You should have received a copy of the GNU General Public License
 
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
*/
 
22
 
 
23
#include "includes.h"
 
24
#include "system/kerberos.h"
 
25
#include "auth/auth.h"
 
26
#include "auth/kerberos/kerberos.h"
 
27
#include "librpc/gen_ndr/ndr_krb5pac.h"
 
28
#include "samba3/samba3.h"
 
29
#include "libcli/security/security.h"
 
30
#include "torture/torture.h"
 
31
#include "auth/auth_sam_reply.h"
 
32
 
 
33
static bool torture_pac_self_check(struct torture_context *tctx)
 
34
{
 
35
        NTSTATUS nt_status;
 
36
        DATA_BLOB tmp_blob;
 
37
        struct PAC_DATA *pac_data;
 
38
        struct PAC_LOGON_INFO *logon_info;
 
39
        union netr_Validation validation;
 
40
 
 
41
        /* Generate a nice, arbitary keyblock */
 
42
        uint8_t server_bytes[16];
 
43
        uint8_t krbtgt_bytes[16];
 
44
        krb5_keyblock server_keyblock;
 
45
        krb5_keyblock krbtgt_keyblock;
 
46
        
 
47
        krb5_error_code ret;
 
48
 
 
49
        struct smb_krb5_context *smb_krb5_context;
 
50
 
 
51
        struct auth_serversupplied_info *server_info;
 
52
        struct auth_serversupplied_info *server_info_out;
 
53
 
 
54
        krb5_principal client_principal;
 
55
        time_t logon_time = time(NULL);
 
56
 
 
57
        TALLOC_CTX *mem_ctx = tctx;
 
58
 
 
59
        torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, 
 
60
                                                        NULL,
 
61
                                                        tctx->lp_ctx,
 
62
                                                        &smb_krb5_context), 
 
63
                       "smb_krb5_init_context");
 
64
 
 
65
        generate_random_buffer(server_bytes, 16);
 
66
        generate_random_buffer(krbtgt_bytes, 16);
 
67
 
 
68
        ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
 
69
                                 ENCTYPE_ARCFOUR_HMAC,
 
70
                                 server_bytes, sizeof(server_bytes),
 
71
                                 &server_keyblock);
 
72
        torture_assert(tctx, !ret, talloc_asprintf(tctx, 
 
73
                                                   "(self test) Server Keyblock encoding failed: %s", 
 
74
                                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
 
75
                                                                              ret, mem_ctx)));
 
76
 
 
77
        ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
 
78
                                 ENCTYPE_ARCFOUR_HMAC,
 
79
                                 krbtgt_bytes, sizeof(krbtgt_bytes),
 
80
                                 &krbtgt_keyblock);
 
81
        if (ret) {
 
82
                char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
 
83
                                                       ret, mem_ctx);
 
84
        
 
85
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
86
                                            &server_keyblock);
 
87
 
 
88
                torture_fail(tctx, talloc_asprintf(tctx, 
 
89
                                                   "(self test) KRBTGT Keyblock encoding failed: %s", err));
 
90
        }
 
91
 
 
92
        /* We need an input, and this one requires no underlying database */
 
93
        nt_status = auth_anonymous_server_info(mem_ctx, lp_netbios_name(tctx->lp_ctx), &server_info);
 
94
 
 
95
        if (!NT_STATUS_IS_OK(nt_status)) {
 
96
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
97
                                            &server_keyblock);
 
98
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
99
                                            &krbtgt_keyblock);
 
100
                torture_fail(tctx, "auth_anonymous_server_info");
 
101
        }
 
102
 
 
103
        ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, 
 
104
                                    server_info->account_name, 
 
105
                                    KRB5_PRINCIPAL_PARSE_NO_REALM, 
 
106
                                    &client_principal);
 
107
        if (ret) {
 
108
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
109
                                            &server_keyblock);
 
110
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
111
                                            &krbtgt_keyblock);
 
112
                torture_fail(tctx, "krb5_parse_name_flags(norealm)");
 
113
        }
 
114
 
 
115
        /* OK, go ahead and make a PAC */
 
116
        ret = kerberos_create_pac(mem_ctx, 
 
117
                                  lp_iconv_convenience(tctx->lp_ctx),
 
118
                                  server_info, 
 
119
                                  smb_krb5_context->krb5_context,  
 
120
                                  &krbtgt_keyblock,
 
121
                                  &server_keyblock,
 
122
                                  client_principal,
 
123
                                  logon_time,
 
124
                                  &tmp_blob);
 
125
        
 
126
        if (ret) {
 
127
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
128
                                            &krbtgt_keyblock);
 
129
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
130
                                            &server_keyblock);
 
131
                krb5_free_principal(smb_krb5_context->krb5_context, 
 
132
                                    client_principal);
 
133
 
 
134
                torture_fail(tctx, talloc_asprintf(tctx,
 
135
                                                   "(self test) PAC encoding failed: %s", 
 
136
                                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
 
137
                                                                              ret, mem_ctx)));
 
138
        }
 
139
 
 
140
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
141
 
 
142
        /* Now check that we can read it back (using full decode and validate) */
 
143
        nt_status = kerberos_decode_pac(mem_ctx, 
 
144
                                        lp_iconv_convenience(tctx->lp_ctx),
 
145
                                        &pac_data,
 
146
                                        tmp_blob,
 
147
                                        smb_krb5_context->krb5_context,
 
148
                                        &krbtgt_keyblock,
 
149
                                        &server_keyblock,
 
150
                                        client_principal, 
 
151
                                        logon_time, NULL);
 
152
 
 
153
        if (!NT_STATUS_IS_OK(nt_status)) {
 
154
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
155
                                            &krbtgt_keyblock);
 
156
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
157
                                            &server_keyblock);
 
158
                krb5_free_principal(smb_krb5_context->krb5_context, 
 
159
                                    client_principal);
 
160
 
 
161
                torture_fail(tctx, talloc_asprintf(tctx,
 
162
                                                   "(self test) PAC decoding failed: %s", 
 
163
                                                   nt_errstr(nt_status)));
 
164
        }
 
165
 
 
166
        /* Now check we can read it back (using Heimdal's pac parsing) */
 
167
        nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
 
168
                                                     lp_iconv_convenience(tctx->lp_ctx),
 
169
                                                     tmp_blob, 
 
170
                                                     smb_krb5_context->krb5_context,
 
171
                                                     &server_info_out);
 
172
 
 
173
        if (!dom_sid_equal(server_info->account_sid, 
 
174
                           server_info_out->account_sid)) {
 
175
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
176
                                            &krbtgt_keyblock);
 
177
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
178
                                            &server_keyblock);
 
179
                krb5_free_principal(smb_krb5_context->krb5_context, 
 
180
                                    client_principal);
 
181
 
 
182
                torture_fail(tctx,  
 
183
                             talloc_asprintf(tctx, 
 
184
                                             "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
 
185
                                             dom_sid_string(mem_ctx, server_info->account_sid), 
 
186
                                             dom_sid_string(mem_ctx, server_info_out->account_sid)));
 
187
        }
 
188
        talloc_free(server_info_out);
 
189
 
 
190
        /* Now check that we can read it back (yet again) */
 
191
        nt_status = kerberos_pac_logon_info(mem_ctx, 
 
192
                                            lp_iconv_convenience(tctx->lp_ctx),
 
193
                                            &logon_info,
 
194
                                            tmp_blob,
 
195
                                            smb_krb5_context->krb5_context,
 
196
                                            &krbtgt_keyblock,
 
197
                                            &server_keyblock,
 
198
                                            client_principal, 
 
199
                                            logon_time, 
 
200
                                            NULL);
 
201
        
 
202
        if (!NT_STATUS_IS_OK(nt_status)) {
 
203
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
204
                                            &krbtgt_keyblock);
 
205
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
206
                                            &server_keyblock);
 
207
                krb5_free_principal(smb_krb5_context->krb5_context, 
 
208
                                    client_principal);
 
209
                
 
210
                torture_fail(tctx,  
 
211
                             talloc_asprintf(tctx, 
 
212
                                             "(self test) PAC decoding (for logon info) failed: %s", 
 
213
                                             nt_errstr(nt_status)));
 
214
        }
 
215
        
 
216
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
217
                                    &krbtgt_keyblock);
 
218
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
219
                                    &server_keyblock);
 
220
        krb5_free_principal(smb_krb5_context->krb5_context, 
 
221
                            client_principal);
 
222
 
 
223
        /* And make a server info from the samba-parsed PAC */
 
224
        validation.sam3 = &logon_info->info3;
 
225
        nt_status = make_server_info_netlogon_validation(mem_ctx,
 
226
                                                         "",
 
227
                                                         3, &validation,
 
228
                                                         &server_info_out); 
 
229
        if (!NT_STATUS_IS_OK(nt_status)) {
 
230
                torture_fail(tctx, 
 
231
                             talloc_asprintf(tctx, 
 
232
                                             "(self test) PAC decoding (make server info) failed: %s", 
 
233
                                             nt_errstr(nt_status)));
 
234
        }
 
235
        
 
236
        if (!dom_sid_equal(server_info->account_sid, 
 
237
                           server_info_out->account_sid)) {
 
238
                torture_fail(tctx,  
 
239
                             talloc_asprintf(tctx, 
 
240
                                             "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
 
241
                                             dom_sid_string(mem_ctx, server_info->account_sid), 
 
242
                                             dom_sid_string(mem_ctx, server_info_out->account_sid)));
 
243
        }
 
244
        return true;
 
245
}
 
246
 
 
247
 
 
248
/* This is the PAC generated on my test network, by my test Win2k3 server.
 
249
   -- abartlet 2005-07-04
 
250
*/
 
251
 
 
252
static const uint8_t saved_pac[] = {
 
253
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
 
254
        0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
 
255
        0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
 
256
        0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
 
257
        0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
 
258
        0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
 
259
        0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
 
260
        0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
 
261
        0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
 
262
        0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
 
263
        0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
 
264
        0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
 
265
        0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
 
266
        0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
267
        0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
 
268
        0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
269
        0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
270
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
271
        0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
272
        0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
 
273
        0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
 
274
        0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
275
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
276
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
277
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
278
        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
 
279
        0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
 
280
        0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
 
281
        0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
 
282
        0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
 
283
        0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
 
284
        0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
 
285
        0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
 
286
        0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
287
        0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
 
288
        0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
 
289
        0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
 
290
        0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
 
291
        0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
 
292
};
 
293
 
 
294
/* Check with a known 'well formed' PAC, from my test server */
 
295
static bool torture_pac_saved_check(struct torture_context *tctx)
 
296
{
 
297
        NTSTATUS nt_status;
 
298
        enum ndr_err_code ndr_err;
 
299
        DATA_BLOB tmp_blob, validate_blob;
 
300
        struct PAC_DATA *pac_data, pac_data2;
 
301
        struct PAC_LOGON_INFO *logon_info;
 
302
        union netr_Validation validation;
 
303
        const char *pac_file, *pac_kdc_key, *pac_member_key;
 
304
        struct auth_serversupplied_info *server_info_out;
 
305
 
 
306
        krb5_keyblock server_keyblock;
 
307
        krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
 
308
        struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
 
309
        
 
310
        krb5_error_code ret;
 
311
        struct smb_krb5_context *smb_krb5_context;
 
312
 
 
313
        const char *principal_string;
 
314
        char *broken_principal_string;
 
315
        krb5_principal client_principal;
 
316
        const char *authtime_string;
 
317
        time_t authtime;
 
318
        TALLOC_CTX *mem_ctx = tctx;
 
319
 
 
320
        torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
 
321
                                                        tctx->lp_ctx,
 
322
                                                        &smb_krb5_context),
 
323
                       "smb_krb5_init_context");
 
324
 
 
325
        pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key", 
 
326
                                             "B286757148AF7FD252C53603A150B7E7");
 
327
 
 
328
        pac_member_key = torture_setting_string(tctx, "pac_member_key", 
 
329
                                                "D217FAEAE5E6B5F95CCC94077AB8A5FC");
 
330
 
 
331
        torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
 
332
        torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
 
333
 
 
334
        /* The krbtgt key in use when the above PAC was generated.
 
335
         * This is an arcfour-hmac-md5 key, extracted with our 'net
 
336
         * samdump' tool. */
 
337
        if (*pac_kdc_key == 0) {
 
338
                krbtgt_bytes = NULL;
 
339
        } else {
 
340
                krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
 
341
                if (!krbtgt_bytes) {
 
342
                        torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
 
343
                }
 
344
        }
 
345
 
 
346
        krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
 
347
        if (!krbsrv_bytes) {
 
348
                torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
 
349
        }
 
350
 
 
351
        ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
 
352
                                 ENCTYPE_ARCFOUR_HMAC,
 
353
                                 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
 
354
                                 &server_keyblock);
 
355
        torture_assert(tctx, !ret,
 
356
                       talloc_asprintf(tctx,
 
357
                                       "(saved test) Server Keyblock encoding failed: %s", 
 
358
                                       smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
 
359
                                                                  ret, mem_ctx)));
 
360
 
 
361
        if (krbtgt_bytes) {
 
362
                ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
 
363
                                         ENCTYPE_ARCFOUR_HMAC,
 
364
                                         krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
 
365
                                         &krbtgt_keyblock);
 
366
                if (ret) {
 
367
                        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
368
                                                    &server_keyblock);
 
369
                        torture_fail(tctx, 
 
370
                                     talloc_asprintf(tctx, 
 
371
                                                     "(saved test) Server Keyblock encoding failed: %s", 
 
372
                                                     smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
 
373
                                                                                ret, mem_ctx)));
 
374
                }
 
375
                krbtgt_keyblock_p = &krbtgt_keyblock;
 
376
        } else {
 
377
                krbtgt_keyblock_p = NULL;
 
378
        }
 
379
 
 
380
        pac_file = torture_setting_string(tctx, "pac_file", NULL);
 
381
        if (pac_file) {
 
382
                tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
 
383
                torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
 
384
        } else {
 
385
                tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
 
386
        }
 
387
        
 
388
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
389
 
 
390
        principal_string = torture_setting_string(tctx, "pac_client_principal", 
 
391
                                                  "w2003final$@WIN2K3.THINKER.LOCAL");
 
392
 
 
393
        authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
 
394
        authtime = strtoull(authtime_string, NULL, 0);
 
395
 
 
396
        ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
 
397
                              &client_principal);
 
398
        if (ret) {
 
399
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
400
                                            krbtgt_keyblock_p);
 
401
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
402
                                            &server_keyblock);
 
403
                torture_fail(tctx,  
 
404
                             talloc_asprintf(tctx, 
 
405
                                             "(saved test) parsing of client principal [%s] failed: %s", 
 
406
                                             principal_string, 
 
407
                                             smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
 
408
        }
 
409
 
 
410
        /* Decode and verify the signaure on the PAC */
 
411
        nt_status = kerberos_decode_pac(mem_ctx, 
 
412
                                        lp_iconv_convenience(tctx->lp_ctx),
 
413
                                        &pac_data,
 
414
                                        tmp_blob,
 
415
                                        smb_krb5_context->krb5_context,
 
416
                                        krbtgt_keyblock_p,
 
417
                                        &server_keyblock, 
 
418
                                        client_principal, authtime, NULL);
 
419
        if (!NT_STATUS_IS_OK(nt_status)) {
 
420
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
421
                                            krbtgt_keyblock_p);
 
422
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
423
                                            &server_keyblock);
 
424
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
425
                
 
426
                torture_fail(tctx, talloc_asprintf(tctx, 
 
427
                                                   "(saved test) PAC decoding failed: %s", 
 
428
                                                   nt_errstr(nt_status)));
 
429
        }
 
430
 
 
431
        /* Now check we can read it back (using Heimdal's pac parsing) */
 
432
        nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
 
433
                                                     lp_iconv_convenience(tctx->lp_ctx),
 
434
                                                     tmp_blob, 
 
435
                                                     smb_krb5_context->krb5_context,
 
436
                                                     &server_info_out);
 
437
 
 
438
        if (!NT_STATUS_IS_OK(nt_status)) {
 
439
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
440
                                            krbtgt_keyblock_p);
 
441
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
442
                                            &server_keyblock);
 
443
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
444
                
 
445
                torture_fail(tctx, talloc_asprintf(tctx, 
 
446
                                                   "(saved test) Heimdal PAC decoding failed: %s", 
 
447
                                                   nt_errstr(nt_status)));
 
448
        }
 
449
 
 
450
        if (!pac_file &&
 
451
            !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
 
452
                                                "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
 
453
                           server_info_out->account_sid)) {
 
454
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
455
                                            krbtgt_keyblock_p);
 
456
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
457
                                            &server_keyblock);
 
458
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
459
 
 
460
                torture_fail(tctx,  
 
461
                             talloc_asprintf(tctx, 
 
462
                                             "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
 
463
                                             "S-1-5-21-3048156945-3961193616-3706469200-1005", 
 
464
                                             dom_sid_string(mem_ctx, server_info_out->account_sid)));
 
465
        }
 
466
 
 
467
        talloc_free(server_info_out);
 
468
 
 
469
        /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
 
470
        nt_status = kerberos_pac_logon_info(mem_ctx, 
 
471
                                            lp_iconv_convenience(tctx->lp_ctx),
 
472
                                            &logon_info,
 
473
                                            tmp_blob,
 
474
                                            smb_krb5_context->krb5_context,
 
475
                                            krbtgt_keyblock_p,
 
476
                                            &server_keyblock,
 
477
                                            client_principal, authtime, NULL);
 
478
 
 
479
        if (!NT_STATUS_IS_OK(nt_status)) {
 
480
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
481
                                            krbtgt_keyblock_p);
 
482
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
483
                                            &server_keyblock);
 
484
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
485
        
 
486
                torture_fail(tctx,  
 
487
                             talloc_asprintf(tctx, 
 
488
                                             "(saved test) PAC decoding (for logon info) failed: %s", 
 
489
                                             nt_errstr(nt_status)));
 
490
        }
 
491
 
 
492
        validation.sam3 = &logon_info->info3;
 
493
        nt_status = make_server_info_netlogon_validation(mem_ctx,
 
494
                                                         "",
 
495
                                                         3, &validation,
 
496
                                                         &server_info_out); 
 
497
        if (!NT_STATUS_IS_OK(nt_status)) {
 
498
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
499
                                            krbtgt_keyblock_p);
 
500
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
501
                                            &server_keyblock);
 
502
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
503
 
 
504
                torture_fail(tctx,  
 
505
                             talloc_asprintf(tctx, 
 
506
                                             "(saved test) PAC decoding (make server info) failed: %s", 
 
507
                                             nt_errstr(nt_status)));
 
508
        }
 
509
 
 
510
        if (!pac_file &&
 
511
            !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
 
512
                                                "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
 
513
                           server_info_out->account_sid)) {
 
514
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
515
                                            krbtgt_keyblock_p);
 
516
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
517
                                            &server_keyblock);
 
518
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
519
 
 
520
                torture_fail(tctx,  
 
521
                             talloc_asprintf(tctx, 
 
522
                                             "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
 
523
                                             "S-1-5-21-3048156945-3961193616-3706469200-1005", 
 
524
                                             dom_sid_string(mem_ctx, server_info_out->account_sid)));
 
525
        }
 
526
 
 
527
        if (krbtgt_bytes == NULL) {
 
528
                torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
 
529
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
530
                                            &server_keyblock);
 
531
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
532
                return true;
 
533
        }
 
534
 
 
535
        ret = kerberos_encode_pac(mem_ctx, 
 
536
                                  lp_iconv_convenience(tctx->lp_ctx),
 
537
                                  pac_data,
 
538
                                  smb_krb5_context->krb5_context,
 
539
                                  krbtgt_keyblock_p,
 
540
                                  &server_keyblock,
 
541
                                  &validate_blob);
 
542
 
 
543
        if (ret != 0) {
 
544
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
545
                                            krbtgt_keyblock_p);
 
546
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
547
                                            &server_keyblock);
 
548
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
549
 
 
550
                torture_fail(tctx, "(saved test) PAC push failed");
 
551
        }
 
552
 
 
553
        dump_data(10, validate_blob.data, validate_blob.length);
 
554
 
 
555
        /* compare both the length and the data bytes after a
 
556
         * pull/push cycle.  This ensures we use the exact same
 
557
         * pointer, padding etc algorithms as win2k3.
 
558
         */
 
559
        if (tmp_blob.length != validate_blob.length) {
 
560
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
561
                                            krbtgt_keyblock_p);
 
562
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
563
                                            &server_keyblock);
 
564
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
565
 
 
566
                torture_fail(tctx, 
 
567
                             talloc_asprintf(tctx, 
 
568
                                             "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
 
569
                                             (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
 
570
        }
 
571
 
 
572
        if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
 
573
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
574
                                            krbtgt_keyblock_p);
 
575
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
576
                                            &server_keyblock);
 
577
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
578
 
 
579
                DEBUG(0, ("tmp_data:\n"));
 
580
                dump_data(0, tmp_blob.data, tmp_blob.length);
 
581
                DEBUG(0, ("validate_blob:\n"));
 
582
                dump_data(0, validate_blob.data, validate_blob.length);
 
583
 
 
584
                torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
 
585
        }
 
586
 
 
587
        ret = kerberos_create_pac(mem_ctx, 
 
588
                                  lp_iconv_convenience(tctx->lp_ctx),
 
589
                                  server_info_out,
 
590
                                  smb_krb5_context->krb5_context,
 
591
                                  krbtgt_keyblock_p,
 
592
                                  &server_keyblock,
 
593
                                  client_principal, authtime,
 
594
                                  &validate_blob);
 
595
 
 
596
        if (ret != 0) {
 
597
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
598
                                            krbtgt_keyblock_p);
 
599
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
600
                                            &server_keyblock);
 
601
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
602
 
 
603
                torture_fail(tctx, "(saved test) regnerated PAC create failed");
 
604
        }
 
605
 
 
606
        dump_data(10,validate_blob.data,validate_blob.length);
 
607
 
 
608
        /* compare both the length and the data bytes after a
 
609
         * pull/push cycle.  This ensures we use the exact same
 
610
         * pointer, padding etc algorithms as win2k3.
 
611
         */
 
612
        if (tmp_blob.length != validate_blob.length) {
 
613
                ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
 
614
                                               lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
 
615
                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
 
616
                nt_status = ndr_map_error2ntstatus(ndr_err);
 
617
                torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
 
618
                
 
619
                NDR_PRINT_DEBUG(PAC_DATA, pac_data);
 
620
 
 
621
                NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
 
622
 
 
623
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
624
                                            krbtgt_keyblock_p);
 
625
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
626
                                            &server_keyblock);
 
627
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
628
 
 
629
                torture_fail(tctx, talloc_asprintf(tctx, 
 
630
                                                   "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
 
631
                                                   (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
 
632
        }
 
633
 
 
634
        if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
 
635
                ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
 
636
                                               lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
 
637
                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
 
638
                nt_status = ndr_map_error2ntstatus(ndr_err);
 
639
                torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
 
640
                
 
641
                NDR_PRINT_DEBUG(PAC_DATA, pac_data);
 
642
 
 
643
                NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
 
644
 
 
645
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
646
                                            krbtgt_keyblock_p);
 
647
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
648
                                            &server_keyblock);
 
649
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
650
 
 
651
                DEBUG(0, ("tmp_data:\n"));
 
652
                dump_data(0, tmp_blob.data, tmp_blob.length);
 
653
                DEBUG(0, ("validate_blob:\n"));
 
654
                dump_data(0, validate_blob.data, validate_blob.length);
 
655
 
 
656
                torture_fail(tctx, talloc_asprintf(tctx, 
 
657
                                                   "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
 
658
        }
 
659
 
 
660
        /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
 
661
        nt_status = kerberos_decode_pac(mem_ctx, 
 
662
                                        lp_iconv_convenience(tctx->lp_ctx),
 
663
                                        &pac_data,
 
664
                                        tmp_blob,
 
665
                                        smb_krb5_context->krb5_context,
 
666
                                        krbtgt_keyblock_p,
 
667
                                        &server_keyblock,
 
668
                                        client_principal, 
 
669
                                        authtime + 1, NULL);
 
670
        if (NT_STATUS_IS_OK(nt_status)) {
 
671
 
 
672
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
673
                                            krbtgt_keyblock_p);
 
674
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
675
                                            &server_keyblock);
 
676
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
677
                torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
 
678
        }
 
679
 
 
680
        /* Break the client principal */
 
681
        krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
682
 
 
683
        broken_principal_string = talloc_strdup(mem_ctx, principal_string);
 
684
        broken_principal_string[0]++;
 
685
 
 
686
        ret = krb5_parse_name(smb_krb5_context->krb5_context,
 
687
                              broken_principal_string, &client_principal);
 
688
        if (ret) {
 
689
 
 
690
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
691
                                            krbtgt_keyblock_p);
 
692
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
693
                                            &server_keyblock);
 
694
                torture_fail(tctx, talloc_asprintf(tctx, 
 
695
                                                   "(saved test) parsing of broken client principal failed: %s", 
 
696
                                                   smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
 
697
        }
 
698
 
 
699
        nt_status = kerberos_decode_pac(mem_ctx, 
 
700
                                        lp_iconv_convenience(tctx->lp_ctx),
 
701
                                        &pac_data,
 
702
                                        tmp_blob,
 
703
                                        smb_krb5_context->krb5_context,
 
704
                                        krbtgt_keyblock_p,
 
705
                                        &server_keyblock,
 
706
                                        client_principal, 
 
707
                                        authtime, NULL);
 
708
        if (NT_STATUS_IS_OK(nt_status)) {
 
709
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
710
                                            krbtgt_keyblock_p);
 
711
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
712
                                            &server_keyblock);
 
713
                torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
 
714
        }
 
715
 
 
716
        /* Finally...  Bugger up the signature, and check we fail the checksum */
 
717
        tmp_blob.data[tmp_blob.length - 2]++;
 
718
 
 
719
        nt_status = kerberos_decode_pac(mem_ctx, 
 
720
                                        lp_iconv_convenience(tctx->lp_ctx),
 
721
                                        &pac_data,
 
722
                                        tmp_blob,
 
723
                                        smb_krb5_context->krb5_context,
 
724
                                        krbtgt_keyblock_p,
 
725
                                        &server_keyblock,
 
726
                                        client_principal, 
 
727
                                        authtime, NULL);
 
728
        if (NT_STATUS_IS_OK(nt_status)) {
 
729
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
730
                                            krbtgt_keyblock_p);
 
731
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
732
                                            &server_keyblock);
 
733
                torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
 
734
        }
 
735
 
 
736
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
737
                                    krbtgt_keyblock_p);
 
738
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
739
                                    &server_keyblock);
 
740
        return true;
 
741
}
 
742
 
 
743
struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
 
744
{
 
745
        struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
 
746
 
 
747
        torture_suite_add_simple_test(suite, "self check", 
 
748
                                      torture_pac_self_check);
 
749
        torture_suite_add_simple_test(suite, "saved check",
 
750
                                      torture_pac_saved_check);
 
751
        return suite;
 
752
}