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