Update the GPL boilerplate with the new address of the FSF.
[freeradius.git] / src / modules / rlm_otp / cardops / cryptocard.c
index 82227d1..cf85fff 100644 (file)
@@ -14,9 +14,9 @@
  *
  *   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
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2005 TRI-D Systems, Inc.
+ * Copyright 2005,2006 TRI-D Systems, Inc.
  */
 
 #include <inttypes.h>
@@ -36,14 +36,20 @@ static struct {
   { "cryptocard-d8-rc", CRYPTOCARD_D8_RC },
   { "cryptocard-h7-rc", CRYPTOCARD_H7_RC },
   { "cryptocard-d7-rc", CRYPTOCARD_D7_RC },
+  { "cryptocard-hp-rc", CRYPTOCARD_HP_RC },
+  { "cryptocard-dp-rc", CRYPTOCARD_DP_RC },
   { "cryptocard-h8-es", CRYPTOCARD_H8_ES },
   { "cryptocard-d8-es", CRYPTOCARD_D8_ES },
   { "cryptocard-h7-es", CRYPTOCARD_H7_ES },
   { "cryptocard-d7-es", CRYPTOCARD_D7_ES },
+  { "cryptocard-hp-es", CRYPTOCARD_HP_ES },
+  { "cryptocard-dp-es", CRYPTOCARD_DP_ES },
   { "cryptocard-h8-rs", CRYPTOCARD_H8_RS },
   { "cryptocard-d8-rs", CRYPTOCARD_D8_RS },
   { "cryptocard-h7-rs", CRYPTOCARD_H7_RS },
   { "cryptocard-d7-rs", CRYPTOCARD_D7_RS },
+  { "cryptocard-hp-rs", CRYPTOCARD_HP_RS },
+  { "cryptocard-dp-rs", CRYPTOCARD_DP_RS },
 
   { NULL, 0 }                                  /* end of list */
 };
@@ -70,7 +76,7 @@ cryptocard_name2fm(const char *name, uint32_t *featuremask)
 
 /*
  * Convert an ASCII keystring to a keyblock.
- * Returns 0 on success, non-zero otherwise.
+ * Returns keylen on success, -1 otherwise.
  */
 static int
 cryptocard_keystring2keyblock(const char *keystring,
@@ -97,7 +103,7 @@ __attribute__ ((unused))
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                      const otp_user_info_t *user_info,
+                      const otp_card_info_t *card_info,
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
@@ -108,46 +114,41 @@ __attribute__ ((unused))
                       time_t when,
                       const char *log_prefix)
 {
-  otp_log(OTP_LOG_ERR, "%s: null state not supported for CRYPTOCard",
-          log_prefix);
+  otp_log(OTP_LOG_ERR, "%s: %s: null state not supported for CRYPTOCard",
+          log_prefix, __func__);
   return -1;
 }
 
 
 /*
  * Return a synchronous challenge.
- * Returns 0 on success, non-zero otherwise.
+ * Returns 0 on success, -1 otherwise.
+ * (-2 rc is for early challenge, N/A for cryptocard.)
  */
 static int
-cryptocard_challenge(const otp_user_info_t *user_info,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                     const char csd[OTP_MAX_CSD_LEN + 1],
+cryptocard_challenge(const otp_card_info_t *card_info,
+                     otp_user_state_t *user_state,
+                     unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
                      time_t when,
-                     char challenge[OTP_MAX_CHALLENGE_LEN + 1],
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                     unsigned ewin,
+                     int twin,
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                     unsigned twin,
+                     int ewin,
                      const char *log_prefix)
 {
   unsigned char output[8];
   int i;
 
-  /* CRYPTOCard sync challenges are always 8 bytes. */
-  if (strlen(challenge) != 8)
-    return -1;
-
-  /* run x99 once on the challenge */
-  if (otp_x99_mac(challenge, 8, output, user_info->keyblock, log_prefix))
+  /* run x99 once on the previous challenge */
+  if (otp_x99_mac(challenge, user_state->clen, output, card_info->keyblock,
+                  log_prefix))
     return -1;
 
   /* convert the mac into the next challenge */
@@ -158,7 +159,7 @@ __attribute__ ((unused))
     output[i] |= 0x30;
   }
   (void) memcpy(challenge, output, 8);
-  challenge[8] = '\0';
+  user_state->clen = 8;
 
   return 0;
 }
@@ -182,62 +183,44 @@ __attribute__ ((unused))
  * 5. Truncate the response for 7 digit display modes.
  */
 static int
-cryptocard_response(otp_user_info_t *user_info,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                    char *csd,
-                    const char *challenge,
-                    char response[OTP_MAX_RESPONSE_LEN + 1],
+cryptocard_response(otp_card_info_t *card_info,
+                    const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
+                    size_t len, char response[OTP_MAX_RESPONSE_LEN + 1],
                     const char *log_prefix)
 {
   unsigned char output[8];
-  char l_response[17];
   const char *conversion;
 
   /* Step 1, 2. */
-  if (otp_x99_mac(challenge, strlen(challenge), output,
-                  user_info->keyblock, log_prefix) !=0)
+  if (otp_x99_mac(challenge, len, output,
+                  card_info->keyblock, log_prefix) !=0)
     return 1;
 
   /* Setup for step 4. */
-  if (user_info->featuremask & OTP_CF_DD)
+  if (card_info->featuremask & OTP_CF_DD)
     conversion = otp_cc_dec_conversion;
   else
     conversion = otp_hex_conversion;
 
   /* Step 3, 4. */
-  otp_keyblock2keystring(l_response, output, conversion);
-  (void) memcpy(response, l_response, 8);
-  response[8] = '\0';
+  (void) otp_keyblock2keystring(response, output, 4, conversion);
 
   /* Step 5. */
-  if (user_info->featuremask & OTP_CF_R7)
+  if (card_info->featuremask & OTP_CF_R7)
     (void) memmove(&response[3], &response[4], 5);
+  else if (card_info->featuremask & OTP_CF_RP)
+    response[3] = '-';
 
   return 0;
 }
 
 
-/* no csd so just return success */
+/*
+ * Update rd (there is no csd for cryptocard).
+ * Returns 0 if succesful, -1 otherwise.
+ */
 static int
-cryptocard_updatecsd(
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                     const otp_user_info_t *user_info,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                     otp_user_state_t *user_state,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                     const char challenge[OTP_MAX_CHALLENGE_LEN + 1],
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                     unsigned twin,
+cryptocard_updatecsd(otp_user_state_t *user_state,
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
@@ -245,59 +228,79 @@ __attribute__ ((unused))
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                     const char *log_prefix)
+                     int twin,
+                     int ewin,
+                     int auth_rc)
 {
+  if (auth_rc == OTP_RC_OK)
+    user_state->rd[0] = '\0';                          /* reset */
+  else
+    (void) sprintf(user_state->rd, "%" PRIx32,
+                   (int32_t) ewin);                    /* rwindow candidate */
+
   return 0;
 }
 
-/* no twin so just return 0 */
+
+/*
+ * Determine if a window position if consecutive relative to a saved
+ * (rwindow candidate) window position, for rwindow override.
+ * user_state contains the previous auth position, twin and ewin the current.
+ * Returns 1 on success (consecutive), 0 otherwise.
+ */
 static int
-cryptocard_nexttwin(
+cryptocard_isconsecutive(
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                    int twin)
+                         const otp_card_info_t *card_info,
+                         const otp_user_state_t *user_state,
+                         int thisewin, const char *log_prefix)
 {
-  return 0;
+  int nextewin;
+
+  /* extract the saved rwindow candidate position */
+  if (sscanf(user_state->rd, "%" SCNx32, &nextewin) != 1) {
+    otp_log(OTP_LOG_ERR, "%s: %s: invalid rwindow data for [%s]",
+            log_prefix, __func__, card_info->username);
+    return 0;
+  }
+  nextewin++;
+
+  /* Is this the next passcode? */
+  if (thisewin == nextewin)
+    return 1;  /* yes */
+  else
+    return 0;  /* no */
 }
 
+
 /* no twin so just return 0 */
 static int
 cryptocard_maxtwin(
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                    const otp_user_info_t *user_info,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                    const char csd[OTP_MAX_CSD_LEN + 1],
+                    const otp_card_info_t *card_info,
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-                    time_t when)
+                    const char csd[OTP_MAX_CSD_LEN + 1])
 {
   return 0;
 }
 
-/* no twin so just return current time */
-static time_t
-cryptocard_twin2authtime(
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                         const char csd[OTP_MAX_CSD_LEN + 1],
-                         time_t when,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                         int twin,
-#ifdef __GNUC__
-__attribute__ ((unused))
-#endif
-                         const char *log_prefix)
+
+/* return human-readable challenge */
+static char *
+cryptocard_printchallenge(char s[OTP_MAX_CHALLENGE_LEN * 2 + 1],
+                          const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
+                          size_t len)
 {
-  return when;
+  /* cryptocard challenge is implicitly ASCII */
+  (void) memcpy(s, challenge, len);
+  s[len] = '\0';
+  return s;
 }
 
 
@@ -312,11 +315,12 @@ static cardops_t cryptocard_cardops = {
   .challenge           = cryptocard_challenge,
   .response            = cryptocard_response,
   .updatecsd           = cryptocard_updatecsd,
-  .nexttwin            = cryptocard_nexttwin,
+  .isconsecutive       = cryptocard_isconsecutive,
   .maxtwin             = cryptocard_maxtwin,
-  .twin2authtime       = cryptocard_twin2authtime
+  .printchallenge      = cryptocard_printchallenge,
 };
 
+
 /* constructor */
 void
 cryptocard_init(void)