]> andersk Git - openssh.git/blob - auth-skey.c
- (djm) Sync with OpenBSD:
[openssh.git] / auth-skey.c
1 /*
2  * Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26 RCSID("$OpenBSD: auth-skey.c,v 1.9 2000/10/19 16:41:13 deraadt Exp $");
27
28 #ifdef SKEY
29 #include "ssh.h"
30 #include "packet.h"
31 #include <openssl/sha.h>
32
33 /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
34
35 /*
36  * try skey authentication,
37  * return 1 on success, 0 on failure, -1 if skey is not available
38  */
39
40 int
41 auth_skey_password(struct passwd * pw, const char *password)
42 {
43         if (strncasecmp(password, "s/key", 5) == 0) {
44                 char *skeyinfo = skey_keyinfo(pw->pw_name);
45                 if (skeyinfo == NULL) {
46                         debug("generating fake skeyinfo for %.100s.",
47                             pw->pw_name);
48                         skeyinfo = skey_fake_keyinfo(pw->pw_name);
49                 }
50                 if (skeyinfo != NULL)
51                         packet_send_debug("%s", skeyinfo);
52                 /* Try again. */
53                 return 0;
54         } else if (skey_haskey(pw->pw_name) == 0 &&
55                    skey_passcheck(pw->pw_name, (char *) password) != -1) {
56                 /* Authentication succeeded. */
57                 return 1;
58         }
59         /* Fall back to ordinary passwd authentication. */
60         return -1;
61 }
62
63 /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
64
65 #define ROUND(x)   (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
66                     ((x)[3]))
67
68 /*
69  * hash_collapse()
70  */
71 static u_int32_t
72 hash_collapse(s)
73         u_char *s;
74 {
75         int len, target;
76         u_int32_t i;
77         
78         if ((strlen(s) % sizeof(u_int32_t)) == 0)
79                 target = strlen(s);    /* Multiple of 4 */
80         else
81                 target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
82
83         for (i = 0, len = 0; len < target; len += 4)
84                 i ^= ROUND(s + len);
85
86         return i;
87 }
88
89 char *
90 skey_fake_keyinfo(char *username)
91 {
92         int i;
93         u_int ptr;
94         u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
95         char pbuf[SKEY_MAX_PW_LEN+1];
96         static char skeyprompt[SKEY_MAX_CHALLENGE+1];
97         char *secret = NULL;
98         size_t secretlen = 0;
99         SHA_CTX ctx;
100         char *p, *u;
101
102         /*
103          * Base first 4 chars of seed on hostname.
104          * Add some filler for short hostnames if necessary.
105          */
106         if (gethostname(pbuf, sizeof(pbuf)) == -1)
107                 *(p = pbuf) = '.';
108         else
109                 for (p = pbuf; *p && isalnum(*p); p++)
110                         if (isalpha(*p) && isupper(*p))
111                                 *p = tolower(*p);
112         if (*p && pbuf - p < 4)
113                 (void)strncpy(p, "asjd", 4 - (pbuf - p));
114         pbuf[4] = '\0';
115
116         /* Hash the username if possible */
117         up = malloc(SHA_DIGEST_LENGTH);
118         if (up != NULL) {
119                 struct stat sb;
120                 time_t t;
121                 int fd;
122
123                 SHA1_Init(&ctx);
124                 SHA1_Update(&ctx, username, strlen(username));
125                 SHA1_Final(up, &ctx);
126
127                 /* Collapse the hash */
128                 ptr = hash_collapse(up);
129                 memset(up, 0, strlen(up));
130
131                 /* See if the random file's there, else use ctime */
132                 if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
133                     && fstat(fd, &sb) == 0 &&
134                     sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
135                     lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
136                     SEEK_SET) != -1 && read(fd, hseed,
137                     SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
138                         close(fd);
139                         fd = -1;
140                         secret = hseed;
141                         secretlen = SKEY_MAX_SEED_LEN;
142                         flg = 0;
143                 } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
144                         t = sb.st_ctime;
145                         secret = ctime(&t);
146                         secretlen = strlen(secret);
147                         flg = 0;
148                 }
149                 if (fd != -1)
150                         close(fd);
151         }
152
153         /* Put that in your pipe and smoke it */
154         if (flg == 0) {
155                 /* Hash secret value with username */
156                 SHA1_Init(&ctx);
157                 SHA1_Update(&ctx, secret, secretlen);
158                 SHA1_Update(&ctx, username, strlen(username));
159                 SHA1_Final(up, &ctx);
160                 
161                 /* Zero out */
162                 memset(secret, 0, secretlen);
163
164                 /* Now hash the hash */
165                 SHA1_Init(&ctx);
166                 SHA1_Update(&ctx, up, strlen(up));
167                 SHA1_Final(up, &ctx);
168                 
169                 ptr = hash_collapse(up + 4);
170                 
171                 for (i = 4; i < 9; i++) {
172                         pbuf[i] = (ptr % 10) + '0';
173                         ptr /= 10;
174                 }
175                 pbuf[i] = '\0';
176
177                 /* Sequence number */
178                 ptr = ((up[2] + up[3]) % 99) + 1;
179
180                 memset(up, 0, SHA_DIGEST_LENGTH); /* SHA1 specific */
181                 free(up);
182
183                 (void)snprintf(skeyprompt, sizeof skeyprompt,
184                               "otp-%.*s %d %.*s",
185                               SKEY_MAX_HASHNAME_LEN,
186                               skey_get_algorithm(),
187                               ptr, SKEY_MAX_SEED_LEN,
188                               pbuf);
189         } else {
190                 /* Base last 8 chars of seed on username */
191                 u = username;
192                 i = 8;
193                 p = &pbuf[4];
194                 do {
195                         if (*u == 0) {
196                                 /* Pad remainder with zeros */
197                                 while (--i >= 0)
198                                         *p++ = '0';
199                                 break;
200                         }
201
202                         *p++ = (*u++ % 10) + '0';
203                 } while (--i != 0);
204                 pbuf[12] = '\0';
205
206                 (void)snprintf(skeyprompt, sizeof skeyprompt,
207                               "otp-%.*s %d %.*s",
208                               SKEY_MAX_HASHNAME_LEN,
209                               skey_get_algorithm(),
210                               99, SKEY_MAX_SEED_LEN, pbuf);
211         }
212         return skeyprompt;
213 }
214
215 #endif /* SKEY */
This page took 0.127672 seconds and 5 git commands to generate.