heimdal Add clock-skew handling to DCE-style GSSAPI
authorAndrew Bartlett <abartlet@samba.org>
Mon, 8 Nov 2010 06:38:38 +0000 (17:38 +1100)
committerAndrew Tridgell <tridge@samba.org>
Mon, 8 Nov 2010 07:58:09 +0000 (07:58 +0000)
The clock skew handling was previously only on properly wrapped
GSSAPI, and was skipped for DCE-style.  This allows the ASN.1 errors
from the krb5_rd_req to suggest parsing as a kerberos error packet.

Andrew Bartlett

Autobuild-User: Andrew Tridgell <tridge@samba.org>
Autobuild-Date: Mon Nov  8 07:58:09 UTC 2010 on sn-devel-104

source4/heimdal/lib/gssapi/krb5/init_sec_context.c

index f4e103a7a5163a9cd209a54e328d5ad2933bed5e..4538a5376e59b6a7c2912291a2896bcb8af276fd 100644 (file)
@@ -698,6 +698,44 @@ failure:
     return ret;
 }
 
+static krb5_error_code
+handle_error_packet(krb5_context context,
+                   gsskrb5_ctx ctx,
+                   krb5_data indata)
+{
+    krb5_error_code kret;
+    KRB_ERROR error;
+
+    kret = krb5_rd_error(context, &indata, &error);
+    if (kret == 0) {
+       kret = krb5_error_from_rd_error(context, &error, NULL);
+
+       /* save the time skrew for this host */
+       if (kret == KRB5KRB_AP_ERR_SKEW) {
+           krb5_data timedata;
+           unsigned char p[4];
+           int32_t t = error.stime - time(NULL);
+
+           p[0] = (t >> 24) & 0xFF;
+           p[1] = (t >> 16) & 0xFF;
+           p[2] = (t >> 8)  & 0xFF;
+           p[3] = (t >> 0)  & 0xFF;
+
+           timedata.data = p;
+           timedata.length = sizeof(p);
+
+           krb5_cc_set_config(context, ctx->ccache, ctx->target,
+                              "time-offset", &timedata);
+
+           if ((ctx->more_flags & RETRIED) == 0)
+                ctx->state = INITIATOR_RESTART;
+           ctx->more_flags |= RETRIED;
+       }
+       free_KRB_ERROR (&error);
+    }
+    return kret;
+}
+
 
 static OM_uint32
 repl_mutual
@@ -730,6 +768,24 @@ repl_mutual
        /* There is no OID wrapping. */
        indata.length   = input_token->length;
        indata.data     = input_token->value;
+       kret = krb5_rd_rep (context,
+                           ctx->auth_context,
+                           &indata,
+                           &repl);
+       if (kret >= ASN1_BAD_TIMEFORMAT && kret <= ASN1_INDEF_EXTRA_DATA) {
+           ret = _gsskrb5_decapsulate (minor_status,
+                                       input_token,
+                                       &indata,
+                                       "\x03\x00",
+                                       GSS_KRB5_MECHANISM);
+           if (ret == GSS_S_COMPLETE) {
+                   *minor_status = handle_error_packet(context, ctx, indata);
+                   return GSS_S_FAILURE;
+           }
+       } else if (kret) {
+           *minor_status = kret;
+           return GSS_S_FAILURE;
+       }
     } else {
        ret = _gsskrb5_decapsulate (minor_status,
                                    input_token,
@@ -744,50 +800,20 @@ repl_mutual
                                        "\x03\x00",
                                        GSS_KRB5_MECHANISM);
            if (ret == GSS_S_COMPLETE) {
-               KRB_ERROR error;
-               
-               kret = krb5_rd_error(context, &indata, &error);
-               if (kret == 0) {
-                   kret = krb5_error_from_rd_error(context, &error, NULL);
-
-                   /* save the time skrew for this host */
-                   if (kret == KRB5KRB_AP_ERR_SKEW) {
-                       krb5_data timedata;
-                       unsigned char p[4];
-                       int32_t t = error.stime - time(NULL);
-
-                       p[0] = (t >> 24) & 0xFF;
-                       p[1] = (t >> 16) & 0xFF;
-                       p[2] = (t >> 8)  & 0xFF;
-                       p[3] = (t >> 0)  & 0xFF;
-
-                       timedata.data = p;
-                       timedata.length = sizeof(p);
-
-                       krb5_cc_set_config(context, ctx->ccache, ctx->target,
-                                          "time-offset", &timedata);
-
-                       if ((ctx->more_flags & RETRIED) == 0)
-                           ctx->state = INITIATOR_RESTART;
-                       ctx->more_flags |= RETRIED;
-                   }
-                   free_KRB_ERROR (&error);
-               }
-               *minor_status = kret;
+               *minor_status = handle_error_packet(context, ctx, indata);
                return GSS_S_FAILURE;
            }
-           return ret;
+       }
+       kret = krb5_rd_rep (context,
+                           ctx->auth_context,
+                           &indata,
+                           &repl);
+       if (kret) {
+           *minor_status = kret;
+           return GSS_S_FAILURE;
        }
     }
 
-    kret = krb5_rd_rep (context,
-                       ctx->auth_context,
-                       &indata,
-                       &repl);
-    if (kret) {
-       *minor_status = kret;
-       return GSS_S_FAILURE;
-    }
     krb5_free_ap_rep_enc_part (context,
                               repl);