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