Ejemplo n.º 1
0
static void tlsmgr_prng_exch_event(int unused_event acl_unused, void *dummy)
{
    const char *myname = "tlsmgr_prng_exch_event";
    unsigned char randbyte;
    int     next_period;
    struct acl_stat st;

    if (acl_msg_verbose)
	acl_msg_info("%s: update PRNG exchange file", myname);

    /*
     * Sanity check. If the PRNG exchange file was removed, there is no point
     * updating it further. Restart the process and update the new file.
     */
    if (acl_fstat(rand_exch->fd.file, &st) < 0)
	acl_msg_fatal("%s: cannot fstat() the PRNG exchange file: %s", myname, acl_last_serror());
    if (st.st_nlink == 0) {
	acl_msg_warn("%s: PRNG exchange file was removed -- exiting to reopen", myname);
	sleep(1);
	exit(0);
    }
    tls_prng_exch_update(rand_exch);

    /*
     * Make prediction difficult for outsiders and calculate the time for the
     * next execution randomly.
     */
    RAND_bytes(&randbyte, 1);
    next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
    acl_event_request_timer(__eventp, tlsmgr_prng_exch_event, dummy, next_period, 0);
}
Ejemplo n.º 2
0
int acl_unix_trigger(ACL_EVENT *event, const char *service,
	const char *buf, int len, int timeout)
{
	const char *myname = "acl_unix_trigger";
	struct ACL_UNIX_TRIGGER *up;
	ACL_SOCKET fd;

	if (acl_msg_verbose > 0)
		acl_msg_info("%s: service %s", myname, service);

	/*
	 * Connect...
	 */
	if ((fd = acl_unix_connect(service, ACL_BLOCKING, timeout)) < 0) {
		if (acl_msg_verbose)
			acl_msg_warn("%s: connect to %s: %s",
				myname, service, strerror(errno));
		return -1;
	}
	acl_close_on_exec(fd, ACL_CLOSE_ON_EXEC);

	/*
	 * Stash away context.
	 */
	up = (struct ACL_UNIX_TRIGGER *) acl_mymalloc(sizeof(*up));
	up->service = acl_mystrdup(service);
	up->stream = acl_vstream_fdopen(fd, O_RDWR, 4096,
			timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX);

	/*
	 * Write the request...
	 */
	if (acl_vstream_writen(up->stream, buf, len) < 0
		|| acl_vstream_writen(up->stream, "", 1) < 0)
	{
		if (acl_msg_verbose)
			acl_msg_warn("%s: write to %s: %s",
				myname, service, strerror(errno));
	}

	/*
	 * Wakeup when the peer disconnects, or when we lose patience.
	 */
#ifdef	__USE_TIMER
	if (timeout > 0)
		acl_event_request_timer(event, acl_unix_trigger_timer,
			(void *) up, (timeout + 100) * 1000000);
	acl_event_enable_read(event, up->stream, 0,
		acl_unix_trigger_event, (void *) up);
#else
	if (timeout > 0)
		acl_event_enable_read(event, up->stream, timeout + 100,
			acl_unix_trigger_event, (void *) up);
	else
		acl_event_enable_read(event, up->stream, 0,
			acl_unix_trigger_event, (void *) up);
#endif

	return 0;
}
Ejemplo n.º 3
0
static void tlsmgr_cache_run_event(int unused_event acl_unused, void *ctx)
{
    const char *myname = "tlsmgr_cache_run_event";
    TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;

    /*
     * This routine runs when it is time for another TLS session cache scan.
     * Make sure this routine gets called again in the future.
     * 
     * Don't start a new scan when the timer goes off while cache cleanup is
     * still in progress.
     */
    if (cache->cache_info->verbose)
	acl_msg_info("%s: start TLS %s session cache cleanup",
		 myname, cache->cache_label);

    if (cache->cache_active == 0)
	cache->cache_active =
	    tls_scache_sequence(cache->cache_info, DICT_SEQ_FUN_FIRST,
				TLS_SCACHE_SEQUENCE_NOTHING);

    acl_event_request_timer(__eventp, tlsmgr_cache_run_event, (char *) cache,
			cache->cache_info->timeout, 0);
}
Ejemplo n.º 4
0
static void tlsmgr_reseed_event(int unused_event acl_unused, void *dummy)
{
    const char *myname = "tlsmgr_reseed_event";
    int     next_period;
    unsigned char randbyte;
    int     must_exit = 0;

    /*
     * Reseed the internal PRNG from external source. Errors are recoverable.
     * We simply restart and reconnect without making a fuss. This is OK
     * because we do require that exchange file updates succeed. The exchange
     * file is the only entropy source that really matters in the long term.
     * 
     * If the administrator specifies an external randomness source that we
     * could not open upon start-up, restart to see if we can open it now
     * (and log a nagging warning if we can't).
     */
    if (*var_tls_rand_source) {

	/*
	 * Source is a random device.
	 */
	if (rand_source_dev) {
	    if (tls_prng_dev_read(rand_source_dev, var_tls_rand_bytes) <= 0) {
		acl_msg_info("%s: cannot read from entropy device %s: %s -- "
			 "exiting to reopen", myname, DEV_PATH(var_tls_rand_source),
			 acl_last_serror());
		must_exit = 1;
	    }
	}

	/*
	 * Source is an EGD compatible socket.
	 */
	else if (rand_source_egd) {
	    if (tls_prng_egd_read(rand_source_egd, var_tls_rand_bytes) <= 0) {
		acl_msg_info("%s: lost connection to EGD server %s -- "
		     "exiting to reconnect", myname, EGD_PATH(var_tls_rand_source));
		must_exit = 1;
	    }
	}

	/*
	 * Source is a regular file. Read the content once and close the
	 * file.
	 */
	else if (rand_source_file) {
	    if (tls_prng_file_read(rand_source_file, var_tls_rand_bytes) <= 0)
		acl_msg_warn("%s: cannot read from entropy file %s: %s",
			 myname, var_tls_rand_source, acl_last_serror());
	    tls_prng_file_close(rand_source_file);
	    rand_source_file = 0;
	    var_tls_rand_source[0] = 0;
	}

	/*
	 * Could not open the external source upon start-up. See if we can
	 * open it this time. Save PRNG state before we exit.
	 */
	else {
	    acl_msg_info("exiting to reopen external entropy source %s",
		     var_tls_rand_source);
	    must_exit = 1;
	}
    }

    /*
     * Save PRNG state in case we must exit.
     */
    if (must_exit) {
	if (rand_exch)
	    tls_prng_exch_update(rand_exch);
	sleep(1);
	acl_msg_info("exit now");
	exit(0);
    }

    /*
     * Make prediction difficult for outsiders and calculate the time for the
     * next execution randomly.
     */
    RAND_bytes(&randbyte, 1);
    next_period = (var_tls_reseed_period * randbyte) / UCHAR_MAX;
    acl_event_request_timer(__eventp, tlsmgr_reseed_event, dummy, next_period, 0);
}
Ejemplo n.º 5
0
void acl_udp_server_request_timer(ACL_EVENT_NOTIFY_TIME timer_fn,
	void *arg, acl_int64 delay, int keep)
{
	acl_event_request_timer(__event, timer_fn, arg, delay, keep);
}
Ejemplo n.º 6
0
static void master_wakeup_timer_event(int type acl_unused,
	ACL_EVENT *event, void *context)
{
	const char *myname = "master_wakeup_timer_event";
	ACL_MASTER_SERV *serv = (ACL_MASTER_SERV *) context;
	static char wakeup = ACL_TRIGGER_REQ_WAKEUP;
	int     status = 0;

	acl_assert(event == acl_var_master_global_event);

	/*
	 * Don't wakeup services whose automatic wakeup feature was
	 * turned off in the mean time.
	 */
	if (serv->wakeup_time == 0)
		return;

	/*
	 * Don't wakeup services whose is ACL_MASTER_SERV_TYPE_SOCK
	 */
	if (serv->type == ACL_MASTER_SERV_TYPE_SOCK)
		return;

	/*
	 * Don't wake up services that are throttled. Find out what
	 * transport to use. We can't block here so we choose a short timeout.
	 */
#define BRIEFLY	1

	if (ACL_MASTER_THROTTLED(serv) == 0) {
		if (acl_msg_verbose)
			acl_msg_info("%s: service %s", myname, serv->name);

		switch (serv->type) {
		case ACL_MASTER_SERV_TYPE_INET:
			status = acl_inet_trigger(acl_var_master_global_event,
				serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
			break;
		case ACL_MASTER_SERV_TYPE_UNIX:
			status = ACL_LOCAL_TRIGGER(acl_var_master_global_event,
				serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
			break;

		/*
		 * If someone compromises the postfix account then this must not
		 * overwrite files outside the chroot jail. Countermeasures:
		 * 
		 * - Limit the damage by accessing the FIFO as postfix not root.
		 * 
		 * - Have fifo_trigger() call safe_open() so we won't follow
		 * arbitrary hard/symlinks to files in/outside the chroot jail.
		 * 
		 * - All non-chroot postfix-related files must be root owned (or
		 * postfix check complains).
		 * 
		 * - The postfix user and group ID must not be shared with other
		 * applications (says the INSTALL documentation).
		 * 
		 * Result of a discussion with Michael Tokarev, who received his
		 * insights from Solar Designer, who tested Postfix with a kernel
		 * module that is paranoid about open() calls.
		 */
		case ACL_MASTER_SERV_TYPE_FIFO:
			if (acl_var_master_limit_privilege)
				acl_set_eugid(acl_var_master_owner_uid,
					acl_var_master_owner_gid);
			status = acl_fifo_trigger(acl_var_master_global_event,
				serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
			if (acl_var_master_limit_privilege)
				acl_set_ugid(getuid(), getgid());
			break;
		default:
			acl_msg_panic("%s: unknown service type: %d",
				myname, serv->type);
		}
		if (status < 0)
			acl_msg_warn("%s: service %s: %s",
				myname, serv->name, strerror(errno));
	}

	/*
	 * Schedule another wakeup event.
	 */
	acl_event_request_timer(acl_var_master_global_event,
		master_wakeup_timer_event, (void *) serv,
		(acl_int64) serv->wakeup_time * 1000000, 0);
}