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