r9084: 'resign' the sample PAC for the validation of the signature algorithms.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 5 Aug 2005 00:41:53 +0000 (00:41 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:31:15 +0000 (13:31 -0500)
If we ever get problems with the kerberos code, it should show up as a
different signature in this PAC.

This involved returning more data from the pac functions, so changed
some callers and split up some functions.

Andrew Bartlett
(This used to be commit d514a7491208afa0533bf9e99601147eb69e08c9)

source4/auth/gensec/gensec_gssapi.c
source4/auth/gensec/gensec_krb5.c
source4/auth/kerberos/kerberos.h
source4/auth/kerberos/kerberos_pac.c
source4/kdc/pac-glue.c
source4/torture/auth/pac.c

index 0a98b69f8294b4516c3bbd8ec1e9bf91bc25d6ea..b6fda0402f8ac8b1b6a314b0f261b2c9d4d37995 100644 (file)
@@ -795,9 +795,9 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
                gss_release_buffer(&min_stat, &pac);
                
                /* decode and verify the pac */
-               nt_status = kerberos_decode_pac(mem_ctx, &logon_info, pac_blob,
-                                               gensec_gssapi_state->smb_krb5_context,
-                                               NULL, keyblock);
+               nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info, pac_blob,
+                                                   gensec_gssapi_state->smb_krb5_context,
+                                                   NULL, keyblock);
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        union netr_Validation validation;
index 76f91717135373bbb4c2d006c3f8e5e1748a1046..2568f11006f5ce1cc22e5ff18c8fb29bcd04dd03 100644 (file)
@@ -449,9 +449,9 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
        account_name = principal;
 
        /* decode and verify the pac */
-       nt_status = kerberos_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac,
-                                       gensec_krb5_state->smb_krb5_context,
-                                       NULL, gensec_krb5_state->keyblock);
+       nt_status = kerberos_pac_logon_info(gensec_krb5_state, &logon_info, gensec_krb5_state->pac,
+                                           gensec_krb5_state->smb_krb5_context,
+                                           NULL, gensec_krb5_state->keyblock);
 
        /* IF we have the PAC - otherwise we need to get this
         * data from elsewere - local ldb, or (TODO) lookup of some
index dcafea3c0cb699beb12fb356e8d5fd18c9133413..0f1b0779b2e789ecc0b12e1f3dab8805ea4a0d46 100644 (file)
@@ -127,17 +127,29 @@ NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
                              struct smb_krb5_context *smb_krb5_context,
                              krb5_keytab *keytab);
 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
-                            struct PAC_LOGON_INFO **logon_info_out,
+                            struct PAC_DATA **pac_data_out,
                             DATA_BLOB blob,
                             struct smb_krb5_context *smb_krb5_context,
-                            krb5_keyblock *service_keyblock,
-                            krb5_keyblock *krbtgt_keyblock);
-
-krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+                            krb5_keyblock *krbtgt_keyblock,
+                            krb5_keyblock *service_keyblock);
+NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
+                                struct PAC_LOGON_INFO **logon_info,
+                                DATA_BLOB blob,
+                                struct smb_krb5_context *smb_krb5_context,
+                                krb5_keyblock *krbtgt_keyblock,
+                                krb5_keyblock *service_keyblock);
+krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
                                    struct auth_serversupplied_info *server_info,
                                    krb5_context context,
                                    krb5_keyblock *krbtgt_keyblock,
                                    krb5_keyblock *server_keyblock,
                                    DATA_BLOB *pac);
+
+krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+                                   struct PAC_DATA *pac_data,
+                                   krb5_context context,
+                                   krb5_keyblock *krbtgt_keyblock,
+                                   krb5_keyblock *service_keyblock,
+                                   DATA_BLOB *pac);
 #endif /* HAVE_KRB5 */
 
index f561bdfe76bb3b72c39ffea50eda1fc3b35e4752..83679972d9ee50e740a1883d90bceb7aeba0090e 100644 (file)
@@ -78,7 +78,7 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
 }
 
  NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
-                             struct PAC_LOGON_INFO **logon_info_out,
+                             struct PAC_DATA **pac_data_out,
                              DATA_BLOB blob,
                              struct smb_krb5_context *smb_krb5_context,
                              krb5_keyblock *krbtgt_keyblock,
@@ -90,46 +90,50 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
        struct PAC_SIGNATURE_DATA kdc_sig;
        struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
        struct PAC_LOGON_INFO *logon_info = NULL;
-       struct PAC_DATA pac_data;
+       struct PAC_DATA *pac_data;
+
        DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length);
        int i;
 
-       /* file_save("tmp_pac_data.dat",blob.data,blob.length); */
+       pac_data = talloc(mem_ctx, struct PAC_DATA);
+       if (!pac_data) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data,
-                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+       status = ndr_pull_struct_blob(&blob, mem_ctx, pac_data,
+                                     (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("can't parse the PAC\n"));
                return status;
        }
 
-       if (pac_data.num_buffers < 3) {
+       if (pac_data->num_buffers < 3) {
                /* we need logon_ingo, service_key and kdc_key */
                DEBUG(0,("less than 3 PAC buffers\n"));
                return NT_STATUS_FOOBAR;
        }
 
-       for (i=0; i < pac_data.num_buffers; i++) {
-               switch (pac_data.buffers[i].type) {
+       for (i=0; i < pac_data->num_buffers; i++) {
+               switch (pac_data->buffers[i].type) {
                        case PAC_TYPE_LOGON_INFO:
-                               if (!pac_data.buffers[i].info) {
+                               if (!pac_data->buffers[i].info) {
                                        break;
                                }
-                               logon_info = pac_data.buffers[i].info->logon_info.info;
+                               logon_info = pac_data->buffers[i].info->logon_info.info;
                                break;
                        case PAC_TYPE_SRV_CHECKSUM:
-                               if (!pac_data.buffers[i].info) {
+                               if (!pac_data->buffers[i].info) {
                                        break;
                                }
-                               srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum;
-                               srv_sig = pac_data.buffers[i].info->srv_cksum;
+                               srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
+                               srv_sig = pac_data->buffers[i].info->srv_cksum;
                                break;
                        case PAC_TYPE_KDC_CHECKSUM:
-                               if (!pac_data.buffers[i].info) {
+                               if (!pac_data->buffers[i].info) {
                                        break;
                                }
-                               kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum;
-                               kdc_sig = pac_data.buffers[i].info->kdc_cksum;
+                               kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
+                               kdc_sig = pac_data->buffers[i].info->kdc_cksum;
                                break;
                        case PAC_TYPE_LOGON_NAME:
                                break;
@@ -181,16 +185,56 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
                }
        }
 
+#if 0
+       if (strcasecmp(logon_info->info3.base.account_name.string, 
+                      "Administrator")== 0) {
+               file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
+       }
+#endif
+
        DEBUG(0,("account_name: %s [%s]\n",
                 logon_info->info3.base.account_name.string, 
                 logon_info->info3.base.full_name.string));
-       *logon_info_out = logon_info;
+       *pac_data_out = pac_data;
 
        return status;
 }
 
+ NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
+                                 struct PAC_LOGON_INFO **logon_info,
+                                 DATA_BLOB blob,
+                                 struct smb_krb5_context *smb_krb5_context,
+                                 krb5_keyblock *krbtgt_keyblock,
+                                 krb5_keyblock *service_keyblock)
+{
+       NTSTATUS nt_status;
+       struct PAC_DATA *pac_data;
+       int i;
+
+       nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
+                                       blob,
+                                       smb_krb5_context,
+                                       krbtgt_keyblock,
+                                       service_keyblock);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       *logon_info = NULL;
+       for (i=0; i < pac_data->num_buffers; i++) {
+               if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
+                       continue;
+               }
+               *logon_info = pac_data->buffers[i].info->logon_info.info; 
+       }
+       if (!*logon_info) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       return NT_STATUS_OK;
+}
+
 static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, 
-                                        DATA_BLOB pac_data,
+                                        DATA_BLOB *pac_data,
                                         struct PAC_SIGNATURE_DATA *sig,
                                         krb5_context context,
                                         krb5_keyblock *keyblock)
@@ -205,15 +249,16 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
                               0,
                               &crypto);
        if (ret) {
-               DEBUG(0,("krb5_crypto_init() failed\n"));
+               DEBUG(0,("krb5_crypto_init() failed: %s\n",
+                         smb_get_krb5_error_message(context, ret, mem_ctx)));
                return ret;
        }
        ret = krb5_create_checksum(context,
                                   crypto,
                                   KRB5_KU_OTHER_CKSUM,
                                   0,
-                                  pac_data.data,
-                                  pac_data.length,
+                                  pac_data->data,
+                                  pac_data->length,
                                   &cksum);
        if (ret) {
                DEBUG(2, ("PAC Verification failed: %s\n", 
@@ -235,6 +280,107 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
 }
 
  krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+                                   struct PAC_DATA *pac_data,
+                                   krb5_context context,
+                                   krb5_keyblock *krbtgt_keyblock,
+                                   krb5_keyblock *service_keyblock,
+                                   DATA_BLOB *pac) 
+{
+       NTSTATUS nt_status;
+       krb5_error_code ret;
+       DATA_BLOB zero_blob = data_blob(NULL, 0);
+       DATA_BLOB tmp_blob = data_blob(NULL, 0);
+       DATA_BLOB service_checksum_blob;
+       struct PAC_SIGNATURE_DATA *kdc_checksum = NULL;
+       struct PAC_SIGNATURE_DATA *srv_checksum = NULL;
+       int i;
+
+       /* First, just get the keytypes filled in (and lengths right, eventually) */
+       for (i=0; i < pac_data->num_buffers; i++) {
+               if (pac_data->buffers[i].type != PAC_TYPE_KDC_CHECKSUM) {
+                       continue;
+               }
+               kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, 
+               ret = make_pac_checksum(mem_ctx, &zero_blob,
+                                       kdc_checksum, 
+                                       context, krbtgt_keyblock);
+               if (ret) {
+                       DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
+                                 smb_get_krb5_error_message(context, ret, mem_ctx)));
+                       talloc_free(pac_data);
+                       return ret;
+               }
+       }
+       
+       for (i=0; i < pac_data->num_buffers; i++) {
+               if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) {
+                       continue;
+               }
+               srv_checksum = &pac_data->buffers[i].info->srv_cksum; 
+               ret = make_pac_checksum(mem_ctx, &zero_blob, 
+                                       srv_checksum, 
+                                       context, service_keyblock);
+               if (ret) {
+                       DEBUG(2, ("making service PAC checksum failed: %s\n", 
+                                 smb_get_krb5_error_message(context, ret, mem_ctx)));
+                       talloc_free(pac_data);
+                       return ret;
+               }
+       }
+
+       if (!kdc_checksum) {
+               DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!"));
+               return EINVAL;
+       }
+       if (!srv_checksum) {
+               DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!"));
+               return EINVAL;
+       }
+
+       /* But wipe out the actual signatures */
+       ZERO_STRUCT(kdc_checksum->signature);
+       ZERO_STRUCT(srv_checksum->signature);
+
+       nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
+               talloc_free(pac_data);
+               return EINVAL;
+       }
+
+       /* Then sign the result of the previous push, where the sig was zero'ed out */
+       ret = make_pac_checksum(mem_ctx, &tmp_blob, srv_checksum,
+                               context, service_keyblock);
+
+       service_checksum_blob
+               = data_blob_const(srv_checksum->signature, sizeof(srv_checksum->signature));
+
+       /* Then sign Server checksum */
+       ret = make_pac_checksum(mem_ctx, &service_checksum_blob, kdc_checksum, context, krbtgt_keyblock);
+       if (ret) {
+               DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
+                         smb_get_krb5_error_message(context, ret, mem_ctx)));
+               talloc_free(pac_data);
+               return ret;
+       }
+
+       /* And push it out again, this time to the world.  This relies on determanistic pointer values */
+       nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
+               talloc_free(pac_data);
+               return EINVAL;
+       }
+
+       *pac = tmp_blob;
+
+       return ret;
+}
+
+
+ krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
                                     struct auth_serversupplied_info *server_info,
                                     krb5_context context,
                                     krb5_keyblock *krbtgt_keyblock,
@@ -242,9 +388,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
                                     DATA_BLOB *pac)
 {
        NTSTATUS nt_status;
-       DATA_BLOB zero_blob = data_blob(NULL, 0);
-       DATA_BLOB tmp_blob = data_blob(NULL, 0);
-       DATA_BLOB service_checksum_blob;
        krb5_error_code ret;
        struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
        struct netr_SamInfo3 *sam3;
@@ -254,9 +397,7 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
        union PAC_INFO *u_LOGON_NAME;
        struct PAC_LOGON_NAME *LOGON_NAME;
        union PAC_INFO *u_KDC_CHECKSUM;
-       struct PAC_SIGNATURE_DATA *KDC_CHECKSUM;
        union PAC_INFO *u_SRV_CHECKSUM;
-       struct PAC_SIGNATURE_DATA *SRV_CHECKSUM;
 
        enum {
                PAC_BUF_LOGON_INFO = 0,
@@ -308,7 +449,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
        }
        pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
        pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = u_SRV_CHECKSUM;
-       SRV_CHECKSUM = &u_SRV_CHECKSUM->srv_cksum;
 
        /* KDC_CHECKSUM */
        u_KDC_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
@@ -318,7 +458,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
        }
        pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
        pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = u_KDC_CHECKSUM;
-       KDC_CHECKSUM = &u_KDC_CHECKSUM->kdc_cksum;
 
        /* now the real work begins... */
 
@@ -341,64 +480,12 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
        LOGON_NAME->account_name        = server_info->account_name;
        LOGON_NAME->logon_time          = timeval_to_nttime(&tv);
 
-
-
-       /* First, just get the keytypes filled in (and lengths right, eventually) */
-       ret = make_pac_checksum(mem_ctx, zero_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
-       if (ret) {
-               DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               talloc_free(pac_data);
-               return ret;
-       }
-
-       ret = make_pac_checksum(mem_ctx, zero_blob, SRV_CHECKSUM, context, service_keyblock);
-       if (ret) {
-               DEBUG(2, ("making service PAC checksum failed: %s\n", 
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               talloc_free(pac_data);
-               return ret;
-       }
-
-       /* But wipe out the actual signatures */
-       ZERO_STRUCT(KDC_CHECKSUM->signature);
-       ZERO_STRUCT(SRV_CHECKSUM->signature);
-
-       nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
-                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
-               talloc_free(pac_data);
-               return EINVAL;
-       }
-
-       /* Then sign the result of the previous push, where the sig was zero'ed out */
-       ret = make_pac_checksum(mem_ctx, tmp_blob, SRV_CHECKSUM,
-                               context, service_keyblock);
-
-       service_checksum_blob
-               = data_blob_const(SRV_CHECKSUM->signature, sizeof(SRV_CHECKSUM->signature));
-
-       /* Then sign Server checksum */
-       ret = make_pac_checksum(mem_ctx, service_checksum_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
-       if (ret) {
-               DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", 
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               talloc_free(pac_data);
-               return ret;
-       }
-
-       /* And push it out again, this time to the world.  This relies on determanistic pointer values */
-       nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
-                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
-               talloc_free(pac_data);
-               return EINVAL;
-       }
-
-       *pac = tmp_blob;
-
+       ret = kerberos_encode_pac(mem_ctx, 
+                                 pac_data, 
+                                 context,
+                                 krbtgt_keyblock,
+                                 service_keyblock,
+                                 pac);
        talloc_free(pac_data);
        return ret;
 }
index c986d60fdf3247d93f6d1850b90e89a3cda1e948..44326cabef0348ea8ccce54512fb9434ac7549e2 100644 (file)
@@ -70,7 +70,7 @@
                return EINVAL;
        }
 
-       ret = kerberos_encode_pac(mem_ctx, server_info, 
+       ret = kerberos_create_pac(mem_ctx, server_info, 
                                  context, 
                                  krbtgt_keyblock,
                                  server_keyblock,
index 59bf00897069ef0eb46b61766e460c6737119007..74a31af890ab36b0b02577069c3af8ae0a9b0d7b 100644 (file)
 #include "librpc/gen_ndr/ndr_krb5pac.h"
 #include "librpc/gen_ndr/ndr_samr.h"
 
-#ifdef HAVE_KRB5
-
 static BOOL torture_pac_self_check(void) 
 {
        NTSTATUS nt_status;
        TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
        DATA_BLOB tmp_blob;
-       struct PAC_LOGON_INFO *pac_info;
+       struct PAC_DATA *pac_data;
 
        /* Generate a nice, arbitary keyblock */
        uint8_t server_bytes[16];
@@ -100,7 +98,7 @@ static BOOL torture_pac_self_check(void)
        }
        
        /* OK, go ahead and make a PAC */
-       ret = kerberos_encode_pac(mem_ctx, server_info, 
+       ret = kerberos_create_pac(mem_ctx, server_info, 
                                  smb_krb5_context->krb5_context,  
                                  &krbtgt_keyblock,
                                  &server_keyblock,
@@ -122,7 +120,7 @@ static BOOL torture_pac_self_check(void)
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
        /* Now check that we can read it back */
-       nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
+       nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
                                        tmp_blob,
                                        smb_krb5_context,
                                        &krbtgt_keyblock,
@@ -197,8 +195,7 @@ static BOOL torture_pac_saved_check(void)
        NTSTATUS nt_status;
        TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
        DATA_BLOB tmp_blob, validate_blob;
-       struct PAC_LOGON_INFO *pac_info;
-       struct PAC_DATA pac_data;
+       struct PAC_DATA *pac_data;
        krb5_keyblock server_keyblock;
        krb5_keyblock krbtgt_keyblock;
        uint8_t server_bytes[16];
@@ -264,35 +261,37 @@ static BOOL torture_pac_saved_check(void)
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
        /* Decode and verify the signaure on the PAC */
-       nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
+       nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
                                        tmp_blob,
                                        smb_krb5_context,
                                        &krbtgt_keyblock,
                                        &server_keyblock);
-       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                   &krbtgt_keyblock);
-       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                   &server_keyblock);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(1, ("PAC decoding failed: %s\n", 
                          nt_errstr(nt_status)));
 
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
                talloc_free(mem_ctx);
                return False;
        }
 
-       nt_status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
-                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(0,("can't parse the PAC\n"));
-               talloc_free(mem_ctx);
-               return False;
-       }
+       ret = kerberos_encode_pac(mem_ctx, 
+                                 pac_data,
+                                 smb_krb5_context->krb5_context,
+                                 &krbtgt_keyblock,
+                                 &server_keyblock,
+                                 &validate_blob);
 
-       nt_status = ndr_push_struct_blob(&validate_blob, mem_ctx, &pac_data,
-                                        (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(0, ("PAC push failed: %s\n", nt_errstr(nt_status)));
+       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                   &krbtgt_keyblock);
+       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                   &server_keyblock);
+
+       if (ret != 0) {
+               DEBUG(0, ("PAC push failed\n"));
                talloc_free(mem_ctx);
                return False;
        }
@@ -328,14 +327,3 @@ BOOL torture_pac(void)
        ret &= torture_pac_saved_check();
        return ret;
 }
-
-#else 
-
-BOOL torture_pac(void) 
-{
-       printf("Cannot do PAC test without Krb5\n");
-       return False;
-}
-
-#endif
-