コード例 #1
0
ファイル: exit.c プロジェクト: OXKernel/ox
static
int dispatch_signal(int signal, int is_root, struct process *proc)
{
    if(signal < SIGHUP || signal > SIGTTOU || !proc) {
        return EINVAL;
    }
    if(is_root || 
       current_process->p_euid == proc->p_euid || 
       is_super_user()) {
        proc->p_signal |= (1 << signal);
        return 0;
    }
    return EPERM;
}// dispatch_signal
コード例 #2
0
static void
check_rules(Port *port, int status)
{

	int r;

	/* index of the backend process */
	int		index;

	/* limits */
	bool	per_user_overriden = false,
			per_database_overriden = false,
			per_ip_overriden = false;

	/* counters */
	int		per_user = 0,
			per_database = 0,
			per_ip = 0;

	/*
	 * Any other plugins which use ClientAuthentication_hook.
	 */
	if (prev_client_auth_hook)
		prev_client_auth_hook(port, status);

	/* No point in checkin the connection rules after failed authentication. */
	if (status != STATUS_OK)
		return;

	/*
	 * Lock ProcArray (serialize the processes, so that we can use the
	 * counters stored in the rule_r struct).
	 *
	 * TODO Use a private array of counters (same number of rules), so
	 *      that we don't need an exclusive lock.
	 */
	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);

	/* reset the rule counters */
	reset_rules();

	/* attach the shared segment */
	attach_procarray();

	/*
	 * Perform the actual check - loop through the backends (procArray), and
	 * compare each valid backend against each rule. If it matches, increment
	 * the counter (and if value exceeds the limit, make a failure).
	 *
	 * TODO First check the rules for the current backend, and then only check
	 *      those rules that match (because those are the only rules that may
	 *      be violated by this new connection).
	 */
	for (index = 0; index < procArray->numProcs; index++)
	{

#if (PG_VERSION_NUM <= 90200)
		volatile PGPROC *proc = procArray->procs[index];
#else
		volatile PGPROC *proc = &ProcGlobal->allProcs[procArray->procs[index]];
#endif

		/* do not count prepared xacts */
		if (proc->pid == 0)
			continue;

		/*
		 * If this is the current backend, then update the local info. This
		 * effectively resets info for crashed backends.
		 *
		 * FIXME Maybe this should happen explicitly before the loop.
		 */
		if (proc->backendId == MyBackendId)
		{
			/* lookup remote host name (unless already done) */
			if (! port->remote_hostname)
			{
				char	remote_hostname[NI_MAXHOST];

				if (! pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
									remote_hostname, sizeof(remote_hostname),
									NULL, 0, 0))
					port->remote_hostname = pstrdup(remote_hostname);
			}

			/* store the backend info into a cache */
			backend_update_info(&backends[proc->backendId], proc,
								port->database_name, port->user_name,
								port->raddr, port->remote_hostname);
		}

		/* if the backend info is valid, */
		if (backend_info_is_valid(backends[proc->backendId], proc))
		{

			/* see if the database/user/IP matches */
			per_database += (strcmp(backends[proc->backendId].database, port->database_name) == 0) ? 1 : 0;
			per_user     += (strcmp(backends[proc->backendId].role, port->user_name) == 0) ? 1 : 0;
			per_ip       += (memcmp(&backends[proc->backendId].socket, &port->raddr, sizeof(SockAddr)) == 0) ? 1 : 0;

			/* check all the rules for this backend */
			for (r = 0; r < rules->n_rules; r++)
			{

				/*
				 * The rule has to be matched by both the current and new session, otherwise
				 * it can't be violated by the new one.
				 *
				 * FIXME This repeatedly checks all the rules for the current backend, which is not
				 *       needed. We only need to do this check (for the new session) once, and then
				 *       walk only the rules that match it. Althouth that may not detect the
				 *       default rules (per db, ...).
				 */
				if (rule_matches(rules->rules[r], port->database_name, port->user_name, port->raddr, port->remote_host))
				{

					/* check if this rule overrides per-db, per-user or per-ip limits */
					per_database_overriden |= rule_is_per_database(&rules->rules[r]);
					per_user_overriden     |= rule_is_per_user(&rules->rules[r]);
					per_ip_overriden       |= rule_is_per_ip(&rules->rules[r]);

					/* Check the rule for a existing backend (we assume it's valid thanks to backend_info_is_valid()). */
					if (rule_matches(rules->rules[r], backends[proc->backendId].database,
									 backends[proc->backendId].role, backends[proc->backendId].socket,
									 backends[proc->backendId].hostname))
					{

						/* increment the match count for this rule */
						++rules->rules[r].count;

						/*
						 * We're looping over all backends (including the current backend), so the
						 * rule is only violated if the limit is actually exceeded.
						 */
						if (rules->rules[r].count > rules->rules[r].limit)
						{

							if (! is_super_user(port->user_name))
								elog(ERROR, "connection limit reached (rule %d, line %d, limit %d)",
											r, rules->rules[r].line, rules->rules[r].limit);
							else
								elog(WARNING, "connection limit reached (rule %d, line %d, limit %d), but the user is a superuser",
											r, rules->rules[r].line, rules->rules[r].limit);

						}
					}
				}

			}
		}
	}

	/*
	 * Check the per-db/user/IP limits, unless there was an exact rule overriding
	 * the defaults for that object, or unless the default was disabled (set to 0).
	 */

	/* check per-database limit */
	if ((! per_database_overriden) && (default_per_database != 0) && (per_database > default_per_database))
	{
		if (! is_super_user(port->user_name))
			elog(ERROR, "per-database connection limit reached (limit %d)",
				 default_per_database);
		else
			elog(WARNING, "per-database  limit reached (limit %d), but the user is a superuser",
				 default_per_database);
	}

	/* check per-user limit */
	if ((! per_user_overriden) && (default_per_role != 0) && (per_user > default_per_role))
	{
		if (! is_super_user(port->user_name))
			elog(ERROR, "per-user connection limit reached (limit %d)",
				 default_per_role);
		else
			elog(WARNING, "per-user connection limit reached (limit %d), but the user is a superuser",
				 default_per_role);
	}

	/* check per-IP limit */
	if ((! per_ip_overriden) && (default_per_ip != 0) && (per_ip > default_per_ip))
	{
		if (! is_super_user(port->user_name))
			elog(ERROR, "per-IP connection limit reached (limit %d)",
				 default_per_ip);
		else
			elog(WARNING, "per-IP connection limit reached (limit %d), but the user is a superuser",
				 default_per_ip);
	}

	LWLockRelease(ProcArrayLock);

}