Skip to content

Commit

Permalink
[agroal#70] TLS support: pgagroal - PostgreSQL
Browse files Browse the repository at this point in the history
Pooling support by saving the SSL session and reusing it
  • Loading branch information
jesperpedersen committed Dec 14, 2021
1 parent aedb8c5 commit 2cc39ea
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 30 deletions.
10 changes: 7 additions & 3 deletions src/include/pgagroal.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ extern "C" {

#define MAIN_UDS ".s.pgagroal"

#define MAX_BUFFER_SIZE 65535
#define DEFAULT_BUFFER_SIZE 65535
#define SECURITY_BUFFER_SIZE 512
#define MAX_BUFFER_SIZE 65535
#define DEFAULT_BUFFER_SIZE 65535
#define SECURITY_BUFFER_SIZE 512
#define SSL_SESSION_BUFFER_SIZE 2048

#define MAX_USERNAME_LENGTH 128
#define MAX_DATABASE_LENGTH 256
Expand Down Expand Up @@ -176,6 +177,9 @@ struct connection
ssize_t security_lengths[NUMBER_OF_SECURITY_MESSAGES]; /**< The lengths of the security messages */
char security_messages[NUMBER_OF_SECURITY_MESSAGES][SECURITY_BUFFER_SIZE]; /**< The security messages */

long ssl_session_length; /**< The length of the SSL session */
unsigned char ssl_session[SSL_SESSION_BUFFER_SIZE]; /**< The SSL session (ASN.1) */

int backend_pid; /**< The backend process id */
int backend_secret; /**< The backend secret */

Expand Down
18 changes: 18 additions & 0 deletions src/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@ pgagroal_user_known(char* user);
int
pgagroal_tls_valid(void);

/**
* Load a SSL connection from a slot
* @param slot The slot
* @param ssl The resulting SSL connection (can be NULL)
* @return 0 upon success, otherwise 1
*/
int
pgagroal_load_tls_connection(int slot, SSL** ssl);

/**
* Save a TLS connection to a slot
* @param ssl The SSL connection
* @param slot The slot
* @return 0 upon success, otherwise 1
*/
int
pgagroal_save_tls_connection(SSL* ssl, int slot);

#ifdef __cplusplus
}
#endif
Expand Down
13 changes: 11 additions & 2 deletions src/libpgagroal/management.c
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,7 @@ write_ssl(SSL* ssl, void* buf, size_t size)
}
else
{
long derr;
int err = SSL_get_error(ssl, numbytes);

switch (err)
Expand All @@ -1397,12 +1398,20 @@ write_ssl(SSL* ssl, void* buf, size_t size)
keep_write = true;
break;
case SSL_ERROR_SYSCALL:
pgagroal_log_error("SSL_ERROR_SYSCALL: %s (%d)", strerror(errno), SSL_get_fd(ssl));
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SYSCALL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
errno = 0;
keep_write = false;
break;
case SSL_ERROR_SSL:
pgagroal_log_error("SSL_ERROR_SSL: %s (%d)", strerror(errno), SSL_get_fd(ssl));
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SSL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
errno = 0;
keep_write = false;
break;
Expand Down
28 changes: 20 additions & 8 deletions src/libpgagroal/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,7 @@ ssl_read_message(SSL* ssl, int timeout, struct message** msg)
}
else
{
long derr;
int err;

err = SSL_get_error(ssl, numbytes);
Expand Down Expand Up @@ -1295,11 +1296,19 @@ ssl_read_message(SSL* ssl, int timeout, struct message** msg)
keep_read = true;
break;
case SSL_ERROR_SYSCALL:
pgagroal_log_error("SSL_ERROR_SYSCALL: %s (%d)", strerror(errno), SSL_get_fd(ssl));
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SYSCALL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
errno = 0;
break;
case SSL_ERROR_SSL:
pgagroal_log_error("SSL_ERROR_SSL: %s (%d)", strerror(errno), SSL_get_fd(ssl));
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SSL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
break;
}
ERR_clear_error();
Expand Down Expand Up @@ -1354,6 +1363,7 @@ ssl_write_message(SSL* ssl, struct message* msg)
}
else
{
long derr;
int err = SSL_get_error(ssl, numbytes);

switch (err)
Expand All @@ -1375,17 +1385,19 @@ ssl_write_message(SSL* ssl, struct message* msg)
keep_write = true;
break;
case SSL_ERROR_SYSCALL:
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SYSCALL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(err, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(err));
pgagroal_log_error("%s", ERR_reason_error_string(err));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
errno = 0;
break;
case SSL_ERROR_SSL:
derr = ERR_get_error();
pgagroal_log_error("SSL_ERROR_SSL: FD %d", SSL_get_fd(ssl));
pgagroal_log_error("%s", ERR_error_string(err, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(err));
pgagroal_log_error("%s", ERR_reason_error_string(err));
pgagroal_log_error("%s", ERR_error_string(derr, NULL));
pgagroal_log_error("%s", ERR_lib_error_string(derr));
pgagroal_log_error("%s", ERR_reason_error_string(derr));
errno = 0;
break;
}
Expand Down
45 changes: 42 additions & 3 deletions src/libpgagroal/pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,14 @@ pgagroal_get_connection(char* username, char* database, bool reuse, bool transac
}
else
{
SSL* s = NULL;
bool kill = false;

if (pgagroal_load_tls_connection(*slot, &s))
{
kill = true;
}

/* Verify the socket for the slot */
if (!pgagroal_socket_isvalid(config->connections[*slot].fd))
{
Expand All @@ -250,7 +256,8 @@ pgagroal_get_connection(char* username, char* database, bool reuse, bool transac

pgagroal_log_debug("pgagroal_get_connection: Slot %d FD %d - Error", *slot, config->connections[*slot].fd);
pgagroal_tracking_event_slot(TRACKER_BAD_CONNECTION, *slot);
status = pgagroal_kill_connection(*slot, *ssl);
status = pgagroal_kill_connection(*slot, s);
s = NULL;

if (config->number_of_users > 0 && config->number_of_limits > 0)
{
Expand All @@ -269,6 +276,8 @@ pgagroal_get_connection(char* username, char* database, bool reuse, bool transac
goto timeout;
}
}

*ssl = s;
}

config->connections[*slot].timestamp = time(NULL);
Expand Down Expand Up @@ -388,8 +397,7 @@ pgagroal_return_connection(int slot, SSL* ssl, bool transaction_mode)
if (config->connections[slot].has_security != SECURITY_INVALID &&
(config->connections[slot].has_security != SECURITY_SCRAM256 ||
(config->connections[slot].has_security == SECURITY_SCRAM256 &&
(config->authquery || pgagroal_user_known(config->connections[slot].username)))) &&
ssl == NULL)
(config->authquery || pgagroal_user_known(config->connections[slot].username)))))
{
state = atomic_load(&config->states[slot]);

Expand All @@ -406,6 +414,20 @@ pgagroal_return_connection(int slot, SSL* ssl, bool transaction_mode)
}
}

if (pgagroal_save_tls_connection(ssl, slot))
{
goto kill_connection;
}

if (ssl != NULL)
{
SSL_CTX* ctx;

ctx = SSL_get_SSL_CTX(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
}

pgagroal_tracking_event_slot(TRACKER_RETURN_CONNECTION_SUCCESS, slot);

config->connections[slot].timestamp = time(NULL);
Expand Down Expand Up @@ -515,6 +537,9 @@ pgagroal_kill_connection(int slot, SSL* ssl)
memset(&config->connections[slot].security_messages[i], 0, SECURITY_BUFFER_SIZE);
}

config->connections[slot].ssl_session_length = 0;
memset(&config->connections[slot].ssl_session, 0, sizeof(config->connections[slot].ssl_session));

config->connections[slot].backend_pid = 0;
config->connections[slot].backend_secret = 0;

Expand Down Expand Up @@ -1120,6 +1145,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1140,6 +1167,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1160,6 +1189,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1180,6 +1211,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1200,6 +1233,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1220,6 +1255,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand All @@ -1240,6 +1277,8 @@ connection_details(int slot)
pgagroal_log_trace(" Size: %zd", connection.security_lengths[i]);
pgagroal_log_mem(&connection.security_messages[i], connection.security_lengths[i]);
}
pgagroal_log_trace(" Session length: %d", connection.ssl_session_length);
pgagroal_log_mem(&connection.ssl_session, connection.ssl_session_length);
pgagroal_log_trace(" Backend PID: %d", connection.backend_pid);
pgagroal_log_trace(" Backend Secret: %d", connection.backend_secret);
break;
Expand Down
Loading

0 comments on commit 2cc39ea

Please sign in to comment.