r8250: More PAC work. We now sucessfully verify the KDC signature from my DC
authorAndrew Bartlett <abartlet@samba.org>
Sat, 9 Jul 2005 01:58:38 +0000 (01:58 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:19:25 +0000 (13:19 -0500)
(I have included the krbtgt key from my test network).

It turns out the krbtgt signature is over the 16 (or whatever,
enc-type dependent) bytes of the signature, not the entire structure.

Also do not even try to use Kerberos or GSSAPI on an IP address, it
will only fail.

Andrew Bartlett
(This used to be commit 3b9558e82fdebb58f240d43f6a594d676eb04daf)

source4/auth/gensec/gensec_gssapi.c
source4/auth/gensec/gensec_krb5.c
source4/auth/kerberos/kerberos.h
source4/auth/kerberos/kerberos_pac.c
source4/librpc/idl/krb5pac.idl
source4/torture/auth/pac.c

index 2b7c4ca2cc0c45d05cb7c4e7cac97922cb04fffa..e6049edc5858ae14ed608b893589e7be0bca4658 100644 (file)
@@ -228,6 +228,16 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
        NTSTATUS nt_status;
        gss_buffer_desc name_token;
        OM_uint32 maj_stat, min_stat;
+       const char *hostname = gensec_get_target_hostname(gensec_security);
+
+       if (!hostname) {
+               DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       if (is_ipaddress(hostname)) {
+               DEBUG(2, ("Cannot do GSSAPI to a IP address"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        nt_status = gensec_gssapi_start(gensec_security);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -238,7 +248,7 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
 
        name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", 
                                           gensec_get_target_service(gensec_security), 
-                                          gensec_get_target_hostname(gensec_security));
+                                          hostname);
        name_token.length = strlen(name_token.value);
 
        maj_stat = gss_import_name (&min_stat,
@@ -786,7 +796,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
                /* decode and verify the pac */
                nt_status = kerberos_decode_pac(mem_ctx, &logon_info, pac_blob,
                                                gensec_gssapi_state->smb_krb5_context,
-                                               keyblock);
+                                               NULL, keyblock);
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        union netr_Validation validation;
index 69dae1c8d9d4fb68c75a5ed0726089769ff409e1..168b6df3640168b899e83297570689293e263d53 100644 (file)
@@ -138,8 +138,13 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
        const char *hostname = gensec_get_target_hostname(gensec_security);
        if (!hostname) {
                DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
-               return NT_STATUS_ACCESS_DENIED;
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       if (is_ipaddress(hostname)) {
+               DEBUG(2, ("Cannot do GSSAPI to a IP address"));
+               return NT_STATUS_INVALID_PARAMETER;
        }
+
                        
        nt_status = gensec_krb5_start(gensec_security);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -444,7 +449,8 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
 
        /* 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, (gensec_krb5_state->keyblock));
+                                       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 a7c370a1e5d109d73e61c024472d713b28213966..c5b361df5ed301be644466668e535da5adbfccf2 100644 (file)
@@ -131,7 +131,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
                             struct PAC_LOGON_INFO **logon_info_out,
                             DATA_BLOB blob,
                             struct smb_krb5_context *smb_krb5_context,
-                            krb5_keyblock *keyblock);
+                            krb5_keyblock *service_keyblock,
+                            krb5_keyblock *krbtgt_keyblock);
 
 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
                                    struct auth_serversupplied_info *server_info,
index b0844187e5ddfbfe675d0c13a28f72a83ee38576..858f91045cb5a5e730ee1b2e0d2f195c64e07f2a 100644 (file)
@@ -53,7 +53,8 @@ static NTSTATUS check_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 NT_STATUS_FOOBAR;
        }
        ret = krb5_verify_checksum(context,
@@ -77,10 +78,11 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
 }
 
  NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
-                            struct PAC_LOGON_INFO **logon_info_out,
-                            DATA_BLOB blob,
-                            struct smb_krb5_context *smb_krb5_context,
-                            krb5_keyblock *keyblock)
+                             struct PAC_LOGON_INFO **logon_info_out,
+                             DATA_BLOB blob,
+                             struct smb_krb5_context *smb_krb5_context,
+                             krb5_keyblock *krbtgt_keyblock,
+                             krb5_keyblock *service_keyblock)
 {
        NTSTATUS status;
        struct PAC_SIGNATURE_DATA srv_sig;
@@ -159,11 +161,26 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
        /* verify by service_key */
        status = check_pac_checksum(mem_ctx, 
                                    modified_pac_blob, &srv_sig, 
-                                   smb_krb5_context->krb5_context, keyblock);
-       
+                                   smb_krb5_context->krb5_context, 
+                                   service_keyblock);
        if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("PAC Decode: Failed to verify the service signature\n"));
                return status;
        }
+
+       if (krbtgt_keyblock) {
+               DATA_BLOB service_checksum_blob
+                       = data_blob(srv_sig_ptr->signature, sizeof(srv_sig_ptr->signature));
+
+               status = check_pac_checksum(mem_ctx, 
+                                           service_checksum_blob, &kdc_sig, 
+                                           smb_krb5_context->krb5_context, krbtgt_keyblock);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("PAC Decode: Failed to verify the krbtgt signature\n"));
+                       return status;
+               }
+       }
+
        DEBUG(0,("account_name: %s [%s]\n",
                 logon_info->info3.base.account_name.string, 
                 logon_info->info3.base.full_name.string));
@@ -221,13 +238,13 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
                                     struct auth_serversupplied_info *server_info,
                                     krb5_context context,
                                     krb5_keyblock *krbtgt_keyblock,
-                                    krb5_keyblock *server_keyblock,
+                                    krb5_keyblock *service_keyblock,
                                     DATA_BLOB *pac)
 {
        NTSTATUS nt_status;
        DATA_BLOB zero_blob = data_blob(NULL, 0);
        DATA_BLOB tmp_blob = data_blob(NULL, 0);
-       DATA_BLOB server_checksum_blob;
+       DATA_BLOB service_checksum_blob;
        krb5_error_code ret;
        struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
        struct netr_SamInfo3 *sam3;
@@ -335,9 +352,9 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
                return ret;
        }
 
-       ret = make_pac_checksum(mem_ctx, zero_blob, SRV_CHECKSUM, context, server_keyblock);
+       ret = make_pac_checksum(mem_ctx, zero_blob, SRV_CHECKSUM, context, service_keyblock);
        if (ret) {
-               DEBUG(2, ("making server PAC checksum failed: %s\n", 
+               DEBUG(2, ("making service PAC checksum failed: %s\n", 
                          smb_get_krb5_error_message(context, ret, mem_ctx)));
                talloc_free(pac_data);
                return ret;
@@ -357,19 +374,13 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
 
        /* 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, server_keyblock);
+                               context, service_keyblock);
 
-       /* Push the Server checksum out */
-       nt_status = ndr_push_struct_blob(&server_checksum_blob, mem_ctx, SRV_CHECKSUM,
-                                        (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(1, ("PAC_SIGNATURE push failed: %s\n", nt_errstr(nt_status)));
-               talloc_free(pac_data);
-               return EINVAL;
-       }
+       service_checksum_blob
+               = data_blob(SRV_CHECKSUM->signature, sizeof(SRV_CHECKSUM->signature));
 
        /* Then sign Server checksum */
-       ret = make_pac_checksum(mem_ctx, server_checksum_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
+       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)));
index 13a562a8f883a35123b7b5b9bbdb0470cf567827..7a975946d7b3ab27705360f75e8d8ce690c8a09e 100644 (file)
@@ -18,7 +18,7 @@ interface krb5pac
                [flag(STR_SIZE2|STR_NOTERM|STR_BYTESIZE)] string account_name;
        } PAC_LOGON_NAME;
 
-       typedef [public,flag(NDR_PAHEX)] struct {
+       typedef [flag(NDR_PAHEX)] struct {
                uint32 type;
                uint8 signature[16];
        } PAC_SIGNATURE_DATA;
index ecf67a90147faa6941e7e5542226255839a20cdc..ade68fcd77ff8c639f04f702bf453588b2e7ad58 100644 (file)
@@ -26,6 +26,7 @@
 #include "auth/auth.h"
 #include "auth/kerberos/kerberos.h"
 #include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "librpc/gen_ndr/ndr_samr.h"
 
 #ifdef HAVE_KRB5
 
@@ -105,14 +106,13 @@ static BOOL torture_pac_self_check(void)
                                  &server_keyblock,
                                  &tmp_blob);
        
-       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                   &krbtgt_keyblock);
-
        if (ret) {
                DEBUG(1, ("PAC encoding failed: %s\n", 
                          smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                     ret, mem_ctx)));
 
+               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);
@@ -125,7 +125,11 @@ static BOOL torture_pac_self_check(void)
        nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
                                        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 (ret) {
@@ -196,7 +200,9 @@ static BOOL torture_pac_saved_check(void)
        struct PAC_LOGON_INFO *pac_info;
        struct PAC_DATA pac_data;
        krb5_keyblock server_keyblock;
+       krb5_keyblock krbtgt_keyblock;
        uint8_t server_bytes[16];
+       struct samr_Password *krbtgt_bytes;
        
        krb5_error_code ret;
 
@@ -209,6 +215,13 @@ static BOOL torture_pac_saved_check(void)
                return False;
        }
 
+       krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, "B286757148AF7FD252C53603A150B7E7");
+       if (!krbtgt_bytes) {
+               DEBUG(0, ("Could not interpret krbtgt key"));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
        /* The machine trust account in use when the above PAC 
           was generated.  It used arcfour-hmac-md5, so this is easy */
        E_md4hash("iqvwmii8CuEkyY", server_bytes);
@@ -226,6 +239,21 @@ static BOOL torture_pac_saved_check(void)
                return False;
        }
 
+       ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
+                                ENCTYPE_ARCFOUR_HMAC,
+                                krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
+                                &krbtgt_keyblock);
+       if (ret) {
+               DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
+                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                    ret, mem_ctx)));
+
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
        tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
 
        /*tmp_blob.data = file_load(lp_parm_string(-1,"torture","pac_file"), &tmp_blob.length);*/
@@ -236,10 +264,13 @@ static BOOL torture_pac_saved_check(void)
        nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
                                        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 (ret) {
+       if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(1, ("PAC decoding failed: %s\n", 
                          nt_errstr(nt_status)));