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 13, 2021
1 parent 717bbd6 commit 4ff42f9
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) */

signed char limit_rule; /**< The limit rule used */
time_t timestamp; /**< The last used timestamp */
pid_t pid; /**< The associated process id */
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 @@ -1234,6 +1234,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 @@ -1269,11 +1270,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 @@ -1328,6 +1337,7 @@ ssl_write_message(SSL* ssl, struct message* msg)
}
else
{
long derr;
int err = SSL_get_error(ssl, numbytes);

switch (err)
Expand All @@ -1349,17 +1359,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].limit_rule = -1;
config->connections[slot].timestamp = -1;
config->connections[slot].fd = -1;
Expand Down Expand Up @@ -1117,6 +1142,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);
break;
case STATE_IN_USE:
pgagroal_log_debug("pgagroal_pool_status: State: IN_USE");
Expand All @@ -1135,6 +1162,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);
break;
case STATE_GRACEFULLY:
pgagroal_log_debug("pgagroal_pool_status: State: GRACEFULLY");
Expand All @@ -1153,6 +1182,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);
break;
case STATE_FLUSH:
pgagroal_log_debug("pgagroal_pool_status: State: FLUSH");
Expand All @@ -1171,6 +1202,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);
break;
case STATE_IDLE_CHECK:
pgagroal_log_debug("pgagroal_pool_status: State: IDLE CHECK");
Expand All @@ -1189,6 +1222,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);
break;
case STATE_VALIDATION:
pgagroal_log_debug("pgagroal_pool_status: State: VALIDATION");
Expand All @@ -1207,6 +1242,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);
break;
case STATE_REMOVE:
pgagroal_log_debug("pgagroal_pool_status: State: REMOVE");
Expand All @@ -1225,6 +1262,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);
break;
default:
pgagroal_log_debug("pgagroal_pool_status: State %d Slot %d FD %d", state, slot, connection.fd);
Expand Down
Loading

0 comments on commit 4ff42f9

Please sign in to comment.