[PATCH] Enable ssh_config to set LogPath option (-E)

bryon bryon at fryer.io
Thu Apr 25 14:21:09 AEST 2024


On Wed, Apr 24, 2024, at 21:32, bryon wrote:
> ssh client has the ability to set the destination of debug logs via the `-E` flag.  ssh_config lacks an equivalent keyword to set the same option via configs.
> 
> This patch follows the same semantics of other `*Path` type keywords and creates a new ssh_config keyword `LogPath`.
> 
> [0] Bugzilla: https://bugzilla.mindrot.org/show_bug.cgi?id=3683
> [1] GitHub PR: https://github.com/openssh/openssh-portable/pull/491
> 

Updated patch below:
 - Moved the parsing of the config files slightly earlier to allow for configurations to be used for log output locations.
 - Updated ssh_config.5 to add documentation for `LogPath`

PR also updated on github [0].
[0] https://github.com/openssh/openssh-portable/pull/491


---
 readconf.c   | 10 +++++++++-
 readconf.h   |  1 +
 ssh.c        | 22 ++++++++++++++--------
 ssh_config.5 |  8 ++++++++
 4 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/readconf.c b/readconf.c
index 3a64a0441..f7d2a9064 100644
--- a/readconf.c
+++ b/readconf.c
@@ -156,7 +156,7 @@ typedef enum {
        oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
        oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
        oTCPKeepAlive, oNumberOfPasswordPrompts,
-       oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
+       oLogFacility, oLogLevel, oLogPath, oLogVerbose, oCiphers, oMacs,
        oPubkeyAuthentication,
        oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
        oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
@@ -271,6 +271,7 @@ static struct {
        { "numberofpasswordprompts", oNumberOfPasswordPrompts },
        { "syslogfacility", oLogFacility },
        { "loglevel", oLogLevel },
+       { "logpath", oLogPath },
        { "logverbose", oLogVerbose },
        { "dynamicforward", oDynamicForward },
        { "preferredauthentications", oPreferredAuthentications },
@@ -1629,6 +1630,10 @@ parse_pubkey_algos:
                }
                break;
 
+       case oLogPath:
+               charptr = &options->log_path;
+               goto parse_string;
+
        case oLocalForward:
        case oRemoteForward:
        case oDynamicForward:
@@ -2585,6 +2590,7 @@ initialize_options(Options * options)
        options->num_permitted_remote_opens = 0;
        options->log_facility = SYSLOG_FACILITY_NOT_SET;
        options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->log_path = NULL;
        options->num_log_verbose = 0;
        options->log_verbose = NULL;
        options->preferred_authentications = NULL;
@@ -2962,6 +2968,7 @@ free_options(Options *o)
        free(o->forward_agent_sock_path);
        free(o->xauth_location);
        FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
+       free(o->log_path);
        free(o->log_verbose);
        free(o->ciphers);
        free(o->macs);
@@ -3584,6 +3591,7 @@ dump_client_config(Options *o, const char *host)
        dump_cfg_string(oLocalCommand, o->local_command);
        dump_cfg_string(oRemoteCommand, o->remote_command);
        dump_cfg_string(oLogLevel, log_level_name(o->log_level));
+       dump_cfg_string(oLogPath, o->log_path);
        dump_cfg_string(oMacs, o->macs);
 #ifdef ENABLE_PKCS11
        dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
diff --git a/readconf.h b/readconf.h
index 9447d5d6e..0137b6690 100644
--- a/readconf.h
+++ b/readconf.h
@@ -54,6 +54,7 @@ typedef struct {
        int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
        SyslogFacility log_facility;    /* Facility for system logging. */
        LogLevel log_level;     /* Level for logging. */
+       char   *log_path;       /* Path for debug logs. */
        u_int   num_log_verbose;        /* Verbose log overrides */
        char   **log_verbose;
        int     port;           /* Port to connect. */
diff --git a/ssh.c b/ssh.c
index 0019281f4..63c426592 100644
--- a/ssh.c
+++ b/ssh.c
@@ -670,7 +670,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, *logfile;
+       char *p, *cp, *line, *argv0;
        char cname[NI_MAXHOST], thishost[NI_MAXHOST];
        struct stat st;
        struct passwd *pw;
@@ -741,7 +741,6 @@ main(int ac, char **av)
        /* Parse command-line arguments. */
        host = NULL;
        use_syslog = 0;
-       logfile = NULL;
        argv0 = av[0];
 
  again:
@@ -777,7 +776,8 @@ main(int ac, char **av)
                        use_syslog = 1;
                        break;
                case 'E':
-                       logfile = optarg;
+                       free(options.control_path);
+                       options.log_path = xstrdup(optarg);
                        break;
                case 'G':
                        config_test = 1;
@@ -1186,14 +1186,22 @@ main(int ac, char **av)
 
        ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
 
+       /* Parse the configuration files */
+       process_config_files(options.host_arg, pw, 0, &want_final_pass);
+
        /*
         * Initialize "log" output.  Since we are the client all output
         * goes to stderr unless otherwise specified by -y or -E.
         */
-       if (use_syslog && logfile != NULL)
+       if (use_syslog && options.log_path != NULL)
                fatal("Can't specify both -y and -E");
-       if (logfile != NULL)
-               log_redirect_stderr_to(logfile);
+       if (options.log_path != NULL) {
+               p = tilde_expand_filename(options.log_path, getuid());
+               options.log_path = p;
+               logit("Debug logging to file: %s", options.log_path);
+               log_redirect_stderr_to(options.log_path);
+               free(p);
+       }
        log_init(argv0,
            options.log_level == SYSLOG_LEVEL_NOT_SET ?
            SYSLOG_LEVEL_INFO : options.log_level,
@@ -1204,8 +1212,6 @@ main(int ac, char **av)
        if (debug_flag)
                logit("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION);
 
-       /* Parse the configuration files */
-       process_config_files(options.host_arg, pw, 0, &want_final_pass);
        if (want_final_pass)
                debug("configuration requests final Match pass");
 
diff --git a/ssh_config.5 b/ssh_config.5
index 2931d807e..b61bd2df8 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1393,6 +1393,14 @@ function, and all code in the
 .Pa packet.c
 file.
 This option is intended for debugging and no overrides are enabled by default.
+.It Cm LogPath
+Specify the path to the log file where debug logging should be appended.
+Arguments to
+.Cm LogPath
+may use the tilde syntax to refer to a user's home directory and
+environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
+section.
 .It Cm MACs
 Specifies the MAC (message authentication code) algorithms
 in order of preference.
-- 
2.39.2


More information about the openssh-unix-dev mailing list