summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-09-07 18:06:11 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-09-07 22:48:23 +0300
commitf08e6e0842bae2dd575b085a8182cdd0f0d55cc5 (patch)
treee3f8db0cf4c735771eee74a4239914a62106683a
parent817286698ccc3f262cd0003401becef6c11050ae (diff)
downloadmailutils-f08e6e0842bae2dd575b085a8182cdd0f0d55cc5.tar.gz
mailutils-f08e6e0842bae2dd575b085a8182cdd0f0d55cc5.tar.bz2
Improve transcript stream.
* include/mailutils/stream.h (MU_IOCTL_LEVEL): New ioctl op. (XSCRIPT_NORMAL, XSCRIPT_SECURE, XSCRIPT_PAYLOAD): New constants. * include/mailutils/sys/xscript-stream.h (_mu_xscript_stream) <level>: New member. * mailbox/xscript-stream.c (TRANS_DISABLED): New flag. (print_transcript): Amount of output varies depending on the current output level. For secure data, try to recognize passwords and to replace them with *** on output. (_xscript_ctl): Support MU_IOCTL_LEVEL. * pop3d/extra.c (set_xscript_level): New function. * pop3d/pop3d.h (set_xscript_level): New proto. * pop3d/retr.c (pop3d_retr): Set XSCRIPT_PAYLOAD level before sending actual data and reset it to XSCRIPT_NORMAL afterwards. * pop3d/top.c (pop3d_top): Likewise. * pop3d/user.c: Set XSCRIPT_SECURE level while expecting the PASS command. * imap4d/fetch.c (imap4d_fetch): Run imap4d_fetch0 in XSCRIPT_PAYLOAD level. * imap4d/uid.c (imap4d_uid): Likewise. * imap4d/imap4d.c (imap4d_mainloop): Unless started in preauth mode, select XSCRIPT_SECURE mode until authentication has been passed. * imap4d/imap4d.h (set_xscript_level): New proto. * imap4d/io.c (io_format_completion_response): Switch to XSCRIPT_NORMAL level when changing to the authenticated state. (imap4d_readline): Read literals in XSCRIPT_PAYLOAD level. * imap4d/util.c (set_xscript_level): New function. * include/mailutils/pop3.h (mu_pop3_trace_mask): New prototype. (MU_POP3_XSCRIPT_MASK): New macro. (_mu_pop3_xscript_level): New proto. * libproto/pop/pop3_pass.c (mu_pop3_pass): Set XSCRIPT_SECURE while sending the password. * libproto/pop/pop3_retr.c (mu_pop3_retr): Set XSCRIPT_PAYLOAD before going to MU_POP3_RETR_RX state. * libproto/pop/pop3_stream.c (_pop3_event_cb): Set XSCRIPT_NORMAL. * libproto/pop/pop3_top.c (mu_pop3_top): Set XSCRIPT_PAYLOAD before going to MU_POP3_TOP_RX state. * libproto/pop/pop3_trace.c (mu_pop3_trace_mask) (_mu_pop3_xscript_level): New functions. * libproto/pop/mbox.c (pop_open): Set trace masks depending on the trace6 and trace7 debug levels. * examples/pop3client.c (com_verbose): Allow to mask/unmask transcript levels.
-rw-r--r--examples/pop3client.c127
-rw-r--r--imap4d/fetch.c3
-rw-r--r--imap4d/imap4d.c4
-rw-r--r--imap4d/imap4d.h4
-rw-r--r--imap4d/io.c8
-rw-r--r--imap4d/uid.c6
-rw-r--r--imap4d/util.c19
-rw-r--r--include/mailutils/pop3.h1
-rw-r--r--include/mailutils/stream.h9
-rw-r--r--include/mailutils/sys/pop3.h3
-rw-r--r--include/mailutils/sys/xscript-stream.h1
-rw-r--r--libproto/pop/mbox.c10
-rw-r--r--libproto/pop/pop3_pass.c5
-rw-r--r--libproto/pop/pop3_retr.c2
-rw-r--r--libproto/pop/pop3_stream.c1
-rw-r--r--libproto/pop/pop3_top.c2
-rw-r--r--libproto/pop/pop3_trace.c32
-rw-r--r--mailbox/xscript-stream.c166
-rw-r--r--pop3d/extra.c20
-rw-r--r--pop3d/pop3d.h2
-rw-r--r--pop3d/retr.c4
-rw-r--r--pop3d/top.c5
-rw-r--r--pop3d/user.c5
23 files changed, 377 insertions, 62 deletions
diff --git a/examples/pop3client.c b/examples/pop3client.c
index 677cd888b..4450f2243 100644
--- a/examples/pop3client.c
+++ b/examples/pop3client.c
@@ -131,8 +131,8 @@ COMMAND commands[] = {
"Get the unique id of message: UIDL [msgno]" },
{ "user", 2, 2, com_user,
"send login: USER user" },
- { "verbose", 1, 2, com_verbose,
- "Enable Protocol tracing: verbose [on|off]" },
+ { "verbose", 1, 4, com_verbose,
+ "Enable Protocol tracing: verbose [on|off|mask|unmask] [x1 [x2]]" },
#ifdef WITH_READLINE
{ "history", 1, 1, com_history,
"Show command history" },
@@ -145,6 +145,14 @@ mu_pop3_t pop3;
/* Flag if verbosity is needed. */
int verbose;
+#define VERBOSE_MASK(n) (1<<((n)+1))
+#define SET_VERBOSE_MASK(n) (verbose |= VERBOSE_MASK (n))
+#define CLR_VERBOSE_MASK(n) (verbose &= VERBOSE_MASK (n))
+#define QRY_VERBOSE_MASK(n) (verbose & VERBOSE_MASK (n))
+#define HAS_VERBOSE_MASK(n) (verbose & ~1)
+#define SET_VERBOSE() (verbose |= 1)
+#define CLR_VERBOSE() (verbose &= ~1)
+#define QRY_VERBOSE() (verbose & 1)
/* When non-zero, this global means the user is done using this program. */
int done;
@@ -408,10 +416,8 @@ get_bool (const char *str, int *pb)
|| mu_c_strcasecmp (str, "false") == 0)
*pb = 0;
else
- {
- mu_error ("not a boolean: %s", str);
- return 1;
- }
+ return 1;
+
return 0;
}
@@ -509,13 +515,91 @@ find_command (char *name)
return NULL;
}
+static int
+string_to_xlev (const char *name, int *pv)
+{
+ if (strcmp (name, "secure") == 0)
+ *pv = XSCRIPT_SECURE;
+ else if (strcmp (name, "payload") == 0)
+ *pv = XSCRIPT_PAYLOAD;
+ else
+ return 1;
+ return 0;
+}
+
+static int
+change_verbose_mask (int set, int argc, char **argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ {
+ int lev;
+
+ if (string_to_xlev (argv[i], &lev))
+ {
+ mu_error ("unknown level: %s", argv[i]);
+ return 1;
+ }
+ if (set)
+ SET_VERBOSE_MASK (lev);
+ else
+ CLR_VERBOSE_MASK (lev);
+ }
+ return 0;
+}
+
+void
+set_verbose (mu_pop3_t p)
+{
+ if (p)
+ {
+ if (QRY_VERBOSE ())
+ {
+ mu_pop3_trace (p, MU_POP3_TRACE_SET);
+ }
+ else
+ mu_pop3_trace (p, MU_POP3_TRACE_CLR);
+ }
+}
+
+void
+set_verbose_mask (mu_pop3_t p)
+{
+ if (p)
+ {
+ mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (XSCRIPT_SECURE)
+ ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
+ XSCRIPT_SECURE);
+ mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (XSCRIPT_PAYLOAD)
+ ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
+ XSCRIPT_PAYLOAD);
+ }
+}
+
int
com_verbose (int argc, char **argv)
{
if (argc == 1)
{
- if (verbose)
- printf ("verbose is on\n");
+ if (QRY_VERBOSE ())
+ {
+ printf ("verbose is on");
+ if (HAS_VERBOSE_MASK ())
+ {
+ char *delim = " (";
+
+ if (QRY_VERBOSE_MASK (XSCRIPT_SECURE))
+ {
+ printf("%ssecure", delim);
+ delim = ", ";
+ }
+ if (QRY_VERBOSE_MASK (XSCRIPT_PAYLOAD))
+ printf("%spayload", delim);
+ printf (")");
+ }
+ printf ("\n");
+ }
else
printf ("verbose is off\n");
}
@@ -525,16 +609,20 @@ com_verbose (int argc, char **argv)
if (get_bool (argv[1], &bv) == 0)
{
- verbose = bv;
- if (pop3 != NULL)
- {
- if (verbose == 1)
- mu_pop3_trace (pop3, MU_POP3_TRACE_SET);
- else
- mu_pop3_trace (pop3, MU_POP3_TRACE_CLR);
- }
+ verbose |= bv;
+ if (argc > 2)
+ change_verbose_mask (verbose, argc - 2, argv + 2);
+ set_verbose (pop3);
}
+ else if (strcmp (argv[1], "mask") == 0)
+ change_verbose_mask (1, argc - 2, argv + 2);
+ else if (strcmp (argv[1], "unmask") == 0)
+ change_verbose_mask (0, argc - 2, argv + 2);
+ else
+ mu_error ("unknown subcommand");
+ set_verbose_mask (pop3);
}
+
return 0;
}
@@ -929,8 +1017,11 @@ com_connect (int argc, char **argv)
{
mu_stream_t tcp;
- if (verbose)
- mu_pop3_trace (pop3, MU_POP3_TRACE_SET);
+ if (QRY_VERBOSE ())
+ {
+ set_verbose (pop3);
+ set_verbose_mask (pop3);
+ }
status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ);
if (status == 0)
{
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index 618409b62..8f9339d51 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -1688,7 +1688,8 @@ imap4d_fetch (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
int rc;
char *err_text = "Completed";
-
+ int xlev = set_xscript_level (XSCRIPT_PAYLOAD);
rc = imap4d_fetch0 (tok, 0, &err_text);
+ set_xscript_level (xlev);
return io_completion_response (command, rc, "%s", err_text);
}
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 1df39659a..340c2bb15 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -417,11 +417,13 @@ imap4d_mainloop (int fd, FILE *infile, FILE *outfile)
return 0;
}
- /* Greetings. */
+ /* Greetings. */
io_untagged_response ((state == STATE_AUTH) ?
RESP_PREAUTH : RESP_OK, "%s", text);
io_flush ();
+ set_xscript_level ((state == STATE_AUTH) ? XSCRIPT_NORMAL : XSCRIPT_SECURE);
+
tokp = imap4d_tokbuf_init ();
while (1)
{
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index ba6ef6516..7618107d0 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -381,7 +381,9 @@ void util_chdir (const char *homedir);
int is_atom (const char *s);
int util_isdelim (const char *str);
int util_trim_nl (char *s, size_t len);
-
+
+int set_xscript_level (int xlev);
+
#ifdef WITH_TLS
int imap4d_init_tls_server (void);
#endif /* WITH_TLS */
diff --git a/imap4d/io.c b/imap4d/io.c
index a8b6cb0be..fcae10707 100644
--- a/imap4d/io.c
+++ b/imap4d/io.c
@@ -241,7 +241,11 @@ io_format_completion_response (mu_stream_t str,
new_state = STATE_NONE;
if (new_state != STATE_NONE)
- state = new_state;
+ {
+ if (new_state == STATE_AUTH)
+ set_xscript_level (XSCRIPT_NORMAL);
+ state = new_state;
+ }
return status;
}
@@ -570,6 +574,7 @@ imap4d_readline (struct imap4d_tokbuf *tok)
char *sp = NULL;
char *buf;
size_t len;
+ int xlev = set_xscript_level (XSCRIPT_PAYLOAD);
number = strtoul (last_arg + 1, &sp, 10);
/* Client can ask for non-synchronised literal,
@@ -595,6 +600,7 @@ imap4d_readline (struct imap4d_tokbuf *tok)
tok->level += len;
tok->buffer[tok->level++] = 0;
tok->argp[tok->argc - 1] = off;
+ set_xscript_level (xlev);
}
else
break;
diff --git a/imap4d/uid.c b/imap4d/uid.c
index 739aff9f6..9d34b4609 100644
--- a/imap4d/uid.c
+++ b/imap4d/uid.c
@@ -37,7 +37,11 @@ imap4d_uid (struct imap4d_command *command, imap4d_tokbuf_t tok)
cmd = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
if (mu_c_strcasecmp (cmd, "FETCH") == 0)
- rc = imap4d_fetch0 (tok, 1, &err_text);
+ {
+ int xlev = set_xscript_level (XSCRIPT_PAYLOAD);
+ rc = imap4d_fetch0 (tok, 1, &err_text);
+ set_xscript_level (xlev);
+ }
else if (mu_c_strcasecmp (cmd, "COPY") == 0)
rc = imap4d_copy0 (tok, 1, &err_text);
else if (mu_c_strcasecmp (cmd, "STORE") == 0)
diff --git a/imap4d/util.c b/imap4d/util.c
index a4c504331..af081fecc 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -672,3 +672,22 @@ is_atom (const char *s)
return 1;
}
+int
+set_xscript_level (int xlev)
+{
+ if (imap4d_transcript)
+ {
+ if (xlev != XSCRIPT_NORMAL)
+ {
+ mu_log_level_t n = xlev == XSCRIPT_SECURE ?
+ MU_DEBUG_TRACE6 : MU_DEBUG_TRACE7;
+
+ if (mu_global_debug_level ("imap4") & MU_DEBUG_LEVEL_MASK (n))
+ return XSCRIPT_NORMAL;
+ }
+
+ if (mu_stream_ioctl (iostream, MU_IOCTL_LEVEL, &xlev) == 0)
+ return xlev;
+ }
+ return 0;
+}
diff --git a/include/mailutils/pop3.h b/include/mailutils/pop3.h
index a6ced1008..53d6c1696 100644
--- a/include/mailutils/pop3.h
+++ b/include/mailutils/pop3.h
@@ -50,6 +50,7 @@ int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout);
#define MU_POP3_TRACE_SET 1
#define MU_POP3_TRACE_QRY 2
int mu_pop3_trace (mu_pop3_t pop3, int op);
+int mu_pop3_trace_mask (mu_pop3_t pop3, int op, int lev);
int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest);
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index e7d04ea4d..ab1d9c4d7 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -63,6 +63,9 @@ enum mu_buffer_type
#define MU_IOCTL_SET_TRANSPORT 6
#define MU_IOCTL_SWAP_STREAM 7
+#define MU_IOCTL_LEVEL 8
+
+
void mu_stream_ref (mu_stream_t stream);
void mu_stream_unref (mu_stream_t stream);
void mu_stream_destroy (mu_stream_t *pstream);
@@ -153,9 +156,15 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port,
int flags);
+/* Transcript output levels */
+#define XSCRIPT_NORMAL 0 /* Normal transcript */
+#define XSCRIPT_SECURE 1 /* Security-related data are being sent/received */
+#define XSCRIPT_PAYLOAD 2 /* Actual payload (may be copious) */
+
int mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport,
mu_stream_t logstr,
const char *prefix[]);
+
int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out);
int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug,
mu_log_level_t level, int flags);
diff --git a/include/mailutils/sys/pop3.h b/include/mailutils/sys/pop3.h
index 1c81579d0..55bedebd1 100644
--- a/include/mailutils/sys/pop3.h
+++ b/include/mailutils/sys/pop3.h
@@ -59,6 +59,7 @@ enum mu_pop3_state
#define MU_POP3_ACK 0x01
#define MU_POP3_TRACE 0x02
+#define MU_POP3_XSCRIPT_MASK(n) (1<<((n)+1))
/* Structure to hold things general to POP3 mailbox, like its state, etc ... */
struct _mu_pop3
@@ -90,6 +91,8 @@ extern int mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream);
extern int mu_pop3_carrier_is_ready (mu_stream_t carrier, int flag,
int timeout);
+int _mu_pop3_xscript_level (mu_pop3_t pop3, int xlev);
+
int _mu_pop3_trace_enable (mu_pop3_t pop3);
int _mu_pop3_trace_disable (mu_pop3_t pop3);
diff --git a/include/mailutils/sys/xscript-stream.h b/include/mailutils/sys/xscript-stream.h
index c6b45387a..0f58bb901 100644
--- a/include/mailutils/sys/xscript-stream.h
+++ b/include/mailutils/sys/xscript-stream.h
@@ -27,6 +27,7 @@ struct _mu_xscript_stream
mu_stream_t transport;
mu_stream_t logstr;
int flags;
+ int level;
char *prefix[2];
};
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index ced5126f2..68e2d93db 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -161,7 +161,11 @@ pop_open (mu_mailbox_t mbox, int flags)
if (mu_debug_check_level (mbox->debug, MU_DEBUG_PROT))
mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET);
-
+ if (mu_debug_check_level (mbox->debug, MU_DEBUG_TRACE6))
+ mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, XSCRIPT_SECURE);
+ if (mu_debug_check_level (mbox->debug, MU_DEBUG_TRACE7))
+ mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, XSCRIPT_PAYLOAD);
+
do
{
status = mu_pop3_connect (mpd->pop3);
@@ -214,7 +218,7 @@ pop_destroy (mu_mailbox_t mbox)
{
size_t i;
mu_monitor_wrlock (mbox->monitor);
- /* Destroy the pop messages and ressources associated to them. */
+ /* Destroy the pop messages and resources associated to them. */
for (i = 0; i < mpd->msg_count; i++)
{
if (mpd->msg[i])
@@ -291,7 +295,7 @@ pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD,
&tmp) != 0)
break;
- if (((i +1) % 10) == 0)
+ if (((i + 1) % 10) == 0)
{
mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS,
NULL);
diff --git a/libproto/pop/pop3_pass.c b/libproto/pop/pop3_pass.c
index 77b860b2f..30f823f96 100644
--- a/libproto/pop/pop3_pass.c
+++ b/libproto/pop/pop3_pass.c
@@ -28,14 +28,17 @@ int
mu_pop3_pass (mu_pop3_t pop3, const char *passwd)
{
int status;
-
+
if (pop3 == NULL || passwd == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
+ if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_SECURE))
+ _mu_pop3_xscript_level (pop3, XSCRIPT_SECURE);
status = mu_pop3_writeline (pop3, "PASS %s\r\n", passwd);
+ _mu_pop3_xscript_level (pop3, XSCRIPT_NORMAL);
MU_POP3_CHECK_ERROR (pop3, status);
/* FIXME: how to obscure the passwd in the stream buffer? */
MU_POP3_FCLR (pop3, MU_POP3_ACK);
diff --git a/libproto/pop/pop3_retr.c b/libproto/pop/pop3_retr.c
index 2189075e9..fc454da93 100644
--- a/libproto/pop/pop3_retr.c
+++ b/libproto/pop/pop3_retr.c
@@ -50,6 +50,8 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream)
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
+ if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_PAYLOAD))
+ _mu_pop3_xscript_level (pop3, XSCRIPT_PAYLOAD);
pop3->state = MU_POP3_RETR_RX;
case MU_POP3_RETR_RX:
diff --git a/libproto/pop/pop3_stream.c b/libproto/pop/pop3_stream.c
index 689bec42b..bd2bd078f 100644
--- a/libproto/pop/pop3_stream.c
+++ b/libproto/pop/pop3_stream.c
@@ -185,6 +185,7 @@ _pop3_event_cb (mu_stream_t str, int ev, int flags)
if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0)
{
struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0];
+ _mu_pop3_xscript_level (sp->pop3, XSCRIPT_NORMAL);
sp->pop3->state = MU_POP3_NO_STATE;
}
}
diff --git a/libproto/pop/pop3_top.c b/libproto/pop/pop3_top.c
index 93957e59a..ebea77fb4 100644
--- a/libproto/pop/pop3_top.c
+++ b/libproto/pop/pop3_top.c
@@ -50,6 +50,8 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines,
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
+ if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_PAYLOAD))
+ _mu_pop3_xscript_level (pop3, XSCRIPT_PAYLOAD);
pop3->state = MU_POP3_TOP_RX;
case MU_POP3_TOP_RX:
diff --git a/libproto/pop/pop3_trace.c b/libproto/pop/pop3_trace.c
index 1a4c27f13..514ac3cad 100644
--- a/libproto/pop/pop3_trace.c
+++ b/libproto/pop/pop3_trace.c
@@ -115,4 +115,36 @@ mu_pop3_trace (mu_pop3_t pop3, int op)
return EINVAL;
}
+int
+mu_pop3_trace_mask (mu_pop3_t pop3, int op, int lev)
+{
+ switch (op)
+ {
+ case MU_POP3_TRACE_SET:
+ pop3->flags |= MU_POP3_XSCRIPT_MASK(lev);
+ break;
+
+ case MU_POP3_TRACE_CLR:
+ pop3->flags &= ~MU_POP3_XSCRIPT_MASK(lev);
+ break;
+
+ case MU_POP3_TRACE_QRY:
+ if (pop3->flags & MU_POP3_XSCRIPT_MASK(lev))
+ break;
+ return MU_ERR_NOENT;
+
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+int
+_mu_pop3_xscript_level (mu_pop3_t pop3, int xlev)
+{
+ if (mu_stream_ioctl (pop3->carrier, MU_IOCTL_LEVEL, &xlev) == 0)
+ return xlev;
+ return XSCRIPT_NORMAL;
+}
+
diff --git a/mailbox/xscript-stream.c b/mailbox/xscript-stream.c
index 993047560..054ced12c 100644
--- a/mailbox/xscript-stream.c
+++ b/mailbox/xscript-stream.c
@@ -30,6 +30,8 @@
#include <mailutils/stream.h>
#include <mailutils/sys/stream.h>
#include <mailutils/sys/xscript-stream.h>
+#include <mailutils/cctype.h>
+#include <mailutils/cstr.h>
/* A "transcript stream" transparently writes data to and reads data from
an underlying transport stream, writing each lineful of data to a "log
@@ -38,47 +40,131 @@
RFCs -- "S: ", for data written ("Server"), and "C: ", for data read
("Client"). */
-#define TRANS_READ 0x1
-#define TRANS_WRITE 0x2
+#define TRANS_READ 0x1
+#define TRANS_WRITE 0x2
+#define TRANS_DISABLED 0x4
#define FLAG_TO_PFX(c) ((c) - 1)
+static int
+word_match (const char *buf, size_t len, int n, const char *word,
+ size_t *pos)
+{
+ size_t i = 0;
+ size_t wl = strlen (word);
+
+ for (;; n--)
+ {
+ /* Skip whitespace separator */
+ for (; i < len && mu_isspace (buf[i]); i++)
+ ;
+
+ if (n == 0)
+ break;
+
+ /* Skip the argument */
+ if (buf[i] == '"')
+ {
+ for (i++; i < len && buf[i] != '"'; i++)
+ if (buf[i] == '\'')
+ i++;
+ }
+ else
+ {
+ for (; i < len && !mu_isspace (buf[i]); i++)
+ ;
+ }
+ }
+
+ if (i + wl <= len &&
+ mu_c_strncasecmp (buf + i, word, wl) == 0 &&
+ mu_isblank (buf[i + wl]))
+ {
+ *pos = i + wl;
+ return 1;
+ }
+
+ return 0;
+}
+
static void
print_transcript (struct _mu_xscript_stream *str, int flag,
const char *buf, size_t size)
{
- while (size)
- {
- const char *p;
- size_t len;
-
- if (str->flags & flag)
- {
- mu_stream_write (str->logstr,
- str->prefix[FLAG_TO_PFX(flag)],
- strlen (str->prefix[FLAG_TO_PFX (flag)]),
- NULL);
- str->flags &= ~flag;
- }
- p = memchr (buf, '\n', size);
- if (p)
- {
- len = p - buf;
- if (p > buf && p[-1] == '\r')
- len--;
+ while (size)
+ {
+ const char *p;
+ size_t len;
+
+ if (str->flags & flag)
+ {
+ mu_stream_write (str->logstr,
+ str->prefix[FLAG_TO_PFX(flag)],
+ strlen (str->prefix[FLAG_TO_PFX (flag)]),
+ NULL);
+ str->flags &= ~(flag | TRANS_DISABLED);
+ }
+
+ if (str->flags & TRANS_DISABLED)
+ return;
+
+ if (str->level == XSCRIPT_PAYLOAD)
+ {
+ mu_stream_printf (str->logstr, "(data...)\n");
+ str->flags |= TRANS_DISABLED;
+ return;
+ }
+
+ p = memchr (buf, '\n', size);
+ if (p)
+ {
+ len = p - buf;
+ if (p > buf && p[-1] == '\r')
+ len--;
+
+ if (str->level == XSCRIPT_SECURE)
+ {
+ size_t i;
+
+ if (word_match (buf, len, 0, "PASS", &i))
+ mu_stream_printf (str->logstr, "PASS ***");
+ else if (word_match (buf, len, 1, "LOGIN", &i))
+ {
+ /* Skip the whitespace separator */
+ for (; i < len && mu_isspace (buf[i]); i++)
+ ;
+ /* Skip the first argument (presumably the user name) */
+ if (buf[i] == '"')
+ {
+ for (i++; i < len && buf[i] != '"'; i++)
+ if (buf[i] == '\'')
+ i++;
+ }
+ else
+ {
+ for (; i < len && !mu_isspace (buf[i]); i++)
+ ;
+ }
+ mu_stream_write (str->logstr, buf, i, NULL);
+ mu_stream_write (str->logstr, " \"***\"", 6, NULL);
+ }
+ else
+ mu_stream_write (str->logstr, buf, len, NULL);
+ }
+ else
mu_stream_write (str->logstr, buf, len, NULL);
- mu_stream_write (str->logstr, "\n", 1, NULL);
- str->flags |= flag;
-
- len = p - buf + 1;
- buf = p + 1;
- size -= len;
- }
- else
- {
- mu_stream_write (str->logstr, buf, size, NULL);
- break;
- }
- }
+ mu_stream_write (str->logstr, "\n", 1, NULL);
+ str->flags |= flag;
+
+ len = p - buf + 1;
+ buf = p + 1;
+ size -= len;
+ }
+ else
+ {
+ mu_stream_write (str->logstr, buf, size, NULL);
+ break;
+ }
+ }
}
static int
@@ -228,6 +314,18 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
status = 0;
}
break;
+
+ case MU_IOCTL_LEVEL:
+ if (!arg)
+ return EINVAL;
+ else
+ {
+ int oldlev = sp->level;
+ sp->level = *(int*)arg;
+ sp->flags = TRANS_READ | TRANS_WRITE;
+ *(int*)arg = oldlev;
+ }
+ break;
default:
return mu_stream_ioctl (sp->transport, op, arg);
diff --git a/pop3d/extra.c b/pop3d/extra.c
index 52bb220f5..461cd529e 100644
--- a/pop3d/extra.c
+++ b/pop3d/extra.c
@@ -338,3 +338,23 @@ pop3d_undelete_all ()
mu_attribute_unset_deleted (attr);
}
}
+
+int
+set_xscript_level (int xlev)
+{
+ if (pop3d_transcript)
+ {
+ if (xlev != XSCRIPT_NORMAL)
+ {
+ mu_log_level_t n = xlev == XSCRIPT_SECURE ?
+ MU_DEBUG_TRACE6 : MU_DEBUG_TRACE7;
+
+ if (mu_global_debug_level ("pop3") & MU_DEBUG_LEVEL_MASK (n))
+ return XSCRIPT_NORMAL;
+ }
+
+ if (mu_stream_ioctl (iostream, MU_IOCTL_LEVEL, &xlev) == 0)
+ return xlev;
+ }
+ return 0;
+}
diff --git a/pop3d/pop3d.h b/pop3d/pop3d.h
index d10a3307d..d831a3e90 100644
--- a/pop3d/pop3d.h
+++ b/pop3d/pop3d.h
@@ -265,4 +265,6 @@ extern int set_bulletin_source (const char *source);
extern int pop3d_begin_session (void);
extern const char *pop3d_error_string (int code);
+extern int set_xscript_level (int xlev);
+
#endif /* _POP3D_H */
diff --git a/pop3d/retr.c b/pop3d/retr.c
index 61908c0bf..103b5ef07 100644
--- a/pop3d/retr.c
+++ b/pop3d/retr.c
@@ -26,6 +26,7 @@ pop3d_retr (char *arg)
mu_message_t msg = NULL;
mu_attribute_t attr = NULL;
mu_stream_t stream;
+ int xscript_level;
if ((strlen (arg) == 0) || (strchr (arg, ' ') != NULL))
return ERR_BAD_ARGS;
@@ -46,6 +47,7 @@ pop3d_retr (char *arg)
return ERR_UNKNOWN;
pop3d_outf ("+OK\n");
+ xscript_level = set_xscript_level (XSCRIPT_PAYLOAD);
mu_stream_copy (iostream, stream, 0, NULL);
mu_stream_destroy (&stream);
@@ -56,5 +58,7 @@ pop3d_retr (char *arg)
pop3d_outf (".\n");
+ set_xscript_level (xscript_level);
+
return OK;
}
diff --git a/pop3d/top.c b/pop3d/top.c
index 7e0ce5de3..cd069c86b 100644
--- a/pop3d/top.c
+++ b/pop3d/top.c
@@ -30,6 +30,7 @@ pop3d_top (char *arg)
mu_body_t body;
mu_stream_t stream;
char *mesgc, *linesc, *p;
+ int xscript_level;
if (strlen (arg) == 0)
return ERR_BAD_ARGS;
@@ -62,6 +63,8 @@ pop3d_top (char *arg)
return ERR_UNKNOWN;
pop3d_outf ("+OK\n");
+ xscript_level = set_xscript_level (XSCRIPT_PAYLOAD);
+
mu_stream_copy (iostream, stream, 0, NULL);
pop3d_outf ("\n");
mu_stream_destroy (&stream);
@@ -85,5 +88,7 @@ pop3d_top (char *arg)
pop3d_outf (".\n");
+ set_xscript_level (xscript_level);
+
return OK;
}
diff --git a/pop3d/user.c b/pop3d/user.c
index cbe8c41d4..414763853 100644
--- a/pop3d/user.c
+++ b/pop3d/user.c
@@ -91,6 +91,7 @@ pop3d_user (char *arg)
{
char *buf, *pass, *cmd;
char buffer[512];
+ int xscript_level;
if (state != AUTHORIZATION)
return ERR_WRONG_STATE;
@@ -101,9 +102,11 @@ pop3d_user (char *arg)
pop3d_outf ("+OK\n");
pop3d_flush_output ();
+ xscript_level = set_xscript_level (XSCRIPT_SECURE);
buf = pop3d_readline (buffer, sizeof (buffer));
pop3d_parse_command (buf, &cmd, &pass);
-
+ set_xscript_level (xscript_level);
+
if (mu_c_strcasecmp (cmd, "PASS") == 0)
{
int rc;

Return to:

Send suggestions and report system problems to the System administrator.