Exemple #1
0
int     vverify_append(const char *queue_id, const char *orig_rcpt,
		              const char *recipient, const char *relay,
		              time_t entry, const char *status,
		              int rcpt_stat, const char *fmt, va_list ap)
{
    VSTRING *text = vstring_alloc(10);
    int     req_stat;

    /*
     * Impedance adaptor between bounce/defer/sent and verify_clnt.
     */
    vstring_vsprintf(text, fmt, ap);
    if (var_verify_neg_cache || rcpt_stat == DEL_RCPT_STAT_OK) {
	req_stat = verify_clnt_update(orig_rcpt, rcpt_stat,
				      "%s", vstring_str(text));
	if (req_stat == VRFY_STAT_OK && strcasecmp(recipient, orig_rcpt) != 0)
	    req_stat = verify_clnt_update(recipient, rcpt_stat,
					  "%s", vstring_str(text));
    } else {
	status = "undeliverable-but-not-cached";
	req_stat = VRFY_STAT_OK;
    }
    if (req_stat == VRFY_STAT_OK) {
	log_adhoc(queue_id, orig_rcpt, recipient, relay,
		  entry, status, "%s", vstring_str(text));
	req_stat = 0;
    } else {
	msg_warn("%s: %s service failure", queue_id, var_verify_service);
	req_stat = -1;
    }
    vstring_free(text);
    return (req_stat);
}
Exemple #2
0
int     memcache_printf(VSTREAM *stream, const char *fmt,...)
{
    va_list ap;
    int     ret;

    va_start(ap, fmt);

    if (msg_verbose) {
	VSTRING *buf = vstring_alloc(100);
	va_list ap2;

	VA_COPY(ap2, ap);
	vstring_vsprintf(buf, fmt, ap2);
	va_end(ap2);
	msg_info("%s write: %s", VSTREAM_PATH(stream), STR(buf));
	vstring_free(buf);
    }

    /*
     * Do the I/O.
     */
    ret = memcache_vprintf(stream, fmt, ap);
    va_end(ap);
    return (ret);
}
Exemple #3
0
VSTRING *vstring_sprintf(VSTRING *vp, const char *format,...)
{
    va_list ap;

    va_start(ap, format);
    vp = vstring_vsprintf(vp, format, ap);
    va_end(ap);
    return (vp);
}
Exemple #4
0
void    msg_vprintf(int level, const char *format, va_list ap)
{
    if (msg_vprintf_lock == 0) {
	msg_vprintf_lock = 1;
	/* On-the-fly initialization for debugging test programs only. */
	if (msg_output_fn_count == 0)
	    msg_vstream_init("unknown", VSTREAM_ERR);
	/* OK if terminating signal handler hijacks control before next stmt. */
	vstring_vsprintf(msg_buffer, percentm(format, errno), ap);
	msg_text(level, vstring_str(msg_buffer));
	msg_vprintf_lock = 0;
    }
}
Exemple #5
0
void    smtp_chat_cmd(SMTP_SESSION *session, const char *fmt,...)
{
    va_list ap;

    /*
     * Format the command, and update the transaction log.
     */
    va_start(ap, fmt);
    vstring_vsprintf(session->buffer, fmt, ap);
    va_end(ap);
    smtp_chat_append(session, "Out: ", STR(session->buffer));

    /*
     * Optionally log the command first, so we can see in the log what the
     * program is trying to do.
     */
    if (msg_verbose)
	msg_info("> %s: %s", session->namaddrport, STR(session->buffer));

    /*
     * Send the command to the SMTP server.
     */
    smtp_fputs(STR(session->buffer), LEN(session->buffer), session->stream);

    /*
     * Force flushing of output does not belong here. It is done in the
     * smtp_loop() main protocol loop when reading the server response, and
     * in smtp_helo() when reading the EHLO response after sending the EHLO
     * command.
     * 
     * If we do forced flush here, then we must longjmp() on error, and a
     * matching "prepare for disaster" error handler must be set up before
     * every smtp_chat_cmd() call.
     */
#if 0

    /*
     * Flush unsent data to avoid timeouts after slow DNS lookups.
     */
    if (time((time_t *) 0) - vstream_ftime(session->stream) > 10)
	vstream_fflush(session->stream);

    /*
     * Abort immediately if the connection is broken.
     */
    if (vstream_ftimeout(session->stream))
	vstream_longjmp(session->stream, SMTP_ERR_TIME);
    if (vstream_ferror(session->stream))
	vstream_longjmp(session->stream, SMTP_ERR_EOF);
#endif
}
void    pcf_print_line(VSTREAM *fp, int mode, const char *fmt,...)
{
    va_list ap;
    static VSTRING *buf = 0;
    char   *start;
    char   *next;
    int     line_len = 0;
    int     word_len;

    /*
     * One-off initialization.
     */
    if (buf == 0)
	buf = vstring_alloc(100);

    /*
     * Format the text.
     */
    va_start(ap, fmt);
    vstring_vsprintf(buf, fmt, ap);
    va_end(ap);

    /*
     * Normalize the whitespace. We don't use the line_wrap() routine because
     * 1) that function does not normalize whitespace between words and 2) we
     * want to normalize whitespace even when not wrapping lines.
     * 
     * XXX Some parameters preserve whitespace: for example, smtpd_banner and
     * smtpd_reject_footer. If we have to preserve whitespace between words,
     * then perhaps readlline() can be changed to canonicalize whitespace
     * that follows a newline.
     */
    for (start = STR(buf); *(start += strspn(start, PCF_SEPARATORS)) != 0; start = next) {
	word_len = strcspn(start, PCF_SEPARATORS);
	if (*(next = start + word_len) != 0)
	    *next++ = 0;
	if (word_len > 0 && line_len > 0) {
	    if ((mode & PCF_FOLD_LINE) == 0
		|| line_len + word_len < PCF_LINE_LIMIT) {
		vstream_fputs(" ", fp);
		line_len += 1;
	    } else {
		vstream_fputs("\n" PCF_INDENT_TEXT, fp);
		line_len = PCF_INDENT_LEN;
	    }
	}
	vstream_fputs(start, fp);
	line_len += word_len;
    }
    vstream_fputs("\n", fp);
}
Exemple #7
0
static NORETURN PRINTFLIKE(1, 2) fatal_with_context(char *format,...)
{
    const char *myname = "fatal_with_context";
    VSTRING *vp = vstring_alloc(100);
    va_list ap;

    if (master_path == 0)
	msg_panic("%s: no configuration file specified", myname);

    va_start(ap, format);
    vstring_vsprintf(vp, format, ap);
    va_end(ap);
    msg_fatal("%s: %s", master_conf_context(), vstring_str(vp));
}
Exemple #8
0
static NORETURN PRINTFLIKE(1, 2) pcf_fix_fatal(const char *fmt,...)
{
    VSTRING *buf = vstring_alloc(100);
    va_list ap;

    /*
     * Replace newline with whitespace.
     */
    va_start(ap, fmt);
    vstring_vsprintf(buf, fmt, ap);
    va_end(ap);
    translit(STR(buf), "\n", " ");
    msg_fatal("%s", STR(buf));
    /* NOTREACHED */
}
Exemple #9
0
void    vlog_adhoc(const char *id, const char *orig_rcpt,
		           const char *recipient, const char *relay,
		           time_t entry, const char *status,
		           const char *fmt, va_list ap)
{
    VSTRING *why = vstring_alloc(100);
    int     delay = time((time_t *) 0) - entry;

    vstring_vsprintf(why, fmt, ap);
    if (orig_rcpt && *orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0)
	msg_info("%s: to=<%s>, orig_to=<%s>, relay=%s, delay=%d, status=%s (%s)",
	  id, recipient, orig_rcpt, relay, delay, status, vstring_str(why));
    else
	msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)",
		 id, recipient, relay, delay, status, vstring_str(why));
    vstring_free(why);
}
Exemple #10
0
static void smtpd_proxy_cmd_warn(SMTPD_STATE *state, const char *fmt,
				         va_list ap)
{
    SMTPD_PROXY *proxy = state->proxy;
    VSTRING *buf;

    /*
     * The command can be omitted at the start of an SMTP session. A null
     * format string is not documented as part of the official interface
     * because it is used only internally to this module.
     */
    buf = vstring_alloc(100);
    vstring_vsprintf(buf, fmt == SMTPD_PROXY_CONN_FMT ?
		     "connection request" : fmt, ap);
    msg_warn("proxy %s rejected \"%s\": \"%s\"",
	     proxy->service_name, STR(buf), STR(proxy->buffer));
    vstring_free(buf);
}
Exemple #11
0
static int match_error(MATCH_LIST *list, const char *fmt,...)
{
    VSTRING *buf = vstring_alloc(100);
    va_list ap;

    /*
     * Report, and maybe return.
     */
    va_start(ap, fmt);
    vstring_vsprintf(buf, fmt, ap);
    va_end(ap);
    if (list->flags & MATCH_FLAG_RETURN) {
	msg_warn("%s", vstring_str(buf));
    } else {
	msg_fatal("%s", vstring_str(buf));
    }
    vstring_free(buf);
    return (0);
}
Exemple #12
0
void    pop3d_chat_reply(POP3D_STATE *state, char *format,...)
{
    va_list ap;
    int     delay = 0;

    va_start(ap, format);
    vstring_vsprintf(state->buffer, format, ap);
    va_end(ap);
    if (var_soft_bounce && STR(state->buffer)[0] == '5')
	STR(state->buffer)[0] = '4';
    pop3_chat_append(state, "Out: ");

    if (msg_verbose)
	msg_info("> %s[%s]: %s", state->name, state->addr, STR(state->buffer));

    /*
     * Slow down clients that make errors. Sleep-on-anything slows down
     * clients that make an excessive number of errors within a session.
     */
    if (state->error_count >= var_pop3d_soft_erlim)
	sleep(delay = var_pop3d_err_sleep);

    pop3_fputs(STR(state->buffer), LEN(state->buffer), state->client);

    /*
     * Flush unsent output if no I/O happened for a while. This avoids
     * timeouts with pipelined POP3 sessions that have lots of server-side
     * delays (tarpit delays or DNS lookups for UCE restrictions).
     */
    if (delay || time((time_t *) 0) - vstream_ftime(state->client) > 10)
	vstream_fflush(state->client);

    /*
     * Abort immediately if the connection is broken.
     */
    if (vstream_ftimeout(state->client))
	vstream_longjmp(state->client, POP3_ERR_TIME);
    if (vstream_ferror(state->client))
	vstream_longjmp(state->client, POP3_ERR_EOF);
}
Exemple #13
0
static void command(VSTREAM *stream, char *fmt,...)
{
    VSTRING *buf;
    va_list ap;

    /*
     * Optionally, log the command before actually sending, so we can see
     * what the program is trying to do.
     */
    if (msg_verbose) {
        buf = vstring_alloc(100);
        va_start(ap, fmt);
        vstring_vsprintf(buf, fmt, ap);
        va_end(ap);
        msg_info("%s", vstring_str(buf));
        vstring_free(buf);
    }
    va_start(ap, fmt);
    smtp_vprintf(stream, fmt, ap);
    va_end(ap);
    smtp_flush(stream);
}
Exemple #14
0
int     been_here_check(BH_TABLE *dup_filter, const char *fmt,...)
{
    VSTRING *buf = vstring_alloc(100);
    int     status;
    va_list ap;

    /*
     * Construct the string to be checked.
     */
    va_start(ap, fmt);
    vstring_vsprintf(buf, fmt, ap);
    va_end(ap);

    /*
     * Do the duplicate check.
     */
    status = been_here_check_fixed(dup_filter, vstring_str(buf));

    /*
     * Cleanup.
     */
    vstring_free(buf);
    return (status);
}
Exemple #15
0
static int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
{
    SMTPD_PROXY *proxy = state->proxy;
    va_list ap;
    char   *cp;
    int     last_char;
    int     err = 0;
    static VSTRING *buffer = 0;

    /*
     * Errors first. Be prepared for delayed errors from the DATA phase.
     */
    if (vstream_ferror(proxy->service_stream)
	|| vstream_feof(proxy->service_stream)
	|| (err = vstream_setjmp(proxy->service_stream)) != 0) {
	return (smtpd_proxy_rdwr_error(state, err));
    }

    /*
     * The command can be omitted at the start of an SMTP session. This is
     * not documented as part of the official interface because it is used
     * only internally to this module.
     */
    if (fmt != SMTPD_PROXY_CONN_FMT) {

	/*
	 * Format the command.
	 */
	va_start(ap, fmt);
	vstring_vsprintf(proxy->request, fmt, ap);
	va_end(ap);

	/*
	 * Optionally log the command first, so that we can see in the log
	 * what the program is trying to do.
	 */
	if (msg_verbose)
	    msg_info("> %s: %s", proxy->service_name, STR(proxy->request));

	/*
	 * Send the command to the proxy server. Since we're going to read a
	 * reply immediately, there is no need to flush buffers.
	 */
	smtp_fputs(STR(proxy->request), LEN(proxy->request),
		   proxy->service_stream);
    }

    /*
     * Early return if we don't want to wait for a server reply (such as
     * after sending QUIT).
     */
    if (expect == SMTPD_PROX_WANT_NONE)
	return (0);

    /*
     * Censor out non-printable characters in server responses and save
     * complete multi-line responses if possible.
     * 
     * We can't parse or store input that exceeds var_line_limit, so we just
     * skip over it to simplify the remainder of the code below.
     */
    VSTRING_RESET(proxy->reply);
    if (buffer == 0)
	buffer = vstring_alloc(10);
    for (;;) {
	last_char = smtp_get(buffer, proxy->service_stream, var_line_limit,
			     SMTP_GET_FLAG_SKIP);
	printable(STR(buffer), '?');
	if (last_char != '\n')
	    msg_warn("%s: response longer than %d: %.30s...",
		     proxy->service_name, var_line_limit,
		     STR(buffer));
	if (msg_verbose)
	    msg_info("< %s: %.100s", proxy->service_name, STR(buffer));

	/*
	 * Defend against a denial of service attack by limiting the amount
	 * of multi-line text that we are willing to store.
	 */
	if (LEN(proxy->reply) < var_line_limit) {
	    if (VSTRING_LEN(proxy->reply))
		vstring_strcat(proxy->reply, "\r\n");
	    vstring_strcat(proxy->reply, STR(buffer));
	}

	/*
	 * Parse the response into code and text. Ignore unrecognized
	 * garbage. This means that any character except space (or end of
	 * line) will have the same effect as the '-' line continuation
	 * character.
	 */
	for (cp = STR(buffer); *cp && ISDIGIT(*cp); cp++)
	     /* void */ ;
	if (cp - STR(buffer) == 3) {
	    if (*cp == '-')
		continue;
	    if (*cp == ' ' || *cp == 0)
		break;
	}
	msg_warn("received garbage from proxy %s: %.100s",
		 proxy->service_name, STR(buffer));
    }

    /*
     * Log a warning in case the proxy does not send the expected response.
     * Silently accept any response when the client expressed no expectation.
     * 
     * Starting with Postfix 2.6 we don't pass through unexpected 2xx or 3xx
     * proxy replies. They are a source of support problems, so we replace
     * them by generic server error replies.
     */
    if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(proxy->reply)) {
	msg_warn("proxy %s rejected \"%s\": \"%s\"",
		 proxy->service_name, fmt == SMTPD_PROXY_CONN_FMT ?
		 "connection request" : STR(proxy->request),
		 STR(proxy->reply));
	if (*STR(proxy->reply) == SMTPD_PROX_WANT_OK
	    || *STR(proxy->reply) == SMTPD_PROX_WANT_MORE) {
	    smtpd_proxy_rdwr_error(state, 0);
	}
	return (-1);
    } else {
	return (0);
    }
}