Transcript stream
Transcript stream
A transcript stream transparently writes data to and reads data from an underlying transport stream, writing each lineful of data to a log stream. Writes to the log stream are prefixed with a string indicating the direction of the data (read/write). Default prefixes are those used in RFCs -- "S: ", for data written ("Server"), and "C: ", for data read ("Client").
The stream can operate in three distinct modes, called transcript levels:
- MU_XSCRIPT_NORMAL
- The default level. Everything is logged indiscriminately. Programmers should excercise care when using this mode, as it can reveal security sensitive data (such as login credentials, etc.) as well as private user's information (mail content).
- MU_XSCRIPT_SECURE
- The stream attempts to locate passwords and replaces them with three asteriscs when sending to the log stream. This mode should be used before the session is authenticated. Currently the following two constructs are recognized:
PASS <STRING> <WORD> LOGIN <STRING1> <STRING2>
- Here, <WORD> stands for an unquoted word, and <STRING> stands for a <WORD> or any sequence of characters enclosed in double-quotes. When the first construct is encountered, <STRING> is replaced with *** in transcript. For the second construct, <STRING2> is replaced.
- These two cover two most used authentication methods used in POP and IMAP protocols.
- MU_XSCRIPT_PAYLOAD
- This mode is suitable when large amounts of user data are passed through the stream, e.g. when sending literals in IMAP or sending replies to RETR or TOP requests in POP protocol. In this mode, the stream logs the single string (data...) upon receiving first block of data and stops further logging.
- This mode can be enabled for a certain amount of data that is about to be sent, if such amount is known beforehand. In that case, the stream will automatically revert to MU_XSCRIPT_NORMAL mode after that much data has been processed. This is used when sending or receiving IMAP literals.
Either direction (hereinafter called channel) is implemented as an independent state machine, so that the above modes can be configured independently for each channel.
Creation
The stream is created using the following call:
int mu_xscript_stream_create(mu_stream_t *res, mu_stream_t transport, mu_stream_t logstr, const char *prefix[]);
Its arguments are:
- res
- Pointer to the return memory location, where the created stream is to be returned.
- transport
- Transport stream.
- logstr
- Log stream.
- prefix
- Optional log prefixes. NULL to use the default.
For example, the following fragment creates transcript stream that will accept data from the standard input stream (mu_strin), write data to the standard output (mu_strout) and log the session transcript to the standard error (mu_strerr).
mu_stream_t iostr; /* Input/output stream */
mu_stream_t xstr; /* Transcript stream */
/* Create the I/O stream */
mu_iostream_create (&iostr, mu_strin, mu_strout);
mu_stream_set_buffer (iostr, mu_buffer_line, 0);
/* Create the transcript stream */
mu_xscript_stream_create (&xstr, iostr, mu_strerr, NULL));
/* Unreference component streams */
mu_stream_unref (iostr);
mu_stream_unref (mu_strerr);
The MU_IOCTL_XSCRIPTSTREAM ioctl
The stream is configured using the MU_IOCTL_XSCRIPTSTREAM ioctl family.
The following opcodes are implemented:
MU_IOCTL_XSCRIPTSTREAM_LEVEL
Set new transcript level(s) for both channels.
Argument:
int *X
On input, X points to the desired transcript level. It will be set on both channels. If different transcript levels are desired, they can be packed into one integer using the MU_XSCRIPT_LEVEL_PACK macro, e.g.:
int n = MU_XSCRIPT_LEVEL_PACK(MU_XSCRIPT_SECURE, MU_XSCRIPT_NORMAL);
mu_stream_ioctl (str, MU_IOCTL_XSCRIPTSTREAM, MU_IOCTL_XSCRIPTSTREAM_LEVEL, &n);
Upon successful return, previous transcript levels are stored in X. This allows the programmer to restore prior settings using the same ioctl.
The returned value is a single transcript level, if levels are the same in both channels, or packed levels otherwise. This ensures compatibility with prior versions of libmailutils.
Whether it is packed or not, the level for each particular channel can be retrieved from X using the MU_XSCRIPT_LEVEL_UNPACK macro.
It is advised to use MU_IOCTL_XSCRIPTSTREAM_LEVEL only when setting same level for both channels. Otherwise, please use MU_IOCTL_XSCRIPTSTREAM_CHANNEL.
MU_IOCTL_XSCRIPTSTREAM_CHANNEL
Reconfigure single channel.
Argument:
struct mu_xscript_channel *C
The structure is defined as follows:
struct mu_xscript_channel
{
int cd; /* Channel descriptor */
int level; /* Channel transcript level */
size_t length; /* Length of data, for MU_XSCRIPT_PAYLOAD */
};
On input, the members of the structure must be set as follows:
- cd
- Must be initialized to 0, for input channel, or 1, for output channel.
- level
- Desired transcript level.
- length
- If level is MU_XSCRIPT_PAYLOAD it can be set to a non-zero value, indicating the amount of user data about to be passed through the channel. The channel will return to MU_XSCRIPT_NORMAL level after that much data are processed.
- For another two levels, length must be 0.