From 03d4d7e60b16f913c75382e32e136ddfa8d6485f Mon Sep 17 00:00:00 2001 From: Damien Miller <djm@mindrot.org> Date: Tue, 23 Apr 2013 15:21:06 +1000 Subject: [PATCH] - dtucker@cvs.openbsd.org 2013/04/07 02:10:33 [log.c log.h ssh.1 ssh.c sshd.8 sshd.c] Add -E option to ssh and sshd to append debugging logs to a specified file instead of stderr or syslog. ok markus@, man page help jmc@ --- ChangeLog | 4 ++++ log.c | 20 ++++++++++++++++++-- log.h | 3 ++- ssh.1 | 9 +++++++-- ssh.c | 28 ++++++++++++++++++++-------- sshd.8 | 9 +++++++-- sshd.c | 19 ++++++++++++++----- 7 files changed, 72 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47c7ce01c..51077256d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,6 +39,10 @@ - markus@cvs.openbsd.org 2013/04/06 16:07:00 [channels.c sshd.c] handle ECONNABORTED for accept(); ok deraadt some time ago... + - dtucker@cvs.openbsd.org 2013/04/07 02:10:33 + [log.c log.h ssh.1 ssh.c sshd.8 sshd.c] + Add -E option to ssh and sshd to append debugging logs to a specified file + instead of stderr or syslog. ok markus@, man page help jmc@ 20130418 - (djm) [config.guess config.sub] Update to last versions before they switch diff --git a/log.c b/log.c index d69154a67..81497a442 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.43 2012/09/06 04:37:39 dtucker Exp $ */ +/* $OpenBSD: log.c,v 1.44 2013/04/07 02:10:33 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -38,6 +38,7 @@ #include <sys/types.h> +#include <fcntl.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -54,6 +55,7 @@ static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; +static int log_stderr_fd = STDERR_FILENO; static int log_facility = LOG_AUTH; static char *argv0; static log_handler_fn *log_handler; @@ -344,6 +346,20 @@ log_is_on_stderr(void) return log_on_stderr; } +/* redirect what would usually get written to stderr to specified file */ +void +log_redirect_stderr_to(const char *logfile) +{ + int fd; + + if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { + fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, + strerror(errno)); + exit(1); + } + log_stderr_fd = fd; +} + #define MSGBUFSIZ 1024 void @@ -429,7 +445,7 @@ do_log(LogLevel level, const char *fmt, va_list args) log_handler = tmp_handler; } else if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); - write(STDERR_FILENO, msgbuf, strlen(msgbuf)); + write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); diff --git a/log.h b/log.h index e3e328b06..ae7df25d3 100644 --- a/log.h +++ b/log.h @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.19 2012/09/06 04:37:39 dtucker Exp $ */ +/* $OpenBSD: log.h,v 1.20 2013/04/07 02:10:33 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -51,6 +51,7 @@ typedef void (log_handler_fn)(LogLevel, const char *, void *); void log_init(char *, LogLevel, SyslogFacility, int); void log_change_level(LogLevel); int log_is_on_stderr(void); +void log_redirect_stderr_to(const char *); SyslogFacility log_facility_number(char *); const char * log_facility_name(SyslogFacility); diff --git a/ssh.1 b/ssh.1 index a5576edb6..d77494b83 100644 --- a/ssh.1 +++ b/ssh.1 @@ -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: ssh.1,v 1.330 2012/10/04 13:21:50 markus Exp $ -.Dd $Mdocdate: October 4 2012 $ +.\" $OpenBSD: ssh.1,v 1.331 2013/04/07 02:10:33 dtucker Exp $ +.Dd $Mdocdate: April 7 2013 $ .Dt SSH 1 .Os .Sh NAME @@ -47,6 +47,7 @@ .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl D Oo Ar bind_address : Oc Ns Ar port +.Op Fl E Ar log_file .Op Fl e Ar escape_char .Op Fl F Ar configfile .Op Fl I Ar pkcs11 @@ -217,6 +218,10 @@ indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. +.It Fl E Ar log_file +Append debug logs to +.Ar log_file +instead of standard error. .It Fl e Ar escape_char Sets the escape character for sessions with a pty (default: .Ql ~ ) . diff --git a/ssh.c b/ssh.c index b50fca38f..cd56f8a74 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.374 2013/03/08 06:32:58 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.375 2013/04/07 02:10:33 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -197,8 +197,8 @@ usage(void) { fprintf(stderr, "usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" -" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" -" [-I pkcs11] [-i identity_file]\n" +" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" +" [-F configfile] [-I pkcs11] [-i identity_file]\n" " [-L [bind_address:]port:host:hostport]\n" " [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" " [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" @@ -238,7 +238,7 @@ int main(int ac, char **av) { int i, r, opt, exit_status, use_syslog; - char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg; + char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; struct stat st; struct passwd *pw; @@ -322,11 +322,12 @@ main(int ac, char **av) /* Parse command-line arguments. */ host = NULL; use_syslog = 0; + logfile = NULL; argv0 = av[0]; again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" - "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { + "ACD:E:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; @@ -356,6 +357,9 @@ main(int ac, char **av) case 'y': use_syslog = 1; break; + case 'E': + logfile = xstrdup(optarg); + break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; @@ -427,9 +431,8 @@ main(int ac, char **av) } else { if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; - break; } - /* FALLTHROUGH */ + break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); @@ -663,12 +666,21 @@ main(int ac, char **av) /* * Initialize "log" output. Since we are the client all output - * actually goes to stderr. + * goes to stderr unless otherwise specified by -y or -E. */ + if (use_syslog && logfile != NULL) + fatal("Can't specify both -y and -E"); + if (logfile != NULL) { + log_redirect_stderr_to(logfile); + xfree(logfile); + } log_init(argv0, options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, SYSLOG_FACILITY_USER, !use_syslog); + if (debug_flag) + logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); + /* * Read per-user configuration file. Ignore the system wide config * file if the user specifies a config file on the command line. diff --git a/sshd.8 b/sshd.8 index 132397839..3ce0da6a3 100644 --- a/sshd.8 +++ b/sshd.8 @@ -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.267 2012/10/04 13:21:50 markus Exp $ -.Dd $Mdocdate: October 4 2012 $ +.\" $OpenBSD: sshd.8,v 1.268 2013/04/07 02:10:33 dtucker Exp $ +.Dd $Mdocdate: April 7 2013 $ .Dt SSHD 8 .Os .Sh NAME @@ -47,6 +47,7 @@ .Op Fl b Ar bits .Op Fl C Ar connection_spec .Op Fl c Ar host_certificate_file +.Op Fl E Ar log_file .Op Fl f Ar config_file .Op Fl g Ar login_grace_time .Op Fl h Ar host_key_file @@ -146,6 +147,10 @@ Multiple .Fl d options increase the debugging level. Maximum is 3. +.It Fl E Ar log_file +Append debug logs to +.Ar log_file +instead of the system log. .It Fl e When this option is specified, .Nm diff --git a/sshd.c b/sshd.c index 5fb2897fa..a0f5c0d26 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.398 2013/04/06 16:07:00 markus Exp $ */ +/* $OpenBSD: sshd.c,v 1.399 2013/04/07 02:10:33 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -900,8 +900,9 @@ usage(void) SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); fprintf(stderr, "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" -" [-f config_file] [-g login_grace_time] [-h host_key_file]\n" -" [-k key_gen_time] [-o option] [-p port] [-u len]\n" +" [-E log_file] [-f config_file] [-g login_grace_time]\n" +" [-h host_key_file] [-k key_gen_time] [-o option] [-p port]\n" +" [-u len]\n" ); exit(1); } @@ -1335,7 +1336,7 @@ main(int ac, char **av) int sock_in = -1, sock_out = -1, newsock = -1; const char *remote_ip; int remote_port; - char *line; + char *line, *logfile = NULL; int config_s[2] = { -1 , -1 }; u_int n; u_int64_t ibytes, obytes; @@ -1373,7 +1374,7 @@ main(int ac, char **av) initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) { + while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; @@ -1402,6 +1403,9 @@ main(int ac, char **av) case 'D': no_daemon_flag = 1; break; + case 'E': + logfile = xstrdup(optarg); + /* FALLTHROUGH */ case 'e': log_stderr = 1; break; @@ -1499,6 +1503,11 @@ main(int ac, char **av) OpenSSL_add_all_algorithms(); + /* If requested, redirect the logs to the specified logfile. */ + if (logfile != NULL) { + log_redirect_stderr_to(logfile); + xfree(logfile); + } /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd)