blob: 208d380bb88a98c3576398c46d56571c61f3ca7f [file] [log] [blame]
Damien Miller95def091999-11-25 00:26:21 +11001#include "includes.h"
Damien Miller80297751999-11-19 13:03:25 +11002#ifdef SKEY
Damien Miller6536c7d2000-06-22 21:32:31 +10003RCSID("$OpenBSD: auth-skey.c,v 1.7 2000/06/20 01:39:38 markus Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10004
5#include "ssh.h"
Damien Milleraae6c611999-12-06 11:47:28 +11006#include "packet.h"
Damien Miller484118e2000-07-02 19:13:56 +10007#include <openssl/sha.h>
Damien Millerd4a8b7e1999-10-27 13:42:43 +10008
9/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
10
Damien Miller4af51302000-04-16 11:18:38 +100011/*
Damien Milleraae6c611999-12-06 11:47:28 +110012 * try skey authentication,
Damien Miller4af51302000-04-16 11:18:38 +100013 * return 1 on success, 0 on failure, -1 if skey is not available
Damien Milleraae6c611999-12-06 11:47:28 +110014 */
15
Damien Miller4af51302000-04-16 11:18:38 +100016int
Damien Milleraae6c611999-12-06 11:47:28 +110017auth_skey_password(struct passwd * pw, const char *password)
18{
19 if (strncasecmp(password, "s/key", 5) == 0) {
20 char *skeyinfo = skey_keyinfo(pw->pw_name);
21 if (skeyinfo == NULL) {
22 debug("generating fake skeyinfo for %.100s.",
23 pw->pw_name);
24 skeyinfo = skey_fake_keyinfo(pw->pw_name);
25 }
26 if (skeyinfo != NULL)
27 packet_send_debug(skeyinfo);
28 /* Try again. */
29 return 0;
30 } else if (skey_haskey(pw->pw_name) == 0 &&
31 skey_passcheck(pw->pw_name, (char *) password) != -1) {
32 /* Authentication succeeded. */
33 return 1;
34 }
35 /* Fall back to ordinary passwd authentication. */
36 return -1;
37}
Damien Miller4e0dbd01999-12-09 10:57:00 +110038
39/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100040
41#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
42 ((x)[3]))
43
44/*
45 * hash_collapse()
46 */
47static u_int32_t
48hash_collapse(s)
Damien Miller4af51302000-04-16 11:18:38 +100049 u_char *s;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100050{
Damien Miller4af51302000-04-16 11:18:38 +100051 int len, target;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100052 u_int32_t i;
53
54 if ((strlen(s) % sizeof(u_int32_t)) == 0)
Damien Miller4af51302000-04-16 11:18:38 +100055 target = strlen(s); /* Multiple of 4 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100056 else
57 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
Damien Miller4af51302000-04-16 11:18:38 +100058
Damien Millerd4a8b7e1999-10-27 13:42:43 +100059 for (i = 0, len = 0; len < target; len += 4)
Damien Miller4af51302000-04-16 11:18:38 +100060 i ^= ROUND(s + len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100061
62 return i;
63}
Damien Miller95def091999-11-25 00:26:21 +110064
Damien Millerd4a8b7e1999-10-27 13:42:43 +100065char *
66skey_fake_keyinfo(char *username)
67{
68 int i;
69 u_int ptr;
70 u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
71 char pbuf[SKEY_MAX_PW_LEN+1];
72 static char skeyprompt[SKEY_MAX_CHALLENGE+1];
73 char *secret = NULL;
74 size_t secretlen = 0;
Damien Miller25e42562000-01-11 10:59:47 +110075 SHA_CTX ctx;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100076 char *p, *u;
77
78 /*
79 * Base first 4 chars of seed on hostname.
80 * Add some filler for short hostnames if necessary.
81 */
82 if (gethostname(pbuf, sizeof(pbuf)) == -1)
83 *(p = pbuf) = '.';
84 else
85 for (p = pbuf; *p && isalnum(*p); p++)
86 if (isalpha(*p) && isupper(*p))
87 *p = tolower(*p);
88 if (*p && pbuf - p < 4)
89 (void)strncpy(p, "asjd", 4 - (pbuf - p));
90 pbuf[4] = '\0';
91
92 /* Hash the username if possible */
Damien Miller25e42562000-01-11 10:59:47 +110093 up = malloc(SHA_DIGEST_LENGTH);
94 if (up != NULL) {
Damien Millerd4a8b7e1999-10-27 13:42:43 +100095 struct stat sb;
96 time_t t;
97 int fd;
98
Damien Miller25e42562000-01-11 10:59:47 +110099 SHA1_Init(&ctx);
100 SHA1_Update(&ctx, username, strlen(username));
Damien Miller484118e2000-07-02 19:13:56 +1000101 SHA1_Final(up, &ctx);
Damien Miller25e42562000-01-11 10:59:47 +1100102
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000103 /* Collapse the hash */
104 ptr = hash_collapse(up);
105 memset(up, 0, strlen(up));
106
107 /* See if the random file's there, else use ctime */
108 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
109 && fstat(fd, &sb) == 0 &&
110 sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
111 lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
112 SEEK_SET) != -1 && read(fd, hseed,
113 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
114 close(fd);
Damien Miller037a0dc1999-12-07 15:38:31 +1100115 fd = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000116 secret = hseed;
117 secretlen = SKEY_MAX_SEED_LEN;
118 flg = 0;
119 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
120 t = sb.st_ctime;
121 secret = ctime(&t);
122 secretlen = strlen(secret);
123 flg = 0;
124 }
Damien Miller037a0dc1999-12-07 15:38:31 +1100125 if (fd != -1)
126 close(fd);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000127 }
128
129 /* Put that in your pipe and smoke it */
130 if (flg == 0) {
131 /* Hash secret value with username */
Damien Miller25e42562000-01-11 10:59:47 +1100132 SHA1_Init(&ctx);
133 SHA1_Update(&ctx, secret, secretlen);
134 SHA1_Update(&ctx, username, strlen(username));
Damien Miller484118e2000-07-02 19:13:56 +1000135 SHA1_Final(up, &ctx);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000136
137 /* Zero out */
138 memset(secret, 0, secretlen);
139
140 /* Now hash the hash */
Damien Miller25e42562000-01-11 10:59:47 +1100141 SHA1_Init(&ctx);
142 SHA1_Update(&ctx, up, strlen(up));
Damien Miller484118e2000-07-02 19:13:56 +1000143 SHA1_Final(up, &ctx);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000144
145 ptr = hash_collapse(up + 4);
146
147 for (i = 4; i < 9; i++) {
148 pbuf[i] = (ptr % 10) + '0';
149 ptr /= 10;
150 }
151 pbuf[i] = '\0';
152
153 /* Sequence number */
154 ptr = ((up[2] + up[3]) % 99) + 1;
155
Damien Miller25e42562000-01-11 10:59:47 +1100156 memset(up, 0, SHA_DIGEST_LENGTH); /* SHA1 specific */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000157 free(up);
158
159 (void)snprintf(skeyprompt, sizeof skeyprompt,
160 "otp-%.*s %d %.*s",
161 SKEY_MAX_HASHNAME_LEN,
162 skey_get_algorithm(),
163 ptr, SKEY_MAX_SEED_LEN,
164 pbuf);
165 } else {
166 /* Base last 8 chars of seed on username */
167 u = username;
168 i = 8;
169 p = &pbuf[4];
170 do {
171 if (*u == 0) {
172 /* Pad remainder with zeros */
173 while (--i >= 0)
174 *p++ = '0';
175 break;
176 }
177
178 *p++ = (*u++ % 10) + '0';
179 } while (--i != 0);
180 pbuf[12] = '\0';
181
182 (void)snprintf(skeyprompt, sizeof skeyprompt,
183 "otp-%.*s %d %.*s",
184 SKEY_MAX_HASHNAME_LEN,
185 skey_get_algorithm(),
186 99, SKEY_MAX_SEED_LEN, pbuf);
187 }
188 return skeyprompt;
189}
Damien Miller80297751999-11-19 13:03:25 +1100190
Damien Miller95def091999-11-25 00:26:21 +1100191#endif /* SKEY */