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