Exemple #1
0
static void pre_jail_init(char *unused_name, char **unused_argv)
{
    mode_t  saved_mask;
    VSTRING *redirect;

    /*
     * Never, ever, get killed by a master signal, as that would corrupt the
     * database when we're in the middle of an update.
     */
    setsid();

    /*
     * Security: don't create root-owned files that contain untrusted data.
     * And don't create Postfix-owned files in root-owned directories,
     * either. We want a correct relationship between (file/directory)
     * ownership and (file/directory) content.
     * 
     * XXX Non-root open can violate the principle of least surprise: Postfix
     * can't open an *SQL config file for database read-write access, even
     * though it can open that same control file for database read-only
     * access.
     * 
     * The solution is to query a map type and obtain its properties before
     * opening it. A clean solution is to add a dict_info() API that is
     * similar to dict_open() except it returns properties (dict flags) only.
     * A pragmatic solution is to overload the existing API and have
     * dict_open() return a dummy map when given a null map name.
     * 
     * However, the proxymap daemon has been opening *SQL maps as non-root for
     * years now without anyone complaining, let's not solve a problem that
     * doesn't exist.
     */
    SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
    redirect = vstring_alloc(100);

    /*
     * Keep state in persistent (external) or volatile (internal) map.
     * 
     * Start the cache cleanup thread after permanently dropping privileges.
     */
#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE \
	    | DICT_FLAG_OPEN_LOCK | DICT_FLAG_UTF8_REQUEST)

    saved_mask = umask(022);
    verify_map =
	dict_cache_open(*var_verify_map ?
			data_redirect_map(redirect, var_verify_map) :
			"internal:verify",
			O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS);
    (void) umask(saved_mask);

    /*
     * Clean up and restore privilege.
     */
    vstring_free(redirect);
    RESTORE_SAVED_EUGID();
}
Exemple #2
0
int     main(int argc, char **argv)
{
    VSTRING *inbuf = vstring_alloc(100);
    VSTRING *result = vstring_alloc(100);
    char   *bufp;
    char   *cmd;
    char   *target;
    char   *junk;

    mail_conf_read();

    while (vstring_get_nonl(inbuf, VSTREAM_IN) != VSTREAM_EOF) {
	bufp = STR(inbuf);
	if (!isatty(0)) {
	    vstream_printf("> %s\n", bufp);
	    vstream_fflush(VSTREAM_OUT);
	}
	if (*bufp == '#')
	    continue;
	if ((cmd = mystrtok(&bufp, " \t")) == 0) {
	    vstream_printf("usage: file path|map maptype:mapname\n");
	    vstream_fflush(VSTREAM_OUT);
	    continue;
	}
	target = mystrtok(&bufp, " \t");
	junk = mystrtok(&bufp, " \t");
	if (strcmp(cmd, "file") == 0 && target && !junk) {
	    data_redirect_file(result, target);
	    vstream_printf("%s -> %s\n", target, STR(result));
	} else if (strcmp(cmd, "map") == 0 && target && !junk) {
	    data_redirect_map(result, target);
	    vstream_printf("%s -> %s\n", target, STR(result));
	} else {
	    vstream_printf("usage: file path|map maptype:mapname\n");
	}
	vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(inbuf);
    return (0);
}
Exemple #3
0
static void pre_jail_init(char *unused_name, char **unused_argv)
{
    VSTRING *redirect;

    /*
     * Open read-only maps before dropping privilege, for consistency with
     * other Postfix daemons.
     */
    psc_acl_pre_jail_init(var_mynetworks, VAR_PSC_ACL);
    if (*var_psc_acl)
	psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
    /* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */
    if (*var_psc_forbid_cmds)
	psc_forbid_cmds = string_list_init(MATCH_FLAG_RETURN,
					   var_psc_forbid_cmds);
    if (*var_psc_dnsbl_reply)
	psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
				    DICT_FLAG_DUP_WARN);

    /*
     * Never, ever, get killed by a master signal, as that would corrupt the
     * database when we're in the middle of an update.
     */
    if (setsid() < 0)
	msg_warn("setsid: %m");

    /*
     * Security: don't create root-owned files that contain untrusted data.
     * And don't create Postfix-owned files in root-owned directories,
     * either. We want a correct relationship between (file or directory)
     * ownership and (file or directory) content. To open files before going
     * to jail, temporarily drop root privileges.
     */
    SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
    redirect = vstring_alloc(100);

    /*
     * Keep state in persistent external map. As a safety measure we sync the
     * database on each update. This hurts on LINUX file systems that sync
     * all dirty disk blocks whenever any application invokes fsync().
     * 
     * Start the cache maintenance pseudo thread after dropping privileges.
     */
#define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
	    DICT_FLAG_OPEN_LOCK)

    if (*var_psc_cache_map)
	psc_cache_map =
	    dict_cache_open(data_redirect_map(redirect, var_psc_cache_map),
			    O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS);

    /*
     * Clean up and restore privilege.
     */
    vstring_free(redirect);
    RESTORE_SAVED_EUGID();

    /*
     * Initialize the dummy SMTP engine.
     */
    psc_smtpd_pre_jail_init();
}
Exemple #4
0
static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
{
    char   *path;
    struct timeval tv;
    TLSMGR_SCACHE *ent;
    VSTRING *redirect;
    HTABLE *dup_filter;
    const char *dup_label;

    /*
     * If nothing else works then at least this will get us a few bits of
     * entropy.
     * 
     * XXX This is our first call into the OpenSSL library. We should find out
     * if this can be moved to the post-jail initialization phase, without
     * breaking compatibility with existing installations.
     */
    GETTIMEOFDAY(&tv);
    tv.tv_sec ^= getpid();
    RAND_seed(&tv, sizeof(struct timeval));

    /*
     * Open the external entropy source. We will not be able to open it again
     * after we are sent to chroot jail, so we keep it open. Errors are not
     * fatal. The exchange file (see below) is the only entropy source that
     * really matters in the long run.
     * 
     * Security note: we open the entropy source while privileged, but we don't
     * access the source until after we release privileges. This way, none of
     * the OpenSSL code gets to execute while we are privileged.
     */
    if (*var_tls_rand_source) {

	/*
	 * Source is a random device.
	 */
	if (!strncmp(var_tls_rand_source, DEV_PREF, DEV_PREF_LEN)) {
	    path = DEV_PATH(var_tls_rand_source);
	    rand_source_dev = tls_prng_dev_open(path, TLS_MGR_TIMEOUT);
	    if (rand_source_dev == 0)
		msg_warn("cannot open entropy device %s: %m", path);
	}

	/*
	 * Source is an EGD compatible socket.
	 */
	else if (!strncmp(var_tls_rand_source, EGD_PREF, EGD_PREF_LEN)) {
	    path = EGD_PATH(var_tls_rand_source);
	    rand_source_egd = tls_prng_egd_open(path, TLS_MGR_TIMEOUT);
	    if (rand_source_egd == 0)
		msg_warn("cannot connect to EGD server %s: %m", path);
	}

	/*
	 * Source is regular file. We read this only once.
	 */
	else {
	    rand_source_file =
		tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
	}
    } else {
	msg_warn("no entropy source specified with parameter %s",
		 VAR_TLS_RAND_SOURCE);
	msg_warn("encryption keys etc. may be predictable");
    }

    /*
     * Security: don't create root-owned files that contain untrusted data.
     * And don't create Postfix-owned files in root-owned directories,
     * either. We want a correct relationship between (file/directory)
     * ownership and (file/directory) content.
     */
    SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
    redirect = vstring_alloc(100);

    /*
     * Open the PRNG exchange file before going to jail, but don't use root
     * privileges. Start the exchange file read/update pseudo thread after
     * dropping privileges.
     */
    if (*var_tls_rand_exch_name) {
	rand_exch =
	    tls_prng_exch_open(data_redirect_file(redirect,
						  var_tls_rand_exch_name));
	if (rand_exch == 0)
	    msg_fatal("cannot open PRNG exchange file %s: %m",
		      var_tls_rand_exch_name);
    }

    /*
     * Open the session cache files and discard old information before going
     * to jail, but don't use root privilege. Start the cache maintenance
     * pseudo threads after dropping privileges.
     */
    dup_filter = htable_create(sizeof(cache_table) / sizeof(cache_table[0]));
    for (ent = cache_table; ent->cache_label; ++ent) {
	/* Sanitize session timeout */
	if (*ent->cache_timeout > 0) {
	    if (*ent->cache_timeout < TLS_SESSION_LIFEMIN)
		*ent->cache_timeout = TLS_SESSION_LIFEMIN;
	} else {
	    *ent->cache_timeout = 0;
	}
	/* External cache database disabled if timeout is non-positive */
	if (*ent->cache_timeout > 0 && **ent->cache_db) {
	    if ((dup_label = htable_find(dup_filter, *ent->cache_db)) != 0)
		msg_fatal("do not use the same TLS cache file %s for %s and %s",
			  *ent->cache_db, dup_label, ent->cache_label);
	    htable_enter(dup_filter, *ent->cache_db, ent->cache_label);
	    ent->cache_info =
		tls_scache_open(data_redirect_map(redirect, *ent->cache_db),
				ent->cache_label,
				tls_log_mask(ent->log_param,
					   *ent->log_level) & TLS_LOG_CACHE,
				*ent->cache_timeout);
	}
    }
    htable_free(dup_filter, (void (*) (char *)) 0);

    /*
     * Clean up and restore privilege.
     */
    vstring_free(redirect);
    RESTORE_SAVED_EUGID();
}