mirror of
https://github.com/cryb-to/cryb-to.git
synced 2024-12-22 04:21:08 +00:00
All property names and values may be percent-encoded.
If the key length is not a multiple of 40 bits, its base32 representation may be padded, and that padding will be encoded. We already decoded the label (which may contain spaces and other unsafe characters), but not the key. For the sake of simplicity and robustness, we now decode the name and value of every property. This corresponds to OpenPAM r886.
This commit is contained in:
parent
d419d7388a
commit
d017611d76
2 changed files with 32 additions and 22 deletions
|
@ -1,5 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 2013-2014 The University of Oslo
|
||||
* Copyright (c) 2013-2016 The University of Oslo
|
||||
* Copyright (c) 2016-2017 Dag-Erling Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -48,6 +49,8 @@
|
|||
struct oath_key *
|
||||
oath_key_from_uri(const char *uri)
|
||||
{
|
||||
char name[64], value[256];
|
||||
size_t namelen, valuelen;
|
||||
struct oath_key *key;
|
||||
const char *p, *q, *r;
|
||||
uintmax_t n;
|
||||
|
@ -86,69 +89,76 @@ oath_key_from_uri(const char *uri)
|
|||
key->counter = UINT64_MAX;
|
||||
key->lastused = UINT64_MAX;
|
||||
while (*p != '\0') {
|
||||
/* locate name-value separator */
|
||||
if ((q = strchr(p, '=')) == NULL)
|
||||
goto invalid;
|
||||
q = q + 1;
|
||||
/* locate end of value */
|
||||
if ((r = strchr(p, '&')) == NULL)
|
||||
r = strchr(p, '\0');
|
||||
if (r < q)
|
||||
/* & before = */
|
||||
goto invalid;
|
||||
/* p points to key, q points to value, r points to & or NUL */
|
||||
if (strlcmp("secret=", p, q - p) == 0) {
|
||||
/* decode name and value*/
|
||||
namelen = sizeof name;
|
||||
valuelen = sizeof value;
|
||||
if (percent_decode(p, q - p - 1, name, &namelen) != 0 ||
|
||||
percent_decode(q, r - q, value, &valuelen) != 0)
|
||||
goto invalid;
|
||||
if (strcmp("secret", name) == 0) {
|
||||
if (key->keylen != 0)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
key->keylen = sizeof key->key;
|
||||
if (base32_decode(q, r - q, key->key, &key->keylen) != 0)
|
||||
if (base32_decode(value, valuelen, key->key, &key->keylen) != 0)
|
||||
goto invalid;
|
||||
} else if (strlcmp("algorithm=", p, q - p) == 0) {
|
||||
} else if (strcmp("algorithm", name) == 0) {
|
||||
if (key->hash != oh_undef)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
if (strlcmp("SHA1", q, r - q) == 0)
|
||||
if (strcmp("SHA1", value) == 0)
|
||||
key->hash = oh_sha1;
|
||||
else if (strlcmp("SHA256", q, r - q) == 0)
|
||||
else if (strcmp("SHA256", value) == 0)
|
||||
key->hash = oh_sha256;
|
||||
else if (strlcmp("SHA512", q, r - q) == 0)
|
||||
else if (strcmp("SHA512", value) == 0)
|
||||
key->hash = oh_sha512;
|
||||
else if (strlcmp("MD5", q, r - q) == 0)
|
||||
else if (strcmp("MD5", value) == 0)
|
||||
key->hash = oh_md5;
|
||||
else
|
||||
goto invalid;
|
||||
} else if (strlcmp("digits=", p, q - p) == 0) {
|
||||
} else if (strcmp("digits", name) == 0) {
|
||||
if (key->digits != 0)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
/* only 6 or 8 */
|
||||
if (r - q != 1 || (*q != '6' && *q != '8'))
|
||||
if (valuelen != 1 || (*value != '6' && *value != '8'))
|
||||
goto invalid;
|
||||
key->digits = *q - '0';
|
||||
} else if (strlcmp("counter=", p, q - p) == 0) {
|
||||
} else if (strcmp("counter", name) == 0) {
|
||||
if (key->counter != UINT64_MAX)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
n = strtoumax(q, &e, 10);
|
||||
if (e != r || n >= UINT64_MAX)
|
||||
n = strtoumax(value, &e, 10);
|
||||
if (e == value || *e != '\0' || n >= UINT64_MAX)
|
||||
goto invalid;
|
||||
key->counter = (uint64_t)n;
|
||||
} else if (strlcmp("lastused=", p, q - p) == 0) {
|
||||
} else if (strcmp("lastused", name) == 0) {
|
||||
if (key->lastused != UINT64_MAX)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
n = strtoumax(q, &e, 10);
|
||||
if (e != r || n >= UINT64_MAX)
|
||||
n = strtoumax(value, &e, 10);
|
||||
if (e == value || *e != '\0' || n >= UINT64_MAX)
|
||||
goto invalid;
|
||||
key->lastused = (uint64_t)n;
|
||||
} else if (strlcmp("period=", p, q - p) == 0) {
|
||||
} else if (strcmp("period", name) == 0) {
|
||||
if (key->timestep != 0)
|
||||
/* dupe */
|
||||
goto invalid;
|
||||
n = strtoumax(q, &e, 10);
|
||||
if (e != r || n > OATH_MAX_TIMESTEP)
|
||||
n = strtoumax(value, &e, 10);
|
||||
if (e == value || *e != '\0' || n > OATH_MAX_TIMESTEP)
|
||||
goto invalid;
|
||||
key->timestep = n;
|
||||
} else if (strlcmp("issuer=", p, q - p) == 0) {
|
||||
} else if (strcmp("issuer", name) == 0) {
|
||||
// noop for now
|
||||
} else {
|
||||
goto invalid;
|
||||
|
|
|
@ -63,7 +63,7 @@ oath_key_to_uri(const struct oath_key *key)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/* XXX the label should be URI-encoded */
|
||||
/* XXX the label and secret should be URI-encoded */
|
||||
if (key->mode == om_hotp) {
|
||||
urilen = asprintf(&uri, "otpauth://%s/%s?"
|
||||
"algorithm=%s&digits=%d&counter=%ju&secret=",
|
||||
|
|
Loading…
Reference in a new issue