diff options
author | Damien Miller <djm@mindrot.org> | 2000-04-29 23:57:08 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-04-29 23:57:08 +1000 |
commit | eba71bab9bf01c0d688f829a8971f902732558df (patch) | |
tree | a9d5b50568bfc10cc50291fd3604debfaf3e3783 /authfile.c | |
parent | 8117111a3c1360727e3c54aad31aa045e7a7871b (diff) |
- Merge big update to OpenSSH-2.0 from OpenBSD CVS
[README.openssh2]
- interop w/ F-secure windows client
- sync documentation
- ssh_host_dsa_key not ssh_dsa_key
[auth-rsa.c]
- missing fclose
[auth.c authfile.c compat.c dsa.c dsa.h hostfile.c key.c key.h radix.c]
[readconf.c readconf.h ssh-add.c ssh-keygen.c ssh.c ssh.h sshconnect.c]
[sshd.c uuencode.c uuencode.h authfile.h]
- add DSA pubkey auth and other SSH2 fixes. use ssh-keygen -[xX]
for trading keys with the real and the original SSH, directly from the
people who invented the SSH protocol.
[auth.c auth.h authfile.c sshconnect.c auth1.c auth2.c sshconnect.h]
[sshconnect1.c sshconnect2.c]
- split auth/sshconnect in one file per protocol version
[sshconnect2.c]
- remove debug
[uuencode.c]
- add trailing =
[version.h]
- OpenSSH-2.0
[ssh-keygen.1 ssh-keygen.c]
- add -R flag: exit code indicates if RSA is alive
[sshd.c]
- remove unused
silent if -Q is specified
[ssh.h]
- host key becomes /etc/ssh_host_dsa_key
[readconf.c servconf.c ]
- ssh/sshd default to proto 1 and 2
[uuencode.c]
- remove debug
[auth2.c ssh-keygen.c sshconnect2.c sshd.c]
- xfree DSA blobs
[auth2.c serverloop.c session.c]
- cleanup logging for sshd/2, respect PasswordAuth no
[sshconnect2.c]
- less debug, respect .ssh/config
[README.openssh2 channels.c channels.h]
- clientloop.c session.c ssh.c
- support for x11-fwding, client+server
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 206 |
1 files changed, 177 insertions, 29 deletions
diff --git a/authfile.c b/authfile.c index e17c60381..f93c9d470 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -15,14 +15,20 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "includes.h" | 17 | #include "includes.h" |
18 | RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $"); | 18 | RCSID("$Id: authfile.c,v 1.12 2000/04/29 13:57:10 damien Exp $"); |
19 | 19 | ||
20 | #include <openssl/bn.h> | 20 | #include <openssl/bn.h> |
21 | #include <openssl/dsa.h> | ||
22 | #include <openssl/rsa.h> | ||
23 | #include <openssl/pem.h> | ||
24 | #include <openssl/evp.h> | ||
25 | |||
21 | #include "xmalloc.h" | 26 | #include "xmalloc.h" |
22 | #include "buffer.h" | 27 | #include "buffer.h" |
23 | #include "bufaux.h" | 28 | #include "bufaux.h" |
24 | #include "cipher.h" | 29 | #include "cipher.h" |
25 | #include "ssh.h" | 30 | #include "ssh.h" |
31 | #include "key.h" | ||
26 | 32 | ||
27 | /* Version identification string for identity files. */ | 33 | /* Version identification string for identity files. */ |
28 | #define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n" | 34 | #define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n" |
@@ -35,8 +41,8 @@ RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $"); | |||
35 | */ | 41 | */ |
36 | 42 | ||
37 | int | 43 | int |
38 | save_private_key(const char *filename, const char *passphrase, | 44 | save_private_key_rsa(const char *filename, const char *passphrase, |
39 | RSA *key, const char *comment) | 45 | RSA *key, const char *comment) |
40 | { | 46 | { |
41 | Buffer buffer, encrypted; | 47 | Buffer buffer, encrypted; |
42 | char buf[100], *cp; | 48 | char buf[100], *cp; |
@@ -128,6 +134,63 @@ save_private_key(const char *filename, const char *passphrase, | |||
128 | return 1; | 134 | return 1; |
129 | } | 135 | } |
130 | 136 | ||
137 | /* save DSA key in OpenSSL PEM format */ | ||
138 | |||
139 | int | ||
140 | save_private_key_dsa(const char *filename, const char *passphrase, | ||
141 | DSA *dsa, const char *comment) | ||
142 | { | ||
143 | FILE *fp; | ||
144 | int fd; | ||
145 | int success = 1; | ||
146 | int len = strlen(passphrase); | ||
147 | |||
148 | if (len > 0 && len <= 4) { | ||
149 | error("passphrase too short: %d bytes", len); | ||
150 | errno = 0; | ||
151 | return 0; | ||
152 | } | ||
153 | fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); | ||
154 | if (fd < 0) { | ||
155 | debug("open %s failed", filename); | ||
156 | return 0; | ||
157 | } | ||
158 | fp = fdopen(fd, "w"); | ||
159 | if (fp == NULL ) { | ||
160 | debug("fdopen %s failed", filename); | ||
161 | close(fd); | ||
162 | return 0; | ||
163 | } | ||
164 | if (len > 0) { | ||
165 | if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(), | ||
166 | (char *)passphrase, strlen(passphrase), NULL, NULL)) | ||
167 | success = 0; | ||
168 | } else { | ||
169 | if (!PEM_write_DSAPrivateKey(fp, dsa, NULL, | ||
170 | NULL, 0, NULL, NULL)) | ||
171 | success = 0; | ||
172 | } | ||
173 | fclose(fp); | ||
174 | return success; | ||
175 | } | ||
176 | |||
177 | int | ||
178 | save_private_key(const char *filename, const char *passphrase, Key *key, | ||
179 | const char *comment) | ||
180 | { | ||
181 | switch (key->type) { | ||
182 | case KEY_RSA: | ||
183 | return save_private_key_rsa(filename, passphrase, key->rsa, comment); | ||
184 | break; | ||
185 | case KEY_DSA: | ||
186 | return save_private_key_dsa(filename, passphrase, key->dsa, comment); | ||
187 | break; | ||
188 | default: | ||
189 | break; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
131 | /* | 194 | /* |
132 | * Loads the public part of the key file. Returns 0 if an error was | 195 | * Loads the public part of the key file. Returns 0 if an error was |
133 | * encountered (the file does not exist or is not readable), and non-zero | 196 | * encountered (the file does not exist or is not readable), and non-zero |
@@ -135,8 +198,7 @@ save_private_key(const char *filename, const char *passphrase, | |||
135 | */ | 198 | */ |
136 | 199 | ||
137 | int | 200 | int |
138 | load_public_key(const char *filename, RSA * pub, | 201 | load_public_key_rsa(const char *filename, RSA * pub, char **comment_return) |
139 | char **comment_return) | ||
140 | { | 202 | { |
141 | int fd, i; | 203 | int fd, i; |
142 | off_t len; | 204 | off_t len; |
@@ -154,7 +216,7 @@ load_public_key(const char *filename, RSA * pub, | |||
154 | 216 | ||
155 | if (read(fd, cp, (size_t) len) != (size_t) len) { | 217 | if (read(fd, cp, (size_t) len) != (size_t) len) { |
156 | debug("Read from key file %.200s failed: %.100s", filename, | 218 | debug("Read from key file %.200s failed: %.100s", filename, |
157 | strerror(errno)); | 219 | strerror(errno)); |
158 | buffer_free(&buffer); | 220 | buffer_free(&buffer); |
159 | close(fd); | 221 | close(fd); |
160 | return 0; | 222 | return 0; |
@@ -183,9 +245,13 @@ load_public_key(const char *filename, RSA * pub, | |||
183 | 245 | ||
184 | /* Read the public key from the buffer. */ | 246 | /* Read the public key from the buffer. */ |
185 | buffer_get_int(&buffer); | 247 | buffer_get_int(&buffer); |
186 | pub->n = BN_new(); | 248 | /* XXX alloc */ |
249 | if (pub->n == NULL) | ||
250 | pub->n = BN_new(); | ||
187 | buffer_get_bignum(&buffer, pub->n); | 251 | buffer_get_bignum(&buffer, pub->n); |
188 | pub->e = BN_new(); | 252 | /* XXX alloc */ |
253 | if (pub->e == NULL) | ||
254 | pub->e = BN_new(); | ||
189 | buffer_get_bignum(&buffer, pub->e); | 255 | buffer_get_bignum(&buffer, pub->e); |
190 | if (comment_return) | 256 | if (comment_return) |
191 | *comment_return = buffer_get_string(&buffer, NULL); | 257 | *comment_return = buffer_get_string(&buffer, NULL); |
@@ -196,6 +262,20 @@ load_public_key(const char *filename, RSA * pub, | |||
196 | return 1; | 262 | return 1; |
197 | } | 263 | } |
198 | 264 | ||
265 | int | ||
266 | load_public_key(const char *filename, Key * key, char **comment_return) | ||
267 | { | ||
268 | switch (key->type) { | ||
269 | case KEY_RSA: | ||
270 | return load_public_key_rsa(filename, key->rsa, comment_return); | ||
271 | break; | ||
272 | case KEY_DSA: | ||
273 | default: | ||
274 | break; | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | |||
199 | /* | 279 | /* |
200 | * Loads the private key from the file. Returns 0 if an error is encountered | 280 | * Loads the private key from the file. Returns 0 if an error is encountered |
201 | * (file does not exist or is not readable, or passphrase is bad). This | 281 | * (file does not exist or is not readable, or passphrase is bad). This |
@@ -204,35 +284,17 @@ load_public_key(const char *filename, RSA * pub, | |||
204 | */ | 284 | */ |
205 | 285 | ||
206 | int | 286 | int |
207 | load_private_key(const char *filename, const char *passphrase, | 287 | load_private_key_rsa(int fd, const char *filename, |
208 | RSA * prv, char **comment_return) | 288 | const char *passphrase, RSA * prv, char **comment_return) |
209 | { | 289 | { |
210 | int fd, i, check1, check2, cipher_type; | 290 | int i, check1, check2, cipher_type; |
211 | off_t len; | 291 | off_t len; |
212 | Buffer buffer, decrypted; | 292 | Buffer buffer, decrypted; |
213 | char *cp; | 293 | char *cp; |
214 | CipherContext cipher; | 294 | CipherContext cipher; |
215 | BN_CTX *ctx; | 295 | BN_CTX *ctx; |
216 | BIGNUM *aux; | 296 | BIGNUM *aux; |
217 | struct stat st; | ||
218 | |||
219 | fd = open(filename, O_RDONLY); | ||
220 | if (fd < 0) | ||
221 | return 0; | ||
222 | 297 | ||
223 | /* check owner and modes */ | ||
224 | if (fstat(fd, &st) < 0 || | ||
225 | (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) || | ||
226 | (st.st_mode & 077) != 0) { | ||
227 | close(fd); | ||
228 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
229 | error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); | ||
230 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
231 | error("Bad ownership or mode(0%3.3o) for '%s'.", | ||
232 | st.st_mode & 0777, filename); | ||
233 | error("It is recommended that your private key files are NOT accessible by others."); | ||
234 | return 0; | ||
235 | } | ||
236 | len = lseek(fd, (off_t) 0, SEEK_END); | 298 | len = lseek(fd, (off_t) 0, SEEK_END); |
237 | lseek(fd, (off_t) 0, SEEK_SET); | 299 | lseek(fd, (off_t) 0, SEEK_SET); |
238 | 300 | ||
@@ -309,7 +371,9 @@ load_private_key(const char *filename, const char *passphrase, | |||
309 | buffer_free(&decrypted); | 371 | buffer_free(&decrypted); |
310 | fail: | 372 | fail: |
311 | BN_clear_free(prv->n); | 373 | BN_clear_free(prv->n); |
374 | prv->n = NULL; | ||
312 | BN_clear_free(prv->e); | 375 | BN_clear_free(prv->e); |
376 | prv->e = NULL; | ||
313 | if (comment_return) | 377 | if (comment_return) |
314 | xfree(*comment_return); | 378 | xfree(*comment_return); |
315 | return 0; | 379 | return 0; |
@@ -343,3 +407,87 @@ fail: | |||
343 | 407 | ||
344 | return 1; | 408 | return 1; |
345 | } | 409 | } |
410 | |||
411 | int | ||
412 | load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return) | ||
413 | { | ||
414 | DSA *dsa; | ||
415 | BIO *in; | ||
416 | FILE *fp; | ||
417 | |||
418 | in = BIO_new(BIO_s_file()); | ||
419 | if (in == NULL) { | ||
420 | error("BIO_new failed"); | ||
421 | return 0; | ||
422 | } | ||
423 | fp = fdopen(fd, "r"); | ||
424 | if (fp == NULL) { | ||
425 | error("fdopen failed"); | ||
426 | return 0; | ||
427 | } | ||
428 | BIO_set_fp(in, fp, BIO_NOCLOSE); | ||
429 | dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase); | ||
430 | if (dsa == NULL) { | ||
431 | debug("PEM_read_bio_DSAPrivateKey failed"); | ||
432 | } else { | ||
433 | /* replace k->dsa with loaded key */ | ||
434 | DSA_free(k->dsa); | ||
435 | k->dsa = dsa; | ||
436 | } | ||
437 | BIO_free(in); | ||
438 | fclose(fp); | ||
439 | if (comment_return) | ||
440 | *comment_return = xstrdup("dsa w/o comment"); | ||
441 | debug("read DSA private key done"); | ||
442 | #ifdef DEBUG_DSS | ||
443 | DSA_print_fp(stderr, dsa, 8); | ||
444 | #endif | ||
445 | return dsa != NULL ? 1 : 0; | ||
446 | } | ||
447 | |||
448 | int | ||
449 | load_private_key(const char *filename, const char *passphrase, Key *key, | ||
450 | char **comment_return) | ||
451 | { | ||
452 | int fd; | ||
453 | int ret = 0; | ||
454 | struct stat st; | ||
455 | |||
456 | fd = open(filename, O_RDONLY); | ||
457 | if (fd < 0) | ||
458 | return 0; | ||
459 | |||
460 | /* check owner and modes */ | ||
461 | if (fstat(fd, &st) < 0 || | ||
462 | (st.st_uid != 0 && st.st_uid != getuid()) || | ||
463 | (st.st_mode & 077) != 0) { | ||
464 | close(fd); | ||
465 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
466 | error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); | ||
467 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
468 | error("Bad ownership or mode(0%3.3o) for '%s'.", | ||
469 | st.st_mode & 0777, filename); | ||
470 | error("It is recommended that your private key files are NOT accessible by others."); | ||
471 | return 0; | ||
472 | } | ||
473 | switch (key->type) { | ||
474 | case KEY_RSA: | ||
475 | if (key->rsa->e != NULL) { | ||
476 | BN_clear_free(key->rsa->e); | ||
477 | key->rsa->e = NULL; | ||
478 | } | ||
479 | if (key->rsa->n != NULL) { | ||
480 | BN_clear_free(key->rsa->n); | ||
481 | key->rsa->n = NULL; | ||
482 | } | ||
483 | ret = load_private_key_rsa(fd, filename, passphrase, | ||
484 | key->rsa, comment_return); | ||
485 | break; | ||
486 | case KEY_DSA: | ||
487 | ret = load_private_key_dsa(fd, passphrase, key, comment_return); | ||
488 | default: | ||
489 | break; | ||
490 | } | ||
491 | close(fd); | ||
492 | return ret; | ||
493 | } | ||