s3-gse: Use gss_get_name_attribute to fetch the pac
authorSimo Sorce <idra@samba.org>
Mon, 9 May 2011 15:33:41 +0000 (11:33 -0400)
committerSimo Sorce <idra@samba.org>
Fri, 13 May 2011 20:39:54 +0000 (16:39 -0400)
This is the only way to be sure the pac signatures are correct.
It requires a fairly new version of MIT Kerberos, but that should be fine, it
is new functionality in 3.6 anyways.

source3/configure.in
source3/librpc/crypto/gse.c
source3/librpc/crypto/gse.h
source3/rpc_server/dcesrv_gssapi.c

index d8c59b675bd0793181e683da813b39a5ccd1043e..72568d838f2b751e566dd4c8f09bdbdea0b240d4 100644 (file)
@@ -3860,6 +3860,7 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_get_credentials_for_user, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_get_host_realm, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_free_host_realm, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(gss_get_name_attribute, $KRB5_LIBS)
 
   # MIT krb5 1.8 does not expose this call (yet)
   AC_CHECK_DECLS(krb5_get_credentials_for_user, [], [], [#include <krb5.h>])
index 064ccda2eb1d3cf222ce6f9462f77452c4c5a371..335dc1c53f149fb08af44e7d753c99149a02d961 100644 (file)
 #include "includes.h"
 #include "gse.h"
 
-#if defined(HAVE_KRB5) && defined(HAVE_GSSAPI_GSSAPI_EXT_H) && defined(HAVE_GSS_WRAP_IOV)
+#if defined(HAVE_KRB5) \
+       && defined(HAVE_GSSAPI_GSSAPI_EXT_H) \
+       && defined(HAVE_GSS_WRAP_IOV) \
+       && defined(HAVE_GSS_GET_NAME_ATTRIBUTE)
 
 #include "smb_krb5.h"
 #include "gse_krb5.h"
@@ -681,42 +684,62 @@ NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
        return NT_STATUS_OK;
 }
 
-NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime)
+NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
+                         TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob)
 {
        OM_uint32 gss_min, gss_maj;
-       gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
-       int32_t tkttime;
+       gss_buffer_desc pac_buffer;
+       gss_buffer_desc pac_display_buffer;
+       gss_buffer_desc pac_name = {
+               .value = discard_const_p(char, "urn:mspac:"),
+               .length = sizeof("urn:mspac:") - 1
+       };
+       int more = -1;
+       int authenticated = false;
+       int complete = false;
+       NTSTATUS status;
 
        if (!gse_ctx->authenticated) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       gss_maj = gss_inquire_sec_context_by_oid(
-                               &gss_min, gse_ctx->gss_ctx,
-                               &gse_authtime_oid, &set);
-       if (gss_maj) {
-               DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
-                         gse_errstr(talloc_tos(), gss_maj, gss_min)));
-               return NT_STATUS_NOT_FOUND;
-       }
+       gss_maj = gss_get_name_attribute(&gss_min,
+                                        gse_ctx->client_name, &pac_name,
+                                        &authenticated, &complete,
+                                        &pac_buffer, &pac_display_buffer,
+                                        &more);
 
-       if ((set == GSS_C_NO_BUFFER_SET) || (set->count != 1) != 0) {
-               DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
-                         "data in results.\n"));
-               return NT_STATUS_INTERNAL_ERROR;
+       if (gss_maj != 0) {
+               DEBUG(0, ("obtaining PAC via GSSAPI gss_get_name_attribute "
+                         "failed: %s\n",
+                         gse_errstr(mem_ctx, gss_maj, gss_min)));
+               return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (set->elements[0].length != sizeof(int32_t)) {
-               DEBUG(0, ("Invalid authtime size!\n"));
-               return NT_STATUS_INTERNAL_ERROR;
-       }
+       if (authenticated && complete) {
+               /* The PAC blob is returned directly */
+               *pac_blob = data_blob_talloc(mem_ctx,
+                                            pac_buffer.value,
+                                            pac_buffer.length);
+               if (!pac_blob->data) {
+                       status = NT_STATUS_NO_MEMORY;
+               } else {
+                       status = NT_STATUS_OK;
+               }
 
-       tkttime = *((int32_t *)set->elements[0].value);
+               gss_maj = gss_release_buffer(&gss_min, &pac_buffer);
+               gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer);
 
-       gss_maj = gss_release_buffer_set(&gss_min, &set);
+               return status;
+       }
 
-       *authtime = (time_t)tkttime;
-       return NT_STATUS_OK;
+       DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, "
+                 "complete: %s, more: %s\n",
+                 authenticated ? "true" : "false",
+                 complete ? "true" : "false",
+                 more ? "true" : "false"));
+
+       return NT_STATUS_ACCESS_DENIED;
 }
 
 size_t gse_get_signature_length(struct gse_context *gse_ctx,
@@ -972,7 +995,8 @@ NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime)
+NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
+                         TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
 }
index a6d9a35a7ffdaf0c913e10625f78d0eedda4e931..d9e4a82e0ee3d62f0fd942d66d2fccf3badf8f39 100644 (file)
@@ -57,7 +57,8 @@ NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
                             TALLOC_CTX *mem_ctx, char **client_name);
 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
                            TALLOC_CTX *mem_ctx, DATA_BLOB *pac);
-NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime);
+NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
+                         TALLOC_CTX *mem_ctx, DATA_BLOB *pac);
 
 size_t gse_get_signature_length(struct gse_context *gse_ctx,
                                int seal, size_t payload_size);
index f60f6ce245136a5f30de21f5d58d893f2da2a925..25d85a6730ccad8c5859f3af3897fa2d881c7266 100644 (file)
@@ -106,11 +106,8 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx,
 {
        TALLOC_CTX *tmp_ctx;
        DATA_BLOB auth_data;
-       time_t tgs_authtime;
-       NTTIME tgs_authtime_nttime;
        DATA_BLOB pac;
        struct PAC_DATA *pac_data;
-       struct PAC_LOGON_NAME *logon_name = NULL;
        struct PAC_LOGON_INFO *logon_info = NULL;
        enum ndr_err_code ndr_err;
        unsigned int i;
@@ -122,14 +119,13 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx,
        char *username;
        struct passwd *pw;
        NTSTATUS status;
-       bool bret;
 
        tmp_ctx = talloc_new(mem_ctx);
        if (!tmp_ctx) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = gse_get_authz_data(gse_ctx, tmp_ctx, &auth_data);
+       status = gse_get_pac_blob(gse_ctx, tmp_ctx, &pac);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
                /* TODO: Fetch user by principal name ? */
                status = NT_STATUS_ACCESS_DENIED;
@@ -139,24 +135,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx,
                goto done;
        }
 
-       bret = unwrap_pac(tmp_ctx, &auth_data, &pac);
-       if (!bret) {
-               DEBUG(1, ("Failed to unwrap PAC\n"));
-               status = NT_STATUS_ACCESS_DENIED;
-               goto done;
-       }
-
-       status = gse_get_client_name(gse_ctx, tmp_ctx, &princ_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto done;
-       }
-
-       status = gse_get_authtime(gse_ctx, &tgs_authtime);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto done;
-       }
-       unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
-
        pac_data = talloc_zero(tmp_ctx, struct PAC_DATA);
        if (!pac_data) {
                status = NT_STATUS_NO_MEMORY;
@@ -182,9 +160,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx,
                        }
                        logon_info = data_buf->info->logon_info.info;
                        break;
-               case PAC_TYPE_LOGON_NAME:
-                       logon_name = &data_buf->info->logon_name;
-                       break;
                default:
                        break;
                }
@@ -194,21 +169,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx,
                status = NT_STATUS_NOT_FOUND;
                goto done;
        }
-       if (!logon_name) {
-               DEBUG(1, ("Invalid PAC data, missing logon info!\n"));
-               status = NT_STATUS_NOT_FOUND;
-               goto done;
-       }
-
-       /* check time */
-       if (tgs_authtime_nttime != logon_name->logon_time) {
-               DEBUG(1, ("Logon time mismatch between ticket and PAC!\n"
-                         "PAC Time = %s | Ticket Time = %s\n",
-                         nt_time_string(tmp_ctx, logon_name->logon_time),
-                         nt_time_string(tmp_ctx, tgs_authtime_nttime)));
-               status = NT_STATUS_ACCESS_DENIED;
-               goto done;
-       }
 
        /* TODO: Should we check princ_name against account_name in
         * logon_name ? Are they supposed to be identical, or can an