Example #1
1
/*
 * SendQuery: send the query string to the backend
 * (and print out results)
 *
 * Note: This is the "front door" way to send a query. That is, use it to
 * send queries actually entered by the user. These queries will be subject to
 * single step mode.
 * To send "back door" queries (generated by slash commands, etc.) in a
 * controlled way, use PSQLexec().
 *
 * Returns true if the query executed successfully, false otherwise.
 */
bool
SendQuery(const char *query)
{
	PGresult   *results;
	TimevalStruct before,
				after;
	bool		OK;

	if (!pset.db)
	{
		psql_error("You are currently not connected to a database.\n");
		return false;
	}

	if (GetVariableBool(pset.vars, "SINGLESTEP"))
	{
		char		buf[3];

		printf(gettext("***(Single step mode: verify command)*******************************************\n"
					   "%s\n"
					   "***(press return to proceed or enter x and return to cancel)********************\n"),
			   query);
		fflush(stdout);
		if (fgets(buf, sizeof(buf), stdin) != NULL)
			if (buf[0] == 'x')
				return false;
	}
	else if (VariableEquals(pset.vars, "ECHO", "queries"))
	{
		puts(query);
		fflush(stdout);
	}

	SetCancelConn();

	if (PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
		!GetVariableBool(pset.vars, "AUTOCOMMIT") &&
		!is_transact_command(query))
	{
		results = PQexec(pset.db, "BEGIN");
		if (PQresultStatus(results) != PGRES_COMMAND_OK)
		{
			psql_error("%s", PQerrorMessage(pset.db));
			PQclear(results);
			ResetCancelConn();
			return false;
		}
		PQclear(results);
	}

	if (pset.timing)
		GETTIMEOFDAY(&before);

	results = PQexec(pset.db, query);

	/* these operations are included in the timing result: */
	OK = (AcceptResult(results) && ProcessCopyResult(results));

	if (pset.timing)
		GETTIMEOFDAY(&after);

	/* but printing results isn't: */
	if (OK)
		OK = PrintQueryResults(results);

	PQclear(results);

	/* Possible microtiming output */
	if (OK && pset.timing)
		printf(gettext("Time: %.3f ms\n"), DIFF_MSEC(&after, &before));

	/* check for events that may occur during query execution */

	if (pset.encoding != PQclientEncoding(pset.db) &&
		PQclientEncoding(pset.db) >= 0)
	{
		/* track effects of SET CLIENT_ENCODING */
		pset.encoding = PQclientEncoding(pset.db);
		pset.popt.topt.encoding = pset.encoding;
		SetVariable(pset.vars, "ENCODING",
					pg_encoding_to_char(pset.encoding));
	}

	PrintNotifications();

	return OK;
}
Example #2
0
/*
 * hourly_stats - print some interesting stats
 */
void
write_stats(void)
{
	FILE	*fp;
	double	ftemp;
#ifdef DOSYNCTODR
	struct timeval tv;
#if !defined(VMS)
	int	prio_set;
#endif
#ifdef HAVE_GETCLOCK
        struct timespec ts;
#endif
	int	o_prio;

	/*
	 * Sometimes having a Sun can be a drag.
	 *
	 * The kernel variable dosynctodr controls whether the system's
	 * soft clock is kept in sync with the battery clock. If it
	 * is zero, then the soft clock is not synced, and the battery
	 * clock is simply left to rot. That means that when the system
	 * reboots, the battery clock (which has probably gone wacky)
	 * sets the soft clock. That means ntpd starts off with a very
	 * confused idea of what time it is. It then takes a large
	 * amount of time to figure out just how wacky the battery clock
	 * has made things drift, etc, etc. The solution is to make the
	 * battery clock sync up to system time. The way to do THAT is
	 * to simply set the time of day to the current time of day, but
	 * as quickly as possible. This may, or may not be a sensible
	 * thing to do.
	 *
	 * CAVEAT: settimeofday() steps the sun clock by about 800 us,
	 *         so setting DOSYNCTODR seems a bad idea in the
	 *         case of us resolution
	 */

#if !defined(VMS)
	/*
	 * (prr) getpriority returns -1 on error, but -1 is also a valid
	 * return value (!), so instead we have to zero errno before the
	 * call and check it for non-zero afterwards.
	 */
	errno = 0;
	prio_set = 0;
	o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */

	/*
	 * (prr) if getpriority succeeded, call setpriority to raise
	 * scheduling priority as high as possible.  If that succeeds
	 * as well, set the prio_set flag so we remember to reset
	 * priority to its previous value below.  Note that on Solaris
	 * 2.6 (and beyond?), both getpriority and setpriority will fail
	 * with ESRCH, because sched_setscheduler (called from main) put
	 * us in the real-time scheduling class which setpriority
	 * doesn't know about. Being in the real-time class is better
	 * than anything setpriority can do, anyhow, so this error is
	 * silently ignored.
	 */
	if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0))
		prio_set = 1;	/* overdrive */
#endif /* VMS */
#ifdef HAVE_GETCLOCK
        (void) getclock(TIMEOFDAY, &ts);
        tv.tv_sec = ts.tv_sec;
        tv.tv_usec = ts.tv_nsec / 1000;
#else /*  not HAVE_GETCLOCK */
	GETTIMEOFDAY(&tv,(struct timezone *)NULL);
#endif /* not HAVE_GETCLOCK */
	if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0)
		msyslog(LOG_ERR, "can't sync battery time: %m");
#if !defined(VMS)
	if (prio_set)
		setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
#endif /* VMS */
#endif /* DOSYNCTODR */
	record_sys_stats();
	ftemp = fabs(prev_drift_comp - drift_comp); 
	prev_drift_comp = drift_comp;
	if (ftemp > clock_phi)
		return;

	if (stats_drift_file != 0 && drift_file_sw) {

		/*
		 * When the frequency file is written, initialize the
		 * wander threshold to a configured initial value.
		 * Thereafter reduce it by a factor of 0.5. When it
		 * drops below the frequency wander, write the frequency
		 * file. This adapts to the prevailing wander yet
		 * minimizes the file writes.
		 */
		drift_file_sw = FALSE;
		wander_resid *= 0.5;
#ifdef DEBUG
		if (debug)
			printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n",
			    clock_stability * 1e6, wander_resid * 1e6,
			    drift_comp * 1e6);
#endif
 		if (sys_leap != LEAP_NOTINSYNC && clock_stability >
		    wander_resid) {
			wander_resid = wander_threshold;
			if ((fp = fopen(stats_temp_file, "w")) == NULL)
			    {
				msyslog(LOG_ERR,
				    "frequency file %s: %m",
				    stats_temp_file);
				return;
			}
			fprintf(fp, "%.3f\n", drift_comp * 1e6);
			(void)fclose(fp);
			/* atomic */
#ifdef SYS_WINNT
			if (_unlink(stats_drift_file)) /* rename semantics differ under NT */
				msyslog(LOG_WARNING, 
					"Unable to remove prior drift file %s, %m", 
					stats_drift_file);
#endif /* SYS_WINNT */

#ifndef NO_RENAME
			if (rename(stats_temp_file, stats_drift_file))
				msyslog(LOG_WARNING, 
					"Unable to rename temp drift file %s to %s, %m", 
					stats_temp_file, stats_drift_file);
#else
			/* we have no rename NFS of ftp in use */
			if ((fp = fopen(stats_drift_file, "w")) ==
			    NULL) {
				msyslog(LOG_ERR,
				    "frequency file %s: %m",
				    stats_drift_file);
				return;
			}
#endif

#if defined(VMS)
			/* PURGE */
			{
				$DESCRIPTOR(oldvers,";-1");
				struct dsc$descriptor driftdsc = {
					strlen(stats_drift_file), 0, 0,
					    stats_drift_file };
				while(lib$delete_file(&oldvers,
				    &driftdsc) & 1);
			}
#endif
		} else {
			/* XXX: Log a message at INFO level */
		}
	}
}
Example #3
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();
}
Example #4
0
int     main(int argc, char **argv)
{
    struct stat st;
    int     fd;
    int     c;
    VSTRING *buf;
    int     status;
    MAIL_STREAM *dst;
    int     rec_type;
    static char *segment_info[] = {
	REC_TYPE_POST_ENVELOPE, REC_TYPE_POST_CONTENT, REC_TYPE_POST_EXTRACT, ""
    };
    char  **expected;
    uid_t   uid = getuid();
    ARGV   *import_env;
    const char *error_text;
    char   *attr_name;
    char   *attr_value;
    const char *errstr;
    char   *junk;
    struct timeval start;
    int     saved_errno;
    int     from_count = 0;
    int     rcpt_count = 0;
    int     validate_input = 1;

    /*
     * Fingerprint executables and core dumps.
     */
    MAIL_VERSION_STAMP_ALLOCATE;

    /*
     * Be consistent with file permissions.
     */
    umask(022);

    /*
     * To minimize confusion, make sure that the standard file descriptors
     * are open before opening anything else. XXX Work around for 44BSD where
     * fstat can return EBADF on an open file descriptor.
     */
    for (fd = 0; fd < 3; fd++)
	if (fstat(fd, &st) == -1
	    && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
	    msg_fatal("open /dev/null: %m");

    /*
     * Set up logging. Censor the process name: it is provided by the user.
     */
    argv[0] = "postdrop";
    msg_vstream_init(argv[0], VSTREAM_ERR);
    msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
    set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));

    /*
     * Check the Postfix library version as soon as we enable logging.
     */
    MAIL_VERSION_CHECK;

    /*
     * Parse JCL. This program is set-gid and must sanitize all command-line
     * arguments. The configuration directory argument is validated by the
     * mail configuration read routine. Don't do complex things until we have
     * completed initializations.
     */
    while ((c = GETOPT(argc, argv, "c:rv")) > 0) {
	switch (c) {
	case 'c':
	    if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
		msg_fatal("out of memory");
	    break;
	case 'r':				/* forward compatibility */
	    break;
	case 'v':
	    if (geteuid() == 0)
		msg_verbose++;
	    break;
	default:
	    msg_fatal("usage: %s [-c config_dir] [-v]", argv[0]);
	}
    }

    /*
     * Read the global configuration file and extract configuration
     * information. Some claim that the user should supply the working
     * directory instead. That might be OK, given that this command needs
     * write permission in a subdirectory called "maildrop". However we still
     * need to reliably detect incomplete input, and so we must perform
     * record-level I/O. With that, we should also take the opportunity to
     * perform some sanity checks on the input.
     */
    mail_conf_read();
    /* Re-evaluate mail_task() after reading main.cf. */
    msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
    get_mail_conf_str_table(str_table);

    /*
     * Mail submission access control. Should this be in the user-land gate,
     * or in the daemon process?
     */
    mail_dict_init();
    if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl,
				       uid)) != 0)
	msg_fatal("User %s(%ld) is not allowed to submit mail",
		  errstr, (long) uid);

    /*
     * Stop run-away process accidents by limiting the queue file size. This
     * is not a defense against DOS attack.
     */
    if (var_message_limit > 0 && get_file_limit() > var_message_limit)
	set_file_limit((off_t) var_message_limit);

    /*
     * This program is installed with setgid privileges. Strip the process
     * environment so that we don't have to trust the C library.
     */
    import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ);
    clean_env(import_env->argv);
    argv_free(import_env);

    if (chdir(var_queue_dir))
	msg_fatal("chdir %s: %m", var_queue_dir);
    if (msg_verbose)
	msg_info("chdir %s", var_queue_dir);

    /*
     * Set up signal handlers and a runtime error handler so that we can
     * clean up incomplete output.
     * 
     * postdrop_sig() uses the in-kernel SIGINT handler address as an atomic
     * variable to prevent nested postdrop_sig() calls. For this reason, the
     * SIGINT handler must be configured before other signal handlers are
     * allowed to invoke postdrop_sig().
     */
    signal(SIGPIPE, SIG_IGN);
    signal(SIGXFSZ, SIG_IGN);

    signal(SIGINT, postdrop_sig);
    signal(SIGQUIT, postdrop_sig);
    if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
	signal(SIGTERM, postdrop_sig);
    if (signal(SIGHUP, SIG_IGN) == SIG_DFL)
	signal(SIGHUP, postdrop_sig);
    msg_cleanup(postdrop_cleanup);

    /* End of initializations. */

    /*
     * Don't trust the caller's time information.
     */
    GETTIMEOFDAY(&start);

    /*
     * Create queue file. mail_stream_file() never fails. Send the queue ID
     * to the caller. Stash away a copy of the queue file name so we can
     * clean up in case of a fatal error or an interrupt.
     */
    dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
			   var_pickup_service, 0444);
    attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
	       SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id),
	       ATTR_TYPE_END);
    vstream_fflush(VSTREAM_OUT);
    postdrop_path = mystrdup(VSTREAM_PATH(dst->stream));

    /*
     * Copy stdin to file. The format is checked so that we can recognize
     * incomplete input and cancel the operation. With the sanity checks
     * applied here, the pickup daemon could skip format checks and pass a
     * file descriptor to the cleanup daemon. These are by no means all
     * sanity checks - the cleanup service and queue manager services will
     * reject messages that lack required information.
     * 
     * If something goes wrong, slurp up the input before responding to the
     * client, otherwise the client will give up after detecting SIGPIPE.
     * 
     * Allow attribute records if the attribute specifies the MIME body type
     * (sendmail -B).
     */
    vstream_control(VSTREAM_IN, CA_VSTREAM_CTL_PATH("stdin"), CA_VSTREAM_CTL_END);
    buf = vstring_alloc(100);
    expected = segment_info;
    /* Override time information from the untrusted caller. */
    rec_fprintf(dst->stream, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT,
		REC_TYPE_TIME_ARG(start));
    for (;;) {
	/* Don't allow PTR records. */
	rec_type = rec_get_raw(VSTREAM_IN, buf, var_line_limit, REC_FLAG_NONE);
	if (rec_type == REC_TYPE_EOF) {		/* request cancelled */
	    mail_stream_cleanup(dst);
	    if (remove(postdrop_path))
		msg_warn("uid=%ld: remove %s: %m", (long) uid, postdrop_path);
	    else if (msg_verbose)
		msg_info("remove %s", postdrop_path);
	    myfree(postdrop_path);
	    postdrop_path = 0;
	    exit(0);
	}
	if (rec_type == REC_TYPE_ERROR)
	    msg_fatal("uid=%ld: malformed input", (long) uid);
	if (strchr(*expected, rec_type) == 0)
	    msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type);
	if (rec_type == **expected)
	    expected++;
	/* Override time information from the untrusted caller. */
	if (rec_type == REC_TYPE_TIME)
	    continue;
	/* Check these at submission time instead of pickup time. */
	if (rec_type == REC_TYPE_FROM)
	    from_count++;
	if (rec_type == REC_TYPE_RCPT)
	    rcpt_count++;
	/* Limit the attribute types that users may specify. */
	if (rec_type == REC_TYPE_ATTR) {
	    if ((error_text = split_nameval(vstring_str(buf), &attr_name,
					    &attr_value)) != 0) {
		msg_warn("uid=%ld: ignoring malformed record: %s: %.200s",
			 (long) uid, error_text, vstring_str(buf));
		continue;
	    }
#define STREQ(x,y) (strcmp(x,y) == 0)

	    if ((STREQ(attr_name, MAIL_ATTR_ENCODING)
		 && (STREQ(attr_value, MAIL_ATTR_ENC_7BIT)
		     || STREQ(attr_value, MAIL_ATTR_ENC_8BIT)
		     || STREQ(attr_value, MAIL_ATTR_ENC_NONE)))
		|| STREQ(attr_name, MAIL_ATTR_DSN_ENVID)
		|| STREQ(attr_name, MAIL_ATTR_DSN_NOTIFY)
		|| rec_attr_map(attr_name)
		|| (STREQ(attr_name, MAIL_ATTR_RWR_CONTEXT)
		    && (STREQ(attr_value, MAIL_ATTR_RWR_LOCAL)
			|| STREQ(attr_value, MAIL_ATTR_RWR_REMOTE)))
		|| STREQ(attr_name, MAIL_ATTR_TRACE_FLAGS)) {	/* XXX */
		rec_fprintf(dst->stream, REC_TYPE_ATTR, "%s=%s",
			    attr_name, attr_value);
	    } else {
		msg_warn("uid=%ld: ignoring attribute record: %.200s=%.200s",
			 (long) uid, attr_name, attr_value);
	    }
	    continue;
	}
	if (REC_PUT_BUF(dst->stream, rec_type, buf) < 0) {
	    /* rec_get() errors must not clobber errno. */
	    saved_errno = errno;
	    while ((rec_type = rec_get_raw(VSTREAM_IN, buf, var_line_limit,
					   REC_FLAG_NONE)) != REC_TYPE_END
		   && rec_type != REC_TYPE_EOF)
		if (rec_type == REC_TYPE_ERROR)
		    msg_fatal("uid=%ld: malformed input", (long) uid);
	    validate_input = 0;
	    errno = saved_errno;
	    break;
	}
	if (rec_type == REC_TYPE_END)
	    break;
    }
    vstring_free(buf);

    /*
     * As of Postfix 2.7 the pickup daemon discards mail without recipients.
     * Such mail may enter the maildrop queue when "postsuper -r" is invoked
     * before the queue manager deletes an already delivered message. Looking
     * at file ownership is not a good way to make decisions on what mail to
     * discard. Instead, the pickup server now requires that new submissions
     * always have at least one recipient record.
     * 
     * The Postfix sendmail command already rejects mail without recipients.
     * However, in the future postdrop may receive mail via other programs,
     * so we add a redundant recipient check here for future proofing.
     * 
     * The test for the sender address is just for consistency of error
     * reporting (report at submission time instead of pickup time). Besides
     * the segment terminator records, there aren't any other mandatory
     * records in a Postfix submission queue file.
     */
    if (validate_input && (from_count == 0 || rcpt_count == 0)) {
	status = CLEANUP_STAT_BAD;
	mail_stream_cleanup(dst);
    }

    /*
     * Finish the file.
     */
    else if ((status = mail_stream_finish(dst, (VSTRING *) 0)) != 0) {
	msg_warn("uid=%ld: %m", (long) uid);
	postdrop_cleanup();
    }

    /*
     * Disable deletion on fatal error before reporting success, so the file
     * will not be deleted after we have taken responsibility for delivery.
     */
    if (postdrop_path) {
	junk = postdrop_path;
	postdrop_path = 0;
	myfree(junk);
    }

    /*
     * Send the completion status to the caller and terminate.
     */
    attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
	       SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
	       SEND_ATTR_STR(MAIL_ATTR_WHY, ""),
	       ATTR_TYPE_END);
    vstream_fflush(VSTREAM_OUT);
    exit(status);
}
Example #5
0
static void perf_get_info(FB_API_HANDLE* handle, P* perf)
{
/**************************************
 *
 *	P E R F _ g e t _ i n f o
 *
 **************************************
 *
 * Functional description
 *	Acquire timing and performance information.  Some info comes
 *	from the system and some from the database.
 *
 **************************************/
	SSHORT buffer_length, item_length;
	ISC_STATUS_ARRAY jrd_status;
#ifdef HAVE_GETTIMEOFDAY
	struct timeval tp;
#else
	struct timeb time_buffer;
#define LARGE_NUMBER 696600000	// to avoid overflow, get rid of decades)
#endif

	// If there isn't a database, zero everything out

	if (!*handle) {
		memset(perf, 0, sizeof(PERF));
	}

	// Get system time

	times(&perf->perf_times);

#ifdef HAVE_GETTIMEOFDAY
	GETTIMEOFDAY(&tp);
	perf->perf_elapsed = tp.tv_sec * 100 + tp.tv_usec / 10000;
#else
	ftime(&time_buffer);
	perf->perf_elapsed = (time_buffer.time - LARGE_NUMBER) * 100 + (time_buffer.millitm / 10);
#endif

	if (!*handle)
		return;

	SCHAR buffer[256];
	buffer_length = sizeof(buffer);
	item_length = sizeof(items);
	isc_database_info(jrd_status, handle, item_length, items, buffer_length, buffer);

	const char* p = buffer;

	while (true)
		switch (*p++)
		{
		case isc_info_reads:
			perf->perf_reads = get_parameter(&p);
			break;

		case isc_info_writes:
			perf->perf_writes = get_parameter(&p);
			break;

		case isc_info_marks:
			perf->perf_marks = get_parameter(&p);
			break;

		case isc_info_fetches:
			perf->perf_fetches = get_parameter(&p);
			break;

		case isc_info_num_buffers:
			perf->perf_buffers = get_parameter(&p);
			break;

		case isc_info_page_size:
			perf->perf_page_size = get_parameter(&p);
			break;

		case isc_info_current_memory:
			perf->perf_current_memory = get_parameter(&p);
			break;

		case isc_info_max_memory:
			perf->perf_max_memory = get_parameter(&p);
			break;

		case isc_info_end:
			return;

		case isc_info_error:
			switch (p[2])
			{
			 case isc_info_marks:
				perf->perf_marks = 0;
				break;
			case isc_info_current_memory:
				perf->perf_current_memory = 0;
				break;
			case isc_info_max_memory:
				perf->perf_max_memory = 0;
				break;
			}

			{
				const SLONG temp = isc_vax_integer(p, 2);
				fb_assert(temp <= MAX_SSHORT);
				p += temp + 2;
			}

			perf->perf_marks = 0;
			break;

		default:
			return;
		}
}
Example #6
0
File: zxidwsc.c Project: kiwiroy/zx
/* Called by:  covimp_test x3, zxid_call_epr, zxid_wsc_valid_resp */
int zxid_wsc_valid_re_env(zxid_conf* cf, zxid_ses* ses, const char* az_cred, struct zx_e_Envelope_s* env, const char* enve)
{
  int n_refs = 0;
  struct zxsig_ref refs[ZXID_N_WSF_SIGNED_HEADERS];
  struct timeval ourts;
  struct timeval srcts = {0,501000};
  zxid_entity* wsc_meta;
  struct zx_wsse_Security_s* sec;
  struct zx_e_Header_s* hdr;
  struct zx_str* issuer;
  struct zx_str* logpath;
  struct zx_str* relto;
  struct zx_str ss;
  zxid_cgi cgi;

  GETTIMEOFDAY(&ourts, 0);
  zxid_set_fault(cf, ses, 0);
  zxid_set_tas3_status(cf, ses, 0);

  if (cf->valid_opt & ZXID_VALID_OPT_SKIP_RESP_HDR) {
    ERR("WARNING! Important response security validations disabled by VALID_OPT=0x%x", cf->valid_opt);
    return 1;
  }
  
  if (!env) {
    ERR("No <e:Envelope> found. enve(%s)", STRNULLCHK(enve));
    zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No SOAP Envelope found.", "IDStarMsgNotUnderstood", 0, 0, 0));
    return 0;
  }
  hdr = env->Header;
  if (!hdr) {
    ERR("No <e:Header> found. %d", 0);
    zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No SOAP Header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
    return 0;
  }
  if (!ZX_SIMPLE_ELEM_CHK(hdr->MessageID)) {
    ERR("No <a:MessageID> found. %d", 0);
    zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No MessageID header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
    return 0;
  }
  relto = ZX_GET_CONTENT(hdr->RelatesTo);
  if (relto && relto->len) {
    if (ses->wsc_msgid) {
      if (strlen(ses->wsc_msgid) == relto->len
	  && !memcmp(ses->wsc_msgid, relto->s, relto->len)) {
	D("RelatesTo check OK %d",1);
      } else {
	/* N.B. [SOAPBinding2] p.27, ll.818-822 indicates RelatesTo checking as SHOULD. */
	if (cf->relto_fatal) {
	  ERR("<a:RelatesTo> (%.*s) does not match request msgid(%s).", relto->len, relto->s, ses->wsc_msgid);
	  zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "RelatesTo in response does not match request MessageID.", "InvalidRefToMsgID", 0, 0, 0));
	  return 0;
	} else {
	  INFO("<a:RelatesTo> (%.*s) does not match request msgid(%s), but configured to ignore this error (RELTO_FATAL=0).", relto->len, relto->s, ses->wsc_msgid);
	}
      }
    } else {
      INFO("Session does not have wsc_msgid. Skipping <a:RelatesTo> check. %d",0);
    }
  } else {
    if (cf->relto_fatal) {
      ERR("No <a:RelatesTo> found. %d", 0);
      zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No RelatesTo header found in reply.", "IDStarMsgNotUnderstood", 0, 0, 0));
      return 0;
    } else {
      INFO("No <a:RelatesTo> found, but configured to ignore this (RELTO_FATAL=0). %d", 0);
      D("No RelTo OK enve(%s)", STRNULLCHK(enve));
    }
  }

  if (!hdr->Sender || !hdr->Sender->providerID && !hdr->Sender->affiliationID) {
    ERR("No <b:Sender> found (or missing providerID or affiliationID). %p", hdr->Sender);
    zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No b:Sender header found (or missing providerID or affiliationID).", "IDStarMsgNotUnderstood", 0, 0, 0));
    return 0;
  }
  issuer = &hdr->Sender->providerID->g;
  
  /* Validate message signature (*** add Issuer trusted check, CA validation, etc.) */
  
  if (!(sec = hdr->Security)) {
    ERR("No <wsse:Security> found. %d", 0);
    zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No wsse:Security header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
    return 0;
  }

  wsc_meta = zxid_get_ent_ss(cf, issuer);
  if (!wsc_meta) {
    ses->sigres = ZXSIG_NO_SIG;
    if (cf->nosig_fatal) {
      INFO("Unable to find SAML metadata for Sender(%.*s), but configured to ignore this problem (NOSIG_FATAL=0).", issuer->len, issuer->s);
    } else {
      ERR("Unable to find SAML metadata for Sender(%.*s).", issuer->len, issuer->s);
      zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No unable to find SAML metadata for sender.", "ProviderIDNotValid", 0, 0, 0));
      return 0;
    }
  }
  
  if (!sec->Signature || !sec->Signature->SignedInfo || !sec->Signature->SignedInfo->Reference) {
    ses->sigres = ZXSIG_NO_SIG;
    if (cf->wsp_nosig_fatal) {
      ERR("No Security/Signature found. %p", sec->Signature);
      zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No wsse:Security/ds:Signature found.", TAS3_STATUS_NOSIG, 0, 0, 0));
      return 0;
    } else {
      INFO("No Security/Signature found, but configured to ignore this problem (WSP_NOSIG_FATAL=0). %p", sec->Signature);
    }
  } else {
    ZERO(refs, sizeof(refs));
    n_refs = zxid_hunt_sig_parts(cf, n_refs, refs, sec->Signature->SignedInfo->Reference, hdr, env->Body);
    /* *** Consider adding BDY and STR */
    ses->sigres = zxsig_validate(cf->ctx, wsc_meta?wsc_meta->sign_cert:0, sec->Signature, n_refs, refs);
    zxid_sigres_map(ses->sigres, &cgi.sigval, &cgi.sigmsg);
    if (cf->sig_fatal && ses->sigres) {
      ERR("Fail due to failed message signature sigres=%d", ses->sigres);
      zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "Message signature did not validate.", TAS3_STATUS_BADSIG, 0, 0, 0));
      return 0;
    }
  }
  if (!zxid_timestamp_chk(cf, ses, sec->Timestamp, &ourts, &srcts, TAS3_PEP_RS_IN, "e:Server"))
    return 0;

  if (hdr->UsageDirective) {
    if (hdr->UsageDirective->Obligation && ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment)) {
      ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment));
      D("Found TAS3 UsageDirective with obligation(%s)", ses->rcvd_usagedir);
    } else if (ZX_GET_CONTENT(hdr->UsageDirective)) {
      ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective));
      D("Found unknown UsageDirective(%s)", ses->rcvd_usagedir);
    } else {
      ERR("UsageDirective empty or not understood. %p", hdr->UsageDirective->Dict);
    }
  }

  zxid_ses_to_pool(cf, ses);
  zxid_snarf_eprs_from_ses(cf, ses);  /* Harvest attributes and bootstrap(s) */

  if (hdr->Status && hdr->Status->code
      && (hdr->Status->code->g.len != 2
	  || hdr->Status->code->g.s[0] != 'O'
	  || hdr->Status->code->g.s[1] != 'K')) {
    ERR("TAS3 or app level error code(%.*s)", hdr->Status->code->g.len, hdr->Status->code->g.s);
    return 0;
  }
  
  /* Call Rs-In PDP */

  if (!zxid_query_ctlpt_pdp(cf, ses, az_cred, env, TAS3_PEP_RS_IN, "e:Client", cf->pepmap_rsin)) {
    return 0;
  }
  
  /* *** execute (or store for future execution) the obligations. */
  
  ss.s = (char*)enve;
  ss.len = strlen(enve);
  logpath = zxlog_path(cf, issuer, ZX_GET_CONTENT(hdr->MessageID),
		       ZXLOG_RELY_DIR, ZXLOG_MSG_KIND, 1);
  if (zxlog_dup_check(cf, logpath, "validate response")) {
    if (cf->dup_msg_fatal) {
      zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate response dup err");
      zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "Duplicate Message.", "DuplicateMsg", 0, 0, 0));
      return 0;
    } else {
      INFO("Duplicate message detected, but configured to ignore this (DUP_MSG_FATAL=0). %d",0);
    }
  }
  zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate response");
  zxlog(cf, &ourts, &srcts, 0, issuer, 0, ses->a7n?&ses->a7n->ID->g:0, ZX_GET_CONTENT(ses->nameid), "N", "K", "VALID", logpath->s, 0);
  return 1;
}
Example #7
0
/*
 * get_systime - return system time in NTP timestamp format.
 */
void
get_systime(
	l_fp *now		/* system time */
	)
{
	double	dtemp;

#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
	struct timespec ts;	/* seconds and nanoseconds */

	/*
	 * Convert Unix timespec from seconds and nanoseconds to NTP
	 * seconds and fraction.
	 */
# ifdef HAVE_CLOCK_GETTIME
	clock_gettime(CLOCK_REALTIME, &ts);
# else
	getclock(TIMEOFDAY, &ts);
# endif
	now->l_i = (int32)ts.tv_sec + JAN_1970;
	dtemp = 0;
	if (sys_tick > FUZZ)
		dtemp = ntp_random() * 2. / FRAC * sys_tick * 1e9;
	else if (sys_tick > 0)
		dtemp = ntp_random() * 2. / FRAC;
	dtemp = (ts.tv_nsec + dtemp) * 1e-9 + sys_residual;
	if (dtemp >= 1.) {
		dtemp -= 1.;
		now->l_i++;
	} else if (dtemp < 0) {
		dtemp += 1.;
		now->l_i--;
	}
	now->l_uf = (u_int32)(dtemp * FRAC);

#else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
	struct timeval tv;	/* seconds and microseconds */

	/*
	 * Convert Unix timeval from seconds and microseconds to NTP
	 * seconds and fraction.
	 */
	GETTIMEOFDAY(&tv, NULL);
	now->l_i = tv.tv_sec + JAN_1970;
	dtemp = 0;
	if (sys_tick > FUZZ)
		dtemp = ntp_random() * 2. / FRAC * sys_tick * 1e6;
	else if (sys_tick > 0)
		dtemp = ntp_random() * 2. / FRAC;
	dtemp = (tv.tv_usec + dtemp) * 1e-6 + sys_residual;
	if (dtemp >= 1.) {
		dtemp -= 1.;
		now->l_i++;
	} else if (dtemp < 0) {
		dtemp += 1.;
		now->l_i--;
	}
	now->l_uf = (u_int32)(dtemp * FRAC);

#endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
}
Example #8
0
File: main.c Project: happyj/qcn
int
handle_pkt (
    int rpktl,
    struct pkt *rpkt,
    struct addrinfo *host
)
{
    struct timeval tv_dst;
    int sw_case, digits;
    char *hostname = NULL, *ref, *ts_str = NULL;
    double offset, precision, root_dispersion;
    char addr_buf[INET6_ADDRSTRLEN];
    char *p_SNTP_PRETEND_TIME;
    time_t pretend_time;

    if(rpktl > 0)
        sw_case = 1;
    else
        sw_case = rpktl;

    switch(sw_case) {
    case SERVER_UNUSEABLE:
        return -1;
        break;

    case PACKET_UNUSEABLE:
        break;

    case SERVER_AUTH_FAIL:
        break;

    case KOD_DEMOBILIZE:
        /* Received a DENY or RESTR KOD packet */
        hostname = addrinfo_to_str(host);
        ref = (char *)&rpkt->refid;
        add_entry(hostname, ref);

        if (ENABLED_OPT(NORMALVERBOSE))
            printf("sntp handle_pkt: Received KOD packet with code: %c%c%c%c from %s, demobilizing all connections\n",
                   ref[0], ref[1], ref[2], ref[3],
                   hostname);

        msyslog(LOG_WARNING, "Received a KOD packet with code %c%c%c%c from %s, demobilizing all connections",
                ref[0], ref[1], ref[2], ref[3], hostname);
        break;

    case KOD_RATE:
        /* Hmm... probably we should sleep a bit here */
        break;

    case 1:
        if (ENABLED_OPT(NORMALVERBOSE)) {
            getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf,
                        sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
            printf("sntp handle_pkt: Received %i bytes from %s\n", rpktl, addr_buf);
        }

        GETTIMEOFDAY(&tv_dst, (struct timezone *)NULL);

        p_SNTP_PRETEND_TIME = getenv("SNTP_PRETEND_TIME");
        if (p_SNTP_PRETEND_TIME) {
#if SIZEOF_TIME_T == 4
            sscanf(p_SNTP_PRETEND_TIME, "%ld", &pretend_time);
#elif SIZEOF_TIME_T == 8
            sscanf(p_SNTP_PRETEND_TIME, "%lld", &pretend_time);
#else
# include "GRONK: unexpected value for SIZEOF_TIME_T"
#endif
            tv_dst.tv_sec = pretend_time;
        }

        offset_calculation(rpkt, rpktl, &tv_dst, &offset,
                           &precision, &root_dispersion);

        for (digits = 0; (precision *= 10.) < 1.; ++digits)
            /* empty */ ;
        if (digits > 6)
            digits = 6;

        ts_str = tv_to_str(&tv_dst);
        printf("%s ", ts_str);
        if (offset > 0)
            printf("+");
        printf("%.*f", digits, offset);
        if (root_dispersion > 0.)
            printf(" +/- %f secs", root_dispersion);
        printf("\n");
        free(ts_str);

        if (p_SNTP_PRETEND_TIME)
            return 0;

        if (ENABLED_OPT(SETTOD) || ENABLED_OPT(ADJTIME))
            return set_time(offset);

        return 0;
    }

    return 1;
}
Example #9
0
static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
{
    const char *myname = "deliver_request_get";
    const char *path;
    struct stat st;
    static VSTRING *queue_name;
    static VSTRING *queue_id;
    static VSTRING *nexthop;
    static VSTRING *encoding;
    static VSTRING *address;
    static VSTRING *client_name;
    static VSTRING *client_addr;
    static VSTRING *client_port;
    static VSTRING *client_proto;
    static VSTRING *client_helo;
    static VSTRING *sasl_method;
    static VSTRING *sasl_username;
    static VSTRING *sasl_sender;
    static VSTRING *rewrite_context;
    static VSTRING *dsn_envid;
    static RCPT_BUF *rcpt_buf;
    int     rcpt_count;
    int     dsn_ret;

    /*
     * Initialize. For some reason I wanted to allow for multiple instances
     * of a deliver_request structure, thus the hoopla with string
     * initialization and copying.
     */
    if (queue_name == 0) {
	queue_name = vstring_alloc(10);
	queue_id = vstring_alloc(10);
	nexthop = vstring_alloc(10);
	encoding = vstring_alloc(10);
	address = vstring_alloc(10);
	client_name = vstring_alloc(10);
	client_addr = vstring_alloc(10);
	client_port = vstring_alloc(10);
	client_proto = vstring_alloc(10);
	client_helo = vstring_alloc(10);
	sasl_method = vstring_alloc(10);
	sasl_username = vstring_alloc(10);
	sasl_sender = vstring_alloc(10);
	rewrite_context = vstring_alloc(10);
	dsn_envid = vstring_alloc(10);
	rcpt_buf = rcpb_create();
    }

    /*
     * Extract the queue file name, data offset, and sender address. Abort
     * the conversation when they send bad information.
     */
    if (attr_scan(stream, ATTR_FLAG_STRICT,
		  ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request->flags,
		  ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
		  ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
		  ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset,
		  ATTR_TYPE_LONG, MAIL_ATTR_SIZE, &request->data_size,
		  ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
		  ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
		  ATTR_TYPE_STR, MAIL_ATTR_SENDER, address,
		  ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid,
		  ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret,
	       ATTR_TYPE_FUNC, msg_stats_scan, (void *) &request->msg_stats,
    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
		  ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_NAME, client_name,
		  ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_ADDR, client_addr,
		  ATTR_TYPE_STR, MAIL_ATTR_LOG_CLIENT_PORT, client_port,
		  ATTR_TYPE_STR, MAIL_ATTR_LOG_PROTO_NAME, client_proto,
		  ATTR_TYPE_STR, MAIL_ATTR_LOG_HELO_NAME, client_helo,
    /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
		  ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, sasl_method,
		  ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
		  ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
    /* XXX Ditto if we want to pass TLS certificate info. */
		  ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
		  ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
		  ATTR_TYPE_END) != 21) {
	msg_warn("%s: error receiving common attributes", myname);
	return (-1);
    }
    if (mail_open_ok(vstring_str(queue_name),
		     vstring_str(queue_id), &st, &path) == 0)
	return (-1);

    /* Don't override hand-off time after deliver_pass() delegation. */
    if (request->msg_stats.agent_handoff.tv_sec == 0)
	GETTIMEOFDAY(&request->msg_stats.agent_handoff);

    request->queue_name = mystrdup(vstring_str(queue_name));
    request->queue_id = mystrdup(vstring_str(queue_id));
    request->nexthop = mystrdup(vstring_str(nexthop));
    request->encoding = mystrdup(vstring_str(encoding));
    request->sender = mystrdup(vstring_str(address));
    request->client_name = mystrdup(vstring_str(client_name));
    request->client_addr = mystrdup(vstring_str(client_addr));
    request->client_port = mystrdup(vstring_str(client_port));
    request->client_proto = mystrdup(vstring_str(client_proto));
    request->client_helo = mystrdup(vstring_str(client_helo));
    request->sasl_method = mystrdup(vstring_str(sasl_method));
    request->sasl_username = mystrdup(vstring_str(sasl_username));
    request->sasl_sender = mystrdup(vstring_str(sasl_sender));
    request->rewrite_context = mystrdup(vstring_str(rewrite_context));
    request->dsn_envid = mystrdup(vstring_str(dsn_envid));
    request->dsn_ret = dsn_ret;

    /*
     * Extract the recipient offset and address list. Skip over any
     * attributes from the sender that we do not understand.
     */
    while (rcpt_count-- > 0) {
	if (attr_scan(stream, ATTR_FLAG_STRICT,
		      ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf,
		      ATTR_TYPE_END) != 1) {
	    msg_warn("%s: error receiving recipient attributes", myname);
	    return (-1);
	}
	recipient_list_add(&request->rcpt_list, rcpt_buf->offset,
			   vstring_str(rcpt_buf->dsn_orcpt),
			   rcpt_buf->dsn_notify,
			   vstring_str(rcpt_buf->orig_addr),
			   vstring_str(rcpt_buf->address));
    }
    if (request->rcpt_list.len <= 0) {
	msg_warn("%s: no recipients in delivery request for destination %s",
		 request->queue_id, request->nexthop);
	return (-1);
    }

    /*
     * Open the queue file and set a shared lock, in order to prevent
     * duplicate deliveries when the queue is flushed immediately after queue
     * manager restart.
     * 
     * The queue manager locks the file exclusively when it enters the active
     * queue, and releases the lock before starting deliveries from that
     * file. The queue manager does not lock the file again when reading more
     * recipients into memory. When the queue manager is restarted, the new
     * process moves files from the active queue to the incoming queue to cool
     * off for a while. Delivery agents should therefore never try to open a
     * file that is locked by a queue manager process.
     * 
     * Opening the queue file can fail for a variety of reasons, such as the
     * system running out of resources. Instead of throwing away mail, we're
     * raising a fatal error which forces the mail system to back off, and
     * retry later.
     */
#define DELIVER_LOCK_MODE (MYFLOCK_OP_SHARED | MYFLOCK_OP_NOWAIT)

    request->fp =
	mail_queue_open(request->queue_name, request->queue_id, O_RDWR, 0);
    if (request->fp == 0) {
	if (errno != ENOENT)
	    msg_fatal("open %s %s: %m", request->queue_name, request->queue_id);
	msg_warn("open %s %s: %m", request->queue_name, request->queue_id);
	return (-1);
    }
    if (msg_verbose)
	msg_info("%s: file %s", myname, VSTREAM_PATH(request->fp));
    if (myflock(vstream_fileno(request->fp), INTERNAL_LOCK, DELIVER_LOCK_MODE) < 0)
	msg_fatal("shared lock %s: %m", VSTREAM_PATH(request->fp));
    close_on_exec(vstream_fileno(request->fp), CLOSE_ON_EXEC);

    return (0);
}
Example #10
0
static int smtp_bulk_fail(SMTP_STATE *state, int throttle_queue)
{
    DELIVER_REQUEST *request = state->request;
    SMTP_SESSION *session = state->session;
    DSN_BUF *why = state->why;
    RECIPIENT *rcpt;
    int     status;
    int     aggregate_status;
    int     soft_error = (STR(why->status)[0] == '4');
    int     soft_bounce_error = (STR(why->status)[0] == '5' && var_soft_bounce);
    int     nrcpt;

    /*
     * Don't defer the recipients just yet when this error qualifies them for
     * delivery to a backup server. Just log something informative to show
     * why we're skipping this host.
     */
    if ((soft_error || soft_bounce_error)
            && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
        msg_info("%s: %s", request->queue_id, STR(why->reason));
        for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
            rcpt = request->rcpt_list.info + nrcpt;
            if (SMTP_RCPT_ISMARKED(rcpt))
                continue;
            SMTP_RCPT_KEEP(state, rcpt);
        }
    }

    /*
     * Defer or bounce all the remaining recipients, and delete them from the
     * delivery request. If a bounce fails, defer instead and do not qualify
     * the recipient for delivery to a backup server.
     */
    else {

        /*
         * If we are still in the connection set-up phase, update the set-up
         * completion time here, otherwise the time spent in set-up latency
         * will be attributed as message transfer latency.
         *
         * All remaining recipients have failed at this point, so we update the
         * delivery completion time stamp so that multiple recipient status
         * records show the same delay values.
         */
        if (request->msg_stats.conn_setup_done.tv_sec == 0) {
            GETTIMEOFDAY(&request->msg_stats.conn_setup_done);
            request->msg_stats.deliver_done =
                request->msg_stats.conn_setup_done;
        } else
            GETTIMEOFDAY(&request->msg_stats.deliver_done);

        (void) DSN_FROM_DSN_BUF(why);
        aggregate_status = 0;
        for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
            rcpt = request->rcpt_list.info + nrcpt;
            if (SMTP_RCPT_ISMARKED(rcpt))
                continue;
            status = (soft_error ? defer_append : bounce_append)
                     (DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
                      &request->msg_stats, rcpt,
                      session ? session->namaddrport : "none", &why->dsn);
            if (status == 0)
                deliver_completed(state->src, rcpt->offset);
            SMTP_RCPT_DROP(state, rcpt);
            aggregate_status |= status;
        }
        state->status |= aggregate_status;
        if ((state->misc_flags & SMTP_MISC_FLAG_COMPLETE_SESSION) == 0
                && throttle_queue && aggregate_status
                && request->hop_status == 0)
            request->hop_status = DSN_COPY(&why->dsn);
    }

    /*
     * Don't cache this session. We can't talk to this server.
     */
    if (throttle_queue && session)
        DONT_CACHE_THROTTLED_SESSION;

    return (-1);
}
Example #11
0
static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender)
{
    VSTRING *buffer = vstring_alloc(100);
    FORWARD_INFO *info;
    VSTREAM *cleanup;

#define FORWARD_OPEN_RETURN(res) do { \
	vstring_free(buffer); \
	return (res); \
    } while (0)

    /*
     * Contact the cleanup service and save the new mail queue id. Request
     * that the cleanup service bounces bad messages to the sender so that we
     * can avoid the trouble of bounce management.
     * 
     * In case you wonder what kind of bounces, examples are "too many hops",
     * "message too large", perhaps some others. The reason not to bounce
     * ourselves is that we don't really know who the recipients are.
     */
    cleanup = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service, BLOCKING);
    if (cleanup == 0) {
	msg_warn("connect to %s/%s: %m",
		 MAIL_CLASS_PUBLIC, var_cleanup_service);
	FORWARD_OPEN_RETURN(0);
    }
    close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
    if (attr_scan(cleanup, ATTR_FLAG_STRICT,
		  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
		  ATTR_TYPE_END) != 1) {
	vstream_fclose(cleanup);
	FORWARD_OPEN_RETURN(0);
    }
    info = (FORWARD_INFO *) mymalloc(sizeof(FORWARD_INFO));
    info->cleanup = cleanup;
    info->queue_id = mystrdup(STR(buffer));
    GETTIMEOFDAY(&info->posting_time);

#define FORWARD_CLEANUP_FLAGS \
	(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_INTERNAL \
	| smtputf8_autodetect(MAIL_SRC_MASK_FORWARD) \
	| ((request->smtputf8 & SMTPUTF8_FLAG_REQUESTED) ? \
	CLEANUP_FLAG_SMTPUTF8 : 0))

    attr_print(cleanup, ATTR_FLAG_NONE,
	       SEND_ATTR_INT(MAIL_ATTR_FLAGS, FORWARD_CLEANUP_FLAGS),
	       ATTR_TYPE_END);

    /*
     * Send initial message envelope information. For bounces, set the
     * designated sender: mailing list owner, posting user, whatever.
     */
    rec_fprintf(cleanup, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT,
		REC_TYPE_TIME_ARG(info->posting_time));
    rec_fputs(cleanup, REC_TYPE_FROM, sender);

    /*
     * Don't send the original envelope ID or full/headers return mask if it
     * was reset due to mailing list expansion.
     */
    if (request->dsn_ret)
	rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%d",
		    MAIL_ATTR_DSN_RET, request->dsn_ret);
    if (request->dsn_envid && *(request->dsn_envid))
	rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
		    MAIL_ATTR_DSN_ENVID, request->dsn_envid);

    /*
     * Zero-length attribute values are place holders for unavailable
     * attribute values. See qmgr_message.c. They are not meant to be
     * propagated to queue files.
     */
#define PASS_ATTR(fp, name, value) do { \
    if ((value) && *(value)) \
	rec_fprintf((fp), REC_TYPE_ATTR, "%s=%s", (name), (value)); \
    } while (0)

    /*
     * XXX encapsulate these as one object.
     */
    PASS_ATTR(cleanup, MAIL_ATTR_LOG_CLIENT_NAME, request->client_name);
    PASS_ATTR(cleanup, MAIL_ATTR_LOG_CLIENT_ADDR, request->client_addr);
    PASS_ATTR(cleanup, MAIL_ATTR_LOG_PROTO_NAME, request->client_proto);
    PASS_ATTR(cleanup, MAIL_ATTR_LOG_HELO_NAME, request->client_helo);
    PASS_ATTR(cleanup, MAIL_ATTR_SASL_METHOD, request->sasl_method);
    PASS_ATTR(cleanup, MAIL_ATTR_SASL_USERNAME, request->sasl_username);
    PASS_ATTR(cleanup, MAIL_ATTR_SASL_SENDER, request->sasl_sender);
    PASS_ATTR(cleanup, MAIL_ATTR_LOG_IDENT, request->log_ident);
    PASS_ATTR(cleanup, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context);

    FORWARD_OPEN_RETURN(info);
}
Example #12
0
void ClientThread(void *dummy)
{

  THREAD FILE *logfile;

  THREAD stats_t  timestat;

  THREAD rqst_timer_t timerarray[MAXNUMOFFILES];
  THREAD SOCKET mastersock = BADSOCKET_VALUE; /* connection to webmaster */


  THREAD page_stats_t *page_stats;    /* actually a dynamic array */

    int   loopcnt = 0;
    int   filecnt;
    int   loop;
    int   ran_number;
    int   page_index;
    int   page_number;
    int   file_count = 0;
    char  file_name[50];
    struct timeval  runningtime;
    time_t    junk;
    int   i;
    int   returnval;

    /*
     * INITIALIZE DATA
     */

    page_stats =
      (page_stats_t *)mymalloc((number_of_pages)*sizeof(page_stats_t));

    for (i=0; i < number_of_pages; i++) {
        page_stats_init(&(page_stats[i]));
    }

    if (debug)
      {
  /*
   *  OPEN A DEBUG FILE
   */
  fflush(stderr);
  sprintf(file_name, "%s.%d", DEBUG_FILE, (int)getpid());
  debugfile = fopen(file_name, "w+");
  if (debugfile == 0)
      errexit("Can't open debug file\n");
  D_PRINTF( "Running in debug mode, %d\n",amclient );
    }

    if (record_all_transactions)
    {
  /*
   *  OPEN A LOG FILE.
   */
  sprintf(file_name, "%s%d", LOG_FILE, (int)getpid());
  returnerr("Log file is %s\n", file_name);
  logfile = fopen(file_name, "w+");
    }

    /* Initialize random number generator */
    junk = getpid ();
    rand_r(&junk);
    D_PRINTF( "Random seed: %d\n", junk );

    for (i=0; i < MAXNUMOFFILES; i++)
    {
  rqtimer_init(&(timerarray[i]));
    }
    stats_init(&timestat);

    D_PRINTF( "Number of files %d\n", numfiles );

    timestat.total_num_of_files = numfiles;

    if (amclient)
    {
        /*
         * WE ARE A CLIENT PROCESS. (i.e. WE ARE NOT RUN BY A USER, BUT BY
         * THE MASTER WWWSTONE PROCESS. WE NEED TO CONNECT TO THE
         * MASTER WHO WILL SYNCHRONIZE ALL THE CLIENTS.
         */
  D_PRINTF( "Trying to connect with %s\n",connectstr );

  mastersock = connecttomaster(connectstr);

  D_PRINTF( "connecttomaster returns %d, %s\n",
          mastersock, neterrstr() );

  if(BADSOCKET(mastersock))
        {
            /*
             * ERROR CONNECTING TO THE MASTER. ABORT.
             */
            errexit("Error connecting to the master: %s\n", neterrstr());
        }
    } /* END IF CLIENT */

#ifdef WIN32
    /* Tell parent we're ready */
    InterlockedIncrement(&CounterSemaphore);

    /* Wait for main() thread to release us */
    WaitForSingleObject(hSemaphore, INFINITE);
    ReleaseSemaphore(hSemaphore, 1, 0);
#endif /* WIN32 */
    if (testtime != 0)
    {
       /*
        * IF RUNNING A TIMED TEST, WE WILL LOOP
  * UNTIL THE ALARM GOES OFF.
        * WE'LL ALSO NEED TO SET THE SIGNAL HANDLER
        */
#ifndef WIN32
      /*signal(SIGALRM, alarmhandler);*/
       /*
        * SEND SIGALRM IN testtime SECONDS
        */
      /*alarm(testtime);*/
#endif /* WIN32 */
    }

    /*
     * AND THEY'RE OFF...
     */

    if (testtime)
  numloops = INFINITY;
    GETTIMEOFDAY(&(timestat.starttime), &(timestat.starttimezone));

    /* LOOP UNTIL WE HIT numloops, OR WE RUN OUT OF TIME */
    for(loopcnt = 0;  (loopcnt < numloops) && !timeexpired;  loopcnt++)
    {
  /*
   * THIS IS WHERE LOAD TESTING IS DONE.
   * GET A RANDOM NUMBER, THEN INDEX INTO THE
   * PAGE, AND THEN REQUEST THAT SET OF FILES.
   */
  if (uil_filelist_f) /* HAVE FILELIST */
  {
      D_PRINTF( "Have filelist\n" );
      /* if (testtime != 0) /* RUNNING IN TIMED MODE */
            if (1)
      {
    D_PRINTF( "Running in timed mode\n" );
    /* random number between 0 and totalweight-1 */
                junk = getpid ();
    ran_number = (rand_r(&junk) % total_weight);
    D_PRINTF( "random %ld\n", ran_number );

    /* loop through pages, find correct one
     * while ran_number is positive, decrement it
     * by the load_num of the current page
     * example: ran_number is 5, pages have weights of 10 and 10
     *          first iteration page_index = 0, ran_number = -5
     *          iteration halted, page_index = 0
     */
    page_index = -1;
    while (ran_number >= 0)
      {
        page_index++;
        D_PRINTF( "Current page index %d: %ld - %d\n",
          page_index, ran_number,
          load_file_list[page_index].load_num
          );
        ran_number -= load_file_list[page_index].load_num;
      }

    if (page_index >= number_of_pages) { page_index--; }

    D_PRINTF( "Final page index %d\n", page_index );
    filecnt = makeload(load_file_list[page_index].num_of_files,
               page_index, timerarray, &timestat, mastersock, page_stats);
                testtime = 1;
      }
      else /* NOT RUNNING IN TIMED MODE */
      {
    for (page_number = 0;
         page_number < number_of_pages;
         page_number++)
    {
        filecnt = makeload(load_file_list[page_number].num_of_files,
      page_number, timerarray, &timestat, mastersock, page_stats);

    } /* END for page_number */
      } /* END if/else TIMED MODE */
  }
  else /* NO FILELIST */
  {
      D_PRINTF( "No filelist\n" );
     /*
      * LOOP THROUGH UNTIL numfiles TIMES OR UNTIL TIMER EXPIRES
      * AND ALARM SETS filecnt TO INFINITY.
      */

      /* does this still work?? */
      /* filecnt = makeload(numfiles, -1, timerarray); */
  } /* END if HAVE FILELIST */

  if (filecnt > 0)
      file_count += filecnt;

    } /* END while loopcnt */

    GETTIMEOFDAY(&(timestat.endtime), &(timestat.endtimezone));
    D_PRINTF( "Test run complete\n" );
    signal(SIGALRM, 0);

    if (testtime == 0)
    {
  numfiles = loopcnt;

  if (uil_filelist_f)
  {
      numfiles = file_count;
  }
    }

    /* This option ( "-R" ) looks broken (e.g. l > 50) -- JEF 2/15/96 */
    if (record_all_transactions)
    {
  /*
   * DUMP THE LOG FILE INFORMATION.
   */
  for (loop=0; loop < (loopcnt * file_count); loop++)
  {
      fprintf(logfile, " entertime \t%d.%d\n"
           " beforeconnect \t%d.%d\n"
           " afterconnect \t%d.%d\n"
           " beforeheader \t%d.%d\n"
           " afterheader \t%d.%d\n"
           " afterbody \t%d.%d\n"
           " exittime \t%d.%d\n"
           " total bytes \t%d\n"
           " body bytes\t%d\n",
    timerarray[loop].entertime.tv_sec,
    timerarray[loop].entertime.tv_usec,
    timerarray[loop].beforeconnect.tv_sec,
    timerarray[loop].beforeconnect.tv_usec,
    timerarray[loop].afterconnect.tv_sec,
    timerarray[loop].afterconnect.tv_usec,
    timerarray[loop].beforeheader.tv_sec,
    timerarray[loop].beforeheader.tv_usec,
    timerarray[loop].afterheader.tv_sec,
    timerarray[loop].afterheader.tv_usec,
    timerarray[loop].afterbody.tv_sec,
    timerarray[loop].afterbody.tv_usec,
    timerarray[loop].exittime.tv_sec,
    timerarray[loop].exittime.tv_usec,
    timerarray[loop].totalbytes,
    timerarray[loop].bodybytes);
  } /* end for loop */
    } /* end if recording all transactions */

    D_PRINTF( "total errors: %d\n",timestat.rs.totalerrs );
    /* gethostname(timestat.hostname,MAXHOSTNAMELEN); */
    /* D_PRINTF( "Test for host: %s\n",timestat.hostname ); */
    D_PRINTF( "Server is: %s running at port number: %d\n",
  webserver,portnum );

    /* sprintf(timestat.hostname,"%s:%d",timestat.hostname,getpid()); */
    if (amclient) /* CLIENT TO A WEBMASTER */
    {
   char *stats_as_text;

        /*
         * SEND THE TIMING DATA TO THE MASTER
         */
  stats_as_text = stats_to_text(&timestat);
  D_PRINTF( "stats_to_text returned %s\n", stats_as_text );

  returnval = senddata(mastersock, stats_as_text,
    SIZEOF_STATSTEXTBASE + number_of_pages*SIZEOF_DOUBLETEXT);
  D_PRINTF( "Wrote time stats to master %d\n", returnval );

  if (returnval < 1)
    {
      D_PRINTF( "Error while writing time stats: %s\n",
        neterrstr() );
      errexit("Error while writing time stats: %s\n",
        neterrstr());
    }

  if (uil_filelist_f)
    /* write pagestats */
    {
      char *page_stats_as_text;
      for (i = 0; i < number_of_pages; i++)
        {
    D_PRINTF( "On page_stats[%d]\n", i );
    page_stats_as_text = page_stats_to_text(&page_stats[i]);
    returnval = strlen(page_stats_as_text);
    D_PRINTF( "page_stats_to_text[%d] returned %d\n",
      i, returnval );
    returnval = senddata(mastersock, page_stats_as_text,
             SIZEOF_PAGESTATSTEXT);
    if (returnval < 1)
      {
        D_PRINTF( "Error while writing page_stats[%d]: %s\n",
          i, neterrstr() );
        errexit("Error while writing page_stats[%d]: %s\n",
          i, neterrstr());
      } /* end if */
    D_PRINTF( "Wrote %d bytes of page_stats[%d] to master\n",
      returnval, i );
        } /* end for */
    } /* end if filelist */

  D_PRINTF( "About to close socket\n" );
        if (NETCLOSE(mastersock))
      D_PRINTF( "Close socket error: %s\n", neterrstr() );
    }
    else /* NOT A CLIENT TO A WEBMASTER */
    {
  if (testtime)
    {
      printf("Test ran for: %d minutes\n",(testtime/60));
  }
  else
  {
      printf("Test ran for: %d iterations.\n",numloops);
  }
  compdifftime(&(timestat.endtime), &(timestat.starttime),
    &(runningtime));
  printf("Total time of test (sec) %d.%d\n", runningtime.tv_sec,
    runningtime.tv_usec);
  printf("Files retrieved per iteration: %d\n",numfiles);  /* 'per iteration' */
  printf("----------------------------------\n");
  printf("Totals:\n\n");
  rqstat_print(&(timestat.rs));

  if (timestat.rs.totalconnects == 0)
      goto end;
  printf("Thruput = %5.2lf Kbytes/sec\n",
         thruputpersec(timestat.rs.totalbytes, &runningtime) / 1000);

  if (uil_filelist_f && numloops && verbose)
  {
      for (loop = 0; loop < number_of_pages; loop++)
      {
    if (timestat.page_numbers[loop] != 0)
    {
        printf ("===============================================================================\n");
        printf ("Page # %d\n\n", loop);
        printf ("Total number of times page was hit %d\n",
          page_stats[loop].totalpages);
        rqstat_print(&(page_stats[loop].rs));
        printf ("Page size %d \n", page_stats[loop].page_size);
        printf ("===============================================================================\n\n");
    } /* END if timestat */
      } /* END for loop */
  } /* END if filelist */
    } /* END if client */

end:
    if(record_all_transactions)
      fclose(logfile);
    if(debug)
    {
  D_PRINTF( "Client exiting.\n" );
  fclose(debugfile);
    }

#ifdef WIN32
    /* tell parent we're done */
    InterlockedIncrement(&CounterSemaphore);
#endif /* WIN32 */

} /* END ClientThread() */
Example #13
0
/*
 * step_systime - step the system clock.
 */
int
step_systime(
	double now
	)
{
	struct timeval timetv, adjtv, oldtimetv;
	int isneg = 0;
	double dtemp;
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
	struct timespec ts;
#endif

	dtemp = sys_residual + now;
	if (dtemp < 0) {
		isneg = 1;
		dtemp = - dtemp;
		adjtv.tv_sec = (int32)dtemp;
		adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
					  1e6 + .5);
	} else {
		adjtv.tv_sec = (int32)dtemp;
		adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
					  1e6 + .5);
	}
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
#ifdef HAVE_CLOCK_GETTIME
	(void) clock_gettime(CLOCK_REALTIME, &ts);
#else
	(void) getclock(TIMEOFDAY, &ts);
#endif
	timetv.tv_sec = ts.tv_sec;
	timetv.tv_usec = ts.tv_nsec / 1000;
#else /*  not HAVE_GETCLOCK */
	(void) GETTIMEOFDAY(&timetv, (struct timezone *)0);
#endif /* not HAVE_GETCLOCK */

	oldtimetv = timetv;

#ifdef DEBUG
	if (debug)
		printf("step_systime: step %.6f residual %.6f\n", now, sys_residual);
#endif
	if (isneg) {
		timetv.tv_sec -= adjtv.tv_sec;
		timetv.tv_usec -= adjtv.tv_usec;
		if (timetv.tv_usec < 0) {
			timetv.tv_sec--;
			timetv.tv_usec += 1000000;
		}
	} else {
		timetv.tv_sec += adjtv.tv_sec;
		timetv.tv_usec += adjtv.tv_usec;
		if (timetv.tv_usec >= 1000000) {
			timetv.tv_sec++;
			timetv.tv_usec -= 1000000;
		}
	}
	if (ntp_set_tod(&timetv, (struct timezone *)0) != 0) {
		msyslog(LOG_ERR, "Can't set time of day: %m");
		return (0);
	}
	sys_residual = 0;

#ifdef NEED_HPUX_ADJTIME
	/*
	 * CHECKME: is this correct when called by ntpdate?????
	 */
	_clear_adjtime();
#endif

	/*
	 * FreeBSD, for example, has:
	 * struct utmp {
	 *	   char    ut_line[UT_LINESIZE];
	 *	   char    ut_name[UT_NAMESIZE];
	 *	   char    ut_host[UT_HOSTSIZE];
	 *	   long    ut_time;
	 * };
	 * and appends line="|", name="date", host="", time for the OLD
	 * and appends line="{", name="date", host="", time for the NEW
	 * to _PATH_WTMP .
	 *
	 * Some OSes have utmp, some have utmpx.
	 */

	/*
	 * Write old and new time entries in utmp and wtmp if step adjustment
	 * is greater than one second.
	 *
	 * This might become even Uglier...
	 */
	if (oldtimetv.tv_sec != timetv.tv_sec)
	{
#ifdef HAVE_UTMP_H
		struct utmp ut;
#endif
#ifdef HAVE_UTMPX_H
		struct utmpx utx;
#endif

#ifdef HAVE_UTMP_H
		memset((char *)&ut, 0, sizeof(ut));
#endif
#ifdef HAVE_UTMPX_H
		memset((char *)&utx, 0, sizeof(utx));
#endif

		/* UTMP */

#ifdef UPDATE_UTMP
# ifdef HAVE_PUTUTLINE
		ut.ut_type = OLD_TIME;
		(void)strcpy(ut.ut_line, OTIME_MSG);
		ut.ut_time = oldtimetv.tv_sec;
		pututline(&ut);
		setutent();
		ut.ut_type = NEW_TIME;
		(void)strcpy(ut.ut_line, NTIME_MSG);
		ut.ut_time = timetv.tv_sec;
		pututline(&ut);
		endutent();
# else /* not HAVE_PUTUTLINE */
# endif /* not HAVE_PUTUTLINE */
#endif /* UPDATE_UTMP */

		/* UTMPX */

#ifdef UPDATE_UTMPX
# ifdef HAVE_PUTUTXLINE
		utx.ut_type = OLD_TIME;
		(void)strcpy(utx.ut_line, OTIME_MSG);
		utx.ut_tv = oldtimetv;
		pututxline(&utx);
		setutxent();
		utx.ut_type = NEW_TIME;
		(void)strcpy(utx.ut_line, NTIME_MSG);
		utx.ut_tv = timetv;
		pututxline(&utx);
		endutxent();
# else /* not HAVE_PUTUTXLINE */
# endif /* not HAVE_PUTUTXLINE */
#endif /* UPDATE_UTMPX */

		/* WTMP */

#ifdef UPDATE_WTMP
# ifdef HAVE_PUTUTLINE
		utmpname(WTMP_FILE);
		ut.ut_type = OLD_TIME;
		(void)strcpy(ut.ut_line, OTIME_MSG);
		ut.ut_time = oldtimetv.tv_sec;
		pututline(&ut);
		ut.ut_type = NEW_TIME;
		(void)strcpy(ut.ut_line, NTIME_MSG);
		ut.ut_time = timetv.tv_sec;
		pututline(&ut);
		endutent();
# else /* not HAVE_PUTUTLINE */
# endif /* not HAVE_PUTUTLINE */
#endif /* UPDATE_WTMP */

		/* WTMPX */

#ifdef UPDATE_WTMPX
# ifdef HAVE_PUTUTXLINE
		utx.ut_type = OLD_TIME;
		utx.ut_tv = oldtimetv;
		(void)strcpy(utx.ut_line, OTIME_MSG);
#  ifdef HAVE_UPDWTMPX
		updwtmpx(WTMPX_FILE, &utx);
#  else /* not HAVE_UPDWTMPX */
#  endif /* not HAVE_UPDWTMPX */
# else /* not HAVE_PUTUTXLINE */
# endif /* not HAVE_PUTUTXLINE */
# ifdef HAVE_PUTUTXLINE
		utx.ut_type = NEW_TIME;
		utx.ut_tv = timetv;
		(void)strcpy(utx.ut_line, NTIME_MSG);
#  ifdef HAVE_UPDWTMPX
		updwtmpx(WTMPX_FILE, &utx);
#  else /* not HAVE_UPDWTMPX */
#  endif /* not HAVE_UPDWTMPX */
# else /* not HAVE_PUTUTXLINE */
# endif /* not HAVE_PUTUTXLINE */
#endif /* UPDATE_WTMPX */

	}
	return (1);
}
Example #14
0
int zxid_sp_sso_finalize_jwt(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* jwt)
{
  char* err = "S"; /* See: RES in zxid-log.pd, section "ZXID Log Format" */
  struct zx_str ss;
  struct timeval ourts;
  struct timeval srcts = {0,501000};
  struct zx_str* logpath;
  char* p;
  char* claims;

  ses->jwt = (char*)jwt;
  //ses->rs = ;
  ses->ssores = 1;
  GETTIMEOFDAY(&ourts, 0);

  D_INDENT("ssof: ");

  claims = zxid_decode_jwt(cf, cgi, ses, jwt);
  if (!claims) {
    ERR("JWT decode error jwt(%s)", STRNULLCHKD(jwt));
    goto erro;
  }
  
  //ses->nid = zx_json_extract_dup(cf->ctx, claims, "\"sub\"");
  ses->nid = zx_json_extract_dup(cf->ctx, claims, "\"user_id\"");
  if (!ses->nid) {
    ERR("JWT decode: no user_id found in jwt(%s)", STRNULLCHKD(jwt));
    goto erro;
  }
  ses->nidfmt = 1;  /* Assume federation */

  ses->tgtjwt = ses->jwt;
  ses->tgt = ses->nid;
  ses->tgtfmt = 1;  /* Assume federation */

  p = zx_json_extract_dup(cf->ctx, claims, "\"iss\"");
  ses->issuer = zx_ref_str(cf->ctx, p);
  if (!p) {
    ERR("JWT decode: no iss found in jwt(%s)", STRNULLCHKD(jwt));
    goto erro;
  }

  D("SSOJWT received. NID(%s) FMT(%d)", ses->nid, ses->nidfmt);
  
  // *** should some signature validation happen here, using issuer (idp) meta?
  cgi->sigval = "N";
  cgi->sigmsg = "Assertion was not signed.";
  ses->sigres = ZXSIG_NO_SIG;
  
  if (cf->log_rely_a7n) {
    DD("Logging rely... %d", 0);
    ss.s = (char*)jwt; ss.len = strlen(jwt);
    logpath = zxlog_path(cf, ses->issuer, &ss, ZXLOG_RELY_DIR, ZXLOG_JWT_KIND, 1);
    if (logpath) {
      ses->sso_a7n_path = ses->tgt_a7n_path = zx_str_to_c(cf->ctx, logpath);
      if (zxlog_dup_check(cf, logpath, "SSO JWT")) {
	if (cf->dup_a7n_fatal) {
	  err = "C";
	  zxlog_blob(cf, cf->log_rely_a7n, logpath, &ss, "sp_sso_finalize_jwt dup err");
	  goto erro;
	}
      }
      zxlog_blob(cf, cf->log_rely_a7n, logpath, &ss, "sp_sso_finalize_jwt");
    }
  }
  DD("Creating session... %d", 0);
  ses->ssores = 0;
  zxid_put_ses(cf, ses);
  //*** zxid_snarf_eprs_from_ses(cf, ses);  /* Harvest attributes and bootstrap(s) */
  cgi->msg = "SSO completed and session created.";
  cgi->op = '-';  /* Make sure management screen does not try to redispatch. */
  zxid_put_user(cf, 0, 0, 0, zx_ref_str(cf->ctx, ses->nid), 0);
  DD("Logging... %d", 0);
  ss.s = ses->nid; ss.len = strlen(ss.s);
  zxlog(cf, &ourts, &srcts, 0, ses->issuer, 0, 0, &ss,
	cgi->sigval, "K", "NEWSESJWT", ses->sid, "sesix(%s)", STRNULLCHKD(ses->sesix));
  zxlog(cf, &ourts, &srcts, 0, ses->issuer, 0, 0, &ss,
	cgi->sigval, "K", ses->nidfmt?"FEDSSOJWT":"TMPSSOJWT", STRNULLCHKD(ses->sesix), 0);

#if 0
  if (cf->idp_ena) {  /* (PXY) Middle IdP of Proxy IdP flow */
    if (cgi->rs && cgi->rs[0]) {
      D("ProxyIdP got RelayState(%s) ar(%s)", cgi->rs, STRNULLCHK(cgi->ssoreq));
      cgi->saml_resp = 0;  /* Clear Response to prevent re-interpretation. We want Request. */
      cgi->ssoreq = cgi->rs;
      zxid_decode_ssoreq(cf, cgi);
      cgi->op = 'V';
      D_DEDENT("ssof: ");
      return ZXID_IDP_REQ; /* Cause zxid_simple_idp_an_ok_do_rest() to be called from zxid_sp_dispatch(); */
    } else {
      INFO("Middle IdP of Proxy IdP flow did not receive RelayState from upstream IdP %p", cgi->rs);
    }
  }
#endif
  D_DEDENT("ssof: ");
  return ZXID_SSO_OK;

erro:
  ERR("SSOJWT fail (%s)", err);
  cgi->msg = "SSO failed. This could be due to signature, timeout, etc., technical failures, or by policy.";
  zxlog(cf, &ourts, &srcts, 0, ses->issuer, 0, 0, 0,
	cgi->sigval, err, ses->nidfmt?"FEDSSOJWT":"TMPSSOJWT", STRNULLCHKD(ses->sesix), "Error.");
  D_DEDENT("ssof: ");
  return 0;
}
Example #15
0
static void
waitForSomething(void)
{
#if defined(__vms) && ( __VMS_VER < 70000000 )
  static struct timeval zerotime =
    {
      0
    };
  unsigned int timer_efn;
#define timer_id 'glut' /* random :-) number */
  unsigned int wait_mask;
#else
  static struct timeval zerotime =
    {
      0, 0
    };
#if !defined(_WIN32)
  fd_set fds;
#endif
#endif
  struct timeval now, timeout, waittime;
#if !defined(_WIN32)
  int rc;
#endif

  /* Flush X protocol since XPending does not do this
     implicitly. */
  XFlush(__glutDisplay);
  if (XPending(__glutDisplay))
  {
    /* It is possible (but quite rare) that XFlush may have
       needed to wait for a writable X connection file
       descriptor, and in the process, may have had to read off
       X protocol from the file descriptor. If XPending is true,
       this case occured and we should avoid waiting in select
       since X protocol buffered within Xlib is due to be
       processed and potentially no more X protocol is on the
       file descriptor, so we would risk waiting improperly in
       select. */
    goto immediatelyHandleXinput;
  }
#if defined(__vms) && ( __VMS_VER < 70000000 )
  timeout = __glutTimerList->timeout;
  GETTIMEOFDAY(&now);
  wait_mask = 1 << (__glutConnectionFD & 31);
  if (IS_AFTER(now, timeout))
  {
    /* We need an event flag for the timer. */
    /* XXX The `right' way to do this is to use LIB$GET_EF, but
       since it needs to be in the same cluster as the EFN for
       the display, we will have hack it. */
    timer_efn = __glutConnectionFD - 1;
    if ((timer_efn / 32) != (__glutConnectionFD / 32))
    {
      timer_efn = __glutConnectionFD + 1;
    }
    rc = SYS$CLREF(timer_efn);
    rc = SYS$SETIMR(timer_efn, &timeout, NULL, timer_id, 0);
    wait_mask |= 1 << (timer_efn & 31);
  }
  else
  {
    timer_efn = 0;
  }
  rc = SYS$WFLOR(__glutConnectionFD, wait_mask);
  if (timer_efn != 0 && SYS$CLREF(timer_efn) == SS$_WASCLR)
  {
    rc = SYS$CANTIM(timer_id, PSL$C_USER);
  }
  /* XXX There does not seem to be checking of "rc" in the code
     above.  Can any of the SYS$ routines above fail? */
#else /* not vms6.2 or lower */
#if !defined(_WIN32)
  FD_ZERO(&fds);
  FD_SET(__glutConnectionFD, &fds);
#endif
  timeout = __glutTimerList->timeout;
  GETTIMEOFDAY(&now);
  if (IS_AFTER(now, timeout))
  {
    TIMEDELTA(waittime, timeout, now);
  }
  else
  {
    waittime = zerotime;
  }
#if !defined(_WIN32)
  rc = select(__glutConnectionFD + 1, &fds,
              NULL, NULL, &waittime);
  if (rc < 0 && errno != EINTR)
    __glutFatalError("select error.");
#else
#if 0 /* XXX Nate, what is this junk? */
  /* Set up a timer to fire in at least a millisecond, then wait for
  the message.  This should act like a select. */
  SetTimer(NULL, 2, waittime.tv_usec, NULL);
  WaitMessage();
  KillTimer(NULL, 2);
#endif

  /* Actually, a sleep seems to do the trick -- do we even need this? */
  Sleep(0);
#endif
#endif /* not vms6.2 or lower */
  /* Without considering the cause of select unblocking, check
     for pending X events and handle any timeouts (by calling
     processEventsAndTimeouts).  We always look for X events
     even if select returned with 0 (indicating a timeout);
     otherwise we risk starving X event processing by continous
     timeouts. */
  if (XPending(__glutDisplay))
  {
immediatelyHandleXinput:
    processEventsAndTimeouts();
  }
  else
  {
    if (__glutTimerList)
      handleTimeouts();
  }
}
Example #16
0
int     deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
{
    const char *myname = "deliver_maildir";
    char   *newdir;
    char   *tmpdir;
    char   *curdir;
    char   *tmpfile;
    char   *newfile;
    DSN_BUF *why = state.msg_attr.why;
    VSTRING *buf;
    VSTREAM *dst;
    int     mail_copy_status;
    int     deliver_status;
    int     copy_flags;
    struct stat st;
    struct timeval starttime;

    GETTIMEOFDAY(&starttime);

    /*
     * Make verbose logging easier to understand.
     */
    state.level++;
    if (msg_verbose)
	MSG_LOG_STATE(myname, state);

    /*
     * Don't deliver trace-only requests.
     */
    if (DEL_REQ_TRACE_ONLY(state.request->flags)) {
	dsb_simple(why, "2.0.0", "delivers to maildir");
	return (sent(BOUNCE_FLAGS(state.request),
		     SENT_ATTR(state.msg_attr)));
    }

    /*
     * Initialize. Assume the operation will fail. Set the delivered
     * attribute to reflect the final recipient.
     */
    if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
	msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
    state.msg_attr.delivered = state.msg_attr.rcpt.address;
    mail_copy_status = MAIL_COPY_STAT_WRITE;
    buf = vstring_alloc(100);

    copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH
	| MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT;

    newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
    tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
    curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);

    /*
     * Create and write the file as the recipient, so that file quota work.
     * Create any missing directories on the fly. The file name is chosen
     * according to ftp://koobera.math.uic.edu/www/proto/maildir.html:
     * 
     * "A unique name has three pieces, separated by dots. On the left is the
     * result of time(). On the right is the result of gethostname(). In the
     * middle is something that doesn't repeat within one second on a single
     * host. I fork a new process for each delivery, so I just use the
     * process ID. If you're delivering several messages from one process,
     * use starttime.pid_count.host, where starttime is the time that your
     * process started, and count is the number of messages you've
     * delivered."
     * 
     * Well, that stopped working on fast machines, and on operating systems
     * that randomize process ID values. When creating a file in tmp/ we use
     * the process ID because it still is an exclusive resource. When moving
     * the file to new/ we use the device number and inode number. I do not
     * care if this breaks on a remote AFS file system, because people should
     * know better.
     * 
     * On January 26, 2003, http://cr.yp.to/proto/maildir.html said:
     * 
     * A unique name has three pieces, separated by dots. On the left is the
     * result of time() or the second counter from gettimeofday(). On the
     * right is the result of gethostname(). (To deal with invalid host
     * names, replace / with \057 and : with \072.) In the middle is a
     * delivery identifier, discussed below.
     * 
     * [...]
     * 
     * Modern delivery identifiers are created by concatenating enough of the
     * following strings to guarantee uniqueness:
     * 
     * [...]
     * 
     * In, where n is (in hexadecimal) the UNIX inode number of this file.
     * Unfortunately, inode numbers aren't always available through NFS.
     * 
     * Vn, where n is (in hexadecimal) the UNIX device number of this file.
     * Unfortunately, device numbers aren't always available through NFS.
     * (Device numbers are also not helpful with the standard UNIX
     * filesystem: a maildir has to be within a single UNIX device for link()
     * and rename() to work.)
     * 
     * Mn, where n is (in decimal) the microsecond counter from the same
     * gettimeofday() used for the left part of the unique name.
     * 
     * Pn, where n is (in decimal) the process ID.
     * 
     * [...]
     */
    set_eugid(usr_attr.uid, usr_attr.gid);
    vstring_sprintf(buf, "%lu.P%d.%s",
		 (unsigned long) starttime.tv_sec, var_pid, get_hostname());
    tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
    newfile = 0;
    if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0
	&& (errno != ENOENT
	    || make_dirs(tmpdir, 0700) < 0
	    || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) {
	dsb_simple(why, mbox_dsn(errno, "4.2.0"),
		   "create maildir file %s: %m", tmpfile);
    } else if (fstat(vstream_fileno(dst), &st) < 0) {

	/*
	 * Coverity 200604: file descriptor leak in code that never executes.
	 * Code replaced by msg_fatal(), as it is not worthwhile to continue
	 * after an impossible error condition.
	 */
	msg_fatal("fstat %s: %m", tmpfile);
    } else {
	vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s",
			(unsigned long) starttime.tv_sec,
			(unsigned long) st.st_dev,
			(unsigned long) st.st_ino,
			(unsigned long) starttime.tv_usec,
			get_hostname());
	newfile = concatenate(newdir, STR(buf), (char *) 0);
	if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr),
					  dst, copy_flags, "\n",
					  why)) == 0) {
	    if (sane_link(tmpfile, newfile) < 0
		&& (errno != ENOENT
		    || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0
		    || sane_link(tmpfile, newfile) < 0)) {
		dsb_simple(why, mbox_dsn(errno, "4.2.0"),
			   "create maildir file %s: %m", newfile);
		mail_copy_status = MAIL_COPY_STAT_WRITE;
	    }
	}
	if (unlink(tmpfile) < 0)
	    msg_warn("remove %s: %m", tmpfile);
    }
    set_eugid(var_owner_uid, var_owner_gid);

    /*
     * The maildir location is controlled by the mail administrator. If
     * delivery fails, try again later. We would just bounce when the maildir
     * location possibly under user control.
     */
    if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
	deliver_status = DEL_STAT_DEFER;
    } else if (mail_copy_status != 0) {
	if (errno == EACCES) {
	    msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
		     (long) usr_attr.uid, (long) usr_attr.gid,
		     STR(why->reason));
	    msg_warn("perhaps you need to create the maildirs in advance");
	}
	vstring_sprintf_prepend(why->reason, "maildir delivery failed: ");
	deliver_status =
	    (STR(why->status)[0] == '4' ?
	     defer_append : bounce_append)
	    (BOUNCE_FLAGS(state.request),
	     BOUNCE_ATTR(state.msg_attr));
    } else {
	dsb_simple(why, "2.0.0", "delivered to maildir");
	deliver_status = sent(BOUNCE_FLAGS(state.request),
			      SENT_ATTR(state.msg_attr));
    }
    vstring_free(buf);
    myfree(newdir);
    myfree(tmpdir);
    myfree(curdir);
    myfree(tmpfile);
    if (newfile)
	myfree(newfile);
    return (deliver_status);
}
Example #17
0
/*
 * Runs test and count average time (if the nloops is grater than 1)
 *
 * returns: -1 = error, 0 = success
 */
int
virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data)
{
    int i, ret = 0;
    double *ts = NULL;

    testCounter++;

    if (testOOM < 2) {
        if (virTestGetVerbose())
            fprintf(stderr, "%2d) %-65s ... ", testCounter, title);
    }

    if (nloops > 1 && (ts = calloc(nloops,
                                   sizeof(double)))==NULL)
        return -1;

    for (i=0; i < nloops; i++) {
        struct timeval before, after;

        if (ts)
            GETTIMEOFDAY(&before);

        virResetLastError();
        ret = body(data);
        virErrorPtr err = virGetLastError();
        if (err) {
            if (virTestGetVerbose() || virTestGetDebug())
                virDispatchError(NULL);
        }

        if (ret != 0) {
            break;
        }

        if (ts) {
            GETTIMEOFDAY(&after);
            ts[i] = DIFF_MSEC(&after, &before);
        }
    }
    if (testOOM < 2) {
        if (virTestGetVerbose()) {
            if (ret == 0 && ts)
                fprintf(stderr, "OK     [%.5f ms]\n",
                        virtTestCountAverage(ts, nloops));
            else if (ret == 0)
                fprintf(stderr, "OK\n");
            else
                fprintf(stderr, "FAILED\n");
        } else {
            if (testCounter != 1 &&
                !((testCounter-1) % 40)) {
                fprintf(stderr, " %-3d\n", (testCounter-1));
                fprintf(stderr, "      ");
            }
            if (ret == 0)
                fprintf(stderr, ".");
            else
                fprintf(stderr, "!");
        }
    }

    free(ts);
    return ret;
}
Example #18
0
/* CENTRY */
int GLUTAPIENTRY 
glutGet(GLenum param)
{
  Window win, root;
  int x, y, value;
  unsigned int width, height, border, depth;

  switch (param) {
  case GLUT_INIT_WINDOW_X:
    return __glutInitX;
  case GLUT_INIT_WINDOW_Y:
    return __glutInitY;
  case GLUT_INIT_WINDOW_WIDTH:
    return __glutInitWidth;
  case GLUT_INIT_WINDOW_HEIGHT:
    return __glutInitHeight;
  case GLUT_INIT_DISPLAY_MODE:
    return __glutDisplayMode;
  case GLUT_WINDOW_X:
    XTranslateCoordinates(__glutDisplay, __glutCurrentWindow->win,
      __glutRoot, 0, 0, &x, &y, &win);
    return x;
  case GLUT_WINDOW_Y:
    XTranslateCoordinates(__glutDisplay, __glutCurrentWindow->win,
      __glutRoot, 0, 0, &x, &y, &win);
    return y;
  case GLUT_WINDOW_WIDTH:
    if (!__glutCurrentWindow->reshape) {
      XGetGeometry(__glutDisplay, __glutCurrentWindow->win,
        &root, &x, &y,
        &width, &height, &border, &depth);
      return width;
    }
    return __glutCurrentWindow->width;
  case GLUT_WINDOW_HEIGHT:
    if (!__glutCurrentWindow->reshape) {
      XGetGeometry(__glutDisplay, __glutCurrentWindow->win,
        &root, &x, &y,
        &width, &height, &border, &depth);
      return height;
    }
    return __glutCurrentWindow->height;

#define GET_CONFIG(attrib) { \
  if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { \
    glXGetConfig(__glutDisplay, __glutCurrentWindow->vis, \
      attrib, &value); \
  } else { \
    glXGetConfig(__glutDisplay, __glutCurrentWindow->overlay->vis, \
      attrib, &value); \
  } \
}

  case GLUT_WINDOW_BUFFER_SIZE:
    GET_CONFIG(GLX_BUFFER_SIZE);
    return value;
  case GLUT_WINDOW_STENCIL_SIZE:
    GET_CONFIG(GLX_STENCIL_SIZE);
    return value;
  case GLUT_WINDOW_DEPTH_SIZE:
    GET_CONFIG(GLX_DEPTH_SIZE);
    return value;
  case GLUT_WINDOW_RED_SIZE:
    GET_CONFIG(GLX_RED_SIZE);
    return value;
  case GLUT_WINDOW_GREEN_SIZE:
    GET_CONFIG(GLX_GREEN_SIZE);
    return value;
  case GLUT_WINDOW_BLUE_SIZE:
    GET_CONFIG(GLX_BLUE_SIZE);
    return value;
  case GLUT_WINDOW_ALPHA_SIZE:
    GET_CONFIG(GLX_ALPHA_SIZE);
    return value;
  case GLUT_WINDOW_ACCUM_RED_SIZE:
    GET_CONFIG(GLX_ACCUM_RED_SIZE);
    return value;
  case GLUT_WINDOW_ACCUM_GREEN_SIZE:
    GET_CONFIG(GLX_ACCUM_GREEN_SIZE);
    return value;
  case GLUT_WINDOW_ACCUM_BLUE_SIZE:
    GET_CONFIG(GLX_ACCUM_BLUE_SIZE);
    return value;
  case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
    GET_CONFIG(GLX_ACCUM_ALPHA_SIZE);
    return value;
  case GLUT_WINDOW_DOUBLEBUFFER:
    GET_CONFIG(GLX_DOUBLEBUFFER);
    return value;
  case GLUT_WINDOW_RGBA:
    GET_CONFIG(GLX_RGBA);
    return value;
  case GLUT_WINDOW_COLORMAP_SIZE:
    GET_CONFIG(GLX_RGBA);
    if (value) {
      return 0;
    } else {
#if defined(_WIN32)
      /* KLUDGE: we always assume 256 colors in CI mode on
         Win32 */
      return 256;
#else
      if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { 
        return __glutCurrentWindow->vis->visual->map_entries;
      } else {
        return __glutCurrentWindow->overlay->vis->visual->map_entries;
      }
#endif /* _WIN32 */
    }
  case GLUT_WINDOW_PARENT:
    return __glutCurrentWindow->parent ?
      __glutCurrentWindow->parent->num + 1 : 0;
  case GLUT_WINDOW_NUM_CHILDREN:
    {
      int num = 0;
      GLUTwindow *children = __glutCurrentWindow->children;

      while (children) {
        num++;
        children = children->siblings;
      }
      return num;
    }
  case GLUT_WINDOW_NUM_SAMPLES:
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
    if (__glutIsSupportedByGLX("GLX_SGIS_multisample")) {
      GET_CONFIG(GLX_SAMPLES_SGIS);
      return value;
    } else {
      return 0;
    }
#else
    /* Independent of GLX server support, multisampling not
       supported by GLX client-side. */
    return 0;
#endif
  case GLUT_WINDOW_STEREO:
    GET_CONFIG(GLX_STEREO);
    return value;
  case GLUT_WINDOW_CURSOR:
    return __glutCurrentWindow->cursor;
  case GLUT_SCREEN_WIDTH:
    return DisplayWidth(__glutDisplay, __glutScreen);
  case GLUT_SCREEN_HEIGHT:
    return DisplayHeight(__glutDisplay, __glutScreen);
  case GLUT_SCREEN_WIDTH_MM:
    return DisplayWidthMM(__glutDisplay, __glutScreen);
  case GLUT_SCREEN_HEIGHT_MM:
    return DisplayHeightMM(__glutDisplay, __glutScreen);
  case GLUT_MENU_NUM_ITEMS:
    return __glutCurrentMenu->num;
  case GLUT_DISPLAY_MODE_POSSIBLE:
    {
      XVisualInfo *vi;
      Bool dummy, visAlloced;
      void *fbc;

#if defined(_WIN32)      
      /* Our fake glXChooseVisual (which is called by
         __glutDetermineVisual) needs an HDC to work with, so grab one
         from the "root" window. */
      XHDC = GetDC(GetDesktopWindow());
#endif
      vi = __glutDetermineWindowVisual(&dummy, &visAlloced, &fbc);
#if defined(_WIN32)      
      ReleaseDC(GetDesktopWindow(), XHDC);
#endif
      if (vi) {
        if (visAlloced)
          XFree(vi);
        return 1;
      }
      return 0;
    }
  case GLUT_ELAPSED_TIME:
    {
#ifdef OLD_VMS
       struct timeval6 elapsed, beginning, now;
#else
       struct timeval elapsed, beginning, now;
#endif

       __glutInitTime(&beginning);
      GETTIMEOFDAY(&now);
      TIMEDELTA(elapsed, now, beginning);
      /* Return elapsed milliseconds. */
#if defined(__vms) && ( __VMS_VER < 70000000 )
      return (int) (elapsed.val / TICKS_PER_MILLISECOND);
#else
      return (int) ((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
#endif
    }
  case GLUT_WINDOW_FORMAT_ID:
#if defined(_WIN32)
    return GetPixelFormat(__glutCurrentWindow->hdc);
#else
    if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
      return (int) __glutCurrentWindow->vis->visualid;
    } else {
      return (int) __glutCurrentWindow->overlay->vis->visualid;
    }
#endif
  default:
    __glutWarning("invalid glutGet parameter: %d", param);
    return -1;
  }
}
Example #19
0
File: main.c Project: happyj/qcn
/* The heart of (S)NTP, exchange NTP packets and compute values to correct the local clock */
int
on_wire (
    struct addrinfo *host,
    struct addrinfo *bcast
)
{
    char addr_buf[INET6_ADDRSTRLEN];
    register int try;
    SOCKET sock;
    struct key *pkt_key = NULL;
    int key_id = 0;
    struct timeval tv_xmt;
    struct pkt x_pkt;
    int error, rpktl, handle_pkt_res;


    if (ENABLED_OPT(AUTHENTICATION)) {
        key_id = (int) OPT_ARG(AUTHENTICATION);
        get_key(key_id, &pkt_key);
    }
    for (try=0; try<5; try++) {
                    memset(&r_pkt, 0, sizeof rbuf);

                    error = GETTIMEOFDAY(&tv_xmt, (struct timezone *)NULL);
                    tv_xmt.tv_sec += JAN_1970;

#ifdef DEBUG
                    printf("sntp on_wire: Current time sec: %i msec: %i\n", (unsigned int) tv_xmt.tv_sec,
                           (unsigned int) tv_xmt.tv_usec);
#endif

                    if (bcast) {
                        create_socket(&sock, (sockaddr_u *)bcast->ai_addr);
                        rpktl = recv_bcst_pkt(sock, &r_pkt, sizeof rbuf, (sockaddr_u *)bcast->ai_addr);
                        closesocket(sock);
                    } else {
                        int pkt_len = generate_pkt(&x_pkt, &tv_xmt, key_id, pkt_key);

                        create_socket(&sock, (sockaddr_u *)host->ai_addr);
                        sendpkt(sock, (sockaddr_u *)host->ai_addr, &x_pkt, pkt_len);
                        rpktl = recvpkt(sock, &r_pkt, sizeof rbuf, &x_pkt);
                        closesocket(sock);
                    }

                    handle_pkt_res = handle_pkt(rpktl, &r_pkt, host);
                    if (handle_pkt_res < 1)
                        return handle_pkt_res;
                }

    getnameinfo(host->ai_addr, host->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
    msyslog(LOG_DEBUG, "Received no useable packet from %s!", addr_buf);

    return -1;
}

/* Compute the 8 bits for li_vn_mode */
void
set_li_vn_mode (
    struct pkt *spkt,
    char leap,
    char version,
    char mode
)
{
    if (leap > 3) {
        msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3 using max. 3");
        leap = 3;
    }

    if (mode > 7) {
        msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3");
        mode = 3;
    }

    spkt->li_vn_mode  = leap << 6;
    spkt->li_vn_mode |= version << 3;
    spkt->li_vn_mode |= mode;
}

/* set_time corrects the local clock by offset with either settimeofday() or by default
 * with adjtime()/adjusttimeofday().
 */
int
set_time(
    double offset
)
{
    struct timeval tp;

    if (ENABLED_OPT(SETTOD)) {
        GETTIMEOFDAY(&tp, NULL);

        tp.tv_sec += (long)offset;
        tp.tv_usec += 1e6 * (offset - (long)offset);
        NORMALIZE_TIMEVAL(tp);

        if (SETTIMEOFDAY(&tp, NULL) < 0) {
            msyslog(LOG_ERR, "Time not set: settimeofday(): %m");
            return -1;
        }
        return 0;
    }

    tp.tv_sec = (long)offset;
    tp.tv_usec = 1e6 * (offset - (long)offset);
    NORMALIZE_TIMEVAL(tp);

    if (ADJTIMEOFDAY(&tp, NULL) < 0) {
        msyslog(LOG_ERR, "Time not set: adjtime(): %m");
        return -1;
    }
    return 0;
}
Example #20
0
int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
                int (*hsfunc) (SSL *),
                int (*rfunc) (SSL *, void *, int),
                int (*wfunc) (SSL *, const void *, int),
                void *buf, int num)
{
    const char *myname = "tls_bio";
    int     status;
    int     err;
    int     enable_deadline;
    struct timeval time_left;		/* amount of time left */
    struct timeval time_deadline;	/* time of deadline */
    struct timeval time_now;		/* time after SSL_mumble() call */

    /*
     * Compensation for interface mis-match: With VSTREAMs, timeout <= 0
     * means wait forever; with the read/write_wait() calls below, we need to
     * specify timeout < 0 instead.
     *
     * Safety: no time limit means no deadline.
     */
    if (timeout <= 0) {
        timeout = -1;
        enable_deadline = 0;
    }

    /*
     * Deadline management is simpler than with VSTREAMs, because we don't
     * need to decrement a per-stream time limit. We just work within the
     * budget that is available for this tls_bio() call.
     */
    else {
        enable_deadline =
            vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE);
        if (enable_deadline) {
            GETTIMEOFDAY(&time_deadline);
            time_deadline.tv_sec += timeout;
        }
    }

    /*
     * If necessary, retry the SSL handshake or read/write operation after
     * handling any pending network I/O.
     */
    for (;;) {
        if (hsfunc)
            status = hsfunc(TLScontext->con);
        else if (rfunc)
            status = rfunc(TLScontext->con, buf, num);
        else if (wfunc)
            status = wfunc(TLScontext->con, buf, num);
        else
            msg_panic("%s: nothing to do here", myname);
        err = SSL_get_error(TLScontext->con, status);

#if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)

        /*
         * There is a bug up to and including OpenSSL-0.9.5a: if an error
         * occurs while checking the peers certificate due to some
         * certificate error (e.g. as happend with a RSA-padding error), the
         * error is put onto the error stack. If verification is not
         * enforced, this error should be ignored, but the error-queue is not
         * cleared, so we can find this error here. The bug has been fixed on
         * May 28, 2000.
         *
         * This bug so far has only manifested as 4800:error:0407006A:rsa
         * routines:RSA_padding_check_PKCS1_type_1:block type is not
         * 01:rsa_pk1.c:100: 4800:error:04067072:rsa
         * routines:RSA_EAY_PUBLIC_DECRYPT:padding check
         * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding
         * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so
         * that we specifically test for this error. We print the errors to
         * the logfile and automatically clear the error queue. Then we retry
         * to get another error code. We cannot do better, since we can only
         * retrieve the last entry of the error-queue without actually
         * cleaning it on the way.
         *
         * This workaround is secure, as verify_result is set to "failed"
         * anyway.
         */
        if (err == SSL_ERROR_SSL) {
            if (ERR_peek_error() == 0x0407006AL) {
                tls_print_errors();
                msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
                err = SSL_get_error(TLScontext->con, status);
            }
        }
#endif

        /*
         * Correspondence between SSL_ERROR_* error codes and tls_bio_(read,
         * write, accept, connect, shutdown) return values (for brevity:
         * retval).
         *
         * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write)
         * this is the number of plaintext bytes sent or received. With
         * SSL_(accept, connect, shutdown) this means that the operation was
         * completed successfully.
         *
         * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force
         * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded.
         *
         * All other SSL_ERROR_* cases correspond with retval <= 0. With
         * SSL_(read, write, accept, connect) retval == 0 means that the
         * remote party either closed the network connection or that it
         * requested TLS shutdown; with SSL_shutdown() retval == 0 means that
         * our own shutdown request is in progress. With all operations
         * retval < 0 means that there was an error. In the latter case,
         * SSL_ERROR_SYSCALL means that error details are returned via the
         * errno value.
         *
         * Find out if we must retry the operation and/or if there is pending
         * network I/O.
         *
         * XXX If we're the first to invoke SSL_shutdown(), then the operation
         * isn't really complete when the call returns. We could hide that
         * anomaly here and repeat the call.
         */
        switch (err) {
        case SSL_ERROR_WANT_WRITE:
        case SSL_ERROR_WANT_READ:
            if (enable_deadline) {
                GETTIMEOFDAY(&time_now);
                timersub(&time_deadline, &time_now, &time_left);
                timeout = time_left.tv_sec + (time_left.tv_usec > 0);
                if (timeout <= 0) {
                    errno = ETIMEDOUT;
                    return (-1);
                }
            }
            if (err == SSL_ERROR_WANT_WRITE) {
                if (write_wait(fd, timeout) < 0)
                    return (-1);		/* timeout error */
            } else {
                if (read_wait(fd, timeout) < 0)
                    return (-1);		/* timeout error */
            }
            break;

        /*
         * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP)
         * etc. Historically, Postfix silently treated these as ordinary
         * I/O errors so we don't really know how common they are. For
         * now, we just log a warning.
         */
        default:
            msg_warn("%s: unexpected SSL_ERROR code %d", myname, err);
        /* FALLTHROUGH */

        /*
         * With tls_timed_read() and tls_timed_write() the caller is the
         * VSTREAM library module which is unaware of TLS, so we log the
         * TLS error stack here. In a better world, each VSTREAM I/O
         * object would provide an error reporting method in addition to
         * the timed_read and timed_write methods, so that we would not
         * need to have ad-hoc code like this.
         */
        case SSL_ERROR_SSL:
            if (rfunc || wfunc)
                tls_print_errors();
        /* FALLTHROUGH */
        case SSL_ERROR_ZERO_RETURN:
        case SSL_ERROR_NONE:
            errno = 0;				/* avoid bogus warnings */
        /* FALLTHROUGH */
        case SSL_ERROR_SYSCALL:
            return (status);
        }
    }
}