Problem with OpenSSL

Joshua Kwan joshk at triplehelix.org
Fri Jun 25 13:13:43 EDT 2004


On Fri, Jun 25, 2004 at 06:08:54PM +0200, pcgod at chatjunkies.org wrote:
> afik, hybrid doesn't support client SSL connections. It does support
> server to server SSL connections. The Chatjunkies ircd development team
> (well, I guess that's just me) has plans to patch ircd-hybrid-7.0.3
> (when it's released) for client SSL connections (if there isn't such a
> patch available already). Once that's done, I have plans to post it
> here. Unfortunately, I'm leaving for vacation.... now, so it's not going
> to get done anytime soon. btw, if there is already such a patch
> available, please let me know so I can save some work :-)

I have a patch already, but you must debug it.

I ripped support from ircd-hybrid-7-bg verbatim. The problem is that
after a long time, SSL clients will lag more and more and more until IRC
is unuseable. It seems to only affect incoming packets (to the server)
from a SSL enabled client.

This patch applies clean to 7.0.2, and will probably do so for 7.0.3
with some minor changes (i.e. $Id$ desync in the patch.)

-- 
Joshua Kwan
-------------- next part --------------
diff -ur clean/autoconf/configure.in ircd-hybrid-7.0/autoconf/configure.in
--- clean/autoconf/configure.in	2003-05-31 00:30:23.000000000 -0700
+++ ircd-hybrid-7.0/autoconf/configure.in	2004-02-15 23:38:13.000000000 -0800
@@ -421,7 +421,7 @@
                 cf_openssl_ciphers="${cf_openssl_ciphers}DES/56 ")
         fi
         CPPFLAGS="$save_CPPFLAGS"
-        SSL_LIBS="$SSL_LIBS -lcrypto"
+        SSL_LIBS="$SSL_LIBS -lcrypto -lssl"
     else
         AC_MSG_RESULT(no - OpenSSL support disabled)
     fi
diff -ur clean/configure ircd-hybrid-7.0/configure
--- clean/configure	2003-05-31 00:30:18.000000000 -0700
+++ ircd-hybrid-7.0/configure	2004-02-16 00:18:55.000000000 -0800
@@ -1877,13 +1877,13 @@
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
   if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
+    CFLAGS="-g -O0"
   else
     CFLAGS="-g"
   fi
 else
   if test "$GCC" = yes; then
-    CFLAGS="-O2"
+    CFLAGS="-O0"
   else
     CFLAGS=
   fi
@@ -2085,7 +2085,7 @@
 if test "x$GCC" = "xyes"; then
 #  Use this for development..
 #  IRC_CFLAGS="-O2 -g -Wunused -Wall -Wshadow -Wmissing-declarations"
-   IRC_CFLAGS="-O2 -g "
+   IRC_CFLAGS="-O0 -g "
 else
   if test "x$TenDRA" = "xyes"; then
             IRC_CFLAGS=""
@@ -5860,7 +5860,7 @@
 
         fi
         CPPFLAGS="$save_CPPFLAGS"
-        SSL_LIBS="$SSL_LIBS -lcrypto"
+        SSL_LIBS="$SSL_LIBS -lcrypto -lssl"
     else
         echo "$as_me:$LINENO: result: no - OpenSSL support disabled" >&5
 echo "${ECHO_T}no - OpenSSL support disabled" >&6
diff -ur clean/doc/example.conf ircd-hybrid-7.0/doc/example.conf
--- clean/doc/example.conf	2003-05-31 00:30:25.000000000 -0700
+++ ircd-hybrid-7.0/doc/example.conf	2004-02-15 23:38:35.000000000 -0800
@@ -86,6 +86,20 @@
 	 *	chmod 0644 rsa.pub
 	 */
 	#rsa_private_key_file = "/usr/local/ircd/etc/rsa.key";
+	
+	/* SSL certificate file, used for client SSL connections
+	 *
+	 * Assuming your private RSA key is stored in rsa.key, you
+	 * must first create a certificate request, then sign it:
+	 *
+	 *  openssl req -new -key rsa.key -out cert.csr
+	 *  openssl x509 -req -in cert.csr -extensions v3_ca \
+	 *   -signkey rsa.key -out cert.pem -trustout
+	 *												-demond
+     *
+     * (see http://www.openssl.org//docs/HOWTO/certificates.txt)
+	 */
+	#ssl_certificate_file = "/usr/local/ircd/etc/cert.pem";
 };
 
 /* admin {}: contains admin information about the server. (OLD A:) */
@@ -169,6 +183,11 @@
 	
 	/* port: listen on all available IPs, ports 6665 to 6669 */
 	port = 6665 .. 6669;
+	
+	/* sslport: listen for client SSL connections ONLY!
+	 *											-demond
+	 */
+	sslport = 8181;
 
 	/* host: set a specific IP/host the ports after the line will listen 
 	 * on.  This may be ipv4 or ipv6.
diff -ur clean/include/channel_mode.h ircd-hybrid-7.0/include/channel_mode.h
--- clean/include/channel_mode.h	2002-10-28 13:09:20.000000000 -0800
+++ ircd-hybrid-7.0/include/channel_mode.h	2004-02-16 02:21:32.000000000 -0800
@@ -100,6 +100,7 @@
 #define MODE_EXCEPTION  0x0800
 #define MODE_INVEX	0x2000
 #define MODE_HIDEOPS    0x4000
+#define MODE_SSLONLY	0x20000	/* only SSL-connected clients allowed */
 
 /*
  * mode flags which take another parameter (With PARAmeterS)
@@ -118,6 +119,7 @@
 #define ParanoidChannel(x)	((x) && ((x)->mode.mode &\
 			        (MODE_PRIVATE|MODE_INVITEONLY))==\
 		                (MODE_PRIVATE|MODE_INVITEONLY))
+#define SSLonlyChannel(x)	((x) && ((x)->mode.mode & MODE_SSLONLY))
 
 struct ChModeChange
 {
diff -ur clean/include/fdlist.h ircd-hybrid-7.0/include/fdlist.h
--- clean/include/fdlist.h	2002-05-24 16:34:07.000000000 -0700
+++ ircd-hybrid-7.0/include/fdlist.h	2004-02-15 23:39:46.000000000 -0800
@@ -25,6 +25,7 @@
 #ifndef INCLUDED_fdlist_h
 #define INCLUDED_fdlist_h
 
+#include "stdinc.h"
 #include "config.h"
 #include "ircd_defs.h"
 #include "res.h"
@@ -115,6 +116,10 @@
         unsigned int nonblocking:1;
         unsigned int ipc:1;
         unsigned int called_connect:1;
+#ifdef HAVE_LIBCRYPTO
+		unsigned int accept_read:1;
+		unsigned int accept_write:1;
+#endif        
     } flags;
     struct {
         /* We don't need the host here ? */
@@ -124,6 +129,10 @@
         void *data;
         /* We'd also add the retry count here when we get to that -- adrian */
     } connect;
+#ifdef HAVE_LIBCRYPTO
+	SSL *ssl;
+	int accept_failures;
+#endif
 };
 
 
@@ -131,7 +140,7 @@
 
 void fdlist_init(void);
 
-extern void  fd_open(int, unsigned int, const char *);
+extern void  fd_open(int, unsigned int, const char *, void *);
 extern void  fd_close(int);
 extern void  fd_dump(struct Client *source_p);
 #ifndef __GNUC__
diff -ur clean/include/listener.h ircd-hybrid-7.0/include/listener.h
--- clean/include/listener.h	2002-05-24 16:34:07.000000000 -0700
+++ ircd-hybrid-7.0/include/listener.h	2004-02-15 23:41:28.000000000 -0800
@@ -45,9 +45,10 @@
   struct irc_inaddr addr;              /* virtual address or INADDR_ANY */
   struct DNSQuery   *dns_query;
   char             vhost[HOSTLEN + 1]; /* virtual name of listener */
+  int	is_ssl;
 };
 
-extern void        add_listener(int port, const char* vaddr_ip);
+extern void        add_listener(int port, const char* vaddr_ip, int is_ssl);
 extern void        close_listener(struct Listener* listener);
 extern void        close_listeners(void);
 extern const char* get_listener_name(const struct Listener* listener);
diff -ur clean/include/numeric.h ircd-hybrid-7.0/include/numeric.h
--- clean/include/numeric.h	2002-11-27 07:46:24.000000000 -0800
+++ ircd-hybrid-7.0/include/numeric.h	2004-02-16 02:21:51.000000000 -0800
@@ -194,6 +194,7 @@
 
 /* numeric_replies */
 
+#define RPL_WHOISSSL         297 /* uses SSL */
 #define RPL_NONE             300
 #define RPL_AWAY             301
 #define RPL_USERHOST         302
@@ -391,6 +392,7 @@
 /* 	ERR_LINKFAIL	     479	unreal */
 /*	ERR_CANNOTKNOCK	     480	unreal */
 /*	ERR_NOULINE	     480	austnet */
+#define ERR_SSLONLYCHAN      480
 #define ERR_NOPRIVILEGES     481
 #define ERR_CHANOPRIVSNEEDED 482
 #define ERR_CANTKILLSERVER   483
diff -ur clean/include/s_bsd.h ircd-hybrid-7.0/include/s_bsd.h
--- clean/include/s_bsd.h	2003-01-19 05:19:50.000000000 -0800
+++ ircd-hybrid-7.0/include/s_bsd.h	2004-02-15 23:51:19.000000000 -0800
@@ -70,7 +70,7 @@
 extern const char * comm_errstr(int status);
 extern int   comm_open(int family, int sock_type, int proto,
                  const char *note);
-extern int   comm_accept(int fd, struct irc_sockaddr *pn);
+extern int   comm_accept(int fd, struct irc_sockaddr *pn, int is_ssl);
 
 /* These must be defined in the network IO loop code of your choice */
 extern void  comm_setselect(int fd, fdlist_t list, unsigned int type,
diff -ur clean/include/s_conf.h ircd-hybrid-7.0/include/s_conf.h
--- clean/include/s_conf.h	2003-02-15 16:22:21.000000000 -0800
+++ ircd-hybrid-7.0/include/s_conf.h	2004-02-15 23:51:29.000000000 -0800
@@ -284,6 +284,9 @@
 #ifdef HAVE_LIBCRYPTO
   char *      rsa_private_key_file;
   RSA *       rsa_private_key;
+  char *      ssl_certificate_file;
+  SSL_CTX *   ctx;
+  SSL_METHOD *meth;
 #endif
   int         hub;
   struct      irc_inaddr ip;
diff -ur clean/include/stdinc.h ircd-hybrid-7.0/include/stdinc.h
--- clean/include/stdinc.h	2002-05-24 16:39:13.000000000 -0700
+++ ircd-hybrid-7.0/include/stdinc.h	2004-02-15 23:55:32.000000000 -0800
@@ -99,3 +99,8 @@
 #ifdef VMS
 #include <sys/ioctl.h>
 #endif
+
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
diff -ur clean/modules/core/m_sjoin.c ircd-hybrid-7.0/modules/core/m_sjoin.c
--- clean/modules/core/m_sjoin.c	2002-07-04 09:07:23.000000000 -0700
+++ ircd-hybrid-7.0/modules/core/m_sjoin.c	2004-02-16 02:24:12.000000000 -0800
@@ -178,6 +178,9 @@
       case 't':
         mode.mode |= MODE_TOPICLIMIT;
         break;
+      case 'S':
+	mode.mode |= MODE_SSLONLY;
+	break;
 #ifdef ANONOPS
       case 'a':
 	if(ConfigChannel.use_anonops)
@@ -737,6 +740,7 @@
   { MODE_MODERATED,  'm' },
   { MODE_INVITEONLY, 'i' },
   { MODE_PRIVATE,    'p' },
+  { MODE_SSLONLY,    'S' },
 #ifdef ANONOPS
   { MODE_HIDEOPS,    'a' },
 #endif
diff -ur clean/modules/m_whois.c ircd-hybrid-7.0/modules/m_whois.c
--- clean/modules/m_whois.c	2003-02-08 16:02:28.000000000 -0800
+++ ircd-hybrid-7.0/modules/m_whois.c	2004-02-16 02:25:12.000000000 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "stdinc.h"
+#include "fdlist.h"
 #include "tools.h"
 #include "common.h"  
 #include "handlers.h"
@@ -460,6 +461,17 @@
     sendto_one(source_p, form_str(RPL_WHOISOPERATOR),
 	       me.name, source_p->name, target_p->name);
 
+#ifdef HAVE_LIBCRYPTO
+  if (MyClient(target_p)) {
+        int fd = target_p->localClient->fd;
+        fde_t *F = (fd > -1)? &fd_table[fd] : NULL;
+        
+        if (F && F->ssl)
+                sendto_one(source_p, form_str(RPL_WHOISSSL),
+                        me.name, source_p->name, target_p->name);
+  }
+#endif
+
   if (MyConnect(target_p)) /* Can't do any of this if not local! db */
   {
     if ( (glob) ||
@@ -582,6 +594,15 @@
             return;
           }
 	}
+	
+  if (MyClient(target_p)) {
+  	int fd = target_p->localClient->fd;
+  	fde_t *F = (fd > -1)? &fd_table[fd] : NULL;
+  	
+  	if (F && F->ssl)
+  		sendto_one(source_p, form_str(RPL_WHOISSSL),
+  			me.name, source_p->name, target_p->name);	
+  }
 
 	/* the client doesnt exist.. erk! */
 	else
diff -ur clean/src/channel.c ircd-hybrid-7.0/src/channel.c
--- clean/src/channel.c	2003-05-28 21:02:36.000000000 -0700
+++ ircd-hybrid-7.0/src/channel.c	2004-02-16 02:25:32.000000000 -0800
@@ -23,7 +23,7 @@
  */
 
 #include "stdinc.h"
-
+#include "fdlist.h"
 #include "tools.h"
 #include "channel.h"
 #include "channel_mode.h"
@@ -1129,6 +1129,22 @@
   if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
     return (ERR_CHANNELISFULL);
 
+  if (SSLonlyChannel(chptr)) 
+  {
+#ifdef HAVE_LIBCRYPTO
+       if (MyClient(source_p)) {
+               int fd = source_p->localClient->fd;
+               fde_t *F = (fd > -1)? &fd_table[fd] : NULL;
+       
+               if (F && !F->ssl)
+                       return (ERR_SSLONLYCHAN);
+       }
+#else
+       return (ERR_SSLONLYCHAN);       /* deny everyone on a non SSL-enabled se
+rver */
+#endif  
+  }
+
   return 0;
 }
 
diff -ur clean/src/channel_mode.c ircd-hybrid-7.0/src/channel_mode.c
--- clean/src/channel_mode.c	2003-04-19 19:33:41.000000000 -0700
+++ ircd-hybrid-7.0/src/channel_mode.c	2004-02-16 02:19:53.000000000 -0800
@@ -499,6 +499,10 @@
   if (chptr->mode.mode & MODE_HIDEOPS)
     *mbuf++ = 'a';
 #endif
+#ifdef HAVE_LIBCRYPTO
+  if (chptr->mode.mode & MODE_SSLONLY)
+    *mbuf++ = 'S';
+#endif
   if (chptr->mode.limit)
   {
     *mbuf++ = 'l';
@@ -1850,7 +1854,7 @@
   {chm_nosuch, NULL},                             /* P */
   {chm_nosuch, NULL},                             /* Q */
   {chm_nosuch, NULL},                             /* R */
-  {chm_nosuch, NULL},                             /* S */
+  {chm_simple, (void*)MODE_SSLONLY},              /* S */
   {chm_nosuch, NULL},                             /* T */
   {chm_nosuch, NULL},                             /* U */
   {chm_nosuch, NULL},                             /* V */
diff -ur clean/src/fdlist.c ircd-hybrid-7.0/src/fdlist.c
--- clean/src/fdlist.c	2002-06-15 00:19:56.000000000 -0700
+++ ircd-hybrid-7.0/src/fdlist.c	2004-02-15 23:39:01.000000000 -0800
@@ -81,7 +81,7 @@
 
 /* Called to open a given filedescriptor */
 void
-fd_open(int fd, unsigned int type, const char *desc)
+fd_open(int fd, unsigned int type, const char *desc, void *ssl)
 {
   fde_t *F = &fd_table[fd];
   assert(fd >= 0);
@@ -111,6 +111,9 @@
   if (desc)
     strncpy(F->desc, desc, FD_DESC_SZ);
   number_fd++;
+#ifdef HAVE_LIBCRYPTO
+  F->ssl = (SSL *)ssl;
+#endif
 }
 
 
@@ -139,6 +142,17 @@
   number_fd--;
   memset(F, '\0', sizeof(fde_t));
   F->timeout = 0;
+  
+#ifdef HAVE_LIBCRYPTO
+  F->flags.accept_read = 0;
+  F->flags.accept_write = 0;
+  F->accept_failures = 0;
+  if (F->ssl) {
+  	SSL_shutdown(F->ssl);
+  	SSL_free(F->ssl);
+  	F->ssl = NULL;
+  }
+#endif
   /* Unlike squid, we're actually closing the FD here! -- adrian */
   close(fd);
 }
diff -ur clean/src/fileio.c ircd-hybrid-7.0/src/fileio.c
--- clean/src/fileio.c	2003-05-28 22:13:26.000000000 -0700
+++ ircd-hybrid-7.0/src/fileio.c	2004-02-15 23:40:04.000000000 -0800
@@ -50,7 +50,7 @@
         errno = ENFILE;
         fd = -1;
     } else if (fd >= 0)
-        fd_open(fd, FD_FILE, filename);
+        fd_open(fd, FD_FILE, filename, NULL);
     
     return fd;
 }
diff -ur clean/src/ircd.c ircd-hybrid-7.0/src/ircd.c
--- clean/src/ircd.c	2003-05-28 22:13:26.000000000 -0700
+++ ircd-hybrid-7.0/src/ircd.c	2004-02-16 00:28:13.000000000 -0800
@@ -658,6 +658,19 @@
   init_resolver();      /* Needs to be setup before the io loop */
 #ifdef HAVE_LIBCRYPTO
   bio_spare_fd=save_spare_fd("SSL private key validation");
+  SSL_load_error_strings();
+  SSLeay_add_ssl_algorithms();
+  ServerInfo.meth = SSLv23_server_method();
+  ServerInfo.ctx = SSL_CTX_new(ServerInfo.meth);
+  if (!ServerInfo.ctx) {
+       fprintf(stderr, "Could not initialize the SSL context -- %s\n",
+               ERR_error_string(ERR_get_error(), NULL));
+  }
+  SSL_CTX_set_options(ServerInfo.ctx, SSL_OP_NO_SSLv2);
+  SSL_CTX_set_options(ServerInfo.ctx, SSL_OP_TLS_ROLLBACK_BUG|SSL_OP_ALL);
+  /*SSL_CTX_set_verify(ServerInfo.ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, 
+NULL);*/
+  SSL_CTX_set_verify(ServerInfo.ctx, SSL_VERIFY_NONE, NULL);
 #endif /* HAVE_LIBCRYPTO */
   read_conf_files(YES);         /* cold start init conf files */
 #ifndef STATIC_MODULES
diff -ur clean/src/ircd_lexer.l ircd-hybrid-7.0/src/ircd_lexer.l
--- clean/src/ircd_lexer.l	2002-10-30 09:44:56.000000000 -0800
+++ ircd-hybrid-7.0/src/ircd_lexer.l	2004-02-15 23:40:34.000000000 -0800
@@ -233,6 +233,7 @@
 ping_cookie	{ return PING_COOKIE; }
 ping_time	{ return PING_TIME; }
 port		{ return PORT; }
+sslport		{ return SSLPORT; }
 quiet_on_ban    { return QUIET_ON_BAN; }
 reason		{ return REASON; }
 redirport       { return REDIRPORT; }
@@ -244,6 +245,7 @@
 resv		{ return RESV; }
 rsa_private_key_file		{ return RSA_PRIVATE_KEY_FILE; }
 rsa_public_key_file		{ return RSA_PUBLIC_KEY_FILE; }
+ssl_certificate_file	{ return SSL_CERTIFICATE_FILE; }
 send_password	{ return SEND_PASSWORD; }
 sendq		{ return SENDQ; }
 serverhide	{ return SERVERHIDE; }
diff -ur clean/src/ircd_parser.y ircd-hybrid-7.0/src/ircd_parser.y
--- clean/src/ircd_parser.y	2002-11-12 05:45:42.000000000 -0800
+++ ircd-hybrid-7.0/src/ircd_parser.y	2004-02-16 00:37:26.000000000 -0800
@@ -47,12 +47,6 @@
 #include "listener.h"
 #include "resv.h"
 
-#ifdef HAVE_LIBCRYPTO
-#include <openssl/rsa.h>
-#include <openssl/bio.h>
-#include <openssl/pem.h>
-#endif
-
 extern char *ip_string;
 
 int yyparse();
@@ -203,6 +197,7 @@
 %token  PING_COOKIE
 %token  PING_TIME
 %token  PORT
+%token  SSLPORT
 %token  QSTRING
 %token  QUIET_ON_BAN
 %token  REASON
@@ -213,6 +208,7 @@
 %token  RESTRICTED
 %token  RSA_PRIVATE_KEY_FILE
 %token  RSA_PUBLIC_KEY_FILE
+%token  SSL_CERTIFICATE_FILE
 %token	RESV
 %token  SECONDS MINUTES HOURS DAYS WEEKS MONTHS YEARS DECADES CENTURIES MILLENNIA
 %token  SENDQ
@@ -409,6 +405,7 @@
                         serverinfo_network_name | serverinfo_network_desc |
                         serverinfo_max_clients | 
                         serverinfo_rsa_private_key_file | serverinfo_vhost6 |
+                        serverinfo_ssl_certificate_file |
                         serverinfo_max_buffer | 
 			error;
 
@@ -470,6 +467,47 @@
 #endif
   };
 
+serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
+  {
+#ifdef HAVE_LIBCRYPTO
+	if (ServerInfo.ctx) {
+	
+  		if (ServerInfo.ssl_certificate_file)
+  		{
+    		MyFree(ServerInfo.ssl_certificate_file);
+    		ServerInfo.ssl_certificate_file = NULL;
+  		}
+
+  		DupString(ServerInfo.ssl_certificate_file, yylval.string);
+
+		if (!ServerInfo.rsa_private_key_file) {
+			ilog(L_ERROR, "Ignoring config file entry ssl_certificate -- no rsa_private_key");
+			break;
+		}
+		
+		if (SSL_CTX_use_certificate_file(ServerInfo.ctx, 
+			ServerInfo.ssl_certificate_file, SSL_FILETYPE_PEM) <= 0) {
+			ilog(L_ERROR, "Error using config file entry ssl_certificate -- %s", ERR_error_string(ERR_get_error(), NULL));
+			break;
+		}
+
+		if (SSL_CTX_use_PrivateKey_file(ServerInfo.ctx, 
+			ServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) <= 0) {
+			sendto_realops_flags(FLAGS_ALL, L_ALL,
+				"Error using config file entry rsa_private_key -- %s",
+				ERR_error_string(ERR_get_error(), NULL));
+			break;
+		}
+		
+		if (!SSL_CTX_check_private_key(ServerInfo.ctx)) {
+			sendto_realops_flags(FLAGS_ALL, L_ALL,
+				"RSA private key doesn't match the SSL certificate public key!");
+			break;
+		}
+	}
+#endif
+  };
+  
 serverinfo_name:        NAME '=' QSTRING ';' 
   {
     /* this isn't rehashable */
@@ -969,7 +1007,8 @@
 listen_items:   listen_items listen_item |
                 listen_item;
 
-listen_item:    listen_port | listen_address | listen_host | error;
+listen_item:    listen_port | listen_sslport |
+				listen_address | listen_host | error;
 
 listen_port: PORT '=' port_items ';' ;
 
@@ -977,13 +1016,29 @@
 
 port_item: NUMBER
 {
-  add_listener($1, listener_address);
+  add_listener($1, listener_address, 0);
+} | NUMBER TWODOTS NUMBER
+{
+  int i;
+  for (i = $1; i <= $3; i++)
+	{
+	  add_listener(i, listener_address, 0);
+	}
+};
+
+listen_sslport: SSLPORT '=' sslport_items ';' ;
+
+sslport_items: sslport_items ',' sslport_item | sslport_item;
+
+sslport_item: NUMBER
+{
+  add_listener($1, listener_address, 1);
 } | NUMBER TWODOTS NUMBER
 {
   int i;
   for (i = $1; i <= $3; i++)
 	{
-	  add_listener(i, listener_address);
+	  add_listener(i, listener_address, 1);
 	}
 };
 
diff -ur clean/src/linebuf.c ircd-hybrid-7.0/src/linebuf.c
--- clean/src/linebuf.c	2002-10-09 08:08:32.000000000 -0700
+++ ircd-hybrid-7.0/src/linebuf.c	2004-02-15 23:41:07.000000000 -0800
@@ -32,6 +32,8 @@
 #include "list.h"
 #include "balloc.h"
 #include "hook.h"
+#include "fdlist.h"
+#include "send.h"
 
 #ifdef STRING_WITH_STRINGS
 # include <string.h>
@@ -634,6 +636,9 @@
 {
   buf_line_t *bufline;
   int retval;
+#ifdef HAVE_LIBCRYPTO
+  fde_t *F = (fd > -1)? &fd_table[fd] : NULL;
+#endif
   
   /* Check we actually have a first buffer */
   if (bufhead->list.head == NULL)
@@ -660,6 +665,86 @@
     }
 
   /* Now, try writing data */
+#ifdef HAVE_LIBCRYPTO
+  if (F && F->ssl) {
+  	/*extern time_t CurrentTime;*/
+  	extern char *get_ssl_error(int);
+  	/*static*/ int alerted = 0;
+  
+  	if (F->flags.accept_write) {
+  		int ret;
+  		/*send(fd, bufline->buf + bufhead->writeofs, bufline->len
+  			- bufhead->writeofs, 0);*/
+  		if ((ret = SSL_accept(F->ssl)) > 0) {
+  			if (!alerted)
+  			sendto_realops_flags(FLAGS_DEBUG, L_ALL, 
+  				"SSL_accept() for %s (socket %d) wanting WRITE succeeded!",
+  				inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd);
+  			F->flags.accept_write = 0;
+  		} else if (F->accept_failures < 4) {
+  			int val = SSL_get_error(F->ssl, ret);  		
+  			sendto_realops_flags(FLAGS_DEBUG, L_ALL, 
+  				"SSL_accept() for %s (socket %d) wanting WRITE error! -- %s",
+  				inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd,
+  				(val == SSL_ERROR_SSL)?
+  				ERR_error_string(ERR_get_error(), NULL) :
+  				get_ssl_error(val));
+  			sendto_realops_flags(FLAGS_DEBUG, L_ALL,
+  				"BIO_sock_should_retry(): %d", BIO_sock_should_retry(ret));
+  		if (val == SSL_ERROR_SYSCALL) {
+  			int err = ERR_get_error();
+  			if (err)
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL, "ERR_get_error() -- %s",
+  					ERR_error_string(err, NULL));
+  			else
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL, "more error info -- %s",
+  					(ret == -1)? strerror(errno) : "got EOF, protocol violation");  
+  		}
+  			sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_state_string_long(): %s",
+  				SSL_state_string_long(F->ssl));
+  			F->accept_failures++;
+  		}
+  		retval = -1; errno = EAGAIN;
+  	} else {
+
+#if 0  				
+  	/*if (CurrentTime % 10 == 0)*/
+  	if (!alerted) {
+  	sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_write() for %s (socket %d) in progress...",
+  		inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd);
+  	sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_state_string_long(): %s",
+  		SSL_state_string_long(F->ssl));
+  	}
+#endif
+  		
+  	retval = SSL_write(F->ssl, bufline->buf + bufhead->writeofs, 
+  				bufline->len - bufhead->writeofs);
+  				
+  	if (retval <= 0 && !alerted) {
+  		int val = SSL_get_error(F->ssl, retval);
+  		/*if (CurrentTime % 10 == 0)*/
+  		sendto_realops_flags(FLAGS_DEBUG, L_ALL, 
+  			"SSL_write() for %s (socket %d) ERROR! -- %s",
+  			inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd,
+  			(val == SSL_ERROR_SSL)?
+  			ERR_error_string(ERR_get_error(), NULL) :
+  			get_ssl_error(val));
+  		if (val == SSL_ERROR_SYSCALL) {
+  			int err = ERR_get_error();
+  			if (err)
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL, "ERR_get_error() -- %s",
+  					ERR_error_string(err, NULL));
+  			else
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL, "more error info -- %s",
+  					(retval == -1)? strerror(errno) : "got EOF, protocol violation");  
+  		} else {
+  			/*SSL_set_accept_state(F->ssl);*/
+  			errno = EAGAIN;
+  		}
+  	}}
+  	alerted = 1;
+  } else
+#endif
   retval = send(fd, bufline->buf + bufhead->writeofs, bufline->len
 		 - bufhead->writeofs, 0);
    
diff -ur clean/src/listener.c ircd-hybrid-7.0/src/listener.c
--- clean/src/listener.c	2003-01-30 02:28:45.000000000 -0800
+++ ircd-hybrid-7.0/src/listener.c	2004-02-15 23:41:18.000000000 -0800
@@ -130,7 +130,7 @@
     sendto_one(source_p, form_str(RPL_STATSPLINE),
                me.name,
                source_p->name,
-               'P',
+               listener->is_ssl? 'S' : 'P',
                listener->port,
                IsOperAdmin(source_p) ? listener->name : me.name,
                listener->ref_count,
@@ -271,7 +271,7 @@
  * the format "255.255.255.255"
  */
 void 
-add_listener(int port, const char* vhost_ip)
+add_listener(int port, const char* vhost_ip, int is_ssl)
 {
   struct Listener* listener;
   struct irc_inaddr   vaddr;
@@ -304,6 +304,8 @@
     listener = make_listener(port, &vaddr);
     listener->next = ListenerPollList;
     ListenerPollList = listener;
+    
+    listener->is_ssl = is_ssl;
   }
 
   listener->fd = -1;
@@ -384,7 +386,7 @@
    * be accepted until some old is closed first.
    */
 
-  fd = comm_accept(listener->fd, &sai);
+  fd = comm_accept(listener->fd, &sai, listener->is_ssl);
 
   if (fd < 0)
   {
diff -ur clean/src/messages.tab ircd-hybrid-7.0/src/messages.tab
--- clean/src/messages.tab	2003-05-05 22:32:17.000000000 -0700
+++ ircd-hybrid-7.0/src/messages.tab	2004-02-16 02:20:22.000000000 -0800
@@ -321,7 +321,7 @@
 /* 294 */       NULL,
 /* 295 */       NULL,
 /* 296 */       NULL,
-/* 297 */       NULL,
+/* 297 RPL_WHOISSSL */	":%s 297 %s %s :is connected via SSL (secure link)",
 /* 298 */       NULL,
 /* 299 */       NULL,
 /* 300 RPL_NONE, */      NULL,
@@ -505,7 +505,7 @@
 /* 477 ERR_MODELESS, */         ":%s 477 %s %s :Channel does not support modes",
 /* 478 ERR_BANLISTFULL, */      ":%s 478 %s %s %s :Channel ban list is full",
 /* 479 ERR_BADCHANNAME */       ":%s 479 %s %s :Illegal channel name",
-/* 480 */       NULL,
+/* 480 ERR_SSLONLYCHAN */       ":%s 480 %s %s :Cannot join channel (+S)",
 /* 481 ERR_NOPRIVILEGES, */
                 ":%s 481 %s :Permission Denied - You're not an IRC operator",
 /* 482 ERR_CHANOPRIVSNEEDED, */ ":%s 482 %s %s :You're not channel operator",
diff -ur clean/src/packet.c ircd-hybrid-7.0/src/packet.c
--- clean/src/packet.c	2003-02-16 14:54:37.000000000 -0800
+++ ircd-hybrid-7.0/src/packet.c	2004-02-15 23:49:11.000000000 -0800
@@ -378,6 +378,10 @@
 #ifndef NDEBUG
   struct hook_io_data hdata;
 #endif
+#ifdef HAVE_LIBCRYPTO
+  fde_t *F = (lclient_p->fd > -1)? &fd_table[lclient_p->fd] : NULL;
+#endif
+
   if(IsDefunct(client_p))
     return;
   
@@ -397,6 +401,74 @@
    * I personally think it makes the code too hairy to make sane.
    *     -- adrian
    */
+#ifdef HAVE_LIBCRYPTO
+  if (F && F->ssl) {
+        /*extern time_t CurrentTime;*/
+        extern char *get_ssl_error(int);
+        /*static*/ int alerted = 0;
+
+        if (F->flags.accept_read) {
+                int ret;
+                /*recv(fd_r, readBuf, READBUF_SIZE, 0);*/
+                if ((ret = SSL_accept(F->ssl)) > 0) {
+                        if (!alerted)
+                        sendto_realops_flags(FLAGS_DEBUG, L_ALL,
+                                "SSL_accept() for %s (socket %d) wanting READ succeeded!",
+                                inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd);
+                        F->flags.accept_read = 0;
+                } else if (F->accept_failures < 4) {
+                        int val = SSL_get_error(F->ssl, ret);
+                        sendto_realops_flags(FLAGS_DEBUG, L_ALL,
+                                "SSL_accept() for %s (socket %d) wanting READ error! -- %s",
+                                inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd,
+                                (val == SSL_ERROR_SSL)?
+                                ERR_error_string(ERR_get_error(), NULL) :
+                                get_ssl_error(val));
+                        sendto_realops_flags(FLAGS_DEBUG, L_ALL,
+                                "BIO_sock_should_retry(): %d", BIO_sock_should_retry(ret));
+                if (val == SSL_ERROR_SYSCALL) {
+                        int err = ERR_get_error();
+                        if (err)
+                                sendto_realops_flags(FLAGS_DEBUG, L_ALL, "ERR_get_error() -- %s",
+                                        ERR_error_string(err, NULL));
+                        else
+                                sendto_realops_flags(FLAGS_DEBUG, L_ALL, "more error info -- %s",
+                                        (ret == -1)? strerror(errno) : "got EOF, protocol violation");
+                }
+                        sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_state_string_long(): %s",
+                                SSL_state_string_long(F->ssl));
+                        F->accept_failures++;
+                }
+                length = -1; errno = EAGAIN;
+        } else {
+
+        length = SSL_read(F->ssl, readBuf, READBUF_SIZE);
+        
+        if (length <= 0 && !alerted) {
+                int val = SSL_get_error(F->ssl, length);
+                /*if (CurrentTime % 10 == 0)*/
+                sendto_realops_flags(FLAGS_DEBUG, L_ALL, 
+                        "SSL_read() for %s (socket %d) ERROR! -- %s",
+                        inetntoa((char *)&S_ADDR(F->connect.hostaddr)), F->fd,
+                        (val == SSL_ERROR_SSL)?
+                        ERR_error_string(ERR_get_error(), NULL) :
+                        get_ssl_error(val));
+                if (val == SSL_ERROR_SYSCALL) {
+                        int err = ERR_get_error();
+                        if (err)
+                                sendto_realops_flags(FLAGS_DEBUG, L_ALL, "ERR_get_error() -- %s",
+                                        ERR_error_string(err, NULL));
+                        else    
+                                sendto_realops_flags(FLAGS_DEBUG, L_ALL, "more error info -- %s",
+                                        (length == -1)? strerror(errno) : "got EOF, protocol violation");
+                } else {
+                        /*SSL_set_accept_state(F->ssl);*/
+                        errno = EAGAIN;
+                }
+        }}
+        alerted = 1;
+  } else
+#endif
   length = recv(fd_r, readBuf, READBUF_SIZE, 0);
 
   if (length <= 0)
diff -ur clean/src/s_auth.c ircd-hybrid-7.0/src/s_auth.c
--- clean/src/s_auth.c	2003-05-28 22:13:26.000000000 -0700
+++ ircd-hybrid-7.0/src/s_auth.c	2004-02-15 23:49:44.000000000 -0800
@@ -87,8 +87,25 @@
   REPORT_HOST_TOOLONG
 } ReportType;
 
+#ifdef HAVE_LIBCRYPTO
+   static void sendheader(struct Client *c, int r) {
+   		int fd = c->localClient->fd;
+   		fde_t *F = (fd > -1)? &fd_table[fd] : NULL;
+   
+   		if (F && F->ssl) {
+   			if (F->flags.accept_write)
+   				if (SSL_accept(F->ssl) > 0)
+   					F->flags.accept_write = 0;
+   			if (!F->flags.accept_read)
+   			SSL_write(F->ssl, HeaderMessages[r].message, HeaderMessages[r].length);
+   		} else {
+   			send(fd, HeaderMessages[r].message, HeaderMessages[r].length, 0);
+   		}
+   }
+#else
 #define sendheader(c, r) \
    send((c)->localClient->fd, HeaderMessages[(r)].message, HeaderMessages[(r)].length, 0)
+#endif
 
 /*
  */
diff -ur clean/src/s_bsd.c ircd-hybrid-7.0/src/s_bsd.c
--- clean/src/s_bsd.c	2003-05-31 00:37:05.000000000 -0700
+++ ircd-hybrid-7.0/src/s_bsd.c	2004-02-15 23:50:42.000000000 -0800
@@ -51,7 +51,6 @@
 #include "memory.h"
 #include "ircd_defs.h"
 
-
 #ifndef IN_LOOPBACKNET
 #define IN_LOOPBACKNET        0x7f
 #endif
@@ -790,7 +789,7 @@
     }
 
   /* Next, update things in our fd tracking */
-  fd_open(fd, FD_SOCKET, note);
+  fd_open(fd, FD_SOCKET, note, NULL);
   return fd;
 }
 
@@ -802,10 +801,14 @@
  * comm_open() does.
  */
 int
-comm_accept(int fd, struct irc_sockaddr *pn)
+comm_accept(int fd, struct irc_sockaddr *pn, int is_ssl)
 {
   int newfd;
   socklen_t addrlen = sizeof(struct irc_sockaddr);
+#ifdef HAVE_LIBCRYPTO
+  SSL *ssl = NULL;
+#endif
+
   if (number_fd >= MASTER_MAX)
     {
       errno = ENFILE;
@@ -820,7 +823,7 @@
   newfd = accept(fd, (struct sockaddr *)&PSOCKADDR(pn), (socklen_t *)&addrlen);
   if (newfd < 0)
     return -1;
-
+    
   /* Set the socket non-blocking, and other wonderful bits */
   if (!set_non_blocking(newfd))
     {
@@ -829,9 +832,115 @@
       return -1;
     }
 
+#ifdef HAVE_LIBCRYPTO
+  if (is_ssl && ServerInfo.ctx) {
+    int retval;
+    extern char *get_ssl_error(int);
+  	fde_t *F = &fd_table[newfd];
+  	
+  	copy_s_addr(F->connect.hostaddr, *pn);
+  
+  	ssl = SSL_new(ServerInfo.ctx);
+  	if (!ssl) {
+  		ilog(L_CRIT, "SSL_new() ERROR! -- %s", ERR_error_string(ERR_get_error(), NULL));
+  		close(newfd);
+  		return -1;
+  	}
+  	SSL_set_fd(ssl, newfd);
+  	
+  	sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_accept() for %s (socket %d) in progress...",
+  		inetntoa((char *)&PS_ADDR(pn)), newfd);
+
+again:
+  	retval = SSL_accept(ssl);
+  	if (retval <= 0) {
+  		switch ((retval = SSL_get_error(ssl, retval))) {
+  		
+	    	case SSL_ERROR_SYSCALL:
+				if (errno==EINTR || errno==EWOULDBLOCK || errno==EAGAIN)
+				
+  			case SSL_ERROR_WANT_READ:
+  			case SSL_ERROR_WANT_WRITE:
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL,
+  					"SSL_accept() for %s wants read or write (%s), passing through...",
+  					inetntoa((char *)&PS_ADDR(pn)), get_ssl_error(retval));
+  					
+  				/* let it through, SSL_read()/SSL_write() will finish the handshake...*/
+  				/*goto again;*/
+  				
+  				/*SSL_set_accept_state(ssl);*/
+  				if (retval == SSL_ERROR_WANT_READ)
+  					F->flags.accept_read = 1;
+  				else if (retval == SSL_ERROR_WANT_WRITE)
+  					F->flags.accept_write = 1;
+  				else
+  					F->flags.accept_read = 1;
+  				break;
+  				
+  			default:
+  				sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_accept() ERROR! -- %s",
+  					(retval == SSL_ERROR_SSL)?
+  					ERR_error_string(ERR_get_error(), NULL) :
+  					get_ssl_error(retval));
+  				SSL_free(ssl);
+  				close(newfd);
+  				return -1;
+  		}
+  	} else {
+  		char *ssl_get_cipher(SSL *);
+  		/*SSL_set_accept_state(ssl);*/
+  		
+  		sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_accept() for %s succeeded!",
+  			inetntoa((char *)&PS_ADDR(pn)));
+  		sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL protocol/cipher: %s",
+  			ssl_get_cipher(ssl));
+  		sendto_realops_flags(FLAGS_DEBUG, L_ALL, "SSL_state_string_long(): %s",
+  			SSL_state_string_long(ssl));
+  	}
+  }
+#endif
+
   /* Next, tag the FD as an incoming connection */
-  fd_open(newfd, FD_SOCKET, "Incoming connection");
+#ifdef HAVE_LIBCRYPTO
+  if (is_ssl && ServerInfo.ctx)
+  	fd_open(newfd, FD_SOCKET, "Incoming SSL connection", ssl);
+  else
+  	fd_open(newfd, FD_SOCKET, "Incoming connection", ssl);
+#else
+  fd_open(newfd, FD_SOCKET, "Incoming connection", NULL);
+#endif
 
   /* .. and return */
   return newfd;
 }
+
+#ifdef HAVE_LIBCRYPTO
+char *ssl_get_cipher(SSL *ssl)
+{
+	static char buf[400];
+	char bots[10];
+	int bits;
+	SSL_CIPHER *c; 
+	
+	buf[0] = '\0';
+	switch(ssl->session->ssl_version)
+	{
+		case SSL2_VERSION:
+			strcat(buf, "SSLv2"); break;
+		case SSL3_VERSION:
+			strcat(buf, "SSLv3"); break;
+		case TLS1_VERSION:
+			strcat(buf, "TLSv1"); break;
+		default:
+			strcat(buf, "UNKNOWN");
+	}
+	strcat(buf, "-");
+	strcat(buf, SSL_get_cipher(ssl));
+	c = SSL_get_current_cipher(ssl);
+	SSL_CIPHER_get_bits(c, &bits);
+	sprintf(bots, "-%d", bits);
+	strcat(buf, bots);
+	strcat(buf, "bits");
+	return (buf);
+}
+#endif
diff -ur clean/src/s_misc.c ircd-hybrid-7.0/src/s_misc.c
--- clean/src/s_misc.c	2002-05-24 16:34:51.000000000 -0700
+++ ircd-hybrid-7.0/src/s_misc.c	2004-02-15 23:54:52.000000000 -0800
@@ -122,3 +122,32 @@
   return timebuffer;
 }
 
+#ifdef HAVE_LIBCRYPTO
+static struct {
+       int err;
+       char *str;
+} errtab[] = {
+       {SSL_ERROR_NONE, "SSL_ERROR_NONE"},
+       {SSL_ERROR_ZERO_RETURN, "SSL_ERROR_ZERO_RETURN"},
+       {SSL_ERROR_WANT_READ, "SSL_ERROR_WANT_READ"},
+       {SSL_ERROR_WANT_WRITE, "SSL_ERROR_WANT_WRITE"},
+       {SSL_ERROR_WANT_CONNECT, "SSL_ERROR_WANT_CONNECT"},
+       /*{SSL_ERROR_WANT_ACCEPT, "SSL_ERROR_WANT_ACCEPT"},*/
+       {SSL_ERROR_WANT_X509_LOOKUP, "SSL_ERROR_WANT_X509_LOOKUP"},
+       {SSL_ERROR_SYSCALL, "SSL_ERROR_SYSCALL"},
+       {SSL_ERROR_SSL, "SSL_ERROR_SSL"},
+       {-1, NULL}
+};
+
+char *get_ssl_error(int sslerr) 
+{
+       int i;
+       
+       for (i=0; errtab[i].err != -1; i++)
+               if (errtab[i].err == sslerr)
+                       return errtab[i].str;
+                       
+       return "<NULL>";
+}
+#endif
+
diff -ur clean/src/s_serv.c ircd-hybrid-7.0/src/s_serv.c
--- clean/src/s_serv.c	2003-05-31 00:30:34.000000000 -0700
+++ ircd-hybrid-7.0/src/s_serv.c	2004-02-15 23:55:03.000000000 -0800
@@ -1458,13 +1458,13 @@
 #endif
 
 #ifdef HAVE_SOCKETPAIR
-    fd_open(server->localClient->ctrlfd, FD_SOCKET, NULL);
-    fd_open(server->localClient->fd, FD_SOCKET, NULL);
+    fd_open(server->localClient->ctrlfd, FD_SOCKET, NULL, NULL);
+    fd_open(server->localClient->fd, FD_SOCKET, NULL, NULL);
 #else
-    fd_open(server->localClient->ctrlfd, FD_PIPE, NULL);
-    fd_open(server->localClient->fd, FD_PIPE, NULL);
-    fd_open(server->localClient->ctrlfd_r, FD_PIPE, NULL);
-    fd_open(server->localClient->fd_r, FD_PIPE, NULL);
+    fd_open(server->localClient->ctrlfd, FD_PIPE, NULL, NULL);
+    fd_open(server->localClient->fd, FD_PIPE, NULL, NULL);
+    fd_open(server->localClient->ctrlfd_r, FD_PIPE, NULL, NULL);
+    fd_open(server->localClient->fd_r, FD_PIPE, NULL, NULL);
 #endif
 
    read_ctrl_packet(slink_fds[0][1][0], server);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 881 bytes
Desc: Digital signature
URL: <http://lists.ircd-hybrid.org/pipermail/hybrid/attachments/20040625/79894d60/attachment.pgp>


More information about the hybrid mailing list