You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by pq...@apache.org on 2009/03/15 03:42:49 UTC

svn commit: r754596 - /labs/orthrus/trunk/src/userdb.c

Author: pquerna
Date: Sun Mar 15 02:42:48 2009
New Revision: 754596

URL: http://svn.apache.org/viewvc?rev=754596&view=rev
Log:
More work on the verification code.

Modified:
    labs/orthrus/trunk/src/userdb.c

Modified: labs/orthrus/trunk/src/userdb.c
URL: http://svn.apache.org/viewvc/labs/orthrus/trunk/src/userdb.c?rev=754596&r1=754595&r2=754596&view=diff
==============================================================================
--- labs/orthrus/trunk/src/userdb.c (original)
+++ labs/orthrus/trunk/src/userdb.c Sun Mar 15 02:42:48 2009
@@ -55,10 +55,14 @@
   return ORTHRUS_SUCCESS;
 }
 
-typedef struct orthrus_user_t {
-  const char *username;
+typedef struct orthrus_challenge_t {
   apr_uint32_t sequence;
   const char *seed;
+} orthrus_challenge_t;
+
+typedef struct orthrus_user_t {
+  const char *username;
+  orthrus_challenge_t ch;
   const char *lastreply;
 } orthrus_user_t;
 
@@ -102,14 +106,14 @@
       return orthrus_error_createf(APR_EGENERAL, "userdb corrupted at line %d", lineno);
     }
 
-    user->sequence = apr_strtoi64(v, NULL, 10);
+    user->ch.sequence = apr_strtoi64(v, NULL, 10);
 
     v = apr_strtok(NULL, " ", &strtok_state);
     if (!v) {
       return orthrus_error_createf(APR_EGENERAL, "userdb corrupted at line %d", lineno);
     }
 
-    user->seed = apr_pstrdup(ort->pool, v);
+    user->ch.seed = apr_pstrdup(ort->pool, v);
 
     v = apr_strtok(NULL, " ", &strtok_state);
     if (!v) {
@@ -142,16 +146,116 @@
     return rv;
   }
 
-  *challenge = apr_psprintf(pool, "otp-md5 %u %s", user->sequence,  user->seed);
+  /* TODO: Configurable algorithms */
+  *challenge = apr_psprintf(pool, "otp-md5 %u %s", user->ch.sequence,  user->ch.seed);
+  
+  return ORTHRUS_SUCCESS;
+}
+
+static orthrus_error_t* decode_challenge(orthrus_t *ort,
+                                         const char *challenge,
+                                         orthrus_challenge_t *ch)
+{
+  char *strtok_state;
+  char *v;
+  char *p = apr_pstrdup(ort->pool, challenge);
+  
+  /* len("otp-md5 1 a") = 11 */
+  if (strlen(p) < 11) {
+    return orthrus_error_create(APR_EGENERAL, "challenge string is too small.");
+  }
+  
+  p += 4;
+
+  if (strncmp("md5 ", p, 4) != 0) {
+    return orthrus_error_create(APR_ENOTIMPL, "only md5 verification is supported.");
+  }
+  
+  p += 4;
+  
+  v = apr_strtok(p, " ", &strtok_state);
+  
+  if (!v) {
+    return orthrus_error_create(APR_EGENERAL, "invalid challenge string when looking for sequence.");
+  }
+  
+  ch->sequence = apr_strtoi64(v, NULL, 10);
+  
+  v = apr_strtok(NULL, " ", &strtok_state);
+  if (!v) {
+    return orthrus_error_create(APR_EGENERAL,
+                                "invalid challenge string when looking for seed.");
+  }
+  
+  ch->seed = apr_pstrdup(ort->pool, v);
+
+  return ORTHRUS_SUCCESS;
+}
+
+static orthrus_error_t* decode_reply(orthrus_t *ort,
+                                    const char *reply,
+                                    orthrus_response_t **resp)
+{
+
+  /* TODO: Support Six word dictionary decoding.
+   *  (note, its just a SHOULD from the RFC) */
+  
+  /* RFC 2289 Section 6.0, "Form of Output":
+   * If a six-word encoded one-time password is valid, it is accepted.  
+   * Otherwise, if the one-time password can be interpreted as hexadecimal, and 
+   * with that decoding it is valid, then it is accepted.*/
+  
   
+  *resp = apr_pcalloc(ort->pool, sizeof(orthrus_response_t));
   return ORTHRUS_SUCCESS;
 }
 
+/* RFC 2289 Section 7.0 "VERIFICATION OF ONE-TIME PASSWORDS":
+ * The server system has a database containing, for each user, the
+ * one-time password from the last successful authentication or the
+ * first OTP of a newly initialized sequence. To authenticate the user,
+ * the server decodes the one-time password received from the generator
+ * into a 64-bit key and then runs this key through the secure hash
+ * function once. If the result of this operation matches the stored
+ * previous OTP, the authentication is successful and the accepted
+ * one-time password is stored for future use.
+ */
+
 orthrus_error_t* orthrus_userdb_verify(orthrus_t *ort,
                                        const char *username,
                                        const char *challenge,
                                        const char *reply,
                                        apr_pool_t *pool)
 {
+  orthrus_error_t* rv;
+  orthrus_challenge_t ch;
+  orthrus_user_t *user;
+  orthrus_response_t *resp;
+
+  rv = userdb_get_user(ort, username, &user);
+  if (rv) {
+    return rv;
+  }
+
+  rv = decode_challenge(ort, challenge, &ch);
+  if (rv) {
+    return rv;
+  }
+  
+  
+  if (strcmp(ch.seed, user->ch.seed) != 0) {
+    return orthrus_error_create(APR_EGENERAL, "seed changed between challenge and verification.");
+  }
+
+  if (ch.sequence != user->ch.sequence) {
+    return orthrus_error_create(APR_EGENERAL, "sequence changed between challenge and verification.");
+  }
+
+  rv = decode_reply(ort, reply, &resp);
+
+  if (rv) {
+    return rv;
+  }
+  
   return orthrus_error_create(APR_ENOTIMPL, "userdb functionality is not complete");
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org