add a `sshd -G` option that parses and prints the effective
authordjm <djm@openbsd.org>
Fri, 10 Feb 2023 04:47:19 +0000 (04:47 +0000)
committerdjm <djm@openbsd.org>
Fri, 10 Feb 2023 04:47:19 +0000 (04:47 +0000)
configuration without attempting to load private keys and perform
other checks. This allows usage of the option before keys have been
generated.

bz3460 feedback/ok dtucker@

usr.bin/ssh/sshd.8
usr.bin/ssh/sshd.c

index d9a6dbf..e9ff0ca 100644 (file)
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: sshd.8,v 1.322 2023/01/18 01:50:21 millert Exp $
-.Dd $Mdocdate: January 18 2023 $
+.\" $OpenBSD: sshd.8,v 1.323 2023/02/10 04:47:19 djm Exp $
+.Dd $Mdocdate: February 10 2023 $
 .Dt SSHD 8
 .Os
 .Sh NAME
@@ -43,7 +43,7 @@
 .Sh SYNOPSIS
 .Nm sshd
 .Bk -words
-.Op Fl 46DdeiqTtV
+.Op Fl 46DGdeiqTtV
 .Op Fl C Ar connection_spec
 .Op Fl c Ar host_certificate_file
 .Op Fl E Ar log_file
@@ -154,6 +154,15 @@ The default is
 .Pa /etc/ssh/sshd_config .
 .Nm
 refuses to start if there is no configuration file.
+.It Fl G
+Parse and print configuration file.
+Check the validity of the configuration file, output the effective configuration
+to stdout and then exit.
+Optionally,
+.Cm Match
+rules may be applied by specifying the connection parameters using one or more
+.Fl C
+options.
 .It Fl g Ar login_grace_time
 Gives the grace time for clients to authenticate themselves (default
 120 seconds).
@@ -208,6 +217,11 @@ Optionally,
 rules may be applied by specifying the connection parameters using one or more
 .Fl C
 options.
+This is similar to the
+.Fl G
+flag, but it includes the additional testing performed by the
+.Fl t
+flag.
 .It Fl t
 Test mode.
 Only check the validity of the configuration file and sanity of the keys.
index f834429..f4e6012 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.596 2023/01/18 01:50:21 millert Exp $ */
+/* $OpenBSD: sshd.c,v 1.597 2023/02/10 04:47:19 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -858,7 +858,7 @@ usage(void)
 {
        fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION);
        fprintf(stderr,
-"usage: sshd [-46DdeiqTtV] [-C connection_spec] [-c host_cert_file]\n"
+"usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n"
 "            [-E log_file] [-f config_file] [-g login_grace_time]\n"
 "            [-h host_key_file] [-o option] [-p port] [-u len]\n"
        );
@@ -1444,6 +1444,21 @@ prepare_proctitle(int ac, char **av)
        return ret;
 }
 
+static void
+print_config(struct ssh *ssh, struct connection_info *connection_info)
+{
+       /*
+        * If no connection info was provided by -C then use
+        * use a blank one that will cause no predicate to match.
+        */
+       if (connection_info == NULL)
+               connection_info = get_connection_info(ssh, 0, 0);
+       connection_info->test = 1;
+       parse_server_match_config(&options, &includes, connection_info);
+       dump_config(&options);
+       exit(0);
+}
+
 /*
  * Main program for the daemon.
  */
@@ -1453,7 +1468,7 @@ main(int ac, char **av)
        struct ssh *ssh = NULL;
        extern char *optarg;
        extern int optind;
-       int r, opt, on = 1, already_daemon, remote_port;
+       int r, opt, on = 1, do_dump_cfg = 0, already_daemon, remote_port;
        int sock_in = -1, sock_out = -1, newsock = -1;
        const char *remote_ip, *rdomain;
        char *fp, *line, *laddr, *logfile = NULL;
@@ -1483,7 +1498,7 @@ main(int ac, char **av)
 
        /* Parse command-line arguments. */
        while ((opt = getopt(ac, av,
-           "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrtV")) != -1) {
+           "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) {
                switch (opt) {
                case '4':
                        options.address_family = AF_INET;
@@ -1508,6 +1523,9 @@ main(int ac, char **av)
                case 'D':
                        no_daemon_flag = 1;
                        break;
+               case 'G':
+                       do_dump_cfg = 1;
+                       break;
                case 'E':
                        logfile = optarg;
                        /* FALLTHROUGH */
@@ -1595,7 +1613,7 @@ main(int ac, char **av)
        }
        if (rexeced_flag || inetd_flag)
                rexec_flag = 0;
-       if (!test_flag && rexec_flag && !path_absolute(av[0]))
+       if (!test_flag && !do_dump_cfg && rexec_flag && !path_absolute(av[0]))
                fatal("sshd re-exec requires execution with an absolute path");
        if (rexeced_flag)
                closefrom(REEXEC_MIN_FREE_FD);
@@ -1696,6 +1714,9 @@ main(int ac, char **av)
 
        debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION);
 
+       if (do_dump_cfg)
+               print_config(ssh, connection_info);
+
        /* load host keys */
        sensitive_data.host_keys = xcalloc(options.num_host_key_files,
            sizeof(struct sshkey *));
@@ -1862,17 +1883,8 @@ main(int ac, char **av)
                            "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
        }
 
-       if (test_flag > 1) {
-               /*
-                * If no connection info was provided by -C then use
-                * use a blank one that will cause no predicate to match.
-                */
-               if (connection_info == NULL)
-                       connection_info = get_connection_info(ssh, 0, 0);
-               connection_info->test = 1;
-               parse_server_match_config(&options, &includes, connection_info);
-               dump_config(&options);
-       }
+       if (test_flag > 1)
+               print_config(ssh, connection_info);
 
        /* Configuration looks good, so exit if in test mode. */
        if (test_flag)