static const char rcsid[] = "$Id$";
/* Global data */
-static unsigned char hmac_key[16]; /* to protect State attribute */
-static int ninstance = 0; /* #instances, for global init */
+static unsigned char hmac_key[16]; /* to protect State attribute */
+static int ninstance = 0; /* #instances, for global init */
/* A mapping of configuration file names to internal variables. */
static const CONF_PARSER module_config[] = {
{ "mschap_mppe_bits", PW_TYPE_INTEGER,
offsetof(otp_option_t, mschap_mppe_types), NULL, "2" },
+ { "site_transform", PW_TYPE_BOOLEAN, offsetof(otp_option_t, site_transform),
+ NULL, "yes" },
{ "debug", PW_TYPE_BOOLEAN, offsetof(otp_option_t, debug),
NULL, "no" },
}
} else {
state = rad_malloc(5);
- (void) sprintf(state, "0x00");
+ /* a non-NUL byte, so that Cisco (see otp_gen_state()) returns it */
+ (void) sprintf(state, "0x01");
}
pairadd(&request->reply->vps, pairmake("State", state, T_OP_EQ));
free(state);
{
VALUE_PAIR *vp;
unsigned char *state;
- int32_t sflags = 0; /* state flags */
- int32_t then; /* state timestamp */
+ unsigned char *raw_state;
+ unsigned char *rad_state;
+ int32_t sflags = 0; /* state flags */
+ int32_t then; /* state timestamp */
+ int e_length; /* expected State length */
if ((vp = pairfind(request->packet->vps, PW_STATE)) != NULL) {
- int e_length;
-
/* set expected State length */
if (inst->allow_async)
- e_length += inst->chal_len + 4 + 4 + 16; /* see otp_gen_state() */
+ e_length = inst->chal_len * 2 + 8 + 8 + 32; /* see otp_gen_state() */
else
e_length = 1;
}
if (inst->allow_async) {
- /* Verify the state. */
- (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);
+ /*
+ * Verify the state.
+ */
+
+ rad_state = rad_malloc(e_length + 1);
+ raw_state = rad_malloc(e_length / 2);
+
+ /* ASCII decode */
+ (void) memcpy(rad_state, vp->strvalue, vp->length);
+ rad_state[e_length] = '\0';
+ (void) otp_keystring2keyblock(rad_state, raw_state);
+ free(rad_state);
+
+ /* extract data from State */
+ (void) memcpy(challenge, raw_state, inst->chal_len);
+ (void) memcpy(&sflags, raw_state + inst->chal_len, 4);
+ (void) memcpy(&then, raw_state + inst->chal_len + 4, 4);
+ free(raw_state);
+
+ /* generate new state from returned input data */
if (otp_gen_state(NULL, &state, challenge, inst->chal_len,
sflags, then, hmac_key) != 0) {
otp_log(OTP_LOG_ERR, "%s: %s: failed to generate state",
log_prefix, __func__);
return RLM_MODULE_FAIL;
}
+ /* compare generated state against returned state to verify hmac */
if (memcmp(state, vp->strvalue, vp->length)) {
otp_log(OTP_LOG_AUTH, "%s: %s: bad state for [%s]: hmac",
log_prefix, __func__, username);