Changeset 643 in openpam


Ignore:
Timestamp:
Mar 5, 2013, 3:24:00 PM (8 years ago)
Author:
Dag-Erling Smørgrav
Message:
  • Add a provisional API for computing the current HOTP or TOTP code.
  • Add a provisional API for matching a user response.
  • Add a provisional API for generating a dummy key. When one of the matching functions recognizes a dummy key, it will go through the motions but never report a match.
Location:
trunk/modules/pam_oath
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/modules/pam_oath/oath.h

    r638 r643  
    102102char *oath_key_to_uri(const struct oath_key *);
    103103
     104#define DUMMY_LABEL     ("oath-dummy-key")
     105#define DUMMY_LABELLEN  (sizeof DUMMY_LABEL)
     106#define DUMMY_KEYLEN    80
     107
     108struct oath_key *oath_dummy_key(enum oath_mode, enum oath_hash, unsigned int);
     109
    104110unsigned int oath_hotp(const uint8_t *, size_t, uint64_t, unsigned int);
     111int oath_hotp_current(struct oath_key *);
     112int oath_hotp_match(struct oath_key *, unsigned int, int);
     113
    105114unsigned int oath_totp(const uint8_t *, size_t, unsigned int);
     115int oath_totp_match(const struct oath_key *, unsigned int, int);
     116unsigned int oath_totp_current(const struct oath_key *);
    106117
    107118#endif
  • trunk/modules/pam_oath/oath_hotp.c

    r623 r643  
    3838
    3939#include <stdint.h>
     40#include <string.h>
    4041
    4142#include "oath.h"
     
    8889        return (D);
    8990}
     91
     92/*
     93 * Computes the current code for the given key and advances the counter.
     94 */
     95int
     96oath_hotp_current(struct oath_key *k)
     97{
     98        unsigned int code;
     99
     100        if (k == NULL)
     101                return (-1);
     102        if (k->mode != om_hotp)
     103                return (-1);
     104        if (k->counter == UINT64_MAX)
     105                return (-1);
     106        code = oath_hotp(k->key, k->keylen, k->counter, k->digits);
     107        k->counter += 1;
     108        return (code);
     109}
     110
     111/*
     112 * Compares the code provided by the user with expected values within a
     113 * given window.  Returns 1 if there was a match, 0 if not, and -1 if an
     114 * error occurred.
     115 */
     116int
     117oath_hotp_match(struct oath_key *k, unsigned int response, int window)
     118{
     119        unsigned int code;
     120        int dummy;
     121
     122        if (k == NULL)
     123                return (-1);
     124        if (window < 1)
     125                return (-1);
     126        if (k->mode != om_hotp)
     127                return (-1);
     128        if (k->counter >= UINT64_MAX - window)
     129                return (-1);
     130        dummy = (memcmp(k->label, DUMMY_LABEL, DUMMY_LABELLEN) == 0);
     131        for (int i = 0; i < window; ++i) {
     132                code = oath_hotp(k->key, k->keylen, k->counter + i, k->digits);
     133                if (code == response && !dummy) {
     134                        k->counter = k->counter + i;
     135                        return (1);
     136                }
     137        }
     138        return (0);
     139}
  • trunk/modules/pam_oath/oath_key.c

    r628 r643  
    113113                goto invalid;
    114114        if (strlcmp("hotp", p, q - p) == 0) {
    115                 openpam_log(PAM_LOG_DEBUG, "OATH mode: HOTP");
    116115                key->mode = om_hotp;
    117116        } else if (strlcmp("totp", p, q - p) == 0) {
    118                 openpam_log(PAM_LOG_DEBUG, "OATH mode: TOTP");
    119117                key->mode = om_totp;
    120118        } else {
     
    133131
    134132        /* extract parameters */
    135         key->counter = UINTMAX_MAX;
     133        key->counter = UINT64_MAX;
    136134        while (*p != '\0') {
    137135                if ((q = strchr(p, '=')) == NULL)
     
    153151                                goto invalid;
    154152                        key->key = key->data + key->labellen;
     153                        key->keylen = key->datalen - key->labellen;
    155154                        if (base32_dec(q, r - q, key->key, &key->keylen) != 0)
    156155                                goto invalid;
     
    180179                        key->digits = *q - '0';
    181180                } else if (strlcmp("counter=", p, q - p) == 0) {
    182                         if (key->counter != UINTMAX_MAX)
     181                        if (key->counter != UINT64_MAX)
    183182                                /* dupe */
    184183                                goto invalid;
    185184                        n = strtoumax(q, &e, 10);
    186                         if (e != r || n >= UINTMAX_MAX)
     185                        if (e != r || n >= UINT64_MAX)
    187186                                goto invalid;
    188187                        key->counter = (uint64_t)n;
     
    227226        if (key->keylen == 0)
    228227                goto invalid;
     228        return (key);
    229229
    230230invalid:
     
    296296
    297297        /* compute length of base32-encoded key and append it */
    298         kslen = base32_enclen(key->keylen);
    299         if ((tmp = realloc(uri, urilen + kslen + 1)) == NULL) {
     298        kslen = base32_enclen(key->keylen) + 1;
     299        if ((tmp = realloc(uri, urilen + kslen)) == NULL) {
    300300                free(uri);
    301301                return (NULL);
     
    309309        return (uri);
    310310}
     311
     312struct oath_key *
     313oath_dummy_key(enum oath_mode mode, enum oath_hash hash, unsigned int digits)
     314{
     315        struct oath_key *key;
     316
     317        if ((key = oath_key_alloc(DUMMY_LABELLEN + DUMMY_KEYLEN)) == NULL)
     318                return (NULL);
     319        key->mode = mode;
     320        key->digits = digits;
     321        key->counter = 0;
     322        key->timestep = 30;
     323        key->hash = hash;
     324        key->label = (char *)key->data;
     325        memcpy(key->label, DUMMY_LABEL, DUMMY_LABELLEN);
     326        key->key = key->data + DUMMY_LABELLEN;
     327        key->keylen = DUMMY_KEYLEN;
     328        return (key);
     329}
  • trunk/modules/pam_oath/oath_totp.c

    r623 r643  
    3535
    3636#include <stdint.h>
     37#include <string.h>
    3738#include <time.h>
    3839
     
    4950        return (oath_hotp(K, Klen, now / TOTP_TIME_STEP, Digit));
    5051}
     52
     53unsigned int
     54oath_totp_current(const struct oath_key *k)
     55{
     56        unsigned int code;
     57        uint64_t seq;
     58
     59        if (k == NULL)
     60                return (-1);
     61        if (k->mode != om_totp)
     62                return (-1);
     63        if (k->timestep == 0)
     64                return (-1);
     65        seq = time(NULL) / k->timestep;
     66        code = oath_hotp(k->key, k->keylen, seq, k->digits);
     67        return (code);
     68}
     69
     70int
     71oath_totp_match(const struct oath_key *k, unsigned int response, int window)
     72{
     73        unsigned int code;
     74        uint64_t seq;
     75        int dummy;
     76
     77        if (k == NULL)
     78                return (-1);
     79        if (window < 1)
     80                return (-1);
     81        if (k->mode != om_totp)
     82                return (-1);
     83        if (k->timestep == 0)
     84                return (-1);
     85        seq = time(NULL) / k->timestep;
     86        dummy = (memcmp(k->label, DUMMY_LABEL, DUMMY_LABELLEN) == 0);
     87        for (int i = -window; i <= window; ++i) {
     88                code = oath_hotp(k->key, k->keylen, seq + i, k->digits);
     89                if (code == response && !dummy)
     90                        return (1);
     91        }
     92        return (0);
     93}
Note: See TracChangeset for help on using the changeset viewer.