]> eyrie.org Git - kerberos/webauth.git/commitdiff
Give a validation remctl command its own timeout error
authorJon Robertson <jonrober@stanford.edu>
Mon, 22 Sep 2014 20:44:34 +0000 (13:44 -0700)
committerJon Robertson <jonrober@stanford.edu>
Mon, 22 Sep 2014 20:44:34 +0000 (13:44 -0700)
In order to set up out of band methods that will time out if the user
doesn't respond to the out of band prompt (such as a phone call), we
need to have a validation remctl call tell us specifically if it timed
out.  Currently it's just sent as a WK_ERR_UNRECOVERABLE_ERROR, which
makes it impossible to carve out special logic for a timeout.  This will
now be sent as its own error code.

Currently this is only true for validate and not for the userinfo
command.  If we later need to do special things for userinfo timeouts as
well, we'll build on this work.

docs/protocol.xml
include/webauth/basic.h
lib/errors.c
lib/userinfo-remctl.c
lib/userinfo.c
perl/lib/WebAuth.xs
perl/lib/WebKDC.pm
perl/lib/WebKDC/WebKDCException.pm
perl/lib/WebLogin.pm

index 0fcd548cd039366f49d6f64c9040fa48b9e16875..374b24ffcd07bcaf5b56e430cd1ae7d1d20c40fc 100644 (file)
               <t hangText='26'>This authentication was rejected due to too
               many failed authentication attempts for this user.  The
               authentication should be retried later.</t>
+
+              <t hangText='27'>This authentication failed due to a remctl
+              timeout.  The authentication should be tried again.</t>
             </list>
           </t>
         </section>
           with more information about possible factors and authentication
           methods.  Remove the attributes for &lt;configuredFactor> tags,
           since that approach was less flexible.</t>
+
+          <t hangText='3.7.0 (2014-09-18, jonrober)'>
+          <vspace blankLines='0'/>Add error code 27, representing a
+          remctl timeout during multifactor login.</t>
         </list>
       </t>
     </section>
index 7fb53986a7df34aa01e4416342266a15150fd3c7..6dde7264d7bf601bcaa2468801153f18d23210af 100644 (file)
@@ -103,6 +103,7 @@ enum webauth_status {
     WA_PEC_AUTH_REJECTED               = 24, /* Auth to this site rejected */
     WA_PEC_AUTH_REPLAY                 = 25, /* Auth was a replay */
     WA_PEC_AUTH_LOCKOUT                = 26, /* Too many failed attempts */
+    WA_PEC_LOGIN_TIMEOUT               = 27, /* Timeout during login */
 
     /* Internal status codes. */
     WA_ERR_INTERNAL = 1000,  /* Internal error */
@@ -124,6 +125,7 @@ enum webauth_status {
     WA_ERR_NO_ROOM,          /* Supplied buffer too small */
     WA_ERR_RAND_FAILURE,     /* Unable to get random data */
     WA_ERR_REMOTE_FAILURE,   /* A remote service call failed */
+    WA_ERR_REMOTE_TIMEOUT,   /* A remote service call timed out */
     WA_ERR_TOKEN_EXPIRED,    /* Token has expired */
     WA_ERR_TOKEN_REJECTED,   /* Token used in invalid context */
     WA_ERR_TOKEN_STALE,      /* Token is stale */
index 8ef71c14ffadd1eed8668aa0e43ecc50e7a68289..d83eb2f3ba1f85d6bc7b40768874796cca2802e5 100644 (file)
@@ -67,6 +67,7 @@ error_string(struct webauth_context *ctx, int s)
     case WA_PEC_AUTH_REPLAY:
         return "authentication appears to be a replay";
     case WA_PEC_AUTH_LOCKOUT:          return "too many failed attempts";
+    case WA_PEC_LOGIN_TIMEOUT:         return "timeout during login";
 
     /* Internal errors. */
     case WA_ERR_INTERNAL:          return "internal error";
@@ -88,6 +89,7 @@ error_string(struct webauth_context *ctx, int s)
     case WA_ERR_NO_ROOM:           return "supplied buffer too small";
     case WA_ERR_RAND_FAILURE:      return "unable to get random data";
     case WA_ERR_REMOTE_FAILURE:    return "remote call failed";
+    case WA_ERR_REMOTE_TIMEOUT:    return "remote call timed out";
     case WA_ERR_TOKEN_EXPIRED:     return "token has expired";
     case WA_ERR_TOKEN_REJECTED:    return "token used in invalid context";
     case WA_ERR_TOKEN_STALE:       return "token is stale";
index 58716fe2b3ea50459e56b94fda9a672d6079b5d2..944788d5c384ec8f3c663d724b37d2384e17518b 100644 (file)
@@ -114,12 +114,18 @@ wai_user_remctl(struct webauth_context *ctx, const char **command,
 
     /* Set up and execute the command. */
     if (!remctl_open(r, c->host, c->port, c->identity)) {
-        s = WA_ERR_REMOTE_FAILURE;
+        if (strstr(remctl_error(r), "timed out") != NULL)
+            s = WA_ERR_REMOTE_TIMEOUT;
+        else
+            s = WA_ERR_REMOTE_FAILURE;
         wai_error_set(ctx, s, "%s", remctl_error(r));
         goto fail;
     }
     if (!remctl_command(r, command)) {
-        s = WA_ERR_REMOTE_FAILURE;
+        if (strstr(remctl_error(r), "timed out") != NULL)
+            s = WA_ERR_REMOTE_TIMEOUT;
+        else
+            s = WA_ERR_REMOTE_FAILURE;
         wai_error_set(ctx, s, "%s", remctl_error(r));
         goto fail;
     }
@@ -133,7 +139,10 @@ wai_user_remctl(struct webauth_context *ctx, const char **command,
     do {
         out = remctl_output(r);
         if (out == NULL) {
-            s = WA_ERR_REMOTE_FAILURE;
+            if (strstr(remctl_error(r), "timed out") != NULL)
+                s = WA_ERR_REMOTE_TIMEOUT;
+            else
+                s = WA_ERR_REMOTE_FAILURE;
             wai_error_set(ctx, s, "%s", remctl_error(r));
             goto fail;
         }
@@ -143,7 +152,10 @@ wai_user_remctl(struct webauth_context *ctx, const char **command,
             wai_buffer_append(buffer, out->data, out->length);
             break;
         case REMCTL_OUT_ERROR:
-            s = WA_ERR_REMOTE_FAILURE;
+            if (strstr(remctl_error(r), "timed out") != NULL)
+                s = WA_ERR_REMOTE_TIMEOUT;
+            else
+                s = WA_ERR_REMOTE_FAILURE;
             wai_buffer_set(errors, out->data, out->length);
             wai_error_set(ctx, s, "%s", errors->data);
             goto fail;
@@ -155,7 +167,10 @@ wai_user_remctl(struct webauth_context *ctx, const char **command,
                                               out->status);
                 if (wai_buffer_find_string(errors, "\n", 0, &offset))
                     errors->data[offset] = '\0';
-                s = WA_ERR_REMOTE_FAILURE;
+                if (strstr(remctl_error(r), "timed out") != NULL)
+                    s = WA_ERR_REMOTE_TIMEOUT;
+                else
+                    s = WA_ERR_REMOTE_FAILURE;
                 wai_error_set(ctx, s, "%s", errors->data);
                 goto fail;
             }
index 916ac24da1cfb053a7b8a977cd625eb1787a9bf8..ce21505a4bf3e16f508a3c704cd0467299d319e4 100644 (file)
@@ -175,6 +175,10 @@ webauth_user_info(struct webauth_context *ctx, const char *user,
     else
         s = wai_user_info_xml(ctx, user, ip, random_mf, url, factors, info);
 
+    /* Map a timeout to a general failure for userinfo. */
+    if (s == WA_ERR_REMOTE_TIMEOUT)
+        s = WA_ERR_REMOTE_FAILURE;
+
     /*
      * If the call succeeded and random_multifactor was set, say that the
      * random multifactor check passed.  If the call failed but we were told
@@ -225,5 +229,10 @@ webauth_user_validate(struct webauth_context *ctx, const char *user,
                                    result);
     else
         s = wai_user_validate_xml(ctx, user, ip, code, type, state, result);
+
+    /* Map a timeout to a protocol error for validation. */
+    if (s == WA_ERR_REMOTE_TIMEOUT)
+        s = WA_PEC_LOGIN_TIMEOUT;
+
     return s;
 }
index f0f4004d6eaa525b0ffddeb7d549e597fd9b3a38..a61f25e83f86a1f1efae1b8ba1c4060560112ff5 100644 (file)
@@ -447,6 +447,7 @@ BOOT:
     IV_CONST(WA_PEC_AUTH_REJECTED);
     IV_CONST(WA_PEC_AUTH_REPLAY);
     IV_CONST(WA_PEC_AUTH_LOCKOUT);
+    IV_CONST(WA_PEC_LOGIN_TIMEOUT);
 
     /* Key types. */
     IV_CONST(WA_KEY_AES);
index 9ace731d1407c8b945cc5d956555b5d832166d5f..46854058197f33bb6d51caad23542690c55df626 100644 (file)
@@ -81,6 +81,7 @@ our %pec_mapping = (
     &WA_PEC_AUTH_REJECTED               => WK_ERR_AUTH_REJECTED,
     &WA_PEC_AUTH_REPLAY                 => WK_ERR_AUTH_REPLAY,
     &WA_PEC_AUTH_LOCKOUT                => WK_ERR_AUTH_LOCKOUT,
+    &WA_PEC_LOGIN_TIMEOUT               => WK_ERR_LOGIN_TIMEOUT,
 );
 
 # Get a keyring from the configured WebLogin keyring path.  This used to
index b1837f13735dc6e312795954bc54dc6d3b9b8e7b..a6298d64cda2f31f059cdcc1e2b6e08e8ee32bf3 100644 (file)
@@ -60,7 +60,8 @@ BEGIN {
                  WK_ERR_LOA_UNAVAILABLE
                  WK_ERR_AUTH_REJECTED
                  WK_ERR_AUTH_REPLAY
-                 WK_ERR_AUTH_LOCKOUT);
+                 WK_ERR_AUTH_LOCKOUT
+                 WK_ERR_LOGIN_TIMEOUT);
 }
 
 # This hash maps the error codes to names, used when stringifying.
@@ -91,6 +92,7 @@ sub WK_ERR_LOA_UNAVAILABLE         () { 12 }
 sub WK_ERR_AUTH_REJECTED           () { 13 }
 sub WK_ERR_AUTH_REPLAY             () { 14 }
 sub WK_ERR_AUTH_LOCKOUT            () { 15 }
+sub WK_ERR_LOGIN_TIMEOUT           () { 16 }
 
 # Create a new WebKDC::WebKDCException object and initialize the status,
 # message, protocol error, and data.
@@ -284,6 +286,11 @@ cache.
 This account has been locked out due to too many unsuccessful login
 attempts.  The login should be retried later.
 
+=item WK_ERR_LOGIN_TIMEOUT
+
+There was a timeout while attempting to log in.  The login should be
+retried, though multiple errors could mean a problem outside of WebAuth.
+
 =back
 
 =head1 CLASS METHODS
index 1d730526178df4e744593e95607ff1a3f145e0f6..ed884bcc0b2487a29ad7f4d7736b72b06c6b6df2 100644 (file)
@@ -2219,14 +2219,10 @@ sub multifactor : Runmode {
             print STDERR "multifactor rejected: $error ($status): $message\n"
                 if $self->param ('logging');
             $self->register_auth_fail ($req->user);
-
-        # We will get this if there is a webkdc timeout for an out-of-band
-        # authentication.  Matching on this isn't optimal because it could be
-        # other things, but for right now build from here.  Do not log an
-        # auth fail for this.
-        } elsif ($status == WK_ERR_UNRECOVERABLE_ERROR) {
+        } elsif ($status == WK_ERR_LOGIN_TIMEOUT) {
             print STDERR "multifactor timeout: $error ($status)\n"
                 if $self->param ('logging');
+            $self->template_params ({err_multifactor_timeout => 1});
 
         } else {
             # Hopefully this is close enough that we can just use the default