Exemplo n.º 1
0
static void scache_single_save_dest(SCACHE *scache, int dest_ttl,
				            const char *dest_label,
				            const char *dest_prop,
				            const char *endp_label)
{
    SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
    const char *myname = "scache_single_save_dest";
    int     refresh;

    if (dest_ttl <= 0)
	msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl);

    /*
     * Optimize: reset timer only, if nothing has changed.
     */
    refresh =
	(SCACHE_SINGLE_DEST_BUSY(sp)
	 && strcmp(STR(sp->dest.dest_label), dest_label) == 0
	 && strcmp(STR(sp->dest.dest_prop), dest_prop) == 0
	 && strcmp(STR(sp->dest.endp_label), endp_label) == 0);

    if (refresh == 0) {
	vstring_strcpy(sp->dest.dest_label, dest_label);
	vstring_strcpy(sp->dest.dest_prop, dest_prop);
	vstring_strcpy(sp->dest.endp_label, endp_label);
    }
    event_request_timer(scache_single_expire_dest, (char *) sp, dest_ttl);

    if (msg_verbose)
	msg_info("%s: %s -> %s%s", myname, dest_label, endp_label,
		 refresh ? " (refreshed)" : "");
}
Exemplo n.º 2
0
static void update_entry(const char *new_channel, const char *new_nexthop,
			         const char *rcpt_domain, VSTRING *channel,
			         VSTRING *nexthop)
{

    /*
     * :[nexthop] means don't change the channel, and don't change the
     * nexthop unless a non-default nexthop is specified. Thus, a right-hand
     * side of ":" is the transport table equivalent of a NOOP.
     */
    if (*new_channel == 0) {			/* :[nexthop] */
	if (*new_nexthop != 0)
	    vstring_strcpy(nexthop, new_nexthop);
    }

    /*
     * transport[:[nexthop]] means change the channel, and reset the nexthop
     * to the default unless a non-default nexthop is specified.
     */
    else {
	vstring_strcpy(channel, new_channel);
	if (*new_nexthop != 0)
	    vstring_strcpy(nexthop, new_nexthop);
	else if (strcmp(STR(channel), MAIL_SERVICE_ERROR) != 0
		 && strcmp(STR(channel), MAIL_SERVICE_RETRY) != 0)
	    vstring_strcpy(nexthop, rcpt_domain);
	else
	    vstring_strcpy(nexthop, "Address is undeliverable");
    }
}
Exemplo n.º 3
0
static void xsasl_dovecot_parse_reply_args(XSASL_DOVECOT_SERVER *server,
					         char *line, VSTRING *reply,
					           int success)
{
    char   *next;

    if (server->username) {
	myfree(server->username);
	server->username = 0;
    }

    /*
     * Note: TAB is part of the Dovecot protocol and must not appear in
     * legitimate Dovecot usernames, otherwise the protocol would break.
     */
    for (; line != NULL; line = next) {
	next = split_at(line, '\t');
	if (strncmp(line, "user="******"reason=", 7) == 0) {
	    if (!success) {
		printable(line + 7, '?');
		vstring_strcpy(reply, line + 7);
	    }
	}
    }
}
Exemplo n.º 4
0
int     main(int unused_argc, char **unused_argv)
{
    VSTRING *in_buf = vstring_alloc(10);
    VSTRING *parse_buf = vstring_alloc(10);
    char   *host;
    char   *port;
    const char *err;

    while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) {
	vstream_printf(">> %s\n", STR(in_buf));
	vstream_fflush(VSTREAM_OUT);
	if (*STR(in_buf) == '#')
	    continue;
	vstring_strcpy(parse_buf, STR(in_buf));
	if ((err = host_port(STR(parse_buf), &host, (char *) 0, &port, "default-service")) != 0) {
	    msg_warn("%s in %s", err, STR(in_buf));
	} else {
	    vstream_printf("host %s port %s\n", host, port);
	    vstream_fflush(VSTREAM_OUT);
	}
    }
    vstring_free(in_buf);
    vstring_free(parse_buf);
    return (0);
}
Exemplo n.º 5
0
char   *fold_addr(VSTRING *result, const char *addr, int flags)
{
    char   *cp;

    /*
     * Fold the address as appropriate.
     */
    switch (flags & FOLD_ADDR_ALL) {
    case FOLD_ADDR_HOST:
	if ((cp = strrchr(addr, '@')) != 0) {
	    cp += 1;
	    vstring_strncpy(result, addr, cp - addr);
	    casefold_append(result, cp);
	    break;
	}
	/* FALLTHROUGH */
    case 0:
	vstring_strcpy(result, addr);
	break;
    case FOLD_ADDR_USER:
	if ((cp = strrchr(addr, '@')) != 0) {
	    casefold_len(result, addr, cp - addr);
	    vstring_strcat(result, cp);
	    break;
	}
	/* FALLTHROUGH */
    case FOLD_ADDR_USER | FOLD_ADDR_HOST:
	casefold(result, addr);
	break;
    }
    return (STR(result));
}
Exemplo n.º 6
0
static int scache_single_find_endp(SCACHE *scache, const char *endp_label,
				           VSTRING *endp_prop)
{
    SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
    const char *myname = "scache_single_find_endp";
    int     fd;

    if (!SCACHE_SINGLE_ENDP_BUSY(sp)) {
	if (msg_verbose)
	    msg_info("%s: no endpoint cache: %s", myname, endp_label);
	return (-1);
    }
    if (strcmp(STR(sp->endp.endp_label), endp_label) == 0) {
	vstring_strcpy(endp_prop, STR(sp->endp.endp_prop));
	fd = sp->endp.fd;
	sp->endp.fd = -1;
	scache_single_free_endp(sp);
	if (msg_verbose)
	    msg_info("%s: found: %s fd=%d", myname, endp_label, fd);
	return (fd);
    }
    if (msg_verbose)
	msg_info("%s: not found: %s", myname, endp_label);
    return (-1);
}
Exemplo n.º 7
0
int     main(int argc, char **argv)
{
    VSTRING *buf = vstring_alloc(100);
    MAPS   *maps;

    msg_vstream_init(basename(argv[0]), VSTREAM_ERR);
    if (argc < 3)
	msg_fatal("usage: %s maptype:mapname address...", argv[0]);

    maps = maps_create(argv[1], argv[1], DICT_FLAG_FOLD_FIX);
    mail_params_init();
    if (chdir(var_queue_dir) < 0)
	msg_fatal("chdir(%s): %m", var_queue_dir);
    argv += 1;

    msg_verbose = 1;
    while (--argc && *++argv) {
	msg_info("-- start %s --", *argv);
	smtp_map11_external(vstring_strcpy(buf, *argv), maps, 1);
	msg_info("-- end %s --", *argv);
    }
    vstring_free(buf);
    maps_free(maps);
    return (0);
}
Exemplo n.º 8
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)));
}
Exemplo n.º 9
0
static int xsasl_dovecot_server_next(XSASL_SERVER *xp, const char *request,
				             VSTRING *reply)
{
    XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;

    if (!is_valid_base64(request)) {
	vstring_strcpy(reply, "Invalid base64 data in continued response");
	return XSASL_AUTH_FAIL;
    }
    /* XXX Encapsulate for logging. */
    vstream_fprintf(server->impl->sasl_stream,
		    "CONT\t%u\t%s\n", server->last_request_id, request);
    if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) {
	vstring_strcpy(reply, "Connection lost to authentication server");
	return XSASL_AUTH_TEMP;
    }
    return xsasl_dovecot_handle_reply(server, reply);
}
int     xsasl_cyrus_server_first(XSASL_SERVER *xp, const char *sasl_method,
			          const char *init_response, VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_first";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    char   *dec_buffer;
    unsigned dec_length;
    unsigned reply_len;
    unsigned serveroutlen;
    int     sasl_status;
    SERVEROUT_TYPE serverout = 0;
    int     xsasl_status;

#if SASL_VERSION_MAJOR < 2
    const char *errstr = 0;

#endif

#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))

    if (msg_verbose)
	msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
		 IFELSE(init_response, ", init_response ", ""),
		 IFELSE(init_response, init_response, ""));

    /*
     * SASL authentication protocol start-up. Process any initial client
     * response that was sent along in the AUTH command.
     */
    if (init_response) {
	reply_len = strlen(init_response);
	VSTRING_RESET(server->decoded);		/* Fix 200512 */
	VSTRING_SPACE(server->decoded, reply_len);
	if ((sasl_status = SASL_DECODE64(init_response, reply_len,
					 dec_buffer = STR(server->decoded),
					 vstring_avail(server->decoded),
					 &dec_length)) != SASL_OK) {
	    vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	    return (XSASL_AUTH_FORM);
	}
	if (msg_verbose)
	    msg_info("%s: decoded initial response %s", myname, dec_buffer);
    } else {
	dec_buffer = 0;
	dec_length = 0;
    }
    sasl_status = SASL_SERVER_START(server->sasl_conn, sasl_method, dec_buffer,
				    dec_length, &serverout,
				    &serveroutlen, &errstr);
    xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
						    serveroutlen, reply);
#if SASL_VERSION_MAJOR < 2
    /* SASL version 1 doesn't free memory that it allocates. */
    free(serverout);
#endif
    return (xsasl_status);
}
Exemplo n.º 11
0
static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server,
				              VSTRING *reply)
{
    const char *myname = "xsasl_dovecot_handle_reply";
    char   *line, *cmd;

    /* XXX Encapsulate for logging. */
    while (vstring_get_nonl(server->sasl_line,
			    server->impl->sasl_stream) != VSTREAM_EOF) {
	line = vstring_str(server->sasl_line);

	if (msg_verbose)
	    msg_info("%s: auth reply: %s", myname, line);

	cmd = line;
	line = split_at(line, '\t');

	if (strcmp(cmd, "OK") == 0) {
	    if (xsasl_dovecot_parse_reply(server, &line) == 0) {
		/* authentication successful */
		xsasl_dovecot_parse_reply_args(server, line, reply, 1);
		return XSASL_AUTH_DONE;
	    }
	} else if (strcmp(cmd, "CONT") == 0) {
	    if (xsasl_dovecot_parse_reply(server, &line) == 0) {
		vstring_strcpy(reply, line);
		return XSASL_AUTH_MORE;
	    }
	} else if (strcmp(cmd, "FAIL") == 0) {
	    if (xsasl_dovecot_parse_reply(server, &line) == 0) {
		/* authentication failure */
		xsasl_dovecot_parse_reply_args(server, line, reply, 0);
		return XSASL_AUTH_FAIL;
	    }
	} else {
	    /* ignore */
	}
    }

    vstring_strcpy(reply, "Connection lost to authentication server");
    return XSASL_AUTH_TEMP;
}
Exemplo n.º 12
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. Note that we
     * only need to match the "static:" substring, not the result value.
     */
    if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 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.
     * 
     * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down)
     * invoke mypwuid_err(), and either change the user_acl() API to
     * propagate the error to the caller, or treat lookup errors as fatal.
     */
    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));
}
Exemplo n.º 13
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(state, 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) {
	if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
				  IGNORE_EXTENSION)) != 0) {
	    cleanup_addr_bcc(state, bcc);
	} else if (cleanup_send_bcc_maps->error) {
	    msg_warn("%s: %s map lookup problem -- "
		     "message not accepted, try again later",
		     state->queue_id, cleanup_send_bcc_maps->title);
	    state->errs |= CLEANUP_STAT_WRITE;
	}
    }
    vstring_free(clean_addr);
}
static int xsasl_cyrus_server_auth_response(int sasl_status,
					            SERVEROUT_TYPE serverout,
					            unsigned serveroutlen,
					            VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_auth_response";
    unsigned enc_length;
    unsigned enc_length_out;

    /*
     * Encode the server first/next non-error response; otherwise return the
     * unencoded error text that corresponds to the SASL error status.
     * 
     * Regarding the hairy expression below: output from sasl_encode64() comes
     * in multiples of four bytes for each triple of input bytes, plus four
     * bytes for any incomplete last triple, plus one byte for the null
     * terminator.
     */
    if (sasl_status == SASL_OK) {
	vstring_strcpy(reply, "");
	return (XSASL_AUTH_DONE);
    } else if (sasl_status == SASL_CONTINUE) {
	if (msg_verbose)
	    msg_info("%s: uncoded server challenge: %.*s",
		     myname, (int) serveroutlen, serverout);
	enc_length = ((serveroutlen + 2) / 3) * 4 + 1;
	VSTRING_RESET(reply);			/* Fix 200512 */
	VSTRING_SPACE(reply, enc_length);
	if ((sasl_status = sasl_encode64(serverout, serveroutlen,
					 STR(reply), vstring_avail(reply),
					 &enc_length_out)) != SASL_OK)
	    msg_panic("%s: sasl_encode64 botch: %s",
		      myname, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_MORE);
    } else {
	if (sasl_status == SASL_NOUSER)		/* privacy */
	    sasl_status = SASL_BADAUTH;
	vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }
}
Exemplo n.º 15
0
char   *sane_basename(VSTRING *bp, const char *path)
{
    static VSTRING *buf;
    const char *first;
    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--;
    }

    /*
     * The pathname does not end in '/'. Skip to last '/' character if any.
     */
    first = last - 1;
    while (first >= path && *first != '/')
	first--;

    return (STR(vstring_strncpy(bp, first + 1, last - first)));
}
Exemplo n.º 16
0
static void scache_single_save_endp(SCACHE *scache, int endp_ttl,
				            const char *endp_label,
				            const char *endp_prop, int fd)
{
    SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache;
    const char *myname = "scache_single_save_endp";

    if (endp_ttl <= 0)
	msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl);

    if (SCACHE_SINGLE_ENDP_BUSY(sp))
	scache_single_free_endp(sp);		/* dump the cached fd */

    vstring_strcpy(sp->endp.endp_label, endp_label);
    vstring_strcpy(sp->endp.endp_prop, endp_prop);
    sp->endp.fd = fd;
    event_request_timer(scache_single_expire_endp, (char *) sp, endp_ttl);

    if (msg_verbose)
	msg_info("%s: %s fd=%d", myname, endp_label, fd);
}
Exemplo n.º 17
0
int     rewrite_proto(VSTREAM *stream)
{
    RWR_CONTEXT *context;
    TOK822 *tree;

    if (attr_scan(stream, ATTR_FLAG_STRICT,
		  ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
		  ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
		  ATTR_TYPE_END) != 2)
	return (-1);

    if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_LOCAL) == 0)
	context = &local_context;
    else if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_REMOTE) == 0)
	context = &remote_context;
    else {
	msg_warn("unknown context: %s", vstring_str(ruleset));
	return (-1);
    }

    /*
     * Sanity check. An address is supposed to be in externalized form.
     */
    if (*vstring_str(address) == 0) {
	msg_warn("rewrite_addr: null address");
	vstring_strcpy(result, vstring_str(address));
    }

    /*
     * Convert the address from externalized (quoted) form to token list,
     * rewrite it, and convert back.
     */
    else {
	tree = tok822_scan_addr(vstring_str(address));
	rewrite_tree(context, tree);
	tok822_externalize(result, tree, TOK822_STR_DEFL);
	tok822_free_tree(tree);
    }
    if (msg_verbose)
	msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
		 vstring_str(address), vstring_str(result));

    attr_print(stream, ATTR_FLAG_NONE,
	       ATTR_TYPE_INT, MAIL_ATTR_FLAGS, server_flags,
	       ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result),
	       ATTR_TYPE_END);

    if (vstream_fflush(stream) != 0) {
	msg_warn("write rewrite reply: %m");
	return (-1);
    }
    return (0);
}
Exemplo n.º 18
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));
}
Exemplo n.º 19
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));
}
Exemplo n.º 20
0
static void morph_recipient(VSTRING *buf, const char *address, int flags)
{

    /*
     * Quote the recipient address as appropriate.
     */
    if (flags & PIPE_OPT_QUOTE_LOCAL)
	quote_822_local(buf, address);
    else
	vstring_strcpy(buf, address);

    /*
     * Fold the recipient address as appropriate.
     */
    if (flags & PIPE_OPT_FOLD_ALL)
	fold_addr(STR(buf), PIPE_OPT_FOLD_FLAGS(flags));
}
Exemplo n.º 21
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));
}
Exemplo n.º 22
0
static void pcf_gobble_cf_line(VSTRING *full_entry_buf, VSTRING *line_buf,
			            VSTREAM *src, VSTREAM *dst, int *lineno)
{
    int     ch;

    vstring_strcpy(full_entry_buf, STR(line_buf));
    for (;;) {
	if ((ch = VSTREAM_GETC(src)) != VSTREAM_EOF)
	    vstream_ungetc(src, ch);
	if ((ch != '#' && !ISSPACE(ch))
	    || vstring_get(line_buf, src) == VSTREAM_EOF)
	    break;
	lineno += 1;
	if (pcf_find_cf_info(line_buf, dst))
	    vstring_strcat(full_entry_buf, STR(line_buf));
    }
}
Exemplo n.º 23
0
char   *data_redirect_map(VSTRING *result, const char *map)
{
    const char *path;
    const char *map_type;
    size_t  map_type_len;

#define MAP_DELIMITER ":"

    /*
     * Sanity check.
     */
    if (map == STR(result))
	msg_panic("data_redirect_map: result clobbers input");

    /*
     * Parse the input into map type and map name.
     */
    path = strchr(map, MAP_DELIMITER[0]);
    if (path != 0) {
	map_type = map;
	map_type_len = path - map;
	path += 1;
    } else {
	map_type = var_db_type;
	map_type_len = strlen(map_type);
	path = map;
    }

    /*
     * Redirect the pathname.
     */
    vstring_strncpy(result, map_type, map_type_len);
    if (name_code(data_redirect_map_types, NAME_CODE_FLAG_NONE, STR(result))) {
	data_redirect_path(result, path, "table", map);
    } else {
	vstring_strcpy(result, path);
    }

    /*
     * (Re)combine the map type with the map name.
     */
    vstring_prepend(result, MAP_DELIMITER, sizeof(MAP_DELIMITER) - 1);
    vstring_prepend(result, map_type, map_type_len);
    return (STR(result));
}
Exemplo n.º 24
0
static int dict_env_update(DICT *dict, const char *name, const char *value)
{
    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));
    }
    if (setenv(name, value, 1))
	msg_fatal("setenv: %m");

    return (DICT_STAT_SUCCESS);
}
Exemplo n.º 25
0
int     cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
			               MAPS *maps, int propagate)
{
    int     count;
    int     expand_to_self;
    ARGV   *new_addr;
    char   *saved_addr;
    int     did_rewrite = 0;

    /*
     * 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.
     */
    for (count = 0; count < MAX_RECURSION; count++) {
	if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) {
	    if (new_addr->argc > 1)
		msg_warn("%s: multi-valued %s entry for %s",
			 state->queue_id, maps->title, STR(addr));
	    saved_addr = mystrdup(STR(addr));
	    did_rewrite |= strcmp(new_addr->argv[0], STR(addr));
	    vstring_strcpy(addr, new_addr->argv[0]);
	    expand_to_self = !strcasecmp_utf8(saved_addr, STR(addr));
	    myfree(saved_addr);
	    argv_free(new_addr);
	    if (expand_to_self)
		return (did_rewrite);
	} else if (maps->error != 0) {
	    msg_warn("%s: %s map lookup problem for %s -- "
		     "message not accepted, try again later",
		     state->queue_id, maps->title, STR(addr));
	    state->errs |= CLEANUP_STAT_WRITE;
	    return (did_rewrite);
	} else {
	    return (did_rewrite);
	}
    }
    msg_warn("%s: unreasonable %s map nesting for %s -- "
	     "message not accepted, try again later",
	     state->queue_id, maps->title, STR(addr));
    return (did_rewrite);
}
Exemplo n.º 26
0
static int verify_cache_validator(const char *addr, const char *raw_data,
				          void *context)
{
    VSTRING *get_buf = (VSTRING *) context;
    int     addr_status;
    long    probed;
    long    updated;
    char   *text;
    long    now = (long) event_time();

#define POS_OR_NEG_ENTRY_EXPIRED(stat, stamp) \
	(POSITIVE_ENTRY_EXPIRED((stat), (stamp)) \
	    || NEGATIVE_ENTRY_EXPIRED((stat), (stamp)))

    vstring_strcpy(get_buf, raw_data);
    return (verify_parse_entry(STR(get_buf), &addr_status,	/* syntax OK */
			       &probed, &updated, &text) == 0
	    && (now - probed < PROBE_TTL	/* probe in progress */
		|| !POS_OR_NEG_ENTRY_EXPIRED(addr_status, updated)));
}
static int xsasl_cyrus_server_next(XSASL_SERVER *xp, const char *request,
				           VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_next";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    unsigned dec_length;
    unsigned request_len;
    unsigned serveroutlen;
    int     sasl_status;
    SERVEROUT_TYPE serverout = 0;
    int     xsasl_status;

#if SASL_VERSION_MAJOR < 2
    const char *errstr = 0;

#endif

    request_len = strlen(request);
    VSTRING_RESET(server->decoded);		/* Fix 200512 */
    VSTRING_SPACE(server->decoded, request_len);
    if ((sasl_status = SASL_DECODE64(request, request_len,
				     STR(server->decoded),
				     vstring_avail(server->decoded),
				     &dec_length)) != SASL_OK) {
	vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FORM);
    }
    if (msg_verbose)
	msg_info("%s: decoded response: %.*s",
		 myname, (int) dec_length, STR(server->decoded));
    sasl_status = SASL_SERVER_STEP(server->sasl_conn, STR(server->decoded),
				   dec_length, &serverout,
				   &serveroutlen, &errstr);
    xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
						    serveroutlen, reply);
#if SASL_VERSION_MAJOR < 2
    /* SASL version 1 doesn't free memory that it allocates. */
    free(serverout);
#endif
    return (xsasl_status);
}
Exemplo n.º 28
0
static char *data_redirect_path(VSTRING *result, const char *path,
			         const char *log_type, const char *log_name)
{
    struct stat st;

#define PATH_DELIMITER "/"

    (void) sane_dirname(result, path);
    if (stat(STR(result), &st) != 0 || st.st_uid == var_owner_uid) {
	vstring_strcpy(result, path);
    } else {
	msg_warn("request to update %s %s in non-%s directory %s",
		 log_type, log_name, var_mail_owner, STR(result));
	msg_warn("redirecting the request to %s-owned %s %s",
		 var_mail_owner, VAR_DATA_DIR, var_data_dir);
	(void) sane_basename(result, path);
	vstring_prepend(result, PATH_DELIMITER, sizeof(PATH_DELIMITER) - 1);
	vstring_prepend(result, var_data_dir, strlen(var_data_dir));
    }
    return (STR(result));
}
Exemplo n.º 29
0
void    msg_text(int level, const char *text)
{
    int     i;

    /*
     * Sanitize the text. Use a private copy if necessary.
     */
    if (msg_text_lock == 0) {
	msg_text_lock = 1;
	/* OK if terminating signal handler hijacks control before next stmt. */
	if (text != vstring_str(msg_buffer))
	    vstring_strcpy(msg_buffer, text);
	printable(vstring_str(msg_buffer), '?');
	/* On-the-fly initialization for debugging test programs only. */
	if (msg_output_fn_count == 0)
	    msg_vstream_init("unknown", VSTREAM_ERR);
	for (i = 0; i < msg_output_fn_count; i++)
	    msg_output_fn[i] (level, vstring_str(msg_buffer));
	msg_text_lock = 0;
    }
}
Exemplo n.º 30
0
static const char *
dict_erlang_lookup(DICT *dict, const char *key)
{
    int ret;
    char *res;
    const char *myname = "dict_erlang_lookup";
    DICT_ERLANG *dict_erlang = (DICT_ERLANG *)dict;

    dict_erlang->dict.error = 0;

    if (dict->flags & DICT_FLAG_FOLD_FIX) {
        if (dict->fold_buf == NULL)
            dict->fold_buf = vstring_alloc(10);
        vstring_strcpy(dict->fold_buf, key);
        key = lowercase(vstring_str(dict->fold_buf));
    }

    if (db_common_check_domain(dict_erlang->ctx, key) == 0) {
        if (msg_verbose)
            msg_info("%s: Skipping lookup of '%s'", myname, key);
        return 0;
    }

    ret = erlang_query(dict_erlang, key, dict_erlang->nodes,
                       dict_erlang->cookie, dict_erlang->mod,
                       dict_erlang->fun, &res);
    switch (ret) {
    case -1:
        dict_erlang->dict.error = DICT_ERR_RETRY;
        return NULL;
    case 0:
        /* Not found */
        return NULL;
    case 1:
        return res;
    default:
        msg_warn("unexpected query result");
        return NULL;
    }
}