blob: f403a1962a87317f8c39772f951b761de572979f [file] [log] [blame]
Damien Miller95def091999-11-25 00:26:21 +11001#include "includes.h"
2
Damien Miller80297751999-11-19 13:03:25 +11003#ifdef SKEY
Damien Miller037a0dc1999-12-07 15:38:31 +11004RCSID("$Id: auth-skey.c,v 1.5 1999/12/06 19:04:57 deraadt Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10005
6#include "ssh.h"
Damien Milleraae6c611999-12-06 11:47:28 +11007#include "packet.h"
8
Damien Miller5428f641999-11-25 11:54:57 +11009#ifdef HAVE_OPENSSL
Damien Miller25e42562000-01-11 10:59:47 +110010#include <openssl/sha.h>
Damien Miller5428f641999-11-25 11:54:57 +110011#endif
12#ifdef HAVE_SSL
Damien Miller25e42562000-01-11 10:59:47 +110013#include <ssl/sha.h>
Damien Miller5428f641999-11-25 11:54:57 +110014#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +100015
16/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
17
Damien Milleraae6c611999-12-06 11:47:28 +110018/*
19 * try skey authentication,
20 * return 1 on success, 0 on failure, -1 if skey is not available
21 */
22
23int
24auth_skey_password(struct passwd * pw, const char *password)
25{
26 if (strncasecmp(password, "s/key", 5) == 0) {
27 char *skeyinfo = skey_keyinfo(pw->pw_name);
28 if (skeyinfo == NULL) {
29 debug("generating fake skeyinfo for %.100s.",
30 pw->pw_name);
31 skeyinfo = skey_fake_keyinfo(pw->pw_name);
32 }
33 if (skeyinfo != NULL)
34 packet_send_debug(skeyinfo);
35 /* Try again. */
36 return 0;
37 } else if (skey_haskey(pw->pw_name) == 0 &&
38 skey_passcheck(pw->pw_name, (char *) password) != -1) {
39 /* Authentication succeeded. */
40 return 1;
41 }
42 /* Fall back to ordinary passwd authentication. */
43 return -1;
44}
Damien Miller4e0dbd01999-12-09 10:57:00 +110045
46/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100047
48#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
49 ((x)[3]))
50
51/*
52 * hash_collapse()
53 */
54static u_int32_t
55hash_collapse(s)
56 u_char *s;
57{
58 int len, target;
59 u_int32_t i;
60
61 if ((strlen(s) % sizeof(u_int32_t)) == 0)
62 target = strlen(s); /* Multiple of 4 */
63 else
64 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
65
66 for (i = 0, len = 0; len < target; len += 4)
67 i ^= ROUND(s + len);
68
69 return i;
70}
Damien Miller95def091999-11-25 00:26:21 +110071
Damien Millerd4a8b7e1999-10-27 13:42:43 +100072char *
73skey_fake_keyinfo(char *username)
74{
75 int i;
76 u_int ptr;
77 u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
78 char pbuf[SKEY_MAX_PW_LEN+1];
79 static char skeyprompt[SKEY_MAX_CHALLENGE+1];
80 char *secret = NULL;
81 size_t secretlen = 0;
Damien Miller25e42562000-01-11 10:59:47 +110082 SHA_CTX ctx;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100083 char *p, *u;
Damien Miller25e42562000-01-11 10:59:47 +110084 char md[SHA_DIGEST_LENGTH];
Damien Millerd4a8b7e1999-10-27 13:42:43 +100085
86 /*
87 * Base first 4 chars of seed on hostname.
88 * Add some filler for short hostnames if necessary.
89 */
90 if (gethostname(pbuf, sizeof(pbuf)) == -1)
91 *(p = pbuf) = '.';
92 else
93 for (p = pbuf; *p && isalnum(*p); p++)
94 if (isalpha(*p) && isupper(*p))
95 *p = tolower(*p);
96 if (*p && pbuf - p < 4)
97 (void)strncpy(p, "asjd", 4 - (pbuf - p));
98 pbuf[4] = '\0';
99
100 /* Hash the username if possible */
Damien Miller25e42562000-01-11 10:59:47 +1100101 up = malloc(SHA_DIGEST_LENGTH);
102 if (up != NULL) {
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000103 struct stat sb;
104 time_t t;
105 int fd;
106
Damien Miller25e42562000-01-11 10:59:47 +1100107 SHA1_Init(&ctx);
108 SHA1_Update(&ctx, username, strlen(username));
109 SHA1_End(&ctx, up);
110
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000111 /* Collapse the hash */
112 ptr = hash_collapse(up);
113 memset(up, 0, strlen(up));
114
115 /* See if the random file's there, else use ctime */
116 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
117 && fstat(fd, &sb) == 0 &&
118 sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
119 lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
120 SEEK_SET) != -1 && read(fd, hseed,
121 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
122 close(fd);
Damien Miller037a0dc1999-12-07 15:38:31 +1100123 fd = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000124 secret = hseed;
125 secretlen = SKEY_MAX_SEED_LEN;
126 flg = 0;
127 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
128 t = sb.st_ctime;
129 secret = ctime(&t);
130 secretlen = strlen(secret);
131 flg = 0;
132 }
Damien Miller037a0dc1999-12-07 15:38:31 +1100133 if (fd != -1)
134 close(fd);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000135 }
136
137 /* Put that in your pipe and smoke it */
138 if (flg == 0) {
139 /* Hash secret value with username */
Damien Miller25e42562000-01-11 10:59:47 +1100140 SHA1_Init(&ctx);
141 SHA1_Update(&ctx, secret, secretlen);
142 SHA1_Update(&ctx, username, strlen(username));
143 SHA1_End(&ctx, up);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000144
145 /* Zero out */
146 memset(secret, 0, secretlen);
147
148 /* Now hash the hash */
Damien Miller25e42562000-01-11 10:59:47 +1100149 SHA1_Init(&ctx);
150 SHA1_Update(&ctx, up, strlen(up));
151 SHA1_End(&ctx, up);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000152
153 ptr = hash_collapse(up + 4);
154
155 for (i = 4; i < 9; i++) {
156 pbuf[i] = (ptr % 10) + '0';
157 ptr /= 10;
158 }
159 pbuf[i] = '\0';
160
161 /* Sequence number */
162 ptr = ((up[2] + up[3]) % 99) + 1;
163
Damien Miller25e42562000-01-11 10:59:47 +1100164 memset(up, 0, SHA_DIGEST_LENGTH); /* SHA1 specific */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000165 free(up);
166
167 (void)snprintf(skeyprompt, sizeof skeyprompt,
168 "otp-%.*s %d %.*s",
169 SKEY_MAX_HASHNAME_LEN,
170 skey_get_algorithm(),
171 ptr, SKEY_MAX_SEED_LEN,
172 pbuf);
173 } else {
174 /* Base last 8 chars of seed on username */
175 u = username;
176 i = 8;
177 p = &pbuf[4];
178 do {
179 if (*u == 0) {
180 /* Pad remainder with zeros */
181 while (--i >= 0)
182 *p++ = '0';
183 break;
184 }
185
186 *p++ = (*u++ % 10) + '0';
187 } while (--i != 0);
188 pbuf[12] = '\0';
189
190 (void)snprintf(skeyprompt, sizeof skeyprompt,
191 "otp-%.*s %d %.*s",
192 SKEY_MAX_HASHNAME_LEN,
193 skey_get_algorithm(),
194 99, SKEY_MAX_SEED_LEN, pbuf);
195 }
196 return skeyprompt;
197}
Damien Miller80297751999-11-19 13:03:25 +1100198
Damien Miller95def091999-11-25 00:26:21 +1100199#endif /* SKEY */