Skip to content

Commit

Permalink
[agroal#70] TLS support: pgagroal - PostgreSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
jesperpedersen committed May 18, 2020
1 parent 3e6c8b6 commit 7fbae4a
Show file tree
Hide file tree
Showing 17 changed files with 633 additions and 89 deletions.
1 change: 1 addition & 0 deletions doc/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct worker_io
int server_fd; /* The server descriptor */
int slot; /* The slot */
SSL* client_ssl; /* The client SSL context */
SSL* server_ssl; /* The server SSL context */
void* shmem; /* The shared memory segment */
void* pipeline_shmem; /* The shared memory segment for the pipeline */
};
Expand Down
4 changes: 4 additions & 0 deletions doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ __Danger zone__
| host | | String | Yes | The address of the PostgreSQL instance |
| port | | Int | Yes | The port of the PostgreSQL instance |
| primary | | Bool | No | Identify the instance as primary (hint) |
| tls | `off` | Bool | No | Enable Transport Layer Security (TLS) towards PostgreSQL |
| tls_cert_file | | String | No | Certificate file for TLS |
| tls_key_file | | String | No | Private key file for TLS |
| tls_ca_file | | String | No | Certificate Authority (CA) file for TLS |

# pgagroal_hba configuration

Expand Down
13 changes: 13 additions & 0 deletions doc/man/pgagroal.conf.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ port
primary
Identify the instance as the primary instance (hint)

tls
Enable Transport Layer Security (TLS). Default is false

tls_cert_file
Certificate file for TLS

tls_key_file
Private key file for TLS

tls_ca_file
Certificate Authority (CA) file for TLS


REPORTING BUGS
==============

Expand Down
8 changes: 8 additions & 0 deletions src/include/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,14 @@ pgagroal_create_auth_scram256_final(char* ss, struct message** msg);
int
pgagroal_write_auth_success(SSL* ssl, int socket);

/**
* Create a SSL message
* @param msg The resulting message
* @return 0 upon success, otherwise 1
*/
int
pgagroal_create_ssl_message(struct message** msg);

/**
* Create a startup message
* @param username The user name
Expand Down
22 changes: 15 additions & 7 deletions src/include/pgagroal.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ extern "C" {
#define ZF_LOG_LEVEL ZF_LOG_DEBUG
#endif

#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 1024

#define IDENTIFIER_LENGTH 64
#define MISC_LENGTH 128
Expand Down Expand Up @@ -120,10 +121,14 @@ extern "C" {
*/
struct server
{
char name[MISC_LENGTH]; /**< The name of the server */
char host[MISC_LENGTH]; /**< The host name of the server */
int port; /**< The port of the server */
int primary; /**< The status of the server */
char name[MISC_LENGTH]; /**< The name of the server */
char host[MISC_LENGTH]; /**< The host name of the server */
int port; /**< The port of the server */
int primary; /**< The status of the server */
bool tls; /**< Is TLS enabled */
char tls_cert_file[MISC_LENGTH]; /**< TLS certificate path */
char tls_key_file[MISC_LENGTH]; /**< TLS key path */
char tls_ca_file[MISC_LENGTH]; /**< TLS CA certificate path */
} __attribute__ ((aligned (64)));

/** @struct
Expand All @@ -141,6 +146,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 */

int ssl_session_length; /**< The length of the SSL session */
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
10 changes: 7 additions & 3 deletions src/include/pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern "C" {

#include <stdbool.h>
#include <stdlib.h>
#include <openssl/ssl.h>

/**
* Get a connection
Expand All @@ -45,28 +46,31 @@ extern "C" {
* @param database The database
* @param reuse Should a slot be reused
* @param slot The resulting slot
* @param ssl The resulting SSL (can be NULL)
* @return 0 upon success, 1 if pool is full, otherwise 2
*/
int
pgagroal_get_connection(void* shmem, char* username, char* database, bool reuse, int* slot);
pgagroal_get_connection(void* shmem, char* username, char* database, bool reuse, int* slot, SSL** ssl);

/**
* Return a connection
* @param shmem The shared memory segment
* @param slot The slot
* @param ssl The SSL connection
* @return 0 upon success, otherwise 1
*/
int
pgagroal_return_connection(void* shmem, int slot);
pgagroal_return_connection(void* shmem, int slot, SSL* ssl);

/**
* Kill a connection
* @param shmem The shared memory segment
* @param slot The slot
* @param ssl The SSL connection
* @return 0 upon success, otherwise 1
*/
int
pgagroal_kill_connection(void* shmem, int slot);
pgagroal_kill_connection(void* shmem, int slot, SSL* ssl);

/**
* Perform idle timeout
Expand Down
26 changes: 24 additions & 2 deletions src/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ extern "C" {
* @param shmem The shared memory segment
* @param slot The resulting slot
* @param client_ssl The client SSL context
* @param server_ssl The server SSL context
* @return 0 upon success, otherwise 1
*/
int
pgagroal_authenticate(int client_fd, char* address, void* shmem, int* slot, SSL** client_ssl);
pgagroal_authenticate(int client_fd, char* address, void* shmem, int* slot, SSL** client_ssl, SSL** server_ssl);

/**
* Authenticate a prefill connection
Expand All @@ -58,10 +59,11 @@ pgagroal_authenticate(int client_fd, char* address, void* shmem, int* slot, SSL*
* @param database The database
* @param shmem The shared memory segment
* @param slot The resulting slot
* @param server_ssl The resulting SSL context
* @return 0 upon success, otherwise 1
*/
int
pgagroal_prefill_auth(char* username, char* password, char* database, void* shmem, int* slot);
pgagroal_prefill_auth(char* username, char* password, char* database, void* shmem, int* slot, SSL** server_ssl);

/**
* Get the master key
Expand Down Expand Up @@ -119,6 +121,26 @@ pgagroal_user_known(char* user, void* shmem);
int
pgagroal_tls_valid(void* shmem);

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

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

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 3 additions & 1 deletion src/include/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extern "C" {
#include <pgagroal.h>

#include <stdlib.h>
#include <openssl/ssl.h>

/**
* Get the primary server
Expand All @@ -51,10 +52,11 @@ pgagroal_get_primary(void* shmem, int* server);
* @param shmem The shared memory segment
* @param slot The slot
* @param socket The descriptor
* @param ssl The SSL connection
* @return 0 upon success, otherwise 1
*/
int
pgagroal_update_server_state(void* shmem, int slot, int socket);
pgagroal_update_server_state(void* shmem, int slot, int socket, SSL* ssl);

/**
* Print the state of the servers
Expand Down
1 change: 1 addition & 0 deletions src/include/worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct worker_io
int server_fd; /**< The server descriptor */
int slot; /**< The slot */
SSL* client_ssl; /**< The client SSL context */
SSL* server_ssl; /**< The server SSL context */
void* shmem; /**< The shared memory segment */
void* pipeline_shmem; /**< The shared memory segment for the pipeline */
};
Expand Down
42 changes: 42 additions & 0 deletions src/libpgagroal/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ pgagroal_read_configuration(char* filename, void* shmem)
{
config->tls = as_bool(value);
}
else if (strlen(section) > 0)
{
srv.tls = as_bool(value);
}
else
{
unknown = true;
Expand All @@ -281,6 +285,17 @@ pgagroal_read_configuration(char* filename, void* shmem)
max = MISC_LENGTH - 1;
memcpy(config->tls_ca_file, value, max);
}
else if (strlen(section) > 0)
{
max = strlen(section);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.name, section, max);
max = strlen(value);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.tls_ca_file, value, max);
}
else
{
unknown = true;
Expand All @@ -295,6 +310,17 @@ pgagroal_read_configuration(char* filename, void* shmem)
max = MISC_LENGTH - 1;
memcpy(config->tls_cert_file, value, max);
}
else if (strlen(section) > 0)
{
max = strlen(section);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.name, section, max);
max = strlen(value);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.tls_cert_file, value, max);
}
else
{
unknown = true;
Expand All @@ -309,6 +335,17 @@ pgagroal_read_configuration(char* filename, void* shmem)
max = MISC_LENGTH - 1;
memcpy(config->tls_key_file, value, max);
}
else if (strlen(section) > 0)
{
max = strlen(section);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.name, section, max);
max = strlen(value);
if (max > MISC_LENGTH - 1)
max = MISC_LENGTH - 1;
memcpy(&srv.tls_key_file, value, max);
}
else
{
unknown = true;
Expand Down Expand Up @@ -660,6 +697,11 @@ pgagroal_validate_configuration(void* shmem)
ZF_LOGF("pgagroal: No port defined for %s", config->servers[i].name);
return 1;
}

if (config->servers[i].tls && (strlen(config->servers[i].tls_cert_file) > 0 || strlen(config->servers[i].tls_key_file) > 0))
{
tls = true;
}
}

if (config->pipeline == PIPELINE_AUTO)
Expand Down
3 changes: 2 additions & 1 deletion src/libpgagroal/management.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ pgagroal_management_transfer_connection(void* shmem, int32_t slot)
error:
free(cmptr);
pgagroal_disconnect(fd);
pgagroal_kill_connection(shmem, slot);
/* TODO */
pgagroal_kill_connection(shmem, slot, NULL);

return 1;
}
Expand Down
24 changes: 24 additions & 0 deletions src/libpgagroal/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,30 @@ pgagroal_write_auth_success(SSL* ssl, int socket)
return ssl_write_message(ssl, true, &msg);
}

int
pgagroal_create_ssl_message(struct message** msg)
{
struct message* m = NULL;
size_t size;

size = 8;

m = (struct message*)malloc(sizeof(struct message));
m->data = malloc(size);

memset(m->data, 0, size);

m->kind = 0;
m->length = size;

pgagroal_write_int32(m->data, size);
pgagroal_write_int32(m->data + 4, 80877103);

*msg = m;

return MESSAGE_STATUS_OK;
}

int
pgagroal_create_startup_message(char* username, char* database, struct message** msg)
{
Expand Down
19 changes: 17 additions & 2 deletions src/libpgagroal/pipeline_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,14 @@ session_client(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
if (likely(msg->kind != 'X'))
{
status = pgagroal_write_socket_message(wi->server_fd, msg);
if (wi->server_ssl == NULL)
{
status = pgagroal_write_socket_message(wi->server_fd, msg);
}
else
{
status = pgagroal_write_ssl_message(wi->server_ssl, msg);
}
if (unlikely(status != MESSAGE_STATUS_OK))
{
goto server_error;
Expand Down Expand Up @@ -267,7 +274,15 @@ session_server(struct ev_loop *loop, struct ev_io *watcher, int revents)

client_active(wi->slot, wi->pipeline_shmem);

status = pgagroal_read_socket_message(wi->server_fd, &msg);
if (wi->server_ssl == NULL)
{
status = pgagroal_read_socket_message(wi->server_fd, &msg);
}
else
{
status = pgagroal_read_ssl_message(wi->server_ssl, &msg);
}

if (likely(status == MESSAGE_STATUS_OK))
{
if (wi->client_ssl == NULL)
Expand Down
Loading

0 comments on commit 7fbae4a

Please sign in to comment.