diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
commit | 95def09838fc61b37b6ea7cd5c234a465b4b129b (patch) | |
tree | 042744f76f40a326b873cb1c3690a6d7d966bc3e /authfile.c | |
parent | 4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff) |
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates
- [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
[ssh.h sshd.8 sshd.c]
syslog changes:
* Unified Logmessage for all auth-types, for success and for failed
* Standard connections get only ONE line in the LOG when level==LOG:
Auth-attempts are logged only, if authentication is:
a) successfull or
b) with passwd or
c) we had more than AUTH_FAIL_LOG failues
* many log() became verbose()
* old behaviour with level=VERBOSE
- [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
messages. allows use of s/key in windows (ttssh, securecrt) and
ssh-1.2.27 clients without 'ssh -v', ok: niels@
- [sshd.8]
-V, for fallback to openssh in SSH2 compatibility mode
- [sshd.c]
fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 597 |
1 files changed, 291 insertions, 306 deletions
diff --git a/authfile.c b/authfile.c index 0e77edf99..35a05d389 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,21 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | 2 | * | |
3 | authfile.c | 3 | * authfile.c |
4 | 4 | * | |
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> | 5 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
6 | 6 | * | |
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 7 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
8 | All rights reserved | 8 | * All rights reserved |
9 | 9 | * | |
10 | Created: Mon Mar 27 03:52:05 1995 ylo | 10 | * Created: Mon Mar 27 03:52:05 1995 ylo |
11 | 11 | * | |
12 | This file contains functions for reading and writing identity files, and | 12 | * This file contains functions for reading and writing identity files, and |
13 | for reading the passphrase from the user. | 13 | * for reading the passphrase from the user. |
14 | 14 | * | |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "includes.h" | 17 | #include "includes.h" |
18 | RCSID("$Id: authfile.c,v 1.3 1999/11/13 02:07:45 damien Exp $"); | 18 | RCSID("$Id: authfile.c,v 1.4 1999/11/24 13:26:22 damien Exp $"); |
19 | 19 | ||
20 | #ifdef HAVE_OPENSSL | 20 | #ifdef HAVE_OPENSSL |
21 | #include <openssl/bn.h> | 21 | #include <openssl/bn.h> |
@@ -42,93 +42,93 @@ int | |||
42 | save_private_key(const char *filename, const char *passphrase, | 42 | save_private_key(const char *filename, const char *passphrase, |
43 | RSA *key, const char *comment) | 43 | RSA *key, const char *comment) |
44 | { | 44 | { |
45 | Buffer buffer, encrypted; | 45 | Buffer buffer, encrypted; |
46 | char buf[100], *cp; | 46 | char buf[100], *cp; |
47 | int f, i; | 47 | int f, i; |
48 | CipherContext cipher; | 48 | CipherContext cipher; |
49 | int cipher_type; | 49 | int cipher_type; |
50 | u_int32_t rand; | 50 | u_int32_t rand; |
51 | 51 | ||
52 | /* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to | 52 | /* If the passphrase is empty, use SSH_CIPHER_NONE to ease |
53 | another cipher; otherwise use SSH_AUTHFILE_CIPHER. */ | 53 | converting to another cipher; otherwise use |
54 | if (strcmp(passphrase, "") == 0) | 54 | SSH_AUTHFILE_CIPHER. */ |
55 | cipher_type = SSH_CIPHER_NONE; | 55 | if (strcmp(passphrase, "") == 0) |
56 | else | 56 | cipher_type = SSH_CIPHER_NONE; |
57 | cipher_type = SSH_AUTHFILE_CIPHER; | 57 | else |
58 | 58 | cipher_type = SSH_AUTHFILE_CIPHER; | |
59 | /* This buffer is used to built the secret part of the private key. */ | 59 | |
60 | buffer_init(&buffer); | 60 | /* This buffer is used to built the secret part of the private key. */ |
61 | 61 | buffer_init(&buffer); | |
62 | /* Put checkbytes for checking passphrase validity. */ | 62 | |
63 | rand = arc4random(); | 63 | /* Put checkbytes for checking passphrase validity. */ |
64 | buf[0] = rand & 0xff; | 64 | rand = arc4random(); |
65 | buf[1] = (rand >> 8) & 0xff; | 65 | buf[0] = rand & 0xff; |
66 | buf[2] = buf[0]; | 66 | buf[1] = (rand >> 8) & 0xff; |
67 | buf[3] = buf[1]; | 67 | buf[2] = buf[0]; |
68 | buffer_append(&buffer, buf, 4); | 68 | buf[3] = buf[1]; |
69 | 69 | buffer_append(&buffer, buf, 4); | |
70 | /* Store the private key (n and e will not be stored because they will | 70 | |
71 | be stored in plain text, and storing them also in encrypted format | 71 | /* Store the private key (n and e will not be stored because they |
72 | would just give known plaintext). */ | 72 | will be stored in plain text, and storing them also in |
73 | buffer_put_bignum(&buffer, key->d); | 73 | encrypted format would just give known plaintext). */ |
74 | buffer_put_bignum(&buffer, key->iqmp); | 74 | buffer_put_bignum(&buffer, key->d); |
75 | buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ | 75 | buffer_put_bignum(&buffer, key->iqmp); |
76 | buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ | 76 | buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ |
77 | 77 | buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ | |
78 | /* Pad the part to be encrypted until its size is a multiple of 8. */ | 78 | |
79 | while (buffer_len(&buffer) % 8 != 0) | 79 | /* Pad the part to be encrypted until its size is a multiple of 8. */ |
80 | buffer_put_char(&buffer, 0); | 80 | while (buffer_len(&buffer) % 8 != 0) |
81 | 81 | buffer_put_char(&buffer, 0); | |
82 | /* This buffer will be used to contain the data in the file. */ | 82 | |
83 | buffer_init(&encrypted); | 83 | /* This buffer will be used to contain the data in the file. */ |
84 | 84 | buffer_init(&encrypted); | |
85 | /* First store keyfile id string. */ | 85 | |
86 | cp = AUTHFILE_ID_STRING; | 86 | /* First store keyfile id string. */ |
87 | for (i = 0; cp[i]; i++) | 87 | cp = AUTHFILE_ID_STRING; |
88 | buffer_put_char(&encrypted, cp[i]); | 88 | for (i = 0; cp[i]; i++) |
89 | buffer_put_char(&encrypted, 0); | 89 | buffer_put_char(&encrypted, cp[i]); |
90 | 90 | buffer_put_char(&encrypted, 0); | |
91 | /* Store cipher type. */ | 91 | |
92 | buffer_put_char(&encrypted, cipher_type); | 92 | /* Store cipher type. */ |
93 | buffer_put_int(&encrypted, 0); /* For future extension */ | 93 | buffer_put_char(&encrypted, cipher_type); |
94 | 94 | buffer_put_int(&encrypted, 0); /* For future extension */ | |
95 | /* Store public key. This will be in plain text. */ | 95 | |
96 | buffer_put_int(&encrypted, BN_num_bits(key->n)); | 96 | /* Store public key. This will be in plain text. */ |
97 | buffer_put_bignum(&encrypted, key->n); | 97 | buffer_put_int(&encrypted, BN_num_bits(key->n)); |
98 | buffer_put_bignum(&encrypted, key->e); | 98 | buffer_put_bignum(&encrypted, key->n); |
99 | buffer_put_string(&encrypted, comment, strlen(comment)); | 99 | buffer_put_bignum(&encrypted, key->e); |
100 | 100 | buffer_put_string(&encrypted, comment, strlen(comment)); | |
101 | /* Allocate space for the private part of the key in the buffer. */ | 101 | |
102 | buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); | 102 | /* Allocate space for the private part of the key in the buffer. */ |
103 | 103 | buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); | |
104 | cipher_set_key_string(&cipher, cipher_type, passphrase, 1); | 104 | |
105 | cipher_encrypt(&cipher, (unsigned char *)cp, | 105 | cipher_set_key_string(&cipher, cipher_type, passphrase, 1); |
106 | (unsigned char *)buffer_ptr(&buffer), | 106 | cipher_encrypt(&cipher, (unsigned char *) cp, |
107 | buffer_len(&buffer)); | 107 | (unsigned char *) buffer_ptr(&buffer), |
108 | memset(&cipher, 0, sizeof(cipher)); | 108 | buffer_len(&buffer)); |
109 | 109 | memset(&cipher, 0, sizeof(cipher)); | |
110 | /* Destroy temporary data. */ | 110 | |
111 | memset(buf, 0, sizeof(buf)); | 111 | /* Destroy temporary data. */ |
112 | buffer_free(&buffer); | 112 | memset(buf, 0, sizeof(buf)); |
113 | 113 | buffer_free(&buffer); | |
114 | /* Write to a file. */ | 114 | |
115 | f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600); | 115 | /* Write to a file. */ |
116 | if (f < 0) | 116 | f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
117 | return 0; | 117 | if (f < 0) |
118 | 118 | return 0; | |
119 | if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) != | 119 | |
120 | buffer_len(&encrypted)) | 120 | if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) != |
121 | { | 121 | buffer_len(&encrypted)) { |
122 | debug("Write to key file %.200s failed: %.100s", filename, | 122 | debug("Write to key file %.200s failed: %.100s", filename, |
123 | strerror(errno)); | 123 | strerror(errno)); |
124 | buffer_free(&encrypted); | 124 | buffer_free(&encrypted); |
125 | close(f); | 125 | close(f); |
126 | remove(filename); | 126 | remove(filename); |
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | close(f); | 129 | close(f); |
130 | buffer_free(&encrypted); | 130 | buffer_free(&encrypted); |
131 | return 1; | 131 | return 1; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* Loads the public part of the key file. Returns 0 if an error | 134 | /* Loads the public part of the key file. Returns 0 if an error |
@@ -136,70 +136,65 @@ save_private_key(const char *filename, const char *passphrase, | |||
136 | non-zero otherwise. */ | 136 | non-zero otherwise. */ |
137 | 137 | ||
138 | int | 138 | int |
139 | load_public_key(const char *filename, RSA *pub, | 139 | load_public_key(const char *filename, RSA * pub, |
140 | char **comment_return) | 140 | char **comment_return) |
141 | { | 141 | { |
142 | int f, i; | 142 | int f, i; |
143 | off_t len; | 143 | off_t len; |
144 | Buffer buffer; | 144 | Buffer buffer; |
145 | char *cp; | 145 | char *cp; |
146 | 146 | ||
147 | /* Read data from the file into the buffer. */ | 147 | /* Read data from the file into the buffer. */ |
148 | f = open(filename, O_RDONLY); | 148 | f = open(filename, O_RDONLY); |
149 | if (f < 0) | 149 | if (f < 0) |
150 | return 0; | 150 | return 0; |
151 | 151 | ||
152 | len = lseek(f, (off_t)0, SEEK_END); | 152 | len = lseek(f, (off_t) 0, SEEK_END); |
153 | lseek(f, (off_t)0, SEEK_SET); | 153 | lseek(f, (off_t) 0, SEEK_SET); |
154 | 154 | ||
155 | buffer_init(&buffer); | 155 | buffer_init(&buffer); |
156 | buffer_append_space(&buffer, &cp, len); | 156 | buffer_append_space(&buffer, &cp, len); |
157 | 157 | ||
158 | if (read(f, cp, (size_t)len) != (size_t)len) | 158 | if (read(f, cp, (size_t) len) != (size_t) len) { |
159 | { | 159 | debug("Read from key file %.200s failed: %.100s", filename, |
160 | debug("Read from key file %.200s failed: %.100s", filename, | 160 | strerror(errno)); |
161 | strerror(errno)); | 161 | buffer_free(&buffer); |
162 | buffer_free(&buffer); | 162 | close(f); |
163 | close(f); | 163 | return 0; |
164 | return 0; | 164 | } |
165 | } | 165 | close(f); |
166 | close(f); | 166 | |
167 | 167 | /* Check that it is at least big enought to contain the ID string. */ | |
168 | /* Check that it is at least big enought to contain the ID string. */ | 168 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { |
169 | if (len < strlen(AUTHFILE_ID_STRING) + 1) | 169 | debug("Bad key file %.200s.", filename); |
170 | { | 170 | buffer_free(&buffer); |
171 | debug("Bad key file %.200s.", filename); | 171 | return 0; |
172 | buffer_free(&buffer); | 172 | } |
173 | return 0; | 173 | /* Make sure it begins with the id string. Consume the id string |
174 | } | 174 | from the buffer. */ |
175 | 175 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) | |
176 | /* Make sure it begins with the id string. Consume the id string from | 176 | if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { |
177 | the buffer. */ | 177 | debug("Bad key file %.200s.", filename); |
178 | for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++) | 178 | buffer_free(&buffer); |
179 | if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i]) | 179 | return 0; |
180 | { | 180 | } |
181 | debug("Bad key file %.200s.", filename); | 181 | /* Skip cipher type and reserved data. */ |
182 | (void) buffer_get_char(&buffer); /* cipher type */ | ||
183 | (void) buffer_get_int(&buffer); /* reserved */ | ||
184 | |||
185 | /* Read the public key from the buffer. */ | ||
186 | buffer_get_int(&buffer); | ||
187 | pub->n = BN_new(); | ||
188 | buffer_get_bignum(&buffer, pub->n); | ||
189 | pub->e = BN_new(); | ||
190 | buffer_get_bignum(&buffer, pub->e); | ||
191 | if (comment_return) | ||
192 | *comment_return = buffer_get_string(&buffer, NULL); | ||
193 | /* The encrypted private part is not parsed by this function. */ | ||
194 | |||
182 | buffer_free(&buffer); | 195 | buffer_free(&buffer); |
183 | return 0; | 196 | |
184 | } | 197 | return 1; |
185 | |||
186 | /* Skip cipher type and reserved data. */ | ||
187 | (void)buffer_get_char(&buffer); /* cipher type */ | ||
188 | (void)buffer_get_int(&buffer); /* reserved */ | ||
189 | |||
190 | /* Read the public key from the buffer. */ | ||
191 | buffer_get_int(&buffer); | ||
192 | pub->n = BN_new(); | ||
193 | buffer_get_bignum(&buffer, pub->n); | ||
194 | pub->e = BN_new(); | ||
195 | buffer_get_bignum(&buffer, pub->e); | ||
196 | if (comment_return) | ||
197 | *comment_return = buffer_get_string(&buffer, NULL); | ||
198 | /* The encrypted private part is not parsed by this function. */ | ||
199 | |||
200 | buffer_free(&buffer); | ||
201 | |||
202 | return 1; | ||
203 | } | 198 | } |
204 | 199 | ||
205 | /* Loads the private key from the file. Returns 0 if an error is encountered | 200 | /* Loads the private key from the file. Returns 0 if an error is encountered |
@@ -208,149 +203,139 @@ load_public_key(const char *filename, RSA *pub, | |||
208 | 203 | ||
209 | int | 204 | int |
210 | load_private_key(const char *filename, const char *passphrase, | 205 | load_private_key(const char *filename, const char *passphrase, |
211 | RSA *prv, char **comment_return) | 206 | RSA * prv, char **comment_return) |
212 | { | 207 | { |
213 | int f, i, check1, check2, cipher_type; | 208 | int f, i, check1, check2, cipher_type; |
214 | off_t len; | 209 | off_t len; |
215 | Buffer buffer, decrypted; | 210 | Buffer buffer, decrypted; |
216 | char *cp; | 211 | char *cp; |
217 | CipherContext cipher; | 212 | CipherContext cipher; |
218 | BN_CTX *ctx; | 213 | BN_CTX *ctx; |
219 | BIGNUM *aux; | 214 | BIGNUM *aux; |
220 | struct stat st; | 215 | struct stat st; |
221 | 216 | ||
222 | /* Read the file into the buffer. */ | 217 | /* Read the file into the buffer. */ |
223 | f = open(filename, O_RDONLY); | 218 | f = open(filename, O_RDONLY); |
224 | if (f < 0) | 219 | if (f < 0) |
225 | return 0; | 220 | return 0; |
226 | 221 | ||
227 | /* We assume we are called under uid of the owner of the file */ | 222 | /* We assume we are called under uid of the owner of the file */ |
228 | if (fstat(f, &st) < 0 || | 223 | if (fstat(f, &st) < 0 || |
229 | (st.st_uid != 0 && st.st_uid != getuid()) || | 224 | (st.st_uid != 0 && st.st_uid != getuid()) || |
230 | (st.st_mode & 077) != 0) { | 225 | (st.st_mode & 077) != 0) { |
231 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | 226 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
232 | error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); | 227 | error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); |
233 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | 228 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
234 | error("Bad ownership or mode(0%3.3o) for '%s'.", | 229 | error("Bad ownership or mode(0%3.3o) for '%s'.", |
235 | st.st_mode & 0777, filename); | 230 | st.st_mode & 0777, filename); |
236 | error("It is recommended that your private key files are NOT accessible by others."); | 231 | error("It is recommended that your private key files are NOT accessible by others."); |
237 | return 0; | 232 | return 0; |
238 | } | 233 | } |
239 | 234 | len = lseek(f, (off_t) 0, SEEK_END); | |
240 | len = lseek(f, (off_t)0, SEEK_END); | 235 | lseek(f, (off_t) 0, SEEK_SET); |
241 | lseek(f, (off_t)0, SEEK_SET); | 236 | |
242 | 237 | buffer_init(&buffer); | |
243 | buffer_init(&buffer); | 238 | buffer_append_space(&buffer, &cp, len); |
244 | buffer_append_space(&buffer, &cp, len); | 239 | |
245 | 240 | if (read(f, cp, (size_t) len) != (size_t) len) { | |
246 | if (read(f, cp, (size_t)len) != (size_t)len) | 241 | debug("Read from key file %.200s failed: %.100s", filename, |
247 | { | 242 | strerror(errno)); |
248 | debug("Read from key file %.200s failed: %.100s", filename, | 243 | buffer_free(&buffer); |
249 | strerror(errno)); | 244 | close(f); |
250 | buffer_free(&buffer); | 245 | return 0; |
251 | close(f); | 246 | } |
252 | return 0; | 247 | close(f); |
253 | } | 248 | |
254 | close(f); | 249 | /* Check that it is at least big enought to contain the ID string. */ |
255 | 250 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { | |
256 | /* Check that it is at least big enought to contain the ID string. */ | 251 | debug("Bad key file %.200s.", filename); |
257 | if (len < strlen(AUTHFILE_ID_STRING) + 1) | 252 | buffer_free(&buffer); |
258 | { | 253 | return 0; |
259 | debug("Bad key file %.200s.", filename); | 254 | } |
260 | buffer_free(&buffer); | 255 | /* Make sure it begins with the id string. Consume the id string |
261 | return 0; | 256 | from the buffer. */ |
262 | } | 257 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) |
263 | 258 | if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { | |
264 | /* Make sure it begins with the id string. Consume the id string from | 259 | debug("Bad key file %.200s.", filename); |
265 | the buffer. */ | 260 | buffer_free(&buffer); |
266 | for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++) | 261 | return 0; |
267 | if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i]) | 262 | } |
268 | { | 263 | /* Read cipher type. */ |
269 | debug("Bad key file %.200s.", filename); | 264 | cipher_type = buffer_get_char(&buffer); |
265 | (void) buffer_get_int(&buffer); /* Reserved data. */ | ||
266 | |||
267 | /* Read the public key from the buffer. */ | ||
268 | buffer_get_int(&buffer); | ||
269 | prv->n = BN_new(); | ||
270 | buffer_get_bignum(&buffer, prv->n); | ||
271 | prv->e = BN_new(); | ||
272 | buffer_get_bignum(&buffer, prv->e); | ||
273 | if (comment_return) | ||
274 | *comment_return = buffer_get_string(&buffer, NULL); | ||
275 | else | ||
276 | xfree(buffer_get_string(&buffer, NULL)); | ||
277 | |||
278 | /* Check that it is a supported cipher. */ | ||
279 | if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & | ||
280 | (1 << cipher_type)) == 0) { | ||
281 | debug("Unsupported cipher %.100s used in key file %.200s.", | ||
282 | cipher_name(cipher_type), filename); | ||
283 | buffer_free(&buffer); | ||
284 | goto fail; | ||
285 | } | ||
286 | /* Initialize space for decrypted data. */ | ||
287 | buffer_init(&decrypted); | ||
288 | buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); | ||
289 | |||
290 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | ||
291 | cipher_set_key_string(&cipher, cipher_type, passphrase, 0); | ||
292 | cipher_decrypt(&cipher, (unsigned char *) cp, | ||
293 | (unsigned char *) buffer_ptr(&buffer), | ||
294 | buffer_len(&buffer)); | ||
295 | |||
270 | buffer_free(&buffer); | 296 | buffer_free(&buffer); |
271 | return 0; | 297 | |
272 | } | 298 | check1 = buffer_get_char(&decrypted); |
273 | 299 | check2 = buffer_get_char(&decrypted); | |
274 | /* Read cipher type. */ | 300 | if (check1 != buffer_get_char(&decrypted) || |
275 | cipher_type = buffer_get_char(&buffer); | 301 | check2 != buffer_get_char(&decrypted)) { |
276 | (void)buffer_get_int(&buffer); /* Reserved data. */ | 302 | if (strcmp(passphrase, "") != 0) |
277 | 303 | debug("Bad passphrase supplied for key file %.200s.", filename); | |
278 | /* Read the public key from the buffer. */ | 304 | /* Bad passphrase. */ |
279 | buffer_get_int(&buffer); | 305 | buffer_free(&decrypted); |
280 | prv->n = BN_new(); | 306 | fail: |
281 | buffer_get_bignum(&buffer, prv->n); | 307 | BN_clear_free(prv->n); |
282 | prv->e = BN_new(); | 308 | BN_clear_free(prv->e); |
283 | buffer_get_bignum(&buffer, prv->e); | 309 | if (comment_return) |
284 | if (comment_return) | 310 | xfree(*comment_return); |
285 | *comment_return = buffer_get_string(&buffer, NULL); | 311 | return 0; |
286 | else | 312 | } |
287 | xfree(buffer_get_string(&buffer, NULL)); | 313 | /* Read the rest of the private key. */ |
288 | 314 | prv->d = BN_new(); | |
289 | /* Check that it is a supported cipher. */ | 315 | buffer_get_bignum(&decrypted, prv->d); |
290 | if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & | 316 | prv->iqmp = BN_new(); |
291 | (1 << cipher_type)) == 0) | 317 | buffer_get_bignum(&decrypted, prv->iqmp); /* u */ |
292 | { | 318 | /* in SSL and SSH p and q are exchanged */ |
293 | debug("Unsupported cipher %.100s used in key file %.200s.", | 319 | prv->q = BN_new(); |
294 | cipher_name(cipher_type), filename); | 320 | buffer_get_bignum(&decrypted, prv->q); /* p */ |
295 | buffer_free(&buffer); | 321 | prv->p = BN_new(); |
296 | goto fail; | 322 | buffer_get_bignum(&decrypted, prv->p); /* q */ |
297 | } | 323 | |
298 | 324 | ctx = BN_CTX_new(); | |
299 | /* Initialize space for decrypted data. */ | 325 | aux = BN_new(); |
300 | buffer_init(&decrypted); | 326 | |
301 | buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); | 327 | BN_sub(aux, prv->q, BN_value_one()); |
302 | 328 | prv->dmq1 = BN_new(); | |
303 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | 329 | BN_mod(prv->dmq1, prv->d, aux, ctx); |
304 | cipher_set_key_string(&cipher, cipher_type, passphrase, 0); | 330 | |
305 | cipher_decrypt(&cipher, (unsigned char *)cp, | 331 | BN_sub(aux, prv->p, BN_value_one()); |
306 | (unsigned char *)buffer_ptr(&buffer), | 332 | prv->dmp1 = BN_new(); |
307 | buffer_len(&buffer)); | 333 | BN_mod(prv->dmp1, prv->d, aux, ctx); |
308 | 334 | ||
309 | buffer_free(&buffer); | 335 | BN_clear_free(aux); |
310 | 336 | BN_CTX_free(ctx); | |
311 | check1 = buffer_get_char(&decrypted); | 337 | |
312 | check2 = buffer_get_char(&decrypted); | 338 | buffer_free(&decrypted); |
313 | if (check1 != buffer_get_char(&decrypted) || | 339 | |
314 | check2 != buffer_get_char(&decrypted)) | 340 | return 1; |
315 | { | ||
316 | if (strcmp(passphrase, "") != 0) | ||
317 | debug("Bad passphrase supplied for key file %.200s.", filename); | ||
318 | /* Bad passphrase. */ | ||
319 | buffer_free(&decrypted); | ||
320 | fail: | ||
321 | BN_clear_free(prv->n); | ||
322 | BN_clear_free(prv->e); | ||
323 | if (comment_return) | ||
324 | xfree(*comment_return); | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /* Read the rest of the private key. */ | ||
329 | prv->d = BN_new(); | ||
330 | buffer_get_bignum(&decrypted, prv->d); | ||
331 | prv->iqmp = BN_new(); | ||
332 | buffer_get_bignum(&decrypted, prv->iqmp); /* u */ | ||
333 | /* in SSL and SSH p and q are exchanged */ | ||
334 | prv->q = BN_new(); | ||
335 | buffer_get_bignum(&decrypted, prv->q); /* p */ | ||
336 | prv->p = BN_new(); | ||
337 | buffer_get_bignum(&decrypted, prv->p); /* q */ | ||
338 | |||
339 | ctx = BN_CTX_new(); | ||
340 | aux = BN_new(); | ||
341 | |||
342 | BN_sub(aux, prv->q, BN_value_one()); | ||
343 | prv->dmq1 = BN_new(); | ||
344 | BN_mod(prv->dmq1, prv->d, aux, ctx); | ||
345 | |||
346 | BN_sub(aux, prv->p, BN_value_one()); | ||
347 | prv->dmp1 = BN_new(); | ||
348 | BN_mod(prv->dmp1, prv->d, aux, ctx); | ||
349 | |||
350 | BN_clear_free(aux); | ||
351 | BN_CTX_free(ctx); | ||
352 | |||
353 | buffer_free(&decrypted); | ||
354 | |||
355 | return 1; | ||
356 | } | 341 | } |