[PATCH] pgsql: add SSL connection implementation to PGSQL plugin

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch fixes a NULL pointer reference bug which existed in the
PGSQL output plugin, as well as enables SSL connections to be made
to PostgreSQL server by the ulog daemon. Parameters introduced are:

'sslmode' - one of:

    disable - only try a non-SSL connection
      allow - first try a non-SSL connection; if that fails, try SSL
	      connection
     prefer - (default) first try an SSL connection; if that fails, try a
              non-SSL connection
    require - only try an SSL connection
 requiressl - equivalent to 'require', but for older PostgreSQL server
	      versions
  verify-ca - only try an SSL connection, and verify that the server
	      certificate is issued by a trusted CA
verify-full - only try an SSL connection, verify that the server certificate
	      is issued by a trusted CA and that the server host name matches
	      that in the certificate

In addition to the above parameter, 4 other connection options can be
specified:

'sslcert' - This parameter specifies the file name of the client SSL
	    certificate. This parameter is ignored if an SSL connection
	    is not made.
 'sslkey' - This parameter specifies the location for the secret key used
	    for the client certificate. It can either specify a file name that
	    will be used or it can specify a key obtained from an external
	    “engine” (engines are OpenSSL loadable modules). An external
	    engine specification should consist of a colon-separated engine
	    name and an engine-specific key identifier. This parameter is
	    ignored if SSL connection is not made. If this key is protected
	    with a password, this will be asked when the connection is made.
	    It is asked every time an attempt for a connection is made.
'sslroot' - This parameter specifies the name of a file containing SSL
	    certificate authority (CA) certificate(s). If the file exists,
	    the server's certificate will be verified to be signed by one of
	    these authorities.
 'sslcrl' - This parameter specifies the file name of the SSL certificate
	    revocation list (CRL). Certificates listed in this file, if it
	    exists, will be rejected while attempting to authenticate the
	    server's certificate.

Example of use:

ulogd.conf
~~~~~~~~~~
[pgsql3]
db="ulogdb"
host="10.1.1.17"
port=5432
user="ulogd"
pass="changeme"
table="nfacct"
procedure="INSERT_NFACCT"
sslmode="verify-full"
sslcert="/etc/pki/tls/private/postgresql.crt"
sslkey="/etc/pki/tls/private/postgresql.key"
sslroot="/etc/pki/tls/private/root.crt"
sslcrl="/etc/pki/tls/private/root.crl"

Signed-off-by: Mr Dash Four <mr.dash.four@xxxxxxxxxxxxxx>
---
 output/pgsql/ulogd_output_PGSQL.c |   99 ++++++++++++++++++++++++++++++++-----
 ulogd.conf.in                     |   26 ++++++++++
 2 files changed, 113 insertions(+), 12 deletions(-)

diff --git a/output/pgsql/ulogd_output_PGSQL.c b/output/pgsql/ulogd_output_PGSQL.c
index cd793ca..c99a0d7 100644
--- a/output/pgsql/ulogd_output_PGSQL.c
+++ b/output/pgsql/ulogd_output_PGSQL.c
@@ -38,7 +38,7 @@ struct pgsql_instance {
 
 /* our configuration directives */
 static struct config_keyset pgsql_kset = {
-	.num_ces = DB_CE_NUM + 6,
+	.num_ces = DB_CE_NUM + 11,
 	.ces = {
 		DB_CES,
 		{ 
@@ -70,8 +70,32 @@ static struct config_keyset pgsql_kset = {
 			.key = "schema", 
 			.type = CONFIG_TYPE_STRING,
 			.options = CONFIG_OPT_NONE,
-			.u.string = "public",
 		},
+		{  // sslmode=disable|allow|prefer|require|requiressl|verify-ca|verify-full
+			.key = "sslmode", 
+			.type = CONFIG_TYPE_STRING,
+			.options = CONFIG_OPT_NONE,
+		},
+		{
+			.key = "sslcert", 
+			.type = CONFIG_TYPE_STRING,
+			.options = CONFIG_OPT_NONE,
+		},
+		{
+			.key = "sslkey", 
+			.type = CONFIG_TYPE_STRING,
+			.options = CONFIG_OPT_NONE,
+		},
+		{
+			.key = "sslroot", 
+			.type = CONFIG_TYPE_STRING,
+			.options = CONFIG_OPT_NONE,
+		},
+		{
+			.key = "sslcrl", 
+			.type = CONFIG_TYPE_STRING,
+			.options = CONFIG_OPT_NONE,
+ 		},
 	},
 };
 #define db_ce(x)	(x->ces[DB_CE_NUM+0])
@@ -80,6 +104,11 @@ static struct config_keyset pgsql_kset = {
 #define pass_ce(x)	(x->ces[DB_CE_NUM+3])
 #define port_ce(x)	(x->ces[DB_CE_NUM+4])
 #define schema_ce(x)	(x->ces[DB_CE_NUM+5])
+#define sslmode_ce(x)	(x->ces[DB_CE_NUM+6])
+#define sslcert_ce(x)	(x->ces[DB_CE_NUM+7])
+#define sslkey_ce(x)	(x->ces[DB_CE_NUM+8])
+#define sslroot_ce(x)	(x->ces[DB_CE_NUM+9])
+#define sslcrl_ce(x)	(x->ces[DB_CE_NUM+10])
 
 #define PGSQL_HAVE_NAMESPACE_TEMPLATE 			\
 	"SELECT nspname FROM pg_namespace n WHERE n.nspname='%s'"
@@ -127,9 +156,12 @@ static int pgsql_namespace(struct ulogd_pluginstance *upi)
 static int get_columns_pgsql(struct ulogd_pluginstance *upi)
 {
 	struct pgsql_instance *pi = (struct pgsql_instance *) upi->private;
+	char *table = table_ce(upi->config_kset).u.string;
+	char *schema = schema_ce(upi->config_kset).u.string;
+	int schema_len = strlen(schema);
 	char pgbuf[strlen(PGSQL_GETCOLUMN_TEMPLATE_SCHEMA)
-		   + strlen(table_ce(upi->config_kset).u.string) 
-		   + strlen(pi->db_inst.schema) + 2];
+		   + strlen(table) 
+		   + schema_len + 2];
 	int i;
 
 	if (!pi->dbh) {
@@ -137,14 +169,14 @@ static int get_columns_pgsql(struct ulogd_pluginstance *upi)
 		return 1;
 	}
 
-	if (pi->db_inst.schema) {
+	if (schema_len > 0) {
 		snprintf(pgbuf, sizeof(pgbuf)-1,
 			 PGSQL_GETCOLUMN_TEMPLATE_SCHEMA,
-			 table_ce(upi->config_kset).u.string,
-			 pi->db_inst.schema);
+			 schema,
+			 table);
 	} else {
 		snprintf(pgbuf, sizeof(pgbuf)-1, PGSQL_GETCOLUMN_TEMPLATE,
-			 table_ce(upi->config_kset).u.string);
+			 table);
 	}
 
 	ulogd_log(ULOGD_DEBUG, "%s\n", pgbuf);
@@ -217,23 +249,39 @@ static int open_db_pgsql(struct ulogd_pluginstance *upi)
 {
 	struct pgsql_instance *pi = (struct pgsql_instance *) upi->private;
 	int len;
+	int status;
 	char *connstr;
 	char *server = host_ce(upi->config_kset).u.string;
 	unsigned int port = port_ce(upi->config_kset).u.value;
 	char *user = user_ce(upi->config_kset).u.string;
 	char *pass = pass_ce(upi->config_kset).u.string;
 	char *db = db_ce(upi->config_kset).u.string;
+	char *sslmode = sslmode_ce(upi->config_kset).u.string;	
+	char *sslcert = sslcert_ce(upi->config_kset).u.string;	
+	char *sslkey = sslkey_ce(upi->config_kset).u.string;	
+	char *sslroot = sslroot_ce(upi->config_kset).u.string;	
+	char *sslcrl = sslcrl_ce(upi->config_kset).u.string;	
 
 	/* 80 is more than what we need for the fixed parts below */
 	len = 80 + strlen(user) + strlen(db);
 
-	/* hostname and  and password are the only optionals */
+	/* hostname and password are not the only optional parameters */
 	if (server)
 		len += strlen(server);
 	if (pass)
 		len += strlen(pass);
 	if (port)
 		len += 20;
+	if (sslmode)
+		len += strlen(sslmode);
+	if (sslcert)
+		len += strlen(sslcert);
+	if (sslkey)
+		len += strlen(sslkey);
+	if (sslroot)
+		len += strlen(sslroot);
+	if (sslcrl)
+		len += strlen(sslcrl);
 
 	connstr = (char *) malloc(len);
 	if (!connstr) 
@@ -261,10 +309,37 @@ static int open_db_pgsql(struct ulogd_pluginstance *upi)
 		strcat(connstr, pass);
 	}
 	
+	if (sslmode && strlen(sslmode) > 0) {
+		if (strncmp(sslmode, "requiressl", 10) == 0) {
+			strcat(connstr, " requiressl=1");
+		} else {
+			strcat(connstr, " sslmode=");
+			strcat(connstr, sslmode);
+		}
+
+		if (sslcert && strlen(sslcert) > 0) {
+			strcat(connstr, " sslcert=");
+			strcat(connstr, sslcert);
+		}
+		if (sslkey && strlen(sslkey)) {
+			strcat(connstr, " sslkey=");
+			strcat(connstr, sslkey);
+		}
+		if (sslroot && strlen(sslroot)) {
+			strcat(connstr, " sslrootcert=");
+			strcat(connstr, sslroot);
+		}
+		if (sslcrl && strlen(sslcrl)) {
+			strcat(connstr, " sslcrl=");
+			strcat(connstr, sslcrl);
+		}
+ 	}
+
 	pi->dbh = PQconnectdb(connstr);
-	if (PQstatus(pi->dbh) != CONNECTION_OK) {
-		ulogd_log(ULOGD_ERROR, "unable to connect to db (%s): %s\n",
-			  connstr, PQerrorMessage(pi->dbh));
+	status = PQstatus(pi->dbh);
+	if (status != CONNECTION_OK) {
+		ulogd_log(ULOGD_ERROR, "unable to connect to db (%s): %s; status=%u\n",
+			  connstr, PQerrorMessage(pi->dbh),status);
 		close_db_pgsql(upi);
 		return -1;
 	}
diff --git a/ulogd.conf.in b/ulogd.conf.in
index 3bd464b..81dabdc 100644
--- a/ulogd.conf.in
+++ b/ulogd.conf.in
@@ -240,6 +240,32 @@ table="nfacct"
 pass="changeme"
 procedure="INSERT_NFACCT"
 
+[pgsql5]
+db="nulog"
+host="localhost"
+user="nupik"
+table="ulog2_ct"
+pass="changeme"
+procedure="INSERT_OR_REPLACE_CT"
+sslmode="prefer"
+sslcert="/etc/pki/tls/private/ct.crt"
+sslkey="/etc/pki/tls/private/ct.key"
+sslroot="/etc/pki/tls/private/root.crt"
+sslcrl="/etc/pki/tls/private/root.crl"
+
+[pgsql6]
+db="nulog"
+host="localhost"
+user="nupik"
+table="nfacct"
+pass="changeme"
+procedure="INSERT_NFACCT"
+sslmode="verify-full"
+sslcert="/etc/pki/tls/private/nfacct.crt"
+sslkey="/etc/pki/tls/private/nfacct.key"
+sslroot="/etc/pki/tls/private/root.crt"
+sslcrl="/etc/pki/tls/private/root.crl"
+
 [dbi1]
 db="ulog2"
 dbtype="pgsql"
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux