SSL (combined patches, notes)

Bear Giles bear at coyotesong.com
Sun May 26 18:56:27 UTC 2002


Attached is a combined patch.  It is known to compile, but I haven't
been able to test it yet since I lack an SSL-enabled client.  However
I'm fairly confident of the changes having just gone through the same
process with PostgreSQL.

Suggested remaining tasks, besides some extensions mentioned in FIXMEs,
include:

 - track the amount of data transferred to perform periodic 
   renegotiation of the session key (SSL_rehandhake()).

 - use SSL_get_peer() to get verified client certificate, if
   available, and use it to create an additional header line when
   posting articles (X-Auth-Poster?).  This header could use

     X509_NAME_oneline(X509_get_subject_name(peer),...)

   for the full distinguished name, or

     X509_name_get_text_by_NID(X509_get_subject_name(peer),
       NID_commonName,...)
   
   for the client's "common name" alone.

 - use the server's key to generate an HMAC of the body of the 
   message (and most headers?), then include that digest in the 
   headers.  This allows a news administrator to determine if
   a complaint about the content of a message is fradulent since
   the message was changed after transmission.

Sample code for the last two items will be posted soon, but won't
be 'active.'

Bear Giles


-- Attached file included as plaintext by Ecartis --
-- Desc: /tmp/inn6a

Index: inn/nnrpd/article.c
diff -c inn/nnrpd/article.c:1.1.1.1 inn/nnrpd/article.c:1.2
*** inn/nnrpd/article.c:1.1.1.1	Sun May 26 09:49:31 2002
--- inn/nnrpd/article.c	Sun May 26 10:25:59 2002
***************
*** 1,4 ****
! /*  $Id: article.c,v 1.1.1.1 2002/05/26 15:49:31 bear Exp $
  **
  **  Article-related routines.
  */
--- 1,4 ----
! /*  $Id: article.c,v 1.2 2002/05/26 16:25:59 bear Exp $
  **
  **  Article-related routines.
  */
***************
*** 15,20 ****
--- 15,21 ----
  #include "tls.h"
  
  #ifdef HAVE_SSL
+ #include <openssl/e_os.h>
  extern SSL *tls_conn;
  #endif 
  
***************
*** 59,67 ****
  static bool PushIOvHelper(struct iovec* vec, int* countp) {
      int result;
  #ifdef HAVE_SSL
!     result = tls_conn
! 	     ? SSL_writev(tls_conn, vec, *countp)
! 	     : writev(STDOUT_FILENO, vec, *countp);
  #else
      result = writev(STDOUT_FILENO, vec, *countp);
  #endif
--- 60,89 ----
  static bool PushIOvHelper(struct iovec* vec, int* countp) {
      int result;
  #ifdef HAVE_SSL
! 	if (tls_conn) {
! Again:
!       result = SSL_writev(tls_conn, vec, *countp);
! 	  switch (SSL_get_error(tls_conn, result)) {
! 	  case SSL_ERROR_NONE:
! 		break;
! 	  case SSL_ERROR_WANT_WRITE:
! 		goto Again;
! 		break;
! 	  case SSL_ERROR_SYSCALL:
! 		errno = get_last_socket_error();
! 		break;
! 	  case SSL_ERROR_SSL:
! 		SSL_shutdown(tls_conn);
! 		tls_conn = NULL;
! 		errno = ECONNRESET;
! 		break;
! 	  case SSL_ERROR_ZERO_RETURN:
! 	    break;
! 	  }
! 	}
! 	else {
! 	  result = writev(STDOUT_FILENO, vec, *countp);
! 	}
  #else
      result = writev(STDOUT_FILENO, vec, *countp);
  #endif
***************
*** 156,165 ****
  static int		highwater = 0;
  
  static bool PushIOb(void) {
      fflush(stdout);
  #ifdef HAVE_SSL
      if (tls_conn) {
!       if (SSL_write(tls_conn, _IO_buffer_, highwater) != highwater) {
          highwater = 0;
          return FALSE;
        }
--- 178,210 ----
  static int		highwater = 0;
  
  static bool PushIOb(void) {
+ #ifdef HAVE_SSL
+ 	int r;
+ #endif
+ 
      fflush(stdout);
  #ifdef HAVE_SSL
      if (tls_conn) {
! Again:
! 	  r = SSL_write(tls_conn, _IO_buffer_, highwater);
! 	  switch (SSL_get_error(tls_conn, r)) {
! 	  case SSL_ERROR_NONE:
! 		break;
! 	  case SSL_ERROR_WANT_WRITE:
! 		goto Again;
! 		break;
! 	  case SSL_ERROR_SYSCALL:
! 		errno = get_last_socket_error();
! 		break;
! 	  case SSL_ERROR_SSL:
! 		SSL_shutdown(tls_conn);
! 		tls_conn = NULL;
! 		errno = ECONNRESET;
! 		break;
! 	  case SSL_ERROR_ZERO_RETURN:
! 	    break;
! 	  }
! 	  if (r != highwater) {
          highwater = 0;
          return FALSE;
        }
Index: inn/nnrpd/misc.c
diff -c inn/nnrpd/misc.c:1.1.1.1 inn/nnrpd/misc.c:1.3
*** inn/nnrpd/misc.c:1.1.1.1	Sun May 26 09:49:31 2002
--- inn/nnrpd/misc.c	Sun May 26 11:50:12 2002
***************
*** 1,4 ****
! /*  $Id: misc.c,v 1.1.1.1 2002/05/26 15:49:31 bear Exp $
  **
  **  Miscellaneous support routines.
  */
--- 1,4 ----
! /*  $Id: misc.c,v 1.3 2002/05/26 17:50:12 bear Exp $
  **
  **  Miscellaneous support routines.
  */
***************
*** 16,21 ****
--- 16,22 ----
  #include "sasl_config.h"
  
  #ifdef HAVE_SSL
+ #include <openssl/e_os.h>
  extern SSL *tls_conn;
  extern int nnrpd_starttls_done;
  #endif 
***************
*** 271,278 ****
  	    if (i == 0 || !FD_ISSET(STDIN_FILENO, &rmask))
  		return RTtimeout;
  #ifdef HAVE_SSL
! 	    if (tls_conn)
  	      count = SSL_read(tls_conn, buffer, sizeof buffer);
  	    else
  	      count = read(STDIN_FILENO, buffer, sizeof buffer);
  #else
--- 272,297 ----
  	    if (i == 0 || !FD_ISSET(STDIN_FILENO, &rmask))
  		return RTtimeout;
  #ifdef HAVE_SSL
! 	    if (tls_conn) {
  	      count = SSL_read(tls_conn, buffer, sizeof buffer);
+ 		  switch (SSL_get_error(tls_conn, count)) {
+ 		  case SSL_ERROR_NONE:
+ 			break;
+ 		  case SSL_ERROR_WANT_READ:
+ 			goto Again;
+ 			break;
+ 		  case SSL_ERROR_SYSCALL:
+ 			errno = get_last_socket_error();
+ 			break;
+ 		  case SSL_ERROR_SSL:
+ 			SSL_shutdown(tls_conn);
+ 			tls_conn = NULL;
+ 			errno = ECONNRESET;
+ 			break;
+ 		  case SSL_ERROR_ZERO_RETURN:
+ 			break;
+ 		  }
+ 		}
  	    else
  	      count = read(STDIN_FILENO, buffer, sizeof buffer);
  #else
***************
*** 644,668 ****
        return;
      }
  
-   result=tls_init_serverengine(5,        /* depth to verify */
- 			       1,        /* can client auth? */
- 			       0,        /* required client to auth? */
- 			       (char *)sasl_config_getstring("tls_ca_file", ""),
- 			       (char *)sasl_config_getstring("tls_ca_path", ""),
- 			       (char *)sasl_config_getstring("tls_cert_file", ""),
- 			       (char *)sasl_config_getstring("tls_key_file", ""));
- 
-   if (result == -1) {
-     Reply("%d Error initializing TLS\r\n", NNTP_STARTTLS_BAD_VAL);
-     
-     syslog(L_ERROR, "error initializing TLS: "
- 	   "[CA_file: %s] [CA_path: %s] [cert_file: %s] [key_file: %s]",
- 	   (char *) sasl_config_getstring("tls_ca_file", ""),
- 	   (char *) sasl_config_getstring("tls_ca_path", ""),
- 	   (char *) sasl_config_getstring("tls_cert_file", ""),
- 	   (char *) sasl_config_getstring("tls_key_file", ""));
-     return;
-   }
    Reply("%d Begin TLS negotiation now\r\n", NNTP_STARTTLS_NEXT_VAL);
    (void)fflush(stdout);
  
--- 663,668 ----
Index: inn/nnrpd/nnrpd.c
diff -c inn/nnrpd/nnrpd.c:1.1.1.1 inn/nnrpd/nnrpd.c:1.5
*** inn/nnrpd/nnrpd.c:1.1.1.1	Sun May 26 09:49:31 2002
--- inn/nnrpd/nnrpd.c	Sun May 26 12:12:48 2002
***************
*** 1,4 ****
! /*  $Id: nnrpd.c,v 1.1.1.1 2002/05/26 15:49:31 bear Exp $
  **
  **  NNTP server for readers (NNRP) for InterNetNews.
  **
--- 1,4 ----
! /*  $Id: nnrpd.c,v 1.5 2002/05/26 18:12:48 bear Exp $
  **
  **  NNTP server for readers (NNRP) for InterNetNews.
  **
***************
*** 31,36 ****
--- 31,37 ----
  #include "sasl_config.h"
  
  #ifdef HAVE_SSL
+ #include <openssl/e_os.h>
  extern SSL *tls_conn;
  int nnrpd_starttls_done = 0;
  #endif 
***************
*** 202,207 ****
--- 203,215 ----
          syslog(L_NOTICE, "%s overstats count %d hit %d miss %d time %d size %d dbz %d seek %d get %d artcheck %d", ClientHost,
              OVERcount, OVERhit, OVERmiss, OVERtime, OVERsize, OVERdbz, OVERseek, OVERget, OVERartcheck);
  
+ #ifdef HAVE_SSL
+ 	if (tls_conn) {
+ 	  SSL_shutdown(tls_conn);
+ 	  SSL_free(tls_conn);
+ 	  tls_conn = NULL;
+ 	} 
+ #endif
       if (DaemonMode) {
       	shutdown(STDIN_FILENO, 2);
       	shutdown(STDOUT_FILENO, 2);
***************
*** 649,659 ****
      char        buff[2048];
  
  #ifdef HAVE_SSL
      if (tls_conn) {
        va_start(args, fmt);
        vsprintf(buff,fmt, args);
        va_end(args);
!       SSL_write(tls_conn, buff, strlen(buff));
      } else {
        va_start(args, fmt);
        vprintf(fmt, args);
--- 657,688 ----
      char        buff[2048];
  
  #ifdef HAVE_SSL
+ 	int			r;
+ 
      if (tls_conn) {
        va_start(args, fmt);
+ 	  /* FIXME: use vsnprintf() - does it exist? */
        vsprintf(buff,fmt, args);
        va_end(args);
! Again:
!       r = SSL_write(tls_conn, buff, strlen(buff));
! 	  switch (SSL_get_error(tls_conn, r)) {
! 	  case SSL_ERROR_NONE:
! 		break;
! 	  case SSL_ERROR_WANT_WRITE:
! 		goto Again;
! 		break;
! 	  case SSL_ERROR_SYSCALL:
! 		errno = get_last_socket_error();
! 		break;
! 	  case SSL_ERROR_SSL:
! 		SSL_shutdown(tls_conn);
! 		tls_conn = NULL;
! 		errno = ECONNRESET;
! 		break;
! 	  case SSL_ERROR_ZERO_RETURN:
! 		break;
! 	  }
      } else {
        va_start(args, fmt);
        vprintf(fmt, args);
***************
*** 670,675 ****
--- 699,705 ----
  
          /* Copy output, but strip trailing CR-LF.  Note we're assuming here
             that no output line can ever be longer than 2045 characters. */
+ 	    /* FIXME: use vsnprintf() - does it exist? */
          vsprintf(buff, fmt, args);
          va_end(args);
          p = buff + strlen(buff) - 1;
***************
*** 687,698 ****
  {
      va_list     args;
      char        buff[2048];
  
      if (tls_conn) {
        va_start(args, fmt);
        vsprintf(buff, fmt, args);
        va_end(args);
!       SSL_write(tls_conn, buff, strlen(buff));
      } else {
        va_start(args, fmt);
        vprintf(fmt, args);
--- 717,748 ----
  {
      va_list     args;
      char        buff[2048];
+ 	int			r;
  
      if (tls_conn) {
        va_start(args, fmt);
+ 	  /* FIXME: use vsnprintf() - does it exist? */
        vsprintf(buff, fmt, args);
        va_end(args);
! Again:
!       r = SSL_write(tls_conn, buff, strlen(buff));
! 	  switch (SSL_get_error(tls_conn, r)) {
! 	  case SSL_ERROR_NONE:
! 		break;
! 	  case SSL_ERROR_WANT_WRITE:
! 		goto Again;
! 		break;
! 	  case SSL_ERROR_SYSCALL:
! 		errno = get_last_socket_error();
! 		break;
! 	  case SSL_ERROR_SSL:
! 		SSL_shutdown(tls_conn);
! 		tls_conn = NULL;
! 		errno = ECONNRESET;
! 		break;
! 	  case SSL_ERROR_ZERO_RETURN:
! 		break;
! 	  }
      } else {
        va_start(args, fmt);
        vprintf(fmt, args);
***************
*** 950,955 ****
--- 1000,1033 ----
          NNRPACCESS = concatpath(innconf->pathetc,_PATH_NNRPACCESS);
      SPOOLlen = strlen(innconf->patharticles);
  
+ #ifdef HAVE_SSL
+     /*
+      * if we have a SSL session, either initially or after
+      * STARTTLS, make sure we can before proceeding.  The
+      * SSL_CTX object may be expensive to initialize, but it
+      * can be shared by all child processes
+      */
+     sasl_config_read();
+     ssl_result=tls_init_serverengine(5,        /* depth to verify */
+ 				     0,        /* can client auth? */
+ 				     0,        /* required client to auth? */
+ 				     (char *)sasl_config_getstring("tls_ca_file", ""),
+ 				     (char *)sasl_config_getstring("tls_ca_path", ""),
+ 				     (char *)sasl_config_getstring("tls_cert_file", ""),
+ 				     (char *)sasl_config_getstring("tls_key_file", ""));
+     if (ssl_result == -1) {
+       Reply("%d Error initializing TLS\r\n", NNTP_STARTTLS_BAD_VAL);
+ 	
+       syslog(L_ERROR, "error initializing TLS: "
+ 	     "[CA_file: %s] [CA_path: %s] [cert_file: %s] [key_file: %s]",
+ 	     (char *) sasl_config_getstring("tls_ca_file", ""),
+ 	     (char *) sasl_config_getstring("tls_ca_path", ""),
+ 	     (char *) sasl_config_getstring("tls_cert_file", ""),
+ 	     (char *) sasl_config_getstring("tls_key_file", ""));
+       ExitWithStats(1, FALSE);
+     }
+ #endif
+ 
      if (DaemonMode) {
  
  #ifdef HAVE_INET6
***************
*** 1140,1165 ****
  #ifdef HAVE_SSL
      ClientSSL = FALSE;
      if (initialSSL) {
-       sasl_config_read();
-       ssl_result=tls_init_serverengine(5,        /* depth to verify */
- 				       0,        /* can client auth? */
- 				       0,        /* required client to auth? */
- 				       (char *)sasl_config_getstring("tls_ca_file", ""),
- 				       (char *)sasl_config_getstring("tls_ca_path", ""),
- 				       (char *)sasl_config_getstring("tls_cert_file", ""),
- 				       (char *)sasl_config_getstring("tls_key_file", ""));
-       if (ssl_result == -1) {
- 	Reply("%d Error initializing TLS\r\n", NNTP_STARTTLS_BAD_VAL);
- 	
- 	syslog(L_ERROR, "error initializing TLS: "
- 	       "[CA_file: %s] [CA_path: %s] [cert_file: %s] [key_file: %s]",
- 	       (char *) sasl_config_getstring("tls_ca_file", ""),
- 	       (char *) sasl_config_getstring("tls_ca_path", ""),
- 	       (char *) sasl_config_getstring("tls_cert_file", ""),
- 	       (char *) sasl_config_getstring("tls_key_file", ""));
- 	ExitWithStats(1, FALSE);
-       }
- 
        ssl_result=tls_start_servertls(0, /* read */
  				     1); /* write */
        if (ssl_result==-1) {
--- 1218,1223 ----
Index: inn/nnrpd/tls.c
diff -c inn/nnrpd/tls.c:1.1.1.1 inn/nnrpd/tls.c:1.7
*** inn/nnrpd/tls.c:1.1.1.1	Sun May 26 09:49:30 2002
--- inn/nnrpd/tls.c	Sun May 26 12:20:11 2002
***************
*** 30,35 ****
--- 30,36 ----
  #include <string.h>
  #include <syslog.h>
  #include <sys/uio.h>
+ #include <sys/stat.h>
  
  /* taken from lib/parsedate.c */
  #ifndef WRITEV_USE_ALLOCA
***************
*** 142,147 ****
--- 143,154 ----
  
  /* taken from OpenSSL apps/s_cb.c */
  
+ /*
+  *	Generate empheral RSA key.  Because of the cost of generating
+  *	ERSA keys (and the consequent caching), it is deprecated in favor
+  *	of EDH keys.
+  */
+ /*
  static RSA *tmp_rsa_cb(SSL * s UNUSED, int export UNUSED, int keylength)
  {
      static RSA *rsa_tmp = NULL;
***************
*** 151,157 ****
--- 158,284 ----
      }
      return (rsa_tmp);
  }
+ */
+ 
+ /*
+  *	Hardcoded DH parameter files, from OpenSSL.
+  *	For information on how these files were generated, see
+  *	"Assigned Number for SKIP Protocols" 
+  *	(http://www.skip-vpn.org/spec/numbers.html.
+  */
+ static const char file_dh512[] =
+ "-----BEGIN DH PARAMETERS-----\n\
+ MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
+ XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
+ -----END DH PARAMETERS-----\n";
+ 
+ static const char file_dh1024[] =
+ "-----BEGIN DH PARAMETERS-----\n\
+ MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
+ jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
+ ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
+ -----END DH PARAMETERS-----\n";
+ 
+ static const char file_dh2048[] =
+ "-----BEGIN DH PARAMETERS-----\n\
+ MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
+ 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
+ T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
+ zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
+ Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
+ CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
+ -----END DH PARAMETERS-----\n";
+ 
+ static const char file_dh4096[] =
+ "-----BEGIN DH PARAMETERS-----\n\
+ MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
+ l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
+ Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
+ Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
+ VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
+ alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
+ sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
+ ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
+ OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
+ AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
+ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
+ -----END DH PARAMETERS-----\n";
+ 
+ /*
+  *	Load hardcoded DH parameters.
+  */
+ static DH *
+ load_dh_buffer (const char *buffer, size_t len)
+ {
+ 	BIO *bio;
+ 	DH *dh = NULL;
+ 
+ 	bio = BIO_new_mem_buf((char *) buffer, len);
+ 	if (bio == NULL)
+ 		return NULL;
+ 	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+ /*	if (dh == NULL) log error */
+ 	BIO_free(bio);
+ 
+ 	return dh;
+ }
  
+ /*
+  *	Generate empheral DH key.  Because this can take a long
+  *	time to compute, we use precomputed parameters of the
+  *	common key sizes.
+  *
+  *	These values can be static (once loaded or computed) since
+  *	the OpenSSL library can effectively generate random keys
+  *	from the information provided.
+  *
+  *	EDH keying is slightly less efficient than static RSA keying,
+  *	but it offers Perfect Forward Secrecy (PFS).
+  *
+  *	FIXME: support user-specified files, to eliminate risk of
+  *	"small group" attacks.
+  */
+ static DH *tmp_dh_cb(SSL *s UNUSED, int export UNUSED, int keylength)
+ {
+ 	DH *r = NULL;
+ 	static DH *dh = NULL;
+ 	static DH *dh512 = NULL;
+ 	static DH *dh1024 = NULL;
+ 	static DH *dh2048 = NULL;
+ 	static DH *dh4096 = NULL;
+ 
+ 	switch (keylength)
+ 	{
+ 	case 512:
+ 		if (dh512 == NULL)
+ 			dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
+ 		r = dh512;
+ 		break;
+ 	case 1024:
+ 		if (dh1024 == NULL)
+ 			dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
+ 		r = dh1024;
+ 		break;
+ 	case 2048:
+ 		if (dh2048 == NULL)
+ 			dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
+ 		r = dh2048;
+ 		break;
+ 	case 4096:
+ 		if (dh4096 == NULL)
+ 			dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
+ 		r = dh4096;
+ 		break;
+ 	default:
+ 		/* we should check current keylength vs. requested keylength* /
+ 		/* also, this is an extremely expensive operation! */
+ 		dh = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
+ 		r = dh;
+ 	}
+ 
+ 	return r;
+ }
+ 
  /* taken from OpenSSL apps/s_cb.c */
  
  static int verify_callback(int ok, X509_STORE_CTX * ctx)
***************
*** 291,296 ****
--- 418,425 ----
  
  static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
  {
+     struct stat buf;
+ 
      if (cert_file != NULL) {
  	if (SSL_CTX_use_certificate_file(ctx, cert_file,
  					 SSL_FILETYPE_PEM) <= 0) {
***************
*** 299,304 ****
--- 428,446 ----
  	}
  	if (key_file == NULL)
  	    key_file = cert_file;
+ 
+ 	/* check ownership and permissions of key file */
+ 	if (lstat(key_file, &buf) == -1) {
+ 	    syslog(L_ERROR, "unable to stat private key '%s'", cert_file);
+ 	    return (0);
+ 	}
+ 	if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) != 0 ||
+ 	    buf.st_uid != getuid()) {
+ 	    syslog(L_ERROR, "bad ownership or permissions on private key '%s'", 
+ 		  cert_file);
+ 	    return (0);
+ 	}
+ 
  	if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
  					SSL_FILETYPE_PEM) <= 0) {
  	    syslog(L_ERROR, "unable to get private key from '%s'", key_file);
***************
*** 340,345 ****
--- 482,488 ----
      char   *CAfile;
      char   *s_cert_file;
      char   *s_key_file;
+     struct stat buf;
  
      if (tls_serverengine)
        return (0);				/* already running */
***************
*** 390,397 ****
  	Printf("TLS engine: cannot load cert/key data\n");
        return (-1);
      }
-     SSL_CTX_set_tmp_rsa_callback(CTX, tmp_rsa_cb);
  
      verify_depth = verifydepth;
      if (askcert!=0)
  	verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
--- 533,549 ----
  	Printf("TLS engine: cannot load cert/key data\n");
        return (-1);
      }
  
+     /* load some randomization data from /dev/urandom, if it exists */
+     /* FIXME: should also check for ".rand" file, update it on exit */
+     if (stat("/dev/urandom", &buf) == 0) {
+       RAND_load_file("/dev/urandom", 16 * 1024);
+     }
+ 
+ /*  SSL_CTX_set_tmp_rsa_callback(CTX, tmp_rsa_cb); */
+     SSL_CTX_set_tmp_dh_callback(CTX, tmp_dh_cb);
+     SSL_CTX_set_options(CTX, SSL_OP_SINGLE_DH_USE);
+ 
      verify_depth = verifydepth;
      if (askcert!=0)
  	verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
***************
*** 475,481 ****
        return (-1);
      }
      
- 
      /*
       * This is the actual handshake routine. It will do all the negotiations
       * and will check the client cert etc.
--- 627,632 ----




More information about the inn-patches mailing list