コード例 #1
0
ファイル: client.c プロジェクト: i0rek/pgbouncer-dev
static bool decide_startup_pool(PgSocket *client, PktHdr *pkt)
{
	const char *username = NULL, *dbname = NULL;
	const char *key, *val;
	bool ok;

	while (1) {
		ok = mbuf_get_string(&pkt->data, &key);
		if (!ok || *key == 0)
			break;
		ok = mbuf_get_string(&pkt->data, &val);
		if (!ok)
			break;

		if (strcmp(key, "database") == 0) {
			slog_debug(client, "got var: %s=%s", key, val);
			dbname = val;
		} else if (strcmp(key, "user") == 0) {
			slog_debug(client, "got var: %s=%s", key, val);
			username = val;
		} else if (varcache_set(&client->vars, key, val)) {
			slog_debug(client, "got var: %s=%s", key, val);
		} else if (strlist_contains(cf_ignore_startup_params, key)) {
			slog_debug(client, "ignoring startup parameter: %s=%s", key, val);
		} else {
			slog_warning(client, "unsupported startup parameter: %s=%s", key, val);
			disconnect_client(client, true, "Unsupported startup parameter: %s", key);
			return false;
		}
	}
	if (!username || !username[0]) {
		disconnect_client(client, true, "No username supplied");
		return false;
	}

	/* if missing dbname, default to username */
	if (!dbname || !dbname[0])
		dbname = username;

	/* check if limit allows, dont limit admin db
	   nb: new incoming conn will be attached to PgSocket, thus
	   get_active_client_count() counts it */
	if (get_active_client_count() > cf_max_client_conn) {
		if (strcmp(dbname, "pgbouncer") != 0) {
			disconnect_client(client, true, "no more connections allowed (max_client_conn)");
			return false;
		}
	}

	/* find pool and log about it */
	if (set_pool(client, dbname, username)) {
		if (cf_log_connections)
			slog_info(client, "login attempt: db=%s user=%s", dbname, username);
		return true;
	} else {
		if (cf_log_connections)
			slog_info(client, "login failed: db=%s user=%s", dbname, username);
		return false;
	}
}
コード例 #2
0
ファイル: pam.c プロジェクト: davidfetter/pgbouncer
/*
 * Initiate the authentication request using PAM. The request result will be
 * available during next calls to pam_poll(). The function might block if the
 * request queue is full until there are free slots available.
 * The function is called only from the main thread.
 */
void pam_auth_begin(PgSocket *client, const char *passwd)
{
	int next_free_slot = (pam_first_free_slot + 1) % PAM_REQUEST_QUEUE_SIZE;
	struct pam_auth_request *request;

	slog_debug(
		client,
		"pam_auth_begin(): pam_first_taken_slot=%d, pam_first_free_slot=%d",
		pam_first_taken_slot, pam_first_free_slot);

	client->wait_for_auth = 1;

	/* Check that we have free slots in the queue, and if no
	 * then block until one is available.
	 */
	if (next_free_slot == pam_first_taken_slot)
		slog_debug(client, "PAM queue is full, waiting");

	while (next_free_slot == pam_first_taken_slot) {
		if (pam_poll() == 0) {
			/* Sleep a bit between consequent queue checks to avoid consuming too much CPU */
			usleep(PAM_QUEUE_WAIT_SLEEP_MCS);
		}
	}

	pthread_mutex_lock(&pam_queue_tail_mutex);

	request = &pam_auth_queue[pam_first_free_slot];

	request->client = client;
	request->connect_time = client->connect_time;
	request->status = PAM_STATUS_IN_PROGRESS;
	memcpy(&request->remote_addr, &client->remote_addr, sizeof(client->remote_addr));
	safe_strcpy(request->username, client->auth_user->name, MAX_USERNAME);
	safe_strcpy(request->password, passwd, MAX_PASSWORD);

	pam_first_free_slot = next_free_slot;

	pthread_mutex_unlock(&pam_queue_tail_mutex);
	pthread_cond_signal(&pam_data_available);
}
コード例 #3
0
ファイル: client.c プロジェクト: davidfetter/pgbouncer
static void set_appname(PgSocket *client, const char *app_name)
{
	char buf[400], abuf[300];
	const char *details;

	if (cf_application_name_add_host) {
		/* give app a name */
		if (!app_name)
			app_name = "app";

		/* add details */
		details = pga_details(&client->remote_addr, abuf, sizeof(abuf));
		snprintf(buf, sizeof(buf), "%s - %s", app_name, details);
		app_name = buf;
	}
	if (app_name) {
		slog_debug(client, "using application_name: %s", app_name);
		varcache_set(&client->vars, "application_name", app_name);
	}
}