]> andersk Git - openssh.git/blob - auth-skey.c
- Fixes to auth-skey to enable it to use the standard OpenSSL libraries
[openssh.git] / auth-skey.c
1 #include "includes.h"
2
3 #ifdef SKEY
4 RCSID("$Id$");
5
6 #include "ssh.h"
7 #include "packet.h"
8
9 #ifdef HAVE_OPENSSL
10 #include <openssl/sha.h>
11 #endif
12 #ifdef HAVE_SSL
13 #include <ssl/sha.h>
14 #endif
15
16 /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
17
18 /* 
19  * try skey authentication,
20  * return 1 on success, 0 on failure, -1 if skey is not available 
21  */
22
23 int 
24 auth_skey_password(struct passwd * pw, const char *password)
25 {
26         if (strncasecmp(password, "s/key", 5) == 0) {
27                 char *skeyinfo = skey_keyinfo(pw->pw_name);
28                 if (skeyinfo == NULL) {
29                         debug("generating fake skeyinfo for %.100s.",
30                             pw->pw_name);
31                         skeyinfo = skey_fake_keyinfo(pw->pw_name);
32                 }
33                 if (skeyinfo != NULL)
34                         packet_send_debug(skeyinfo);
35                 /* Try again. */
36                 return 0;
37         } else if (skey_haskey(pw->pw_name) == 0 &&
38                    skey_passcheck(pw->pw_name, (char *) password) != -1) {
39                 /* Authentication succeeded. */
40                 return 1;
41         }
42         /* Fall back to ordinary passwd authentication. */
43         return -1;
44 }
45
46 /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
47
48 #define ROUND(x)   (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
49                     ((x)[3]))
50
51 /*
52  * hash_collapse()
53  */
54 static u_int32_t
55 hash_collapse(s)
56         u_char *s;
57 {
58         int len, target;
59         u_int32_t i;
60         
61         if ((strlen(s) % sizeof(u_int32_t)) == 0)
62                 target = strlen(s);    /* Multiple of 4 */
63         else
64                 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
65   
66         for (i = 0, len = 0; len < target; len += 4)
67                 i ^= ROUND(s + len);
68
69         return i;
70 }
71
72 char *
73 skey_fake_keyinfo(char *username)
74 {
75         int i;
76         u_int ptr;
77         u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
78         char pbuf[SKEY_MAX_PW_LEN+1];
79         static char skeyprompt[SKEY_MAX_CHALLENGE+1];
80         char *secret = NULL;
81         size_t secretlen = 0;
82         SHA_CTX ctx;
83         char *p, *u;
84         char md[SHA_DIGEST_LENGTH];
85
86         /*
87          * Base first 4 chars of seed on hostname.
88          * Add some filler for short hostnames if necessary.
89          */
90         if (gethostname(pbuf, sizeof(pbuf)) == -1)
91                 *(p = pbuf) = '.';
92         else
93                 for (p = pbuf; *p && isalnum(*p); p++)
94                         if (isalpha(*p) && isupper(*p))
95                                 *p = tolower(*p);
96         if (*p && pbuf - p < 4)
97                 (void)strncpy(p, "asjd", 4 - (pbuf - p));
98         pbuf[4] = '\0';
99
100         /* Hash the username if possible */
101         up = malloc(SHA_DIGEST_LENGTH);
102         if (up != NULL) {
103                 struct stat sb;
104                 time_t t;
105                 int fd;
106
107                 SHA1_Init(&ctx);
108                 SHA1_Update(&ctx, username, strlen(username));
109                 SHA1_End(&ctx, up);
110
111                 /* Collapse the hash */
112                 ptr = hash_collapse(up);
113                 memset(up, 0, strlen(up));
114
115                 /* See if the random file's there, else use ctime */
116                 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
117                     && fstat(fd, &sb) == 0 &&
118                     sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
119                     lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
120                     SEEK_SET) != -1 && read(fd, hseed,
121                     SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
122                         close(fd);
123                         fd = -1;
124                         secret = hseed;
125                         secretlen = SKEY_MAX_SEED_LEN;
126                         flg = 0;
127                 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
128                         t = sb.st_ctime;
129                         secret = ctime(&t);
130                         secretlen = strlen(secret);
131                         flg = 0;
132                 }
133                 if (fd != -1)
134                         close(fd);
135         }
136
137         /* Put that in your pipe and smoke it */
138         if (flg == 0) {
139                 /* Hash secret value with username */
140                 SHA1_Init(&ctx);
141                 SHA1_Update(&ctx, secret, secretlen);
142                 SHA1_Update(&ctx, username, strlen(username));
143                 SHA1_End(&ctx, up);
144                 
145                 /* Zero out */
146                 memset(secret, 0, secretlen);
147
148                 /* Now hash the hash */
149                 SHA1_Init(&ctx);
150                 SHA1_Update(&ctx, up, strlen(up));
151                 SHA1_End(&ctx, up);
152                 
153                 ptr = hash_collapse(up + 4);
154                 
155                 for (i = 4; i < 9; i++) {
156                         pbuf[i] = (ptr % 10) + '0';
157                         ptr /= 10;
158                 }
159                 pbuf[i] = '\0';
160
161                 /* Sequence number */
162                 ptr = ((up[2] + up[3]) % 99) + 1;
163
164                 memset(up, 0, SHA_DIGEST_LENGTH); /* SHA1 specific */
165                 free(up);
166
167                 (void)snprintf(skeyprompt, sizeof skeyprompt,
168                               "otp-%.*s %d %.*s",
169                               SKEY_MAX_HASHNAME_LEN,
170                               skey_get_algorithm(),
171                               ptr, SKEY_MAX_SEED_LEN,
172                               pbuf);
173         } else {
174                 /* Base last 8 chars of seed on username */
175                 u = username;
176                 i = 8;
177                 p = &pbuf[4];
178                 do {
179                         if (*u == 0) {
180                                 /* Pad remainder with zeros */
181                                 while (--i >= 0)
182                                         *p++ = '0';
183                                 break;
184                         }
185
186                         *p++ = (*u++ % 10) + '0';
187                 } while (--i != 0);
188                 pbuf[12] = '\0';
189
190                 (void)snprintf(skeyprompt, sizeof skeyprompt,
191                               "otp-%.*s %d %.*s",
192                               SKEY_MAX_HASHNAME_LEN,
193                               skey_get_algorithm(),
194                               99, SKEY_MAX_SEED_LEN, pbuf);
195         }
196         return skeyprompt;
197 }
198
199 #endif /* SKEY */
This page took 0.057916 seconds and 5 git commands to generate.