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: }