From: Matthew Mondor Date: Thu, 13 Jan 2005 10:38:30 +0000 (+0000) Subject: Added OpenSSL support, ported from diff distributed against 1.4.x bahamut X-Git-Tag: rubiks-ircd-1-0-6~42 X-Git-Url: http://git.pulsar-zone.net/?a=commitdiff_plain;h=9f807accd5ce5a3d771a66d18bf9914ded633955;p=rubiks-ircd.git Added OpenSSL support, ported from diff distributed against 1.4.x bahamut --- diff --git a/configure b/configure index 7f5fb61..cb42f4c 100755 --- a/configure +++ b/configure @@ -5678,6 +5678,8 @@ if test "X$cf_enable_openssl" != "Xno" ; then echo "$as_me:$LINENO: result: $cf_openssl_basedir" >&5 echo "${ECHO_T}$cf_openssl_basedir" >&6 cf_enable_openssl="yes" + USESSL="-DUSE_SSL" + SSLLIB="-lssl" encryption="enabled" cat >>confdefs.h <<\_ACEOF #define HAVE_ENCRYPTION_ON 1 @@ -7726,6 +7728,8 @@ s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t +s,@USESSL@,$USESSL,;t t +s,@SSLLIB@,$SSLLIB,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t diff --git a/include/config.h b/include/config.h index 011829f..e52366c 100644 --- a/include/config.h +++ b/include/config.h @@ -18,7 +18,7 @@ * */ -/* $Id: config.h,v 1.4 2005/01/13 09:11:39 mmondor Exp $ */ +/* $Id: config.h,v 1.5 2005/01/13 10:35:43 mmondor Exp $ */ #ifndef __config_include__ #define __config_include__ @@ -570,6 +570,26 @@ */ #define FAKEHOST +/* SSL + * SSL support stolen from fqircd + */ +#ifdef USE_SSL +#define IRCDSSL_KPATH "ircd.key" +#define IRCDSSL_CPATH "ircd.crt" + +#define RECV_CHECK_SSL(from, buf, len) (IsSSL(from) && from->ssl) ?\ + safe_SSL_read(from, buf, len) :\ + recv(from->fd, buf, len, 0) +#define SEND_CHECK_SSL(to, buf, len) (IsSSL(to) && to->ssl) ?\ + safe_SSL_write(to, buf, len) :\ + send(to->fd, buf, len, 0) + +#define WRITEV_CHECK_SSL(to, iov, len) (IsSSL(to) && to->ssl) ?\ + safe_SSL_write(to,iov->iov_base,iov->iov_len) :\ + writev(to->fd, iov, len); +#endif + + /****************************************************************** * STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP * diff --git a/include/confparse.h b/include/confparse.h index c45c874..d3492d7 100644 --- a/include/confparse.h +++ b/include/confparse.h @@ -4,7 +4,7 @@ * Apply the GPL here. */ -/* $Id: confparse.h,v 1.2 2005/01/13 06:19:56 mmondor Exp $ */ +/* $Id: confparse.h,v 1.3 2005/01/13 10:35:43 mmondor Exp $ */ /* our structures */ @@ -288,6 +288,9 @@ sConf confporttab[] = {SCONFT_PORT, SCONFF_PORT, VARTYPE_INT}, {SCONFT_BIND, SCONFF_BIND, VARTYPE_NAME}, {SCONFT_IPMASK, SCONFF_IPMASK, VARTYPE_NAME}, +#ifdef USE_SSL + {SCONFT_TYPE, SCONFF_TYPE, VARTYPE_NAME}, +#endif {(char *) 0, 0, 0} }; diff --git a/include/h.h b/include/h.h index a14c10f..2f54788 100644 --- a/include/h.h +++ b/include/h.h @@ -25,7 +25,7 @@ * */ -/* $Id: h.h,v 1.1 2005/01/12 07:44:58 mmondor Exp $ */ +/* $Id: h.h,v 1.2 2005/01/13 10:35:43 mmondor Exp $ */ #include "send.h" #include "ircsprintf.h" @@ -336,3 +336,7 @@ void remove_from_list(DLink **, void *, DLink *); void print_list_memory(aClient *); #include "find.h" + +#ifdef USE_SSL +#include "ssl.h" +#endif diff --git a/include/numeric.h b/include/numeric.h index b21a88e..768f220 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -18,7 +18,7 @@ * */ -/* $Id: numeric.h,v 1.1 2005/01/12 07:44:58 mmondor Exp $ */ +/* $Id: numeric.h,v 1.2 2005/01/13 10:35:43 mmondor Exp $ */ #define RPL_WELCOME 001 @@ -88,6 +88,10 @@ #define RPL_SILELIST 271 #define RPL_ENDOFSILELIST 272 +#ifdef USE_SSL +#define RPL_USINGSSL 275 +#endif + #define RPL_NONE 300 #define RPL_AWAY 301 #define RPL_USERHOST 302 @@ -235,6 +239,10 @@ #define ERR_NONONREG 486 #define ERR_MSGSERVICES 487 +#ifdef USE_SSL +#define ERR_NOSSL 488 +#endif + #define ERR_NOOPERHOST 491 #define ERR_UMODEUNKNOWNFLAG 501 diff --git a/include/ssl.h b/include/ssl.h new file mode 100644 index 0000000..0435a6e --- /dev/null +++ b/include/ssl.h @@ -0,0 +1,11 @@ +#ifndef __SSL_INCLUDE__ +#define __SSL_INCLUDE__ + +int safe_SSL_read(aClient *, void *, int); +int safe_SSL_write(aClient *, const void *, int); +int safe_SSL_accept(aClient *, int); +int SSL_smart_shutdown(SSL *); +int initssl(void); +int rehash_ssl(void); + +#endif diff --git a/include/struct.h b/include/struct.h index 446936f..76275a3 100644 --- a/include/struct.h +++ b/include/struct.h @@ -20,7 +20,7 @@ * */ -/* $Id: struct.h,v 1.4 2005/01/13 06:21:18 mmondor Exp $ */ +/* $Id: struct.h,v 1.5 2005/01/13 10:35:43 mmondor Exp $ */ #ifndef __struct_include__ #define __struct_include__ @@ -50,6 +50,17 @@ #endif #endif +#ifdef USE_SSL + +#include /* OpenSSL stuff */ +#include +#include +#include +#include +#include + +#endif + #define REPORT_DO_DNS_ ":%s NOTICE AUTH :*** Looking up your hostname..." #define REPORT_FIN_DNS_ ":%s NOTICE AUTH :*** Found your hostname" #define REPORT_FIN_DNSC_ ":%s NOTICE AUTH :*** Found your hostname, cached" @@ -230,6 +241,9 @@ typedef struct MotdItem aMotd; #define FLAGS_RC4OUT 0x2000000 /* This link is rc4 encrypted. */ #define FLAGS_ZIPPED_IN 0x4000000 /* This link is gzipped. */ #define FLAGS_ZIPPED_OUT 0x8000000 /* This link is gzipped. */ +#ifdef USE_SSL +#define FLAGS_SSL 0x20000000 /* client is using SSL */ +#endif /* Capabilities of the ircd or clients */ @@ -291,9 +305,9 @@ typedef struct MotdItem aMotd; #define UMODE_h 0x20000 /* umode +h - Helper */ #define UMODE_m 0x40000 /* umode +m - spambot notices */ #define UMODE_R 0x80000 /* unmode +R - No non registered msgs */ -#ifdef DCCALLOW +/* #define UMODE_e */ #define UMODE_e 0x100000 /* umode +e - oper notices for the above +D */ -#endif +/* #endif */ #define UMODE_x 0x200000 /* umode +x - Squelch with notice */ #define UMODE_X 0x400000 /* umode +X - Squelch without notice */ #ifdef DCCALLOW @@ -303,6 +317,10 @@ typedef struct MotdItem aMotd; #define UMODE_j 0x2000000 /* umode +j - client rejection notices */ #define UMODE_K 0x4000000 /* umode +K - U: lined server kill messages */ #define UMODE_I 0x8000000 /* umode +I - invisible oper (masked) */ +#ifdef USE_SSL +#define UMODE_S 0x10000000 /* umode +S - SSL user */ +#endif + /* for sendto_ops_lev */ @@ -379,6 +397,9 @@ typedef struct MotdItem aMotd; #define IsUmodek(x) ((x)->umode & UMODE_k) #define IsUmodes(x) ((x)->umode & UMODE_s) #define IsUmodeI(x) ((x)->umode & UMODE_I) +#ifdef USE_SSL +#define IsUmodeS(x) ((x)->umode & UMODE_S) +#endif #define IsNoNonReg(x) ((x)->umode & UMODE_R) #define IsWSquelch(x) ((x)->umode & UMODE_x) #define IsSSquelch(x) ((x)->umode & UMODE_X) @@ -401,6 +422,11 @@ typedef struct MotdItem aMotd; #define SendGlobops(x) ((x)->umode & UMODE_g) #define SendChatops(x) ((x)->umode & UMODE_b) #define SendRnotice(x) ((x)->umode & UMODE_n) +#ifdef USE_SSL +#define IsSSL(x) ((x)->flags & FLAGS_SSL) +#define SetSSL(x) ((x)->flags |= FLAGS_SSL) +#define SetSSLUmode(x) ((x)->umode |= UMODE_S) +#endif #define NoMsgThrottle(x) ((x)->umode & UMODE_F) #define IsListening(x) ((x)->flags & FLAGS_LISTEN) #define IsLocal(x) ((x)->flags & FLAGS_LOCAL) @@ -758,6 +784,7 @@ struct Conf_Port char *allow; char *address; int port; + char *type; aListener *lstn; int legal; aPort *next; @@ -794,6 +821,12 @@ struct Listener { u_long ccount; /* total number of clients to connect here */ int clients; /* number of clients currently on this */ aPort *aport; /* link to the P: line I came from */ +#ifdef USE_SSL + long flags; + SSL *ssl; + X509 *client_cert; +#endif + }; @@ -987,6 +1020,10 @@ struct Client * this socket? */ int capabilities; /* what this server/client supports */ aClass *class; /* our current effective class */ +#ifdef USE_SSL + SSL *ssl; + X509 *client_cert; +#endif #ifdef MSG_TARGET_LIMIT struct { @@ -1240,6 +1277,10 @@ struct Channel #define MODE_MODREG 0x10000 #define MODE_LISTED 0x20000 #define MODE_JOINRATE 0x40000 +#ifdef USE_SSL +#define MODE_SSL 0x80000 +#endif + /* mode flags which take another parameter (With PARAmeterS) */ @@ -1463,6 +1504,8 @@ typedef struct SearchOptions /* internal defines for cptr->sockerr */ #define IRCERR_BUFALLOC -11 #define IRCERR_ZIP -12 +#define IRCERR_SSL -13 + #endif /* __struct_include__ */ diff --git a/src/Makefile.in b/src/Makefile.in index 3abbff2..2f7035a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ CC=@CC@ RM=@RM@ MV=@MV@ -IRCDLIBS=@LIBS@ ../zlib/libz.a +IRCDLIBS=@LIBS@ ../zlib/libz.a @SSLLIB@ INCLUDEDIR=-I../include OPENSSLINC=@SSL_INCLUDES@ ENGINE=@SENGINE@ @@ -9,7 +9,7 @@ CRYPTO=@ENCRYPT_SRC@ INSTALL=@INSTALL@ INSTALL_BIN=@INSTALL_PROGRAM@ INSTALL_DIR=@INSTALL_DIR@ -CFLAGS=@CFLAGS@ +CFLAGS=@CFLAGS@ RES_SRC = @@ -22,7 +22,7 @@ SOURCES = blalloc.c bsd.c channel.c clientlist.c clones.c confparse.c \ modules.c packet.c parse.c pcre.c res.c s_auth.c s_bsd.c s_conf.c \ s_debug.c s_err.c s_misc.c s_numeric.c s_serv.c s_user.c sbuf.c \ scache.c send.c struct.c support.c throttle.c userban.c whowas.c \ - zlink.c \ + zlink.c ssl.c \ $(ENGINE) $(CRYPTO) OBJECTS = $(SOURCES:.c=.o) version.o @@ -307,6 +307,8 @@ whowas.o: whowas.c ../include/struct.h ../include/config.h \ ../include/sbuf.h ../include/common.h ../include/sys.h \ ../include/numeric.h ../include/h.h ../include/send.h \ ../include/fdlist.h ../include/ircsprintf.h ../include/find.h +ssl.o: ssl.c \ +../include/ssl.h dh.o: dh.c \ ../include/patchlevel.h diff --git a/src/bsd.c b/src/bsd.c index 08cc2b0..dc4ba5c 100644 --- a/src/bsd.c +++ b/src/bsd.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bsd.c,v 1.1 2005/01/12 07:44:56 mmondor Exp $ */ +/* $Id: bsd.c,v 1.2 2005/01/13 10:35:43 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -84,10 +84,18 @@ int deliver_it(aClient *cptr, char *str, int len) writecalls++; #endif #ifdef WRITEV_IOV +#ifdef USE_SSL + retval = WRITEV_CHECK_SSL(cptr, iov, len); +#else retval = writev(cptr->fd, iov, len); +#endif +#else +#ifdef USE_SSL + retval = SEND_CHECK_SSL(cptr, str, len); #else retval = send(cptr->fd, str, len, 0); #endif +#endif /* * Convert WOULDBLOCK to a return of "0 bytes moved". This * should occur only if socket was non-blocking. Note, that all is diff --git a/src/channel.c b/src/channel.c index ae8182a..31ea9ef 100644 --- a/src/channel.c +++ b/src/channel.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: channel.c,v 1.1 2005/01/12 07:44:56 mmondor Exp $ */ +/* $Id: channel.c,v 1.2 2005/01/13 10:35:43 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -1026,6 +1026,11 @@ static void channel_modes(aClient *cptr, char *mbuf, char *pbuf, *mbuf++ = 'O'; if (chptr->mode.mode & MODE_MODREG) *mbuf++ = 'M'; +#ifdef USE_SSL + if (chptr->mode.mode & MODE_SSL) + *mbuf++ = 'S'; +#endif + #ifdef USE_CHANMODE_L if (chptr->mode.mode & MODE_LISTED) *mbuf++ = 'L'; @@ -1387,6 +1392,9 @@ static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, MODE_TOPICLIMIT, 't', MODE_REGONLY, 'R', MODE_INVITEONLY, 'i', MODE_NOCOLOR, 'c', MODE_OPERONLY, 'O', MODE_MODREG, 'M', +#ifdef USE_SSL + MODE_SSL, 'S', +#endif #ifdef USE_CHANMODE_L MODE_LISTED, 'L', #endif @@ -2173,6 +2181,13 @@ static int can_join(aClient *sptr, aChannel *chptr, char *key) r = "+l"; error = ERR_CHANNELISFULL; } +#ifdef USE_SSL + else if (chptr->mode.mode & MODE_SSL && !IsSSL(sptr) && !IsOper(sptr)) + { + r = "+S"; + error = ERR_NOSSL; + } +#endif else if (chptr->mode.mode & MODE_REGONLY && !IsRegNick(sptr)) error = ERR_NEEDREGGEDNICK; else if (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key))) @@ -4197,6 +4212,9 @@ int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]) SJ_MODEADD('M', MODE_MODREG); SJ_MODEADD('c', MODE_NOCOLOR); SJ_MODEADD('O', MODE_OPERONLY); +#ifdef USE_SSL + SJ_MODEADD('S', MODE_SSL); +#endif #ifdef USE_CHANMODE_L SJ_MODEADD('L', MODE_LISTED); #endif @@ -4356,6 +4374,10 @@ int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]) #ifdef USE_CHANMODE_L SJ_MODEPLUS('L', MODE_LISTED); #endif +#ifdef USE_SSL + SJ_MODEPLUS('S', MODE_SSL); +#endif + SJ_MODEMINUS('p', MODE_PRIVATE); SJ_MODEMINUS('s', MODE_SECRET); @@ -4371,6 +4393,9 @@ int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]) #ifdef USE_CHANMODE_L SJ_MODEMINUS('L', MODE_LISTED); #endif +#ifdef USE_SSL + SJ_MODEMINUS('S', MODE_SSL); +#endif } diff --git a/src/ircd.c b/src/ircd.c index d7d7076..cbd3194 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: ircd.c,v 1.1 2005/01/12 07:44:56 mmondor Exp $ */ +/* $Id: ircd.c,v 1.2 2005/01/13 10:35:44 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -656,6 +656,9 @@ main(int argc, char *argv[]) char tmp[PATH_MAX]; FILE *mcsfp; char *conferr; +#ifdef USE_SSL + extern int ssl_capable; +#endif if ((timeofday = time(NULL)) == -1) { @@ -895,6 +898,18 @@ main(int argc, char *argv[]) R_fail_id = strlen(REPORT_FAIL_ID); NOW = time(NULL); + +#ifdef USE_SSL + fprintf(stderr, "SSL: Trying to intialize SSL support . . .\n"); + if(!(ssl_capable = initssl())) + fprintf(stderr, "SSL: failure. (did you generate your " + "certificate ?)\nSSL: Server running with SSL " + "code disabled, consult the above error log for " + "details.\n"); + else + fprintf(stderr, "SSL: success.\n"); +#endif + init_sys(); forked = 1; diff --git a/src/m_who.c b/src/m_who.c index a556464..7d54061 100644 --- a/src/m_who.c +++ b/src/m_who.c @@ -20,7 +20,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: m_who.c,v 1.1 2005/01/12 07:44:56 mmondor Exp $ */ +/* $Id: m_who.c,v 1.2 2005/01/13 10:35:44 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -724,10 +724,19 @@ int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[]) } else { +#ifdef USE_SSL + i = 0; + status[i++]=(ac->user->away==NULL ? 'H' : 'G'); + status[i]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) && + IsAnOper(sptr) ? '%' : 0)); + status[((status[i]) ? ++i : i)]=(IsUmodeS(ac) ? 'S' : 0); + status[++i]=0; +#else status[0]=(ac->user->away==NULL ? 'H' : 'G'); status[1]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) && IsAnOper(sptr) ? '%' : 0)); status[2]=0; +#endif sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, wsopts.show_chan ? first_visible_channel(ac, sptr) : "*", ac->user->username, WHO_HOST(ac), @@ -765,6 +774,10 @@ int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[]) status[i++]=(ac->user->away==NULL ? 'H' : 'G'); status[i]=(IsAnOper(ac) ? '*' : ((IsInvisible(ac) && IsOper(sptr)) ? '%' : 0)); +#ifdef USE_SSL + status[((status[i]) ? ++i : i)]=(IsUmodeS(ac) ? 'S' : 0); +#endif + status[((status[i]) ? ++i : i)]=((cm->flags&CHFL_CHANOP) ? '@' : ((cm->flags&CHFL_VOICE) ? '+' : 0)); diff --git a/src/s_bsd.c b/src/s_bsd.c index 3af59b8..a0bf5ba 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: s_bsd.c,v 1.1 2005/01/12 07:44:57 mmondor Exp $ */ +/* $Id: s_bsd.c,v 1.2 2005/01/13 10:35:44 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -61,6 +61,8 @@ #include "fdlist.h" #include "fds.h" + + extern void engine_init(); extern fdlist default_fdlist; extern int forked; @@ -274,6 +276,10 @@ int add_listener(aPort *aport) struct sockaddr_in server; int ad[4], len = sizeof(server); char ipname[20]; +#ifdef USE_SSL + extern int ssl_capable; +#endif + memset(&lstn, 0, sizeof(aListener)); ad[0] = ad[1] = ad[2] = ad[3] = 0; @@ -360,6 +366,16 @@ int add_listener(aPort *aport) aport->lstn = lptr; set_listener_non_blocking(lptr->fd, lptr); + +#ifdef USE_SSL + if(aport->type && (strcmp(aport->type, "SSL")) == 0 && ssl_capable) { + SetSSL(lptr); + lptr->ssl = NULL; + lptr->client_cert = NULL; + } +#endif + + add_fd(lptr->fd, FDT_LISTENER, lptr); set_fd_flags(lptr->fd, FDF_WANTREAD); @@ -895,8 +911,20 @@ void close_connection(aClient *cptr) if (cptr->fd >= 0) { +#ifdef USE_SSL + if(!IsDead(cptr)) +#endif dump_connections(cptr->fd); local[cptr->fd] = NULL; +#ifdef USE_SSL + if(IsSSL(cptr) && cptr->ssl) { + SSL_set_shutdown(cptr->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(cptr->ssl); + SSL_free(cptr->ssl); + cptr->ssl = NULL; + } +#endif + del_fd(cptr->fd); close(cptr->fd); cptr->fd = -2; @@ -1299,6 +1327,45 @@ aClient *add_connection(aListener *lptr, int fd) start_auth(acptr); #endif check_client_fd(acptr); +#ifdef USE_SSL + if (IsSSL(lptr)) + { + extern SSL_CTX *ircdssl_ctx; + + acptr->ssl = NULL; + + /*SSL client init.*/ + if((acptr->ssl = SSL_new(ircdssl_ctx)) == NULL) + { + sendto_realops_lev(DEBUG_LEV, "SSL creation of " + "new SSL object failed [client %s]", + acptr->sockhost); + fprintf(stderr, "SSL creation of " + "new SSL object failed [client %s]\n", acptr->sockhost ); + ircstp->is_ref++; + acptr->fd = -2; + free_client(acptr); + return NULL ; + } + SetSSL(acptr); + set_non_blocking(fd, acptr); + set_sock_opts(fd, acptr); + SSL_set_fd(acptr->ssl, fd); + + if (!safe_SSL_accept(acptr, fd)) + { + SSL_set_shutdown(acptr->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(acptr->ssl); + SSL_free(acptr->ssl); + ircstp->is_ref++; + acptr->fd = -2; + free_client(acptr); + (void) close(fd); + return NULL; + } + } +#endif + return acptr; } @@ -1382,7 +1449,19 @@ int read_packet(aClient * cptr) if (!(IsPerson(cptr) && SBufLength(&cptr->recvQ) > MAX_CLIENT_RECVQ)) { errno = 0; - + +#ifdef USE_SSL +#if defined ( MAXBUFFERS ) + if (IsPerson(cptr)) + length = RECV_CHECK_SSL(cptr, readbuf, 8192 * sizeof(char)); + else + length = RECV_CHECK_SSL(cptr, readbuf, rcvbufmax * sizeof(char)); +#else + length = RECV_CHECK_SSL(cptr, readbuf, sizeof(readbuf)); +#endif + +#else + #if defined(MAXBUFFERS) if (IsPerson(cptr)) length = recv(cptr->fd, readbuf, 8192 * sizeof(char), 0); @@ -1392,6 +1471,8 @@ int read_packet(aClient * cptr) length = recv(cptr->fd, readbuf, sizeof(readbuf), 0); #endif +#endif + cptr->lasttime = timeofday; if (cptr->lasttime > cptr->since) cptr->since = cptr->lasttime; @@ -1561,6 +1642,15 @@ int readwrite_client(aClient *cptr, int isread, int iswrite) * - the socket is waiting for a connect() call * - the socket is blocked */ +#ifdef USE_SSL + if (cptr->ssl != NULL && IsSSL(cptr) && + !SSL_is_init_finished(cptr->ssl)) + { + if(IsDead(cptr) || (!safe_SSL_accept(cptr, cptr->fd))) + close_connection(cptr); + return 1; + } +#endif if(iswrite) { diff --git a/src/s_conf.c b/src/s_conf.c index 16c2dee..08954c7 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: s_conf.c,v 1.3 2005/01/13 08:04:03 mmondor Exp $ */ +/* $Id: s_conf.c,v 1.4 2005/01/13 10:35:45 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -196,6 +196,9 @@ free_oper(aOper *ptr) void free_port(aPort *ptr) { +#ifdef USE_SSL + MyFree(ptr->type); +#endif MyFree(ptr->allow); MyFree(ptr->address); MyFree(ptr); @@ -1262,6 +1265,19 @@ confadd_port(cVar *vars[], int lnum) tmp->type = NULL; x->port = atoi(tmp->value); } +#ifdef USE_SSL + else if(tmp->type && (tmp->type->flag & SCONFF_TYPE)) + { + if (x->type) + { + confparse_error("Multiple port types", lnum); + free_port(x); + return -1; + } + tmp->type = NULL; + DupString(x->type, tmp->value); + } +#endif } if(!(x->port > 0)) { diff --git a/src/s_err.c b/src/s_err.c index 565f831..7baca0f 100644 --- a/src/s_err.c +++ b/src/s_err.c @@ -300,7 +300,7 @@ static char *replies[] = /* 272 RPL_ENDOFSILELIST*/ ":%s 272 %s :End of /SILENCE list.", /* 273 */ NULL, /* 274 */ NULL, - /* 275 */ NULL, /* In use by Undernet */ + /* 275 */ ":%s 275 %s %s :is using a secure connection (SSL)", /* 276 */ NULL, /* 277 */ NULL, /* 278 */ NULL, @@ -552,7 +552,8 @@ static char *replies[] = "registered nick to private message %s", /* 487 ERR_MSGSERVICES */ ":%s 487 %s :Error! \"/msg %s\" is no longer supported. " "Use \"/msg %s@%s\" or \"/%s\" instead.", - /* 488 */ NULL, + /* 488 ERR_NOPRIVILEGES */ ":%s 488 %s :SSL Only channel (+S), You must connect " + "using SSL to join this channel.", /* 489 */ NULL, /* In use by Undernet */ /* 490 */ NULL, /* 491 ERR_NOOPERHOST */ ":%s 491 %s :No Oper block for your host", diff --git a/src/s_misc.c b/src/s_misc.c index ee7dc69..09e8228 100644 --- a/src/s_misc.c +++ b/src/s_misc.c @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: s_misc.c,v 1.2 2005/01/13 06:20:45 mmondor Exp $ */ +/* $Id: s_misc.c,v 1.3 2005/01/13 10:35:45 mmondor Exp $ */ #include #include "struct.h" @@ -683,7 +683,11 @@ exit_client(aClient *cptr, aClient *sptr, aClient *from, char *comment) } } #endif - if (sptr->fd >= 0) + if (sptr->fd >= 0 +#ifdef USE_SSL + && !IsDead(sptr) +#endif +) { if (cptr != NULL && sptr != cptr) sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)", diff --git a/src/s_serv.c b/src/s_serv.c index 7acba49..f045e12 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: s_serv.c,v 1.1 2005/01/12 07:44:57 mmondor Exp $ */ +/* $Id: s_serv.c,v 1.2 2005/01/13 10:35:45 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -2421,6 +2421,17 @@ m_rehash(aClient *cptr, aClient *sptr, int parc, char *parv[]) remove_simbans_match_flags(SBAN_CHAN|SBAN_TEMPORARY, 0); return 0; } +#ifdef USE_SSL + else if(mycmp(parv[1], "SSL") == 0) + { + sendto_ops("%s is reloading SSL support", parv[0]); + sendto_one(sptr, rpl_str(RPL_REHASHING), me.name, parv[0], + "SSL support"); + + rehash_ssl(); + } +#endif + } else { diff --git a/src/s_user.c b/src/s_user.c index 2db04b5..364bc6d 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: s_user.c,v 1.3 2005/01/13 06:20:45 mmondor Exp $ */ +/* $Id: s_user.c,v 1.4 2005/01/13 10:35:45 mmondor Exp $ */ #include "struct.h" #include "common.h" @@ -90,6 +90,9 @@ int user_modes[] = UMODE_x, 'x', UMODE_X, 'X', UMODE_j, 'j', +#ifdef USE_SSL + UMODE_S, 'S', +#endif UMODE_K, 'K', UMODE_I, 'I', 0, 0 @@ -998,9 +1001,16 @@ register_user(aClient *cptr, aClient *sptr, char *nick, char *username) client_set_fakehost(sptr,pwaconf); #endif +#ifdef USE_SSL + sendto_realops_lev(CCONN_LEV, "Client connecting: %s (%s@%s) [%s] {%d} %s", + nick, user->username, user->host, sptr->hostip, + sptr->class->name, IsSSL(sptr) ? "SSL" : ""); +#else + sendto_realops_lev(CCONN_LEV, "Client connecting: %s (%s@%s) [%s] {%s}", nick, user->username, user->host, sptr->hostip, sptr->class->name); +#endif send_lusers(sptr, sptr, 1, parv); @@ -2036,6 +2046,11 @@ m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (user->away) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, user->away); +#ifdef USE_SSL + if (IsUmodeS(acptr)) + sendto_one(sptr, rpl_str(RPL_USINGSSL), me.name, parv[0], name); +#endif + buf[0] = '\0'; if (IsAnOper(acptr)) @@ -2132,6 +2147,10 @@ do_user(char *nick, aClient *cptr, aClient *sptr, char *username, char *host, #ifndef NO_DEFAULT_INVISIBLE sptr->umode |= UMODE_i; #endif +#ifdef USE_SSL + if(IsSSL(sptr)) + SetSSLUmode(sptr); +#endif #ifdef NO_USER_SERVERKILLS sptr->umode &= ~UMODE_k; #endif diff --git a/src/ssl.c b/src/ssl.c new file mode 100644 index 0000000..554c504 --- /dev/null +++ b/src/ssl.c @@ -0,0 +1,292 @@ +/************************************************************************ + * IRC - Internet Relay Chat, src/ssl.c + * Copyright (C) 2002 Barnaba Marcello + * + * 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. + * + * SSL functions . . . + */ + +#include "struct.h" +#include "common.h" +#include "sys.h" +#include +#include "h.h" + +#ifdef USE_SSL + + +#define SAFE_SSL_READ 1 +#define SAFE_SSL_WRITE 2 +#define SAFE_SSL_ACCEPT 3 + +extern int errno; + +SSL_CTX *ircdssl_ctx; +int ssl_capable = 0; + +int initssl(void) +{ + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); + ircdssl_ctx = SSL_CTX_new(SSLv23_server_method()); + if (!ircdssl_ctx) { + ERR_print_errors_fp(stderr); + return 0; + } + if (SSL_CTX_use_certificate_file(ircdssl_ctx, + IRCDSSL_CPATH, SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp(stderr); + SSL_CTX_free(ircdssl_ctx); + return 0; + } + if (SSL_CTX_use_PrivateKey_file(ircdssl_ctx, + IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp(stderr); + SSL_CTX_free(ircdssl_ctx); + return 0; + } + if (!SSL_CTX_check_private_key(ircdssl_ctx)) { + fprintf(stderr, "Server certificate does not match Server key"); + SSL_CTX_free(ircdssl_ctx); + return 0; + } + return 1; +} + +static void disable_ssl(int do_errors) +{ + if(do_errors) + { + char buf[256]; + unsigned long e; + + while((e = ERR_get_error())) + { + ERR_error_string_n(e, buf, sizeof(buf) - 1); + sendto_realops("SSL ERROR: %s", buf); + } + } + + if(ircdssl_ctx) + SSL_CTX_free(ircdssl_ctx); + + sendto_ops("Disabling SSL support due to unrecoverable SSL errors. /Rehash again to retry."); + ssl_capable = 0; + + return; +} + +int rehash_ssl(void) +{ + if(ircdssl_ctx) + SSL_CTX_free(ircdssl_ctx); + + if(!(ircdssl_ctx = SSL_CTX_new(SSLv23_server_method()))) + { + disable_ssl(1); + return 0; + } + + if (SSL_CTX_use_certificate_file(ircdssl_ctx, + IRCDSSL_CPATH, SSL_FILETYPE_PEM) <= 0) + { + disable_ssl(1); + + return 0; + } + + if (SSL_CTX_use_PrivateKey_file(ircdssl_ctx, + IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0) + { + disable_ssl(1); + + return 0; + } + + if (!SSL_CTX_check_private_key(ircdssl_ctx)) + { + sendto_realops("SSL ERROR: Server certificate does not match server key"); + disable_ssl(0); + + return 0; + } + + return 1; +} + +static int fatal_ssl_error(int, int, aClient *); + +int safe_SSL_read(aClient *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 0; + } + case SSL_ERROR_SSL: + if(errno == EAGAIN) + return 0; + default: + return fatal_ssl_error(ssl_err, SAFE_SSL_READ, acptr); + } + } + return len; +} + +int safe_SSL_write(aClient *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: + case SSL_ERROR_WANT_READ: + 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(aClient *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 -1; + } + return 1; +} + +int SSL_smart_shutdown(SSL *ssl) { + char 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, aClient *sptr) +{ + /* don`t alter errno */ + 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] report to vjt@azzurra.org"; + } + + 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_lev(DEBUG_LEV, "%s to " + "%s!%s@%s aborted with%serror (%s). [%s]", + ssl_func, *sptr->name ? sptr->name : "", + (sptr->user && sptr->user->username) ? sptr->user-> + username : "", sptr->sockhost, + (errno > 0) ? " " : " no ", errstr, ssl_errstr); +#ifdef USE_SYSLOG + syslog(LOG_ERR, "SSL error in %s: %s [%s]", ssl_func, errstr, + ssl_errstr); +#endif + + /* if we reply() something here, we might just trigger another + * fatal_ssl_error() call and loop until a stack overflow... + * the client won`t get the ERROR : ... string, but this is + * the only way to do it. + * IRC protocol wasn`t SSL enabled .. --vjt + */ + + errno = errtmp ? errtmp : EIO; /* Stick a generic I/O error */ + sptr->sockerr = IRCERR_SSL; + sptr->flags |= FLAGS_DEADSOCKET; + return -1; +} +#endif