]> andersk Git - openssh.git/blame - auth-skey.c
- (djm) Use standard OpenSSL functions in auth-skey.c. Patch from
[openssh.git] / auth-skey.c
CommitLineData
5260325f 1#include "includes.h"
91b8065d 2#ifdef SKEY
74fc9186 3RCSID("$OpenBSD: auth-skey.c,v 1.7 2000/06/20 01:39:38 markus Exp $");
8efc0c15 4
5#include "ssh.h"
57112b5a 6#include "packet.h"
a4070484 7#include <openssl/sha.h>
8efc0c15 8
9/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
10
6ae2364d 11/*
57112b5a 12 * try skey authentication,
6ae2364d 13 * return 1 on success, 0 on failure, -1 if skey is not available
57112b5a 14 */
15
6ae2364d 16int
57112b5a 17auth_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}
59625cbb 38
39/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
8efc0c15 40
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)
6ae2364d 49 u_char *s;
8efc0c15 50{
6ae2364d 51 int len, target;
8efc0c15 52 u_int32_t i;
53
54 if ((strlen(s) % sizeof(u_int32_t)) == 0)
6ae2364d 55 target = strlen(s); /* Multiple of 4 */
8efc0c15 56 else
57 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
6ae2364d 58
8efc0c15 59 for (i = 0, len = 0; len < target; len += 4)
6ae2364d 60 i ^= ROUND(s + len);
8efc0c15 61
62 return i;
63}
5260325f 64
8efc0c15 65char *
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;
2598df62 75 SHA_CTX ctx;
8efc0c15 76 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 */
2598df62 93 up = malloc(SHA_DIGEST_LENGTH);
94 if (up != NULL) {
8efc0c15 95 struct stat sb;
96 time_t t;
97 int fd;
98
2598df62 99 SHA1_Init(&ctx);
100 SHA1_Update(&ctx, username, strlen(username));
a4070484 101 SHA1_Final(up, &ctx);
2598df62 102
8efc0c15 103 /* 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);
a408af76 115 fd = -1;
8efc0c15 116 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 }
a408af76 125 if (fd != -1)
126 close(fd);
8efc0c15 127 }
128
129 /* Put that in your pipe and smoke it */
130 if (flg == 0) {
131 /* Hash secret value with username */
2598df62 132 SHA1_Init(&ctx);
133 SHA1_Update(&ctx, secret, secretlen);
134 SHA1_Update(&ctx, username, strlen(username));
a4070484 135 SHA1_Final(up, &ctx);
8efc0c15 136
137 /* Zero out */
138 memset(secret, 0, secretlen);
139
140 /* Now hash the hash */
2598df62 141 SHA1_Init(&ctx);
142 SHA1_Update(&ctx, up, strlen(up));
a4070484 143 SHA1_Final(up, &ctx);
8efc0c15 144
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
2598df62 156 memset(up, 0, SHA_DIGEST_LENGTH); /* SHA1 specific */
8efc0c15 157 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}
91b8065d 190
5260325f 191#endif /* SKEY */
This page took 0.314508 seconds and 5 git commands to generate.