Heimdal provides Kerberos PAC parsing routines. Use them.
authorAndrew Bartlett <abartlet@samba.org>
Thu, 28 Aug 2008 06:28:47 +0000 (16:28 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 28 Aug 2008 06:28:47 +0000 (16:28 +1000)
This uses Heimdal's PAC parsing code in the:
 - LOCAL-PAC test
 - gensec_gssapi server
 - KDC (where is was already used, the support code refactored from here)

In addition, the service and KDC checksums are recorded in the struct
auth_serversupplied_info, allowing them to be extracted for validation
across NETLOGON.

Andrew Bartlett

source/auth/auth.h
source/auth/gensec/gensec_gssapi.c
source/auth/kerberos/kerberos_pac.c
source/auth/session.c
source/kdc/pac-glue.c
source/torture/auth/pac.c

index da8aac48ef3a9762ab07be2e3a71f83ab6208b72..af9ed52f782cdab1da43a8bec3d573fb4838d2da 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef _SAMBA_AUTH_H
 #define _SAMBA_AUTH_H
 
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
 extern const char *user_attrs[];
 
 union netr_Validation;
@@ -115,6 +117,8 @@ struct auth_serversupplied_info
        uint32_t acct_flags;
 
        bool authenticated;
+
+       struct PAC_SIGNATURE_DATA pac_srv_sig, pac_kdc_sig;
 };
 
 struct auth_method_context;
index 20576256c283cbea0106d1b1fc6a9858aa32361e..1334e799aea34705ba7b96950922b274b56218e6 100644 (file)
@@ -1221,14 +1221,8 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
        struct auth_serversupplied_info *server_info = NULL;
        struct auth_session_info *session_info = NULL;
-       struct PAC_LOGON_INFO *logon_info;
        OM_uint32 maj_stat, min_stat;
-       gss_buffer_desc name_token;
        gss_buffer_desc pac;
-       krb5_keyblock *keyblock;
-       time_t authtime;
-       krb5_principal principal;
-       char *principal_string;
        DATA_BLOB pac_blob;
        
        if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
@@ -1241,28 +1235,6 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
        mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); 
        NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
 
-       maj_stat = gss_display_name (&min_stat,
-                                    gensec_gssapi_state->client_name,
-                                    &name_token,
-                                    NULL);
-       if (GSS_ERROR(maj_stat)) {
-               DEBUG(1, ("GSS display_name failed: %s\n", 
-                         gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
-               talloc_free(mem_ctx);
-               return NT_STATUS_FOOBAR;
-       }
-
-       principal_string = talloc_strndup(mem_ctx, 
-                                         (const char *)name_token.value, 
-                                         name_token.length);
-
-       gss_release_buffer(&min_stat, &name_token);
-
-       if (!principal_string) {
-               talloc_free(mem_ctx);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 
                                                               gensec_gssapi_state->gssapi_context, 
                                                               KRB5_AUTHDATA_WIN2K_PAC,
@@ -1282,82 +1254,63 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
         * kind... 
         */
        if (pac_blob.length) {
-               krb5_error_code ret;
-               union netr_Validation validation;
-
-               maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
-                                                                    gensec_gssapi_state->gssapi_context, 
-                                                                    &authtime);
-               
-               if (GSS_ERROR(maj_stat)) {
-                       DEBUG(1, ("gsskrb5_extract_authtime_from_sec_context: %s\n", 
-                                 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+               nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
+                                                            lp_iconv_convenience(gensec_security->lp_ctx),
+                                                            pac_blob, 
+                                                            gensec_gssapi_state->smb_krb5_context->krb5_context,
+                                                            &server_info);
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        talloc_free(mem_ctx);
-                       return NT_STATUS_FOOBAR;
+                       return nt_status;
                }
+       } else {
+               gss_buffer_desc name_token;
+               char *principal_string;
 
-               maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 
-                                                           gensec_gssapi_state->gssapi_context, 
-                                                           &keyblock);
-               
+               maj_stat = gss_display_name (&min_stat,
+                                            gensec_gssapi_state->client_name,
+                                            &name_token,
+                                            NULL);
                if (GSS_ERROR(maj_stat)) {
-                       DEBUG(1, ("gsskrb5_copy_service_keyblock failed: %s\n", 
+                       DEBUG(1, ("GSS display_name failed: %s\n", 
                                  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
                        talloc_free(mem_ctx);
                        return NT_STATUS_FOOBAR;
-               } 
-
-               ret = krb5_parse_name_flags(gensec_gssapi_state->smb_krb5_context->krb5_context,
-                                           principal_string, 
-                                           KRB5_PRINCIPAL_PARSE_MUST_REALM,
-                                           &principal);
-               if (ret) {
-                       krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,
-                                          keyblock);
-                       talloc_free(mem_ctx);
-                       return NT_STATUS_INVALID_PARAMETER;
                }
                
-               /* decode and verify the pac */
-               nt_status = kerberos_pac_logon_info(mem_ctx, lp_iconv_convenience(gensec_security->lp_ctx), &logon_info, pac_blob,
-                                                   gensec_gssapi_state->smb_krb5_context->krb5_context,
-                                                   NULL, keyblock, principal, authtime, NULL);
-               krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);
-               krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,
-                                  keyblock);
-
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       talloc_free(mem_ctx);
-                       return nt_status;
-               }
-               validation.sam3 = &logon_info->info3;
-               nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, 
-                                                                NULL,
-                                                                3, &validation,
-                                                                &server_info); 
-               if (!NT_STATUS_IS_OK(nt_status)) {
+               principal_string = talloc_strndup(mem_ctx, 
+                                                 (const char *)name_token.value, 
+                                                 name_token.length);
+               
+               gss_release_buffer(&min_stat, &name_token);
+               
+               if (!principal_string) {
                        talloc_free(mem_ctx);
-                       return nt_status;
+                       return NT_STATUS_NO_MEMORY;
                }
-       } else if (!lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {
-               DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
-                         gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
-               nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, principal_string,
-                                                         &server_info);
 
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       talloc_free(mem_ctx);
-                       return nt_status;
+               if (!lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {
+                       DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
+                                 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+                       nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx, 
+                                                                 gensec_security->lp_ctx, principal_string,
+                                                                 &server_info);
+                       
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               talloc_free(mem_ctx);
+                               return nt_status;
+                       }
+               } else {
+                       DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
+                                 principal_string,
+                                 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+                       return NT_STATUS_ACCESS_DENIED;
                }
-       } else {
-               DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
-                         principal_string,
-                         gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
-               return NT_STATUS_ACCESS_DENIED;
        }
 
        /* references the server_info into the session_info */
-       nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, server_info, &session_info);
+       nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, 
+                                              gensec_security->lp_ctx, server_info, &session_info);
        if (!NT_STATUS_IS_OK(nt_status)) {
                talloc_free(mem_ctx);
                return nt_status;
index e485f75302bfb1576ca50c0feed34fc4249d0687..9ebace32cb5b188675a9821177b75150be95772f 100644 (file)
@@ -3,7 +3,7 @@
 
    Create and parse the krb5 PAC
    
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005,2008
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Luke Howard 2002-2003
    Copyright (C) Stefan Metzmacher 2004-2005
@@ -25,6 +25,7 @@
 
 #include "includes.h"
 #include "system/kerberos.h"
+#include "auth/auth.h"
 #include "auth/kerberos/kerberos.h"
 #include "librpc/gen_ndr/ndr_krb5pac.h"
 #include "lib/ldb/include/ldb.h"
@@ -654,3 +655,123 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+krb5_error_code kerberos_pac_to_server_info(TALLOC_CTX *mem_ctx,
+                                               struct smb_iconv_convenience *iconv_convenience,
+                                               krb5_pac pac,
+                                               krb5_context context,
+                                               struct auth_serversupplied_info **server_info) 
+{
+       NTSTATUS nt_status;
+       enum ndr_err_code ndr_err;
+       krb5_error_code ret;
+
+       DATA_BLOB pac_logon_info_in, pac_srv_checksum_in, pac_kdc_checksum_in;
+       krb5_data k5pac_logon_info_in, k5pac_srv_checksum_in, k5pac_kdc_checksum_in;
+
+       union PAC_INFO info;
+       union netr_Validation validation;
+       struct auth_serversupplied_info *server_info_out;
+
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+       if (!tmp_ctx) {
+               return ENOMEM;
+       }
+
+       ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_LOGON_INFO, &k5pac_logon_info_in);
+       if (ret != 0) {
+               talloc_free(tmp_ctx);
+               return EINVAL;
+       }
+
+       pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length);
+
+       ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, iconv_convenience, &info,
+                                     PAC_TYPE_LOGON_INFO,
+                                     (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
+       krb5_data_free(&k5pac_logon_info_in);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
+               nt_status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
+               talloc_free(tmp_ctx);
+               return EINVAL;
+       }
+
+       /* Pull this right into the normal auth sysstem structures */
+       validation.sam3 = &info.logon_info.info->info3;
+       nt_status = make_server_info_netlogon_validation(mem_ctx,
+                                                        "",
+                                                        3, &validation,
+                                                        &server_info_out); 
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               talloc_free(tmp_ctx);
+               return EINVAL;
+       }
+       
+       ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
+       if (ret != 0) {
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);
+               
+       ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, server_info_out, 
+                                      iconv_convenience, &server_info_out->pac_srv_sig,
+                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+       krb5_data_free(&k5pac_srv_checksum_in);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               nt_status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the KDC signature: %s\n",
+                       nt_errstr(nt_status)));
+               return EINVAL;
+       }
+
+       ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
+       if (ret != 0) {
+               talloc_free(tmp_ctx);
+               return ret;
+       }
+
+       pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);
+               
+       ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, server_info_out, 
+                                      iconv_convenience, &server_info_out->pac_kdc_sig,
+                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+       krb5_data_free(&k5pac_kdc_checksum_in);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               nt_status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the KDC signature: %s\n",
+                       nt_errstr(nt_status)));
+               return EINVAL;
+       }
+
+       *server_info = server_info_out;
+       
+       return 0;
+}
+
+
+NTSTATUS kerberos_pac_blob_to_server_info(TALLOC_CTX *mem_ctx,
+                                                    struct smb_iconv_convenience *iconv_convenience,
+                                                    DATA_BLOB pac_blob, 
+                                                    krb5_context context,
+                                                    struct auth_serversupplied_info **server_info) 
+{
+       krb5_error_code ret;
+       krb5_pac pac;
+       ret = krb5_pac_parse(context, 
+                            pac_blob.data, pac_blob.length, 
+                            &pac);
+       if (ret) {
+               return map_nt_error_from_unix(ret);
+       }
+
+
+       ret = kerberos_pac_to_server_info(mem_ctx, iconv_convenience, pac, context, server_info);
+       krb5_pac_free(context, pac);
+       if (ret) {
+               return map_nt_error_from_unix(ret);
+       }
+       return NT_STATUS_OK;
+}
index b254ee5da68bfcd520de0864ef1db3a8662dc702..d75f1793e199c29405ffe8e7f2fdd4a15b1ac901 100644 (file)
@@ -333,6 +333,9 @@ _PUBLIC_ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
                NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
        }
 
+       ZERO_STRUCT(server_info->pac_srv_sig);
+       ZERO_STRUCT(server_info->pac_kdc_sig);
+
        *_server_info = server_info;
        return NT_STATUS_OK;
 }
index bee271eaa939fe869aa552f7c7d00423bb2b07c9..cbdbb86b1f5ccd6b41ecb5cc38c01c8d7f0d92c5 100644 (file)
@@ -153,18 +153,12 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
                                struct hdb_entry_ex *client,  
                                struct hdb_entry_ex *server, krb5_pac *pac)
 {
-       NTSTATUS nt_status;
-       enum ndr_err_code ndr_err;
        krb5_error_code ret;
 
        unsigned int userAccountControl;
 
        struct hdb_ldb_private *private = talloc_get_type(server->ctx, struct hdb_ldb_private);
-       krb5_data k5pac_in;
-       DATA_BLOB pac_in;
 
-       union PAC_INFO info;
-       union netr_Validation validation;
        struct auth_serversupplied_info *server_info_out;
 
        TALLOC_CTX *mem_ctx = talloc_named(private, 0, "samba_get_pac context");
@@ -176,46 +170,22 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
        /* The service account may be set not to want the PAC */
        userAccountControl = ldb_msg_find_attr_as_uint(private->msg, "userAccountControl", 0);
        if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
+               talloc_free(mem_ctx);
                *pac = NULL;
                return 0;
        }
 
-       ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &k5pac_in);
-       if (ret != 0) {
-               return ret;
-       }
+       ret = kerberos_pac_to_server_info(mem_ctx, private->iconv_convenience,
+                                         *pac, context, &server_info_out);
 
-       pac_in = data_blob_talloc(mem_ctx, k5pac_in.data, k5pac_in.length);
-       krb5_data_free(&k5pac_in);
-       if (!pac_in.data) {
-               talloc_free(mem_ctx);
-               return ENOMEM;
-       }
-               
-       ndr_err = ndr_pull_union_blob(&pac_in, mem_ctx, private->iconv_convenience, &info,
-                                     PAC_TYPE_LOGON_INFO,
-                                     (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
-               nt_status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
-               talloc_free(mem_ctx);
-               return EINVAL;
-       }
+       /* We will compleatly regenerate this pac */
+       krb5_pac_free(context, *pac);
 
-       /* Pull this right into the normal auth sysstem structures */
-       validation.sam3 = &info.logon_info.info->info3;
-       nt_status = make_server_info_netlogon_validation(mem_ctx,
-                                                        "",
-                                                        3, &validation,
-                                                        &server_info_out); 
-       if (!NT_STATUS_IS_OK(nt_status)) {
+       if (ret) {
                talloc_free(mem_ctx);
-               return ENOMEM;
+               return ret;
        }
 
-       /* We will compleatly regenerate this pac */
-       krb5_pac_free(context, *pac);
-
        ret = make_pac(context, mem_ctx, private->iconv_convenience, server_info_out, pac);
 
        talloc_free(mem_ctx);
index 4e51c669507e19b85fa9692245fcfb85afcc4186..42901f1eff155d9fdaf48920c92d6810f316d885 100644 (file)
@@ -139,7 +139,7 @@ static bool torture_pac_self_check(struct torture_context *tctx)
 
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
-       /* Now check that we can read it back */
+       /* Now check that we can read it back (using full decode and validate) */
        nt_status = kerberos_decode_pac(mem_ctx, 
                                        lp_iconv_convenience(tctx->lp_ctx),
                                        &pac_data,
@@ -163,7 +163,31 @@ static bool torture_pac_self_check(struct torture_context *tctx)
                                                   nt_errstr(nt_status)));
        }
 
-       /* Now check that we can read it back */
+       /* Now check we can read it back (using Heimdal's pac parsing) */
+       nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
+                                                    lp_iconv_convenience(tctx->lp_ctx),
+                                                    tmp_blob, 
+                                                    smb_krb5_context->krb5_context,
+                                                    &server_info_out);
+
+       if (!dom_sid_equal(server_info->account_sid, 
+                          server_info_out->account_sid)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, 
+                                   client_principal);
+
+               torture_fail(tctx,  
+                            talloc_asprintf(tctx, 
+                                            "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
+                                            dom_sid_string(mem_ctx, server_info->account_sid), 
+                                            dom_sid_string(mem_ctx, server_info_out->account_sid)));
+       }
+       talloc_free(server_info_out);
+
+       /* Now check that we can read it back (yet again) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
                                            lp_iconv_convenience(tctx->lp_ctx),
                                            &logon_info,
@@ -196,6 +220,7 @@ static bool torture_pac_self_check(struct torture_context *tctx)
        krb5_free_principal(smb_krb5_context->krb5_context, 
                            client_principal);
 
+       /* And make a server info from the samba-parsed PAC */
        validation.sam3 = &logon_info->info3;
        nt_status = make_server_info_netlogon_validation(mem_ctx,
                                                         "",
@@ -403,7 +428,45 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                                   nt_errstr(nt_status)));
        }
 
-       /* Parse the PAC again, for the logon info this time */
+       /* Now check we can read it back (using Heimdal's pac parsing) */
+       nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
+                                                    lp_iconv_convenience(tctx->lp_ctx),
+                                                    tmp_blob, 
+                                                    smb_krb5_context->krb5_context,
+                                                    &server_info_out);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           krbtgt_keyblock_p);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+               
+               torture_fail(tctx, talloc_asprintf(tctx, 
+                                                  "(saved test) Heimdal PAC decoding failed: %s", 
+                                                  nt_errstr(nt_status)));
+       }
+
+       if (!pac_file &&
+           !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
+                                               "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
+                          server_info_out->account_sid)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           krbtgt_keyblock_p);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+
+               torture_fail(tctx,  
+                            talloc_asprintf(tctx, 
+                                            "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
+                                            "S-1-5-21-3048156945-3961193616-3706469200-1005", 
+                                            dom_sid_string(mem_ctx, server_info_out->account_sid)));
+       }
+
+       talloc_free(server_info_out);
+
+       /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
                                            lp_iconv_convenience(tctx->lp_ctx),
                                            &logon_info,