Changeset 700 in openpam


Ignore:
Timestamp:
Aug 15, 2013, 5:17:15 PM (7 years ago)
Author:
Dag-Erling Smørgrav
Message:

Major cleanup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/modules/pam_oath/pam_oath.c

    r697 r700  
    5252enum pam_oath_nokey { nokey_error = -1, nokey_fail, nokey_fake, nokey_ignore };
    5353
     54static const char *pam_oath_default_keyfile = "/var/oath/%u.otpauth";
     55
     56/*
     57 * Parse the nokey or badkey option, which indicates how we should act if
     58 * the user has no keyfile or the keyfile is invalid.
     59 */
    5460static enum pam_oath_nokey
    55 get_nokey_option(pam_handle_t *pamh, const char *option)
     61pam_oath_nokey_option(pam_handle_t *pamh, const char *option)
    5662{
    5763        const char *value;
     
    7076}
    7177
     78/*
     79 * Determine the location of the user's keyfile.
     80 */
     81static char *
     82pam_oath_keyfile(pam_handle_t *pamh)
     83{
     84        const char *keyfile;
     85        char *path;
     86        size_t size;
     87
     88        if ((keyfile = openpam_get_option(pamh, "keyfile")) == NULL)
     89                keyfile = pam_oath_default_keyfile;
     90        size = 0;
     91        if (openpam_subst(pamh, NULL, &size, keyfile) != PAM_TRY_AGAIN)
     92                return (NULL);
     93        if ((path = malloc(size)) == NULL)
     94                return (NULL);
     95        if (openpam_subst(pamh, path, &size, keyfile) != PAM_SUCCESS) {
     96                free(path);
     97                return (NULL);
     98        }
     99        return (path);
     100}
     101
     102/*
     103 * Load the user's key.
     104 */
     105static struct oath_key *
     106pam_oath_load_key(const char *keyfile)
     107{
     108
     109        /* XXX should check ownership and permissions */
     110        return (oath_key_from_file(keyfile));
     111}
     112
     113/*
     114 * Save the user's key.
     115 */
     116static int
     117pam_oath_save_key(const struct oath_key *key, const char *keyfile)
     118{
     119
     120        /* not implemented */
     121        (void)key;
     122        (void)keyfile;
     123        return (0);
     124}
     125
    72126PAM_EXTERN int
    73127pam_sm_authenticate(pam_handle_t *pamh, int flags,
     
    88142        (void)argv;
    89143
     144        keyfile = NULL;
     145        key = NULL;
     146
     147        openpam_log(PAM_LOG_VERBOSE, "attempting OATH authentication");
     148
    90149        /* check how to behave if the user does not have a valid key */
    91         if ((nokey = get_nokey_option(pamh, "nokey")) == nokey_error ||
    92             (badkey = get_nokey_option(pamh, "badkey")) == nokey_error)
    93                 return (PAM_SERVICE_ERR);
     150        if ((nokey = pam_oath_nokey_option(pamh, "nokey")) == nokey_error ||
     151            (badkey = pam_oath_nokey_option(pamh, "badkey")) == nokey_error) {
     152                pam_err = PAM_SERVICE_ERR;
     153                goto done;
     154        }
    94155
    95156        /* identify user */
    96157        if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
    97                 return (pam_err);
    98         if ((pwd = getpwnam(user)) == NULL)
    99                 return (PAM_USER_UNKNOWN);
     158                goto done;
     159        if ((pwd = getpwnam(user)) == NULL) {
     160                pam_err = PAM_USER_UNKNOWN;
     161                goto done;
     162        }
     163
     164        openpam_log(PAM_LOG_VERBOSE, "authenticating user %s", user);
    100165
    101166        /* load key */
    102         /* XXX implement additional schemes */
    103         keyfile = calloc(1, strlen(pwd->pw_dir) + sizeof "/.otpauth");
    104         if (keyfile == NULL)
    105                 return (PAM_SYSTEM_ERR);
    106         sprintf(keyfile, "%s/.otpauth", pwd->pw_dir);
    107         key = oath_key_from_file(keyfile);
    108         free(keyfile);
     167        if ((keyfile = pam_oath_keyfile(pamh)) == NULL) {
     168                pam_err = PAM_SYSTEM_ERR;
     169                goto done;
     170        }
     171        openpam_log(PAM_LOG_VERBOSE, "attempting to load %s for %s", keyfile, user);
     172        key = pam_oath_load_key(keyfile);
    109173
    110174        /*
     
    114178         * provide enough information for us to tell the difference
    115179         * between a bad key and no key at all.
     180         *
     181         * XXX move this into pam_oath_load_key()
    116182         */
    117183        if (key == NULL) {
     184                openpam_log(PAM_LOG_VERBOSE, "no key found for %s", user);
    118185                switch (nokey) {
    119186                case nokey_fail:
    120                         return (PAM_AUTHINFO_UNAVAIL);
     187                        pam_err = PAM_AUTHINFO_UNAVAIL;
     188                        goto done;
    121189                case nokey_fake:
    122190                        key = oath_key_dummy(om_hotp, oh_sha1, 6);
    123191                        break;
    124192                case nokey_ignore:
    125                         return (PAM_IGNORE);
     193                        pam_err = PAM_IGNORE;
     194                        goto done;
    126195                default:
    127196                        /* can't happen */
    128                         return (PAM_SERVICE_ERR);
     197                        pam_err = PAM_SERVICE_ERR;
     198                        goto done;
    129199                }
    130200        }
     
    134204            (const char **)&password, PAM_OATH_PROMPT);
    135205        if (pam_err != PAM_SUCCESS) {
    136                 oath_key_free(key);
    137                 return (pam_err);
     206                openpam_log(PAM_LOG_VERBOSE, "conversation failure");
     207                goto done;
    138208        }
    139209
     
    148218        else
    149219                ret = oath_totp_match(key, response, 1);
     220        openpam_log(PAM_LOG_VERBOSE, "verification code %s",
     221            ret ? "matched" : "did not match");
     222        if (ret == 0) {
     223                pam_err = PAM_AUTH_ERR;
     224                goto done;
     225        }
     226
     227        /* write back (update counter for HOTP etc) */
     228        if (pam_oath_save_key(key, keyfile) != 0) {
     229                pam_err = PAM_SYSTEM_ERR;
     230                goto done;
     231        }
     232
     233        openpam_log(PAM_LOG_VERBOSE, "OATH authentication succeeded");
     234        pam_err = PAM_SUCCESS;
     235done:
    150236        oath_key_free(key);
    151         if (ret != 1)
    152                 return (PAM_AUTH_ERR);
    153 
    154         /* XXX write back */
    155         return (PAM_SUCCESS);
     237        free(keyfile);
     238        return (pam_err);
    156239}
    157240
Note: See TracChangeset for help on using the changeset viewer.