]> andersk Git - openssh.git/blob - auth-skey.c
- Added autoconf option to enable Kerberos 4 support (untested)
[openssh.git] / auth-skey.c
1 #ifdef SKEY
2
3 #include "includes.h"
4 RCSID("$Id$");
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  */
18 static u_int32_t
19 hash_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 }
35 char *
36 skey_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 }
152
153 #endif SKEY
This page took 1.178404 seconds and 5 git commands to generate.