Interface changes to use state manager instead of local state.
authorfcusack <fcusack>
Thu, 15 Sep 2005 07:19:02 +0000 (07:19 +0000)
committerfcusack <fcusack>
Thu, 15 Sep 2005 07:19:02 +0000 (07:19 +0000)
Does not include the code that actually talks to the state manager
yet (otp_state.c).  Free improvement: better logging of softfail
and hardfail conditions.

raddb/otp.conf
src/modules/rlm_otp/Makefile.in
src/modules/rlm_otp/cardops/cryptocard.c
src/modules/rlm_otp/cardops/cryptocard.h
src/modules/rlm_otp/otp.h
src/modules/rlm_otp/otp_cardops.c
src/modules/rlm_otp/otp_cardops.h
src/modules/rlm_otp/otp_rlm.c
src/modules/rlm_otp/otp_sync.c [deleted file]
src/modules/rlm_otp/otp_sync.h [deleted file]
src/modules/rlm_otp/otp_x99.c

index dce3afb..0bd16e2 100644 (file)
@@ -36,11 +36,9 @@ otp {
        # (default: /etc/otppasswd)
        #pwdfile = /etc/otppasswd
 
-       # Directory containing sync mode and state info.
-       # This directory must be mode 0700, and owned by the
-       # the user radiusd runs as.
-       # (default: /etc/otpsync.d)
-       #syncdir = /etc/otpsync.d
+       # State manager rendezvous point.
+       # (default: /var/run/lsmd/socket)
+       #lsmd_rp = /var/run/lsmd/socket
 
        # Text to use for the challenge.  The '%' character is
        # disallowed, except that you MUST have a single "%s"
index 2c3002b..3e1d3ce 100644 (file)
@@ -21,9 +21,9 @@
 #
 #######################################################################
 TARGET         = @targetname@
-SRCS           = otp_rlm.c otp_util.c otp_radstate.c otp_x99.c otp_sync.c
+SRCS           = otp_rlm.c otp_util.c otp_radstate.c otp_x99.c otp_state.c
 SRCS          += otp_site.c otp_pwe.c otp_log.c otp_cardops.c
-HEADERS        = otp.h otp_rad.h otp_sync.h otp_pwe.h otp_cardops.h
+HEADERS        = otp.h otp_rad.h otp_pwe.h otp_cardops.h
 RLM_CFLAGS     = @otp_cflags@ $(OPENSSL_INCLUDE)
 CARDOPS_LTLIBS = $(patsubst %.c,%.lo,$(wildcard cardops/*.c))
 RLM_LIBS       = @otp_ldflags@ $(OPENSSL_LIBS) $(CARDOPS_LTLIBS)
index e07e6b1..5349c0a 100644 (file)
@@ -86,8 +86,7 @@ cryptocard_keystring2keyblock(const char *keystring, unsigned char keyblock[])
  * Returns 0 on success, non-zero otherwise.
  */
 static int
-cryptocard_challenge(const char *syncdir, otp_user_info_t *user_info,
-                    int ewin,
+cryptocard_challenge(const otp_user_info_t *user_info, unsigned int ewin,
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
@@ -95,26 +94,13 @@ __attribute__ ((unused))
                     char challenge[OTP_MAX_CHALLENGE_LEN + 1])
 {
     unsigned char output[8];
-    int i, rc = -1;
-
-    if (ewin == 0) {
-       /* Return currently stored next challenge. */
-       return otp_get_sync_challenge(syncdir, user_info->username, challenge);
-
-    } else if (challenge[0]) {
-       /* iterate once on the supplied challenge */
-       ewin = 1;
-    } else {
-       /* iterate ewin times on the stored next challenge */
-       rc = otp_get_sync_challenge(syncdir, user_info->username, challenge);
-       if (rc)
-           return rc;
-    }
+    int i, rc = 0;
+
     /* CRYPTOCard sync challenges are always 8 bytes. */
-    if (strlen(challenge) != 8) {
+    if (strlen(challenge) != 8)
        return -1;
-    }
 
+    /* iterate ewin times on the challenge */
     while (ewin--) {
        if ((rc = otp_x99_mac(challenge, 8, output,
                              user_info->keyblock)) == 0) {
index c7370c2..768023c 100644 (file)
@@ -41,9 +41,8 @@
 static int cryptocard_name2fm(const char *name, uint32_t *featuremask);
 static int cryptocard_keystring2keyblock(const char *keystring,
                                         unsigned char keyblock[]);
-static int cryptocard_challenge(const char *syncdir,
-                               otp_user_info_t *user_info,
-                               int ewin, int twin,
+static int cryptocard_challenge(const otp_user_info_t *user_info,
+                               unsigned int ewin, int twin,
                                char challenge[OTP_MAX_CHALLENGE_LEN + 1]);
 static int cryptocard_response(otp_user_info_t *user_info,
                               const char *challenge,
index dfe5ae1..6384e42 100644 (file)
 #ifndef OTP_H
 #define OTP_H
 
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+#include <pthread.h>
+
 #include <inttypes.h>
 #include <openssl/des.h> /* des_cblock */
 #include <time.h>        /* time_t */
@@ -34,8 +39,8 @@
 /* Default passwd file */
 #define OTP_PWDFILE "/etc/otppasswd"
 
-/* Default sync dir */
-#define OTP_SYNCDIR "/etc/otpsync.d"
+/* state manager rendezvous point */
+#define OTP_LSMD_RP "/var/run/lsmd/socket"
 
 /* Default prompt for presentation of challenge */
 #define OTP_CHALLENGE_PROMPT "Challenge: %s\n Response: "
@@ -69,7 +74,7 @@
 /* struct used for instance/option data */
 typedef struct otp_option_t {
     char *pwdfile;     /* file containing user:card_type:key entries      */
-    char *syncdir;     /* dir containing sync mode and state info         */
+    char *lsmd_rp;     /* state manager rendezvous point                  */
     char *chal_prompt; /* text to present challenge to user, must have %s */
     int chal_len;      /* challenge length, min 5 digits                  */
     int softfail;      /* number of auth fails before time delay starts   */
@@ -122,6 +127,24 @@ typedef struct otp_user_info_t {
 #endif
 } otp_user_info_t;
 
+/* user-specific state info */
+#define OTP_MAX_CSD_LEN 64
+typedef struct otp_user_state_t {
+    int                locked;                 /* locked aka success flag        */
+    int                *fdp;                   /* fd for return data             */
+    int                updated;                /* state updated? (1 unless err)  */
+    char       challenge[OTP_MAX_CHALLENGE_LEN+1];     /* next sync chal */
+    char       csd[OTP_MAX_CSD_LEN+1]; /* card specific data             */
+    unsigned   failcount;              /* number of consecutive failures */
+    time_t     authtime;               /* time of last auth              */
+    int                authpos;                /* window position for softfail   */
+} otp_user_state_t;
+
+/* fc (failcondition) shortcuts */
+#define OTP_FC_FAIL_NONE 0     /* no failures */
+#define OTP_FC_FAIL_HARD 1     /* failed hard */
+#define OTP_FC_FAIL_SOFT 2     /* failed soft */
+
 /* otp_cardops.c */
 /* return codes from otp_pw_valid() */
 #define OTP_RC_OK              0
@@ -141,7 +164,7 @@ extern int otp_pw_valid(const char *username,
 /* otp_x99.c */
 extern int otp_x99_mac(const unsigned char *input, size_t len,
                       unsigned char output[8],
-                      unsigned char keyblock[OTP_MAX_KEY_LEN]);
+                      const unsigned char keyblock[OTP_MAX_KEY_LEN]);
 
 /* otp_util.c */
 /* Character maps for generic hex and vendor specific decimal modes */
@@ -160,24 +183,10 @@ extern void otp_keyblock2keystring(char *s, const des_cblock keyblock,
 extern int otp_get_user_info(const char *pwdfile, const char *username,
                             otp_user_info_t *user_info);
 
-/* otp_sync.c */
-#define OTP_FC_FAIL_ERR  -1
-#define OTP_FC_FAIL_HARD -2
-#define OTP_FC_FAIL_SOFT -3
-
-extern int otp_get_sync_challenge(const char *syncdir, const char *username,
-                                 char challenge[OTP_MAX_CHALLENGE_LEN + 1]);
-extern int otp_set_sync_data(const char *syncdir, const char *username,
-                            const char *challenge, const des_cblock keyblock);
-extern int otp_check_failcount(const char *syncdir, const otp_option_t *inst);
-extern int otp_incr_failcount(const char *syncdir, const char *username);
-extern int otp_reset_failcount(const char *syncdir, const char *username);
-extern int otp_get_last_auth(const char *syncdir, const char *username,
-                            time_t *last_auth);
-extern int otp_upd_last_auth(const char *syncdir, const char *username);
-extern unsigned otp_get_last_auth_pos(const char *syncdir,const char *username);
-extern int otp_set_last_auth_pos(const char *syncdir, const char *username,
-                                unsigned pos);
+/* otp_state.c */
+extern int otp_state_get(const otp_option_t *opt, const char *username,
+                        otp_user_state_t *user_state, const char *log_prefix);
+extern int otp_state_put(const char *username, otp_user_state_t *user_state);
 
 /* otp_site.c */
 extern int otp_challenge_transform(const char *username,
@@ -193,4 +202,3 @@ extern void otp_log(int level, const char *format, ...);
 #endif
 
 #endif /* OTP_H */
-
index 00156ae..746c9a5 100644 (file)
@@ -26,6 +26,7 @@
 
 static const char rcsid[] = "$Id$";
 
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -63,15 +64,16 @@ otp_pw_valid(const char *username, char *challenge, const char *passcode,
             cmpfunc_t cmpfunc, void *data,
             const char *log_prefix)
 {
-    int                rc, fc, nmatch, i;
+    int                rc, nmatch, i;
+    int                fc = OTP_FC_FAIL_NONE;  /* failcondition */
 
                /* expected response */
     char       e_response[OTP_MAX_RESPONSE_LEN + OTP_MAX_PIN_LEN + 1];
     int                pin_adjust = 0; /* pin offset in e_response */
-    unsigned   auth_pos = 0;   /* window position of this authentication */
-    time_t     last_auth_time; /* time of last authentication */
+    int                authpos = -2;   /* window pos of last success auth, or -2 */
 
-    otp_user_info_t    user_info = { .cardops = NULL };
+    otp_user_info_t    user_info  = { .cardops = NULL };
+    otp_user_state_t   user_state = { .locked = 0 };
 
     /* sanity */
     if (!challenge) {
@@ -143,22 +145,40 @@ otp_pw_valid(const char *username, char *challenge, const char *passcode,
        pin_adjust = strlen(e_response);
     }
 
-    /* Get the time of the last authentication. */
-    if (otp_get_last_auth(opt->syncdir, username, &last_auth_time) != 0) {
-       otp_log(OTP_LOG_ERR,
-               "%s: unable to get last auth time for [%s]",
+    /* Get user state. */
+    if (otp_state_get(opt, username, &user_state, log_prefix) != 0) {
+       otp_log(OTP_LOG_ERR, "%s: unable to get state for [%s]",
                log_prefix, username);
        rc = OTP_RC_SERVICE_ERR;
        goto auth_done_service_err;
-       /* NB: last_auth_time, failcount not updated. */
     }
 
-    /* Get failure count for later evaluation. */
-    fc = otp_check_failcount(username, opt);
-    if (fc == OTP_FC_FAIL_ERR) {
-       rc = OTP_RC_SERVICE_ERR;
-       goto auth_done_service_err;
-       /* NB: last_auth_time, failcount not updated. */
+    /* Set fc (failcondition). */
+    if (opt->hardfail && user_state.failcount >= opt->hardfail) {
+       fc = OTP_FC_FAIL_HARD;
+    } else if (opt->softfail && user_state.failcount >= opt->softfail) {
+       time_t when;
+       int fcount;
+
+       /*
+        * Determine the next time this user can authenticate.
+        *
+        * Once we hit softfail, we introduce a 1m delay before the user
+        * can authenticate.  For each successive failed authentication,
+        * we double the delay time, up to a max of 32 minutes.  While in
+        * the "delay mode" of operation, all authentication ATTEMPTS are
+        * considered failures.  Also, each attempt during the delay period
+        * restarts the clock.
+        *
+        * The advantage of a delay instead of a simple lockout is that an
+        * attacker can't lock out a user as easily; the user need only wait
+        * a bit before he can authenticate.
+        */
+       fcount = user_state.failcount - opt->softfail;
+       when   = user_state.authtime +
+                (fcount > 5 ? 32 * 60 : (1 << fcount) * 60);
+       if (time(NULL) < when)
+           fc = OTP_FC_FAIL_SOFT;
     }
 
 async_response:
@@ -172,7 +192,7 @@ async_response:
                    log_prefix, username);
            rc = OTP_RC_SERVICE_ERR;
            goto auth_done_service_err;
-           /* NB: last_auth_time, failcount not updated. */
+           /* NB: state not updated. */
        }
 
        /* Calculate the async response. */
@@ -183,7 +203,7 @@ async_response:
                    "to challenge %s", log_prefix, username, challenge);
            rc = OTP_RC_SERVICE_ERR;
            goto auth_done_service_err;
-           /* NB: last_auth_time, failcount not updated. */
+           /* NB: state not updated. */
        }
        /* NOTE: We do not display the PIN. */
 #if defined(FREERADIUS)
@@ -218,14 +238,16 @@ async_response:
            if (fc == OTP_FC_FAIL_HARD) {
                otp_log(OTP_LOG_AUTH,
                        "%s: bad async auth for [%s]: valid but in hardfail",
-                       log_prefix, username);
+                       " (%d/%d failed/max)", log_prefix, username,
+                       user_state.failcount, opt->hardfail);
                rc = OTP_RC_MAXTRIES;
                goto auth_done;
            }
            if (fc == OTP_FC_FAIL_SOFT) {
                otp_log(OTP_LOG_AUTH,
                        "%s: bad async auth for [%s]: valid but in softfail",
-                       log_prefix, username);
+                       " (%d/%d failed/max)", log_prefix, username,
+                       user_state.failcount, opt->softfail);
                rc = OTP_RC_MAXTRIES;
                goto auth_done;
            }
@@ -260,37 +282,20 @@ sync_response:
      * a previous authentication is further ahead in the
      * window (when in softfail), because we want to
      * report a correct passcode even if it is behind
-     * the currently acceptable window,
+     * the currently acceptable window.
      */
     if ((user_info.featuremask & OTP_CF_SM) && opt->allow_sync) {
-       int end = opt->ewindow_size, last_auth_pos = 0;
+       int end = opt->ewindow_size;
 
        /* Increase window for ewindow2. */
-       if (opt->ewindow2_size && fc == OTP_FC_FAIL_SOFT) {
-           last_auth_pos = otp_get_last_auth_pos(opt->syncdir, username);
-           if (last_auth_pos < 0) {
-               otp_log(OTP_LOG_ERR,
-                       "%s: unable to get last auth window position for [%s]",
-                       log_prefix, username);
-               rc = OTP_RC_SERVICE_ERR;
-               goto auth_done_service_err;
-               /* NB: last_auth_time, failcount not updated. */
-           }
+       if (opt->ewindow2_size && fc == OTP_FC_FAIL_SOFT)
            end = opt->ewindow2_size;
-       }
 
-        for (i = 0; i <= end; ++i) {
-           /* Get sync challenge and key. */
-           if (user_info.cardops->challenge(opt->syncdir, &user_info,
-                                            i, 0, challenge) != 0) {
-               otp_log(OTP_LOG_ERR,
-                       "%s: unable to get sync challenge e:%d t:%d for [%s]",
-                       log_prefix, i, 0, username);
-               rc = OTP_RC_SERVICE_ERR;
-               goto auth_done_service_err;
-               /* NB: last_auth_time, failcount not updated. */
-           }
+       /* Setup initial challenge. */
+       (void) strcpy(challenge, user_state.challenge);
 
+       /* Test each sync response in the window. */
+        for (i = 0; i <= end; ++i) {
            /* Calculate sync response. */
            if (user_info.cardops->response(&user_info, challenge,
                                            &e_response[pin_adjust]) != 0) {
@@ -300,7 +305,7 @@ sync_response:
                        log_prefix, i, 0, username, challenge);
                rc = OTP_RC_SERVICE_ERR;
                goto auth_done_service_err;
-               /* NB: last_auth_time, failcount not updated. */
+               /* NB: state not updated. */
            }
            /* NOTE: We do not display the PIN. */
 #if defined(FREERADIUS)
@@ -326,9 +331,10 @@ sync_response:
                nmatch = cmpfunc(data, e_response);
            if (!nmatch) {
                if (fc == OTP_FC_FAIL_HARD) {
-                   otp_log(OTP_LOG_AUTH, "%s: bad sync auth for [%s]: "
-                                         "valid but in hardfail",
-                           log_prefix, username);
+                   otp_log(OTP_LOG_AUTH,
+                           "%s: bad sync auth for [%s]: valid but in hardfail",
+                           " (%d/%d failed/max)", log_prefix, username,
+                           user_state.failcount, opt->hardfail);
                    rc = OTP_RC_MAXTRIES;
                    goto auth_done;
                }
@@ -339,9 +345,11 @@ sync_response:
                if (fc == OTP_FC_FAIL_SOFT) {
                    if (!opt->ewindow2_size) {
                        /* ewindow2 mode not configured */
-                       otp_log(OTP_LOG_AUTH, "%s: bad sync auth for [%s]: "
-                                             "valid but in softfail",
-                               log_prefix, username);
+                       otp_log(OTP_LOG_AUTH,
+                               "%s: bad sync auth for [%s]: "
+                               "valid but in softfail",
+                               " (%d/%d failed/max)", log_prefix, username,
+                               user_state.failcount, opt->softfail);
                        rc = OTP_RC_MAXTRIES;
                        goto auth_done;
                    }
@@ -349,21 +357,10 @@ sync_response:
                    /*
                     * User must enter two consecutive correct sync passcodes
                     * for ewindow2 softfail override.
-                    *
-                    * last_auth_pos == 0 could mean that the last entry was
-                    * correct and at the zeroeth sync position, or that the
-                    * last entry was correct and async, or that the last
-                    * entry was incorrect.  Since we can't differentiate,
-                    * we can't use a 0 last_auth_pos as the first passcode
-                    * in the ewindow2 sequence.  This means that users who
-                    * start an ewindow2 softfail override at the very left
-                    * edge of the window must enter 3 passcodes (0,1,2)
-                    * instead of 2.
-                    * TODO: update get_last_auth_pos to return pos+1.
                     */
-                   if (last_auth_pos && (i == last_auth_pos + 1) &&
+                   if ((i == user_state.authpos + 1) &&
                        /* ... within ewindow2_delay seconds. */
-                       (time(NULL) - last_auth_time < opt->ewindow2_delay)) {
+                       (time(NULL) - user_state.authtime < opt->ewindow2_delay)) {
                        /* This is the 2nd of two consecutive responses. */
                        otp_log(OTP_LOG_AUTH,
                                "%s: ewindow2 softfail override for [%s] at "
@@ -379,11 +376,11 @@ sync_response:
                                    "%s: auth: [%s] ewindow2 candidate "
                                    "at position %i", log_prefix, username, i);
 #endif
-                       auth_pos = i;
+                       authpos = i;
                        rc = OTP_RC_AUTH_ERR;
                        goto auth_done;
                    }
-               }
+               } /* if (in softfail) */
 
                /* Authenticated in sync mode. */
                rc = OTP_RC_OK;
@@ -391,6 +388,17 @@ sync_response:
                goto auth_done;
 
            } /* if (passcode is valid) */
+
+           /* Get next challenge (extra work at end of loop; TODO: fix). */
+           if (user_info.cardops->challenge(&user_info,
+                                            1, 0, challenge) != 0) {
+               otp_log(OTP_LOG_ERR,
+                       "%s: unable to get sync challenge e:%d t:%d for [%s]",
+                       log_prefix, i, 0, username);
+               rc = OTP_RC_SERVICE_ERR;
+               goto auth_done_service_err;
+               /* NB: state not updated. */
+           }
        } /* for (each slot in the window) */
     } /* if (sync mode possible) */
 
@@ -400,64 +408,60 @@ sync_response:
 auth_done:
     if (rc == OTP_RC_OK) {
        if (resync) {
-           /*
-            * Resync the card.
-            *
-            * We "fail-out" if we can't do this, because for sync mode the
-            * response can be reused until sync data is updated, an obvious
-            * replay attack.
-            *
-            * For async mode with RADIUS, if we can't update the last auth
-            * time (a side effect of otp_set_sync_data()), we will be open
-            * to a less obvious replay attack over the lifetime of the State
-            * attribute (opt->chal_delay): if someone that can see RADIUS
-            * traffic captures an Access-Request containing a State
-            * attribute, and can cause the NAS to cycle the request id
-            * within opt->chal_delay secs, then they can login to the NAS
-            * and insert the captured State attribute into the new
-            * Access-Request, and we'll give an Access-Accept.
-            */
-           if (user_info.cardops->challenge(opt->syncdir, &user_info,
+           /* Resync the card. */
+           if (user_info.cardops->challenge(&user_info,
                                             1, 0, challenge) != 0) {
                otp_log(OTP_LOG_ERR, "%s: unable to get sync challenge "
                        "e:%d t:%d for [%s] (for resync)",
                        log_prefix, 1, 0, username);
                rc = OTP_RC_SERVICE_ERR;
-           } else if (otp_set_sync_data(opt->syncdir, username, challenge,
-                                        user_info.keyblock) != 0) {
-               otp_log(OTP_LOG_ERR,
-                       "%s: unable to set sync data for [%s] (for resync)",
-                       log_prefix, username);
-               rc = OTP_RC_SERVICE_ERR;
-           }
-       } else {
-           /* Just update failcount, last_auth_time, auth_pos. */
-           if (otp_reset_failcount(opt->syncdir, username) != 0) {
-               otp_log(OTP_LOG_ERR,
-                       "%s: unable to reset failcount for [%s]",
-                       log_prefix, username);
-               rc = OTP_RC_SERVICE_ERR;
+               goto auth_done_service_err;
+               /* NB: state not updated. */
            }
+           (void) strcpy(user_state.challenge, challenge);
        }
+       user_state.failcount = 0;
+       user_state.authtime  = time(NULL);
+       user_state.authpos   = 0;
+       user_state.updated   = 1;
     } else {
-       if (otp_incr_failcount(opt->syncdir, username) != 0) {
-           otp_log(OTP_LOG_ERR,
-                   "%s: unable to increment failure count for user [%s]",
-                   log_prefix, username);
-           rc = OTP_RC_SERVICE_ERR;
-       }
-       if (otp_set_last_auth_pos(opt->syncdir, username, auth_pos)) {
-           otp_log(OTP_LOG_ERR,
-                   "%s: unable to set auth window position for user [%s]",
-                   log_prefix, username);
-           rc = OTP_RC_SERVICE_ERR;
-       }
        /*
-        * TODO: consolidate reset_failcount, incr_failcount, s_l_a_p
-        * into set_sync_data with longterm lock.
+        * Note that we initialized authpos to -2 to accomodate ewindow2 test
+        * (i == user_state.authpos + 1) above; if we'd only set it to -1,
+        * after a failure authpos+1 == 0 and user can login with only one
+        * correct passcode (viz. the zeroeth passcode).
         */
+       user_state.authpos = authpos;
+       if (++user_state.failcount == UINT_MAX)
+           user_state.failcount--;
+       user_state.updated = 1;
     }
 
 auth_done_service_err: /* exit here for system errors */
+    /*
+     * Release and update state.
+     *
+     * We "fail-out" if we can't do this, because for sync mode the
+     * response can be reused until state data is updated, an obvious
+     * replay attack.
+     *
+     * For async mode with RADIUS, if we can't update the last auth
+     * time, we will be open to a less obvious replay attack over the
+     * lifetime of the State attribute (opt->chal_delay): if someone
+     * that can see RADIUS traffic captures an Access-Request containing
+     * a State attribute, and can cause the NAS to cycle the request id
+     * within opt->chal_delay secs, then they can login to the NAS and
+     * insert the captured State attribute into the new Access-Request,
+     * and we'll give an Access-Accept.
+     */
+    if (user_state.locked) {
+       if (otp_state_put(username, &user_state) != 0) {
+           otp_log(OTP_LOG_ERR,
+                   "%s: unable to put state for [%s]",
+                   log_prefix, username);
+           rc = OTP_RC_SERVICE_ERR;    /* no matter what it might have been */
+       }
+    }
+
     return rc;
 }
index f0067c2..ac947f2 100644 (file)
@@ -49,8 +49,8 @@ typedef struct cardops_t {
 
     int (*name2fm)(const char *name, uint32_t *featuremask);
     int (*keystring2keyblock)(const char *keystring, unsigned char keyblock[]);
-    int (*challenge)(const char *syncdir, otp_user_info_t *user_info,
-                    int ewin, int twin, char challenge[]);
+    int (*challenge)(const otp_user_info_t *user_info,
+                    unsigned int ewin, int twin, char challenge[]);
     int (*response)(otp_user_info_t *user_info, const char *challenge,
                    char response[OTP_MAX_RESPONSE_LEN + 1]);
 } cardops_t;
index d67d9a3..e043e21 100644 (file)
@@ -62,8 +62,8 @@ static int ninstance = 0;             /* #instances, for global init    */
 static const CONF_PARSER module_config[] = {
     { "pwdfile", PW_TYPE_STRING_PTR, offsetof(otp_option_t, pwdfile),
       NULL, OTP_PWDFILE },
-    { "syncdir", PW_TYPE_STRING_PTR, offsetof(otp_option_t, syncdir),
-      NULL, OTP_SYNCDIR },
+    { "lsmd_rp", PW_TYPE_STRING_PTR, offsetof(otp_option_t, lsmd_rp),
+      NULL, OTP_LSMD_RP },
     { "challenge_prompt", PW_TYPE_STRING_PTR,offsetof(otp_option_t,chal_prompt),
       NULL, OTP_CHALLENGE_PROMPT },
     { "challenge_length", PW_TYPE_INTEGER, offsetof(otp_option_t, chal_len),
@@ -133,7 +133,6 @@ otp_instantiate(CONF_SECTION *conf, void **instance)
 {
     otp_option_t *opt;
     char *p;
-    struct stat st;
 
     /* Set up a storage area for instance data. */
     opt = rad_malloc(sizeof(*opt));
@@ -267,18 +266,6 @@ otp_instantiate(CONF_SECTION *conf, void **instance)
     }
 #endif
 
-    if (stat(opt->syncdir, &st) != 0) {
-       otp_log(OTP_LOG_ERR, "syncdir %s error: %s",
-               opt->syncdir, strerror(errno));
-       free(opt);
-       return -1;
-    }
-    if (st.st_mode != (S_IFDIR|S_IRWXU)) {
-       otp_log(OTP_LOG_ERR, "syncdir %s has loose permissions", opt->syncdir);
-       free(opt);
-       return -1;
-    }
-
     /* Set the instance name (for use with authorize()) */
     opt->name = cf_section_name2(conf);
     if (!opt->name)
@@ -318,7 +305,7 @@ otp_authorize(void *instance, REQUEST *request)
        auth_type_found = 0;
        if ((vp = pairfind(request->config_items, PW_AUTHTYPE)) != NULL) {
            auth_type_found = 1;
-           if (strcmp(vp->vp_strvalue, inst->name)) {
+           if (strcmp(vp->strvalue, inst->name)) {
                return RLM_MODULE_NOOP;
            }
        }
@@ -458,7 +445,7 @@ otp_authenticate(void *instance, REQUEST *request)
                "auth: Attribute \"User-Name\" required for authentication.");
        return RLM_MODULE_INVALID;
     }
-    username = request->username->vp_strvalue;
+    username = request->username->strvalue;
 
     if ((data.pwattr = otp_pwe_present(request)) == 0) {
        otp_log(OTP_LOG_AUTH, "auth: Attribute \"User-Password\" "
@@ -496,15 +483,15 @@ otp_authenticate(void *instance, REQUEST *request)
            if (inst->allow_async) {
                /* Verify the state. */
                (void) memset(challenge, 0, sizeof(challenge));
-               (void) memcpy(challenge, vp->vp_strvalue, inst->chal_len);
-               (void) memcpy(&sflags, vp->vp_strvalue + inst->chal_len, 4);
-               (void) memcpy(&then, vp->vp_strvalue + inst->chal_len + 4, 4);
+               (void) memcpy(challenge, vp->strvalue, inst->chal_len);
+               (void) memcpy(&sflags, vp->strvalue + inst->chal_len, 4);
+               (void) memcpy(&then, vp->strvalue + inst->chal_len + 4, 4);
                if (otp_gen_state(NULL, &state, challenge,
                                  sflags, then, hmac_key) != 0) {
                    otp_log(OTP_LOG_ERR, "auth: failed to generate state");
                    return RLM_MODULE_FAIL;
                }
-               if (memcmp(state, vp->vp_strvalue, vp->length)) {
+               if (memcmp(state, vp->strvalue, vp->length)) {
                    otp_log(OTP_LOG_AUTH,
                            "auth: bad state for [%s]: hmac", username);
                    free(state);
@@ -572,7 +559,6 @@ module_t rlm_otp = {
        "otp",
        RLM_TYPE_THREAD_SAFE,           /* type */
        otp_instantiate,                /* instantiation */
-       otp_detach,                     /* detach */
        {
                otp_authenticate,       /* authentication */
                otp_authorize,          /* authorization */
@@ -583,4 +569,5 @@ module_t rlm_otp = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
+       otp_detach,                     /* detach */
 };
diff --git a/src/modules/rlm_otp/otp_sync.c b/src/modules/rlm_otp/otp_sync.c
deleted file mode 100644 (file)
index 47beaa8..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * otp_sync.c
- * $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001,2002  Google, Inc.
- * Copyright 2005 Frank Cusack
- */
-
-#include "otp.h"
-#include "otp_sync.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <openssl/des.h> /* des_cblock */
-
-static const char rcsid[] = "$Id$";
-
-
-/*
- * Sync data fields changed slightly between v1 and v2, and were renamed.
- * These routines, however, retain the v1 names.  The name:field mapping is:
- *       *_last_auth: last_auth_t      last authentication time
- *       *_failcount: last_auth_s      number of consecutive auth failures
- *   *_last_auth_pos: last_auth_p      window pos. of last auth (not in v1)
- */
-
-
-/* Get stored sync challenge for a given user.
- * Returns 0 on success, non-zero otherwise.
- */
-int
-otp_get_sync_challenge(const char *syncdir, const char *username,
-                      char challenge[OTP_MAX_CHALLENGE_LEN + 1])
-{
-    int rc;
-    char *lock;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-    rc = otp_get_sd(syncdir, username, challenge, NULL, NULL, NULL);
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * Set sync data for a given user.
- * Returns 0 on success, non-zero otherwise.
- * Side effects:
- * - Resets failure count to 0 on successful return.
- * - Sets last auth time to "now" on successful return.
- * - Sets last auth window position to 0.
- * Because of the failure count reset, this should only be called for/after
- * successful authentications.
- *
- * username:  duh
- * challenge: The challenge to be stored.
- * keyblock:  The key to be stored.  This is for sync modes in which the
- *            key changes for successive challenges. (NOT IMPLEMENTED)
- */
-int
-otp_set_sync_data(const char *syncdir, const char *username,
-                 const char *challenge,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                  const des_cblock keyblock)
-{
-    int rc;
-    char *lock;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    rc = otp_set_sd(syncdir, username, challenge, 0, time(NULL), 0);
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * Return the last time the user authenticated.
- * Returns 0 on success, non-zero otherwise.
- */
-int
-otp_get_last_auth(const char *syncdir, const char *username, time_t *last_auth)
-{
-    int rc;
-    char *lock;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-    rc = otp_get_sd(syncdir, username, NULL, NULL, last_auth, NULL);
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-/*
- * Set the last auth time for a user to "now".
- * Returns 0 on success, non-zero otherwise.
- * Note that otp_set_sync_data() also resets the auth time.
- * This function is no longer called, (the failcount() routines do this work),
- * but I'm saving it here for reference.
- */
-int
-otp_upd_last_auth(const char *syncdir, const char *username)
-{
-    int failcount, rc;
-    char *lock;
-    char challenge[OTP_MAX_CHALLENGE_LEN + 1];
-    unsigned pos;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    rc = otp_get_sd(syncdir, username, challenge, &failcount, NULL, &pos);
-    if (rc == 0)
-       rc = otp_set_sd(syncdir, username, challenge, failcount, time(NULL),
-                       pos);
-
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * Atomically increment a user's failed login count.
- * Also updates last_auth.
- */
-int
-otp_incr_failcount(const char *syncdir, const char *username)
-{
-    int failcount, rc;
-    char *lock;
-    char challenge[OTP_MAX_CHALLENGE_LEN + 1];
-    unsigned pos;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    /* Get current value. */
-    rc = otp_get_sd(syncdir, username, challenge, &failcount, NULL, &pos);
-    if (rc == 0) {
-       /* Increment. */
-       if (++failcount == INT_MAX)
-           failcount--;
-       rc = otp_set_sd(syncdir, username, challenge, failcount, time(NULL),
-                       pos);
-    }
-
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-/*
- * Reset failure count to 0.  Also updates last_auth and resets pos.
- * Returns 0 on success, non-zero otherwise.
- * This is almost just like otp_incr_failcount().
- * otp_set_sync_data() resets the failcount also, but that's because
- * we keep the failcount and other sync data together; we don't want
- * to necessarily make that visible to our callers (otp_cardops.c).
- */
-int
-otp_reset_failcount(const char *syncdir, const char *username)
-{
-    int rc;
-    char *lock;
-    char challenge[OTP_MAX_CHALLENGE_LEN + 1];
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    rc = otp_get_sd(syncdir, username, challenge, NULL, NULL, NULL);
-    if (rc == 0)
-       rc = otp_set_sd(syncdir, username, challenge, 0, time(NULL), 0);
-
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * checks the failure counter.
- * returns 0 if the user is allowed to authenticate, < 0 otherwise:
- *   OTP_FC_FAIL_ERR if the user is failed due to internal error,
- *   OTP_FC_FAIL_HARD if the user is failed "hard",
- *   OTP_FC_FAIL_SOFT if the user is failed "soft".
- * caller does not need to log failures, we do it (in order to be specific).
- */
-int
-otp_check_failcount(const char *username, const otp_option_t *inst)
-{
-    time_t last_auth;
-    int failcount;
-
-    if (otp_get_last_auth(inst->syncdir, username, &last_auth) != 0) {
-       otp_log(OTP_LOG_ERR,
-               "auth: unable to get last auth time for [%s]", username);
-       return OTP_FC_FAIL_ERR;
-    }
-    if (otp_get_failcount(inst->syncdir, username, &failcount) != 0) {
-       otp_log(OTP_LOG_ERR,
-               "auth: unable to get failure count for [%s]", username);
-       return OTP_FC_FAIL_ERR;
-    }
-
-    /* Check against hardfail setting. */
-    if (inst->hardfail && failcount >= inst->hardfail) {
-       otp_log(OTP_LOG_AUTH,
-               "auth: %d/%d failed/max authentications for [%s]",
-               failcount, inst->hardfail, username);
-       if (otp_incr_failcount(inst->syncdir, username) != 0) {
-           otp_log(OTP_LOG_ERR,
-                   "auth: unable to increment failure count for "
-                   "locked out user [%s]", username);
-       }
-       return OTP_FC_FAIL_HARD;
-    }
-
-    /* Check against softfail setting. */
-    if (inst->softfail && failcount >= inst->softfail) {
-       time_t when;
-       int fcount;
-
-       /*
-        * Determine the next time this user can authenticate.
-        *
-        * Once we hit softfail, we introduce a 1m delay before the user
-        * can authenticate.  For each successive failed authentication,
-        * we double the delay time, up to a max of 32 minutes.  While in
-        * the "delay mode" of operation, all authentication ATTEMPTS are
-        * considered failures (we don't test if the password is correct).
-        * Also, each attempt during the delay period restarts the clock.
-        *
-        * The advantage of a delay instead of a simple lockout is that an
-        * attacker can't lock out a user as easily; the user need only wait
-        * a bit before he can authenticate.
-        */
-       fcount = failcount - inst->softfail;
-       when = last_auth + (fcount > 5 ? 32 * 60 : (1 << fcount) * 60);
-       if (time(NULL) < when) {
-           otp_log(OTP_LOG_AUTH,
-                   "auth: user [%s] auth too soon while delayed, "
-                   "%d/%d failed/softfail authentications",
-                   username, failcount, inst->softfail);
-           if (otp_incr_failcount(inst->syncdir, username) != 0) {
-               otp_log(OTP_LOG_ERR,
-                       "auth: unable to increment failure count for "
-                       "delayed user [%s]", username);
-           }
-           return OTP_FC_FAIL_SOFT;
-       }
-    }
-
-    return 0;
-}
-
-/*
- * Get the last auth window position for ewindow2.
- * Returns 0 on failure (caller cannot distinguish between failure and
- * a 0 position).
- */
-unsigned
-otp_get_last_auth_pos(const char *syncdir, const char *username)
-{
-    int rc;
-    char *lock;
-    char challenge[OTP_MAX_CHALLENGE_LEN + 1];
-    unsigned pos;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    rc = otp_get_sd(syncdir, username, challenge, NULL, NULL, &pos);
-
-    otp_release_sd_lock(lock);
-    return rc ? 0 : pos;
-}
-
-/*
- * Record the last auth window position (for ewindow2).
- */
-int
-otp_set_last_auth_pos(const char *syncdir, const char *username, unsigned pos)
-{
-    int rc;
-    char *lock;
-    char challenge[OTP_MAX_CHALLENGE_LEN + 1];
-    int failcount;
-    time_t last_auth;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-
-    rc = otp_get_sd(syncdir, username, challenge, &failcount, &last_auth, NULL);
-    if (rc == 0)
-       rc = otp_set_sd(syncdir, username, challenge, failcount, last_auth,
-                       pos);
-
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * Return the failed login count for a user.
- * Returns 0 on success, non-zero otherwise.
- */
-static int
-otp_get_failcount(const char *syncdir, const char *username, int *failcount)
-{
-    int rc;
-    char *lock;
-
-    if ((lock = otp_acquire_sd_lock(syncdir, username)) == NULL)
-       return -1;
-    rc = otp_get_sd(syncdir, username, NULL, failcount, NULL, NULL);
-    otp_release_sd_lock(lock);
-    return rc;
-}
-
-
-/*
- * Sync data is kept in a flat file[s], only because it's easy to implement.
- * It might be worth looking at Berkeley DB, but the flat file implementation
- * gives maximal concurrency with minimal complexity.  Performance will be
- * better on filesystems like ext2fs, ffs w/ soft updates, etc, due to
- * the large number of ephemeral dot-files created/destroyed for locking.
- *
- * One file per user is created, and we typically expect that each thread
- * is handling a different user (even if a user is authenticating to
- * multiple NASs/ports, he can't really authenticate simultaneously to
- * each -- unless it's an attack), so this should give us maximal
- * concurrency.
- *
- * The file format is 'version:user:challenge:key:failures:last_auth:'.
- * Version is there to provide easy forward compatibility.  The trailing
- * colon is there for the same reason.  Future versions must add data to
- * the end.  The current version is 1.
- *
- * For performance enhancements, it might be more worthwhile to look at
- * caching the inst->pwdfile data.  Users who are disabled should also
- * be cached somehow, to reduce the impact of possible attacks.
- */
-
-
-/*
- * otp_acquire_sd_lock() returns NULL on failure, or a char *
- * which must be passed to otp_release_sd_lock() later.
- */
-static char *
-otp_acquire_sd_lock(const char *syncdir, const char *username)
-{
-    char *lockfile;
-    int i, fd = -1;
-    struct stat st;
-
-    /* Verify permissions first. */
-    if (stat(syncdir, &st) != 0) {
-       otp_log(OTP_LOG_ERR, "otp_acquire_sd_lock: syncdir %s error: %s",
-               syncdir, strerror(errno));
-       return NULL;
-    }
-    if (st.st_mode != (S_IFDIR|S_IRUSR|S_IWUSR|S_IXUSR)) {
-       otp_log(OTP_LOG_ERR,
-               "otp_acquire_sd_lock: syncdir %s has loose permissions",
-               syncdir);
-       return NULL;
-    }
-
-    /* We use dotfile locking. */
-    lockfile = malloc(strlen(syncdir) + strlen(username) + 3);
-    if (!lockfile) {
-       otp_log(OTP_LOG_CRIT, "otp_acquire_sd_lock: out of memory");
-       return NULL;
-    }
-    (void) sprintf(lockfile, "%s/.%s", syncdir, username);
-
-    /*
-     * Try to obtain exclusive access.  10 should be *plenty* of
-     * iterations, we don't expect concurrent accesses to the same file,
-     * and any accesses should be very quick.  This is broken over NFS,
-     * but you shouldn't have this data on NFS anyway.
-     */
-    for (i = 0; i < 10; ++i) {
-       if ((fd = open(lockfile, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) != -1) {
-           break;
-       }
-       /* break stale locks (older than 60s) */
-       if (stat(lockfile, &st) == 0)
-           if (st.st_ctime  < time(NULL) - 60)
-               (void) unlink(lockfile);
-
-       usleep(500000); /* 0.5 second */
-    }
-    if (fd == -1) {
-       otp_log(OTP_LOG_ERR,
-               "otp_acquire_sd_lock: unable to acquire lock for [%s]",
-               username);
-       free(lockfile);
-       return NULL;
-    }
-
-    (void) close(fd);
-    return lockfile;
-}
-
-static void
-otp_release_sd_lock(char *lockfile)
-{
-    (void) unlink(lockfile);
-    free(lockfile);
-}
-
-
-/*
- * otp_get_sd() returns 0 on success, non-zero otherwise.
- * On successful returns, challenge, failures, last_auth, pos are filled in,
- * if non-NULL.
- * On unsuccessful returns, challenge, failures, last_auth, pos may be garbage.
- * challenge should be sized as indicated (if non-NULL).
- * The caller must have obtained an exclusive lock on the sync file.
- */
-static int
-otp_get_sd(const char *syncdir, const char *username,
-          char challenge[OTP_MAX_CHALLENGE_LEN + 1], int *failures,
-          time_t *last_auth, unsigned *pos)
-{
-    char syncfile[PATH_MAX + 1];
-    FILE *fp;
-
-    char syncdata[BUFSIZ];
-    char *p, *q;
-    unsigned ver = UINT_MAX;
-
-    (void) snprintf(syncfile, PATH_MAX, "%s/%s",  syncdir, username);
-    syncfile[PATH_MAX] = '\0';
-
-    /* Open sync file. */
-    if ((fp = fopen(syncfile, "r")) == NULL) {
-       if (errno != ENOENT) {
-           otp_log(OTP_LOG_ERR, "otp_get_sd: unable to open sync file %s: %s",
-                   syncfile, strerror(errno));
-           return -1;
-       }
-       /*
-        * Sync file did not exist.  If we can create it, all is well.
-        * Set the challenge to something "impossible".
-        */
-       if (failures)
-           *failures = 0;
-       return otp_set_sd(syncdir, username, "NEWSTATE", 0, 0, 0);
-    }
-
-    /* Read sync data. */
-    if ((fgets(syncdata, sizeof(syncdata), fp) == NULL) || !strlen(syncdata)) {
-       otp_log(OTP_LOG_ERR, "otp_get_sd: unable to read sync data from %s: %s",
-               syncfile, strerror(errno));
-       (void) fclose(fp);
-       return -1;
-    }
-    (void) fclose(fp);
-    p = syncdata;
-
-    /* Now, parse the sync data. */
-    /* Get the version. */
-    if ((q = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data for user %s", username);
-       return -1;
-    }
-    *q++ = '\0';
-    if ((sscanf(p, "%u", &ver) != 1) || (ver > 2)) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (version) for user %s",
-               username);
-       return -1;
-    }
-    p = q;
-
-    /* Sanity check the username. */
-    if ((q = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (username) for user %s",
-               username);
-       return -1;
-    }
-    *q++ = '\0';
-    if (strcmp(p, username)) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (user mismatch) for user %s",
-               username);
-       return -1;
-    }
-    p = q;
-
-    /* Get challenge. */
-    if ((q = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (challenge) for user %s",
-               username);
-       return -1;
-    }
-    *q++ = '\0';
-    if (strlen(p) > OTP_MAX_CHALLENGE_LEN) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (challenge length) for user %s",
-               username);
-       return -1;
-    }
-    if (challenge)
-       strcpy(challenge, p);
-    p = q;
-
-    /* Eat key. */
-    if ((p = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (key) for user %s", username);
-       return -1;
-    }
-    p++;
-
-    /* Get failures. */
-    if ((q = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (failures) for user %s",
-               username);
-       return -1;
-    }
-    *q++ = '\0';
-    if (failures && (sscanf(p, "%d", failures) != 1)) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (failures) for user %s",
-               username);
-       return -1;
-    }
-    p = q;
-
-    /* Get last_auth. */
-    if ((q = strchr(p, ':')) == NULL) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (last_auth) for user %s",
-               username);
-       return -1;
-    }
-    *q++ = '\0';
-    if (last_auth && (sscanf(p, "%ld", last_auth) != 1)) {
-       otp_log(OTP_LOG_ERR,
-               "otp_get_sd: invalid sync data (last_auth) for user %s",
-               username);
-       return -1;
-    }
-    p = q;
-
-    /* Get last auth position. */
-    if (pos) {
-       if (ver == 1) {
-           *pos = 0;
-       } else if (sscanf(p, "%u", pos) != 1) {
-           otp_log(OTP_LOG_ERR,
-                   "otp_get_sd: invalid sync data (win. pos) for user %s",
-                   username);
-           return -1;
-       }
-    }
-    return 0;
-}
-
-
-/*
- * See otp_get_sd().
- * The caller must have obtained an exclusive lock on the sync file.
- */
-static int
-otp_set_sd(const char *syncdir, const char *username, const char *challenge,
-          int failures, time_t last_auth, unsigned pos)
-{
-    char syncfile[PATH_MAX + 1];
-    FILE *fp;
-
-    (void) snprintf(syncfile, PATH_MAX, "%s/%s",  syncdir, username);
-    syncfile[PATH_MAX] = '\0';
-
-    if ((fp = fopen(syncfile, "w")) == NULL) {
-       otp_log(OTP_LOG_ERR, "otp_set_sd: unable to open sync file %s: %s",
-               syncfile, strerror(errno));
-       return -1;
-    }
-
-    /* Write our (version 2) sync data. */
-    (void) fprintf(fp, "2:%s:%s:%s:%d:%ld:%u:\n", username, challenge, "",
-                  failures, last_auth, pos);
-    if (fclose(fp) != 0) {
-       otp_log(OTP_LOG_ERR, "otp_set_sd: unable to write sync file %s: %s",
-               syncfile, strerror(errno));
-       return -1;
-    }
-
-    return 0;
-}
-
diff --git a/src/modules/rlm_otp/otp_sync.h b/src/modules/rlm_otp/otp_sync.h
deleted file mode 100644 (file)
index 5b75927..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * otp_sync.h
- * $Id$
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001,2002  Google, Inc.
- * Copyright 2005 Frank Cusack
- */
-
-#ifndef OTP_SYNC_H
-#define OTP_SYNC_H
-
-static int otp_get_failcount(const char *syncdir, const char *username,
-                            int *failcount);
-static char *otp_acquire_sd_lock(const char *syncdir, const char *username);
-static void otp_release_sd_lock(char *lockfile);
-
-static int otp_get_sd(const char *syncdir, const char *username,
-                     char challenge[OTP_MAX_CHALLENGE_LEN + 1], int *failures,
-                     time_t *last_async, unsigned *pos);
-static int otp_set_sd(const char *syncdir, const char *username,
-                     const char *challenge, int failures, time_t last_async,
-                     unsigned pos);
-
-#endif /* OTP_SYNC_H */
index 689eeec..03b63df 100644 (file)
@@ -45,7 +45,7 @@ static const char rcsid[] = "$Id$";
  */
 int
 otp_x99_mac(const unsigned char *input, size_t len, unsigned char output[8],
-           unsigned char keyblock[OTP_MAX_KEY_LEN])
+           const unsigned char keyblock[OTP_MAX_KEY_LEN])
 {
     des_key_schedule ks;
     des_cblock ivec;