]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: Defer creation of ~/.ssh by ssh(1) until we attempt to
authordtucker@openbsd.org <dtucker@openbsd.org>
Fri, 26 Jun 2020 05:02:03 +0000 (05:02 +0000)
committerDamien Miller <djm@mindrot.org>
Fri, 26 Jun 2020 05:24:27 +0000 (15:24 +1000)
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

hostfile.c
hostfile.h
ssh-keygen.c
ssh.c

index a91dbbd94094d4f11d3a0e5b835362581596984c..4b39def043447ce631114d719f2dc8df0622648b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.80 2020/05/13 09:52:41 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.81 2020/06/26 05:02:03 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -57,6 +57,7 @@
 #include "hostfile.h"
 #include "log.h"
 #include "misc.h"
+#include "pathnames.h"
 #include "ssherr.h"
 #include "digest.h"
 #include "hmac.h"
@@ -449,6 +450,38 @@ write_host_entry(FILE *f, const char *host, const char *ip,
        return success;
 }
 
+/*
+ * Create user ~/.ssh directory if it doesn't exist and we want to write to it.
+ * If notify is set, a message will be emitted if the directory is created.
+ */
+void
+hostfile_create_user_ssh_dir(const char *filename, int notify)
+{
+       char *dotsshdir = NULL, *p;
+       size_t len;
+       struct stat st;
+
+       if ((p = strrchr(filename, '/')) == NULL)
+               return;
+       len = p - filename;
+       dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid());
+       if ((strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0
+           || stat(dotsshdir, &st)) == 0)
+               ; /* do nothing, path not in ~/.ssh or dir already exists */
+       else if (errno != ENOENT)
+               error("Could not stat %s: %s", dotsshdir, strerror(errno));
+       else {
+               ssh_selinux_setfscreatecon(dotsshdir);
+               if (mkdir(dotsshdir, 0700) == -1)
+                       error("Could not create directory '%.200s' (%s).",
+                           dotsshdir, strerror(errno));
+               else if (notify)
+                       logit("Created directory '%s'.", dotsshdir);
+               ssh_selinux_setfscreatecon(NULL);
+       }
+       free(dotsshdir);
+}
+
 /*
  * Appends an entry to the host file.  Returns false if the entry could not
  * be appended.
@@ -462,6 +495,7 @@ add_host_to_hostfile(const char *filename, const char *host,
 
        if (key == NULL)
                return 1;       /* XXX ? */
+       hostfile_create_user_ssh_dir(filename, 0);
        f = fopen(filename, "a");
        if (!f)
                return 0;
index 49fcbb7e88335accce6453380171024e9d52e95c..de8b677e38c0b5f047166a72f259b47b781c85bd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.h,v 1.25 2020/05/13 09:52:41 djm Exp $ */
+/* $OpenBSD: hostfile.h,v 1.26 2020/06/26 05:02:03 dtucker Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -106,4 +106,6 @@ typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx);
 int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
     const char *host, const char *ip, u_int options);
 
+void hostfile_create_user_ssh_dir(const char *, int);
+
 #endif
index bdc29e00ac8ae8304b2ddbda31713ae86ddae309..7c6f11f4057f08c80a5c6a54b648f6ed08ee6fbb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.412 2020/05/29 03:11:54 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.413 2020/06/26 05:02:03 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -3082,11 +3082,10 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-       char dotsshdir[PATH_MAX], comment[1024], *passphrase;
+       char comment[1024], *passphrase;
        char *rr_hostname = NULL, *ep, *fp, *ra;
        struct sshkey *private, *public;
        struct passwd *pw;
-       struct stat st;
        int r, opt, type;
        int change_passphrase = 0, change_comment = 0, show_cert = 0;
        int find_host = 0, delete_host = 0, hash_hosts = 0;
@@ -3609,20 +3608,8 @@ main(int argc, char **argv)
                ask_filename(pw, "Enter file in which to save the key");
 
        /* Create ~/.ssh directory if it doesn't already exist. */
-       snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
-           pw->pw_dir, _PATH_SSH_USER_DIR);
-       if (strstr(identity_file, dotsshdir) != NULL) {
-               if (stat(dotsshdir, &st) == -1) {
-                       if (errno != ENOENT) {
-                               error("Could not stat %s: %s", dotsshdir,
-                                   strerror(errno));
-                       } else if (mkdir(dotsshdir, 0700) == -1) {
-                               error("Could not create directory '%s': %s",
-                                   dotsshdir, strerror(errno));
-                       } else if (!quiet)
-                               printf("Created directory '%s'.\n", dotsshdir);
-               }
-       }
+       hostfile_create_user_ssh_dir(identity_file, !quiet);
+
        /* If the file already exists, ask the user to confirm. */
        if (!confirm_overwrite(identity_file))
                exit(1);
diff --git a/ssh.c b/ssh.c
index dfae0a73dc32cf4d6e37693fb71edb354bf0941c..a767a1839c4ce6a0315d7a7a18050a69cc696ec8 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.529 2020/06/05 03:15:26 dtucker Exp $ */
+/* $OpenBSD: ssh.c,v 1.530 2020/06/26 05:02:03 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -645,7 +645,7 @@ main(int ac, char **av)
        struct ssh *ssh = NULL;
        int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
        int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
-       char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
+       char *p, *cp, *line, *argv0, *logfile;
        char cname[NI_MAXHOST];
        struct stat st;
        struct passwd *pw;
@@ -1572,22 +1572,6 @@ main(int ac, char **av)
                }
        }
 
-       /* Create ~/.ssh * directory if it doesn't already exist. */
-       if (config == NULL) {
-               r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
-                   strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
-               if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) {
-#ifdef WITH_SELINUX
-                       ssh_selinux_setfscreatecon(buf);
-#endif
-                       if (mkdir(buf, 0700) < 0)
-                               error("Could not create directory '%.200s'.",
-                                   buf);
-#ifdef WITH_SELINUX
-                       ssh_selinux_setfscreatecon(NULL);
-#endif
-               }
-       }
        /* load options.identity_files */
        load_public_identity_files(pw);