libcli/auth Move PAC parsing and verification in common.
authorAndrew Bartlett <abartlet@samba.org>
Wed, 20 Apr 2011 02:05:27 +0000 (12:05 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 20 Apr 2011 02:31:07 +0000 (04:31 +0200)
This uses the source3 PAC code (originally from Samba4) with some
small changes to restore functionality needed by the torture tests,
and to have a common API.

Andrew Bartlett

12 files changed:
libcli/auth/kerberos_pac.c [new file with mode: 0644]
libcli/auth/krb5_wrap.h
libcli/auth/wscript_build
source3/Makefile.in
source3/include/krb5_protos.h
source3/libads/authdata.c
source3/libads/kerberos_verify.c
source3/wscript_build
source4/auth/gensec/gensec_krb5.c
source4/auth/kerberos/kerberos.h
source4/auth/kerberos/kerberos_pac.c
source4/torture/auth/pac.c

diff --git a/libcli/auth/kerberos_pac.c b/libcli/auth/kerberos_pac.c
new file mode 100644 (file)
index 0000000..6a41eb1
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+   Unix SMB/CIFS implementation.
+   kerberos authorization data (PAC) utility library
+   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Luke Howard 2002-2003
+   Copyright (C) Stefan Metzmacher 2004-2005
+   Copyright (C) Guenther Deschner 2005,2007,2008
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#ifdef HAVE_KRB5
+
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "libcli/auth/krb5_wrap.h"
+
+krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
+                                         DATA_BLOB pac_data,
+                                         struct PAC_SIGNATURE_DATA *sig,
+                                         krb5_context context,
+                                         const krb5_keyblock *keyblock)
+{
+       krb5_error_code ret;
+       krb5_checksum cksum;
+       krb5_keyusage usage = 0;
+
+       smb_krb5_checksum_from_pac_sig(&cksum, sig);
+
+#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */
+       usage = KRB5_KU_OTHER_CKSUM;
+#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */
+       usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;
+#else
+#error UNKNOWN_KRB5_KEYUSAGE
+#endif
+
+       ret = smb_krb5_verify_checksum(context,
+                                      keyblock,
+                                      usage,
+                                      &cksum,
+                                      pac_data.data,
+                                      pac_data.length);
+
+       if (ret) {
+               DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n",
+                       error_message(ret), ret));
+               return ret;
+       }
+
+       return ret;
+}
+
+/**
+* @brief Decode a blob containing a NDR envoded PAC structure
+*
+* @param mem_ctx         - The memory context
+* @param pac_data_blob   - The data blob containing the NDR encoded data
+* @param context         - The Kerberos Context
+* @param service_keyblock - The Service Key used to verify the checksum
+* @param client_principal - The client principal
+* @param tgs_authtime     - The ticket timestamp
+* @param pac_data_out    - [out] The decoded PAC
+*
+* @return - A NTSTATUS error code
+*/
+NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
+                            DATA_BLOB pac_data_blob,
+                            krb5_context context,
+                            const krb5_keyblock *krbtgt_keyblock,
+                            const krb5_keyblock *service_keyblock,
+                            krb5_const_principal client_principal,
+                            time_t tgs_authtime,
+                            struct PAC_DATA **pac_data_out)
+{
+       NTSTATUS status;
+       enum ndr_err_code ndr_err;
+       krb5_error_code ret;
+       DATA_BLOB modified_pac_blob;
+
+       NTTIME tgs_authtime_nttime;
+       krb5_principal client_principal_pac = NULL;
+       int i;
+
+       struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
+       struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
+       struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
+       struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
+       struct PAC_LOGON_NAME *logon_name = NULL;
+       struct PAC_LOGON_INFO *logon_info = NULL;
+       struct PAC_DATA *pac_data = NULL;
+       struct PAC_DATA_RAW *pac_data_raw = NULL;
+
+       DATA_BLOB *srv_sig_blob = NULL;
+       DATA_BLOB *kdc_sig_blob = NULL;
+
+       bool bool_ret;
+
+       *pac_data_out = NULL;
+
+       pac_data = talloc(mem_ctx, struct PAC_DATA);
+       pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
+       kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
+       srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
+       if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
+                      (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the PAC: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       if (pac_data->num_buffers < 4) {
+               /* we need logon_ingo, service_key and kdc_key */
+               DEBUG(0,("less than 4 PAC buffers\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       ndr_err = ndr_pull_struct_blob(
+                               &pac_data_blob, pac_data_raw, pac_data_raw,
+                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the PAC: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       if (pac_data_raw->num_buffers < 4) {
+               /* we need logon_ingo, service_key and kdc_key */
+               DEBUG(0,("less than 4 PAC buffers\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (pac_data->num_buffers != pac_data_raw->num_buffers) {
+               /* we need logon_ingo, service_key and kdc_key */
+               DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
+                         "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
+                         pac_data_raw->num_buffers));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       for (i=0; i < pac_data->num_buffers; i++) {
+               struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
+               struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];
+
+               if (data_buf->type != raw_buf->type) {
+                       DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
+                                 "%d while PAC_DATA_RAW has %d\n", i,
+                                 data_buf->type, raw_buf->type));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               switch (data_buf->type) {
+               case PAC_TYPE_LOGON_INFO:
+                       if (!data_buf->info) {
+                               break;
+                       }
+                       logon_info = data_buf->info->logon_info.info;
+                       break;
+               case PAC_TYPE_SRV_CHECKSUM:
+                       if (!data_buf->info) {
+                               break;
+                       }
+                       srv_sig_ptr = &data_buf->info->srv_cksum;
+                       srv_sig_blob = &raw_buf->info->remaining;
+                       break;
+               case PAC_TYPE_KDC_CHECKSUM:
+                       if (!data_buf->info) {
+                               break;
+                       }
+                       kdc_sig_ptr = &data_buf->info->kdc_cksum;
+                       kdc_sig_blob = &raw_buf->info->remaining;
+                       break;
+               case PAC_TYPE_LOGON_NAME:
+                       logon_name = &data_buf->info->logon_name;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (!logon_info) {
+               DEBUG(0,("PAC no logon_info\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!logon_name) {
+               DEBUG(0,("PAC no logon_name\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!srv_sig_ptr || !srv_sig_blob) {
+               DEBUG(0,("PAC no srv_key\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!kdc_sig_ptr || !kdc_sig_blob) {
+               DEBUG(0,("PAC no kdc_key\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* Find and zero out the signatures,
+        * as required by the signing algorithm */
+
+       /* We find the data blobs above,
+        * now we parse them to get at the exact portion we should zero */
+       ndr_err = ndr_pull_struct_blob(
+                       kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
+                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the KDC signature: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       ndr_err = ndr_pull_struct_blob(
+                       srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
+                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't parse the SRV signature: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       /* Now zero the decoded structure */
+       memset(kdc_sig_wipe->signature.data,
+               '\0', kdc_sig_wipe->signature.length);
+       memset(srv_sig_wipe->signature.data,
+               '\0', srv_sig_wipe->signature.length);
+
+       /* and reencode, back into the same place it came from */
+       ndr_err = ndr_push_struct_blob(
+                       kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
+                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't repack the KDC signature: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+       ndr_err = ndr_push_struct_blob(
+                       srv_sig_blob, pac_data_raw, srv_sig_wipe,
+                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't repack the SRV signature: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       /* push out the whole structure, but now with zero'ed signatures */
+       ndr_err = ndr_push_struct_blob(
+                       &modified_pac_blob, pac_data_raw, pac_data_raw,
+                       (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               DEBUG(0,("can't repack the RAW PAC: %s\n",
+                       nt_errstr(status)));
+               return status;
+       }
+
+       /* verify by service_key */
+       ret = check_pac_checksum(mem_ctx,
+                                modified_pac_blob, srv_sig_ptr,
+                                context,
+                                service_keyblock);
+       if (ret) {
+               DEBUG(1, ("PAC Decode: Failed to verify the service "
+                         "signature: %s\n", error_message(ret)));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (krbtgt_keyblock) {
+               /* verify the service key checksum by krbtgt_key */
+               ret = check_pac_checksum(mem_ctx,
+                                        srv_sig_ptr->signature, kdc_sig_ptr,
+                                        context, krbtgt_keyblock);
+               if (ret) {
+                       DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
+                                 smb_get_krb5_error_message(context, ret, mem_ctx)));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       /* Convert to NT time, so as not to loose accuracy in comparison */
+       unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
+
+       if (tgs_authtime_nttime != logon_name->logon_time) {
+               DEBUG(2, ("PAC Decode: "
+                         "Logon time mismatch between ticket and PAC!\n"));
+               DEBUG(2, ("PAC Decode: PAC: %s\n",
+                         nt_time_string(mem_ctx, logon_name->logon_time)));
+               DEBUG(2, ("PAC Decode: Ticket: %s\n",
+                         nt_time_string(mem_ctx, tgs_authtime_nttime)));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       ret = smb_krb5_parse_name_norealm(context,
+                                         logon_name->account_name,
+                                         &client_principal_pac);
+       if (ret) {
+               DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
+                         logon_name->account_name, error_message(ret)));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       bool_ret = smb_krb5_principal_compare_any_realm(context,
+                                                       client_principal,
+                                                       client_principal_pac);
+
+       krb5_free_principal(context, client_principal_pac);
+
+       if (!bool_ret) {
+               DEBUG(2, ("Name in PAC [%s] does not match principal name "
+                         "in ticket\n", logon_name->account_name));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(3,("Found account name from PAC: %s [%s]\n",
+                logon_info->info3.base.account_name.string,
+                logon_info->info3.base.full_name.string));
+
+       DEBUG(10,("Successfully validated Kerberos PAC\n"));
+
+       if (DEBUGLEVEL >= 10) {
+               const char *s;
+               s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data);
+               if (s) {
+                       DEBUGADD(10,("%s\n", s));
+               }
+       }
+
+       *pac_data_out = pac_data;
+
+       return NT_STATUS_OK;
+}
+
+#endif
index 3cdcedc97119928968679fa44fb8097e2235bc2c..4f333cc4b0dece55ce92a03d8736da95562194cc 100644 (file)
@@ -54,3 +54,18 @@ krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
                                         krb5_checksum *cksum,
                                         uint8_t *data,
                                          size_t length);
                                         krb5_checksum *cksum,
                                         uint8_t *data,
                                          size_t length);
+
+krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
+                                  DATA_BLOB pac_data,
+                                  struct PAC_SIGNATURE_DATA *sig,
+                                  krb5_context context,
+                                  const krb5_keyblock *keyblock);
+
+NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
+                            DATA_BLOB pac_data_blob,
+                            krb5_context context,
+                            const krb5_keyblock *krbtgt_keyblock,
+                            const krb5_keyblock *service_keyblock,
+                            krb5_const_principal client_principal,
+                            time_t tgs_authtime,
+                            struct PAC_DATA **pac_data_out);
index 6f5483f48b9d738964d78c9e887de2f7b793fc8c..e7d8b5660f53362e1e313b3af7165dca07ac96f9 100644 (file)
@@ -40,5 +40,5 @@ bld.SAMBA_SUBSYSTEM('SPNEGO_PARSE',
                     deps='asn1util')
 
 bld.SAMBA_SUBSYSTEM('KRB5_WRAP',
                     deps='asn1util')
 
 bld.SAMBA_SUBSYSTEM('KRB5_WRAP',
-                    source='krb5_wrap.c',
-                    deps='krb5')
+                    source='krb5_wrap.c kerberos_pac.c',
+                    deps='krb5 ndr-krb5pac')
index 78acdc9d94813912ffed119721fbf4b8a4ddeaa5..e503112392aca970e96c2087d56d0369b9e0b7ff 100644 (file)
@@ -511,7 +511,7 @@ LIBADS_OBJ = libads/ldap.o \
              libads/disp_sec.o libads/ldap_utils.o \
             libads/ldap_schema.o libads/util.o libads/ndr.o
 
              libads/disp_sec.o libads/ldap_utils.o \
             libads/ldap_schema.o libads/util.o libads/ndr.o
 
-LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o \
+LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o ../libcli/auth/kerberos_pac.o \
                    ../librpc/ndr/ndr_krb5pac.o \
                    librpc/gen_ndr/ndr_krb5pac.o
 
                    ../librpc/ndr/ndr_krb5pac.o \
                    librpc/gen_ndr/ndr_krb5pac.o
 
index 530122b79e171426bebf8842723dd67df19c0eaf..d80e77d2eb6236a46f58f3116dc4d89d2adab9f7 100644 (file)
@@ -58,21 +58,6 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, kr
 void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype);
 bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2);
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
 void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype);
 bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2);
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
-NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx,
-                        DATA_BLOB *pac_data_blob,
-                        krb5_context context,
-                        krb5_keyblock *service_keyblock,
-                        krb5_const_principal client_principal,
-                        time_t tgs_authtime,
-                        struct PAC_DATA **pac_data_out);
-void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
-                                   struct PAC_SIGNATURE_DATA *sig);
-krb5_error_code smb_krb5_verify_checksum(krb5_context context,
-                                        const krb5_keyblock *keyblock,
-                                        krb5_keyusage usage,
-                                        krb5_checksum *cksum,
-                                        uint8 *data,
-                                        size_t length);
 time_t get_authtime_from_tkt(krb5_ticket *tkt);
 krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context,
                                                 const krb5_data *inbuf,
 time_t get_authtime_from_tkt(krb5_ticket *tkt);
 krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context,
                                                 const krb5_data *inbuf,
index 0d877ddef89ad62284a8e96223344277d0fd6f38..6f49b857da7dbdc2128b608196813bd74f7344ca 100644 (file)
 
 #ifdef HAVE_KRB5
 
 
 #ifdef HAVE_KRB5
 
-/****************************************************************
-****************************************************************/
-
-static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
-                                         DATA_BLOB pac_data,
-                                         struct PAC_SIGNATURE_DATA *sig,
-                                         krb5_context context,
-                                         krb5_keyblock *keyblock)
-{
-       krb5_error_code ret;
-       krb5_checksum cksum;
-       krb5_keyusage usage = 0;
-
-       smb_krb5_checksum_from_pac_sig(&cksum, sig);
-
-#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */
-       usage = KRB5_KU_OTHER_CKSUM;
-#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */
-       usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;
-#else
-#error UNKNOWN_KRB5_KEYUSAGE
-#endif
-
-       ret = smb_krb5_verify_checksum(context,
-                                      keyblock,
-                                      usage,
-                                      &cksum,
-                                      pac_data.data,
-                                      pac_data.length);
-
-       if (ret) {
-               DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n",
-                       error_message(ret), ret));
-               return ret;
-       }
-
-       return ret;
-}
-
-/**
-* @brief Decode a blob containing a NDR envoded PAC structure
-*
-* @param mem_ctx         - The memory context
-* @param pac_data_blob   - The data blob containing the NDR encoded data
-* @param context         - The Kerberos Context
-* @param service_keyblock - The Service Key used to verify the checksum
-* @param client_principal - The client principal
-* @param tgs_authtime     - The ticket timestamp
-* @param pac_data_out    - [out] The decoded PAC
-*
-* @return - A NTSTATUS error code
-*/
-NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx,
-                        DATA_BLOB *pac_data_blob,
-                        krb5_context context,
-                        krb5_keyblock *service_keyblock,
-                        krb5_const_principal client_principal,
-                        time_t tgs_authtime,
-                        struct PAC_DATA **pac_data_out)
-{
-       NTSTATUS status;
-       enum ndr_err_code ndr_err;
-       krb5_error_code ret;
-       DATA_BLOB modified_pac_blob;
-
-       NTTIME tgs_authtime_nttime;
-       krb5_principal client_principal_pac = NULL;
-       int i;
-
-       struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
-       struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
-       struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
-       struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
-       struct PAC_LOGON_NAME *logon_name = NULL;
-       struct PAC_LOGON_INFO *logon_info = NULL;
-       struct PAC_DATA *pac_data = NULL;
-       struct PAC_DATA_RAW *pac_data_raw = NULL;
-
-       DATA_BLOB *srv_sig_blob = NULL;
-       DATA_BLOB *kdc_sig_blob = NULL;
-
-       bool bool_ret;
-
-       *pac_data_out = NULL;
-
-       pac_data = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA);
-       pac_data_raw = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA_RAW);
-       kdc_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA);
-       srv_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA);
-       if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data, pac_data,
-                      (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       if (pac_data->num_buffers < 4) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0,("less than 4 PAC buffers\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       ndr_err = ndr_pull_struct_blob(
-                               pac_data_blob, pac_data_raw, pac_data_raw,
-                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       if (pac_data_raw->num_buffers < 4) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0,("less than 4 PAC buffers\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (pac_data->num_buffers != pac_data_raw->num_buffers) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
-                         "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
-                         pac_data_raw->num_buffers));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       for (i=0; i < pac_data->num_buffers; i++) {
-               struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
-               struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];
-
-               if (data_buf->type != raw_buf->type) {
-                       DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
-                                 "%d while PAC_DATA_RAW has %d\n", i,
-                                 data_buf->type, raw_buf->type));
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
-               switch (data_buf->type) {
-               case PAC_TYPE_LOGON_INFO:
-                       if (!data_buf->info) {
-                               break;
-                       }
-                       logon_info = data_buf->info->logon_info.info;
-                       break;
-               case PAC_TYPE_SRV_CHECKSUM:
-                       if (!data_buf->info) {
-                               break;
-                       }
-                       srv_sig_ptr = &data_buf->info->srv_cksum;
-                       srv_sig_blob = &raw_buf->info->remaining;
-                       break;
-               case PAC_TYPE_KDC_CHECKSUM:
-                       if (!data_buf->info) {
-                               break;
-                       }
-                       kdc_sig_ptr = &data_buf->info->kdc_cksum;
-                       kdc_sig_blob = &raw_buf->info->remaining;
-                       break;
-               case PAC_TYPE_LOGON_NAME:
-                       logon_name = &data_buf->info->logon_name;
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (!logon_info) {
-               DEBUG(0,("PAC no logon_info\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!logon_name) {
-               DEBUG(0,("PAC no logon_name\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!srv_sig_ptr || !srv_sig_blob) {
-               DEBUG(0,("PAC no srv_key\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!kdc_sig_ptr || !kdc_sig_blob) {
-               DEBUG(0,("PAC no kdc_key\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       /* Find and zero out the signatures,
-        * as required by the signing algorithm */
-
-       /* We find the data blobs above,
-        * now we parse them to get at the exact portion we should zero */
-       ndr_err = ndr_pull_struct_blob(
-                       kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
-                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the KDC signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       ndr_err = ndr_pull_struct_blob(
-                       srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
-                       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the SRV signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* Now zero the decoded structure */
-       memset(kdc_sig_wipe->signature.data,
-               '\0', kdc_sig_wipe->signature.length);
-       memset(srv_sig_wipe->signature.data,
-               '\0', srv_sig_wipe->signature.length);
-
-       /* and reencode, back into the same place it came from */
-       ndr_err = ndr_push_struct_blob(
-                       kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
-                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the KDC signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-       ndr_err = ndr_push_struct_blob(
-                       srv_sig_blob, pac_data_raw, srv_sig_wipe,
-                       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the SRV signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* push out the whole structure, but now with zero'ed signatures */
-       ndr_err = ndr_push_struct_blob(
-                       &modified_pac_blob, pac_data_raw, pac_data_raw,
-                       (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the RAW PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* verify by service_key */
-       ret = check_pac_checksum(mem_ctx,
-                                modified_pac_blob, srv_sig_ptr,
-                                context,
-                                service_keyblock);
-       if (ret) {
-               DEBUG(1, ("PAC Decode: Failed to verify the service "
-                         "signature: %s\n", error_message(ret)));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /* Convert to NT time, so as not to loose accuracy in comparison */
-       unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
-
-       if (tgs_authtime_nttime != logon_name->logon_time) {
-               DEBUG(2, ("PAC Decode: "
-                         "Logon time mismatch between ticket and PAC!\n"));
-               DEBUG(2, ("PAC Decode: PAC: %s\n",
-                         nt_time_string(mem_ctx, logon_name->logon_time)));
-               DEBUG(2, ("PAC Decode: Ticket: %s\n",
-                         nt_time_string(mem_ctx, tgs_authtime_nttime)));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       ret = smb_krb5_parse_name_norealm(context,
-                                         logon_name->account_name,
-                                         &client_principal_pac);
-       if (ret) {
-               DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
-                         logon_name->account_name, error_message(ret)));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       bool_ret = smb_krb5_principal_compare_any_realm(context,
-                                                       client_principal,
-                                                       client_principal_pac);
-
-       krb5_free_principal(context, client_principal_pac);
-
-       if (!bool_ret) {
-               DEBUG(2, ("Name in PAC [%s] does not match principal name "
-                         "in ticket\n", logon_name->account_name));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       DEBUG(3,("Found account name from PAC: %s [%s]\n",
-                logon_info->info3.base.account_name.string,
-                logon_info->info3.base.full_name.string));
-
-       DEBUG(10,("Successfully validated Kerberos PAC\n"));
-
-       if (DEBUGLEVEL >= 10) {
-               const char *s;
-               s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data);
-               if (s) {
-                       DEBUGADD(10,("%s\n", s));
-               }
-       }
-
-       *pac_data_out = pac_data;
-
-       return NT_STATUS_OK;
-}
-
 /****************************************************************
 Given a username, password and other details, return the
 PAC_LOGON_INFO (the structure containing the important user
 /****************************************************************
 Given a username, password and other details, return the
 PAC_LOGON_INFO (the structure containing the important user
index 7eda7fd8dd80c73752d76da8124e088fed8fdddd..fab38dc4deb53a23246ba162e1977a62cc0fff9a 100644 (file)
@@ -680,9 +680,9 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
 
        if (got_auth_data) {
                struct PAC_DATA *pac_data;
 
        if (got_auth_data) {
                struct PAC_DATA *pac_data;
-               pac_ret = decode_pac_data(mem_ctx, &auth_data, context,
-                                         keyblock, client_principal,
-                                         authtime, &pac_data);
+               pac_ret = kerberos_decode_pac(mem_ctx, auth_data, context,
+                                             NULL, keyblock, client_principal,
+                                             authtime, &pac_data);
                data_blob_free(&auth_data);
                if (!NT_STATUS_IS_OK(pac_ret)) {
                        DEBUG(3, (__location__ ": failed to decode "
                data_blob_free(&auth_data);
                if (!NT_STATUS_IS_OK(pac_ret)) {
                        DEBUG(3, (__location__ ": failed to decode "
index e966d0d29faea2182a6922686c28d1f64baeeb9e..7a01a7a366fa4f189b57cdfe5cb696fdc3c56fd3 100755 (executable)
@@ -833,7 +833,7 @@ bld.SAMBA3_LIBRARY('ads',
 
 bld.SAMBA3_SUBSYSTEM('LIBADS_SERVER',
                     source=LIBADS_SERVER_SRC,
 
 bld.SAMBA3_SUBSYSTEM('LIBADS_SERVER',
                     source=LIBADS_SERVER_SRC,
-                    deps='ndr-krb5pac krb5',
+                    deps='ndr-krb5pac krb5 KRB5_WRAP',
                    vars=locals())
 
 bld.SAMBA3_SUBSYSTEM('LIBADS_PRINTER',
                    vars=locals())
 
 bld.SAMBA3_SUBSYSTEM('LIBADS_PRINTER',
index e6497bb9055729fc558608c59ce9b7776b69f2ca..c3e3b98f74373d77f814691a53c5cec2f171c16e 100644 (file)
@@ -697,11 +697,11 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
 
                /* decode and verify the pac */
                nt_status = kerberos_pac_logon_info(gensec_krb5_state, 
 
                /* decode and verify the pac */
                nt_status = kerberos_pac_logon_info(gensec_krb5_state, 
-                                                   &logon_info, pac,
+                                                   pac,
                                                    gensec_krb5_state->smb_krb5_context->krb5_context,
                                                    NULL, gensec_krb5_state->keyblock,
                                                    client_principal,
                                                    gensec_krb5_state->smb_krb5_context->krb5_context,
                                                    NULL, gensec_krb5_state->keyblock,
                                                    client_principal,
-                                                   gensec_krb5_state->ticket->ticket.authtime, NULL);
+                                                   gensec_krb5_state->ticket->ticket.authtime, &logon_info);
 
                if (!NT_STATUS_IS_OK(nt_status)) {
                        free(principal_string);
 
                if (!NT_STATUS_IS_OK(nt_status)) {
                        free(principal_string);
index 3f021ad70acc8063f9fd81b86058d5b1794c0c3a..c712569e5debee3ce21df17eea58cad51f38f815 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "auth/kerberos/krb5_init_context.h"
 #include "librpc/gen_ndr/krb5pac.h"
 
 #include "auth/kerberos/krb5_init_context.h"
 #include "librpc/gen_ndr/krb5pac.h"
+#include "libcli/auth/krb5_wrap.h"
 
 struct auth_user_info_dc;
 struct cli_credentials;
 
 struct auth_user_info_dc;
 struct cli_credentials;
@@ -112,24 +113,14 @@ bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, k
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
-NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
-                            struct PAC_DATA **pac_data_out,
-                            DATA_BLOB blob,
-                            krb5_context context,
-                            const krb5_keyblock *krbtgt_keyblock,
-                            const krb5_keyblock *service_keyblock,
-                            krb5_const_principal client_principal,
-                            time_t tgs_authtime,
-                            krb5_error_code *k5ret);
- NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
-                                 struct PAC_LOGON_INFO **logon_info,
-                                 DATA_BLOB blob,
-                                 krb5_context context,
-                                 const krb5_keyblock *krbtgt_keyblock,
-                                 const krb5_keyblock *service_keyblock,
-                                 krb5_const_principal client_principal,
-                                 time_t tgs_authtime, 
-                                 krb5_error_code *k5ret);
+NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
+                                DATA_BLOB blob,
+                                krb5_context context,
+                                const krb5_keyblock *krbtgt_keyblock,
+                                const krb5_keyblock *service_keyblock,
+                                krb5_const_principal client_principal,
+                                time_t tgs_authtime,
+                                struct PAC_LOGON_INFO **logon_info);
  krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
                                    struct PAC_DATA *pac_data,
                                    krb5_context context,
  krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
                                    struct PAC_DATA *pac_data,
                                    krb5_context context,
index 07f936ad2ed533388ab4a90f39652a331a8c1ad2..5bc80c9a583dba5c0419beb2e098414d2aafa2d7 100644 (file)
 #include <ldb.h>
 #include "auth/auth_sam_reply.h"
 
 #include <ldb.h>
 #include "auth/auth_sam_reply.h"
 
-krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
-                                  DATA_BLOB pac_data,
-                                  struct PAC_SIGNATURE_DATA *sig,
-                                  krb5_context context,
-                                  const krb5_keyblock *keyblock)
-{
-       krb5_error_code ret;
-       krb5_crypto crypto;
-       Checksum cksum;
-
-       cksum.cksumtype         = (CKSUMTYPE)sig->type;
-       cksum.checksum.length   = sig->signature.length;
-       cksum.checksum.data     = sig->signature.data;
-
-       ret = krb5_crypto_init(context,
-                              keyblock,
-                              0,
-                              &crypto);
-       if (ret) {
-               DEBUG(0,("krb5_crypto_init() failed: %s\n",
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               return ret;
-       }
-       ret = krb5_verify_checksum(context,
-                                  crypto,
-                                  KRB5_KU_OTHER_CKSUM,
-                                  pac_data.data,
-                                  pac_data.length,
-                                  &cksum);
-       krb5_crypto_destroy(context, crypto);
-
-       return ret;
-}
-
- NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
-                             struct PAC_DATA **pac_data_out,
-                             DATA_BLOB blob,
-                             krb5_context context,
-                             const krb5_keyblock *krbtgt_keyblock,
-                             const krb5_keyblock *service_keyblock,
-                             krb5_const_principal client_principal,
-                             time_t tgs_authtime,
-                             krb5_error_code *k5ret)
-{
-       krb5_error_code ret;
-       NTSTATUS status;
-       enum ndr_err_code ndr_err;
-       struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
-       struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
-       struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
-       struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
-       struct PAC_LOGON_INFO *logon_info = NULL;
-       struct PAC_LOGON_NAME *logon_name = NULL;
-       struct PAC_DATA *pac_data;
-       struct PAC_DATA_RAW *pac_data_raw;
-
-       DATA_BLOB *srv_sig_blob = NULL;
-       DATA_BLOB *kdc_sig_blob = NULL;
-
-       DATA_BLOB modified_pac_blob;
-       NTTIME tgs_authtime_nttime;
-       krb5_principal client_principal_pac;
-       uint32_t i;
-
-       krb5_clear_error_message(context);
-
-       if (k5ret) {
-               *k5ret = KRB5_PARSE_MALFORMED;
-       }
-
-       pac_data = talloc(mem_ctx, struct PAC_DATA);
-       pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
-       kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
-       srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
-       if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
-               if (k5ret) {
-                       *k5ret = ENOMEM;
-               }
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ndr_err = ndr_pull_struct_blob(&blob, pac_data,
-                       pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       if (pac_data->num_buffers < 4) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0,("less than 4 PAC buffers\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw,
-                                      pac_data_raw,
-                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       if (pac_data_raw->num_buffers < 4) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0,("less than 4 PAC buffers\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (pac_data->num_buffers != pac_data_raw->num_buffers) {
-               /* we need logon_ingo, service_key and kdc_key */
-               DEBUG(0,("misparse!  PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
-                        pac_data->num_buffers, pac_data_raw->num_buffers));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       for (i=0; i < pac_data->num_buffers; i++) {
-               if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) {
-                       DEBUG(0,("misparse!  PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
-                                i, pac_data->buffers[i].type, pac_data->buffers[i].type));
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
-               switch (pac_data->buffers[i].type) {
-                       case PAC_TYPE_LOGON_INFO:
-                               if (!pac_data->buffers[i].info) {
-                                       break;
-                               }
-                               logon_info = pac_data->buffers[i].info->logon_info.info;
-                               break;
-                       case PAC_TYPE_SRV_CHECKSUM:
-                               if (!pac_data->buffers[i].info) {
-                                       break;
-                               }
-                               srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
-                               srv_sig_blob = &pac_data_raw->buffers[i].info->remaining;
-                               break;
-                       case PAC_TYPE_KDC_CHECKSUM:
-                               if (!pac_data->buffers[i].info) {
-                                       break;
-                               }
-                               kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
-                               kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining;
-                               break;
-                       case PAC_TYPE_LOGON_NAME:
-                               logon_name = &pac_data->buffers[i].info->logon_name;
-                               break;
-                       default:
-                               break;
-               }
-       }
-
-       if (!logon_info) {
-               DEBUG(0,("PAC no logon_info\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!logon_name) {
-               DEBUG(0,("PAC no logon_name\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!srv_sig_ptr || !srv_sig_blob) {
-               DEBUG(0,("PAC no srv_key\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!kdc_sig_ptr || !kdc_sig_blob) {
-               DEBUG(0,("PAC no kdc_key\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       /* Find and zero out the signatures, as required by the signing algorithm */
-
-       /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
-       ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe,
-                                      kdc_sig_wipe,
-                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the KDC signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe,
-                                      srv_sig_wipe,
-                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't parse the SRV signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* Now zero the decoded structure */
-       memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
-       memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
-
-       /* and reencode, back into the same place it came from */
-       ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
-                                      kdc_sig_wipe,
-                                      (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the KDC signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-       ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
-                                      srv_sig_wipe,
-                                      (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the SRV signature: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* push out the whole structure, but now with zero'ed signatures */
-       ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
-                                      pac_data_raw,
-                                      (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               status = ndr_map_error2ntstatus(ndr_err);
-               DEBUG(0,("can't repack the RAW PAC: %s\n",
-                       nt_errstr(status)));
-               return status;
-       }
-
-       /* verify by service_key */
-       ret = check_pac_checksum(mem_ctx,
-                                modified_pac_blob, srv_sig_ptr,
-                                context,
-                                service_keyblock);
-       if (ret) {
-               DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               if (k5ret) {
-                       *k5ret = ret;
-               }
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       if (krbtgt_keyblock) {
-               ret = check_pac_checksum(mem_ctx,
-                                           srv_sig_ptr->signature, kdc_sig_ptr,
-                                           context, krbtgt_keyblock);
-               if (ret) {
-                       DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
-                                 smb_get_krb5_error_message(context, ret, mem_ctx)));
-                       if (k5ret) {
-                               *k5ret = ret;
-                       }
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-       }
-
-       /* Convert to NT time, so as not to loose accuracy in comparison */
-       unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
-
-       if (tgs_authtime_nttime != logon_name->logon_time) {
-               DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
-               DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time)));
-               DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime)));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM,
-                                   &client_principal_pac);
-       if (ret) {
-               DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
-                         logon_name->account_name,
-                         smb_get_krb5_error_message(context, ret, mem_ctx)));
-               if (k5ret) {
-                       *k5ret = ret;
-               }
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
-               DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n",
-                         logon_name->account_name));
-               krb5_free_principal(context, client_principal_pac);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       krb5_free_principal(context, client_principal_pac);
-
-#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(3,("Found account name from PAC: %s [%s]\n",
-                logon_info->info3.base.account_name.string,
-                logon_info->info3.base.full_name.string));
-       *pac_data_out = pac_data;
-
-       return NT_STATUS_OK;
-}
-
 _PUBLIC_  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
 _PUBLIC_  NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
-                                 struct PAC_LOGON_INFO **logon_info,
-                                 DATA_BLOB blob,
-                                 krb5_context context,
-                                 const krb5_keyblock *krbtgt_keyblock,
-                                 const krb5_keyblock *service_keyblock,
-                                 krb5_const_principal client_principal,
-                                 time_t tgs_authtime,
-                                 krb5_error_code *k5ret)
+                                          DATA_BLOB blob,
+                                          krb5_context context,
+                                          const krb5_keyblock *krbtgt_keyblock,
+                                          const krb5_keyblock *service_keyblock,
+                                          krb5_const_principal client_principal,
+                                          time_t tgs_authtime,
+                                          struct PAC_LOGON_INFO **logon_info)
 {
        NTSTATUS nt_status;
        struct PAC_DATA *pac_data;
        int i;
        nt_status = kerberos_decode_pac(mem_ctx,
 {
        NTSTATUS nt_status;
        struct PAC_DATA *pac_data;
        int i;
        nt_status = kerberos_decode_pac(mem_ctx,
-                                       &pac_data,
                                        blob,
                                        context,
                                        krbtgt_keyblock,
                                        service_keyblock,
                                        client_principal,
                                        tgs_authtime,
                                        blob,
                                        context,
                                        krbtgt_keyblock,
                                        service_keyblock,
                                        client_principal,
                                        tgs_authtime,
-                                       k5ret);
+                                       &pac_data);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
index 4a306131ccf74ff5af1fcf4b07d0991d7ced4f2e..f09e039964e0858926541c86435e9f62b0416502 100644 (file)
@@ -142,13 +142,13 @@ static bool torture_pac_self_check(struct torture_context *tctx)
 
        /* Now check that we can read it back (using full decode and validate) */
        nt_status = kerberos_decode_pac(mem_ctx, 
 
        /* Now check that we can read it back (using full decode and validate) */
        nt_status = kerberos_decode_pac(mem_ctx, 
-                                       &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        &krbtgt_keyblock,
                                        &server_keyblock,
                                        client_principal, 
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        &krbtgt_keyblock,
                                        &server_keyblock,
                                        client_principal, 
-                                       logon_time, NULL);
+                                       logon_time,
+                                       &pac_data);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
@@ -189,14 +189,13 @@ static bool torture_pac_self_check(struct torture_context *tctx)
 
        /* Now check that we can read it back (yet again) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
 
        /* Now check that we can read it back (yet again) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
-                                           &logon_info,
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            &krbtgt_keyblock,
                                            &server_keyblock,
                                            client_principal, 
                                            logon_time, 
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            &krbtgt_keyblock,
                                            &server_keyblock,
                                            client_principal, 
                                            logon_time, 
-                                           NULL);
+                                           &logon_info);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
@@ -408,12 +407,11 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
 
        /* Decode and verify the signaure on the PAC */
        nt_status = kerberos_decode_pac(mem_ctx, 
 
        /* Decode and verify the signaure on the PAC */
        nt_status = kerberos_decode_pac(mem_ctx, 
-                                       &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock, 
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock, 
-                                       client_principal, authtime, NULL);
+                                       client_principal, authtime, &pac_data);
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);
@@ -466,12 +464,11 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
 
        /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
 
        /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
-                                           &logon_info,
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            krbtgt_keyblock_p,
                                            &server_keyblock,
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            krbtgt_keyblock_p,
                                            &server_keyblock,
-                                           client_principal, authtime, NULL);
+                                           client_principal, authtime, &logon_info);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
@@ -654,13 +651,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
 
        /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
        nt_status = kerberos_decode_pac(mem_ctx, 
 
        /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
        nt_status = kerberos_decode_pac(mem_ctx, 
-                                       &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
-                                       authtime + 1, NULL);
+                                       authtime + 1, &pac_data);
        if (NT_STATUS_IS_OK(nt_status)) {
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
        if (NT_STATUS_IS_OK(nt_status)) {
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
@@ -691,13 +687,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
        }
 
        nt_status = kerberos_decode_pac(mem_ctx, 
        }
 
        nt_status = kerberos_decode_pac(mem_ctx, 
-                                       &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
-                                       authtime, NULL);
+                                       authtime, &pac_data);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);
@@ -710,13 +705,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
        tmp_blob.data[tmp_blob.length - 2]++;
 
        nt_status = kerberos_decode_pac(mem_ctx, 
        tmp_blob.data[tmp_blob.length - 2]++;
 
        nt_status = kerberos_decode_pac(mem_ctx, 
-                                       &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
-                                       authtime, NULL);
+                                       authtime,
+                                       &pac_data);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            krbtgt_keyblock_p);