[BACK]Return to auth-skey.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/auth-skey.c, Revision 1.8

1.8     ! deraadt     1: /*
        !             2:  * Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
        !             3:  *
        !             4:  * Redistribution and use in source and binary forms, with or without
        !             5:  * modification, are permitted provided that the following conditions
        !             6:  * are met:
        !             7:  * 1. Redistributions of source code must retain the above copyright
        !             8:  *    notice, this list of conditions and the following disclaimer.
        !             9:  * 2. Redistributions in binary form must reproduce the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer in the
        !            11:  *    documentation and/or other materials provided with the distribution.
        !            12:  *
        !            13:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            15:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            16:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            17:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            18:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            19:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            20:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            21:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            22:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            23:  */
        !            24:
1.1       markus     25: #include "includes.h"
1.8     ! deraadt    26: RCSID("$OpenBSD: auth-skey.c,v 1.7 2000/06/20 01:39:38 markus Exp $");
1.1       markus     27:
                     28: #include "ssh.h"
1.4       markus     29: #include "packet.h"
1.1       markus     30: #include <sha1.h>
                     31:
1.6       markus     32: /*
1.4       markus     33:  * try skey authentication,
1.6       markus     34:  * return 1 on success, 0 on failure, -1 if skey is not available
1.4       markus     35:  */
                     36:
1.6       markus     37: int
1.4       markus     38: auth_skey_password(struct passwd * pw, const char *password)
                     39: {
                     40:        if (strncasecmp(password, "s/key", 5) == 0) {
                     41:                char *skeyinfo = skey_keyinfo(pw->pw_name);
                     42:                if (skeyinfo == NULL) {
                     43:                        debug("generating fake skeyinfo for %.100s.",
                     44:                            pw->pw_name);
                     45:                        skeyinfo = skey_fake_keyinfo(pw->pw_name);
                     46:                }
                     47:                if (skeyinfo != NULL)
                     48:                        packet_send_debug(skeyinfo);
                     49:                /* Try again. */
                     50:                return 0;
                     51:        } else if (skey_haskey(pw->pw_name) == 0 &&
                     52:                   skey_passcheck(pw->pw_name, (char *) password) != -1) {
                     53:                /* Authentication succeeded. */
                     54:                return 1;
                     55:        }
                     56:        /* Fall back to ordinary passwd authentication. */
                     57:        return -1;
                     58: }
                     59:
1.1       markus     60: /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
                     61:
                     62: #define ROUND(x)   (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
                     63:                    ((x)[3]))
                     64:
                     65: /*
                     66:  * hash_collapse()
                     67:  */
                     68: static u_int32_t
                     69: hash_collapse(s)
1.6       markus     70:        u_char *s;
1.1       markus     71: {
1.6       markus     72:        int len, target;
1.1       markus     73:        u_int32_t i;
                     74:
                     75:        if ((strlen(s) % sizeof(u_int32_t)) == 0)
1.6       markus     76:                target = strlen(s);    /* Multiple of 4 */
1.1       markus     77:        else
                     78:                target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
1.6       markus     79:
1.1       markus     80:        for (i = 0, len = 0; len < target; len += 4)
1.6       markus     81:                i ^= ROUND(s + len);
1.1       markus     82:
                     83:        return i;
                     84: }
1.3       markus     85:
1.1       markus     86: char *
                     87: skey_fake_keyinfo(char *username)
                     88: {
                     89:        int i;
                     90:        u_int ptr;
                     91:        u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
                     92:        char pbuf[SKEY_MAX_PW_LEN+1];
                     93:        static char skeyprompt[SKEY_MAX_CHALLENGE+1];
                     94:        char *secret = NULL;
                     95:        size_t secretlen = 0;
                     96:        SHA1_CTX ctx;
                     97:        char *p, *u;
                     98:
                     99:        /*
                    100:         * Base first 4 chars of seed on hostname.
                    101:         * Add some filler for short hostnames if necessary.
                    102:         */
                    103:        if (gethostname(pbuf, sizeof(pbuf)) == -1)
                    104:                *(p = pbuf) = '.';
                    105:        else
                    106:                for (p = pbuf; *p && isalnum(*p); p++)
                    107:                        if (isalpha(*p) && isupper(*p))
                    108:                                *p = tolower(*p);
                    109:        if (*p && pbuf - p < 4)
                    110:                (void)strncpy(p, "asjd", 4 - (pbuf - p));
                    111:        pbuf[4] = '\0';
                    112:
                    113:        /* Hash the username if possible */
                    114:        if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
                    115:                struct stat sb;
                    116:                time_t t;
                    117:                int fd;
                    118:
                    119:                /* Collapse the hash */
                    120:                ptr = hash_collapse(up);
                    121:                memset(up, 0, strlen(up));
                    122:
                    123:                /* See if the random file's there, else use ctime */
                    124:                if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
                    125:                    && fstat(fd, &sb) == 0 &&
                    126:                    sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
                    127:                    lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
                    128:                    SEEK_SET) != -1 && read(fd, hseed,
                    129:                    SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
                    130:                        close(fd);
1.5       deraadt   131:                        fd = -1;
1.1       markus    132:                        secret = hseed;
                    133:                        secretlen = SKEY_MAX_SEED_LEN;
                    134:                        flg = 0;
                    135:                } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
                    136:                        t = sb.st_ctime;
                    137:                        secret = ctime(&t);
                    138:                        secretlen = strlen(secret);
                    139:                        flg = 0;
                    140:                }
1.5       deraadt   141:                if (fd != -1)
                    142:                        close(fd);
1.1       markus    143:        }
                    144:
                    145:        /* Put that in your pipe and smoke it */
                    146:        if (flg == 0) {
                    147:                /* Hash secret value with username */
                    148:                SHA1Init(&ctx);
                    149:                SHA1Update(&ctx, secret, secretlen);
                    150:                SHA1Update(&ctx, username, strlen(username));
                    151:                SHA1End(&ctx, up);
                    152:
                    153:                /* Zero out */
                    154:                memset(secret, 0, secretlen);
                    155:
                    156:                /* Now hash the hash */
                    157:                SHA1Init(&ctx);
                    158:                SHA1Update(&ctx, up, strlen(up));
                    159:                SHA1End(&ctx, up);
                    160:
                    161:                ptr = hash_collapse(up + 4);
                    162:
                    163:                for (i = 4; i < 9; i++) {
                    164:                        pbuf[i] = (ptr % 10) + '0';
                    165:                        ptr /= 10;
                    166:                }
                    167:                pbuf[i] = '\0';
                    168:
                    169:                /* Sequence number */
                    170:                ptr = ((up[2] + up[3]) % 99) + 1;
                    171:
                    172:                memset(up, 0, 20); /* SHA1 specific */
                    173:                free(up);
                    174:
1.2       deraadt   175:                (void)snprintf(skeyprompt, sizeof skeyprompt,
1.1       markus    176:                              "otp-%.*s %d %.*s",
                    177:                              SKEY_MAX_HASHNAME_LEN,
                    178:                              skey_get_algorithm(),
                    179:                              ptr, SKEY_MAX_SEED_LEN,
                    180:                              pbuf);
                    181:        } else {
                    182:                /* Base last 8 chars of seed on username */
                    183:                u = username;
                    184:                i = 8;
                    185:                p = &pbuf[4];
                    186:                do {
                    187:                        if (*u == 0) {
                    188:                                /* Pad remainder with zeros */
                    189:                                while (--i >= 0)
                    190:                                        *p++ = '0';
                    191:                                break;
                    192:                        }
                    193:
                    194:                        *p++ = (*u++ % 10) + '0';
                    195:                } while (--i != 0);
                    196:                pbuf[12] = '\0';
                    197:
1.2       deraadt   198:                (void)snprintf(skeyprompt, sizeof skeyprompt,
                    199:                              "otp-%.*s %d %.*s",
1.1       markus    200:                              SKEY_MAX_HASHNAME_LEN,
                    201:                              skey_get_algorithm(),
                    202:                              99, SKEY_MAX_SEED_LEN, pbuf);
                    203:        }
                    204:        return skeyprompt;
                    205: }