mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-08 03:03:13 +02:00
- Added support for STARTTLS. This allows users to switch to SSL without
having to use a special SSL-only port, they can simply switch to SSL on any port. This is currently only supported by few clients (such as KVIrc 4). This functionality can be disabled by setting set::ssl::options::no-starttls, for example if you don't want to offer SSL to your users and only want it to be used for server to server links. Naturally, the IRCd must be compiled with SSL support for STARTTLS to work. - Fixed SSL_ERROR_WANT_READ in IRCd_ssl_write()
This commit is contained in:
@@ -1850,3 +1850,11 @@
|
||||
stuff instead of hacking configure directly :P .
|
||||
- Made the timesynch log output more clear and understandable.
|
||||
- Added an 'UnrealIRCd started' log message on startup.
|
||||
- Added support for STARTTLS. This allows users to switch to SSL without
|
||||
having to use a special SSL-only port, they can simply switch to SSL on
|
||||
any port. This is currently only supported by few clients (such as KVIrc 4).
|
||||
This functionality can be disabled by setting set::ssl::options::no-starttls,
|
||||
for example if you don't want to offer SSL to your users and only want it
|
||||
to be used for server to server links.
|
||||
Naturally, the IRCd must be compiled with SSL support for STARTTLS to work.
|
||||
- Fixed SSL_ERROR_WANT_READ in IRCd_ssl_write()
|
||||
|
||||
@@ -2468,6 +2468,8 @@ set {
|
||||
Disallows connections from people with self-signed certificates.</p>
|
||||
<p><font class="set">set::ssl::options::verify-certificate;</font><br>
|
||||
Makes Unreal determine if the SSL certificate is valid before allowing connection.</p>
|
||||
<p><font class="set">set::ssl::options::no-starttls;</font><br>
|
||||
Disable STARTTLS. STARTTLS allows clients to use SSL on regular (non-SSL) ports.</p>
|
||||
<p><font class="set">set::throttle::period <timevalue></font><br>
|
||||
How long a user must wait before reconnecting more than set::throttle::connections
|
||||
times.</p>
|
||||
|
||||
+6
-1
@@ -232,6 +232,7 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
||||
|
||||
#define STAT_LOG -7 /* logfile for -x */
|
||||
#define STAT_CONNECTING -6
|
||||
#define STAT_SSL_STARTTLS_HANDSHAKE -8
|
||||
#define STAT_SSL_CONNECT_HANDSHAKE -5
|
||||
#define STAT_SSL_ACCEPT_HANDSHAKE -4
|
||||
#define STAT_HANDSHAKE -3
|
||||
@@ -254,9 +255,11 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
||||
#define IsLog(x) ((x)->status == STAT_LOG)
|
||||
|
||||
#ifdef USE_SSL
|
||||
#define IsSSLStartTLSHandshake(x) ((x)->status == STAT_SSL_STARTTLS_HANDSHAKE)
|
||||
#define IsSSLAcceptHandshake(x) ((x)->status == STAT_SSL_ACCEPT_HANDSHAKE)
|
||||
#define IsSSLConnectHandshake(x) ((x)->status == STAT_SSL_CONNECT_HANDSHAKE)
|
||||
#define IsSSLHandshake(x) (IsSSLAcceptHandshake(x) || IsSSLConnectHandshake(x))
|
||||
#define IsSSLHandshake(x) (IsSSLAcceptHandshake(x) || IsSSLConnectHandshake(x) | IsSSLStartTLSHandshake(x))
|
||||
#define SetSSLStartTLSHandshake(x) ((x)->status = STAT_SSL_STARTTLS_HANDSHAKE)
|
||||
#define SetSSLAcceptHandshake(x) ((x)->status = STAT_SSL_ACCEPT_HANDSHAKE)
|
||||
#define SetSSLConnectHandshake(x) ((x)->status = STAT_SSL_CONNECT_HANDSHAKE)
|
||||
#endif
|
||||
@@ -935,6 +938,8 @@ typedef struct {
|
||||
#define SSLFLAG_FAILIFNOCERT 0x1
|
||||
#define SSLFLAG_VERIFYCERT 0x2
|
||||
#define SSLFLAG_DONOTACCEPTSELFSIGNED 0x4
|
||||
#define SSLFLAG_NOSTARTTLS 0x8
|
||||
|
||||
struct Client {
|
||||
struct Client *next, *prev, *hnext;
|
||||
anUser *user; /* ...defined, if this is a User */
|
||||
|
||||
+6
-1
@@ -188,7 +188,8 @@ MOD_FILES=SRC/MODULES/L_COMMANDS.C SRC/MODULES/M_CHGHOST.C SRC/MODULES/M_SDESC.C
|
||||
SRC/MODULES/M_NICK.C SRC/MODULES/M_USER.C SRC/MODULES/M_MODE.C \
|
||||
SRC/MODULES/M_WATCH.C SRC/MODULES/M_PART.C SRC/MODULES/M_JOIN.C \
|
||||
SRC/MODULES/M_MOTD.C SRC/MODULES/M_OPERMOTD.C SRC/MODULES/M_BOTMOTD.C \
|
||||
SRC/MODULES/M_LUSERS.C SRC/MODULES/M_NAMES.C SRC/MODULES/M_SVSNOLAG.C
|
||||
SRC/MODULES/M_LUSERS.C SRC/MODULES/M_NAMES.C SRC/MODULES/M_SVSNOLAG.C \
|
||||
SRC/MODULES/M_STARTTLS.C
|
||||
|
||||
DLL_FILES=SRC/MODULES/M_CHGHOST.DLL SRC/MODULES/M_SDESC.DLL SRC/MODULES/M_SETIDENT.DLL \
|
||||
SRC/MODULES/M_SETNAME.DLL SRC/MODULES/M_SETHOST.DLL SRC/MODULES/M_CHGIDENT.DLL \
|
||||
@@ -224,6 +225,7 @@ DLL_FILES=SRC/MODULES/M_CHGHOST.DLL SRC/MODULES/M_SDESC.DLL SRC/MODULES/M_SETIDE
|
||||
SRC/MODULES/M_WATCH.DLL SRC/MODULES/M_PART.DLL SRC/MODULES/M_JOIN.DLL \
|
||||
SRC/MODULES/M_MOTD.DLL SRC/MODULES/M_OPERMOTD.DLL SRC/MODULES/M_BOTMOTD.DLL \
|
||||
SRC/MODULES/M_LUSERS.DLL SRC/MODULES/M_NAMES.DLL SRC/MODULES/M_SVSNOLAG.DLL \
|
||||
SRC/MODULES/M_STARTTLS.DLL \
|
||||
SRC/MODULES/CLOAK.DLL
|
||||
|
||||
|
||||
@@ -783,6 +785,9 @@ src/modules/cloak.dll: src/modules/cloak.c $(INCLUDES)
|
||||
src/modules/m_svsnolag.dll: src/modules/m_svsnolag.c $(INCLUDES)
|
||||
$(CC) $(MODCFLAGS) src/modules/m_svsnolag.c $(MODLFLAGS)
|
||||
|
||||
src/modules/m_starttls.dll: src/modules/m_starttls.c $(INCLUDES)
|
||||
$(CC) $(MODCFLAGS) src/modules/m_starttls.c $(MODLFLAGS)
|
||||
|
||||
dummy:
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ R_MODULES= \
|
||||
m_connect.so m_dccallow.so m_userip.so m_nick.so m_user.so \
|
||||
m_mode.so m_watch.so m_part.so m_join.so m_motd.so m_opermotd.so \
|
||||
m_botmotd.so m_lusers.so m_names.so m_svsnolag.so m_addmotd.so \
|
||||
m_svslusers.so
|
||||
m_svslusers.so m_starttls.so
|
||||
|
||||
#note change of .c to .o
|
||||
COMMANDS=m_sethost.o m_chghost.o m_chgident.o m_setname.o m_setident.o \
|
||||
@@ -76,7 +76,7 @@ COMMANDS=m_sethost.o m_chghost.o m_chgident.o m_setname.o m_setident.o \
|
||||
m_svsfline.o m_dccdeny.o m_undccdeny.o m_whowas.o \
|
||||
m_connect.o m_dccallow.o m_userip.o m_nick.o m_user.o \
|
||||
m_mode.o m_watch.o m_part.o m_join.o m_motd.o m_opermotd.o \
|
||||
m_botmotd.o m_lusers.o m_names.o m_svsnolag.o
|
||||
m_botmotd.o m_lusers.o m_names.o m_svsnolag.o m_starttls.o
|
||||
|
||||
|
||||
MODULES=commands.so cloak.so $(R_MODULES)
|
||||
@@ -407,6 +407,9 @@ m_names.o: m_names.c $(INCLUDES)
|
||||
m_svsnolag.o: m_svsnolag.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -c m_svsnolag.c
|
||||
|
||||
m_starttls.o: m_starttls.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -c m_starttls.c
|
||||
|
||||
#############################################################################
|
||||
# .so's section
|
||||
#############################################################################
|
||||
@@ -819,6 +822,10 @@ m_svsnolag.so: m_svsnolag.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o m_svsnolag.so m_svsnolag.c
|
||||
|
||||
m_starttls.so: m_starttls.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o m_starttls.so m_starttls.c
|
||||
|
||||
#############################################################################
|
||||
# and now the remaining modules...
|
||||
#############################################################################
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* IRC - Internet Relay Chat, src/modules/m_starttls.c
|
||||
* (C) 2009 Syzop & The UnrealIRCd Team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "msg.h"
|
||||
#include "proto.h"
|
||||
#include "channel.h"
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "h.h"
|
||||
#ifdef STRIPBADWORDS
|
||||
#include "badwords.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "version.h"
|
||||
#endif
|
||||
|
||||
DLLFUNC CMD_FUNC(m_starttls);
|
||||
|
||||
#define MSG_STARTTLS "STARTTLS"
|
||||
|
||||
ModuleHeader MOD_HEADER(m_starttls)
|
||||
= {
|
||||
"m_starttls",
|
||||
"$Id$",
|
||||
"command /starttls",
|
||||
"3.2-b8-1",
|
||||
NULL
|
||||
};
|
||||
|
||||
DLLFUNC int MOD_INIT(m_starttls)(ModuleInfo *modinfo)
|
||||
{
|
||||
CommandAdd(modinfo->handle, MSG_STARTTLS, NULL, m_starttls, MAXPARA, M_UNREGISTERED);
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
DLLFUNC int MOD_LOAD(m_starttls)(int module_load)
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
DLLFUNC int MOD_UNLOAD(m_starttls)(int module_unload)
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
DLLFUNC CMD_FUNC(m_starttls)
|
||||
{
|
||||
if (!MyConnect(sptr) || !IsUnknown(sptr))
|
||||
return 0;
|
||||
#ifndef USE_SSL
|
||||
/* sendnotice(sptr, "This server does not support SSL"); */
|
||||
/* or numeric 691? */
|
||||
/* actually... it's probably best to just act like we don't know this command...? */
|
||||
sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS");
|
||||
return 0;
|
||||
#else
|
||||
if (iConf.ssl_options & SSLFLAG_NOSTARTTLS)
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "STARTTLS");
|
||||
return 0;
|
||||
}
|
||||
if (IsSecure(sptr))
|
||||
{
|
||||
sendto_one(sptr, ":%s 691 %s :STARTTLS failed. Already using TLS.", me.name, sptr->name);
|
||||
return 0;
|
||||
}
|
||||
dbuf_delete(&sptr->recvQ, 1000000); /* Clear up any remaining plaintext commands */
|
||||
sendto_one(sptr, ":%s 670 %s :STARTTLS successful, go ahead with TLS handshake", me.name, sptr->name);
|
||||
// ^^ FIXME, use: RPL_STARTTLS
|
||||
send_queued(sptr);
|
||||
|
||||
SetSSLStartTLSHandshake(sptr);
|
||||
Debug((DEBUG_DEBUG, "Starting SSL handshake (due to STARTTLS) for %s", sptr->sockhost));
|
||||
if ((sptr->ssl = SSL_new(ctx_server)) == NULL)
|
||||
goto fail;
|
||||
sptr->flags |= FLAGS_SSL;
|
||||
SSL_set_fd(sptr->ssl, sptr->fd);
|
||||
SSL_set_nonblocking(sptr->ssl);
|
||||
if (!ircd_SSL_accept(sptr, sptr->fd)) {
|
||||
Debug((DEBUG_DEBUG, "Failed SSL accept handshake in instance 1: %s", sptr->sockhost));
|
||||
SSL_set_shutdown(sptr->ssl, SSL_RECEIVED_SHUTDOWN);
|
||||
SSL_smart_shutdown(sptr->ssl);
|
||||
SSL_free(sptr->ssl);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* HANDSHAKE IN PROGRESS */
|
||||
return 0;
|
||||
fail:
|
||||
/* Failure */
|
||||
sendto_one(sptr, ":%s 691 %s :STARTTLS failed", me.name, sptr->name); // FIXME, use: ERR_STARTTLS
|
||||
sptr->ssl = NULL;
|
||||
sptr->flags &= ~FLAGS_SSL;
|
||||
SetUnknown(sptr);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
+11
-4
@@ -1972,21 +1972,24 @@ deadsocket:
|
||||
!(DoingDNS(cptr) || DoingAuth(cptr))
|
||||
#ifdef USE_SSL
|
||||
&&
|
||||
!(IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr))
|
||||
!(IsSSLHandshake(cptr))
|
||||
#endif
|
||||
)
|
||||
length = read_packet(cptr, &read_set);
|
||||
#ifdef USE_SSL
|
||||
if ((length != FLUSH_BUFFER) && (cptr->ssl != NULL) &&
|
||||
(IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr)) &&
|
||||
IsSSLHandshake(cptr) &&
|
||||
FD_ISSET(cptr->fd, &read_set))
|
||||
{
|
||||
if (!SSL_is_init_finished(cptr->ssl))
|
||||
{
|
||||
if (IsDead(cptr) || IsSSLAcceptHandshake(cptr) ? !ircd_SSL_accept(cptr, cptr->fd) : ircd_SSL_connect(cptr) < 0)
|
||||
if (IsDead(cptr) ||
|
||||
(IsSSLAcceptHandshake(cptr) || IsSSLStartTLSHandshake(cptr)) ? !ircd_SSL_accept(cptr, cptr->fd) : ircd_SSL_connect(cptr) < 0)
|
||||
{
|
||||
length = -1;
|
||||
}
|
||||
/* if (IsSSLStartTLSHandshake(cptr))
|
||||
length = read_packet(cptr, &read_set); */
|
||||
}
|
||||
if (SSL_is_init_finished(cptr->ssl))
|
||||
{
|
||||
@@ -1995,10 +1998,14 @@ deadsocket:
|
||||
Debug((DEBUG_ERROR, "ssl: start_of_normal_client_handshake(%s)", cptr->sockhost));
|
||||
start_of_normal_client_handshake(cptr);
|
||||
}
|
||||
else
|
||||
else if (IsSSLConnectHandshake(cptr))
|
||||
{
|
||||
Debug((DEBUG_ERROR, "ssl: completed_connection", cptr->name));
|
||||
completed_connection(cptr);
|
||||
} else if (IsSSLStartTLSHandshake(cptr))
|
||||
{
|
||||
SetUnknown(cptr);
|
||||
/* STARTTLS is now complete. We could send something, but I don't know why... */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -295,6 +295,7 @@ static OperFlag _SSLFlags[] = {
|
||||
{ SSLFLAG_FAILIFNOCERT, "fail-if-no-clientcert" },
|
||||
{ SSLFLAG_DONOTACCEPTSELFSIGNED, "no-self-signed" },
|
||||
{ SSLFLAG_VERIFYCERT, "verify-certificate" },
|
||||
{ SSLFLAG_NOSTARTTLS, "no-starttls" }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -726,7 +726,7 @@ static char *replies[] = {
|
||||
/* 667 */ NULL,
|
||||
/* 668 */ NULL,
|
||||
/* 669 */ NULL,
|
||||
/* 670 */ NULL, /* kineircd */
|
||||
/* 670 RPL_STARTTLS */ ":%s 670 %s :STARTTLS successful, go ahead with TLS handshake", /* kineircd */
|
||||
/* 671 RPL_WHOISSECURE */ ":%s 671 %s %s :%s", /* our variation on the kineircd numeric */
|
||||
/* 672 */ NULL, /* ithildin */
|
||||
/* 673 */ NULL, /* ithildin */
|
||||
@@ -747,7 +747,7 @@ static char *replies[] = {
|
||||
/* 688 */ NULL, /* kineircd */
|
||||
/* 689 */ NULL, /* kineircd */
|
||||
/* 690 */ NULL, /* kineircd */
|
||||
/* 691 */ NULL,
|
||||
/* 691 ERR_STARTTLS */ ":%s 691 %s :%s",
|
||||
/* 692 */ NULL,
|
||||
/* 693 */ NULL,
|
||||
/* 694 */ NULL,
|
||||
|
||||
@@ -490,6 +490,9 @@ int ircd_SSL_write(aClient *acptr, const void *buf, int sz)
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
SET_ERRNO(P_EWOULDBLOCK);
|
||||
return -1;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
SET_ERRNO(P_EWOULDBLOCK); /* is this correct? next write will block if not read, so sounds right... */
|
||||
return -1;
|
||||
case SSL_ERROR_SSL:
|
||||
if(ERRNO == EAGAIN)
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user