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.
Showing
23 changed files
with
377 additions
and
62 deletions
... | @@ -131,8 +131,8 @@ COMMAND commands[] = { | ... | @@ -131,8 +131,8 @@ COMMAND commands[] = { |
131 | "Get the unique id of message: UIDL [msgno]" }, | 131 | "Get the unique id of message: UIDL [msgno]" }, |
132 | { "user", 2, 2, com_user, | 132 | { "user", 2, 2, com_user, |
133 | "send login: USER user" }, | 133 | "send login: USER user" }, |
134 | { "verbose", 1, 2, com_verbose, | 134 | { "verbose", 1, 4, com_verbose, |
135 | "Enable Protocol tracing: verbose [on|off]" }, | 135 | "Enable Protocol tracing: verbose [on|off|mask|unmask] [x1 [x2]]" }, |
136 | #ifdef WITH_READLINE | 136 | #ifdef WITH_READLINE |
137 | { "history", 1, 1, com_history, | 137 | { "history", 1, 1, com_history, |
138 | "Show command history" }, | 138 | "Show command history" }, |
... | @@ -145,6 +145,14 @@ mu_pop3_t pop3; | ... | @@ -145,6 +145,14 @@ mu_pop3_t pop3; |
145 | 145 | ||
146 | /* Flag if verbosity is needed. */ | 146 | /* Flag if verbosity is needed. */ |
147 | int verbose; | 147 | int verbose; |
148 | #define VERBOSE_MASK(n) (1<<((n)+1)) | ||
149 | #define SET_VERBOSE_MASK(n) (verbose |= VERBOSE_MASK (n)) | ||
150 | #define CLR_VERBOSE_MASK(n) (verbose &= VERBOSE_MASK (n)) | ||
151 | #define QRY_VERBOSE_MASK(n) (verbose & VERBOSE_MASK (n)) | ||
152 | #define HAS_VERBOSE_MASK(n) (verbose & ~1) | ||
153 | #define SET_VERBOSE() (verbose |= 1) | ||
154 | #define CLR_VERBOSE() (verbose &= ~1) | ||
155 | #define QRY_VERBOSE() (verbose & 1) | ||
148 | 156 | ||
149 | /* When non-zero, this global means the user is done using this program. */ | 157 | /* When non-zero, this global means the user is done using this program. */ |
150 | int done; | 158 | int done; |
... | @@ -408,10 +416,8 @@ get_bool (const char *str, int *pb) | ... | @@ -408,10 +416,8 @@ get_bool (const char *str, int *pb) |
408 | || mu_c_strcasecmp (str, "false") == 0) | 416 | || mu_c_strcasecmp (str, "false") == 0) |
409 | *pb = 0; | 417 | *pb = 0; |
410 | else | 418 | else |
411 | { | 419 | return 1; |
412 | mu_error ("not a boolean: %s", str); | 420 | |
413 | return 1; | ||
414 | } | ||
415 | return 0; | 421 | return 0; |
416 | } | 422 | } |
417 | 423 | ||
... | @@ -509,13 +515,91 @@ find_command (char *name) | ... | @@ -509,13 +515,91 @@ find_command (char *name) |
509 | return NULL; | 515 | return NULL; |
510 | } | 516 | } |
511 | 517 | ||
518 | static int | ||
519 | string_to_xlev (const char *name, int *pv) | ||
520 | { | ||
521 | if (strcmp (name, "secure") == 0) | ||
522 | *pv = XSCRIPT_SECURE; | ||
523 | else if (strcmp (name, "payload") == 0) | ||
524 | *pv = XSCRIPT_PAYLOAD; | ||
525 | else | ||
526 | return 1; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int | ||
531 | change_verbose_mask (int set, int argc, char **argv) | ||
532 | { | ||
533 | int i; | ||
534 | |||
535 | for (i = 0; i < argc; i++) | ||
536 | { | ||
537 | int lev; | ||
538 | |||
539 | if (string_to_xlev (argv[i], &lev)) | ||
540 | { | ||
541 | mu_error ("unknown level: %s", argv[i]); | ||
542 | return 1; | ||
543 | } | ||
544 | if (set) | ||
545 | SET_VERBOSE_MASK (lev); | ||
546 | else | ||
547 | CLR_VERBOSE_MASK (lev); | ||
548 | } | ||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | void | ||
553 | set_verbose (mu_pop3_t p) | ||
554 | { | ||
555 | if (p) | ||
556 | { | ||
557 | if (QRY_VERBOSE ()) | ||
558 | { | ||
559 | mu_pop3_trace (p, MU_POP3_TRACE_SET); | ||
560 | } | ||
561 | else | ||
562 | mu_pop3_trace (p, MU_POP3_TRACE_CLR); | ||
563 | } | ||
564 | } | ||
565 | |||
566 | void | ||
567 | set_verbose_mask (mu_pop3_t p) | ||
568 | { | ||
569 | if (p) | ||
570 | { | ||
571 | mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (XSCRIPT_SECURE) | ||
572 | ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR, | ||
573 | XSCRIPT_SECURE); | ||
574 | mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (XSCRIPT_PAYLOAD) | ||
575 | ? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR, | ||
576 | XSCRIPT_PAYLOAD); | ||
577 | } | ||
578 | } | ||
579 | |||
512 | int | 580 | int |
513 | com_verbose (int argc, char **argv) | 581 | com_verbose (int argc, char **argv) |
514 | { | 582 | { |
515 | if (argc == 1) | 583 | if (argc == 1) |
516 | { | 584 | { |
517 | if (verbose) | 585 | if (QRY_VERBOSE ()) |
518 | printf ("verbose is on\n"); | 586 | { |
587 | printf ("verbose is on"); | ||
588 | if (HAS_VERBOSE_MASK ()) | ||
589 | { | ||
590 | char *delim = " ("; | ||
591 | |||
592 | if (QRY_VERBOSE_MASK (XSCRIPT_SECURE)) | ||
593 | { | ||
594 | printf("%ssecure", delim); | ||
595 | delim = ", "; | ||
596 | } | ||
597 | if (QRY_VERBOSE_MASK (XSCRIPT_PAYLOAD)) | ||
598 | printf("%spayload", delim); | ||
599 | printf (")"); | ||
600 | } | ||
601 | printf ("\n"); | ||
602 | } | ||
519 | else | 603 | else |
520 | printf ("verbose is off\n"); | 604 | printf ("verbose is off\n"); |
521 | } | 605 | } |
... | @@ -525,16 +609,20 @@ com_verbose (int argc, char **argv) | ... | @@ -525,16 +609,20 @@ com_verbose (int argc, char **argv) |
525 | 609 | ||
526 | if (get_bool (argv[1], &bv) == 0) | 610 | if (get_bool (argv[1], &bv) == 0) |
527 | { | 611 | { |
528 | verbose = bv; | 612 | verbose |= bv; |
529 | if (pop3 != NULL) | 613 | if (argc > 2) |
530 | { | 614 | change_verbose_mask (verbose, argc - 2, argv + 2); |
531 | if (verbose == 1) | 615 | set_verbose (pop3); |
532 | mu_pop3_trace (pop3, MU_POP3_TRACE_SET); | ||
533 | else | ||
534 | mu_pop3_trace (pop3, MU_POP3_TRACE_CLR); | ||
535 | } | ||
536 | } | 616 | } |
617 | else if (strcmp (argv[1], "mask") == 0) | ||
618 | change_verbose_mask (1, argc - 2, argv + 2); | ||
619 | else if (strcmp (argv[1], "unmask") == 0) | ||
620 | change_verbose_mask (0, argc - 2, argv + 2); | ||
621 | else | ||
622 | mu_error ("unknown subcommand"); | ||
623 | set_verbose_mask (pop3); | ||
537 | } | 624 | } |
625 | |||
538 | return 0; | 626 | return 0; |
539 | } | 627 | } |
540 | 628 | ||
... | @@ -929,8 +1017,11 @@ com_connect (int argc, char **argv) | ... | @@ -929,8 +1017,11 @@ com_connect (int argc, char **argv) |
929 | { | 1017 | { |
930 | mu_stream_t tcp; | 1018 | mu_stream_t tcp; |
931 | 1019 | ||
932 | if (verbose) | 1020 | if (QRY_VERBOSE ()) |
933 | mu_pop3_trace (pop3, MU_POP3_TRACE_SET); | 1021 | { |
1022 | set_verbose (pop3); | ||
1023 | set_verbose_mask (pop3); | ||
1024 | } | ||
934 | status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ); | 1025 | status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ); |
935 | if (status == 0) | 1026 | if (status == 0) |
936 | { | 1027 | { | ... | ... |
... | @@ -1679,7 +1679,8 @@ imap4d_fetch (struct imap4d_command *command, imap4d_tokbuf_t tok) | ... | @@ -1679,7 +1679,8 @@ imap4d_fetch (struct imap4d_command *command, imap4d_tokbuf_t tok) |
1679 | { | 1679 | { |
1680 | int rc; | 1680 | int rc; |
1681 | char *err_text = "Completed"; | 1681 | char *err_text = "Completed"; |
1682 | 1682 | int xlev = set_xscript_level (XSCRIPT_PAYLOAD); | |
1683 | rc = imap4d_fetch0 (tok, 0, &err_text); | 1683 | rc = imap4d_fetch0 (tok, 0, &err_text); |
1684 | set_xscript_level (xlev); | ||
1684 | return io_completion_response (command, rc, "%s", err_text); | 1685 | return io_completion_response (command, rc, "%s", err_text); |
1685 | } | 1686 | } | ... | ... |
... | @@ -417,11 +417,13 @@ imap4d_mainloop (int fd, FILE *infile, FILE *outfile) | ... | @@ -417,11 +417,13 @@ imap4d_mainloop (int fd, FILE *infile, FILE *outfile) |
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | /* Greetings. */ | 420 | /* Greetings. */ |
421 | io_untagged_response ((state == STATE_AUTH) ? | 421 | io_untagged_response ((state == STATE_AUTH) ? |
422 | RESP_PREAUTH : RESP_OK, "%s", text); | 422 | RESP_PREAUTH : RESP_OK, "%s", text); |
423 | io_flush (); | 423 | io_flush (); |
424 | 424 | ||
425 | set_xscript_level ((state == STATE_AUTH) ? XSCRIPT_NORMAL : XSCRIPT_SECURE); | ||
426 | |||
425 | tokp = imap4d_tokbuf_init (); | 427 | tokp = imap4d_tokbuf_init (); |
426 | while (1) | 428 | while (1) |
427 | { | 429 | { | ... | ... |
... | @@ -381,7 +381,9 @@ void util_chdir (const char *homedir); | ... | @@ -381,7 +381,9 @@ void util_chdir (const char *homedir); |
381 | int is_atom (const char *s); | 381 | int is_atom (const char *s); |
382 | int util_isdelim (const char *str); | 382 | int util_isdelim (const char *str); |
383 | int util_trim_nl (char *s, size_t len); | 383 | int util_trim_nl (char *s, size_t len); |
384 | 384 | ||
385 | int set_xscript_level (int xlev); | ||
386 | |||
385 | #ifdef WITH_TLS | 387 | #ifdef WITH_TLS |
386 | int imap4d_init_tls_server (void); | 388 | int imap4d_init_tls_server (void); |
387 | #endif /* WITH_TLS */ | 389 | #endif /* WITH_TLS */ | ... | ... |
... | @@ -241,7 +241,11 @@ io_format_completion_response (mu_stream_t str, | ... | @@ -241,7 +241,11 @@ io_format_completion_response (mu_stream_t str, |
241 | new_state = STATE_NONE; | 241 | new_state = STATE_NONE; |
242 | 242 | ||
243 | if (new_state != STATE_NONE) | 243 | if (new_state != STATE_NONE) |
244 | state = new_state; | 244 | { |
245 | if (new_state == STATE_AUTH) | ||
246 | set_xscript_level (XSCRIPT_NORMAL); | ||
247 | state = new_state; | ||
248 | } | ||
245 | 249 | ||
246 | return status; | 250 | return status; |
247 | } | 251 | } |
... | @@ -570,6 +574,7 @@ imap4d_readline (struct imap4d_tokbuf *tok) | ... | @@ -570,6 +574,7 @@ imap4d_readline (struct imap4d_tokbuf *tok) |
570 | char *sp = NULL; | 574 | char *sp = NULL; |
571 | char *buf; | 575 | char *buf; |
572 | size_t len; | 576 | size_t len; |
577 | int xlev = set_xscript_level (XSCRIPT_PAYLOAD); | ||
573 | 578 | ||
574 | number = strtoul (last_arg + 1, &sp, 10); | 579 | number = strtoul (last_arg + 1, &sp, 10); |
575 | /* Client can ask for non-synchronised literal, | 580 | /* Client can ask for non-synchronised literal, |
... | @@ -595,6 +600,7 @@ imap4d_readline (struct imap4d_tokbuf *tok) | ... | @@ -595,6 +600,7 @@ imap4d_readline (struct imap4d_tokbuf *tok) |
595 | tok->level += len; | 600 | tok->level += len; |
596 | tok->buffer[tok->level++] = 0; | 601 | tok->buffer[tok->level++] = 0; |
597 | tok->argp[tok->argc - 1] = off; | 602 | tok->argp[tok->argc - 1] = off; |
603 | set_xscript_level (xlev); | ||
598 | } | 604 | } |
599 | else | 605 | else |
600 | break; | 606 | break; | ... | ... |
... | @@ -37,7 +37,11 @@ imap4d_uid (struct imap4d_command *command, imap4d_tokbuf_t tok) | ... | @@ -37,7 +37,11 @@ imap4d_uid (struct imap4d_command *command, imap4d_tokbuf_t tok) |
37 | cmd = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); | 37 | cmd = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); |
38 | 38 | ||
39 | if (mu_c_strcasecmp (cmd, "FETCH") == 0) | 39 | if (mu_c_strcasecmp (cmd, "FETCH") == 0) |
40 | rc = imap4d_fetch0 (tok, 1, &err_text); | 40 | { |
41 | int xlev = set_xscript_level (XSCRIPT_PAYLOAD); | ||
42 | rc = imap4d_fetch0 (tok, 1, &err_text); | ||
43 | set_xscript_level (xlev); | ||
44 | } | ||
41 | else if (mu_c_strcasecmp (cmd, "COPY") == 0) | 45 | else if (mu_c_strcasecmp (cmd, "COPY") == 0) |
42 | rc = imap4d_copy0 (tok, 1, &err_text); | 46 | rc = imap4d_copy0 (tok, 1, &err_text); |
43 | else if (mu_c_strcasecmp (cmd, "STORE") == 0) | 47 | else if (mu_c_strcasecmp (cmd, "STORE") == 0) | ... | ... |
... | @@ -672,3 +672,22 @@ is_atom (const char *s) | ... | @@ -672,3 +672,22 @@ is_atom (const char *s) |
672 | return 1; | 672 | return 1; |
673 | } | 673 | } |
674 | 674 | ||
675 | int | ||
676 | set_xscript_level (int xlev) | ||
677 | { | ||
678 | if (imap4d_transcript) | ||
679 | { | ||
680 | if (xlev != XSCRIPT_NORMAL) | ||
681 | { | ||
682 | mu_log_level_t n = xlev == XSCRIPT_SECURE ? | ||
683 | MU_DEBUG_TRACE6 : MU_DEBUG_TRACE7; | ||
684 | |||
685 | if (mu_global_debug_level ("imap4") & MU_DEBUG_LEVEL_MASK (n)) | ||
686 | return XSCRIPT_NORMAL; | ||
687 | } | ||
688 | |||
689 | if (mu_stream_ioctl (iostream, MU_IOCTL_LEVEL, &xlev) == 0) | ||
690 | return xlev; | ||
691 | } | ||
692 | return 0; | ||
693 | } | ... | ... |
... | @@ -50,6 +50,7 @@ int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout); | ... | @@ -50,6 +50,7 @@ int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout); |
50 | #define MU_POP3_TRACE_SET 1 | 50 | #define MU_POP3_TRACE_SET 1 |
51 | #define MU_POP3_TRACE_QRY 2 | 51 | #define MU_POP3_TRACE_QRY 2 |
52 | int mu_pop3_trace (mu_pop3_t pop3, int op); | 52 | int mu_pop3_trace (mu_pop3_t pop3, int op); |
53 | int mu_pop3_trace_mask (mu_pop3_t pop3, int op, int lev); | ||
53 | 54 | ||
54 | int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest); | 55 | int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest); |
55 | 56 | ... | ... |
... | @@ -63,6 +63,9 @@ enum mu_buffer_type | ... | @@ -63,6 +63,9 @@ enum mu_buffer_type |
63 | #define MU_IOCTL_SET_TRANSPORT 6 | 63 | #define MU_IOCTL_SET_TRANSPORT 6 |
64 | #define MU_IOCTL_SWAP_STREAM 7 | 64 | #define MU_IOCTL_SWAP_STREAM 7 |
65 | 65 | ||
66 | #define MU_IOCTL_LEVEL 8 | ||
67 | |||
68 | |||
66 | void mu_stream_ref (mu_stream_t stream); | 69 | void mu_stream_ref (mu_stream_t stream); |
67 | void mu_stream_unref (mu_stream_t stream); | 70 | void mu_stream_unref (mu_stream_t stream); |
68 | void mu_stream_destroy (mu_stream_t *pstream); | 71 | void mu_stream_destroy (mu_stream_t *pstream); |
... | @@ -153,9 +156,15 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, | ... | @@ -153,9 +156,15 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, |
153 | int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port, | 156 | int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port, |
154 | int flags); | 157 | int flags); |
155 | 158 | ||
159 | /* Transcript output levels */ | ||
160 | #define XSCRIPT_NORMAL 0 /* Normal transcript */ | ||
161 | #define XSCRIPT_SECURE 1 /* Security-related data are being sent/received */ | ||
162 | #define XSCRIPT_PAYLOAD 2 /* Actual payload (may be copious) */ | ||
163 | |||
156 | int mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport, | 164 | int mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport, |
157 | mu_stream_t logstr, | 165 | mu_stream_t logstr, |
158 | const char *prefix[]); | 166 | const char *prefix[]); |
167 | |||
159 | int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out); | 168 | int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out); |
160 | int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, | 169 | int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, |
161 | mu_log_level_t level, int flags); | 170 | mu_log_level_t level, int flags); | ... | ... |
... | @@ -59,6 +59,7 @@ enum mu_pop3_state | ... | @@ -59,6 +59,7 @@ enum mu_pop3_state |
59 | 59 | ||
60 | #define MU_POP3_ACK 0x01 | 60 | #define MU_POP3_ACK 0x01 |
61 | #define MU_POP3_TRACE 0x02 | 61 | #define MU_POP3_TRACE 0x02 |
62 | #define MU_POP3_XSCRIPT_MASK(n) (1<<((n)+1)) | ||
62 | 63 | ||
63 | /* Structure to hold things general to POP3 mailbox, like its state, etc ... */ | 64 | /* Structure to hold things general to POP3 mailbox, like its state, etc ... */ |
64 | struct _mu_pop3 | 65 | struct _mu_pop3 |
... | @@ -90,6 +91,8 @@ extern int mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream); | ... | @@ -90,6 +91,8 @@ extern int mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream); |
90 | extern int mu_pop3_carrier_is_ready (mu_stream_t carrier, int flag, | 91 | extern int mu_pop3_carrier_is_ready (mu_stream_t carrier, int flag, |
91 | int timeout); | 92 | int timeout); |
92 | 93 | ||
94 | int _mu_pop3_xscript_level (mu_pop3_t pop3, int xlev); | ||
95 | |||
93 | int _mu_pop3_trace_enable (mu_pop3_t pop3); | 96 | int _mu_pop3_trace_enable (mu_pop3_t pop3); |
94 | int _mu_pop3_trace_disable (mu_pop3_t pop3); | 97 | int _mu_pop3_trace_disable (mu_pop3_t pop3); |
95 | 98 | ... | ... |
... | @@ -161,7 +161,11 @@ pop_open (mu_mailbox_t mbox, int flags) | ... | @@ -161,7 +161,11 @@ pop_open (mu_mailbox_t mbox, int flags) |
161 | 161 | ||
162 | if (mu_debug_check_level (mbox->debug, MU_DEBUG_PROT)) | 162 | if (mu_debug_check_level (mbox->debug, MU_DEBUG_PROT)) |
163 | mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET); | 163 | mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET); |
164 | 164 | if (mu_debug_check_level (mbox->debug, MU_DEBUG_TRACE6)) | |
165 | mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, XSCRIPT_SECURE); | ||
166 | if (mu_debug_check_level (mbox->debug, MU_DEBUG_TRACE7)) | ||
167 | mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, XSCRIPT_PAYLOAD); | ||
168 | |||
165 | do | 169 | do |
166 | { | 170 | { |
167 | status = mu_pop3_connect (mpd->pop3); | 171 | status = mu_pop3_connect (mpd->pop3); |
... | @@ -214,7 +218,7 @@ pop_destroy (mu_mailbox_t mbox) | ... | @@ -214,7 +218,7 @@ pop_destroy (mu_mailbox_t mbox) |
214 | { | 218 | { |
215 | size_t i; | 219 | size_t i; |
216 | mu_monitor_wrlock (mbox->monitor); | 220 | mu_monitor_wrlock (mbox->monitor); |
217 | /* Destroy the pop messages and ressources associated to them. */ | 221 | /* Destroy the pop messages and resources associated to them. */ |
218 | for (i = 0; i < mpd->msg_count; i++) | 222 | for (i = 0; i < mpd->msg_count; i++) |
219 | { | 223 | { |
220 | if (mpd->msg[i]) | 224 | if (mpd->msg[i]) |
... | @@ -291,7 +295,7 @@ pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -291,7 +295,7 @@ pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) |
291 | if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, | 295 | if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, |
292 | &tmp) != 0) | 296 | &tmp) != 0) |
293 | break; | 297 | break; |
294 | if (((i +1) % 10) == 0) | 298 | if (((i + 1) % 10) == 0) |
295 | { | 299 | { |
296 | mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS, | 300 | mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS, |
297 | NULL); | 301 | NULL); | ... | ... |
... | @@ -28,14 +28,17 @@ int | ... | @@ -28,14 +28,17 @@ int |
28 | mu_pop3_pass (mu_pop3_t pop3, const char *passwd) | 28 | mu_pop3_pass (mu_pop3_t pop3, const char *passwd) |
29 | { | 29 | { |
30 | int status; | 30 | int status; |
31 | 31 | ||
32 | if (pop3 == NULL || passwd == NULL) | 32 | if (pop3 == NULL || passwd == NULL) |
33 | return EINVAL; | 33 | return EINVAL; |
34 | 34 | ||
35 | switch (pop3->state) | 35 | switch (pop3->state) |
36 | { | 36 | { |
37 | case MU_POP3_NO_STATE: | 37 | case MU_POP3_NO_STATE: |
38 | if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_SECURE)) | ||
39 | _mu_pop3_xscript_level (pop3, XSCRIPT_SECURE); | ||
38 | status = mu_pop3_writeline (pop3, "PASS %s\r\n", passwd); | 40 | status = mu_pop3_writeline (pop3, "PASS %s\r\n", passwd); |
41 | _mu_pop3_xscript_level (pop3, XSCRIPT_NORMAL); | ||
39 | MU_POP3_CHECK_ERROR (pop3, status); | 42 | MU_POP3_CHECK_ERROR (pop3, status); |
40 | /* FIXME: how to obscure the passwd in the stream buffer? */ | 43 | /* FIXME: how to obscure the passwd in the stream buffer? */ |
41 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | 44 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | ... | ... |
... | @@ -50,6 +50,8 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream) | ... | @@ -50,6 +50,8 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream) |
50 | MU_POP3_CHECK_OK (pop3); | 50 | MU_POP3_CHECK_OK (pop3); |
51 | status = mu_pop3_stream_create (pop3, pstream); | 51 | status = mu_pop3_stream_create (pop3, pstream); |
52 | MU_POP3_CHECK_ERROR (pop3, status); | 52 | MU_POP3_CHECK_ERROR (pop3, status); |
53 | if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_PAYLOAD)) | ||
54 | _mu_pop3_xscript_level (pop3, XSCRIPT_PAYLOAD); | ||
53 | pop3->state = MU_POP3_RETR_RX; | 55 | pop3->state = MU_POP3_RETR_RX; |
54 | 56 | ||
55 | case MU_POP3_RETR_RX: | 57 | case MU_POP3_RETR_RX: | ... | ... |
... | @@ -185,6 +185,7 @@ _pop3_event_cb (mu_stream_t str, int ev, int flags) | ... | @@ -185,6 +185,7 @@ _pop3_event_cb (mu_stream_t str, int ev, int flags) |
185 | if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0) | 185 | if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0) |
186 | { | 186 | { |
187 | struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0]; | 187 | struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0]; |
188 | _mu_pop3_xscript_level (sp->pop3, XSCRIPT_NORMAL); | ||
188 | sp->pop3->state = MU_POP3_NO_STATE; | 189 | sp->pop3->state = MU_POP3_NO_STATE; |
189 | } | 190 | } |
190 | } | 191 | } | ... | ... |
... | @@ -50,6 +50,8 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines, | ... | @@ -50,6 +50,8 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines, |
50 | MU_POP3_CHECK_OK (pop3); | 50 | MU_POP3_CHECK_OK (pop3); |
51 | status = mu_pop3_stream_create (pop3, pstream); | 51 | status = mu_pop3_stream_create (pop3, pstream); |
52 | MU_POP3_CHECK_ERROR (pop3, status); | 52 | MU_POP3_CHECK_ERROR (pop3, status); |
53 | if (mu_pop3_trace_mask (pop3, MU_POP3_TRACE_QRY, XSCRIPT_PAYLOAD)) | ||
54 | _mu_pop3_xscript_level (pop3, XSCRIPT_PAYLOAD); | ||
53 | pop3->state = MU_POP3_TOP_RX; | 55 | pop3->state = MU_POP3_TOP_RX; |
54 | 56 | ||
55 | case MU_POP3_TOP_RX: | 57 | case MU_POP3_TOP_RX: | ... | ... |
... | @@ -115,4 +115,36 @@ mu_pop3_trace (mu_pop3_t pop3, int op) | ... | @@ -115,4 +115,36 @@ mu_pop3_trace (mu_pop3_t pop3, int op) |
115 | return EINVAL; | 115 | return EINVAL; |
116 | } | 116 | } |
117 | 117 | ||
118 | int | ||
119 | mu_pop3_trace_mask (mu_pop3_t pop3, int op, int lev) | ||
120 | { | ||
121 | switch (op) | ||
122 | { | ||
123 | case MU_POP3_TRACE_SET: | ||
124 | pop3->flags |= MU_POP3_XSCRIPT_MASK(lev); | ||
125 | break; | ||
126 | |||
127 | case MU_POP3_TRACE_CLR: | ||
128 | pop3->flags &= ~MU_POP3_XSCRIPT_MASK(lev); | ||
129 | break; | ||
130 | |||
131 | case MU_POP3_TRACE_QRY: | ||
132 | if (pop3->flags & MU_POP3_XSCRIPT_MASK(lev)) | ||
133 | break; | ||
134 | return MU_ERR_NOENT; | ||
135 | |||
136 | default: | ||
137 | return EINVAL; | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | _mu_pop3_xscript_level (mu_pop3_t pop3, int xlev) | ||
144 | { | ||
145 | if (mu_stream_ioctl (pop3->carrier, MU_IOCTL_LEVEL, &xlev) == 0) | ||
146 | return xlev; | ||
147 | return XSCRIPT_NORMAL; | ||
148 | } | ||
149 | |||
118 | 150 | ... | ... |
... | @@ -30,6 +30,8 @@ | ... | @@ -30,6 +30,8 @@ |
30 | #include <mailutils/stream.h> | 30 | #include <mailutils/stream.h> |
31 | #include <mailutils/sys/stream.h> | 31 | #include <mailutils/sys/stream.h> |
32 | #include <mailutils/sys/xscript-stream.h> | 32 | #include <mailutils/sys/xscript-stream.h> |
33 | #include <mailutils/cctype.h> | ||
34 | #include <mailutils/cstr.h> | ||
33 | 35 | ||
34 | /* A "transcript stream" transparently writes data to and reads data from | 36 | /* A "transcript stream" transparently writes data to and reads data from |
35 | an underlying transport stream, writing each lineful of data to a "log | 37 | an underlying transport stream, writing each lineful of data to a "log |
... | @@ -38,47 +40,131 @@ | ... | @@ -38,47 +40,131 @@ |
38 | RFCs -- "S: ", for data written ("Server"), and "C: ", for data read | 40 | RFCs -- "S: ", for data written ("Server"), and "C: ", for data read |
39 | ("Client"). */ | 41 | ("Client"). */ |
40 | 42 | ||
41 | #define TRANS_READ 0x1 | 43 | #define TRANS_READ 0x1 |
42 | #define TRANS_WRITE 0x2 | 44 | #define TRANS_WRITE 0x2 |
45 | #define TRANS_DISABLED 0x4 | ||
43 | #define FLAG_TO_PFX(c) ((c) - 1) | 46 | #define FLAG_TO_PFX(c) ((c) - 1) |
44 | 47 | ||
48 | static int | ||
49 | word_match (const char *buf, size_t len, int n, const char *word, | ||
50 | size_t *pos) | ||
51 | { | ||
52 | size_t i = 0; | ||
53 | size_t wl = strlen (word); | ||
54 | |||
55 | for (;; n--) | ||
56 | { | ||
57 | /* Skip whitespace separator */ | ||
58 | for (; i < len && mu_isspace (buf[i]); i++) | ||
59 | ; | ||
60 | |||
61 | if (n == 0) | ||
62 | break; | ||
63 | |||
64 | /* Skip the argument */ | ||
65 | if (buf[i] == '"') | ||
66 | { | ||
67 | for (i++; i < len && buf[i] != '"'; i++) | ||
68 | if (buf[i] == '\'') | ||
69 | i++; | ||
70 | } | ||
71 | else | ||
72 | { | ||
73 | for (; i < len && !mu_isspace (buf[i]); i++) | ||
74 | ; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | if (i + wl <= len && | ||
79 | mu_c_strncasecmp (buf + i, word, wl) == 0 && | ||
80 | mu_isblank (buf[i + wl])) | ||
81 | { | ||
82 | *pos = i + wl; | ||
83 | return 1; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
45 | static void | 89 | static void |
46 | print_transcript (struct _mu_xscript_stream *str, int flag, | 90 | print_transcript (struct _mu_xscript_stream *str, int flag, |
47 | const char *buf, size_t size) | 91 | const char *buf, size_t size) |
48 | { | 92 | { |
49 | while (size) | 93 | while (size) |
50 | { | 94 | { |
51 | const char *p; | 95 | const char *p; |
52 | size_t len; | 96 | size_t len; |
53 | 97 | ||
54 | if (str->flags & flag) | 98 | if (str->flags & flag) |
55 | { | 99 | { |
56 | mu_stream_write (str->logstr, | 100 | mu_stream_write (str->logstr, |
57 | str->prefix[FLAG_TO_PFX(flag)], | 101 | str->prefix[FLAG_TO_PFX(flag)], |
58 | strlen (str->prefix[FLAG_TO_PFX (flag)]), | 102 | strlen (str->prefix[FLAG_TO_PFX (flag)]), |
59 | NULL); | 103 | NULL); |
60 | str->flags &= ~flag; | 104 | str->flags &= ~(flag | TRANS_DISABLED); |
61 | } | 105 | } |
62 | p = memchr (buf, '\n', size); | 106 | |
63 | if (p) | 107 | if (str->flags & TRANS_DISABLED) |
64 | { | 108 | return; |
65 | len = p - buf; | 109 | |
66 | if (p > buf && p[-1] == '\r') | 110 | if (str->level == XSCRIPT_PAYLOAD) |
67 | len--; | 111 | { |
112 | mu_stream_printf (str->logstr, "(data...)\n"); | ||
113 | str->flags |= TRANS_DISABLED; | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | p = memchr (buf, '\n', size); | ||
118 | if (p) | ||
119 | { | ||
120 | len = p - buf; | ||
121 | if (p > buf && p[-1] == '\r') | ||
122 | len--; | ||
123 | |||
124 | if (str->level == XSCRIPT_SECURE) | ||
125 | { | ||
126 | size_t i; | ||
127 | |||
128 | if (word_match (buf, len, 0, "PASS", &i)) | ||
129 | mu_stream_printf (str->logstr, "PASS ***"); | ||
130 | else if (word_match (buf, len, 1, "LOGIN", &i)) | ||
131 | { | ||
132 | /* Skip the whitespace separator */ | ||
133 | for (; i < len && mu_isspace (buf[i]); i++) | ||
134 | ; | ||
135 | /* Skip the first argument (presumably the user name) */ | ||
136 | if (buf[i] == '"') | ||
137 | { | ||
138 | for (i++; i < len && buf[i] != '"'; i++) | ||
139 | if (buf[i] == '\'') | ||
140 | i++; | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | for (; i < len && !mu_isspace (buf[i]); i++) | ||
145 | ; | ||
146 | } | ||
147 | mu_stream_write (str->logstr, buf, i, NULL); | ||
148 | mu_stream_write (str->logstr, " \"***\"", 6, NULL); | ||
149 | } | ||
150 | else | ||
151 | mu_stream_write (str->logstr, buf, len, NULL); | ||
152 | } | ||
153 | else | ||
68 | mu_stream_write (str->logstr, buf, len, NULL); | 154 | mu_stream_write (str->logstr, buf, len, NULL); |
69 | mu_stream_write (str->logstr, "\n", 1, NULL); | 155 | mu_stream_write (str->logstr, "\n", 1, NULL); |
70 | str->flags |= flag; | 156 | str->flags |= flag; |
71 | 157 | ||
72 | len = p - buf + 1; | 158 | len = p - buf + 1; |
73 | buf = p + 1; | 159 | buf = p + 1; |
74 | size -= len; | 160 | size -= len; |
75 | } | 161 | } |
76 | else | 162 | else |
77 | { | 163 | { |
78 | mu_stream_write (str->logstr, buf, size, NULL); | 164 | mu_stream_write (str->logstr, buf, size, NULL); |
79 | break; | 165 | break; |
80 | } | 166 | } |
81 | } | 167 | } |
82 | } | 168 | } |
83 | 169 | ||
84 | static int | 170 | static int |
... | @@ -228,6 +314,18 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -228,6 +314,18 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) |
228 | status = 0; | 314 | status = 0; |
229 | } | 315 | } |
230 | break; | 316 | break; |
317 | |||
318 | case MU_IOCTL_LEVEL: | ||
319 | if (!arg) | ||
320 | return EINVAL; | ||
321 | else | ||
322 | { | ||
323 | int oldlev = sp->level; | ||
324 | sp->level = *(int*)arg; | ||
325 | sp->flags = TRANS_READ | TRANS_WRITE; | ||
326 | *(int*)arg = oldlev; | ||
327 | } | ||
328 | break; | ||
231 | 329 | ||
232 | default: | 330 | default: |
233 | return mu_stream_ioctl (sp->transport, op, arg); | 331 | return mu_stream_ioctl (sp->transport, op, arg); | ... | ... |
... | @@ -338,3 +338,23 @@ pop3d_undelete_all () | ... | @@ -338,3 +338,23 @@ pop3d_undelete_all () |
338 | mu_attribute_unset_deleted (attr); | 338 | mu_attribute_unset_deleted (attr); |
339 | } | 339 | } |
340 | } | 340 | } |
341 | |||
342 | int | ||
343 | set_xscript_level (int xlev) | ||
344 | { | ||
345 | if (pop3d_transcript) | ||
346 | { | ||
347 | if (xlev != XSCRIPT_NORMAL) | ||
348 | { | ||
349 | mu_log_level_t n = xlev == XSCRIPT_SECURE ? | ||
350 | MU_DEBUG_TRACE6 : MU_DEBUG_TRACE7; | ||
351 | |||
352 | if (mu_global_debug_level ("pop3") & MU_DEBUG_LEVEL_MASK (n)) | ||
353 | return XSCRIPT_NORMAL; | ||
354 | } | ||
355 | |||
356 | if (mu_stream_ioctl (iostream, MU_IOCTL_LEVEL, &xlev) == 0) | ||
357 | return xlev; | ||
358 | } | ||
359 | return 0; | ||
360 | } | ... | ... |
... | @@ -265,4 +265,6 @@ extern int set_bulletin_source (const char *source); | ... | @@ -265,4 +265,6 @@ extern int set_bulletin_source (const char *source); |
265 | extern int pop3d_begin_session (void); | 265 | extern int pop3d_begin_session (void); |
266 | extern const char *pop3d_error_string (int code); | 266 | extern const char *pop3d_error_string (int code); |
267 | 267 | ||
268 | extern int set_xscript_level (int xlev); | ||
269 | |||
268 | #endif /* _POP3D_H */ | 270 | #endif /* _POP3D_H */ | ... | ... |
... | @@ -26,6 +26,7 @@ pop3d_retr (char *arg) | ... | @@ -26,6 +26,7 @@ pop3d_retr (char *arg) |
26 | mu_message_t msg = NULL; | 26 | mu_message_t msg = NULL; |
27 | mu_attribute_t attr = NULL; | 27 | mu_attribute_t attr = NULL; |
28 | mu_stream_t stream; | 28 | mu_stream_t stream; |
29 | int xscript_level; | ||
29 | 30 | ||
30 | if ((strlen (arg) == 0) || (strchr (arg, ' ') != NULL)) | 31 | if ((strlen (arg) == 0) || (strchr (arg, ' ') != NULL)) |
31 | return ERR_BAD_ARGS; | 32 | return ERR_BAD_ARGS; |
... | @@ -46,6 +47,7 @@ pop3d_retr (char *arg) | ... | @@ -46,6 +47,7 @@ pop3d_retr (char *arg) |
46 | return ERR_UNKNOWN; | 47 | return ERR_UNKNOWN; |
47 | 48 | ||
48 | pop3d_outf ("+OK\n"); | 49 | pop3d_outf ("+OK\n"); |
50 | xscript_level = set_xscript_level (XSCRIPT_PAYLOAD); | ||
49 | mu_stream_copy (iostream, stream, 0, NULL); | 51 | mu_stream_copy (iostream, stream, 0, NULL); |
50 | mu_stream_destroy (&stream); | 52 | mu_stream_destroy (&stream); |
51 | 53 | ||
... | @@ -56,5 +58,7 @@ pop3d_retr (char *arg) | ... | @@ -56,5 +58,7 @@ pop3d_retr (char *arg) |
56 | 58 | ||
57 | pop3d_outf (".\n"); | 59 | pop3d_outf (".\n"); |
58 | 60 | ||
61 | set_xscript_level (xscript_level); | ||
62 | |||
59 | return OK; | 63 | return OK; |
60 | } | 64 | } | ... | ... |
... | @@ -30,6 +30,7 @@ pop3d_top (char *arg) | ... | @@ -30,6 +30,7 @@ pop3d_top (char *arg) |
30 | mu_body_t body; | 30 | mu_body_t body; |
31 | mu_stream_t stream; | 31 | mu_stream_t stream; |
32 | char *mesgc, *linesc, *p; | 32 | char *mesgc, *linesc, *p; |
33 | int xscript_level; | ||
33 | 34 | ||
34 | if (strlen (arg) == 0) | 35 | if (strlen (arg) == 0) |
35 | return ERR_BAD_ARGS; | 36 | return ERR_BAD_ARGS; |
... | @@ -62,6 +63,8 @@ pop3d_top (char *arg) | ... | @@ -62,6 +63,8 @@ pop3d_top (char *arg) |
62 | return ERR_UNKNOWN; | 63 | return ERR_UNKNOWN; |
63 | pop3d_outf ("+OK\n"); | 64 | pop3d_outf ("+OK\n"); |
64 | 65 | ||
66 | xscript_level = set_xscript_level (XSCRIPT_PAYLOAD); | ||
67 | |||
65 | mu_stream_copy (iostream, stream, 0, NULL); | 68 | mu_stream_copy (iostream, stream, 0, NULL); |
66 | pop3d_outf ("\n"); | 69 | pop3d_outf ("\n"); |
67 | mu_stream_destroy (&stream); | 70 | mu_stream_destroy (&stream); |
... | @@ -85,5 +88,7 @@ pop3d_top (char *arg) | ... | @@ -85,5 +88,7 @@ pop3d_top (char *arg) |
85 | 88 | ||
86 | pop3d_outf (".\n"); | 89 | pop3d_outf (".\n"); |
87 | 90 | ||
91 | set_xscript_level (xscript_level); | ||
92 | |||
88 | return OK; | 93 | return OK; |
89 | } | 94 | } | ... | ... |
... | @@ -91,6 +91,7 @@ pop3d_user (char *arg) | ... | @@ -91,6 +91,7 @@ pop3d_user (char *arg) |
91 | { | 91 | { |
92 | char *buf, *pass, *cmd; | 92 | char *buf, *pass, *cmd; |
93 | char buffer[512]; | 93 | char buffer[512]; |
94 | int xscript_level; | ||
94 | 95 | ||
95 | if (state != AUTHORIZATION) | 96 | if (state != AUTHORIZATION) |
96 | return ERR_WRONG_STATE; | 97 | return ERR_WRONG_STATE; |
... | @@ -101,9 +102,11 @@ pop3d_user (char *arg) | ... | @@ -101,9 +102,11 @@ pop3d_user (char *arg) |
101 | pop3d_outf ("+OK\n"); | 102 | pop3d_outf ("+OK\n"); |
102 | pop3d_flush_output (); | 103 | pop3d_flush_output (); |
103 | 104 | ||
105 | xscript_level = set_xscript_level (XSCRIPT_SECURE); | ||
104 | buf = pop3d_readline (buffer, sizeof (buffer)); | 106 | buf = pop3d_readline (buffer, sizeof (buffer)); |
105 | pop3d_parse_command (buf, &cmd, &pass); | 107 | pop3d_parse_command (buf, &cmd, &pass); |
106 | 108 | set_xscript_level (xscript_level); | |
109 | |||
107 | if (mu_c_strcasecmp (cmd, "PASS") == 0) | 110 | if (mu_c_strcasecmp (cmd, "PASS") == 0) |
108 | { | 111 | { |
109 | int rc; | 112 | int rc; | ... | ... |
-
Please register or sign in to post a comment