r11272: In trying to track down why Win2k3 is again rejecting our PAC, ensure
[kai/samba-autobuild/.git] / source4 / auth / kerberos / kerberos_pac.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Create and parse the krb5 PAC
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7    Copyright (C) Andrew Tridgell 2001
8    Copyright (C) Luke Howard 2002-2003
9    Copyright (C) Stefan Metzmacher 2004-2005
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include "includes.h"
28 #include "system/kerberos.h"
29 #include "system/time.h"
30 #include "system/network.h"
31 #include "auth/auth.h"
32 #include "auth/kerberos/kerberos.h"
33 #include "librpc/gen_ndr/ndr_krb5pac.h"
34 #include "auth/auth.h"
35
36 static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 
37                                           DATA_BLOB pac_data,
38                                           struct PAC_SIGNATURE_DATA *sig,
39                                           krb5_context context,
40                                           krb5_keyblock *keyblock)
41 {
42         krb5_error_code ret;
43         krb5_crypto crypto;
44         Checksum cksum;
45
46         cksum.cksumtype         = (CKSUMTYPE)sig->type;
47         cksum.checksum.length   = sig->signature.length;
48         cksum.checksum.data     = sig->signature.data;
49
50         ret = krb5_crypto_init(context,
51                                keyblock,
52                                0,
53                                &crypto);
54         if (ret) {
55                 DEBUG(0,("krb5_crypto_init() failed: %s\n", 
56                           smb_get_krb5_error_message(context, ret, mem_ctx)));
57                 return ret;
58         }
59         ret = krb5_verify_checksum(context,
60                                    crypto,
61                                    KRB5_KU_OTHER_CKSUM,
62                                    pac_data.data,
63                                    pac_data.length,
64                                    &cksum);
65         krb5_crypto_destroy(context, crypto);
66
67         return ret;
68 }
69
70  NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
71                               struct PAC_DATA **pac_data_out,
72                               DATA_BLOB blob,
73                               krb5_context context,
74                               krb5_keyblock *krbtgt_keyblock,
75                               krb5_keyblock *service_keyblock,
76                               krb5_const_principal client_principal,
77                               time_t tgs_authtime)
78 {
79         krb5_error_code ret;
80         NTSTATUS status;
81         struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
82         struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
83         struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
84         struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
85         struct PAC_LOGON_INFO *logon_info = NULL;
86         struct PAC_LOGON_NAME *logon_name = NULL;
87         struct PAC_DATA *pac_data;
88         struct PAC_DATA_RAW *pac_data_raw;
89
90         DATA_BLOB *srv_sig_blob;
91         DATA_BLOB *kdc_sig_blob;
92
93         DATA_BLOB modified_pac_blob;
94         NTTIME tgs_authtime_nttime;
95         krb5_principal client_principal_pac;
96         int i;
97
98         pac_data = talloc(mem_ctx, struct PAC_DATA);
99         pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
100         kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
101         srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
102         if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
103                 return NT_STATUS_NO_MEMORY;
104         }
105
106         status = ndr_pull_struct_blob(&blob, pac_data, pac_data,
107                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
108         if (!NT_STATUS_IS_OK(status)) {
109                 DEBUG(0,("can't parse the PAC\n"));
110                 return status;
111         }
112
113         if (pac_data->num_buffers < 4) {
114                 /* we need logon_ingo, service_key and kdc_key */
115                 DEBUG(0,("less than 4 PAC buffers\n"));
116                 return NT_STATUS_INVALID_PARAMETER;
117         }
118
119         status = ndr_pull_struct_blob(&blob, pac_data_raw, pac_data_raw,
120                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
121         if (!NT_STATUS_IS_OK(status)) {
122                 DEBUG(0,("can't parse the PAC\n"));
123                 return status;
124         }
125
126         if (pac_data_raw->num_buffers < 4) {
127                 /* we need logon_ingo, service_key and kdc_key */
128                 DEBUG(0,("less than 4 PAC buffers\n"));
129                 return NT_STATUS_INVALID_PARAMETER;
130         }
131
132         if (pac_data->num_buffers != pac_data_raw->num_buffers) {
133                 /* we need logon_ingo, service_key and kdc_key */
134                 DEBUG(0,("misparse!  PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
135                          pac_data->num_buffers, pac_data_raw->num_buffers));
136                 return NT_STATUS_INVALID_PARAMETER;
137         }
138
139         for (i=0; i < pac_data->num_buffers; i++) {
140                 if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) {
141                         DEBUG(0,("misparse!  PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
142                                  i, pac_data->buffers[i].type, pac_data->buffers[i].type));
143                         return NT_STATUS_INVALID_PARAMETER;
144                 }
145                 switch (pac_data->buffers[i].type) {
146                         case PAC_TYPE_LOGON_INFO:
147                                 if (!pac_data->buffers[i].info) {
148                                         break;
149                                 }
150                                 logon_info = pac_data->buffers[i].info->logon_info.info;
151                                 break;
152                         case PAC_TYPE_SRV_CHECKSUM:
153                                 if (!pac_data->buffers[i].info) {
154                                         break;
155                                 }
156                                 srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
157                                 srv_sig_blob = &pac_data_raw->buffers[i].info->remaining;
158                                 break;
159                         case PAC_TYPE_KDC_CHECKSUM:
160                                 if (!pac_data->buffers[i].info) {
161                                         break;
162                                 }
163                                 kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
164                                 kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining;
165                                 break;
166                         case PAC_TYPE_LOGON_NAME:
167                                 logon_name = &pac_data->buffers[i].info->logon_name;
168                                 break;
169                         default:
170                                 break;
171                 }
172         }
173
174         if (!logon_info) {
175                 DEBUG(0,("PAC no logon_info\n"));
176                 return NT_STATUS_INVALID_PARAMETER;
177         }
178
179         if (!logon_name) {
180                 DEBUG(0,("PAC no logon_name\n"));
181                 return NT_STATUS_INVALID_PARAMETER;
182         }
183
184         if (!srv_sig_ptr || !srv_sig_blob) {
185                 DEBUG(0,("PAC no srv_key\n"));
186                 return NT_STATUS_INVALID_PARAMETER;
187         }
188
189         if (!kdc_sig_ptr || !kdc_sig_blob) {
190                 DEBUG(0,("PAC no kdc_key\n"));
191                 return NT_STATUS_INVALID_PARAMETER;
192         }
193
194         /* Find and zero out the signatures, as required by the signing algorithm */
195
196         /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
197         status = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
198                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
199         if (!NT_STATUS_IS_OK(status)) {
200                 DEBUG(0,("can't parse the KDC signature\n"));
201                 return status;
202         }
203         
204         status = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
205                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
206         if (!NT_STATUS_IS_OK(status)) {
207                 DEBUG(0,("can't parse the SRV signature\n"));
208                 return status;
209         }
210         
211         /* Now zero the decoded structure */
212         memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
213         memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
214         
215         /* and reencode, back into the same place it came from */
216         status = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
217                                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
218         if (!NT_STATUS_IS_OK(status)) {
219                 DEBUG(0,("can't repack the KDC signature\n"));
220                 return status;
221         }       
222         status = ndr_push_struct_blob(srv_sig_blob, pac_data_raw, srv_sig_wipe,
223                                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
224         if (!NT_STATUS_IS_OK(status)) {
225                 DEBUG(0,("can't repack the SRV signature\n"));
226                 return status;
227         }
228
229         /* push out the whole structure, but now with zero'ed signatures */
230         status = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw, pac_data_raw,
231                                          (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
232         if (!NT_STATUS_IS_OK(status)) {
233                 DEBUG(0,("can't repack the RAW PAC\n"));
234                 return status;
235         }
236
237         /* verify by service_key */
238         ret = check_pac_checksum(mem_ctx, 
239                                  modified_pac_blob, srv_sig_ptr, 
240                                  context, 
241                                  service_keyblock);
242         if (ret) {
243                 DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
244                           smb_get_krb5_error_message(context, ret, mem_ctx)));
245                 return NT_STATUS_ACCESS_DENIED;
246         }
247
248         if (krbtgt_keyblock) {
249                 ret = check_pac_checksum(mem_ctx, 
250                                             srv_sig_ptr->signature, kdc_sig_ptr, 
251                                             context, krbtgt_keyblock);
252                 if (ret) {
253                         DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
254                                   smb_get_krb5_error_message(context, ret, mem_ctx)));
255                         return NT_STATUS_ACCESS_DENIED;
256                 }
257         }
258
259         /* Convert to NT time, so as not to loose accuracy in comparison */
260         unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
261
262         if (tgs_authtime_nttime != logon_name->logon_time) {
263                 DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
264                 DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time)));
265                 DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime)));
266                 return NT_STATUS_ACCESS_DENIED;
267         }
268
269         ret = krb5_parse_name_norealm(context, logon_name->account_name, &client_principal_pac);
270         if (ret) {
271                 DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", 
272                           logon_name->account_name, 
273                           smb_get_krb5_error_message(context, ret, mem_ctx)));
274                 return NT_STATUS_INVALID_PARAMETER;
275         }
276
277         if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
278                 DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n", 
279                           logon_name->account_name));
280                 return NT_STATUS_ACCESS_DENIED;
281         }
282         
283 #if 0
284         if (strcasecmp(logon_info->info3.base.account_name.string, 
285                        "Administrator")== 0) {
286                 file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
287         }
288 #endif
289
290         DEBUG(0,("account_name: %s [%s]\n",
291                  logon_info->info3.base.account_name.string, 
292                  logon_info->info3.base.full_name.string));
293         *pac_data_out = pac_data;
294
295         return status;
296 }
297
298  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
299                                   struct PAC_LOGON_INFO **logon_info,
300                                   DATA_BLOB blob,
301                                   krb5_context context,
302                                   krb5_keyblock *krbtgt_keyblock,
303                                   krb5_keyblock *service_keyblock,
304                                   krb5_const_principal client_principal,
305                                   time_t tgs_authtime)
306 {
307         NTSTATUS nt_status;
308         struct PAC_DATA *pac_data;
309         int i;
310
311         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
312                                         blob,
313                                         context,
314                                         krbtgt_keyblock,
315                                         service_keyblock,
316                                         client_principal, 
317                                         tgs_authtime);
318         if (!NT_STATUS_IS_OK(nt_status)) {
319                 return nt_status;
320         }
321
322         *logon_info = NULL;
323         for (i=0; i < pac_data->num_buffers; i++) {
324                 if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
325                         continue;
326                 }
327                 *logon_info = pac_data->buffers[i].info->logon_info.info; 
328         }
329         if (!*logon_info) {
330                 return NT_STATUS_INVALID_PARAMETER;
331         }
332         return NT_STATUS_OK;
333 }
334
335 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 
336                                          DATA_BLOB *pac_data,
337                                          struct PAC_SIGNATURE_DATA *sig,
338                                          krb5_context context,
339                                          krb5_keyblock *keyblock)
340 {
341         krb5_error_code ret;
342         krb5_crypto crypto;
343         Checksum cksum;
344
345
346         ret = krb5_crypto_init(context,
347                                keyblock,
348                                0,
349                                &crypto);
350         if (ret) {
351                 DEBUG(0,("krb5_crypto_init() failed: %s\n",
352                           smb_get_krb5_error_message(context, ret, mem_ctx)));
353                 return ret;
354         }
355         ret = krb5_create_checksum(context,
356                                    crypto,
357                                    KRB5_KU_OTHER_CKSUM,
358                                    0,
359                                    pac_data->data,
360                                    pac_data->length,
361                                    &cksum);
362         if (ret) {
363                 DEBUG(2, ("PAC Verification failed: %s\n", 
364                           smb_get_krb5_error_message(context, ret, mem_ctx)));
365         }
366
367         krb5_crypto_destroy(context, crypto);
368
369         if (ret) {
370                 return ret;
371         }
372
373         sig->type = cksum.cksumtype;
374         sig->signature = data_blob_talloc(mem_ctx, cksum.checksum.data, cksum.checksum.length);
375         free_Checksum(&cksum);
376
377         return 0;
378 }
379
380  krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
381                                     struct PAC_DATA *pac_data,
382                                     krb5_context context,
383                                     krb5_keyblock *krbtgt_keyblock,
384                                     krb5_keyblock *service_keyblock,
385                                     DATA_BLOB *pac) 
386 {
387         NTSTATUS nt_status;
388         krb5_error_code ret;
389         DATA_BLOB zero_blob = data_blob(NULL, 0);
390         DATA_BLOB tmp_blob = data_blob(NULL, 0);
391         struct PAC_SIGNATURE_DATA *kdc_checksum = NULL;
392         struct PAC_SIGNATURE_DATA *srv_checksum = NULL;
393         int i;
394
395         /* First, just get the keytypes filled in (and lengths right, eventually) */
396         for (i=0; i < pac_data->num_buffers; i++) {
397                 if (pac_data->buffers[i].type != PAC_TYPE_KDC_CHECKSUM) {
398                         continue;
399                 }
400                 kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 
401                 ret = make_pac_checksum(mem_ctx, &zero_blob,
402                                         kdc_checksum, 
403                                         context, krbtgt_keyblock);
404                 if (ret) {
405                         DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
406                                   smb_get_krb5_error_message(context, ret, mem_ctx)));
407                         talloc_free(pac_data);
408                         return ret;
409                 }
410         }
411         
412         for (i=0; i < pac_data->num_buffers; i++) {
413                 if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) {
414                         continue;
415                 }
416                 srv_checksum = &pac_data->buffers[i].info->srv_cksum; 
417                 ret = make_pac_checksum(mem_ctx, &zero_blob, 
418                                         srv_checksum, 
419                                         context, service_keyblock);
420                 if (ret) {
421                         DEBUG(2, ("making service PAC checksum failed: %s\n", 
422                                   smb_get_krb5_error_message(context, ret, mem_ctx)));
423                         talloc_free(pac_data);
424                         return ret;
425                 }
426         }
427
428         if (!kdc_checksum) {
429                 DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!"));
430                 return EINVAL;
431         }
432         if (!srv_checksum) {
433                 DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!"));
434                 return EINVAL;
435         }
436
437         /* But wipe out the actual signatures */
438         memset(kdc_checksum->signature.data, '\0', kdc_checksum->signature.length);
439         memset(srv_checksum->signature.data, '\0', srv_checksum->signature.length);
440
441         nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
442                                          (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
443         if (!NT_STATUS_IS_OK(nt_status)) {
444                 DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
445                 talloc_free(pac_data);
446                 return EINVAL;
447         }
448
449         /* Then sign the result of the previous push, where the sig was zero'ed out */
450         ret = make_pac_checksum(mem_ctx, &tmp_blob, srv_checksum,
451                                 context, service_keyblock);
452
453         /* Then sign Server checksum */
454         ret = make_pac_checksum(mem_ctx, &srv_checksum->signature, kdc_checksum, context, krbtgt_keyblock);
455         if (ret) {
456                 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
457                           smb_get_krb5_error_message(context, ret, mem_ctx)));
458                 talloc_free(pac_data);
459                 return ret;
460         }
461
462         /* And push it out again, this time to the world.  This relies on determanistic pointer values */
463         nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
464                                          (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
465         if (!NT_STATUS_IS_OK(nt_status)) {
466                 DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
467                 talloc_free(pac_data);
468                 return EINVAL;
469         }
470
471         *pac = tmp_blob;
472
473         return ret;
474 }
475
476
477  krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
478                                      struct auth_serversupplied_info *server_info,
479                                      krb5_context context,
480                                      krb5_keyblock *krbtgt_keyblock,
481                                      krb5_keyblock *service_keyblock,
482                                      krb5_principal client_principal,
483                                      time_t tgs_authtime,
484                                      DATA_BLOB *pac)
485 {
486         NTSTATUS nt_status;
487         krb5_error_code ret;
488         struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
489         struct netr_SamInfo3 *sam3;
490         union PAC_INFO *u_LOGON_INFO;
491         struct PAC_LOGON_INFO *LOGON_INFO;
492         union PAC_INFO *u_LOGON_NAME;
493         struct PAC_LOGON_NAME *LOGON_NAME;
494         union PAC_INFO *u_KDC_CHECKSUM;
495         union PAC_INFO *u_SRV_CHECKSUM;
496
497         char *name;
498                 
499         enum {
500                 PAC_BUF_LOGON_INFO = 0,
501                 PAC_BUF_LOGON_NAME = 1,
502                 PAC_BUF_SRV_CHECKSUM = 2,
503                 PAC_BUF_KDC_CHECKSUM = 3,
504                 PAC_BUF_NUM_BUFFERS = 4
505         };
506
507         if (!pac_data) {
508                 return ENOMEM;
509         }
510
511         pac_data->num_buffers = PAC_BUF_NUM_BUFFERS;
512         pac_data->version = 0;
513
514         pac_data->buffers = talloc_array(pac_data, 
515                                          struct PAC_BUFFER,
516                                          pac_data->num_buffers);
517         if (!pac_data->buffers) {
518                 talloc_free(pac_data);
519                 return ENOMEM;
520         }
521
522         /* LOGON_INFO */
523         u_LOGON_INFO = talloc_zero(pac_data->buffers, union PAC_INFO);
524         if (!u_LOGON_INFO) {
525                 talloc_free(pac_data);
526                 return ENOMEM;
527         }
528         pac_data->buffers[PAC_BUF_LOGON_INFO].type = PAC_TYPE_LOGON_INFO;
529         pac_data->buffers[PAC_BUF_LOGON_INFO].info = u_LOGON_INFO;
530
531         /* LOGON_NAME */
532         u_LOGON_NAME = talloc_zero(pac_data->buffers, union PAC_INFO);
533         if (!u_LOGON_NAME) {
534                 talloc_free(pac_data);
535                 return ENOMEM;
536         }
537         pac_data->buffers[PAC_BUF_LOGON_NAME].type = PAC_TYPE_LOGON_NAME;
538         pac_data->buffers[PAC_BUF_LOGON_NAME].info = u_LOGON_NAME;
539         LOGON_NAME = &u_LOGON_NAME->logon_name;
540
541         /* SRV_CHECKSUM */
542         u_SRV_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
543         if (!u_SRV_CHECKSUM) {
544                 talloc_free(pac_data);
545                 return ENOMEM;
546         }
547         pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
548         pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = u_SRV_CHECKSUM;
549
550         /* KDC_CHECKSUM */
551         u_KDC_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
552         if (!u_KDC_CHECKSUM) {
553                 talloc_free(pac_data);
554                 return ENOMEM;
555         }
556         pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
557         pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = u_KDC_CHECKSUM;
558
559         /* now the real work begins... */
560
561         LOGON_INFO = talloc_zero(u_LOGON_INFO, struct PAC_LOGON_INFO);
562         if (!LOGON_INFO) {
563                 talloc_free(pac_data);
564                 return ENOMEM;
565         }
566         nt_status = auth_convert_server_info_saminfo3(LOGON_INFO, server_info, &sam3);
567         if (!NT_STATUS_IS_OK(nt_status)) {
568                 DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status)));
569                 talloc_free(pac_data);
570                 return EINVAL;
571         }
572
573         u_LOGON_INFO->logon_info.info           = LOGON_INFO;
574         LOGON_INFO->info3 = *sam3;
575
576         ret = krb5_unparse_name_norealm(context, client_principal, &name);
577         if (ret) {
578                 return ret;
579         }
580         LOGON_NAME->account_name        = talloc_strdup(LOGON_NAME, name);
581         free(name);
582         /*
583           this logon_time field is absolutely critical. This is what
584           caused all our PAC troubles :-)
585         */
586         unix_to_nt_time(&LOGON_NAME->logon_time, tgs_authtime);
587
588         ret = kerberos_encode_pac(mem_ctx, 
589                                   pac_data, 
590                                   context,
591                                   krbtgt_keyblock,
592                                   service_keyblock,
593                                   pac);
594         talloc_free(pac_data);
595         return ret;
596 }
597