TLS/SSL support: code changes.
This adds the required code to enable ssl/tls support during compile and run time, respectively.
This commit is contained in:
parent
ebf5edfd87
commit
ef3327d372
52
configure.in
52
configure.in
|
@ -309,6 +309,52 @@ if test "$x_io_backend" = "none"; then
|
|||
AC_MSG_ERROR([No useabe IO API activated/found!?])
|
||||
fi
|
||||
|
||||
# use SSL?
|
||||
|
||||
AC_ARG_WITH(openssl,
|
||||
[ --with-openssl enable SSL support using OpenSSL],
|
||||
[ if test "$withval" = "yes"; then
|
||||
if test "$withval" != "yes"; then
|
||||
CFLAGS="-I$withval/include $CFLAGS"
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval/lib $LDFLAGS"
|
||||
fi
|
||||
AC_CHECK_LIB(crypto, BIO_s_mem)
|
||||
AC_CHECK_LIB(ssl, SSL_library_init)
|
||||
AC_CHECK_FUNCS(SSL_library_init, x_ssl_openssl=yes,
|
||||
AC_MSG_ERROR([Can't enable openssl])
|
||||
)
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(gnutls,
|
||||
[ --with-gnutls enable SSL support using gnutls],
|
||||
[ if test "$withval" = "yes"; then
|
||||
if test "$withval" != "yes"; then
|
||||
CFLAGS="-I$withval/include $CFLAGS"
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval/lib $LDFLAGS"
|
||||
fi
|
||||
AC_CHECK_LIB(gnutls, gnutls_global_init)
|
||||
AC_CHECK_FUNCS(gnutls_global_init, x_ssl_gnutls=yes,
|
||||
AC_MSG_ERROR([Can't enable gnutls])
|
||||
)
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
x_ssl_lib="no"
|
||||
if test "$x_ssl_gnutls" = "yes"; then
|
||||
if test "$x_ssl_openssl" = "yes";then
|
||||
AC_MSG_ERROR([Cannot enable both gnutls and openssl])
|
||||
fi
|
||||
x_ssl_lib=gnutls
|
||||
fi
|
||||
if test "$x_ssl_openssl" = "yes"; then
|
||||
x_ssl_lib=openssl
|
||||
fi
|
||||
|
||||
# use TCP wrappers?
|
||||
|
||||
x_tcpwrap_on=no
|
||||
|
@ -588,7 +634,11 @@ echo $ECHO_N " I/O backend: $ECHO_C"
|
|||
echo "\"$x_io_backend\""
|
||||
|
||||
echo $ECHO_N " IPv6 protocol: $ECHO_C"
|
||||
echo "$x_ipv6_on"
|
||||
echo $ECHO_N "$x_ipv6_on $ECHO_C"
|
||||
|
||||
echo $ECHO_N " SSL support: $ECHO_C"
|
||||
echo "$x_ssl_lib"
|
||||
|
||||
echo
|
||||
|
||||
# -eof-
|
||||
|
|
|
@ -21,7 +21,7 @@ LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
|
|||
sbin_PROGRAMS = ngircd
|
||||
|
||||
ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
|
||||
conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
|
||||
conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
|
||||
irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
|
||||
match.c numeric.c parse.c rendezvous.c resolve.c
|
||||
|
||||
|
@ -30,7 +30,7 @@ ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
|
|||
ngircd_LDADD = -lngportab -lngtool -lngipaddr
|
||||
|
||||
noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conn.h conn-func.h \
|
||||
conn-zip.h hash.h io.h irc.h irc-channel.h irc-info.h irc-login.h \
|
||||
conn-ssl.h conn-zip.h hash.h io.h irc.h irc-channel.h irc-info.h irc-login.h \
|
||||
irc-mode.h irc-op.h irc-oper.h irc-server.h irc-write.h lists.h log.h \
|
||||
match.h numeric.h parse.h rendezvous.h resolve.h \
|
||||
defines.h messages.h
|
||||
|
|
|
@ -281,6 +281,14 @@ array_free(array * a)
|
|||
a->used = 0;
|
||||
}
|
||||
|
||||
void
|
||||
array_free_wipe(array *a)
|
||||
{
|
||||
size_t bytes = a->allocated;
|
||||
if (bytes)
|
||||
memset(a->mem, 0, bytes);
|
||||
array_free(a);
|
||||
}
|
||||
|
||||
void *
|
||||
array_start(const array * const a)
|
||||
|
|
|
@ -76,6 +76,39 @@ static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
|
|||
#define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
|
||||
#endif
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
struct SSLOptions Conf_SSLOptions;
|
||||
|
||||
static void
|
||||
ConfSSL_Init(void)
|
||||
{
|
||||
free(Conf_SSLOptions.KeyFile);
|
||||
Conf_SSLOptions.KeyFile = NULL;
|
||||
|
||||
free(Conf_SSLOptions.CertFile);
|
||||
Conf_SSLOptions.CertFile = NULL;
|
||||
|
||||
free(Conf_SSLOptions.DHFile);
|
||||
Conf_SSLOptions.DHFile = NULL;
|
||||
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ConfSSL_Puts(void)
|
||||
{
|
||||
if (Conf_SSLOptions.KeyFile)
|
||||
printf( " SSLKeyFile = %s\n", Conf_SSLOptions.KeyFile);
|
||||
if (Conf_SSLOptions.CertFile)
|
||||
printf( " SSLCertFile = %s\n", Conf_SSLOptions.CertFile);
|
||||
if (Conf_SSLOptions.DHFile)
|
||||
printf( " SSLDHFile = %s\n", Conf_SSLOptions.DHFile);
|
||||
if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
|
||||
puts(" SSLKeyFilePassword = <secret>" );
|
||||
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *
|
||||
strdup_warn(const char *str)
|
||||
{
|
||||
|
@ -202,10 +235,16 @@ Conf_Test( void )
|
|||
printf( " MotdPhrase = %s\n", Conf_MotdPhrase );
|
||||
printf( " ChrootDir = %s\n", Conf_Chroot );
|
||||
printf( " PidFile = %s\n", Conf_PidFile);
|
||||
printf(" Listen = %s\n", Conf_ListenAddress);
|
||||
fputs(" Ports = ", stdout);
|
||||
|
||||
ports_puts(&Conf_ListenPorts);
|
||||
printf(" Listen = %s\n", Conf_ListenAddress);
|
||||
#ifdef SSL_SUPPORT
|
||||
fputs(" SSLPorts = ", stdout);
|
||||
ports_puts(&Conf_SSLOptions.ListenPorts);
|
||||
ConfSSL_Puts();
|
||||
#endif
|
||||
|
||||
pwd = getpwuid( Conf_UID );
|
||||
if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name );
|
||||
else printf( " ServerUID = %ld\n", (long)Conf_UID );
|
||||
|
@ -248,6 +287,9 @@ Conf_Test( void )
|
|||
printf( " Name = %s\n", Conf_Server[i].name );
|
||||
printf( " Host = %s\n", Conf_Server[i].host );
|
||||
printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
|
||||
#ifdef SSL_SUPPORT
|
||||
printf( " SSLConnect = %s\n", Conf_Server[i].SSLConnect?"yes":"no");
|
||||
#endif
|
||||
printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
|
||||
printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
|
||||
printf( " Group = %d\n", Conf_Server[i].group );
|
||||
|
@ -543,7 +585,9 @@ Read_Config( bool ngircd_starting )
|
|||
strcpy( section, "" );
|
||||
Init_Server_Struct( &New_Server );
|
||||
New_Server_Idx = NONE;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
ConfSSL_Init();
|
||||
#endif
|
||||
/* Read configuration file */
|
||||
while( true ) {
|
||||
if( ! fgets( str, LINE_LEN, fd )) break;
|
||||
|
@ -923,6 +967,37 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if( strcasecmp( Var, "SSLPorts" ) == 0 ) {
|
||||
ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if( strcasecmp( Var, "SSLKeyFile" ) == 0 ) {
|
||||
assert(Conf_SSLOptions.KeyFile == NULL );
|
||||
Conf_SSLOptions.KeyFile = strdup_warn(Arg);
|
||||
return;
|
||||
}
|
||||
if( strcasecmp( Var, "SSLCertFile" ) == 0 ) {
|
||||
assert(Conf_SSLOptions.CertFile == NULL );
|
||||
Conf_SSLOptions.CertFile = strdup_warn(Arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if( strcasecmp( Var, "SSLKeyFilePassword" ) == 0 ) {
|
||||
assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
|
||||
if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
|
||||
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Could not copy %s: %s!",
|
||||
NGIRCd_ConfFile, Line, Var, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if( strcasecmp( Var, "SSLDHFile" ) == 0 ) {
|
||||
assert(Conf_SSLOptions.DHFile == NULL);
|
||||
Conf_SSLOptions.DHFile = strdup_warn( Arg );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
|
||||
NGIRCd_ConfFile, Line, Var);
|
||||
} /* Handle_GLOBAL */
|
||||
|
@ -1032,6 +1107,12 @@ Handle_SERVER( int Line, char *Var, char *Arg )
|
|||
NGIRCd_ConfFile, Line, port );
|
||||
return;
|
||||
}
|
||||
#ifdef SSL_SUPPORT
|
||||
if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
|
||||
New_Server.SSLConnect = Check_ArgIsTrue(Arg);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if( strcasecmp( Var, "Group" ) == 0 ) {
|
||||
/* Server group */
|
||||
#ifdef HAVE_ISDIGIT
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include "portab.h"
|
||||
#include "tool.h"
|
||||
#include "ng_ipaddr.h"
|
||||
#include "resolve.h"
|
||||
#include "conf-ssl.h"
|
||||
|
||||
|
||||
typedef struct _Conf_Oper
|
||||
{
|
||||
|
@ -46,8 +49,23 @@ typedef struct _Conf_Server
|
|||
CONN_ID conn_id; /* ID of server connection or NONE */
|
||||
ng_ipaddr_t bind_addr; /* source address to use for outgoing connections */
|
||||
ng_ipaddr_t dst_addr[2]; /* list of addresses to connect to */
|
||||
#ifdef SSL_SUPPORT
|
||||
bool SSLConnect; /* connect() using SSL? */
|
||||
#endif
|
||||
} CONF_SERVER;
|
||||
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
struct SSLOptions {
|
||||
char *KeyFile;
|
||||
char *CertFile;
|
||||
char *DHFile;
|
||||
array ListenPorts;
|
||||
array KeyFilePassword;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _Conf_Channel
|
||||
{
|
||||
char name[CHANNEL_NAME_LEN]; /* Name of the channel */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define CONN_MODULE
|
||||
|
||||
#include "portab.h"
|
||||
#include "conf-ssl.h"
|
||||
#include "io.h"
|
||||
|
||||
#include "imp.h"
|
||||
|
@ -58,6 +59,7 @@
|
|||
#include "ngircd.h"
|
||||
#include "client.h"
|
||||
#include "conf.h"
|
||||
#include "conn-ssl.h"
|
||||
#include "conn-zip.h"
|
||||
#include "conn-func.h"
|
||||
#include "log.h"
|
||||
|
@ -99,6 +101,11 @@ int deny_severity = LOG_ERR;
|
|||
|
||||
static void server_login PARAMS((CONN_ID idx));
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
extern struct SSLOptions Conf_SSLOptions;
|
||||
static void cb_connserver_login_ssl PARAMS((int sock, short what));
|
||||
static void cb_clientserver_ssl PARAMS((int sock, short what));
|
||||
#endif
|
||||
static void cb_Read_Resolver_Result PARAMS(( int sock, UNUSED short what));
|
||||
static void cb_Connect_to_Server PARAMS(( int sock, UNUSED short what));
|
||||
static void cb_clientserver PARAMS((int sock, short what));
|
||||
|
@ -112,6 +119,22 @@ cb_listen(int sock, short irrelevant)
|
|||
}
|
||||
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
static void
|
||||
cb_listen_ssl(int sock, short irrelevant)
|
||||
{
|
||||
int fd;
|
||||
(void) irrelevant;
|
||||
fd = New_Connection(sock);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
NumConnections++;
|
||||
io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
cb_connserver(int sock, UNUSED short what)
|
||||
{
|
||||
|
@ -166,6 +189,13 @@ cb_connserver(int sock, UNUSED short what)
|
|||
if (res >= 0) /* connect succeeded, remove all additional addresses */
|
||||
memset(&Conf_Server[res].dst_addr, 0, sizeof(&Conf_Server[res].dst_addr));
|
||||
Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING );
|
||||
#ifdef SSL_SUPPORT
|
||||
if ( Conn_OPTION_ISSET( &My_Connections[idx], CONN_SSL_CONNECT )) {
|
||||
io_event_setcb( sock, cb_connserver_login_ssl );
|
||||
io_event_add( sock, IO_WANTWRITE|IO_WANTREAD );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
server_login(idx);
|
||||
}
|
||||
|
||||
|
@ -185,24 +215,88 @@ server_login(CONN_ID idx)
|
|||
}
|
||||
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
static void
|
||||
cb_connserver_login_ssl(int sock, short unused)
|
||||
{
|
||||
CONN_ID idx = Socket2Index(sock);
|
||||
|
||||
assert(idx >= 0);
|
||||
if (idx < 0) {
|
||||
io_close(sock);
|
||||
return;
|
||||
}
|
||||
(void) unused;
|
||||
switch (ConnSSL_Connect( &My_Connections[idx])) {
|
||||
case 1: break;
|
||||
case 0: LogDebug("ConnSSL_Connect: not ready");
|
||||
return;
|
||||
case -1:
|
||||
Log(LOG_INFO, "SSL connection on socket %d failed", sock);
|
||||
Conn_Close(idx, "Can't connect!", NULL, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Log( LOG_INFO, "SSL Connection %d with \"%s:%d\" established.", idx,
|
||||
My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
|
||||
|
||||
server_login(idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
cb_clientserver(int sock, short what)
|
||||
{
|
||||
CONN_ID idx = Socket2Index( sock );
|
||||
if (idx <= NONE) {
|
||||
#ifdef DEBUG
|
||||
Log(LOG_WARNING, "WTF: cb_clientserver wants to write on unknown socket?!");
|
||||
CONN_ID idx = Socket2Index(sock);
|
||||
|
||||
assert(idx >= 0);
|
||||
|
||||
if (idx < 0) {
|
||||
io_close(sock);
|
||||
return;
|
||||
}
|
||||
#ifdef SSL_SUPPORT
|
||||
if (what & IO_WANTREAD || (Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_WANT_WRITE)))
|
||||
Read_Request( idx ); /* if TLS layer needs to write additional data, call Read_Request instead so SSL/TLS can continue */
|
||||
#else
|
||||
if (what & IO_WANTREAD)
|
||||
Read_Request( idx );
|
||||
#endif
|
||||
if (what & IO_WANTWRITE)
|
||||
Handle_Write( idx );
|
||||
}
|
||||
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
static void
|
||||
cb_clientserver_ssl(int sock, short what)
|
||||
{
|
||||
CONN_ID idx = Socket2Index(sock);
|
||||
|
||||
assert(idx >= 0);
|
||||
|
||||
if (idx < 0) {
|
||||
io_close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ConnSSL_Accept(&My_Connections[idx])) {
|
||||
case 1: break; /* OK */
|
||||
case 0: return; /* EAGAIN: this callback will be invoked again by the io layer */
|
||||
default:
|
||||
Conn_Close( idx, "Socket closed!", "SSL accept error", false );
|
||||
return;
|
||||
}
|
||||
if (what & IO_WANTREAD)
|
||||
Read_Request( idx );
|
||||
Read_Request(idx);
|
||||
|
||||
if (what & IO_WANTWRITE)
|
||||
Handle_Write( idx );
|
||||
Handle_Write(idx);
|
||||
|
||||
io_event_setcb(sock, cb_clientserver); /* SSL handshake completed */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
GLOBAL void
|
||||
|
@ -323,8 +417,12 @@ Conn_InitListeners( void )
|
|||
|
||||
while (listen_addr) {
|
||||
ngt_TrimStr(listen_addr);
|
||||
if (*listen_addr)
|
||||
if (*listen_addr) {
|
||||
created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
|
||||
#ifdef SSL_SUPPORT
|
||||
created += ports_initlisteners(&Conf_SSLOptions.ListenPorts, listen_addr, cb_listen_ssl);
|
||||
#endif
|
||||
}
|
||||
|
||||
listen_addr = strtok(NULL, ",");
|
||||
}
|
||||
|
@ -477,6 +575,44 @@ NewListener(const char *listen_addr, UINT16 Port)
|
|||
return sock;
|
||||
} /* NewListener */
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
/*
|
||||
* SSL/TLS connections require extra treatment:
|
||||
* When either CONN_SSL_WANT_WRITE or CONN_SSL_WANT_READ is set, we
|
||||
* need to take care of that first, before checking read/write buffers.
|
||||
* For instance, while we might have data in our write buffer, the
|
||||
* TLS/SSL protocol might need to read internal data first for TLS/SSL
|
||||
* writes to succeed.
|
||||
*
|
||||
* If this function returns true, such a condition is met and we have
|
||||
* to reverse the condition (check for read even if we've data to write,
|
||||
* do not check for read but writeability even if write-buffer is empty).
|
||||
*/
|
||||
static bool
|
||||
SSL_WantRead(const CONNECTION *c)
|
||||
{
|
||||
if (Conn_OPTION_ISSET(c, CONN_SSL_WANT_READ)) {
|
||||
io_event_add(c->sock, IO_WANTREAD);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool
|
||||
SSL_WantWrite(const CONNECTION *c)
|
||||
{
|
||||
if (Conn_OPTION_ISSET(c, CONN_SSL_WANT_WRITE)) {
|
||||
io_event_add(c->sock, IO_WANTWRITE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static inline bool
|
||||
SSL_WantRead(UNUSED const CONNECTION *c) { return false; }
|
||||
static inline bool
|
||||
SSL_WantWrite(UNUSED const CONNECTION *c) { return false; }
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* "Main Loop": Loop until shutdown or restart is signalled.
|
||||
|
@ -532,7 +668,8 @@ Conn_Handler(void)
|
|||
if (wdatalen > 0)
|
||||
#endif
|
||||
{
|
||||
/* Set the "WANTWRITE" flag on this socket */
|
||||
if (SSL_WantRead(&My_Connections[i]))
|
||||
continue;
|
||||
io_event_add(My_Connections[i].sock,
|
||||
IO_WANTWRITE);
|
||||
}
|
||||
|
@ -542,7 +679,10 @@ Conn_Handler(void)
|
|||
for (i = 0; i < Pool_Size; i++) {
|
||||
if (My_Connections[i].sock <= NONE)
|
||||
continue;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (SSL_WantWrite(&My_Connections[i]))
|
||||
continue; /* TLS/SSL layer needs to write data; deal with this first */
|
||||
#endif
|
||||
if (Resolve_INPROGRESS(&My_Connections[i].res_stat)) {
|
||||
/* Wait for completion of resolver sub-process ... */
|
||||
io_event_del(My_Connections[i].sock,
|
||||
|
@ -816,7 +956,12 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
|
|||
|
||||
/* Search client, if any (re-check!) */
|
||||
c = Conn_GetClient( Idx );
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
|
||||
Log( LOG_INFO, "SSL Connection %d shutting down", Idx );
|
||||
ConnSSL_Free(&My_Connections[Idx]);
|
||||
}
|
||||
#endif
|
||||
/* Shut down socket */
|
||||
if (! io_close(My_Connections[Idx].sock)) {
|
||||
/* Oops, we can't close the socket!? This is ... ugly! */
|
||||
|
@ -966,9 +1111,15 @@ Handle_Write( CONN_ID Idx )
|
|||
("Handle_Write() called for connection %d, %ld bytes pending ...",
|
||||
Idx, wdatalen);
|
||||
|
||||
len = write(My_Connections[Idx].sock,
|
||||
array_start(&My_Connections[Idx].wbuf), wdatalen );
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
|
||||
len = ConnSSL_Write(&My_Connections[Idx], array_start(&My_Connections[Idx].wbuf), wdatalen);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
len = write(My_Connections[Idx].sock,
|
||||
array_start(&My_Connections[Idx].wbuf), wdatalen );
|
||||
}
|
||||
if( len < 0 ) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return true;
|
||||
|
@ -1170,6 +1321,11 @@ Read_Request( CONN_ID Idx )
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL))
|
||||
len = ConnSSL_Read( &My_Connections[Idx], readbuf, sizeof(readbuf));
|
||||
else
|
||||
#endif
|
||||
len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
|
||||
if (len == 0) {
|
||||
Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
|
||||
|
@ -1551,7 +1707,16 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|||
Init_Conn_Struct( new_sock );
|
||||
Conf_Server[Server].conn_id = NONE;
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
|
||||
&Conf_Server[Server] ))
|
||||
{
|
||||
Log(LOG_ALERT, "Could not initialize SSL for outgoing connection");
|
||||
Conn_Close( new_sock, "Could not initialize SSL for outgoing connection", NULL, false );
|
||||
Init_Conn_Struct( new_sock );
|
||||
Conf_Server[Server].conn_id = NONE;
|
||||
}
|
||||
#endif
|
||||
LogDebug("Registered new connection %d on socket %d.",
|
||||
new_sock, My_Connections[new_sock].sock );
|
||||
Conn_OPTION_ADD( &My_Connections[new_sock], CONN_ISCONNECTING );
|
||||
|
@ -1773,4 +1938,19 @@ Conn_GetClient( CONN_ID Idx )
|
|||
return c ? c->client : NULL;
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
/* we cannot access My_Connections in irc-info.c */
|
||||
GLOBAL bool
|
||||
Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len)
|
||||
{
|
||||
return ConnSSL_GetCipherInfo(&My_Connections[Idx], buf, len);
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
Conn_UsesSSL(CONN_ID Idx)
|
||||
{
|
||||
return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL);
|
||||
}
|
||||
#endif
|
||||
/* -eof- */
|
||||
|
|
|
@ -28,7 +28,14 @@
|
|||
#define CONN_ZIP 4 /* zlib compressed link */
|
||||
#endif
|
||||
|
||||
#include "conf-ssl.h"
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
#define CONN_SSL_CONNECT 8 /* wait for ssl connect to finish */
|
||||
#define CONN_SSL 16 /* this connection is SSL encrypted */
|
||||
#define CONN_SSL_WANT_WRITE 32 /* SSL/TLS library needs to write protocol data */
|
||||
#define CONN_SSL_WANT_READ 64 /* SSL/TLS library needs to read protocol data */
|
||||
#endif
|
||||
typedef int CONN_ID;
|
||||
|
||||
#include "client.h"
|
||||
|
@ -74,6 +81,9 @@ typedef struct _Connection
|
|||
#ifdef ZLIB
|
||||
ZIPDATA zip; /* Compression information */
|
||||
#endif /* ZLIB */
|
||||
#ifdef SSL_SUPPORT
|
||||
struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */
|
||||
#endif
|
||||
} CONNECTION;
|
||||
|
||||
GLOBAL CONNECTION *My_Connections;
|
||||
|
@ -98,6 +108,12 @@ GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool In
|
|||
GLOBAL void Conn_SyncServerStruct PARAMS(( void ));
|
||||
|
||||
GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
|
||||
#ifdef SSL_SUPPORT
|
||||
GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
|
||||
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
|
||||
#else
|
||||
static inline bool Conn_UsesSSL(UNUSED CONN_ID Idx) { return false; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
|
|
|
@ -1167,6 +1167,23 @@ Show_MOTD_End(CLIENT *Client)
|
|||
return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
static bool Show_MOTD_SSLInfo(CLIENT *Client)
|
||||
{
|
||||
bool ret = true;
|
||||
char buf[COMMAND_LEN] = "Connected using Cipher ";
|
||||
|
||||
if (!Conn_GetCipherInfo(Client_Conn(Client), buf + 23, sizeof buf - 23))
|
||||
return true;
|
||||
|
||||
if (!Show_MOTD_Sendline(Client, buf))
|
||||
ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline bool Show_MOTD_SSLInfo(UNUSED CLIENT *c) { return true; }
|
||||
#endif
|
||||
|
||||
GLOBAL bool
|
||||
IRC_Show_MOTD( CLIENT *Client )
|
||||
|
@ -1181,13 +1198,17 @@ IRC_Show_MOTD( CLIENT *Client )
|
|||
return DISCONNECTED;
|
||||
if (!Show_MOTD_Sendline(Client, Conf_MotdPhrase))
|
||||
return DISCONNECTED;
|
||||
|
||||
return Show_MOTD_End(Client);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = fopen( Conf_MotdFile, "r" );
|
||||
if( ! fd ) {
|
||||
Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
|
||||
if (Conn_UsesSSL(Client_Conn(Client))) {
|
||||
if (!Show_MOTD_Start(Client))
|
||||
return DISCONNECTED;
|
||||
goto out;
|
||||
}
|
||||
return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
|
||||
}
|
||||
|
||||
|
@ -1205,6 +1226,9 @@ IRC_Show_MOTD( CLIENT *Client )
|
|||
}
|
||||
}
|
||||
fclose(fd);
|
||||
out:
|
||||
if (!Show_MOTD_SSLInfo(Client))
|
||||
return DISCONNECTED;
|
||||
return Show_MOTD_End(Client);
|
||||
} /* IRC_Show_MOTD */
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "defines.h"
|
||||
#include "resolve.h"
|
||||
#include "conn.h"
|
||||
#include "conf-ssl.h"
|
||||
#include "client.h"
|
||||
#include "channel.h"
|
||||
#include "conf.h"
|
||||
|
@ -367,6 +368,10 @@ Fill_Version( void )
|
|||
|
||||
strlcat( NGIRCd_VersionAddition, "ZLIB", sizeof NGIRCd_VersionAddition );
|
||||
#endif
|
||||
#ifdef SSL_SUPPORT
|
||||
if ( NGIRCd_VersionAddition[0] ) strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
|
||||
strlcat( NGIRCd_VersionAddition, "SSL", sizeof NGIRCd_VersionAddition );
|
||||
#endif
|
||||
#ifdef TCPWRAP
|
||||
if( NGIRCd_VersionAddition[0] )
|
||||
strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
|
||||
|
@ -465,7 +470,10 @@ NGIRCd_Rehash( void )
|
|||
|
||||
/* Create new pre-defined channels */
|
||||
Channel_InitPredefined( );
|
||||
|
||||
|
||||
if (!ConnSSL_InitLibrary())
|
||||
Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys");
|
||||
|
||||
/* Start listening on sockets */
|
||||
Conn_InitListeners( );
|
||||
|
||||
|
@ -726,6 +734,9 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
|
|||
if (initialized)
|
||||
return true;
|
||||
|
||||
if (!ConnSSL_InitLibrary())
|
||||
Log(LOG_WARNING, "Warning: Error during SSL initialization, continuing");
|
||||
|
||||
if( Conf_Chroot[0] ) {
|
||||
if( chdir( Conf_Chroot ) != 0 ) {
|
||||
Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
|
||||
|
|
Loading…
Reference in New Issue