diff options
author | dtucker@openbsd.org <dtucker@openbsd.org> | 2020-06-26 05:02:03 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-06-26 15:24:27 +1000 |
commit | 74344c3ca42c3f53b00b025daf09ae7f6aa38076 (patch) | |
tree | 4952081cdbd6c6f3e6e891cd09a7688f003ea639 | |
parent | c9e24daac6324fcbdba171392c325bf9ccc3c768 (diff) |
upstream: Defer creation of ~/.ssh by ssh(1) until we attempt to
write to it so we don't leave an empty .ssh directory when it's not needed.
Use the same function to replace the code in ssh-keygen that does the same
thing. bz#3156, ok djm@
OpenBSD-Commit-ID: 59c073b569be1a60f4de36f491a4339bc4ae870f
-rw-r--r-- | hostfile.c | 36 | ||||
-rw-r--r-- | hostfile.h | 4 | ||||
-rw-r--r-- | ssh-keygen.c | 21 | ||||
-rw-r--r-- | ssh.c | 20 |
4 files changed, 44 insertions, 37 deletions
diff --git a/hostfile.c b/hostfile.c index a91dbbd94..4b39def04 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hostfile.c,v 1.80 2020/05/13 09:52:41 djm Exp $ */ | 1 | /* $OpenBSD: hostfile.c,v 1.81 2020/06/26 05:02:03 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -57,6 +57,7 @@ | |||
57 | #include "hostfile.h" | 57 | #include "hostfile.h" |
58 | #include "log.h" | 58 | #include "log.h" |
59 | #include "misc.h" | 59 | #include "misc.h" |
60 | #include "pathnames.h" | ||
60 | #include "ssherr.h" | 61 | #include "ssherr.h" |
61 | #include "digest.h" | 62 | #include "digest.h" |
62 | #include "hmac.h" | 63 | #include "hmac.h" |
@@ -450,6 +451,38 @@ write_host_entry(FILE *f, const char *host, const char *ip, | |||
450 | } | 451 | } |
451 | 452 | ||
452 | /* | 453 | /* |
454 | * Create user ~/.ssh directory if it doesn't exist and we want to write to it. | ||
455 | * If notify is set, a message will be emitted if the directory is created. | ||
456 | */ | ||
457 | void | ||
458 | hostfile_create_user_ssh_dir(const char *filename, int notify) | ||
459 | { | ||
460 | char *dotsshdir = NULL, *p; | ||
461 | size_t len; | ||
462 | struct stat st; | ||
463 | |||
464 | if ((p = strrchr(filename, '/')) == NULL) | ||
465 | return; | ||
466 | len = p - filename; | ||
467 | dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid()); | ||
468 | if ((strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0 | ||
469 | || stat(dotsshdir, &st)) == 0) | ||
470 | ; /* do nothing, path not in ~/.ssh or dir already exists */ | ||
471 | else if (errno != ENOENT) | ||
472 | error("Could not stat %s: %s", dotsshdir, strerror(errno)); | ||
473 | else { | ||
474 | ssh_selinux_setfscreatecon(dotsshdir); | ||
475 | if (mkdir(dotsshdir, 0700) == -1) | ||
476 | error("Could not create directory '%.200s' (%s).", | ||
477 | dotsshdir, strerror(errno)); | ||
478 | else if (notify) | ||
479 | logit("Created directory '%s'.", dotsshdir); | ||
480 | ssh_selinux_setfscreatecon(NULL); | ||
481 | } | ||
482 | free(dotsshdir); | ||
483 | } | ||
484 | |||
485 | /* | ||
453 | * Appends an entry to the host file. Returns false if the entry could not | 486 | * Appends an entry to the host file. Returns false if the entry could not |
454 | * be appended. | 487 | * be appended. |
455 | */ | 488 | */ |
@@ -462,6 +495,7 @@ add_host_to_hostfile(const char *filename, const char *host, | |||
462 | 495 | ||
463 | if (key == NULL) | 496 | if (key == NULL) |
464 | return 1; /* XXX ? */ | 497 | return 1; /* XXX ? */ |
498 | hostfile_create_user_ssh_dir(filename, 0); | ||
465 | f = fopen(filename, "a"); | 499 | f = fopen(filename, "a"); |
466 | if (!f) | 500 | if (!f) |
467 | return 0; | 501 | return 0; |
diff --git a/hostfile.h b/hostfile.h index 49fcbb7e8..de8b677e3 100644 --- a/hostfile.h +++ b/hostfile.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hostfile.h,v 1.25 2020/05/13 09:52:41 djm Exp $ */ | 1 | /* $OpenBSD: hostfile.h,v 1.26 2020/06/26 05:02:03 dtucker Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -106,4 +106,6 @@ typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx); | |||
106 | int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, | 106 | int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, |
107 | const char *host, const char *ip, u_int options); | 107 | const char *host, const char *ip, u_int options); |
108 | 108 | ||
109 | void hostfile_create_user_ssh_dir(const char *, int); | ||
110 | |||
109 | #endif | 111 | #endif |
diff --git a/ssh-keygen.c b/ssh-keygen.c index bdc29e00a..7c6f11f40 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.412 2020/05/29 03:11:54 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.413 2020/06/26 05:02:03 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -3082,11 +3082,10 @@ usage(void) | |||
3082 | int | 3082 | int |
3083 | main(int argc, char **argv) | 3083 | main(int argc, char **argv) |
3084 | { | 3084 | { |
3085 | char dotsshdir[PATH_MAX], comment[1024], *passphrase; | 3085 | char comment[1024], *passphrase; |
3086 | char *rr_hostname = NULL, *ep, *fp, *ra; | 3086 | char *rr_hostname = NULL, *ep, *fp, *ra; |
3087 | struct sshkey *private, *public; | 3087 | struct sshkey *private, *public; |
3088 | struct passwd *pw; | 3088 | struct passwd *pw; |
3089 | struct stat st; | ||
3090 | int r, opt, type; | 3089 | int r, opt, type; |
3091 | int change_passphrase = 0, change_comment = 0, show_cert = 0; | 3090 | int change_passphrase = 0, change_comment = 0, show_cert = 0; |
3092 | int find_host = 0, delete_host = 0, hash_hosts = 0; | 3091 | int find_host = 0, delete_host = 0, hash_hosts = 0; |
@@ -3609,20 +3608,8 @@ main(int argc, char **argv) | |||
3609 | ask_filename(pw, "Enter file in which to save the key"); | 3608 | ask_filename(pw, "Enter file in which to save the key"); |
3610 | 3609 | ||
3611 | /* Create ~/.ssh directory if it doesn't already exist. */ | 3610 | /* Create ~/.ssh directory if it doesn't already exist. */ |
3612 | snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", | 3611 | hostfile_create_user_ssh_dir(identity_file, !quiet); |
3613 | pw->pw_dir, _PATH_SSH_USER_DIR); | 3612 | |
3614 | if (strstr(identity_file, dotsshdir) != NULL) { | ||
3615 | if (stat(dotsshdir, &st) == -1) { | ||
3616 | if (errno != ENOENT) { | ||
3617 | error("Could not stat %s: %s", dotsshdir, | ||
3618 | strerror(errno)); | ||
3619 | } else if (mkdir(dotsshdir, 0700) == -1) { | ||
3620 | error("Could not create directory '%s': %s", | ||
3621 | dotsshdir, strerror(errno)); | ||
3622 | } else if (!quiet) | ||
3623 | printf("Created directory '%s'.\n", dotsshdir); | ||
3624 | } | ||
3625 | } | ||
3626 | /* If the file already exists, ask the user to confirm. */ | 3613 | /* If the file already exists, ask the user to confirm. */ |
3627 | if (!confirm_overwrite(identity_file)) | 3614 | if (!confirm_overwrite(identity_file)) |
3628 | exit(1); | 3615 | exit(1); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.529 2020/06/05 03:15:26 dtucker Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.530 2020/06/26 05:02:03 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -645,7 +645,7 @@ main(int ac, char **av) | |||
645 | struct ssh *ssh = NULL; | 645 | struct ssh *ssh = NULL; |
646 | int i, r, opt, exit_status, use_syslog, direct, timeout_ms; | 646 | int i, r, opt, exit_status, use_syslog, direct, timeout_ms; |
647 | int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; | 647 | int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; |
648 | char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; | 648 | char *p, *cp, *line, *argv0, *logfile; |
649 | char cname[NI_MAXHOST]; | 649 | char cname[NI_MAXHOST]; |
650 | struct stat st; | 650 | struct stat st; |
651 | struct passwd *pw; | 651 | struct passwd *pw; |
@@ -1572,22 +1572,6 @@ main(int ac, char **av) | |||
1572 | } | 1572 | } |
1573 | } | 1573 | } |
1574 | 1574 | ||
1575 | /* Create ~/.ssh * directory if it doesn't already exist. */ | ||
1576 | if (config == NULL) { | ||
1577 | r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, | ||
1578 | strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | ||
1579 | if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) { | ||
1580 | #ifdef WITH_SELINUX | ||
1581 | ssh_selinux_setfscreatecon(buf); | ||
1582 | #endif | ||
1583 | if (mkdir(buf, 0700) < 0) | ||
1584 | error("Could not create directory '%.200s'.", | ||
1585 | buf); | ||
1586 | #ifdef WITH_SELINUX | ||
1587 | ssh_selinux_setfscreatecon(NULL); | ||
1588 | #endif | ||
1589 | } | ||
1590 | } | ||
1591 | /* load options.identity_files */ | 1575 | /* load options.identity_files */ |
1592 | load_public_identity_files(pw); | 1576 | load_public_identity_files(pw); |
1593 | 1577 | ||