Change OTPSyncRequest structure to use OctetString

This change has two motivations:
  1. Clients don't have to parse the string.
  2. Future token types may have new formats.

Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Nathaniel McCallum
2014-05-23 13:01:59 -04:00
committed by Martin Kosek
parent 6af1fc4763
commit 7b15fcd57b
5 changed files with 78 additions and 55 deletions

View File

@@ -1157,8 +1157,8 @@ static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
/* Loop through each token. */
for (int i = 0; tokens[i] && !success; i++) {
/* Attempt authentication. */
success = otptoken_validate_string(tokens[i], OTP_VALIDATE_STEPS,
creds->bv_val, creds->bv_len, true);
success = otptoken_validate_berval(tokens[i], OTP_VALIDATE_STEPS,
creds, true);
/* Truncate the password to remove the OTP code at the end. */
if (success) {

View File

@@ -58,10 +58,11 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
{
struct otptoken **tokens = NULL;
LDAPControl **controls = NULL;
struct berval *second = NULL;
struct berval *first = NULL;
BerElement *ber = NULL;
char *token_dn = NULL;
int second = 0;
int first = 0;
bool success;
if (slapi_pblock_get(pb, SLAPI_REQCONTROLS, &controls) != 0)
return false;
@@ -79,32 +80,30 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
return false;
/* Decode the token codes. */
if (ber_scanf(ber, "{ii", &first, &second) == LBER_ERROR) {
if (ber_scanf(ber, "{OO", &first, &second) == LBER_ERROR) {
ber_free(ber, 1);
return false;
}
/* Decode the optional token DN. */
ber_scanf(ber, "a", &token_dn);
if (ber_scanf(ber, "}") == LBER_ERROR) {
ber_free(ber, 1);
return false;
/* Process the synchronization. */
success = false;
if (ber_scanf(ber, "}") != LBER_ERROR) {
tokens = otptoken_find(plugin_id, user_dn, token_dn, true, NULL);
if (tokens != NULL) {
success = otptoken_sync_berval(tokens, OTP_SYNC_MAX_STEPS, first, second);
otptoken_free_array(tokens);
}
}
ber_memfree(token_dn); token_dn = NULL;
ber_bvfree(second);
ber_bvfree(first);
ber_free(ber, 1);
/* Find all the tokens. */
tokens = otptoken_find(plugin_id, user_dn, token_dn, true, NULL);
ber_memfree(token_dn);
if (tokens == NULL)
if (!success)
return false;
/* Synchronize the token. */
if (!otptoken_sync(tokens, OTP_SYNC_MAX_STEPS, first, second)) {
otptoken_free_array(tokens);
return false;
}
otptoken_free_array(tokens);
}
return true;

View File

@@ -48,8 +48,8 @@
* The ASN.1 encoding of the request structure:
*
* OTPSyncRequest ::= SEQUENCE {
* firstCode INTEGER,
* secondCode INTEGER,
* firstCode OCTET STRING,
* secondCode OCTET STRING,
* tokenDN OCTET STRING OPTIONAL
* }
*/

View File

@@ -449,7 +449,8 @@ const Slapi_DN *otptoken_get_sdn(struct otptoken *token)
return token->sdn;
}
bool otptoken_validate(struct otptoken *token, size_t steps, uint32_t code)
static bool otptoken_validate(struct otptoken *token, size_t steps,
uint32_t code)
{
time_t now = 0;
@@ -477,44 +478,53 @@ bool otptoken_validate(struct otptoken *token, size_t steps, uint32_t code)
return false;
}
bool otptoken_validate_string(struct otptoken *token, size_t steps,
const char *code, ssize_t len, bool tail)
/*
* Convert code berval to decimal.
*
* NOTE: We can't use atol() or strtoul() because:
* 1. If we have leading zeros, atol() fails.
* 2. Neither support limiting conversion by length.
*/
static bool bvtod(const struct berval *code, uint32_t *out)
{
*out = 0;
for (ber_len_t i = 0; i < code->bv_len; i++) {
if (code->bv_val[i] < '0' || code->bv_val[i] > '9')
return false;
*out *= 10;
*out += code->bv_val[i] - '0';
}
return code->bv_len != 0;
}
bool otptoken_validate_berval(struct otptoken *token, size_t steps,
const struct berval *code, bool tail)
{
struct berval tmp;
uint32_t otp;
if (token == NULL || code == NULL)
return false;
tmp = *code;
if (len < 0)
len = strlen(code);
if (len < token->token.digits)
if (tmp.bv_len < token->token.digits)
return false;
if (tail)
code = &code[len - token->token.digits];
len = token->token.digits;
tmp.bv_val = &tmp.bv_val[tmp.bv_len - token->token.digits];
tmp.bv_len = token->token.digits;
/*
* Convert code string to decimal.
*
* NOTE: We can't use atol() or strtoul() because:
* 1. We may have leading zeros (atol() fails here).
* 2. Neither support limiting conversion by length.
*/
otp = 0;
for (ssize_t i = 0; i < len; i++) {
if (code[i] < '0' || code[i] > '9')
return false;
otp *= 10;
otp += code[i] - '0';
}
if (!bvtod(&tmp, &otp))
return false;
return otptoken_validate(token, steps, otp);
}
bool otptoken_sync(struct otptoken * const *tokens, size_t steps,
uint32_t first_code, uint32_t second_code)
static bool otptoken_sync(struct otptoken * const *tokens, size_t steps,
uint32_t first_code, uint32_t second_code)
{
time_t now = 0;
@@ -542,3 +552,19 @@ bool otptoken_sync(struct otptoken * const *tokens, size_t steps,
return false;
}
bool otptoken_sync_berval(struct otptoken * const *tokens, size_t steps,
const struct berval *first_code,
const struct berval *second_code)
{
uint32_t second = 0;
uint32_t first = 0;
if (!bvtod(first_code, &first))
return false;
if (!bvtod(second_code, &second))
return false;
return otptoken_sync(tokens, steps, first, second);
}

View File

@@ -80,16 +80,14 @@ int otptoken_get_digits(struct otptoken *token);
/* Get the SDN of the token. */
const Slapi_DN *otptoken_get_sdn(struct otptoken *token);
/* Validate the token code within a range of steps. */
bool otptoken_validate(struct otptoken *token, size_t steps, uint32_t code);
/* Validate the token code within a range of steps. If tail is true,
* it will be assumed that the token is specified at the end of the string. */
bool otptoken_validate_string(struct otptoken *token, size_t steps,
const char *code, ssize_t len, bool tail);
bool otptoken_validate_berval(struct otptoken *token, size_t steps,
const struct berval *code, bool tail);
/* Synchronize the token within a range of steps. */
bool otptoken_sync(struct otptoken * const *tokens, size_t steps,
uint32_t first_code, uint32_t second_code);
bool otptoken_sync_berval(struct otptoken * const *tokens, size_t steps,
const struct berval *first_code,
const struct berval *second_code);
#endif /* LIBOTP_H_ */