[prev in list] [next in list] [prev in thread] [next in thread] 

List:       nagios-devel
Subject:    [Nagios-devel] SSL/TLS encryption + authentication in NDOUtils
From:       Matthieu Kermagoret <mkermagoret () merethis ! com>
Date:       2009-07-20 13:44:13
Message-ID: 11966f020907200644v282b119bg364ad44ddf113b60 () mail ! gmail ! com
[Download RAW message or body]

Hi all !

Here's a(nother) patch that provide SSL/TLS support to the NDOUtils.


What are its main characteristics ?

This patch uses the GNU TLS library for all cryptographic-related
tasks. Encryption can be configured to use either anonymous temporary
keys or certificates, the latter being able to provide authentication.


How to activate it ?

By default all SSL/TLS related code won't be compiled (the USE_TLS
macro needs to be defined). Once this macro has been set, nodutils
will be compiled with SSL/TLS support but you will have to activate it
in your configuration (either in a file or by a command line switch)
so that you can finally use it. I'm no autotools expert so I won't
provide any addin to the current files. But this shouldn't be
difficult, if any autoconf adept wan't to have a look...


How to configure it ?

There are 4 variables that can be defined :
  - use_tls : whether or not TLS should be activated on the socket
  - tls_cert : public certificate in PEM format. Will be used by the
peer to encrypt the connection
  - tls_key : private key in PEM format. Used to decrypt the connection
  - tls_ca : if one want authentication to be enforced, this variable
shall be set to the Certification Authority's public certificate (in
PEM format) that should have delivered the certificate of the peer. If
not, connection will be dropped.

Those variables can directly be defined in ndomod and ndo2db
configuration files. For file2sock and log2ndo, use command-line
switches :
  -T (or --tls) for use_tls
  -c <certification> (or --cert) for tls_cert
  -k <key> (or --key) for tls_key
  -C <CA> (or --ca) for tls_ca

If tls_cert _and_ tls_key are set, the connection will be encrypted
thanks to the certificate. If not, an anonymous temporary key will be
used.

Please, let me know what you think about it.

Best regards,

-- 
Matthieu KERMAGORET | Développeur

mkermagoret@merethis.com

MERETHIS est éditeur du logiciel Centreon.

["ndoutils-tls.patch" (text/x-diff)]

diff -Naur a/include/io.h b/include/io.h
--- a/include/io.h	2007-01-08 01:35:54.000000000 +0100
+++ b/include/io.h	2009-07-20 09:46:43.000000000 +0200
@@ -9,6 +9,9 @@
 #ifndef _NDO_IO_H
 #define _NDO_IO_H
 
+#ifdef USE_TLS
+# include <gnutls/gnutls.h>
+#endif /* USE_TLS */
 #include "config.h"
 
 
@@ -31,16 +34,41 @@
 	void *mmap_buf;
         }ndo_mmapfile;
 
+#ifdef USE_TLS
+/* TLS_CONF structure - hold TLS configuration */
+typedef struct ndo_tls_conf_struct{
+	int use;
+	char *cert;
+	char *key;
+	char *ca;
+	}ndo_tls_conf;
+
+/* TLS_DATA - store TLS informations */
+typedef struct ndo_tls_data_struct{
+	gnutls_session_t session;
+	union{
+		gnutls_anon_client_credentials_t anon;
+		gnutls_certificate_credentials_t cert;
+		}cred;
+	}ndo_tls_data;
+#endif /* USE_TLS */
 
 ndo_mmapfile *ndo_mmap_fopen(char *);
 int ndo_mmap_fclose(ndo_mmapfile *);
 char *ndo_mmap_fgets(ndo_mmapfile *);
 
+#ifdef USE_TLS
+int ndo_sink_open(char *,int,int,int,int,int *,const ndo_tls_conf *,ndo_tls_data *);
+int ndo_sink_write(int,char *,int,ndo_tls_data *);
+int ndo_sink_write_newline(int,ndo_tls_data *);
+int ndo_sink_close(int,ndo_tls_data *);
+#else
 int ndo_sink_open(char *,int,int,int,int,int *);
 int ndo_sink_write(int,char *,int);
 int ndo_sink_write_newline(int);
-int ndo_sink_flush(int);
 int ndo_sink_close(int);
+#endif /* USE_TLS */
+int ndo_sink_flush(int);
 int ndo_inet_aton(register const char *,struct in_addr *);
 
 void ndo_strip_buffer(char *);
diff -Naur a/include/ndo2db.h b/include/ndo2db.h
--- a/include/ndo2db.h	2009-07-20 12:11:35.000000000 +0200
+++ b/include/ndo2db.h	2009-07-20 09:40:56.000000000 +0200
@@ -9,6 +9,9 @@
 #ifndef _NDO2DB_NDO2DB_H
 #define _NDO2DB_NDO2DB_H
 
+#ifdef USE_TLS
+# include <gnutls/gnutls.h>
+#endif /* USE_TLS */
 #include "config.h"
 #include "utils.h"
 
@@ -111,6 +114,18 @@
         }ndo2db_idi;
 
 
+#ifdef USE_TLS
+typedef struct ndo2db_tls_struct{
+	gnutls_session_t session;
+	union{
+		gnutls_anon_server_credentials_t anon;
+		gnutls_certificate_credentials_t cert;
+		}cred;
+	gnutls_dh_params_t dh_params;
+	}ndo2db_tls;
+#endif /* USE_TLS */
+
+
 
 /*************** DB server types ***************/
 #define NDO2DB_DBSERVER_NONE                            0
@@ -233,6 +248,11 @@
 int ndo2db_check_for_client_input(ndo2db_idi *,ndo_dbuf *);
 int ndo2db_handle_client_input(ndo2db_idi *,char *);
 
+#ifdef USE_TLS
+int ndo2db_tls_init(ndo2db_tls *,int);
+void ndo2db_tls_deinit(ndo2db_tls *);
+#endif /* USE_TLS */
+
 int ndo2db_start_input_data(ndo2db_idi *);
 int ndo2db_end_input_data(ndo2db_idi *);
 int ndo2db_add_input_data_item(ndo2db_idi *,int,char *);
diff -Naur a/src/file2sock.c b/src/file2sock.c
--- a/src/file2sock.c	2009-07-20 12:11:35.000000000 +0200
+++ b/src/file2sock.c	2009-07-20 12:39:14.000000000 +0200
@@ -29,6 +29,10 @@
 int show_version=NDO_FALSE;
 int show_license=NDO_FALSE;
 int show_help=NDO_FALSE;
+#ifdef USE_TLS
+ndo_tls_conf tls_conf={0,NULL,NULL,NULL};
+ndo_tls_data *tls_data=NULL;
+#endif /* USE_TLS */
 
 int main(int argc, char **argv){
 	int sd=0;
@@ -56,6 +60,9 @@
 		printf("other processing is done before sending the contents to the destination \
socket.\n");  printf("\n");
 		printf("Usage: %s -s <source> -d <dest> [-t <type>] [-p <port>]\n",argv[0]);
+#ifdef USE_TLS
+		printf("          [-T] [-c <cert>] [-k <key>] [-C <CA>]\n");
+#endif /* USE_TLS */
 		printf("\n");
 		printf("<source>   = Name of the file to read from.  Use '-' to read from \
stdin.\n");  printf("<dest>     = If destination is a TCP socket, the \
address/hostname to connect to.\n"); @@ -64,6 +71,12 @@
 		printf("                 tcp\n");
 		printf("                 unix (default)\n");
 		printf("<port>     = Port number to connect to if destination is TCP socket.\n");
+#ifdef USE_TLS
+		printf("<cert>     = Certificate file with which peer will encrypt the \
connection.\n"); +		printf("<key>      = Key file associated with the \
certificate.\n"); +		printf("<CA>       = If peer certificate has to be checked, \
specify the Certificate\n"); +		printf("             Authority certificate that \
should have signed the peer certificate.\n"); +#endif /* USE_TLS */
 		printf("\n");
 
 		exit(1);
@@ -78,7 +91,11 @@
 	        }
 
 	/* open data sink */
+#ifdef USE_TLS
+	if(ndo_sink_open(dest_name,sd,socket_type,tcp_port,0,&sd,&tls_conf,tls_data)==NDO_ERROR){
 +#else
 	if(ndo_sink_open(dest_name,sd,socket_type,tcp_port,0,&sd)==NDO_ERROR){
+#endif /* USE_TLS */
 		perror("Cannot open destination socket");
 		close(fd);
 		exit(1);
@@ -117,7 +134,15 @@
 
 	/* close the data sink */
 	ndo_sink_flush(sd);
+#ifdef USE_TLS
+	ndo_sink_close(sd,tls_data);
+	if(tls_data){
+		free(tls_data);
+		gnutls_global_deinit();
+		}
+#else
 	ndo_sink_close(sd);
+#endif /* USE_TLS */
 
 	/* close the source file */
 	close(fd);
@@ -141,6 +166,12 @@
 		{"help", no_argument, 0, 'h'},
 		{"license", no_argument, 0, 'l'},
 		{"version", no_argument, 0, 'V'},
+# ifdef USE_TLS
+		{"tls", no_argument, 0, 'T'},
+		{"cert", required_argument, 0, 'c'},
+		{"key", required_argument, 0, 'k'},
+		{"ca", required_argument, 0, 'C'},
+# endif /* USE_TLS */
 		{0, 0, 0, 0}
                 };
 #endif
@@ -151,7 +182,11 @@
 		return NDO_OK;
 	        }
 
+#ifdef USE_TLS
+	snprintf(optchars,sizeof(optchars),"s:d:t:p:hlVTc:k:C:");
+#else
 	snprintf(optchars,sizeof(optchars),"s:d:t:p:hlV");
+#endif /* USE_TLS */
 
 	while(1){
 #ifdef HAVE_GETOPT_H
@@ -194,6 +229,22 @@
 		case 'd':
 			dest_name=strdup(optarg);
 			break;
+#ifdef USE_TLS
+		case 'T':
+			tls_conf.use=NDO_TRUE;
+			gnutls_global_init();
+			tls_data=malloc(sizeof(*tls_data));
+			break;
+		case 'c':
+			tls_conf.cert=strdup(optarg);
+			break;
+		case 'k':
+			tls_conf.key=strdup(optarg);
+			break;
+		case 'C':
+			tls_conf.ca=strdup(optarg);
+			break;
+#endif /* USE_TLS */
 		default:
 			return NDO_ERROR;
 			break;
diff -Naur a/src/io.c b/src/io.c
--- a/src/io.c	2009-07-20 12:11:35.000000000 +0200
+++ b/src/io.c	2009-07-20 11:11:27.000000000 +0200
@@ -135,12 +135,17 @@
 
 
 /* opens data sink */
+#ifdef USE_TLS
+int ndo_sink_open(char *name, int fd, int type, int port, int flags, int *nfd, const \
ndo_tls_conf *tls_conf, ndo_tls_data *tls_data){ +#else
 int ndo_sink_open(char *name, int fd, int type, int port, int flags, int *nfd){
+#endif /* USE_TLS */
 	struct sockaddr_un server_address_u;
 	struct sockaddr_in server_address_i;
 	struct hostent *hp=NULL;
 	mode_t mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
 	int newfd=0;
+	int ret;
 
 	/* use file */
 	if(type==NDO_SINK_FILE){
@@ -196,20 +201,99 @@
 			memcpy(&server_address_i.sin_addr,hp->h_addr,hp->h_length);
 	                }
 
+#ifdef USE_TLS
+		if(tls_conf->use){
+
+			/* initialize TLS session */
+			if(gnutls_init(&tls_data->session,GNUTLS_CLIENT)!=GNUTLS_E_SUCCESS)
+				return NDO_ERROR;
+
+			/* use default ciphers */
+			if(gnutls_priority_set_direct(tls_data->session,"NORMAL:+ANON-DH:%COMPAT",NULL)!=GNUTLS_E_SUCCESS)
 +				goto tls_deinit;
+
+			/* we shall use certificates */
+			if(tls_conf->cert&&tls_conf->key){
+				/* use provided certificates */
+				if(gnutls_certificate_allocate_credentials(&tls_data->cred.cert)!=GNUTLS_E_SUCCESS)
 +					goto tls_deinit;
+				if(gnutls_certificate_set_x509_key_file(tls_data->cred.cert,tls_conf->cert,tls_conf->key,GNUTLS_X509_FMT_PEM)!=GNUTLS_E_SUCCESS)
 +					goto tls_clean;
+				/* set authentication */
+				if(tls_conf->ca)
+					if(gnutls_certificate_set_x509_trust_file(tls_data->cred.cert,tls_conf->ca,GNUTLS_X509_FMT_PEM)<0)
 +						goto tls_clean;
+
+				/* apply credentials to the context */
+				if(gnutls_credentials_set(tls_data->session,GNUTLS_CRD_CERTIFICATE,tls_data->cred.cert)!=GNUTLS_E_SUCCESS)
 +					goto tls_clean;
+
+			/* if no parameters are set, set anonymous credentials */
+			}else{
+				if(gnutls_anon_allocate_client_credentials(&tls_data->cred.anon)!=GNUTLS_E_SUCCESS)
 +					goto tls_clean;
+				if(gnutls_credentials_set(tls_data->session,GNUTLS_CRD_ANON,tls_data->cred.anon)!=GNUTLS_E_SUCCESS)
 +					goto tls_clean;
+				}
+			}
+#endif /* USE_TLS */
+
 		/* create a socket */
-		if(!(newfd=socket(PF_INET,SOCK_STREAM,0)))
-			return NDO_ERROR;
+		if(!(newfd=socket(PF_INET,SOCK_STREAM,0))){
+#ifdef USE_TLS
+			if(tls_conf->use)
+				goto tls_clean;
+			else
+#endif /* USE_TLS */
+				return NDO_ERROR;
+			}
 
 		/* copy the host/ip address and port */
-		server_address_i.sin_family=AF_INET; 
+		server_address_i.sin_family=AF_INET;
 		server_address_i.sin_port=htons(port);
 
 		/* connect to the socket */
 		if((connect(newfd,(struct sockaddr \
*)&server_address_i,sizeof(server_address_i)))){  close(newfd);
-			return NDO_ERROR;
+#ifdef USE_TLS
+			if(tls_conf->use)
+				goto tls_clean;
+			else
+#endif /* USE_TLS */
+				return NDO_ERROR;
 		        }
-	        }
+
+#ifdef USE_TLS
+		if(tls_conf->use){
+
+			/* associate the socket with the security layer */
+			gnutls_transport_set_ptr(tls_data->session,(gnutls_transport_ptr_t)newfd);
+
+			/* perform TLS handshake */
+			if(gnutls_handshake(tls_data->session)!=GNUTLS_E_SUCCESS){
+				close(newfd);
+				goto tls_clean;
+				}
+			if(tls_conf->ca&&(gnutls_certificate_verify_peers2(tls_data->session,&ret)!=0||(ret&(GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED|GNUTLS_CERT_SIGNER_NOT_FOUND)))){
 +				gnutls_bye(tls_data->session,GNUTLS_SHUT_RDWR);
+				close(newfd);
+				goto tls_clean;
+			  }
+
+			/* this code is used to cleanup TLS in case of error */
+			if(0){
+				tls_clean:
+					if(tls_conf->cert&&tls_conf->key)
+						gnutls_certificate_free_credentials(tls_data->cred.cert);
+					else
+						gnutls_anon_free_client_credentials(tls_data->cred.anon);
+				tls_deinit:
+					gnutls_deinit(tls_data->session);
+					return NDO_ERROR;
+				}
+			}
+#endif /* USE_TLS */
+		}
 
 	/* unknown sink type */
 	else
@@ -223,7 +307,11 @@
 
 
 /* writes to data sink */
+#ifdef USE_TLS
+int ndo_sink_write(int fd, char *buf, int buflen, ndo_tls_data *tls_data){
+#else
 int ndo_sink_write(int fd, char *buf, int buflen){
+#endif /* USE_TLS */
 	int tbytes=0;
 	int result=0;
 
@@ -235,7 +323,12 @@
 	while(tbytes<buflen){
 
 		/* try to write everything we have left */
-		result=write(fd,buf+tbytes,buflen-tbytes);
+#ifdef USE_TLS
+		if(tls_data)
+			result=gnutls_record_send(tls_data->session,buf+tbytes,buflen-tbytes);
+		else
+#endif /* USE_TLS */
+			result=write(fd,buf+tbytes,buflen-tbytes);
 
 		/* some kind of error occurred */
 		if(result==-1){
@@ -254,10 +347,17 @@
 
 
 /* writes a newline to data sink */
+#ifdef USE_TLS
+int ndo_sink_write_newline(int fd, ndo_tls_data *tls_data){
+
+	return ndo_sink_write(fd,"\n",1,tls_data);
+	}
+#else
 int ndo_sink_write_newline(int fd){
 
 	return ndo_sink_write(fd,"\n",1);
         }
+#endif /* USE_TLS */
 
 
 /* flushes data sink */
@@ -271,12 +371,21 @@
 
 
 /* closes data sink */
+#ifdef USE_TLS
+int ndo_sink_close(int fd, ndo_tls_data *tls_data){
+#else
 int ndo_sink_close(int fd){
+#endif /* USE_TLS */
 
 	/* no need to close STDOUT */
 	if(fd==STDOUT_FILENO)
 		return NDO_OK;
 
+#ifdef USE_TLS
+	if(tls_data)
+		gnutls_bye(tls_data->session,GNUTLS_SHUT_RDWR);
+#endif /* USE_TLS */
+
 	/* close the socket */
 	shutdown(fd,2);
 	close(fd);
diff -Naur a/src/log2ndo.c b/src/log2ndo.c
--- a/src/log2ndo.c	2009-07-20 12:11:35.000000000 +0200
+++ b/src/log2ndo.c	2009-07-20 12:39:46.000000000 +0200
@@ -29,6 +29,10 @@
 int show_version=NDO_FALSE;
 int show_license=NDO_FALSE;
 int show_help=NDO_FALSE;
+#ifdef USE_TLS
+ndo_tls_conf tls_conf={0,NULL,NULL,NULL};
+ndo_tls_data *tls_data=NULL;
+#endif /* USE_TLS */
 
 
 int main(int argc, char **argv){
@@ -60,6 +64,9 @@
 		printf("NDO2DB daemon.\n");
 		printf("\n");
 		printf("Usage: %s -s <source> -d <dest> -i <instance> [-t <type>] [-p \
<port>]\n",argv[0]); +#ifdef USE_TLS
+		printf("          [-T] [-c <cert>] [-k <key>] [-C <CA>]\n");
+#endif /* USE_TLS */
 		printf("\n");
 		printf("<source>   = Name of the Nagios/NetSaint log file to read from.\n");
 		printf("<dest>     = If destination is a TCP socket, the address/hostname to \
connect to.\n"); @@ -69,6 +76,12 @@
 		printf("                 tcp\n");
 		printf("                 unix (default)\n");
 		printf("<port>     = Port number to connect to if destination is TCP socket.\n");
+#ifdef USE_TLS
+		printf("<cert>     = Certificate file with which peer will encrypt the \
connection.\n"); +		printf("<key>      = Key file associated with the \
certificate.\n"); +		printf("<CA>       = If peer certificate has to be checked, \
specify the Certificate\n"); +		printf("             Authority certificate that \
should have signed the peer certificate.\n"); +#endif /* USE_TLS */
 		printf("\n");
 
 		exit(1);
@@ -87,7 +100,11 @@
 	        }
 
 	/* open the destination */
+#ifdef USE_TLS
+	if(ndo_sink_open(dest_name,sd,socket_type,tcp_port,0,&sd,&tls_conf,tls_data)==NDO_ERROR){
 +#else
 	if(ndo_sink_open(dest_name,sd,socket_type,tcp_port,0,&sd)==NDO_ERROR){
+#endif /* USE_TLS */
 		ndo_mmap_fclose(thefile);
 		exit(1);
 	        }
@@ -125,7 +142,11 @@
 		 ,NDO_API_STARTDATADUMP
 		);
 	tempbuf[sizeof(tempbuf)-1]='\x0';
+#ifdef USE_TLS
+	ndo_sink_write(sd,tempbuf,strlen(tempbuf),tls_data);
+#else
 	ndo_sink_write(sd,tempbuf,strlen(tempbuf));
+#endif /* USE_TLS */
 
 
 
@@ -150,7 +171,11 @@
 			 ,NDO_API_ENDDATA
 			);
 		tempbuf[sizeof(tempbuf)-1]='\x0';
+#ifdef USE_TLS
+		ndo_sink_write(sd,tempbuf,strlen(tempbuf),tls_data);
+#else
 		ndo_sink_write(sd,tempbuf,strlen(tempbuf));
+#endif /* USE_TLS */
 
 		/* free allocated memory */
 		free(input);
@@ -170,13 +195,25 @@
 		 ,NDO_API_GOODBYE
 		);
 	tempbuf[sizeof(tempbuf)-1]='\x0';
+#ifdef USE_TLS
+	ndo_sink_write(sd,tempbuf,strlen(tempbuf),tls_data);
+#else
 	ndo_sink_write(sd,tempbuf,strlen(tempbuf));
+#endif /* USE_TLS */
 
 
 
 	/* close the destination */
 	ndo_sink_flush(sd);
+#ifdef USE_TLS
+	ndo_sink_close(sd,tls_data);
+	if(tls_data){
+		free(tls_data);
+		gnutls_global_deinit();
+		}
+#else
 	ndo_sink_close(sd);
+#endif /* USE_TLS */
 
 	/* close the file */
 	ndo_mmap_fclose(thefile);
@@ -201,6 +238,12 @@
 		{"help", no_argument, 0, 'h'},
 		{"license", no_argument, 0, 'l'},
 		{"version", no_argument, 0, 'V'},
+# ifdef USE_TLS
+		{"tls", no_argument, 0, 'T'},
+		{"cert", required_argument, 0, 'c'},
+		{"key", required_argument, 0, 'k'},
+		{"ca", required_argument, 0, 'C'},
+# endif /* USE_TLS */
 		{0, 0, 0, 0}
                 };
 #endif
@@ -211,7 +254,11 @@
 		return NDO_OK;
 	        }
 
+#ifdef USE_TLS
+	snprintf(optchars,sizeof(optchars),"s:d:i:t:p:hlVTc:k:C:");
+#else
 	snprintf(optchars,sizeof(optchars),"s:d:i:t:p:hlV");
+#endif /* USE_TLS */
 
 	while(1){
 #ifdef HAVE_GETOPT_H
@@ -257,6 +304,22 @@
 		case 'i':
 			instance_name=strdup(optarg);
 			break;
+#ifdef USE_TLS
+		case 'T':
+			tls_conf.use=NDO_TRUE;
+			gnutls_global_init();
+			tls_data=malloc(sizeof(*tls_data));
+			break;
+		case 'c':
+			tls_conf.cert=strdup(optarg);
+			break;
+		case 'k':
+			tls_conf.key=strdup(optarg);
+			break;
+		case 'C':
+			tls_conf.ca=strdup(optarg);
+			break;
+#endif /* USE_TLS */
 		default:
 			return NDO_ERROR;
 			break;
diff -Naur a/src/ndo2db.c b/src/ndo2db.c
--- a/src/ndo2db.c	2009-07-20 12:11:35.000000000 +0200
+++ b/src/ndo2db.c	2009-07-20 11:11:05.000000000 +0200
@@ -15,6 +15,9 @@
 #include <mcheck.h>
 #endif
 
+#ifdef USE_TLS
+# include <gnutls/gnutls.h>
+#endif /* USE_TLS */
 /* include our project's header files */
 #include "../include/config.h"
 #include "../include/common.h"
@@ -44,6 +47,12 @@
 int ndo2db_show_version=NDO_FALSE;
 int ndo2db_show_license=NDO_FALSE;
 int ndo2db_show_help=NDO_FALSE;
+#ifdef USE_TLS
+int ndo2db_use_tls=NDO_FALSE;
+char *ndo2db_tls_cert=NULL;
+char *ndo2db_tls_key=NULL;
+char *ndo2db_tls_ca=NULL;
+#endif /* USE_TLS */
 
 ndo2db_dbconfig ndo2db_db_settings;
 time_t ndo2db_db_last_checkin_time=0L;
@@ -118,6 +127,14 @@
 		exit(1);
 	        }
 
+#ifdef USE_TLS
+	/* initialize the TLS library */
+	if((ndo2db_use_tls==NDO_TRUE)&&(gnutls_global_init()!=GNUTLS_E_SUCCESS)){
+		printf("Could not initialize the TLS library.\n");
+		exit(1);
+		}
+#endif /* USE_TLS */
+
 	/* make sure we support the db option chosen... */
 #ifdef USE_MYSQL
 	if(ndo2db_db_settings.server_type==NDO2DB_DBSERVER_MYSQL)
@@ -381,6 +398,16 @@
 		ndo2db_debug_verbosity=atoi(val);
 	else if(!strcmp(var,"max_debug_file_size"))
 		ndo2db_max_debug_file_size=strtoul(val,NULL,0);
+#ifdef USE_TLS
+	else if(!strcmp(var,"use_tls"))
+		ndo2db_use_tls=strtol(val,NULL,0);
+	else if(!strcmp(var,"tls_cert"))
+		ndo2db_tls_cert=strdup(val);
+	else if(!strcmp(var,"tls_key"))
+		ndo2db_tls_key=strdup(val);
+	else if(!strcmp(var,"tls_ca"))
+		ndo2db_tls_ca=strdup(val);
+#endif /* USE_TLS */
 
 	return NDO_OK;
         }
@@ -454,6 +481,21 @@
 		free(ndo2db_debug_file);
 		ndo2db_debug_file=NULL;
 		}
+#ifdef USE_TLS
+	if(ndo2db_tls_cert){
+		free(ndo2db_tls_cert);
+		ndo2db_tls_cert=NULL;
+		}
+	if(ndo2db_tls_key){
+		free(ndo2db_tls_key);
+		ndo2db_tls_key=NULL;
+		}
+	if(ndo2db_tls_ca){
+		free(ndo2db_tls_ca);
+		ndo2db_tls_ca=NULL;
+		}
+	gnutls_global_deinit();
+#endif /* USE_TLS */
 
 	return NDO_OK;
 	}
@@ -861,6 +903,9 @@
 	char buf[512];
 	int result=0;
 	int error=NDO_FALSE;
+#ifdef USE_TLS
+	ndo2db_tls tls;
+#endif /* USE_TLS */
 
 	/* open syslog facility */
 	/*openlog("ndo2db",0,LOG_DAEMON);*/
@@ -882,6 +927,12 @@
 	/* initialize dynamic buffer (2KB chunk size) */
 	ndo_dbuf_init(&dbuf,dbuf_chunk);
 
+#ifdef USE_TLS
+	/* initialize TLS structures */
+	if(ndo2db_use_tls)
+		ndo2db_tls_init(&tls,sd);
+#endif /* USE_TLS */
+
 	/* initialize database connection */
 	ndo2db_db_init(&idi);
 	ndo2db_db_connect(&idi);
@@ -889,7 +940,12 @@
 	/* read all data from client */
 	while(1){
 
-		result=read(sd,buf,sizeof(buf)-1);
+#ifdef USE_TLS
+		if(ndo2db_use_tls)
+			result=gnutls_record_recv(tls.session,buf,sizeof(buf)-1);
+		else
+#endif /* USE_TLS */
+			result=read(sd,buf,sizeof(buf)-1);
 
 		/* bail out on hard errors */
 		if(result==-1 && (errno!=EAGAIN && errno!=EINTR)){
@@ -931,6 +987,12 @@
 	printf("BYTES: %lu, LINES: %lu\n",idi.bytes_processed,idi.lines_processed);
 #endif
 
+#ifdef USE_TLS
+	/* shutdown TLS */
+	if(ndo2db_use_tls)
+		ndo2db_tls_deinit(&tls);
+#endif /* USE_TLS */
+
 	/* free memory allocated to dynamic buffer */
 	ndo_dbuf_free(&dbuf);
 
@@ -1367,6 +1429,121 @@
         }
 
 
+#ifdef USE_TLS
+int ndo2db_tls_init(ndo2db_tls *tls, int sd){
+	/* parameters used to generate Diffie-Hellman keys */
+	/* those 2048 bits parameters were generated the 10/07/09 on Ubuntu 9.04 with \
OpenSSL 0.9.8g */ +	static char dh_params_2048[] =
+		"-----BEGIN DH PARAMETERS-----\n"
+		"MIIBCAKCAQEAqvIBJkRHEpT+IVBvpsmwwkpd/5cRjPPurlYKX618TteGts3gYjbi\n"
+		"DXUzPBZqEs9rgk3Q5mmjvMj5UePyKCQX77+Tu7nm7zdAgwv9kx0KqbqJiDxOIFMi\n"
+		"ibdo05PBUg63HQjxCWwWSmoyV6JkUnO3R1bp4I6D499BhJengVh32UhhMpkW4QhP\n"
+		"J1bROQZayOMZ0P1gS8SYoMJcG0LbL7TSjhqYc/gKHLbvzlmfWO53kIe9/ezJc6MS\n"
+		"Y+DHI36C9XXoES+w24D9dlCuW6qnbUsEF/vIqKK1js4qrhppyk42sk7aAI5TcSbs\n"
+		"58voeJ9NQgeZqnnF2mo7Wd+MHF3I/hHnkwIBAg==\n"
+		"-----END DH PARAMETERS-----\n";
+	gnutls_datum_t dh_params;
+	int ret;
+
+	/* load Diffie-Hellman parameters */
+	if(gnutls_dh_params_init(&tls->dh_params)!=GNUTLS_E_SUCCESS)
+		return NDO_ERROR;
+	dh_params.data=dh_params_2048;
+	dh_params.size=sizeof(dh_params_2048);
+	if(gnutls_dh_params_import_pkcs3(tls->dh_params,&dh_params,GNUTLS_X509_FMT_PEM)!=GNUTLS_E_SUCCESS)
 +		return NDO_ERROR;
+
+	/* initialize the session */
+	if(gnutls_init(&tls->session,GNUTLS_SERVER)!=GNUTLS_E_SUCCESS)
+		return NDO_ERROR;
+
+	/* use default ciphers */
+	if(gnutls_priority_set_direct(tls->session,"NORMAL:+ANON-DH",NULL)!=GNUTLS_E_SUCCESS){
 +		gnutls_deinit(tls->session);
+		return NDO_ERROR;
+		}
+
+	/* shall we use certificates ? */
+	if(ndo2db_tls_cert&&ndo2db_tls_key){
+		if(gnutls_certificate_allocate_credentials(&tls->cred.cert)!=GNUTLS_E_SUCCESS){
+			gnutls_deinit(tls->session);
+			return NDO_ERROR;
+			}
+		if((ret=gnutls_certificate_set_x509_key_file(tls->cred.cert,ndo2db_tls_cert,ndo2db_tls_key,GNUTLS_X509_FMT_PEM))!=GNUTLS_E_SUCCESS){
 +			syslog(LOG_ERR,"Warning while loading TLS certificate: \
%s",gnutls_strerror(ret)); +			ndo2db_tls_deinit(tls);
+			return NDO_ERROR;
+			}
+
+		/* set authentication */
+		if(ndo2db_tls_ca){
+			if((ret=gnutls_certificate_set_x509_trust_file(tls->cred.cert,ndo2db_tls_ca,GNUTLS_X509_FMT_PEM))<0){
 +				syslog(LOG_ERR, "Warning while loading trusted CAs: %s", gnutls_strerror(ret));
+				ndo2db_tls_deinit(tls);
+				return NDO_ERROR;
+				}
+			}
+
+		/* apply DH parameters */
+		gnutls_certificate_set_dh_params(tls->cred.cert,tls->dh_params);
+
+		/* apply credentials */
+		if(gnutls_credentials_set(tls->session,GNUTLS_CRD_CERTIFICATE,tls->cred.cert)!=GNUTLS_E_SUCCESS){
 +			ndo2db_tls_deinit(tls);
+			return NDO_ERROR;
+			}
+
+		/* request client certificate */
+		gnutls_certificate_server_set_request(tls->session,GNUTLS_CERT_REQUEST);
+
+	/* if no parameters are set, set anonymous credentials */
+	}else{
+		if(gnutls_anon_allocate_server_credentials(&tls->cred.anon)!=GNUTLS_E_SUCCESS){
+			gnutls_deinit(tls->session);
+			return NDO_ERROR;
+			}
+		gnutls_anon_set_server_dh_params(tls->cred.anon,tls->dh_params);
+		if(gnutls_credentials_set(tls->session,GNUTLS_CRD_ANON,tls->cred.anon)!=GNUTLS_E_SUCCESS){
 +			ndo2db_tls_deinit(tls);
+			return NDO_ERROR;
+			}
+		}
+
+	/* set Diffie-Hellman parameters length (2048 bits) */
+	gnutls_dh_set_prime_bits(tls->session,2048);
+
+	/* associate FD with TLS session */
+	gnutls_transport_set_ptr(tls->session,(gnutls_transport_ptr_t)sd);
+
+	/* TLS handshake  */
+	if((ret=gnutls_handshake(tls->session))!=GNUTLS_E_SUCCESS){
+		syslog(LOG_ERR,"TLS handshake failed: %s",gnutls_strerror(ret));
+		ndo2db_tls_deinit(tls);
+		return NDO_ERROR;
+		}
+
+	/* check client certificate */
+	if(ndo2db_tls_ca&&(gnutls_certificate_verify_peers2(tls->session,&ret)!=GNUTLS_E_SUC \
CESS||(ret&(GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED|GNUTLS_CERT_SIGNER_NOT_FOUND)))){ \
+			syslog(LOG_ERR,"Invalid peer certificate"); \
+			gnutls_bye(tls->session,GNUTLS_SHUT_RDWR); +			ndo2db_tls_deinit(tls);
+			return NDO_ERROR;
+			}
+
+	return NDO_OK;
+	}
+
+
+void ndo2db_tls_deinit(ndo2db_tls *tls){
+	if(ndo2db_tls_cert&&ndo2db_tls_key)
+		gnutls_certificate_free_credentials(tls->cred.cert);
+	else
+		gnutls_anon_free_server_credentials(tls->cred.anon);
+	gnutls_deinit(tls->session);
+	}
+#endif /* USE_TLS */
+
+
 int ndo2db_start_input_data(ndo2db_idi *idi){
 	int x;
 
diff -Naur a/src/ndomod.c b/src/ndomod.c
--- a/src/ndomod.c	2009-07-20 12:11:35.000000000 +0200
+++ b/src/ndomod.c	2009-07-20 12:30:59.000000000 +0200
@@ -77,6 +77,10 @@
 int ndomod_config_output_options=NDOMOD_CONFIG_DUMP_ALL;
 unsigned long ndomod_sink_buffer_slots=5000;
 ndomod_sink_buffer sinkbuf;
+#ifdef USE_TLS
+ndo_tls_conf ndomod_tls_conf={0,NULL,NULL,NULL};
+ndo_tls_data *ndomod_tls_data=NULL;
+#endif /* USE_TLS */
 
 extern int errno;
 
@@ -437,6 +441,24 @@
 	else if(!strcmp(var,"buffer_file"))
 		ndomod_buffer_file=strdup(val);
 
+#ifdef USE_TLS
+	else if(!strcmp(var,"use_tls")){
+		ndomod_tls_conf.use=strtol(val,NULL,0);
+		if(ndomod_tls_conf.use&&!ndomod_tls_data)
+			gnutls_global_init();
+			ndomod_tls_data=malloc(sizeof(*ndomod_tls_data));
+		}
+
+	else if(!strcmp(var,"tls_cert"))
+		ndomod_tls_conf.cert=strdup(val);
+
+	else if(!strcmp(var,"tls_key"))
+		ndomod_tls_conf.key=strdup(val);
+
+	else if(!strcmp(var,"tls_ca"))
+		ndomod_tls_conf.ca=strdup(val);
+#endif /* USE_TLS */
+
 	else
 		return NDO_ERROR;
 
@@ -475,7 +497,11 @@
 	/* try and open sink */
 	if(ndomod_sink_type==NDO_SINK_FILE)
 		flags=O_WRONLY|O_CREAT|O_APPEND;
+#ifdef USE_TLS
+	if(ndo_sink_open(ndomod_sink_name,0,ndomod_sink_type,ndomod_sink_tcp_port,flags,&ndomod_sink_fd,&ndomod_tls_conf,ndomod_tls_data)==NDO_ERROR)
 +#else
 	if(ndo_sink_open(ndomod_sink_name,0,ndomod_sink_type,ndomod_sink_tcp_port,flags,&ndomod_sink_fd)==NDO_ERROR)
 +#endif /* USE_TLS */
 		return NDO_ERROR;
 
 	/* mark the sink as being open */
@@ -499,11 +525,24 @@
 	ndo_sink_flush(ndomod_sink_fd);
 
 	/* close sink */
+#ifdef USE_TLS
+	ndo_sink_close(ndomod_sink_fd,ndomod_tls_data);
+#else
 	ndo_sink_close(ndomod_sink_fd);
+#endif /* USE_TLS */
 
 	/* mark the sink as being closed */
 	ndomod_sink_is_open=NDO_FALSE;
 
+#ifdef USE_TLS
+	/* shutdown TLS */
+	if(ndomod_tls_data){
+		free(ndomod_tls_data);
+		ndomod_tls_data=NULL;
+		gnutls_global_deinit();
+		}
+#endif /* USE_TLS */
+
 	return NDO_OK;
         }
 
@@ -736,7 +775,11 @@
 			sbuf=ndomod_sink_buffer_peek(&sinkbuf);
 
 			buflen=strlen(sbuf);
+#ifdef USE_TLS
+			result=ndo_sink_write(ndomod_sink_fd,sbuf,buflen,ndomod_tls_data);
+#else
 			result=ndo_sink_write(ndomod_sink_fd,sbuf,buflen);
+#endif /* USE_TLS */
 
 			/* an error occurred... */
 			if(result<0){
@@ -780,7 +823,11 @@
 
 	/* write the data */
 	buflen=strlen(buf);
+#ifdef USE_TLS
+	result=ndo_sink_write(ndomod_sink_fd,buf,buflen,ndomod_tls_data);
+#else
 	result=ndo_sink_write(ndomod_sink_fd,buf,buflen);
+#endif /* USE_TLS */
 
 	/* an error occurred... */
 	if(result<0){



------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge

_______________________________________________
Nagios-devel mailing list
Nagios-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nagios-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic