diff --git a/Changes b/Changes index 440d7efac..bce70c999 100644 --- a/Changes +++ b/Changes @@ -1432,3 +1432,4 @@ seen. gmtime warning still there - Added some technical documentation in doc/technical. Docs include: 005.txt, base64.txt, token.txt, protoctl.txt, and vl.txt - Send +f and +L in correct part of 005. +- Fixed SSL linking, again.. diff --git a/include/ssl.h b/include/ssl.h index bf5ac8e1e..a54b978db 100644 --- a/include/ssl.h +++ b/include/ssl.h @@ -17,4 +17,4 @@ extern int ircd_SSL_accept(aClient *acptr, int fd); extern int ircd_SSL_connect(aClient *acptr); extern int SSL_smart_shutdown(SSL *ssl); extern int ircd_SSL_client_handshake(aClient *acptr); - +extern void SSL_set_nonblocking(SSL *s); diff --git a/include/struct.h b/include/struct.h index aea5d1c79..7097ec28c 100644 --- a/include/struct.h +++ b/include/struct.h @@ -195,8 +195,10 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */ #define BOOT_AUTODIE 64 #define BOOT_NOFORK 128 -#define STAT_LOG -6 /* logfile for -x */ -#define STAT_CONNECTING -4 +#define STAT_LOG -7 /* logfile for -x */ +#define STAT_CONNECTING -6 +#define STAT_SSL_CONNECT_HANDSHAKE -5 +#define STAT_SSL_ACCEPT_HANDSHAKE -4 #define STAT_HANDSHAKE -3 #define STAT_ME -2 #define STAT_UNKNOWN -1 @@ -216,6 +218,13 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */ #define IsClient(x) ((x)->status == STAT_CLIENT) #define IsLog(x) ((x)->status == STAT_LOG) +#ifdef USE_SSL +#define IsSSLAcceptHandshake(x) ((x)->status == STAT_SSL_ACCEPT_HANDSHAKE) +#define IsSSLConnectHandshake(x) ((x)->status == STAT_SSL_CONNECT_HANDSHAKE) +#define SetSSLAcceptHandshake(x) ((x)->status = STAT_SSL_ACCEPT_HANDSHAKE) +#define SetSSLConnectHandshake(x) ((x)->status = STAT_SSL_CONNECT_HANDSHAKE) +#endif + #define SetConnecting(x) ((x)->status = STAT_CONNECTING) #define SetHandshake(x) ((x)->status = STAT_HANDSHAKE) #define SetMe(x) ((x)->status = STAT_ME) @@ -267,7 +276,6 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */ #define FLAGS_SHUNNED 0x4000000 #ifdef USE_SSL #define FLAGS_SSL 0x10000000 -#define FLAGS_SSL_HSHAKE 0x20000000 #endif #define FLAGS_DCCBLOCK 0x40000000 #define FLAGS_MAP 0x80000000 /* Show this entry in /map */ @@ -331,7 +339,6 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */ #ifdef STRIPBADWORDS #define IsFilteringWords(x) ((x)->umodes & UMODE_STRIPBADWORDS) #endif - #define IsNetAdmin(x) ((x)->umodes & UMODE_NETADMIN) #define IsCoAdmin(x) ((x)->umodes & UMODE_COADMIN) #define IsSAdmin(x) ((x)->umodes & UMODE_SADMIN) diff --git a/src/ircd.c b/src/ircd.c index bdabf8ea4..0c65ef143 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -643,7 +643,11 @@ extern TS check_pings(TS currenttime) * Check UNKNOWN connections - if they have been in this state * for > 100s, close them. */ - if (IsUnknown(cptr)) + if (IsUnknown(cptr) +#ifdef USE_SSL + || (IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr)) +#endif + ) if (cptr->firsttime ? ((TStime() - cptr->firsttime) > 100) : 0) (void)exit_client(cptr, cptr, &me, diff --git a/src/s_bsd.c b/src/s_bsd.c index d68fb7b63..27e10b1e7 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -144,6 +144,7 @@ extern fdlist socks_fdlist; # endif # endif #endif +void start_of_normal_client_handshake(aClient *acptr); /* winlocal */ void add_local_client(aClient* cptr) @@ -1139,7 +1140,7 @@ void set_non_blocking(int fd, aClient *cptr) */ aClient *add_connection(aClient *cptr, int fd) { - Link lin; + Link lin; aClient *acptr; ConfigItem_ban *bconf; int i, j; @@ -1225,25 +1226,6 @@ add_con_refuse: goto add_con_refuse; } acptr->port = ntohs(addr.SIN_PORT); - if (SHOWCONNECTINFO) { - /* Start of the very first DNS check */ - if (!(cptr->umodes & LISTENER_SSL)) - FDwrite(fd, REPORT_DO_DNS, R_do_dns); - } - lin.flags = ASYNC_CLIENT; - lin.value.cptr = acptr; - Debug((DEBUG_DNS, "lookup %s", acptr->sockhost)); - acptr->hostp = gethost_byaddr((char *)&acptr->ip, &lin); - - if (!acptr->hostp) - SetDNS(acptr); - else - { - if (SHOWCONNECTINFO) - if (!(cptr->umodes & LISTENER_SSL)) - FDwrite(fd, REPORT_FIN_DNSC, R_fin_dnsc); - } - nextdnscheck = 1; } acptr->fd = fd; @@ -1257,9 +1239,14 @@ add_con_refuse: { ((ConfigItem_listen *) acptr->listener->class)->clients++; } + add_client_to_list(acptr); + set_non_blocking(acptr->fd, acptr); + set_sock_opts(acptr->fd, acptr); + IRCstats.unknown++; #ifdef USE_SSL if (cptr->umodes & LISTENER_SSL) { + SetSSLAcceptHandshake(acptr); if ((acptr->ssl = SSL_new(ctx_server)) == NULL) { goto add_con_refuse; @@ -1273,16 +1260,35 @@ add_con_refuse: goto add_con_refuse; } } + else #endif - add_client_to_list(acptr); - set_non_blocking(acptr->fd, acptr); - set_sock_opts(acptr->fd, acptr); - IRCstats.unknown++; - start_auth(acptr); - + start_of_normal_client_handshake(acptr); return acptr; } +void start_of_normal_client_handshake(aClient *acptr) +{ + Link lin; + acptr->status = STAT_UNKNOWN; + if (SHOWCONNECTINFO) { + sendto_one(acptr, REPORT_DO_DNS); + } + lin.flags = ASYNC_CLIENT; + lin.value.cptr = acptr; + Debug((DEBUG_DNS, "lookup %s", acptr->sockhost)); + acptr->hostp = gethost_byaddr((char *)&acptr->ip, &lin); + + if (!acptr->hostp) + SetDNS(acptr); + else + { + if (SHOWCONNECTINFO) + sendto_one(acptr, REPORT_FIN_DNSC); + } + nextdnscheck = 1; + start_auth(acptr); +} + /* ** read_packet ** @@ -1584,16 +1590,6 @@ int read_message(time_t delay, fdlist *listp) if (IsLog(cptr)) continue; -#ifdef USE_SSL - if (cptr->ssl != NULL && IsSSL(cptr) && - !SSL_is_init_finished((SSL *)cptr->ssl)) - { - if (IsDead(cptr) || (IsConnecting(cptr) ? !ircd_SSL_connect(cptr) : !ircd_SSL_accept(cptr, cptr->fd))) - close_connection(cptr); - continue; - } -#endif - if (DoingAuth(cptr)) { auth++; @@ -1831,8 +1827,33 @@ deadsocket: } } length = 1; /* for fall through case */ - if (!NoNewLine(cptr) || FD_ISSET(cptr->fd, &read_set)) + if ((!NoNewLine(cptr) || FD_ISSET(cptr->fd, &read_set)) +#ifdef USE_SSL + && + !(IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr)) +#endif + ) length = read_packet(cptr, &read_set); + if ((cptr->ssl != NULL) && + (IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(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) + { + length = -1; + } + } + else + { + if (IsSSLAcceptHandshake(cptr)) + start_of_normal_client_handshake(cptr); + else + completed_connection(cptr); + + } + } if (length > 0) flush_connections(cptr); if ((length != FLUSH_BUFFER) && IsDead(cptr)) diff --git a/src/ssl.c b/src/ssl.c index 574711e0a..8b9c3b414 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -145,7 +145,7 @@ void init_ctx_server(void) void init_ctx_client(void) { - ctx_client = SSL_CTX_new(SSLv3_client_method()); + ctx_client = SSL_CTX_new(SSLv23_client_method()); if (!ctx_client) { ircd_log(LOG_ERROR, "Failed to do SSL CTX new client"); @@ -304,6 +304,12 @@ int SSL_change_fd(SSL *s, int fd) return 1; } +void SSL_set_nonblocking(SSL *s) +{ + BIO_set_nbio(SSL_get_rbio(s),1); + BIO_set_nbio(SSL_get_wbio(s),1); +} + char *ssl_get_cipher(SSL *ssl) { static char buf[400]; @@ -394,14 +400,15 @@ int ircd_SSL_client_handshake(aClient *acptr) { int ssl_err; - acptr->ssl = SSL_new(ctx_server); + acptr->ssl = SSL_new(ctx_client); if (!acptr->ssl) { - sendto_realops("Failed to SSL_new(ctx_server)"); + sendto_realops("Failed to SSL_new(ctx_client)"); return FALSE; } SSL_set_fd(acptr->ssl, acptr->fd); SSL_set_connect_state(acptr->ssl); + SSL_set_nonblocking(acptr->ssl); if (acptr->serv && acptr->serv->conf->ciphers) { if (SSL_set_cipher_list((SSL *)acptr->ssl, @@ -420,9 +427,11 @@ int ircd_SSL_client_handshake(aClient *acptr) case -1: return -1; case 0: - return 1; + SetSSLConnectHandshake(acptr); + return 0; case 1: - return (completed_connection(acptr)); + /* SSL_init_finished in s_bsd will finish the job */ + return 1; default: return -1; } @@ -455,7 +464,6 @@ int ircd_SSL_accept(aClient *acptr, int fd) { int ircd_SSL_connect(aClient *acptr) { int ssl_err; - if((ssl_err = SSL_connect((SSL *)acptr->ssl)) <= 0) { switch(ssl_err = SSL_get_error((SSL *)acptr->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: