diff -Nru ircd-hybrid-old/configure ircd-hybrid/configure
--- ircd-hybrid-old/configure	2004-02-17 01:37:43 +0300
+++ ircd-hybrid/configure	2004-04-20 10:02:06 +0400
@@ -6765,7 +6765,7 @@
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto  $LIBS"
+LIBS="-lcrypto -lssl  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -6827,7 +6827,7 @@
 #define HAVE_LIBCRYPTO 1
 _ACEOF
 
-  LIBS="-lcrypto $LIBS"
+  LIBS="-lcrypto -lssl $LIBS"
 
 fi
 
@@ -7441,7 +7441,7 @@
 done
 
 		fi
-		SSL_LIBS="$SSL_LIBS -lcrypto"
+		SSL_LIBS="$SSL_LIBS -lcrypto -lssl"
 		SSL_SRCS_ENABLE='$(SSL_SRCS)'
 	else
 	        echo "$as_me:$LINENO: result: no - OpenSSL support disabled" >&5
diff -Nru ircd-hybrid-old/contrib/m_whois.c ircd-hybrid/contrib/m_whois.c
--- ircd-hybrid-old/contrib/m_whois.c	2003-10-21 06:31:10 +0400
+++ ircd-hybrid/contrib/m_whois.c	2004-04-20 10:01:21 +0400
@@ -426,6 +426,11 @@
 
   if (MyConnect(target_p)) /* Can't do any of this if not local! db */
   {
+#ifdef HAVE_LIBCRYPTO
+    if (target_p->ssl)
+      sendto_one(source_p, form_str(RPL_USINGSSL),
+                 me.name, source_p->name, target_p->name);
+#endif
     if ((glob) || (MyClient(source_p) && (IsOper(source_p) ||
         !ConfigServerHide.hide_servers)) || (source_p == target_p))
     {
diff -Nru ircd-hybrid-old/etc/example.conf ircd-hybrid/etc/example.conf
--- ircd-hybrid-old/etc/example.conf	2004-02-28 09:12:23 +0300
+++ ircd-hybrid/etc/example.conf	2004-04-20 10:01:21 +0400
@@ -92,6 +92,23 @@
 	 *	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
+         */
+        #ssl_certificate_file = "/usr/local/ircd/etc/cert.pem";
+
+        /* Certification Authority certificate file, used to sign
+         * ssl_certificate_file. Shouldn't be used if certificate
+         * is self-signed
+         */
+        #ssl_ca_certificate_file = "/usr/local/ircd/etc/ca.pem";	
 };
 
 /* admin {}: contains admin information about the server. (OLD A:) */
@@ -185,15 +202,20 @@
 	
 	/* port: listen on all available IPs, ports 6665 to 6669 */
 	port = 6665 .. 6669;
+	
+        /* sslport: listen for SSL connections on all available IPs, ports 9995 to 9999 */
+        sslport = 9995 .. 9999;	
 
 	/* host: set a specific IP/host the ports after the line will listen 
 	 * on.  This may be ipv4 or ipv6.
 	 */
 	host = "1.2.3.4";
 	port = 7000, 7001;
+	sslport = 7099;
 
 	host = "3ffe:1234:a:b:c::d";
 	port = 7002;
+	sslport = 7199;
 };
 
 /* auth {}: allow users to connect to the ircd (OLD I:) */
diff -Nru ircd-hybrid-old/include/client.h ircd-hybrid/include/client.h
--- ircd-hybrid-old/include/client.h	2004-02-24 06:36:18 +0300
+++ ircd-hybrid/include/client.h	2004-04-20 10:01:21 +0400
@@ -129,6 +129,10 @@
 					   * bit mapped lazylink servers 
 					   * mapped here
 					   */
+#ifdef HAVE_LIBCRYPTO
+  SSL *ssl;
+#endif
+					   
   /*
    * client->name is the unique name for a client nick or host
    */
@@ -365,8 +369,8 @@
 #define FLAGS_BLOCKED     0x01000000 /* must wait for COMM_SELECT_WRITE          */
 #define FLAGS_SBLOCKED    0x02000000 /* slinkq is blocked                        */
 #define FLAGS_USERHOST    0x04000000 /* client is in userhost hash               */
-/*                        0x08000000  */
-/*                        0x10000000  */
+#define FLAGS_SSL         0x08000000 /* client connected thru SSL                */
+#define FLAGS_DOINGAUTH   0x10000000 /* client is still authenticating           */
 /*                        0x20000000  */
 /*                        0x40000000  */
 /*                        0x80000000  */
@@ -446,6 +450,8 @@
 #define IsCanFlood(x)		((x)->flags & FLAGS_CANFLOOD)
 #define IsDefunct(x)            ((x)->flags & (FLAGS_DEADSOCKET|FLAGS_CLOSING| \
 					       FLAGS_KILLED))
+#define SetSSL(x)               ((x)->flags |= FLAGS_SSL)
+#define IsSSL(x)                (((x)->flags & FLAGS_SSL) && (x)->ssl)					       
 
 /* oper flags */
 #define MyOper(x)               (MyConnect(x) && IsOper(x))
diff -Nru ircd-hybrid-old/include/listener.h ircd-hybrid/include/listener.h
--- ircd-hybrid-old/include/listener.h	2003-06-26 16:19:45 +0400
+++ ircd-hybrid/include/listener.h	2004-04-20 10:01:21 +0400
@@ -46,9 +46,10 @@
   struct irc_ssaddr addr;              /* virtual address or INADDR_ANY */
   struct DNSQuery   *dns_query;
   char             vhost[HOSTLEN + 1]; /* virtual name of listener */
+  int    is_ssl;                       /* if our listener is a SSL listener */  
 };
 
-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_listeners(void);
 extern const char *get_listener_name(const struct Listener *listener);
 extern void show_ports(struct Client *source_p);
diff -Nru ircd-hybrid-old/include/numeric.h ircd-hybrid/include/numeric.h
--- ircd-hybrid-old/include/numeric.h	2004-03-17 07:08:57 +0300
+++ ircd-hybrid/include/numeric.h	2004-04-20 10:01:21 +0400
@@ -162,6 +162,8 @@
 #define RPL_LOCALUSERS       265
 #define RPL_GLOBALUSERS      266
 
+#define RPL_USINGSSL         275
+
 #define RPL_ACCEPTLIST	     281
 #define RPL_ENDOFACCEPT      282
 #define RPL_ISMESSAGING	     283
diff -Nru ircd-hybrid-old/include/patchlevel.h ircd-hybrid/include/patchlevel.h
--- ircd-hybrid-old/include/patchlevel.h	2003-03-02 11:06:19 +0300
+++ ircd-hybrid/include/patchlevel.h	2004-04-20 10:01:21 +0400
@@ -23,5 +23,5 @@
  */
 
 #ifndef PATCHLEVEL
-#define PATCHLEVEL   "hybrid-7.1beta1"
+#define PATCHLEVEL   "hybrid-7.1beta1-SSL"
 #endif
diff -Nru ircd-hybrid-old/include/s_conf.h ircd-hybrid/include/s_conf.h
--- ircd-hybrid-old/include/s_conf.h	2004-02-01 08:25:44 +0300
+++ ircd-hybrid/include/s_conf.h	2004-04-20 10:01:21 +0400
@@ -27,6 +27,7 @@
 #include "setup.h"
 #ifdef HAVE_LIBCRYPTO
 #include <openssl/rsa.h>
+#include <openssl/ssl.h>
 #endif
 #include "fileio.h"             /* FBFILE */
 #include "ircd_defs.h"
@@ -366,6 +367,10 @@
 #ifdef HAVE_LIBCRYPTO
   char *rsa_private_key_file;
   RSA *rsa_private_key;
+  char *ssl_certificate_file;
+  char *ssl_ca_certificate_file;
+  SSL_CTX *ctx;
+  SSL_METHOD *meth;  
 #endif
   char *sid;
   int hub;
diff -Nru ircd-hybrid-old/include/ssl.h ircd-hybrid/include/ssl.h
--- ircd-hybrid-old/include/ssl.h	1970-01-01 03:00:00 +0300
+++ ircd-hybrid/include/ssl.h	2004-04-20 10:01:21 +0400
@@ -0,0 +1,44 @@
+/*
+ *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ *  ssl.h: Secure Sockets Layer header.
+ *
+ *  Copyright (C) 2004 by the past and present ircd coders, and others.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ *
+ *  $Id: ssl.h,v 1.0 2004/20/04 07:24:32 Sakura Exp $
+ */
+
+#ifndef INCLUDED_ssl_h
+#define INCLUDED_ssl_h
+
+#include "setup.h"
+
+#ifdef HAVE_LIBCRYPTO
+#include "client.h"
+
+extern int safe_SSL_read(struct Client *, void *, int);
+extern int safe_SSL_write(struct Client *, const void *, int);
+extern int safe_SSL_accept(struct Client *, int);
+extern int SSL_smart_shutdown(SSL *);
+extern int initssl(void);
+extern SSL_CTX *ircdssl_ctx;
+
+#endif
+
+extern void ircd_init_ssl(void);
+
+#endif  /* INCLUDED_ssl_h */
diff -Nru ircd-hybrid-old/include/stdinc.h ircd-hybrid/include/stdinc.h
--- ircd-hybrid-old/include/stdinc.h	2003-06-28 22:01:54 +0400
+++ ircd-hybrid/include/stdinc.h	2004-04-20 10:01:21 +0400
@@ -65,6 +65,17 @@
 # endif
 #endif
 
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#endif
+
 #ifdef HAVE_CRYPT_H
 #include <crypt.h>
 #endif
diff -Nru ircd-hybrid-old/include/supported.h ircd-hybrid/include/supported.h
--- ircd-hybrid-old/include/supported.h	2003-09-28 06:16:03 +0400
+++ ircd-hybrid/include/supported.h	2004-04-20 10:01:21 +0400
@@ -31,6 +31,17 @@
 
 #define CASEMAP "rfc1459"
 
+#ifdef HAVE_LIBCRYPTO
+#define FEATURES "SSL WALLCHOPS"   \
+                 "%s%s%s"          \
+                 " MODES=%i"       \
+                 " MAXCHANNELS=%i" \
+                 " MAXBANS=%i"     \
+                 " MAXTARGETS=%i"  \
+                 " NICKLEN=%i"     \
+                 " TOPICLEN=%i"    \
+                 " KICKLEN=%i"
+#else
 #define FEATURES "WALLCHOPS"       \
                  "%s%s%s"          \
                  " MODES=%i"       \
@@ -40,6 +51,7 @@
                  " NICKLEN=%i"     \
                  " TOPICLEN=%i"    \
                  " KICKLEN=%i"
+#endif
 
 #define FEATURESVALUES ConfigChannel.use_knock ? " KNOCK" : "", \
         ConfigChannel.use_except ? " EXCEPTS" : "", \
diff -Nru ircd-hybrid-old/include/tools.h ircd-hybrid/include/tools.h
--- ircd-hybrid-old/include/tools.h	2003-10-24 15:38:43 +0400
+++ ircd-hybrid/include/tools.h	2004-04-20 10:01:21 +0400
@@ -64,6 +64,7 @@
 extern void dlinkAddBefore(dlink_node *b, void *data, dlink_node *m, dlink_list *list);
 extern void dlinkAddTail(void *data, dlink_node *m, dlink_list *list);
 extern void dlinkDelete(dlink_node *m, dlink_list *list);
+extern void dlinkDeleteNode(dlink_node *m, dlink_list *list);
 extern void dlinkMoveList(dlink_list *from, dlink_list *to);
 extern dlink_node *dlinkFind(dlink_list *m, void *data);
 extern dlink_node *dlinkFindDelete(dlink_list *m, void *data);
diff -Nru ircd-hybrid-old/modules/m_whois.c ircd-hybrid/modules/m_whois.c
--- ircd-hybrid-old/modules/m_whois.c	2004-03-17 07:08:58 +0300
+++ ircd-hybrid/modules/m_whois.c	2004-04-20 10:01:21 +0400
@@ -428,6 +428,11 @@
 
   if (MyConnect(target_p)) /* Can't do any of this if not local! db */
   {
+#ifdef HAVE_LIBCRYPTO
+    if (target_p->ssl)
+      sendto_one(source_p, form_str(RPL_USINGSSL),
+                 me.name, source_p->name, target_p->name);
+#endif  
     if ((glob) ||
          (MyClient(source_p) && (IsOper(source_p) ||
                                   !ConfigServerHide.hide_servers)) ||
diff -Nru ircd-hybrid-old/src/client.c ircd-hybrid/src/client.c
--- ircd-hybrid-old/src/client.c	2004-04-01 06:53:24 +0400
+++ ircd-hybrid/src/client.c	2004-04-20 10:01:21 +0400
@@ -53,6 +53,7 @@
 #include "listener.h"
 #include "irc_res.h"
 #include "userhost.h"
+#include "ssl.h"
 
 /* Pointer to beginning of Client list */
 dlink_list global_client_list = {NULL, NULL, 0};
@@ -1249,6 +1250,16 @@
         if ((m = dlinkFindDelete(&oper_list, source_p)) != NULL)
           free_dlink_node(m);
       }
+      
+#ifdef HAVE_LIBCRYPTO
+    /* Close the ssl connection also */
+    if (IsSSL(source_p)) {
+      SSL_set_shutdown(source_p->ssl, SSL_RECEIVED_SHUTDOWN);
+      SSL_smart_shutdown(source_p->ssl);
+      SSL_free(source_p->ssl);
+      source_p->ssl = NULL;
+    }
+#endif      
 
       /* a little extra paranoia */
       if (IsPerson(source_p))
diff -Nru ircd-hybrid-old/src/ircd.c ircd-hybrid/src/ircd.c
--- ircd-hybrid-old/src/ircd.c	2004-02-03 06:59:55 +0300
+++ ircd-hybrid/src/ircd.c	2004-04-20 10:01:21 +0400
@@ -62,7 +62,7 @@
 #include "hook.h"
 #include "ircd_getopt.h"
 #include "balloc.h"
-
+#include "ssl.h"
 
 /* Try and find the correct name to use with getrlimit() for setting the max.
  * number of files allowed to be open by this process.
@@ -553,6 +553,21 @@
     make_daemon();
   else
     print_startup(getpid());
+    
+#ifdef HAVE_LIBCRYPTO
+  printf("SSL: Initialize\n");
+
+  SSL_load_error_strings();
+  SSLeay_add_ssl_algorithms();
+  ServerInfo.ctx = SSL_CTX_new(SSLv23_server_method());
+
+  if (!ServerInfo.ctx) {
+       ERR_print_errors_fp(stderr);
+       return 0;
+  }
+
+  printf("SSL: Client based SSL connections are enabled.\n");
+#endif    
 
   setup_signals();
   /* We need this to initialise the fd array before anything else */
diff -Nru ircd-hybrid-old/src/ircd_lexer.l ircd-hybrid/src/ircd_lexer.l
--- ircd-hybrid-old/src/ircd_lexer.l	2003-10-04 23:31:19 +0400
+++ ircd-hybrid/src/ircd_lexer.l	2004-04-20 10:01:21 +0400
@@ -242,6 +242,7 @@
 ping_cookie	{ return PING_COOKIE; }
 ping_time	{ return PING_TIME; }
 port		{ return PORT; }
+sslport         { return SSLPORT; }
 quarantine	{ return RESV; }
 quiet_on_ban    { return QUIET_ON_BAN; }
 reason		{ return REASON; }
@@ -254,6 +255,8 @@
 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; }
+ssl_ca_certificate_file         { return SSL_CA_CERTIFICATE_FILE; }
 send_password	{ return SEND_PASSWORD; }
 sendq		{ return SENDQ; }
 serverhide	{ return SERVERHIDE; }
diff -Nru ircd-hybrid-old/src/ircd_parser.y ircd-hybrid/src/ircd_parser.y
--- ircd-hybrid-old/src/ircd_parser.y	2004-03-03 14:31:16 +0300
+++ ircd-hybrid/src/ircd_parser.y	2004-04-20 10:01:21 +0400
@@ -256,6 +256,7 @@
 %token  PING_COOKIE
 %token  PING_TIME
 %token  PORT
+%token  SSLPORT
 %token  QSTRING
 %token  QUIET_ON_BAN
 %token  REASON
@@ -266,6 +267,8 @@
 %token  RESTRICTED
 %token  RSA_PRIVATE_KEY_FILE
 %token  RSA_PUBLIC_KEY_FILE
+%token  SSL_CERTIFICATE_FILE
+%token  SSL_CA_CERTIFICATE_FILE
 %token  RESV
 %token  SECONDS MINUTES HOURS DAYS WEEKS
 %token  SENDQ
@@ -458,7 +461,9 @@
                         serverinfo_hub | serverinfo_description |
                         serverinfo_network_name | serverinfo_network_desc |
                         serverinfo_max_clients | 
-                        serverinfo_rsa_private_key_file | serverinfo_vhost6 |
+			serverinfo_rsa_private_key_file | serverinfo_ssl_certificate_file |
+                        serverinfo_ssl_ca_certificate_file |
+                        serverinfo_vhost6 |
                         serverinfo_sid |
 			error;
 
@@ -517,6 +522,73 @@
 #endif
 };
 
+serverinfo_ssl_certificate_file: SSL_CERTIFICATE_FILE '=' QSTRING ';'
+{
+#ifdef HAVE_LIBCRYPTO
+  if (ypass == 2)
+  {
+    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) {
+        yyerror("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) {
+        yyerror("Error using config file entry ssl_certificate");
+        break;
+      }
+
+      if (SSL_CTX_use_PrivateKey_file(ServerInfo.ctx,
+          ServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) <= 0) {
+        yyerror("Error using config file entry rsa_private_key");
+        break;
+      }
+
+      if (!SSL_CTX_check_private_key(ServerInfo.ctx)) {
+        yyerror("RSA private key doesn't match the SSL certificate public key!");
+        break;
+      }
+    }
+  }
+#endif
+};
+
+serverinfo_ssl_ca_certificate_file: SSL_CA_CERTIFICATE_FILE '=' QSTRING ';'
+{
+#ifdef HAVE_LIBCRYPTO
+  if (ypass == 2)
+  {
+    if (ServerInfo.ctx) {
+
+      if (ServerInfo.ssl_ca_certificate_file)
+      {
+        MyFree(ServerInfo.ssl_ca_certificate_file);
+        ServerInfo.ssl_ca_certificate_file = NULL;
+      }
+
+      DupString(ServerInfo.ssl_ca_certificate_file, yylval.string);
+
+      if (ServerInfo.ssl_ca_certificate_file != NULL &&
+          SSL_CTX_load_verify_locations(ServerInfo.ctx,
+          ServerInfo.ssl_ca_certificate_file, NULL) != 1) {
+        yyerror("Error using config file entry ssl_ca_certificate");
+        break;
+      }
+    }
+  }
+#endif
+};
+
 serverinfo_name: NAME '=' QSTRING ';' 
 {
   /* this isn't rehashable */
@@ -1280,7 +1352,7 @@
 };
 
 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 ';' ;
 
@@ -1289,7 +1361,28 @@
 port_item: NUMBER
 {
   if (ypass == 2)
-    add_listener($1, listener_address);
+    add_listener($1, listener_address, 0);  
+} | NUMBER TWODOTS NUMBER
+{
+  if (ypass == 2)
+  {
+    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
+{
+  if (ypass == 2)
+    add_listener($1, listener_address, 1);
 } | NUMBER TWODOTS NUMBER
 {
   if (ypass == 2)
@@ -1298,7 +1391,7 @@
 
     for (i = $1; i <= $3; i++)
     {
-      add_listener(i, listener_address);
+      add_listener(i, listener_address, 1);
     }
   }
 };
diff -Nru ircd-hybrid-old/src/listener.c ircd-hybrid/src/listener.c
--- ircd-hybrid-old/src/listener.c	2003-08-10 07:54:21 +0400
+++ ircd-hybrid/src/listener.c	2004-04-20 10:01:21 +0400
@@ -112,7 +112,7 @@
     listener = ptr->data;
     sendto_one(source_p, form_str(RPL_STATSPLINE),
                me.name, source_p->name,
-               'P', listener->port,
+	       listener->is_ssl ? 'S' : 'P', listener->port,
                IsAdmin(source_p) ? listener->name : me.name,
                listener->ref_count,
                (listener->active)?"active":"disabled");
@@ -245,7 +245,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_ssaddr vaddr;
@@ -313,7 +313,7 @@
   {
     /* add the ipv4 listener if we havent already */
     pass = 1;
-    add_listener(port, "0.0.0.0");
+    add_listener(port, "0.0.0.0", is_ssl);
   }
   pass = 0;
 #endif
@@ -326,6 +326,7 @@
   else
   {
     listener = make_listener(port, &vaddr);
+    listener->is_ssl = is_ssl;
     dlinkAdd(listener, &listener->listener_node, &ListenerPollList);
   }
 
diff -Nru ircd-hybrid-old/src/Makefile.in ircd-hybrid/src/Makefile.in
--- ircd-hybrid-old/src/Makefile.in	2004-01-23 03:46:43 +0300
+++ ircd-hybrid/src/Makefile.in	2004-04-20 10:01:21 +0400
@@ -109,7 +109,8 @@
  @SSL_SRCS_ENABLE@ \
  @DYNLINK_C@ \
  tools.c \
- whowas.c
+ whowas.c \
+ ssl.c
 
 SRCS = ${BASE_SRCS} $(NETIO_SRC)
 OBJS = ${SRCS:.c=.o}
diff -Nru ircd-hybrid-old/src/messages.tab ircd-hybrid/src/messages.tab
--- ircd-hybrid-old/src/messages.tab	2004-03-26 23:25:41 +0300
+++ ircd-hybrid/src/messages.tab	2004-04-20 10:01:21 +0400
@@ -295,7 +295,7 @@
 /* 272 */  {NULL, NULL, NULL},
 /* 273 */  {NULL, NULL, NULL},
 /* 274 */  {NULL, NULL, NULL},
-/* 275 */  {NULL, NULL, NULL},
+/* 275 */  {"RPL_USINGSSL", ":%s 275 %s %s :connected via SSL (secure link)", NULL},
 /* 276 */  {NULL, NULL, NULL},
 /* 277 */  {NULL, NULL, NULL},
 /* 278 */  {NULL, NULL, NULL},
diff -Nru ircd-hybrid-old/src/packet.c ircd-hybrid/src/packet.c
--- ircd-hybrid-old/src/packet.c	2003-06-06 08:31:50 +0400
+++ ircd-hybrid/src/packet.c	2004-04-20 10:11:03 +0400
@@ -37,6 +37,7 @@
 #include "memory.h"
 #include "hook.h"
 #include "send.h"
+#include "ssl.h"
 
 static char readBuf[READBUF_SIZE];
 static void client_dopacket(struct Client *client_p, char *buffer, size_t length);
@@ -426,6 +427,14 @@
    * I personally think it makes the code too hairy to make sane.
    *     -- adrian
    */
+#ifdef HAVE_LIBCRYPTO
+  if (IsSSL(client_p))
+  {
+    length = safe_SSL_read(client_p, readBuf, READBUF_SIZE);
+    printf("read: %s\n", readBuf);
+  }
+  else
+#endif   
   length = recv(fd_r, readBuf, READBUF_SIZE, 0);
 
   if (length <= 0)
diff -Nru ircd-hybrid-old/src/s_auth.c ircd-hybrid/src/s_auth.c
--- ircd-hybrid-old/src/s_auth.c	2004-01-26 06:35:20 +0300
+++ ircd-hybrid/src/s_auth.c	2004-04-20 10:01:21 +0400
@@ -53,6 +53,7 @@
 #include "s_stats.h"
 #include "send.h"
 #include "memory.h"
+#include "ssl.h"
 
 /*
  * a bit different approach
@@ -85,8 +86,16 @@
   REPORT_HOST_TOOLONG
 };
 
+#ifdef HAVE_LIBCRYPTO
+#define sendheader(c, r) \
+   if (IsSSL(c)) \
+     safe_SSL_write(c, HeaderMessages[(r)].message, HeaderMessages[(r)].length); \
+   else \
+     send((c)->localClient->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   
 
 /*
  * Ok, the original was confusing.
@@ -397,6 +406,9 @@
 start_auth(struct Client *client)
 {
   struct AuthRequest *auth = NULL;
+  
+  if (client->flags & FLAGS_DOINGAUTH)
+    return;
 
   assert(client != NULL);
 
@@ -415,6 +427,8 @@
   gethost_byaddr(&client->localClient->ip, client->localClient->dns_query);
   SetDNSPending(auth);
   dlinkAdd(auth, &auth->dns_node, &auth_doing_dns_list);
+  
+  client->flags |= FLAGS_DOINGAUTH;  
 
   if(ConfigFileEntry.disable_auth == 0)
     (void)start_auth_query(auth);
diff -Nru ircd-hybrid-old/src/s_bsd.c ircd-hybrid/src/s_bsd.c
--- ircd-hybrid-old/src/s_bsd.c	2003-09-20 02:13:13 +0400
+++ ircd-hybrid/src/s_bsd.c	2004-04-20 10:10:49 +0400
@@ -49,6 +49,7 @@
 #include "s_stats.h"
 #include "send.h"
 #include "memory.h"
+#include "ssl.h"
 
 #ifndef IN_LOOPBACKNET
 #define IN_LOOPBACKNET        0x7f
@@ -66,6 +67,9 @@
 static PF comm_connect_timeout;
 static void comm_connect_dns_callback(void *vptr, struct DNSReply *reply);
 static PF comm_connect_tryconnect;
+#ifdef HAVE_LIBCRYPTO
+static void comm_tryssl_callback(int fd, struct Client *new_client);
+#endif
 
 /* close_all_connections() can be used *before* the system come up! */
 void
@@ -376,6 +380,9 @@
   struct Client*     new_client;
   socklen_t len = sizeof(struct irc_ssaddr);
   struct irc_ssaddr   irn;
+#ifdef HAVE_LIBCRYPTO
+  int new_ssl = 0;
+#endif  
   assert(NULL != listener);
 
 #ifdef USE_IAUTH
@@ -443,12 +450,60 @@
   
   new_client->localClient->listener  = listener;
   ++listener->ref_count;
+  
+#ifdef HAVE_LIBCRYPTO
+  if ((listener->is_ssl) && !(new_client->ssl))
+  {
+    new_ssl = 1;
+    new_client->ssl = NULL;
+    
+    /*SSL client init */
+    if((new_client->ssl = SSL_new(ServerInfo.ctx)) == NULL)
+    {
+      dlink_node * m;
+      m = dlinkFind(&unknown_list, new_client);
+      if (m)
+        dlinkDeleteNode(m, &unknown_list);
+      report_error(L_ALL, "Could not create new ssl connection %s :%s",
+          get_listener_name(listener), errno);
+      ServerStats->is_ref++;
+      free_client(new_client);
+      return;
+    }
+    
+    SetSSL(new_client);
+  }
+#endif  
 
   if (!set_non_blocking(new_client->localClient->fd))
     report_error(L_ALL, NONB_ERROR_MSG, get_client_name(new_client, SHOW_IP), errno);
   if (!disable_sock_options(new_client->localClient->fd))
     report_error(L_ALL, OPT_ERROR_MSG, get_client_name(new_client, SHOW_IP), errno);
-  start_auth(new_client);
+
+#ifdef HAVE_LIBCRYPTO
+  if (IsSSL(new_client) && new_ssl)
+  {
+    SSL_set_fd(new_client->ssl, new_client->localClient->fd);
+    if (!safe_SSL_accept(new_client, new_client->localClient->fd))
+    {
+      dlink_node * m;
+      m = dlinkFind(&unknown_list, new_client);
+      if (m)
+        dlinkDeleteNode(m, &unknown_list);
+      SSL_set_shutdown(new_client->ssl, SSL_RECEIVED_SHUTDOWN);
+      SSL_smart_shutdown(new_client->ssl);
+      SSL_free(new_client->ssl);
+      ServerStats->is_ref++;
+      free_client(new_client);
+      return;
+    }
+    comm_setselect(fd, FDLIST_SERVER, COMM_SELECT_READ|COMM_SELECT_WRITE,
+                   comm_tryssl_callback, new_client, 0);
+  }
+#endif    
+  
+  if(new_ssl != 1)
+    start_auth(new_client);
 }
 
 /*
@@ -747,6 +802,35 @@
  comm_connect_callback(fd, COMM_OK);
 }
 
+#ifdef HAVE_LIBCRYPTO
+static void
+comm_tryssl_callback(int fd, struct Client *new_client)
+{
+  if (IsSSL(new_client))
+  {
+    printf("comm_tryssl_callback called\n");
+    if (!SSL_is_init_finished(new_client->ssl))
+    {
+      if (!safe_SSL_accept(new_client, new_client->localClient->fd))
+      {
+        //dead_link_on_read(new_client, errno);
+        return;
+      }
+      else
+      {
+        comm_setselect(fd, FDLIST_SERVER, COMM_SELECT_READ|COMM_SELECT_WRITE,
+                      comm_tryssl_callback, new_client, 0);
+        return;
+      }
+    }
+    else if (!IsDoingAuth(new_client))
+    {
+      start_auth(new_client);
+    }
+  }
+}
+#endif
+
 /*
  * comm_errorstr() - return an error string for the given error condition
  */
diff -Nru ircd-hybrid-old/src/send.c ircd-hybrid/src/send.c
--- ircd-hybrid-old/src/send.c	2004-02-24 06:36:20 +0300
+++ ircd-hybrid/src/send.c	2004-04-20 10:08:40 +0400
@@ -42,6 +42,7 @@
 #include "s_log.h"
 #include "memory.h"
 #include "hook.h"
+#include "ssl.h"
 
 #define LOG_BUFSIZE 2048
 
@@ -276,6 +277,17 @@
 #endif
     do {
       first = to->localClient->buf_sendq.blocks.head->data;
+#ifdef HAVE_LIBCRYPTO
+      if (IsSSL(to))
+      {
+        retlen = safe_SSL_write(to, first->data, first->size);
+        printf("safe_ssl_write: writing: %s\n", first->data);
+        printf("safe_ssl_write: %d written\n", retlen);
+	if (retlen <= 0)
+          break;
+      }
+      else
+#endif
       if ((retlen = send(to->localClient->fd, first->data,
                          first->size, 0)) <= 0)
         break;
diff -Nru ircd-hybrid-old/src/ssl.c ircd-hybrid/src/ssl.c
--- ircd-hybrid-old/src/ssl.c	1970-01-01 03:00:00 +0300
+++ ircd-hybrid/src/ssl.c	2004-04-20 10:01:21 +0400
@@ -0,0 +1,188 @@
+/*
+ *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ *  ssl.c: Client ssl connections.
+ *
+ *  Copyright (C) 2003 by the past and present ircd coders, and others.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ *
+ * $Id: ssl.c,v 1.0 2003/12/03 21:22:43 Sakura Exp $
+ *
+ */
+
+#include "stdinc.h"
+#include "common.h"
+#include "s_conf.h"
+#include "ssl.h"
+#include "send.h"
+#include "s_bsd.h"
+
+#define SAFE_SSL_READ  1
+#define SAFE_SSL_WRITE  2
+#define SAFE_SSL_ACCEPT  3
+
+#ifdef HAVE_LIBCRYPTO
+
+static int fatal_ssl_error(int, int, struct Client *);
+
+int safe_SSL_read(struct Client *acptr, void *buf, int sz)
+{
+  int len, ssl_err;
+
+  len = SSL_read(acptr->ssl, buf, sz);
+
+  if (len <= 0) {
+    switch (ssl_err = SSL_get_error(acptr->ssl, len)) {
+      case SSL_ERROR_SYSCALL:
+        if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) {
+      case SSL_ERROR_WANT_READ:
+        errno = EWOULDBLOCK;
+          return -1;
+        }
+      case SSL_ERROR_SSL:
+        if (errno == EAGAIN)
+          return -1;
+      default:
+        return fatal_ssl_error(ssl_err, SAFE_SSL_READ, acptr);
+    }
+  }
+  return len;
+}
+
+int safe_SSL_write(struct Client *acptr, const void *buf, int sz)
+{
+  int len, ssl_err;
+
+  len = SSL_write(acptr->ssl, buf, sz);
+  if (len <= 0) {
+    switch (ssl_err = SSL_get_error(acptr->ssl, len)) {
+      case SSL_ERROR_SYSCALL:
+        if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) {
+      case SSL_ERROR_WANT_WRITE:
+        errno = EWOULDBLOCK;
+          return 0;
+        }
+      case SSL_ERROR_SSL:
+        if (errno == EAGAIN)
+          return 0;
+      default:
+        return fatal_ssl_error(ssl_err, SAFE_SSL_WRITE, acptr);
+    }
+  }
+  return len;
+}
+
+int safe_SSL_accept(struct Client *acptr, int fd)
+{
+
+  int ssl_err;
+
+  if ((ssl_err = SSL_accept(acptr->ssl)) <= 0) {
+    switch (ssl_err = SSL_get_error(acptr->ssl, ssl_err)) {
+      case SSL_ERROR_SYSCALL:
+        if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
+      case SSL_ERROR_WANT_READ:
+      case SSL_ERROR_WANT_WRITE:
+        /* handshake will be completed later . . */
+        return 1;
+      default:
+        return fatal_ssl_error(ssl_err, SAFE_SSL_ACCEPT, acptr);
+    }
+  /* NOTREACHED */
+  return 0;
+  }
+  return 1;
+}
+
+int SSL_smart_shutdown(SSL * ssl)
+{
+  int i;
+  int rc;
+
+  rc = 0;
+  for (i = 0; i < 4; i++) {
+    if ((rc = SSL_shutdown(ssl)))
+      break;
+  }
+
+  return rc;
+}
+
+static int fatal_ssl_error(int ssl_error, int where, struct Client *sptr)
+{
+  int errtmp = errno;
+  char *errstr = strerror(errtmp);
+  char *ssl_errstr, *ssl_func;
+
+  switch (where) {
+    case SAFE_SSL_READ:
+      ssl_func = "SSL_read()";
+      break;
+    case SAFE_SSL_WRITE:
+      ssl_func = "SSL_write()";
+      break;
+    case SAFE_SSL_ACCEPT:
+      ssl_func = "SSL_accept()";
+      break;
+    default:
+      ssl_func = "undefined SSL func [this is a bug]";
+  }
+  
+  switch(ssl_error) {
+    case SSL_ERROR_NONE:
+      ssl_errstr = "No error";
+      break;
+    case SSL_ERROR_SSL:
+      ssl_errstr = "Internal OpenSSL error or protocol error";
+      break;
+    case SSL_ERROR_WANT_READ:
+      ssl_errstr = "OpenSSL functions requested a read()";
+      break;
+    case SSL_ERROR_WANT_WRITE:
+      ssl_errstr = "OpenSSL functions requested a write()";
+      break;
+    case SSL_ERROR_WANT_X509_LOOKUP:
+      ssl_errstr = "OpenSSL requested a X509 lookup which didn`t arrive";
+      break;
+    case SSL_ERROR_SYSCALL:
+      ssl_errstr = "Underlying syscall error";
+      break;
+    case SSL_ERROR_ZERO_RETURN:
+      ssl_errstr = "Underlying socket operation returned zero";
+      break;
+    case SSL_ERROR_WANT_CONNECT:
+      ssl_errstr = "OpenSSL functions wanted a connect()";
+      break;
+    default:
+      ssl_errstr = "Unknown OpenSSL error (huh?)";
+  }
+  
+  sendto_realops_flags(UMODE_ALL, L_ALL,
+	               "%s to %s!%s@%s aborted with error (%s). [%s]",
+		       ssl_func, *sptr->name ? sptr->name : " <unknown>",
+		       *sptr->username ? sptr->username : "<unregistered>", 
+		       sptr->host, (errno > 0) ? " " : " no ",
+		       ssl_errstr);
+			   
+  report_error(L_ADMIN, "%s to aborted (%s)",
+               ssl_func, errno);
+  report_error(L_OPER, "%s to aborted (%s)",
+               ssl_func, errno);
+
+  sptr->flags |= FLAGS_DEADSOCKET;
+  return 0;
+}
+#endif
diff -Nru ircd-hybrid-old/src/tools.c ircd-hybrid/src/tools.c
--- ircd-hybrid-old/src/tools.c	2003-10-24 15:38:44 +0400
+++ ircd-hybrid/src/tools.c	2004-04-20 10:01:21 +0400
@@ -27,7 +27,7 @@
 
 #include "stdinc.h"
 #include "tools.h"
-
+#include "list.h"
 
 #ifndef NDEBUG
 /*
@@ -133,6 +133,11 @@
   list->length--;
 }
 
+void dlinkDeleteNode(dlink_node *m, dlink_list *list)
+{
+    dlinkDelete(m, list);
+    free_dlink_node(m);
+}
 
 /*
  * dlinkFind
