summaryrefslogtreecommitdiff
path: root/authfile.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-03-26 13:44:06 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-03-26 13:44:06 +0000
commitd0fca423fcee576f4787d01f8bad3f9c0efd62ab (patch)
tree696cb73350804862b8e39ccb53dc4edff2f68976 /authfile.c
parent7bfff36ca3acf469de9fcad98826562ea6c1fbbe (diff)
- markus@cvs.openbsd.org 2001/03/26 08:07:09
[authfile.c authfile.h ssh-add.c ssh-keygen.c ssh.c sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c] simpler key load/save interface, see authfile.h
Diffstat (limited to 'authfile.c')
-rw-r--r--authfile.c343
1 files changed, 181 insertions, 162 deletions
diff --git a/authfile.c b/authfile.c
index 9f03d5137..c867724db 100644
--- a/authfile.c
+++ b/authfile.c
@@ -36,7 +36,7 @@
36 */ 36 */
37 37
38#include "includes.h" 38#include "includes.h"
39RCSID("$OpenBSD: authfile.c,v 1.28 2001/02/21 09:05:54 deraadt Exp $"); 39RCSID("$OpenBSD: authfile.c,v 1.29 2001/03/26 08:07:07 markus Exp $");
40 40
41#include <openssl/err.h> 41#include <openssl/err.h>
42#include <openssl/evp.h> 42#include <openssl/evp.h>
@@ -51,7 +51,7 @@ RCSID("$OpenBSD: authfile.c,v 1.28 2001/02/21 09:05:54 deraadt Exp $");
51#include "log.h" 51#include "log.h"
52#include "authfile.h" 52#include "authfile.h"
53 53
54/* Version identification string for identity files. */ 54/* Version identification string for SSH v1 identity files. */
55static const char authfile_id_string[] = 55static const char authfile_id_string[] =
56 "SSH PRIVATE KEY FILE FORMAT 1.1\n"; 56 "SSH PRIVATE KEY FILE FORMAT 1.1\n";
57 57
@@ -63,8 +63,8 @@ static const char authfile_id_string[] =
63 */ 63 */
64 64
65int 65int
66save_private_key_rsa1(const char *filename, const char *passphrase, 66key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
67 RSA *key, const char *comment) 67 const char *comment)
68{ 68{
69 Buffer buffer, encrypted; 69 Buffer buffer, encrypted;
70 char buf[100], *cp; 70 char buf[100], *cp;
@@ -100,10 +100,10 @@ save_private_key_rsa1(const char *filename, const char *passphrase,
100 * will be stored in plain text, and storing them also in encrypted 100 * will be stored in plain text, and storing them also in encrypted
101 * format would just give known plaintext). 101 * format would just give known plaintext).
102 */ 102 */
103 buffer_put_bignum(&buffer, key->d); 103 buffer_put_bignum(&buffer, key->rsa->d);
104 buffer_put_bignum(&buffer, key->iqmp); 104 buffer_put_bignum(&buffer, key->rsa->iqmp);
105 buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ 105 buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */
106 buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ 106 buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */
107 107
108 /* Pad the part to be encrypted until its size is a multiple of 8. */ 108 /* Pad the part to be encrypted until its size is a multiple of 8. */
109 while (buffer_len(&buffer) % 8 != 0) 109 while (buffer_len(&buffer) % 8 != 0)
@@ -122,9 +122,9 @@ save_private_key_rsa1(const char *filename, const char *passphrase,
122 buffer_put_int(&encrypted, 0); /* For future extension */ 122 buffer_put_int(&encrypted, 0); /* For future extension */
123 123
124 /* Store public key. This will be in plain text. */ 124 /* Store public key. This will be in plain text. */
125 buffer_put_int(&encrypted, BN_num_bits(key->n)); 125 buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
126 buffer_put_bignum(&encrypted, key->n); 126 buffer_put_bignum(&encrypted, key->rsa->n);
127 buffer_put_bignum(&encrypted, key->e); 127 buffer_put_bignum(&encrypted, key->rsa->e);
128 buffer_put_string(&encrypted, comment, strlen(comment)); 128 buffer_put_string(&encrypted, comment, strlen(comment));
129 129
130 /* Allocate space for the private part of the key in the buffer. */ 130 /* Allocate space for the private part of the key in the buffer. */
@@ -156,10 +156,10 @@ save_private_key_rsa1(const char *filename, const char *passphrase,
156 return 1; 156 return 1;
157} 157}
158 158
159/* save SSH2 key in OpenSSL PEM format */ 159/* save SSH v2 key in OpenSSL PEM format */
160int 160int
161save_private_key_ssh2(const char *filename, const char *_passphrase, 161key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
162 Key *key, const char *comment) 162 const char *comment)
163{ 163{
164 FILE *fp; 164 FILE *fp;
165 int fd; 165 int fd;
@@ -199,16 +199,18 @@ save_private_key_ssh2(const char *filename, const char *_passphrase,
199} 199}
200 200
201int 201int
202save_private_key(const char *filename, const char *passphrase, Key *key, 202key_save_private(Key *key, const char *filename, const char *passphrase,
203 const char *comment) 203 const char *comment)
204{ 204{
205 switch (key->type) { 205 switch (key->type) {
206 case KEY_RSA1: 206 case KEY_RSA1:
207 return save_private_key_rsa1(filename, passphrase, key->rsa, comment); 207 return key_save_private_rsa1(key, filename, passphrase,
208 comment);
208 break; 209 break;
209 case KEY_DSA: 210 case KEY_DSA:
210 case KEY_RSA: 211 case KEY_RSA:
211 return save_private_key_ssh2(filename, passphrase, key, comment); 212 return key_save_private_pem(key, filename, passphrase,
213 comment);
212 break; 214 break;
213 default: 215 default:
214 break; 216 break;
@@ -217,22 +219,20 @@ save_private_key(const char *filename, const char *passphrase, Key *key,
217} 219}
218 220
219/* 221/*
220 * Loads the public part of the key file. Returns 0 if an error was 222 * Loads the public part of the ssh v1 key file. Returns NULL if an error was
221 * encountered (the file does not exist or is not readable), and non-zero 223 * encountered (the file does not exist or is not readable), and the key
222 * otherwise. 224 * otherwise.
223 */ 225 */
224 226
225int 227Key *
226load_public_key_rsa(const char *filename, RSA * pub, char **comment_return) 228key_load_public_rsa1(int fd, const char *filename, char **commentp)
227{ 229{
228 int fd, i;
229 off_t len;
230 Buffer buffer; 230 Buffer buffer;
231 Key *pub;
231 char *cp; 232 char *cp;
233 int i;
234 off_t len;
232 235
233 fd = open(filename, O_RDONLY);
234 if (fd < 0)
235 return 0;
236 len = lseek(fd, (off_t) 0, SEEK_END); 236 len = lseek(fd, (off_t) 0, SEEK_END);
237 lseek(fd, (off_t) 0, SEEK_SET); 237 lseek(fd, (off_t) 0, SEEK_SET);
238 238
@@ -243,16 +243,14 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
243 debug("Read from key file %.200s failed: %.100s", filename, 243 debug("Read from key file %.200s failed: %.100s", filename,
244 strerror(errno)); 244 strerror(errno));
245 buffer_free(&buffer); 245 buffer_free(&buffer);
246 close(fd); 246 return NULL;
247 return 0;
248 } 247 }
249 close(fd);
250 248
251 /* Check that it is at least big enough to contain the ID string. */ 249 /* Check that it is at least big enough to contain the ID string. */
252 if (len < sizeof(authfile_id_string)) { 250 if (len < sizeof(authfile_id_string)) {
253 debug3("Bad RSA1 key file %.200s.", filename); 251 debug3("Bad RSA1 key file %.200s.", filename);
254 buffer_free(&buffer); 252 buffer_free(&buffer);
255 return 0; 253 return NULL;
256 } 254 }
257 /* 255 /*
258 * Make sure it begins with the id string. Consume the id string 256 * Make sure it begins with the id string. Consume the id string
@@ -262,7 +260,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
262 if (buffer_get_char(&buffer) != authfile_id_string[i]) { 260 if (buffer_get_char(&buffer) != authfile_id_string[i]) {
263 debug3("Bad RSA1 key file %.200s.", filename); 261 debug3("Bad RSA1 key file %.200s.", filename);
264 buffer_free(&buffer); 262 buffer_free(&buffer);
265 return 0; 263 return NULL;
266 } 264 }
267 /* Skip cipher type and reserved data. */ 265 /* Skip cipher type and reserved data. */
268 (void) buffer_get_char(&buffer); /* cipher type */ 266 (void) buffer_get_char(&buffer); /* cipher type */
@@ -270,37 +268,33 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
270 268
271 /* Read the public key from the buffer. */ 269 /* Read the public key from the buffer. */
272 buffer_get_int(&buffer); 270 buffer_get_int(&buffer);
273 /* XXX alloc */ 271 pub = key_new(KEY_RSA1);
274 if (pub->n == NULL) 272 buffer_get_bignum(&buffer, pub->rsa->n);
275 pub->n = BN_new(); 273 buffer_get_bignum(&buffer, pub->rsa->e);
276 buffer_get_bignum(&buffer, pub->n); 274 if (commentp)
277 /* XXX alloc */ 275 *commentp = buffer_get_string(&buffer, NULL);
278 if (pub->e == NULL)
279 pub->e = BN_new();
280 buffer_get_bignum(&buffer, pub->e);
281 if (comment_return)
282 *comment_return = buffer_get_string(&buffer, NULL);
283 /* The encrypted private part is not parsed by this function. */ 276 /* The encrypted private part is not parsed by this function. */
284 277
285 buffer_free(&buffer); 278 buffer_free(&buffer);
286 279 return pub;
287 return 1;
288} 280}
289 281
290/* load public key from private-key file */ 282/* load public key from private-key file, works only for SSH v1 */
291int 283Key *
292load_public_key(const char *filename, Key * key, char **comment_return) 284key_load_public_type(int type, const char *filename, char **commentp)
293{ 285{
294 switch (key->type) { 286 Key *pub;
295 case KEY_RSA1: 287 int fd;
296 return load_public_key_rsa(filename, key->rsa, comment_return); 288
297 break; 289 if (type == KEY_RSA1) {
298 case KEY_DSA: 290 fd = open(filename, O_RDONLY);
299 case KEY_RSA: 291 if (fd < 0)
300 default: 292 return NULL;
301 break; 293 pub = key_load_public_rsa1(fd, filename, commentp);
294 close(fd);
295 return pub;
302 } 296 }
303 return 0; 297 return NULL;
304} 298}
305 299
306/* 300/*
@@ -310,9 +304,9 @@ load_public_key(const char *filename, Key * key, char **comment_return)
310 * Assumes we are called under uid of the owner of the file. 304 * Assumes we are called under uid of the owner of the file.
311 */ 305 */
312 306
313int 307Key *
314load_private_key_rsa1(int fd, const char *filename, 308key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
315 const char *passphrase, RSA * prv, char **comment_return) 309 char **commentp)
316{ 310{
317 int i, check1, check2, cipher_type; 311 int i, check1, check2, cipher_type;
318 off_t len; 312 off_t len;
@@ -322,6 +316,7 @@ load_private_key_rsa1(int fd, const char *filename,
322 Cipher *cipher; 316 Cipher *cipher;
323 BN_CTX *ctx; 317 BN_CTX *ctx;
324 BIGNUM *aux; 318 BIGNUM *aux;
319 Key *prv = NULL;
325 320
326 len = lseek(fd, (off_t) 0, SEEK_END); 321 len = lseek(fd, (off_t) 0, SEEK_END);
327 lseek(fd, (off_t) 0, SEEK_SET); 322 lseek(fd, (off_t) 0, SEEK_SET);
@@ -334,7 +329,7 @@ load_private_key_rsa1(int fd, const char *filename,
334 strerror(errno)); 329 strerror(errno));
335 buffer_free(&buffer); 330 buffer_free(&buffer);
336 close(fd); 331 close(fd);
337 return 0; 332 return NULL;
338 } 333 }
339 334
340 /* Check that it is at least big enough to contain the ID string. */ 335 /* Check that it is at least big enough to contain the ID string. */
@@ -342,7 +337,7 @@ load_private_key_rsa1(int fd, const char *filename,
342 debug3("Bad RSA1 key file %.200s.", filename); 337 debug3("Bad RSA1 key file %.200s.", filename);
343 buffer_free(&buffer); 338 buffer_free(&buffer);
344 close(fd); 339 close(fd);
345 return 0; 340 return NULL;
346 } 341 }
347 /* 342 /*
348 * Make sure it begins with the id string. Consume the id string 343 * Make sure it begins with the id string. Consume the id string
@@ -353,7 +348,7 @@ load_private_key_rsa1(int fd, const char *filename,
353 debug3("Bad RSA1 key file %.200s.", filename); 348 debug3("Bad RSA1 key file %.200s.", filename);
354 buffer_free(&buffer); 349 buffer_free(&buffer);
355 close(fd); 350 close(fd);
356 return 0; 351 return NULL;
357 } 352 }
358 353
359 /* Read cipher type. */ 354 /* Read cipher type. */
@@ -362,12 +357,12 @@ load_private_key_rsa1(int fd, const char *filename,
362 357
363 /* Read the public key from the buffer. */ 358 /* Read the public key from the buffer. */
364 buffer_get_int(&buffer); 359 buffer_get_int(&buffer);
365 prv->n = BN_new(); 360 prv = key_new_private(KEY_RSA1);
366 buffer_get_bignum(&buffer, prv->n); 361
367 prv->e = BN_new(); 362 buffer_get_bignum(&buffer, prv->rsa->n);
368 buffer_get_bignum(&buffer, prv->e); 363 buffer_get_bignum(&buffer, prv->rsa->e);
369 if (comment_return) 364 if (commentp)
370 *comment_return = buffer_get_string(&buffer, NULL); 365 *commentp = buffer_get_string(&buffer, NULL);
371 else 366 else
372 xfree(buffer_get_string(&buffer, NULL)); 367 xfree(buffer_get_string(&buffer, NULL));
373 368
@@ -395,93 +390,81 @@ load_private_key_rsa1(int fd, const char *filename,
395 if (check1 != buffer_get_char(&decrypted) || 390 if (check1 != buffer_get_char(&decrypted) ||
396 check2 != buffer_get_char(&decrypted)) { 391 check2 != buffer_get_char(&decrypted)) {
397 if (strcmp(passphrase, "") != 0) 392 if (strcmp(passphrase, "") != 0)
398 debug("Bad passphrase supplied for key file %.200s.", filename); 393 debug("Bad passphrase supplied for key file %.200s.",
394 filename);
399 /* Bad passphrase. */ 395 /* Bad passphrase. */
400 buffer_free(&decrypted); 396 buffer_free(&decrypted);
401fail: 397 goto fail;
402 BN_clear_free(prv->n);
403 prv->n = NULL;
404 BN_clear_free(prv->e);
405 prv->e = NULL;
406 if (comment_return)
407 xfree(*comment_return);
408 close(fd);
409 return 0;
410 } 398 }
411 /* Read the rest of the private key. */ 399 /* Read the rest of the private key. */
412 prv->d = BN_new(); 400 buffer_get_bignum(&decrypted, prv->rsa->d);
413 buffer_get_bignum(&decrypted, prv->d); 401 buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */
414 prv->iqmp = BN_new(); 402 /* in SSL and SSH v1 p and q are exchanged */
415 buffer_get_bignum(&decrypted, prv->iqmp); /* u */ 403 buffer_get_bignum(&decrypted, prv->rsa->q); /* p */
416 /* in SSL and SSH p and q are exchanged */ 404 buffer_get_bignum(&decrypted, prv->rsa->p); /* q */
417 prv->q = BN_new();
418 buffer_get_bignum(&decrypted, prv->q); /* p */
419 prv->p = BN_new();
420 buffer_get_bignum(&decrypted, prv->p); /* q */
421 405
406 /* calculate p-1 and q-1 */
422 ctx = BN_CTX_new(); 407 ctx = BN_CTX_new();
423 aux = BN_new(); 408 aux = BN_new();
424 409
425 BN_sub(aux, prv->q, BN_value_one()); 410 BN_sub(aux, prv->rsa->q, BN_value_one());
426 prv->dmq1 = BN_new(); 411 BN_mod(prv->rsa->dmq1, prv->rsa->d, aux, ctx);
427 BN_mod(prv->dmq1, prv->d, aux, ctx);
428 412
429 BN_sub(aux, prv->p, BN_value_one()); 413 BN_sub(aux, prv->rsa->p, BN_value_one());
430 prv->dmp1 = BN_new(); 414 BN_mod(prv->rsa->dmp1, prv->rsa->d, aux, ctx);
431 BN_mod(prv->dmp1, prv->d, aux, ctx);
432 415
433 BN_clear_free(aux); 416 BN_clear_free(aux);
434 BN_CTX_free(ctx); 417 BN_CTX_free(ctx);
435 418
436 buffer_free(&decrypted); 419 buffer_free(&decrypted);
437 close(fd); 420 close(fd);
438 return 1; 421 return prv;
422
423fail:
424 if (commentp)
425 xfree(*commentp);
426 close(fd);
427 key_free(prv);
428 return NULL;
439} 429}
440 430
441int 431Key *
442load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return) 432key_load_private_pem(int fd, int type, const char *passphrase,
433 char **commentp)
443{ 434{
444 FILE *fp; 435 FILE *fp;
445 int success = 0;
446 EVP_PKEY *pk = NULL; 436 EVP_PKEY *pk = NULL;
437 Key *prv = NULL;
447 char *name = "<no key>"; 438 char *name = "<no key>";
448 439
449 fp = fdopen(fd, "r"); 440 fp = fdopen(fd, "r");
450 if (fp == NULL) { 441 if (fp == NULL) {
451 error("fdopen failed"); 442 error("fdopen failed");
452 close(fd); 443 close(fd);
453 return 0; 444 return NULL;
454 } 445 }
455 pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); 446 pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
456 if (pk == NULL) { 447 if (pk == NULL) {
457 debug("PEM_read_PrivateKey failed"); 448 debug("PEM_read_PrivateKey failed");
458 (void)ERR_get_error(); 449 (void)ERR_get_error();
459 } else if (pk->type == EVP_PKEY_RSA) { 450 } else if (pk->type == EVP_PKEY_RSA &&
460 /* replace k->rsa with loaded key */ 451 (type == KEY_UNSPEC||type==KEY_RSA)) {
461 if (k->type == KEY_RSA || k->type == KEY_UNSPEC) { 452 prv = key_new(KEY_UNSPEC);
462 if (k->rsa != NULL) 453 prv->rsa = EVP_PKEY_get1_RSA(pk);
463 RSA_free(k->rsa); 454 prv->type = KEY_RSA;
464 k->rsa = EVP_PKEY_get1_RSA(pk); 455 name = "rsa w/o comment";
465 k->type = KEY_RSA;
466 name = "rsa w/o comment";
467 success = 1;
468#ifdef DEBUG_PK 456#ifdef DEBUG_PK
469 RSA_print_fp(stderr, k->rsa, 8); 457 RSA_print_fp(stderr, prv->rsa, 8);
470#endif 458#endif
471 } 459 } else if (pk->type == EVP_PKEY_DSA &&
472 } else if (pk->type == EVP_PKEY_DSA) { 460 (type == KEY_UNSPEC||type==KEY_DSA)) {
473 /* replace k->dsa with loaded key */ 461 prv = key_new(KEY_UNSPEC);
474 if (k->type == KEY_DSA || k->type == KEY_UNSPEC) { 462 prv->dsa = EVP_PKEY_get1_DSA(pk);
475 if (k->dsa != NULL) 463 prv->type = KEY_DSA;
476 DSA_free(k->dsa); 464 name = "dsa w/o comment";
477 k->dsa = EVP_PKEY_get1_DSA(pk);
478 k->type = KEY_DSA;
479 name = "dsa w/o comment";
480#ifdef DEBUG_PK 465#ifdef DEBUG_PK
481 DSA_print_fp(stderr, k->dsa, 8); 466 DSA_print_fp(stderr, prv->dsa, 8);
482#endif 467#endif
483 success = 1;
484 }
485 } else { 468 } else {
486 error("PEM_read_PrivateKey: mismatch or " 469 error("PEM_read_PrivateKey: mismatch or "
487 "unknown EVP_PKEY save_type %d", pk->save_type); 470 "unknown EVP_PKEY save_type %d", pk->save_type);
@@ -489,24 +472,18 @@ load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_ret
489 fclose(fp); 472 fclose(fp);
490 if (pk != NULL) 473 if (pk != NULL)
491 EVP_PKEY_free(pk); 474 EVP_PKEY_free(pk);
492 if (success && comment_return) 475 if (prv != NULL && commentp)
493 *comment_return = xstrdup(name); 476 *commentp = xstrdup(name);
494 debug("read SSH2 private key done: name %s success %d", name, success); 477 debug("read PEM private key done: type %s",
495 return success; 478 prv ? key_type(prv) : "<unknown>");
479 return prv;
496} 480}
497 481
498int 482int
499load_private_key(const char *filename, const char *passphrase, Key *key, 483key_perm_ok(int fd, const char *filename)
500 char **comment_return)
501{ 484{
502 int fd;
503 int ret = 0;
504 struct stat st; 485 struct stat st;
505 486
506 fd = open(filename, O_RDONLY);
507 if (fd < 0)
508 return 0;
509
510 /* check owner and modes */ 487 /* check owner and modes */
511#ifdef HAVE_CYGWIN 488#ifdef HAVE_CYGWIN
512 if (check_ntsec(filename)) 489 if (check_ntsec(filename))
@@ -521,40 +498,78 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
521 error("Bad ownership or mode(0%3.3o) for '%s'.", 498 error("Bad ownership or mode(0%3.3o) for '%s'.",
522 st.st_mode & 0777, filename); 499 st.st_mode & 0777, filename);
523 error("It is recommended that your private key files are NOT accessible by others."); 500 error("It is recommended that your private key files are NOT accessible by others.");
501 error("This private key will be ignored.");
524 return 0; 502 return 0;
525 } 503 }
526 switch (key->type) { 504 return 1;
527 case KEY_RSA1: 505}
528 if (key->rsa->e != NULL) {
529 BN_clear_free(key->rsa->e);
530 key->rsa->e = NULL;
531 }
532 if (key->rsa->n != NULL) {
533 BN_clear_free(key->rsa->n);
534 key->rsa->n = NULL;
535 }
536 ret = load_private_key_rsa1(fd, filename, passphrase,
537 key->rsa, comment_return); /* closes fd */
538 506
507Key *
508key_load_private_type(int type, const char *filename, const char *passphrase,
509 char **commentp)
510{
511 int fd;
512
513 fd = open(filename, O_RDONLY);
514 if (fd < 0)
515 return NULL;
516 if (!key_perm_ok(fd, filename)) {
517 debug("bad permissions: ignore key: %s", filename);
518 close(fd);
519 return NULL;
520 }
521 switch (type) {
522 case KEY_RSA1:
523 return key_load_private_rsa1(fd, filename, passphrase,
524 commentp);
525 /* closes fd */
539 break; 526 break;
540 case KEY_DSA: 527 case KEY_DSA:
541 case KEY_RSA: 528 case KEY_RSA:
542 case KEY_UNSPEC: 529 case KEY_UNSPEC:
543 ret = load_private_key_ssh2(fd, passphrase, key, 530 return key_load_private_pem(fd, type, passphrase, commentp);
544 comment_return); /* closes fd */ 531 /* closes fd */
545 break; 532 break;
546 default: 533 default:
547 close(fd); 534 close(fd);
548 break; 535 break;
549 } 536 }
550 return ret; 537 return NULL;
538}
539
540Key *
541key_load_private(const char *filename, const char *passphrase,
542 char **commentp)
543{
544 Key *pub;
545 int fd;
546
547 fd = open(filename, O_RDONLY);
548 if (fd < 0)
549 return NULL;
550 if (!key_perm_ok(fd, filename)) {
551 debug("bad permissions: ignore key: %s", filename);
552 close(fd);
553 return NULL;
554 }
555 pub = key_load_public_rsa1(fd, filename, commentp);
556 lseek(fd, (off_t) 0, SEEK_SET); /* rewind */
557 if (pub == NULL) {
558 /* closes fd */
559 return key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
560 } else {
561 /* it's a SSH v1 key if the public key part is readable */
562 key_free(pub);
563 /* closes fd */
564 return key_load_private_rsa1(fd, filename, passphrase, NULL);
565 }
551} 566}
552 567
553int 568int
554do_load_public_key(const char *filename, Key *k, char **commentp) 569key_try_load_public(Key *k, const char *filename, char **commentp)
555{ 570{
556 FILE *f; 571 FILE *f;
557 char line[1024]; 572 char line[4096];
558 char *cp; 573 char *cp;
559 574
560 f = fopen(filename, "r"); 575 f = fopen(filename, "r");
@@ -585,19 +600,23 @@ do_load_public_key(const char *filename, Key *k, char **commentp)
585 return 0; 600 return 0;
586} 601}
587 602
588/* load public key from pubkey file */ 603/* load public key from ssh v1 private or any pubkey file */
589int 604Key *
590try_load_public_key(const char *filename, Key *k, char **commentp) 605key_load_public(const char *filename, char **commentp)
591{ 606{
592 char pub[MAXPATHLEN]; 607 Key *pub;
593 608 char file[MAXPATHLEN];
594 if (do_load_public_key(filename, k, commentp) == 1) 609
595 return 1; 610 pub = key_load_public_type(KEY_RSA1, filename, commentp);
596 if (strlcpy(pub, filename, sizeof pub) >= MAXPATHLEN) 611 if (pub != NULL)
597 return 0; 612 return pub;
598 if (strlcat(pub, ".pub", sizeof pub) >= MAXPATHLEN) 613 pub = key_new(KEY_UNSPEC);
599 return 0; 614 if (key_try_load_public(pub, filename, commentp) == 1)
600 if (do_load_public_key(pub, k, commentp) == 1) 615 return pub;
601 return 1; 616 if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
602 return 0; 617 (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
618 (key_try_load_public(pub, file, commentp) == 1))
619 return pub;
620 key_free(pub);
621 return NULL;
603} 622}