blob: 66e09bb5912bc961ed9f4760f923d6f6ba3577dc [file] [log] [blame]
Damien Miller80297751999-11-19 13:03:25 +11001#ifdef SKEY
2
Damien Millerd4a8b7e1999-10-27 13:42:43 +10003#include "includes.h"
4RCSID("$Id: auth-skey.c,v 1.2 1999/10/16 20:57:52 deraadt Exp $");
5
6#include "ssh.h"
7#include <sha1.h>
8
9/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
10
11
12#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
13 ((x)[3]))
14
15/*
16 * hash_collapse()
17 */
18static u_int32_t
19hash_collapse(s)
20 u_char *s;
21{
22 int len, target;
23 u_int32_t i;
24
25 if ((strlen(s) % sizeof(u_int32_t)) == 0)
26 target = strlen(s); /* Multiple of 4 */
27 else
28 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
29
30 for (i = 0, len = 0; len < target; len += 4)
31 i ^= ROUND(s + len);
32
33 return i;
34}
35char *
36skey_fake_keyinfo(char *username)
37{
38 int i;
39 u_int ptr;
40 u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
41 char pbuf[SKEY_MAX_PW_LEN+1];
42 static char skeyprompt[SKEY_MAX_CHALLENGE+1];
43 char *secret = NULL;
44 size_t secretlen = 0;
45 SHA1_CTX ctx;
46 char *p, *u;
47
48 /*
49 * Base first 4 chars of seed on hostname.
50 * Add some filler for short hostnames if necessary.
51 */
52 if (gethostname(pbuf, sizeof(pbuf)) == -1)
53 *(p = pbuf) = '.';
54 else
55 for (p = pbuf; *p && isalnum(*p); p++)
56 if (isalpha(*p) && isupper(*p))
57 *p = tolower(*p);
58 if (*p && pbuf - p < 4)
59 (void)strncpy(p, "asjd", 4 - (pbuf - p));
60 pbuf[4] = '\0';
61
62 /* Hash the username if possible */
63 if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
64 struct stat sb;
65 time_t t;
66 int fd;
67
68 /* Collapse the hash */
69 ptr = hash_collapse(up);
70 memset(up, 0, strlen(up));
71
72 /* See if the random file's there, else use ctime */
73 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
74 && fstat(fd, &sb) == 0 &&
75 sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
76 lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
77 SEEK_SET) != -1 && read(fd, hseed,
78 SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
79 close(fd);
80 secret = hseed;
81 secretlen = SKEY_MAX_SEED_LEN;
82 flg = 0;
83 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
84 t = sb.st_ctime;
85 secret = ctime(&t);
86 secretlen = strlen(secret);
87 flg = 0;
88 }
89 }
90
91 /* Put that in your pipe and smoke it */
92 if (flg == 0) {
93 /* Hash secret value with username */
94 SHA1Init(&ctx);
95 SHA1Update(&ctx, secret, secretlen);
96 SHA1Update(&ctx, username, strlen(username));
97 SHA1End(&ctx, up);
98
99 /* Zero out */
100 memset(secret, 0, secretlen);
101
102 /* Now hash the hash */
103 SHA1Init(&ctx);
104 SHA1Update(&ctx, up, strlen(up));
105 SHA1End(&ctx, up);
106
107 ptr = hash_collapse(up + 4);
108
109 for (i = 4; i < 9; i++) {
110 pbuf[i] = (ptr % 10) + '0';
111 ptr /= 10;
112 }
113 pbuf[i] = '\0';
114
115 /* Sequence number */
116 ptr = ((up[2] + up[3]) % 99) + 1;
117
118 memset(up, 0, 20); /* SHA1 specific */
119 free(up);
120
121 (void)snprintf(skeyprompt, sizeof skeyprompt,
122 "otp-%.*s %d %.*s",
123 SKEY_MAX_HASHNAME_LEN,
124 skey_get_algorithm(),
125 ptr, SKEY_MAX_SEED_LEN,
126 pbuf);
127 } else {
128 /* Base last 8 chars of seed on username */
129 u = username;
130 i = 8;
131 p = &pbuf[4];
132 do {
133 if (*u == 0) {
134 /* Pad remainder with zeros */
135 while (--i >= 0)
136 *p++ = '0';
137 break;
138 }
139
140 *p++ = (*u++ % 10) + '0';
141 } while (--i != 0);
142 pbuf[12] = '\0';
143
144 (void)snprintf(skeyprompt, sizeof skeyprompt,
145 "otp-%.*s %d %.*s",
146 SKEY_MAX_HASHNAME_LEN,
147 skey_get_algorithm(),
148 99, SKEY_MAX_SEED_LEN, pbuf);
149 }
150 return skeyprompt;
151}
Damien Miller80297751999-11-19 13:03:25 +1100152
153#endif SKEY