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; } }
/* * 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); }
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); } }