2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* Session logging.
|
|
|
|
*/
|
|
|
|
|
2001-12-14 14:57:50 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
|
|
|
|
/* log session to file stuff ... */
|
2018-09-11 14:17:16 +00:00
|
|
|
struct LogContext_tag {
|
2002-10-26 12:58:13 +00:00
|
|
|
FILE *lgfp;
|
2005-02-18 22:03:15 +00:00
|
|
|
enum { L_CLOSED, L_OPENING, L_OPEN, L_ERROR } state;
|
2005-02-18 18:33:31 +00:00
|
|
|
bufchain queue;
|
2011-10-02 11:01:57 +00:00
|
|
|
Filename *currlogfilename;
|
2018-09-12 08:10:51 +00:00
|
|
|
Frontend *frontend;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf;
|
|
|
|
int logtype; /* cached out of conf */
|
2002-10-26 12:58:13 +00:00
|
|
|
};
|
2001-12-14 14:57:50 +00:00
|
|
|
|
2015-08-08 12:35:44 +00:00
|
|
|
static Filename *xlatlognam(Filename *s, char *hostname, int port,
|
|
|
|
struct tm *tm);
|
2001-12-14 14:57:50 +00:00
|
|
|
|
|
|
|
/*
|
2005-02-18 18:33:31 +00:00
|
|
|
* Internal wrapper function which must be called for _all_ output
|
|
|
|
* to the log file. It takes care of opening the log file if it
|
|
|
|
* isn't open, buffering data if it's in the process of being
|
|
|
|
* opened asynchronously, etc.
|
2001-12-14 14:57:50 +00:00
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
static void logwrite(LogContext *ctx, void *data, int len)
|
2001-12-14 14:57:50 +00:00
|
|
|
{
|
2005-02-18 18:33:31 +00:00
|
|
|
/*
|
2005-02-18 22:03:15 +00:00
|
|
|
* In state L_CLOSED, we call logfopen, which will set the state
|
|
|
|
* to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
|
|
|
|
* those three _after_ processing L_CLOSED.
|
2005-02-18 18:33:31 +00:00
|
|
|
*/
|
2005-02-18 22:03:15 +00:00
|
|
|
if (ctx->state == L_CLOSED)
|
2005-02-18 18:33:31 +00:00
|
|
|
logfopen(ctx);
|
|
|
|
|
2005-02-18 22:03:15 +00:00
|
|
|
if (ctx->state == L_OPENING) {
|
2005-02-18 18:33:31 +00:00
|
|
|
bufchain_add(&ctx->queue, data, len);
|
2005-02-18 22:03:15 +00:00
|
|
|
} else if (ctx->state == L_OPEN) {
|
2005-02-18 18:33:31 +00:00
|
|
|
assert(ctx->lgfp);
|
2011-07-12 18:13:33 +00:00
|
|
|
if (fwrite(data, 1, len, ctx->lgfp) < (size_t)len) {
|
2009-08-07 00:19:04 +00:00
|
|
|
logfclose(ctx);
|
|
|
|
ctx->state = L_ERROR;
|
2009-08-30 11:09:22 +00:00
|
|
|
/* Log state is L_ERROR so this won't cause a loop */
|
|
|
|
logevent(ctx->frontend,
|
|
|
|
"Disabled writing session log due to error while writing");
|
2009-08-07 00:19:04 +00:00
|
|
|
}
|
2005-02-18 22:03:15 +00:00
|
|
|
} /* else L_ERROR, so ignore the write */
|
2005-02-18 18:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convenience wrapper on logwrite() which printf-formats the
|
|
|
|
* string.
|
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
static void logprintf(LogContext *ctx, const char *fmt, ...)
|
2005-02-18 18:33:31 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char *data;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
data = dupvprintf(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
logwrite(ctx, data, strlen(data));
|
|
|
|
sfree(data);
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
|
|
|
|
2004-08-12 01:02:01 +00:00
|
|
|
/*
|
|
|
|
* Flush any open log file.
|
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
void logflush(LogContext *ctx)
|
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (ctx->logtype > 0)
|
2005-02-18 22:03:15 +00:00
|
|
|
if (ctx->state == L_OPEN)
|
2004-08-12 01:02:01 +00:00
|
|
|
fflush(ctx->lgfp);
|
|
|
|
}
|
|
|
|
|
2018-09-11 14:17:16 +00:00
|
|
|
static void logfopen_callback(void *vctx, int mode)
|
2005-02-18 18:33:31 +00:00
|
|
|
{
|
2018-09-11 14:17:16 +00:00
|
|
|
LogContext *ctx = (LogContext *)vctx;
|
2005-02-18 18:33:31 +00:00
|
|
|
char buf[256], *event;
|
|
|
|
struct tm tm;
|
|
|
|
const char *fmode;
|
2015-09-25 08:15:21 +00:00
|
|
|
int shout = FALSE;
|
2005-02-18 18:33:31 +00:00
|
|
|
|
|
|
|
if (mode == 0) {
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_ERROR; /* disable logging */
|
2005-02-18 18:33:31 +00:00
|
|
|
} else {
|
2005-02-19 01:20:16 +00:00
|
|
|
fmode = (mode == 1 ? "ab" : "wb");
|
2009-02-23 22:40:09 +00:00
|
|
|
ctx->lgfp = f_open(ctx->currlogfilename, fmode, FALSE);
|
2015-09-25 08:15:21 +00:00
|
|
|
if (ctx->lgfp) {
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_OPEN;
|
2015-09-25 08:15:21 +00:00
|
|
|
} else {
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_ERROR;
|
2015-09-25 08:15:21 +00:00
|
|
|
shout = TRUE;
|
|
|
|
}
|
2005-02-18 18:33:31 +00:00
|
|
|
}
|
|
|
|
|
2018-09-26 10:48:11 +00:00
|
|
|
if (ctx->state == L_OPEN && conf_get_int(ctx->conf, CONF_logheader)) {
|
2005-02-18 18:33:31 +00:00
|
|
|
/* Write header line into log file. */
|
|
|
|
tm = ltime();
|
|
|
|
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
|
|
|
|
logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
|
|
|
|
" =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
event = dupprintf("%s session log (%s mode) to file: %s",
|
2009-08-30 11:09:22 +00:00
|
|
|
ctx->state == L_ERROR ?
|
|
|
|
(mode == 0 ? "Disabled writing" : "Error writing") :
|
|
|
|
(mode == 1 ? "Appending" : "Writing new"),
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
(ctx->logtype == LGTYP_ASCII ? "ASCII" :
|
|
|
|
ctx->logtype == LGTYP_DEBUG ? "raw" :
|
|
|
|
ctx->logtype == LGTYP_PACKETS ? "SSH packets" :
|
|
|
|
ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" :
|
2005-02-18 18:33:31 +00:00
|
|
|
"unknown"),
|
2011-10-02 11:01:57 +00:00
|
|
|
filename_to_str(ctx->currlogfilename));
|
2005-02-18 18:33:31 +00:00
|
|
|
logevent(ctx->frontend, event);
|
2015-09-25 08:15:21 +00:00
|
|
|
if (shout) {
|
|
|
|
/*
|
|
|
|
* If we failed to open the log file due to filesystem error
|
|
|
|
* (as opposed to user action such as clicking Cancel in the
|
|
|
|
* askappend box), we should log it more prominently. We do
|
|
|
|
* this by sending it to the same place that stderr output
|
|
|
|
* from the main session goes (so, either a console tool's
|
|
|
|
* actual stderr, or a terminal window).
|
|
|
|
*
|
|
|
|
* Of course this is one case in which that policy won't cause
|
|
|
|
* it to turn up embarrassingly in a log file of real server
|
|
|
|
* output, because the whole point is that we haven't managed
|
|
|
|
* to open any such log file :-)
|
|
|
|
*/
|
|
|
|
from_backend(ctx->frontend, 1, event, strlen(event));
|
|
|
|
from_backend(ctx->frontend, 1, "\r\n", 2);
|
|
|
|
}
|
2005-02-18 18:33:31 +00:00
|
|
|
sfree(event);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Having either succeeded or failed in opening the log file,
|
|
|
|
* we should write any queued data out.
|
|
|
|
*/
|
2005-02-18 22:03:15 +00:00
|
|
|
assert(ctx->state != L_OPENING); /* make _sure_ it won't be requeued */
|
2005-02-18 18:33:31 +00:00
|
|
|
while (bufchain_size(&ctx->queue)) {
|
|
|
|
void *data;
|
|
|
|
int len;
|
|
|
|
bufchain_prefix(&ctx->queue, &data, &len);
|
|
|
|
logwrite(ctx, data, len);
|
|
|
|
bufchain_consume(&ctx->queue, len);
|
|
|
|
}
|
2018-10-01 20:03:34 +00:00
|
|
|
logflush(ctx);
|
2005-02-18 18:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open the log file. Takes care of detecting an already-existing
|
|
|
|
* file and asking the user whether they want to append, overwrite
|
|
|
|
* or cancel logging.
|
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
void logfopen(LogContext *ctx)
|
2005-02-18 18:33:31 +00:00
|
|
|
{
|
|
|
|
struct tm tm;
|
|
|
|
int mode;
|
|
|
|
|
|
|
|
/* Prevent repeat calls */
|
2005-02-18 22:03:15 +00:00
|
|
|
if (ctx->state != L_CLOSED)
|
2005-02-18 18:33:31 +00:00
|
|
|
return;
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (!ctx->logtype)
|
2005-02-18 18:33:31 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
tm = ltime();
|
|
|
|
|
|
|
|
/* substitute special codes in file name */
|
2011-10-02 11:01:57 +00:00
|
|
|
if (ctx->currlogfilename)
|
|
|
|
filename_free(ctx->currlogfilename);
|
|
|
|
ctx->currlogfilename =
|
|
|
|
xlatlognam(conf_get_filename(ctx->conf, CONF_logfilename),
|
2015-08-08 12:35:44 +00:00
|
|
|
conf_get_str(ctx->conf, CONF_host),
|
|
|
|
conf_get_int(ctx->conf, CONF_port), &tm);
|
2005-02-18 18:33:31 +00:00
|
|
|
|
2018-02-07 07:22:18 +00:00
|
|
|
if (open_for_write_would_lose_data(ctx->currlogfilename)) {
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
|
|
|
|
if (logxfovr != LGXF_ASK) {
|
|
|
|
mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
|
2005-02-18 18:33:31 +00:00
|
|
|
} else
|
|
|
|
mode = askappend(ctx->frontend, ctx->currlogfilename,
|
|
|
|
logfopen_callback, ctx);
|
|
|
|
} else
|
|
|
|
mode = 2; /* create == overwrite */
|
|
|
|
|
|
|
|
if (mode < 0)
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_OPENING;
|
2005-02-18 18:33:31 +00:00
|
|
|
else
|
|
|
|
logfopen_callback(ctx, mode); /* open the file */
|
|
|
|
}
|
|
|
|
|
2018-09-11 14:17:16 +00:00
|
|
|
void logfclose(LogContext *ctx)
|
2005-02-18 18:33:31 +00:00
|
|
|
{
|
|
|
|
if (ctx->lgfp) {
|
|
|
|
fclose(ctx->lgfp);
|
|
|
|
ctx->lgfp = NULL;
|
|
|
|
}
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_CLOSED;
|
2005-02-18 18:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Log session traffic.
|
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
void logtraffic(LogContext *ctx, unsigned char c, int logmode)
|
2005-02-18 18:33:31 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (ctx->logtype > 0) {
|
|
|
|
if (ctx->logtype == logmode)
|
2005-02-18 18:33:31 +00:00
|
|
|
logwrite(ctx, &c, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-15 13:21:32 +00:00
|
|
|
/*
|
Remove FLAG_STDERR completely.
Originally, it controlled whether ssh.c should send terminal messages
(such as login and password prompts) to terminal.c or to stderr. But
we've had the from_backend() abstraction for ages now, which even has
an existing flag to indicate that the data is stderr rather than
stdout data; applications which set FLAG_STDERR are precisely those
that link against uxcons or wincons, so from_backend will do the
expected thing anyway with data sent to it with that flag set. So
there's no reason ssh.c can't just unconditionally pass everything
through that, and remove the special case.
FLAG_STDERR was also used by winproxy and uxproxy to decide whether to
capture standard error from a local proxy command, or whether to let
the proxy command send its diagnostics directly to the usual standard
error. On reflection, I think it's better to unconditionally capture
the proxy's stderr, for three reasons. Firstly, it means proxy
diagnostics are prefixed with 'proxy:' so that you can tell them apart
from any other stderr spew (which used to be particularly confusing if
both the main application and the proxy command were instances of
Plink); secondly, proxy diagnostics are now reliably copied to packet
log files along with all the other Event Log entries, even by
command-line tools; and thirdly, this means the option to suppress
proxy command diagnostics after the main session starts will actually
_work_ in the command-line tools, which it previously couldn't.
A more minor structure change is that copying of Event Log messages to
stderr in verbose mode is now done by wincons/uxcons, instead of
centrally in logging.c (since logging.c can now no longer check
FLAG_STDERR to decide whether to do it). The total amount of code to
do this is considerably smaller than the defensive-sounding comment in
logevent.c explaining why I did it the other way instead :-)
2018-09-21 15:15:49 +00:00
|
|
|
* Log an Event Log entry. Used in SSH packet logging mode, to copy
|
|
|
|
* the Event Log entries into the same log file as the packet data.
|
2002-09-15 13:21:32 +00:00
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
void log_eventlog(LogContext *ctx, const char *event)
|
2002-09-15 13:21:32 +00:00
|
|
|
{
|
2006-12-23 09:04:27 +00:00
|
|
|
/* If we don't have a context yet (eg winnet.c init) then skip entirely */
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (ctx->logtype != LGTYP_PACKETS &&
|
|
|
|
ctx->logtype != LGTYP_SSHRAW)
|
2002-09-15 13:21:32 +00:00
|
|
|
return;
|
2005-02-18 18:33:31 +00:00
|
|
|
logprintf(ctx, "Event Log: %s\r\n", event);
|
New logging mode, which records the exact bytes sent over the wire
in an SSH connection _in addition_ to the decrypted packets. This
will hopefully come in useful for debugging wire data corruption
issues: you can strace the server, enable this mode in the client,
and compare the sent and received data.
I'd _like_ to have this mode also log Diffie-Hellman private
exponents, session IDs, encryption and MAC keys, so that the
resulting log file could be used to independently verify the
correctness of all cryptographic operations performed by PuTTY.
However, I haven't been able to convince myself that the security
implications are acceptable. (It doesn't matter that this
information would permit an attacker to decrypt the session, because
the _already_ decrypted session is stored alongside it in the log
file. And I'm not planning, under any circumstances, to log users'
private keys. But gaining access to the log file while the session
was still running would permit an attacker to _hijack_ the session,
and that's the iffy bit.)
[originally from svn r6835]
2006-08-29 19:07:11 +00:00
|
|
|
logflush(ctx);
|
2002-09-15 13:21:32 +00:00
|
|
|
}
|
|
|
|
|
2001-12-14 14:57:50 +00:00
|
|
|
/*
|
|
|
|
* Log an SSH packet.
|
2004-10-02 00:33:27 +00:00
|
|
|
* If n_blanks != 0, blank or omit some parts.
|
|
|
|
* Set of blanking areas must be in increasing order.
|
2001-12-14 14:57:50 +00:00
|
|
|
*/
|
2018-09-11 14:17:16 +00:00
|
|
|
void log_packet(LogContext *ctx, int direction, int type,
|
2015-05-15 10:15:42 +00:00
|
|
|
const char *texttype, const void *data, int len,
|
2008-11-11 07:47:27 +00:00
|
|
|
int n_blanks, const struct logblank_t *blanks,
|
2013-11-17 14:05:41 +00:00
|
|
|
const unsigned long *seq,
|
|
|
|
unsigned downstream_id, const char *additional_log_text)
|
2001-12-14 14:57:50 +00:00
|
|
|
{
|
|
|
|
char dumpdata[80], smalldata[5];
|
2005-02-18 18:33:31 +00:00
|
|
|
int p = 0, b = 0, omitted = 0;
|
|
|
|
int output_pos = 0; /* NZ if pending output in dumpdata */
|
2001-12-14 14:57:50 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (!(ctx->logtype == LGTYP_SSHRAW ||
|
|
|
|
(ctx->logtype == LGTYP_PACKETS && texttype)))
|
2001-12-14 14:57:50 +00:00
|
|
|
return;
|
2004-10-02 00:33:27 +00:00
|
|
|
|
2005-02-18 18:33:31 +00:00
|
|
|
/* Packet header. */
|
2008-11-11 07:47:27 +00:00
|
|
|
if (texttype) {
|
2013-11-17 14:05:41 +00:00
|
|
|
logprintf(ctx, "%s packet ",
|
|
|
|
direction == PKT_INCOMING ? "Incoming" : "Outgoing");
|
|
|
|
|
|
|
|
if (seq)
|
|
|
|
logprintf(ctx, "#0x%lx, ", *seq);
|
|
|
|
|
|
|
|
logprintf(ctx, "type %d / 0x%02x (%s)", type, type, texttype);
|
|
|
|
|
|
|
|
if (downstream_id) {
|
|
|
|
logprintf(ctx, " on behalf of downstream #%u", downstream_id);
|
|
|
|
if (additional_log_text)
|
|
|
|
logprintf(ctx, " (%s)", additional_log_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
logprintf(ctx, "\r\n");
|
2008-11-11 07:47:27 +00:00
|
|
|
} else {
|
2012-10-10 18:32:23 +00:00
|
|
|
/*
|
|
|
|
* Raw data is logged with a timestamp, so that it's possible
|
|
|
|
* to determine whether a mysterious delay occurred at the
|
|
|
|
* client or server end. (Timestamping the raw data avoids
|
|
|
|
* cluttering the normal case of only logging decrypted SSH
|
|
|
|
* messages, and also adds conceptual rigour in the case where
|
|
|
|
* an SSH message arrives in several pieces.)
|
|
|
|
*/
|
|
|
|
char buf[256];
|
|
|
|
struct tm tm;
|
|
|
|
tm = ltime();
|
|
|
|
strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
|
|
|
logprintf(ctx, "%s raw data at %s\r\n",
|
|
|
|
direction == PKT_INCOMING ? "Incoming" : "Outgoing",
|
|
|
|
buf);
|
2008-11-11 07:47:27 +00:00
|
|
|
}
|
2005-02-18 18:33:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Output a hex/ASCII dump of the packet body, blanking/omitting
|
|
|
|
* parts as specified.
|
|
|
|
*/
|
|
|
|
while (p < len) {
|
|
|
|
int blktype;
|
|
|
|
|
|
|
|
/* Move to a current entry in the blanking array. */
|
|
|
|
while ((b < n_blanks) &&
|
|
|
|
(p >= blanks[b].offset + blanks[b].len))
|
|
|
|
b++;
|
|
|
|
/* Work out what type of blanking to apply to
|
|
|
|
* this byte. */
|
|
|
|
blktype = PKTLOG_EMIT; /* default */
|
|
|
|
if ((b < n_blanks) &&
|
|
|
|
(p >= blanks[b].offset) &&
|
|
|
|
(p < blanks[b].offset + blanks[b].len))
|
|
|
|
blktype = blanks[b].type;
|
|
|
|
|
|
|
|
/* If we're about to stop omitting, it's time to say how
|
|
|
|
* much we omitted. */
|
|
|
|
if ((blktype != PKTLOG_OMIT) && omitted) {
|
|
|
|
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
|
|
|
omitted, (omitted==1?"":"s"));
|
|
|
|
omitted = 0;
|
|
|
|
}
|
2004-10-02 00:33:27 +00:00
|
|
|
|
2005-02-18 18:33:31 +00:00
|
|
|
/* (Re-)initialise dumpdata as necessary
|
|
|
|
* (start of row, or if we've just stopped omitting) */
|
|
|
|
if (!output_pos && !omitted)
|
|
|
|
sprintf(dumpdata, " %08x%*s\r\n", p-(p%16), 1+3*16+2+16, "");
|
|
|
|
|
|
|
|
/* Deal with the current byte. */
|
|
|
|
if (blktype == PKTLOG_OMIT) {
|
|
|
|
omitted++;
|
|
|
|
} else {
|
|
|
|
int c;
|
|
|
|
if (blktype == PKTLOG_BLANK) {
|
|
|
|
c = 'X';
|
|
|
|
sprintf(smalldata, "XX");
|
|
|
|
} else { /* PKTLOG_EMIT */
|
|
|
|
c = ((unsigned char *)data)[p];
|
|
|
|
sprintf(smalldata, "%02x", c);
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
2005-02-18 18:33:31 +00:00
|
|
|
dumpdata[10+2+3*(p%16)] = smalldata[0];
|
|
|
|
dumpdata[10+2+3*(p%16)+1] = smalldata[1];
|
2017-11-27 20:39:17 +00:00
|
|
|
dumpdata[10+1+3*16+2+(p%16)] = (c >= 0x20 && c < 0x7F ? c : '.');
|
2005-02-18 18:33:31 +00:00
|
|
|
output_pos = (p%16) + 1;
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
2004-10-02 00:33:27 +00:00
|
|
|
|
2005-02-18 18:33:31 +00:00
|
|
|
p++;
|
2001-12-14 14:57:50 +00:00
|
|
|
|
2005-02-18 18:33:31 +00:00
|
|
|
/* Flush row if necessary */
|
|
|
|
if (((p % 16) == 0) || (p == len) || omitted) {
|
|
|
|
if (output_pos) {
|
|
|
|
strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
|
|
|
|
logwrite(ctx, dumpdata, strlen(dumpdata));
|
|
|
|
output_pos = 0;
|
|
|
|
}
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2005-02-18 18:33:31 +00:00
|
|
|
/* Tidy up */
|
|
|
|
if (omitted)
|
|
|
|
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
|
|
|
omitted, (omitted==1?"":"s"));
|
|
|
|
logflush(ctx);
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 08:10:51 +00:00
|
|
|
LogContext *log_init(Frontend *frontend, Conf *conf)
|
2002-10-26 12:58:13 +00:00
|
|
|
{
|
2018-09-11 14:17:16 +00:00
|
|
|
LogContext *ctx = snew(LogContext);
|
2002-10-26 12:58:13 +00:00
|
|
|
ctx->lgfp = NULL;
|
2005-02-18 22:03:15 +00:00
|
|
|
ctx->state = L_CLOSED;
|
2002-10-26 12:58:13 +00:00
|
|
|
ctx->frontend = frontend;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
ctx->conf = conf_copy(conf);
|
|
|
|
ctx->logtype = conf_get_int(ctx->conf, CONF_logtype);
|
2011-10-02 11:01:57 +00:00
|
|
|
ctx->currlogfilename = NULL;
|
2005-02-18 18:33:31 +00:00
|
|
|
bufchain_init(&ctx->queue);
|
2002-10-26 12:58:13 +00:00
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
2018-09-11 14:17:16 +00:00
|
|
|
void log_free(LogContext *ctx)
|
2003-01-15 23:30:21 +00:00
|
|
|
{
|
|
|
|
logfclose(ctx);
|
2005-02-18 18:33:31 +00:00
|
|
|
bufchain_clear(&ctx->queue);
|
2011-10-02 11:01:57 +00:00
|
|
|
if (ctx->currlogfilename)
|
|
|
|
filename_free(ctx->currlogfilename);
|
2014-11-09 00:54:35 +00:00
|
|
|
conf_free(ctx->conf);
|
2003-01-15 23:30:21 +00:00
|
|
|
sfree(ctx);
|
|
|
|
}
|
|
|
|
|
2018-09-11 14:17:16 +00:00
|
|
|
void log_reconfig(LogContext *ctx, Conf *conf)
|
2003-01-12 15:10:27 +00:00
|
|
|
{
|
|
|
|
int reset_logging;
|
|
|
|
|
2011-10-02 11:01:57 +00:00
|
|
|
if (!filename_equal(conf_get_filename(ctx->conf, CONF_logfilename),
|
|
|
|
conf_get_filename(conf, CONF_logfilename)) ||
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_get_int(ctx->conf, CONF_logtype) !=
|
|
|
|
conf_get_int(conf, CONF_logtype))
|
2003-01-12 15:10:27 +00:00
|
|
|
reset_logging = TRUE;
|
|
|
|
else
|
|
|
|
reset_logging = FALSE;
|
|
|
|
|
|
|
|
if (reset_logging)
|
2003-01-12 15:42:24 +00:00
|
|
|
logfclose(ctx);
|
2003-01-12 15:10:27 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_free(ctx->conf);
|
|
|
|
ctx->conf = conf_copy(conf);
|
|
|
|
|
|
|
|
ctx->logtype = conf_get_int(ctx->conf, CONF_logtype);
|
2003-01-12 15:10:27 +00:00
|
|
|
|
|
|
|
if (reset_logging)
|
2003-01-12 15:42:24 +00:00
|
|
|
logfopen(ctx);
|
2003-01-12 15:10:27 +00:00
|
|
|
}
|
|
|
|
|
2001-12-14 14:57:50 +00:00
|
|
|
/*
|
|
|
|
* translate format codes into time/date strings
|
|
|
|
* and insert them into log file name
|
|
|
|
*
|
2006-10-31 16:59:56 +00:00
|
|
|
* "&Y":YYYY "&m":MM "&d":DD "&T":hhmmss "&h":<hostname> "&&":&
|
2001-12-14 14:57:50 +00:00
|
|
|
*/
|
2015-08-08 12:35:44 +00:00
|
|
|
static Filename *xlatlognam(Filename *src, char *hostname, int port,
|
|
|
|
struct tm *tm)
|
2011-10-02 11:01:57 +00:00
|
|
|
{
|
2015-08-08 12:35:44 +00:00
|
|
|
char buf[32], *bufp;
|
2001-12-14 14:57:50 +00:00
|
|
|
int size;
|
2011-10-02 11:01:57 +00:00
|
|
|
char *buffer;
|
|
|
|
int buflen, bufsize;
|
2003-02-01 17:24:27 +00:00
|
|
|
const char *s;
|
2011-10-02 11:01:57 +00:00
|
|
|
Filename *ret;
|
2003-02-01 12:54:40 +00:00
|
|
|
|
2011-10-02 11:01:57 +00:00
|
|
|
bufsize = FILENAME_MAX;
|
|
|
|
buffer = snewn(bufsize, char);
|
|
|
|
buflen = 0;
|
|
|
|
s = filename_to_str(src);
|
2001-12-14 14:57:50 +00:00
|
|
|
|
|
|
|
while (*s) {
|
2015-09-25 08:23:26 +00:00
|
|
|
int sanitise = FALSE;
|
2001-12-14 14:57:50 +00:00
|
|
|
/* Let (bufp, len) be the string to append. */
|
|
|
|
bufp = buf; /* don't usually override this */
|
|
|
|
if (*s == '&') {
|
|
|
|
char c;
|
|
|
|
s++;
|
2002-10-09 18:09:42 +00:00
|
|
|
size = 0;
|
2009-01-11 14:26:27 +00:00
|
|
|
if (*s) switch (c = *s++, tolower((unsigned char)c)) {
|
2001-12-14 14:57:50 +00:00
|
|
|
case 'y':
|
|
|
|
size = strftime(buf, sizeof(buf), "%Y", tm);
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
size = strftime(buf, sizeof(buf), "%m", tm);
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
size = strftime(buf, sizeof(buf), "%d", tm);
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
size = strftime(buf, sizeof(buf), "%H%M%S", tm);
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
bufp = hostname;
|
|
|
|
size = strlen(bufp);
|
|
|
|
break;
|
2015-08-08 12:35:44 +00:00
|
|
|
case 'p':
|
|
|
|
size = sprintf(buf, "%d", port);
|
|
|
|
break;
|
2001-12-14 14:57:50 +00:00
|
|
|
default:
|
|
|
|
buf[0] = '&';
|
|
|
|
size = 1;
|
|
|
|
if (c != '&')
|
|
|
|
buf[size++] = c;
|
|
|
|
}
|
2015-09-25 08:23:26 +00:00
|
|
|
/* Never allow path separators - or any other illegal
|
|
|
|
* filename character - to come out of any of these
|
|
|
|
* auto-format directives. E.g. 'hostname' can contain
|
|
|
|
* colons, if it's an IPv6 address, and colons aren't
|
|
|
|
* legal in filenames on Windows. */
|
|
|
|
sanitise = TRUE;
|
2001-12-14 14:57:50 +00:00
|
|
|
} else {
|
|
|
|
buf[0] = *s++;
|
|
|
|
size = 1;
|
|
|
|
}
|
2011-10-02 11:01:57 +00:00
|
|
|
if (bufsize <= buflen + size) {
|
|
|
|
bufsize = (buflen + size) * 5 / 4 + 512;
|
|
|
|
buffer = sresize(buffer, bufsize, char);
|
|
|
|
}
|
2015-09-25 08:23:26 +00:00
|
|
|
while (size-- > 0) {
|
|
|
|
char c = *bufp++;
|
|
|
|
if (sanitise)
|
|
|
|
c = filename_char_sanitise(c);
|
|
|
|
buffer[buflen++] = c;
|
|
|
|
}
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|
2011-10-02 11:01:57 +00:00
|
|
|
buffer[buflen] = '\0';
|
2003-02-01 12:54:40 +00:00
|
|
|
|
2011-10-02 11:01:57 +00:00
|
|
|
ret = filename_from_str(buffer);
|
|
|
|
sfree(buffer);
|
|
|
|
return ret;
|
2001-12-14 14:57:50 +00:00
|
|
|
}
|