Beispiel #1
0
int     main(int unused_argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(1);

    msg_vstream_init(argv[0], VSTREAM_ERR);
    msg_verbose = 1;

    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
	msg_info("testing: \"%s\"", vstring_str(buffer));
	valid_hostname(vstring_str(buffer), DO_GRIPE);
	valid_hostaddr(vstring_str(buffer), DO_GRIPE);
    }
    exit(0);
}
Beispiel #2
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));
}
Beispiel #3
0
int     main(int argc, char **argv)
{
	VSTRING *in = vstring_alloc(10);
	VSTRING *out = vstring_alloc(10);
	int     un_escape = 1;

	if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0)
		msg_fatal("usage: %s [-e (escape)]", argv[0]);

	if (un_escape) {
		while (vstring_fgets_nonl(in, VSTREAM_IN)) {
			unescape(out, vstring_str(in));
			vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
		}
	} else {
		while (vstring_fgets(in, VSTREAM_IN)) {
			escape(out, vstring_str(in), VSTRING_LEN(in));
			vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
		}
	}
	vstream_fflush(VSTREAM_OUT);
	exit(0);
}
Beispiel #4
0
const char *str_long_name_mask_opt(VSTRING *buf, const char *context,
                                   const LONG_NAME_MASK * table,
                                   long mask, int flags)
{
    const char *myname = "name_mask";
    int     len;
    static VSTRING *my_buf = 0;
    int     delim = (flags & NAME_MASK_COMMA ? ',' :
                     (flags & NAME_MASK_PIPE ? '|' : ' '));
    const LONG_NAME_MASK *np;

    if ((flags & STR_NAME_MASK_REQUIRED) == 0)
        msg_panic("%s: missing NAME_MASK_NUMBER/FATAL/RETURN/WARN/IGNORE flag",
                  myname);

    if (buf == 0) {
        if (my_buf == 0)
            my_buf = vstring_alloc(1);
        buf = my_buf;
    }
    VSTRING_RESET(buf);

    for (np = table; mask != 0; np++) {
        if (np->name == 0) {
            if (flags & NAME_MASK_NUMBER) {
                vstring_sprintf_append(buf, "0x%lx%c", mask, delim);
            } else if (flags & NAME_MASK_FATAL) {
                msg_fatal("%s: unknown %s bit in mask: 0x%lx",
                          myname, context, mask);
            } else if (flags & NAME_MASK_RETURN) {
                msg_warn("%s: unknown %s bit in mask: 0x%lx",
                         myname, context, mask);
                return (0);
            } else if (flags & NAME_MASK_WARN) {
                msg_warn("%s: unknown %s bit in mask: 0x%lx",
                         myname, context, mask);
            }
            break;
        }
        if (mask & np->mask) {
            mask &= ~np->mask;
            vstring_sprintf_append(buf, "%s%c", np->name, delim);
        }
    }
    if ((len = VSTRING_LEN(buf)) > 0)
        vstring_truncate(buf, len - 1);
    VSTRING_TERMINATE(buf);

    return (STR(buf));
}
Beispiel #5
0
DICT   *dict_env_open(const char *name, int unused_flags, int dict_flags)
{
    DICT   *dict;

    dict = dict_alloc(DICT_TYPE_ENVIRON, name, sizeof(*dict));
    dict->lookup = dict_env_lookup;
    dict->update = dict_env_update;
    dict->close = dict_env_close;
    dict->flags = dict_flags | DICT_FLAG_FIXED;
    if (dict_flags & DICT_FLAG_FOLD_FIX)
	dict->fold_buf = vstring_alloc(10);
    dict->owner.status = DICT_OWNER_TRUSTED;
    return (DICT_DEBUG (dict));
}
Beispiel #6
0
int     main(int unused_argc, char **unused_argv)
{
    VSTRING *buf = vstring_alloc(1);
    ARGV   *argv;
    struct action *ap;
    int     interactive = isatty(0);

    endp_prop = vstring_alloc(1);
    dest_prop = vstring_alloc(1);

    vstream_fileno(VSTREAM_ERR) = 1;

    while (get_buffer(buf, VSTREAM_IN, interactive) != VSTREAM_EOF) {
	argv = argv_split(STR(buf), CHARS_SPACE);
	if (argv->argc > 0 && argv->argv[0][0] != '#') {
	    msg_verbose = verbose_level;
	    for (ap = actions; ap->command != 0; ap++) {
		if (strcmp(ap->command, argv->argv[0]) == 0) {
		    if ((ap->flags & FLAG_NEED_CACHE) != 0 && scache == 0)
			msg_error("no session cache");
		    else
			ap->action(argv);
		    break;
		}
	    }
	    msg_verbose = 0;
	    if (ap->command == 0)
		msg_error("bad command: %s", argv->argv[0]);
	}
	argv_free(argv);
    }
    scache_free(scache);
    vstring_free(endp_prop);
    vstring_free(dest_prop);
    vstring_free(buf);
    exit(0);
}
Beispiel #7
0
int     main(int unused_argc, char **unused_argv)
{
	VSTRING *vp = vstring_alloc(100);
	TOK822 *list;
	VSTRING *buf = vstring_alloc(100);

#define TEST_TOKEN_LIMIT 20

	while (readlline(buf, VSTREAM_IN, (int *) 0)) {
		while (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\n') {
			vstring_end(buf)[-1] = 0;
			vstring_truncate(buf, VSTRING_LEN(buf) - 1);
		}
		if (!isatty(vstream_fileno(VSTREAM_IN)))
			vstream_printf(">>>%s<<<\n\n", vstring_str(buf));
		list = tok822_parse_limit(vstring_str(buf), TEST_TOKEN_LIMIT);
		vstream_printf("Parse tree:\n");
		tok822_print(list, 0);
		vstream_printf("\n");

		vstream_printf("Internalized:\n%s\n\n",
				vstring_str(tok822_internalize(vp, list, TOK822_STR_DEFL)));
		vstream_fflush(VSTREAM_OUT);
		vstream_printf("Externalized, no newlines inserted:\n%s\n\n",
				vstring_str(tok822_externalize(vp, list,
						TOK822_STR_DEFL | TOK822_STR_TRNC)));
		vstream_fflush(VSTREAM_OUT);
		vstream_printf("Externalized, newlines inserted:\n%s\n\n",
				vstring_str(tok822_externalize(vp, list,
						TOK822_STR_DEFL | TOK822_STR_LINE | TOK822_STR_TRNC)));
		vstream_fflush(VSTREAM_OUT);
		tok822_free_tree(list);
	}
	vstring_free(vp);
	vstring_free(buf);
	return (0);
}
Beispiel #8
0
int     milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
			           int flags, void *ptr)
{
    MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
    int     ret;

    /*
     * We could simplify this by moving memory allocation into attr_scan*().
     */
    VSTRING *conn_macros = vstring_alloc(10);
    VSTRING *helo_macros = vstring_alloc(10);
    VSTRING *mail_macros = vstring_alloc(10);
    VSTRING *rcpt_macros = vstring_alloc(10);
    VSTRING *data_macros = vstring_alloc(10);
    VSTRING *eoh_macros = vstring_alloc(10);
    VSTRING *eod_macros = vstring_alloc(10);
    VSTRING *unk_macros = vstring_alloc(10);

    /*
     * The attribute order does not matter, except that it must be the same
     * as in the milter_macros_print() function.
     */
    ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, conn_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, helo_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mail_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, data_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, eoh_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, eod_macros,
		  ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_UNK, unk_macros,
		  ATTR_TYPE_END);

    /*
     * Don't optimize for error.
     */
    mp->conn_macros = vstring_export(conn_macros);
    mp->helo_macros = vstring_export(helo_macros);
    mp->mail_macros = vstring_export(mail_macros);
    mp->rcpt_macros = vstring_export(rcpt_macros);
    mp->data_macros = vstring_export(data_macros);
    mp->eoh_macros = vstring_export(eoh_macros);
    mp->eod_macros = vstring_export(eod_macros);
    mp->unk_macros = vstring_export(unk_macros);

    return (ret == 8 ? 1 : -1);
}
Beispiel #9
0
char   *dir_forest(VSTRING *buf, const char *path, int depth)
{
    const char *myname = "dir_forest";
    static VSTRING *private_buf = 0;
    int     n;
    const char *cp;
    int     ch;

    /*
     * Sanity checks.
     */
    if (*path == 0)
	msg_panic("%s: empty path", myname);
    if (depth < 1)
	msg_panic("%s: depth %d", myname, depth);

    /*
     * Your buffer or mine?
     */
    if (buf == 0) {
	if (private_buf == 0)
	    private_buf = vstring_alloc(1);
	buf = private_buf;
    }

    /*
     * Generate one or more subdirectory levels, depending on the pathname
     * contents. When the pathname is short, use underscores instead.
     * Disallow non-printable characters or characters that are special to
     * the file system.
     */
    VSTRING_RESET(buf);
    for (cp = path, n = 0; n < depth; n++) {
	if ((ch = *cp) == 0) {
	    ch = '_';
	} else {
	    if (!ISPRINT(ch) || ch == '.' || ch == '/')
		msg_panic("%s: invalid pathname: %s", myname, path);
	    cp++;
	}
	VSTRING_ADDCH(buf, ch);
	VSTRING_ADDCH(buf, '/');
    }
    VSTRING_TERMINATE(buf);

    if (msg_verbose > 1)
	msg_info("%s: %s -> %s", myname, path, vstring_str(buf));
    return (vstring_str(buf));
}
Beispiel #10
0
const char *check_user_acl_byuid(char *acl, uid_t uid)
{
    struct mypasswd *mypwd;
    STRING_LIST *list;
    static VSTRING *who = 0;
    int     matched;
    const char *name;

    /*
     * Optimize for the most common case. This also makes Postfix a little
     * more robust in the face of local infrastructure failures.
     */
    if (strcmp(acl, STATIC_ANYONE_ACL) == 0)
	return (0);

    /*
     * XXX: Substitute "unknown" for UIDs without username, so that
     * static:anyone results in "permit" even when the uid is not found in
     * the password file, and so that a pattern of !unknown can be used to
     * block non-existent accounts.
     * 
     * The alternative is to use the UID as a surrogate lookup key for
     * non-existent accounts. There are several reasons why this is not a
     * good idea. 1) An ACL with a numerical UID should work regardless of
     * whether or not an account has a password file entry. Therefore we
     * would always have search on the numerical UID whenever the username
     * fails to produce a match. 2) The string-list infrastructure is not
     * really suitable for mixing numerical and non-numerical user
     * information, because the numerical match is done in a separate pass
     * from the non-numerical match. This breaks when the ! operator is used.
     */
    if ((mypwd = mypwuid(uid)) == 0) {
	name = "unknown";
    } else {
	name = mypwd->pw_name;
    }

    list = string_list_init(MATCH_FLAG_NONE, acl);
    if ((matched = string_list_match(list, name)) == 0) {
	if (!who)
	    who = vstring_alloc(10);
	vstring_strcpy(who, name);
    }
    string_list_free(list);
    if (mypwd)
	mypwfree(mypwd);

    return (matched ? 0 : vstring_str(who));
}
Beispiel #11
0
static const char *dict_env_lookup(DICT *dict, const char *name)
{
    dict->error = 0;

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_FIX) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(10);
	vstring_strcpy(dict->fold_buf, name);
	name = lowercase(vstring_str(dict->fold_buf));
    }
    return (safe_getenv(name));
}
Beispiel #12
0
static const char *dict_ht_lookup(DICT *dict, const char *name)
{
    DICT_HT *dict_ht = (DICT_HT *) dict;

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_FIX) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(10);
	vstring_strcpy(dict->fold_buf, name);
	name = lowercase(vstring_str(dict->fold_buf));
    }
    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name));
}
Beispiel #13
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 */
}
Beispiel #14
0
int     main(int argc, char **argv)
{
    int     type;
    char   *name;
    VSTRING *fqdn = vstring_alloc(100);
    VSTRING *why = vstring_alloc(100);
    DNS_RR *rr;

    msg_vstream_init(argv[0], VSTREAM_ERR);
    if (argc != 3)
	msg_fatal("usage: %s type name", argv[0]);
    if ((type = dns_type(argv[1])) == 0)
	msg_fatal("invalid query type: %s", argv[1]);
    name = argv[2];
    msg_verbose = 1;
    switch (dns_lookup_types(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why, type, 0)) {
    default:
	msg_fatal("%s", vstring_str(why));
    case DNS_OK:
	printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
	print_rr(rr);
    }
    exit(0);
}
Beispiel #15
0
static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id,
					          int session_id_length,
					          int *unused_copy)
{
    const char *myname = "get_server_session_cb";
    TLS_SESS_STATE *TLScontext;
    VSTRING *cache_id;
    VSTRING *session_data = vstring_alloc(2048);
    SSL_SESSION *session = 0;

    if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0)
	msg_panic("%s: null TLScontext in session lookup callback", myname);

#define GEN_CACHE_ID(buf, id, len, service) \
    do { \
	buf = vstring_alloc(2 * (len + strlen(service))); \
	hex_encode(buf, (char *) (id), (len)); \
    	vstring_sprintf_append(buf, "&s=%s", (service)); \
    	vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
    } while (0)


    GEN_CACHE_ID(cache_id, session_id, session_id_length, TLScontext->serverid);

    if (TLScontext->log_level >= 2)
	msg_info("%s: looking up session %s in %s cache", TLScontext->namaddr,
		 STR(cache_id), TLScontext->cache_type);

    /*
     * Load the session from cache and decode it.
     */
    if (tls_mgr_lookup(TLScontext->cache_type, STR(cache_id),
		       session_data) == TLS_MGR_STAT_OK) {
	session = tls_session_activate(STR(session_data), LEN(session_data));
	if (session && (TLScontext->log_level >= 2))
	    msg_info("%s: reloaded session %s from %s cache",
		     TLScontext->namaddr, STR(cache_id),
		     TLScontext->cache_type);
    }

    /*
     * Clean up.
     */
    vstring_free(cache_id);
    vstring_free(session_data);

    return (session);
}
Beispiel #16
0
DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *fp, off_t offset, int flags)
{
    char   *cp;
    DELIVERED_HDR_INFO *info;
    const HEADER_OPTS *hdr;

    /*
     * Sanity check.
     */
    info = (DELIVERED_HDR_INFO *) mymalloc(sizeof(*info));
    info->flags = flags;
    info->buf = vstring_alloc(10);
    info->table = htable_create(0);

    if (vstream_fseek(fp, offset, SEEK_SET) < 0)
	msg_fatal("seek queue file %s: %m", VSTREAM_PATH(fp));

    /*
     * XXX Assume that mail_copy() produces delivered-to headers that fit in
     * a REC_TYPE_NORM record. Lowercase the delivered-to addresses for
     * consistency.
     * 
     * XXX Don't get bogged down by gazillions of delivered-to headers.
     */
#define DELIVERED_HDR_LIMIT	1000

    while (rec_get(fp, info->buf, 0) == REC_TYPE_NORM
	   && info->table->used < DELIVERED_HDR_LIMIT) {
	if (is_header(STR(info->buf))) {
	    if ((hdr = header_opts_find(STR(info->buf))) != 0
		&& hdr->type == HDR_DELIVERED_TO) {
		cp = STR(info->buf) + strlen(hdr->name) + 1;
		while (ISSPACE(*cp))
		    cp++;
		if (info->flags & FOLD_ADDR_ALL)
		    fold_addr(cp, info->flags);
		if (msg_verbose)
		    msg_info("delivered_hdr_init: %s", cp);
		htable_enter(info->table, cp, (char *) 0);
	    }
	} else if (ISSPACE(STR(info->buf)[0])) {
	    continue;
	} else {
	    break;
	}
    }
    return (info);
}
Beispiel #17
0
PSC_STATE *psc_new_session_state(VSTREAM *stream,
				         const char *addr,
				         const char *port)
{
    PSC_STATE *state;
    HTABLE_INFO *ht;

    state = (PSC_STATE *) mymalloc(sizeof(*state));
    PSC_INIT_TESTS(state);
    if ((state->smtp_client_stream = stream) != 0)
	psc_check_queue_length++;
    state->smtp_server_fd = (-1);
    state->smtp_client_addr = mystrdup(addr);
    state->smtp_client_port = mystrdup(port);
    state->send_buf = vstring_alloc(100);
    state->test_name = "TEST NAME HERE";
    state->dnsbl_reply = 0;
    state->final_reply = "421 4.3.2 Service currently unavailable\r\n";
    state->rcpt_reply = "450 4.3.2 Service currently unavailable\r\n";
    state->command_count = 0;
    state->protocol = MAIL_PROTO_SMTP;
    state->helo_name = 0;
    state->sender = 0;
    state->cmd_buffer = 0;
    state->read_state = 0;
    state->ehlo_discard_mask = 0;		/* XXX Should be ~0 */
    state->expand_buf = 0;

    /*
     * Update the stress level.
     */
    if (psc_stress == 0
	&& psc_check_queue_length >= psc_hiwat_check_queue_length) {
	psc_stress = 1;
	msg_info("entering STRESS mode with %d connections",
		 psc_check_queue_length);
    }

    /*
     * Update the per-client session count.
     */
    if ((ht = htable_locate(psc_client_concurrency, addr)) == 0)
	ht = htable_enter(psc_client_concurrency, addr, (char *) 0);
    ht->value += 1;
    state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value);

    return (state);
}
Beispiel #18
0
void    cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr,
			               MAPS *maps, int propagate)
{
    VSTRING *temp = vstring_alloc(100);

    /*
     * Produce sensible output even in the face of a recoverable error. This
     * simplifies error recovery considerably because we can do delayed error
     * checking in one place, instead of having error handling code all over
     * the place.
     */
    quote_822_local(temp, STR(addr));
    cleanup_map11_external(state, temp, maps, propagate);
    unquote_822_local(addr, STR(temp));
    vstring_free(temp);
}
Beispiel #19
0
int     main(int argc, char **argv)
{
    VSTRING *buf = vstring_alloc(10);
    char   *dir;
    char   *base;

    while (vstring_get_nonl(buf, VSTREAM_IN) > 0) {
	dir = sane_dirname((VSTRING *) 0, STR(buf));
	base = sane_basename((VSTRING *) 0, STR(buf));
	vstream_printf("input=\"%s\" dir=\"%s\" base=\"%s\"\n",
		       STR(buf), dir, base);
    }
    vstream_fflush(VSTREAM_OUT);
    vstring_free(buf);
    return (0);
}
Beispiel #20
0
DICT   *dict_ht_open(const char *name, int unused_open_flags, int dict_flags)
{
    DICT_HT *dict_ht;

    dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht));
    dict_ht->dict.lookup = dict_ht_lookup;
    dict_ht->dict.update = dict_ht_update;
    dict_ht->dict.sequence = dict_ht_sequence;
    dict_ht->dict.close = dict_ht_close;
    dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED;
    if (dict_flags & DICT_FLAG_FOLD_FIX)
	dict_ht->dict.fold_buf = vstring_alloc(10);
    dict_ht->table = htable_create(0);
    dict_ht->dict.owner.status = DICT_OWNER_TRUSTED;
    return (&dict_ht->dict);
}
Beispiel #21
0
int     main(int unused_argc, char **unused_argv)
{
    int     mask_bits;
    VSTRING *buf = vstring_alloc(1);
    const char *mask_string;

    while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
        mask_bits = ehlo_mask(vstring_str(buf));
        mask_string = str_ehlo_mask(mask_bits);
        vstream_printf("%s -> 0x%x -> %s\n", vstring_str(buf), mask_bits,
                       mask_string);
        vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(buf);
    exit(0);
}
Beispiel #22
0
void    smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name,
			        const char *sasl_opts_val)
{
    XSASL_CLIENT_CREATE_ARGS create_args;

    if (msg_verbose)
	msg_info("starting new SASL client");
    if ((session->sasl_client =
	 XSASL_CLIENT_CREATE(smtp_sasl_impl, &create_args,
			     stream = session->stream,
			     service = var_procname,
			     server_name = session->host,
			     security_options = sasl_opts_val)) == 0)
	msg_fatal("SASL per-connection initialization failed");
    session->sasl_reply = vstring_alloc(20);
}
Beispiel #23
0
int     main(int unused_argc, char **unused_argv)
{
    VSTRING *buf = vstring_alloc(100);
    off_t   offset;

    while (vstring_fgets_nonl(buf, VSTREAM_IN)) {
        if ((offset = off_cvt_string(STR(buf))) < 0) {
            msg_warn("bad input %s", STR(buf));
        } else {
            vstream_printf("%s\n", STR(off_cvt_number(buf, offset)));
        }
        vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(buf);
    return (0);
}
Beispiel #24
0
static RESPONSE *response(VSTREAM *stream, VSTRING *buf)
{
    static RESPONSE rdata;
    int     more;
    char   *cp;

    /*
     * Initialize the response data buffer. Defend against a denial of
     * service attack by limiting the amount of multi-line text that we are
     * willing to store.
     */
    if (rdata.buf == 0) {
        rdata.buf = vstring_alloc(100);
        vstring_ctl(rdata.buf, VSTRING_CTL_MAXLEN, (ssize_t) var_line_limit, 0);
    }

    /*
     * Censor out non-printable characters in server responses. Concatenate
     * multi-line server responses. Separate the status code from the text.
     * Leave further parsing up to the application.
     */
#define BUF ((char *) vstring_str(buf))
    VSTRING_RESET(rdata.buf);
    for (;;) {
        smtp_get(buf, stream, var_line_limit, SMTP_GET_FLAG_SKIP);
        for (cp = BUF; *cp != 0; cp++)
            if (!ISPRINT(*cp) && !ISSPACE(*cp))
                *cp = '?';
        cp = BUF;
        if (msg_verbose)
            msg_info("<<< %s", cp);
        while (ISDIGIT(*cp))
            cp++;
        rdata.code = (cp - BUF == 3 ? atoi(BUF) : 0);
        if ((more = (*cp == '-')) != 0)
            cp++;
        while (ISSPACE(*cp))
            cp++;
        vstring_strcat(rdata.buf, cp);
        if (more == 0)
            break;
        VSTRING_ADDCH(rdata.buf, '\n');
    }
    VSTRING_TERMINATE(rdata.buf);
    rdata.str = vstring_str(rdata.buf);
    return (&rdata);
}
Beispiel #25
0
char   *sane_dirname(VSTRING *bp, const char *path)
{
    static VSTRING *buf;
    const char *last;

    /*
     * Your buffer or mine?
     */
    if (bp == 0) {
	bp = buf;
	if (bp == 0)
	    bp = buf = vstring_alloc(10);
    }

    /*
     * Special case: return "." for null or zero-length input.
     */
    if (path == 0 || *path == 0)
	return (STR(vstring_strcpy(bp, ".")));

    /*
     * Remove trailing '/' characters from input. Return "/" if input is all
     * '/' characters.
     */
    last = path + strlen(path) - 1;
    while (*last == '/') {
	if (last == path)
	    return (STR(vstring_strcpy(bp, "/")));
	last--;
    }

    /*
     * This pathname does not end in '/'. Skip to last '/' character if any.
     */
    while (last >= path && *last != '/')
	last--;
    if (last < path)				/* no '/' */
	return (STR(vstring_strcpy(bp, ".")));

    /*
     * Strip trailing '/' characters from dirname (not strictly needed).
     */
    while (last > path && *last == '/')
	last--;

    return (STR(vstring_strncpy(bp, path, last - path + 1)));
}
Beispiel #26
0
MAPS   *maps_create(const char *title, const char *map_names, int dict_flags)
{
    const char *myname = "maps_create";
    char   *temp;
    char   *bufp;
    static char sep[] = CHARS_COMMA_SP;
    static char parens[] = CHARS_BRACE;
    MAPS   *maps;
    char   *map_type_name;
    VSTRING *map_type_name_flags;
    DICT   *dict;

    /*
     * Initialize.
     */
    maps = (MAPS *) mymalloc(sizeof(*maps));
    maps->title = mystrdup(title);
    maps->argv = argv_alloc(2);
    maps->error = 0;

    /*
     * For each specified type:name pair, either register a new dictionary,
     * or increment the reference count of an existing one.
     */
    if (*map_names) {
	bufp = temp = mystrdup(map_names);
	map_type_name_flags = vstring_alloc(10);

#define OPEN_FLAGS	O_RDONLY

	while ((map_type_name = mystrtokq(&bufp, sep, parens)) != 0) {
	    vstring_sprintf(map_type_name_flags, "%s(%o,%s)",
			    map_type_name, OPEN_FLAGS,
			    dict_flags_str(dict_flags));
	    if ((dict = dict_handle(vstring_str(map_type_name_flags))) == 0)
		dict = dict_open(map_type_name, OPEN_FLAGS, dict_flags);
	    if ((dict->flags & dict_flags) != dict_flags)
		msg_panic("%s: map %s has flags 0%o, want flags 0%o",
			  myname, map_type_name, dict->flags, dict_flags);
	    dict_register(vstring_str(map_type_name_flags), dict);
	    argv_add(maps->argv, vstring_str(map_type_name_flags), ARGV_END);
	}
	myfree(temp);
	vstring_free(map_type_name_flags);
    }
    return (maps);
}
Beispiel #27
0
void    cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
{
    VSTRING *clean_addr = vstring_alloc(100);
    const char *bcc;

    /*
     * Note: an unqualified envelope address is for all practical purposes
     * equivalent to a fully qualified local address, both for delivery and
     * for replying. Having to support both forms is error prone, therefore
     * an incomplete envelope address is rewritten to fully qualified form in
     * the local domain context.
     * 
     * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle
     * bounced mail traffic more robustly.
     */
    cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf);
    if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
		    sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
	canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
	if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0)
	    vstring_strcpy(clean_addr, "");
    }
    if (state->flags & CLEANUP_FLAG_MAP_OK) {
	if (cleanup_send_canon_maps
	    && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
	    cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
	if (cleanup_comm_canon_maps
	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
	if (cleanup_masq_domains
	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
	    cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
    }
    CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
    if (state->sender)				/* XXX Can't happen */
	myfree(state->sender);
    state->sender = mystrdup(STR(clean_addr));	/* Used by Milter client */
    if ((state->flags & CLEANUP_FLAG_BCC_OK)
	&& *STR(clean_addr)
	&& cleanup_send_bcc_maps
	&& (bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
				 IGNORE_EXTENSION)) != 0)
	cleanup_addr_bcc(state, bcc);
    vstring_free(clean_addr);
}
Beispiel #28
0
void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
{
    VSTRING *clean_addr = vstring_alloc(100);
    const char *bcc;

    /*
     * Note: an unqualified envelope address is for all practical purposes
     * equivalent to a fully qualified local address, both for delivery and
     * for replying. Having to support both forms is error prone, therefore
     * an incomplete envelope address is rewritten to fully qualified form in
     * the local domain context.
     */
    cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
			     clean_addr, *buf ? buf : var_empty_addr);
    if (state->flags & CLEANUP_FLAG_MAP_OK) {
	if (cleanup_rcpt_canon_maps
	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
	if (cleanup_comm_canon_maps
	    && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
	    cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
				cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
	if (cleanup_masq_domains
	    && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
	    cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
    }
    cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
			  state->orig_rcpt, STR(clean_addr));
    if (state->recip)				/* This can happen */
	myfree(state->recip);
    state->recip = mystrdup(STR(clean_addr));	/* Used by Milter client */
    if ((state->flags & CLEANUP_FLAG_BCC_OK)
	&& *STR(clean_addr)
	&& cleanup_rcpt_bcc_maps) {
	if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr),
				  IGNORE_EXTENSION)) != 0) {
	    cleanup_addr_bcc(state, bcc);
	} else if (cleanup_rcpt_bcc_maps->error) {
	    msg_warn("%s: %s map lookup problem -- "
		     "message not accepted, try again later",
		     state->queue_id, cleanup_rcpt_bcc_maps->title);
	    state->errs |= CLEANUP_STAT_WRITE;
	}
    }
    vstring_free(clean_addr);
}
Beispiel #29
0
const char *fullname(void)
{
    static VSTRING *result;
    char   *cp;
    int     ch;
    uid_t   uid;
    struct passwd *pwd;

    if (result == 0)
	result = vstring_alloc(10);

    /*
     * Try the environment.
     */
    if ((cp = safe_getenv("NAME")) != 0)
	return (vstring_str(vstring_strcpy(result, cp)));

    /*
     * Try the password file database.
     */
    uid = getuid();
    if ((pwd = getpwuid(uid)) == 0)
	return (0);

    /*
     * Replace all `&' characters by the login name of this user, first
     * letter capitalized. Although the full name comes from the protected
     * password file, the actual data is specified by the user so we should
     * not trust its sanity.
     */
    VSTRING_RESET(result);
    for (cp = pwd->pw_gecos; (ch = *(unsigned char *) cp) != 0; cp++) {
	if (ch == ',' || ch == ';' || ch == '%')
	    break;
	if (ch == '&') {
	    if (pwd->pw_name[0]) {
		VSTRING_ADDCH(result, TOUPPER(pwd->pw_name[0]));
		vstring_strcat(result, pwd->pw_name + 1);
	    }
	} else {
	    VSTRING_ADDCH(result, ch);
	}
    }
    VSTRING_TERMINATE(result);
    return (vstring_str(result));
}
Beispiel #30
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);
}