1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-28 03:26:38 +02:00

- Port the SSL code over to the evented I/O subsystem.

This commit is contained in:
William Pitcock
2012-10-05 14:19:54 +00:00
parent 97b643aad7
commit 25318ec24b
5 changed files with 102 additions and 108 deletions
+1
View File
@@ -808,3 +808,4 @@ extern aPendingNet *find_pending_net_by_numeric_butone(int numeric, aClient *exe
extern aClient *find_pending_net_duplicates(aClient *cptr, aClient **srv, int *numeric);
extern aClient *find_non_pending_net_duplicates(aClient *cptr);
extern void finish_auth(aClient *acptr);
extern void read_packet(int fd, int revents, void *data);
+1 -3
View File
@@ -6,10 +6,8 @@ extern SSL_METHOD *meth;
extern void init_ssl();
extern int ssl_handshake(aClient *); /* Handshake the accpeted con.*/
extern int ssl_client_handshake(aClient *, ConfigItem_link *); /* and the initiated con.*/
extern int ircd_SSL_read(aClient *acptr, void *buf, int sz);
extern int ircd_SSL_write(aClient *acptr, const void *buf, int sz);
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 ircd_SSL_client_handshake(int, int, void *);
extern void SSL_set_nonblocking(SSL *s);
+51 -26
View File
@@ -90,8 +90,6 @@ static int pollfd_count = 0;
static int pollfd_to_client[MAXCONNECTIONS]; /* use get_client_by_pollfd() for grabbing, don't grab from array directly ! */
#endif
static void read_packet(int fd, int revents, void *data);
#ifdef INET6
static unsigned char minus_one[] =
{ 255, 255, 255, 255, 255, 255, 255, 255, 255,
@@ -1528,6 +1526,7 @@ struct hostent *he;
doauth:
start_auth(acptr);
fd_setselect(acptr->fd, FD_SELECT_READ, read_packet, acptr);
}
void proceed_normal_client_handshake(aClient *acptr, struct hostent *he)
@@ -1541,12 +1540,6 @@ void proceed_normal_client_handshake(aClient *acptr, struct hostent *he)
finish_auth(acptr);
}
void finish_auth(aClient *acptr)
{
SetAccess(acptr);
fd_setselect(acptr->fd, FD_SELECT_READ, read_packet, acptr);
}
/*
** read_packet
**
@@ -1624,7 +1617,7 @@ static void parse_client_queued(aClient *cptr)
}
}
static void read_packet(int fd, int revents, void *data)
void read_packet(int fd, int revents, void *data)
{
aClient *cptr = data;
int length = 0;
@@ -1636,16 +1629,48 @@ static void read_packet(int fd, int revents, void *data)
while (1)
{
#ifdef USE_SSL
if (cptr->flags & FLAGS_SSL)
length = ircd_SSL_read(cptr, readbuf, sizeof(readbuf));
if (IsSSL(cptr) && cptr->ssl != NULL)
{
fd_setselect(fd, FD_SELECT_READ, read_packet, cptr);
fd_setselect(fd, FD_SELECT_WRITE, NULL, cptr);
length = SSL_read(cptr->ssl, readbuf, sizeof(readbuf));
if (length < 0)
{
int err = SSL_get_error(cptr->ssl, length);
ircd_log(LOG_ERROR, "error %d", err);
switch (err)
{
case SSL_ERROR_WANT_WRITE:
fd_setselect(fd, FD_SELECT_READ, NULL, cptr);
fd_setselect(fd, FD_SELECT_WRITE, read_packet, cptr);
break;
case SSL_ERROR_WANT_READ:
SET_ERRNO(P_EWOULDBLOCK);
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_SSL:
if (ERRNO == P_EAGAIN)
break;
default:
length = 0;
SET_ERRNO(0);
break;
}
}
}
else
#endif
length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
if (length < 0 && ERRNO == P_EWOULDBLOCK)
return;
if (length == 0)
if (length <= 0)
{
if (length < 0 && (ERRNO == P_EWOULDBLOCK || ERRNO == P_EAGAIN || ERRNO == P_EINTR))
return;
exit_client(cptr, cptr, cptr, "Read error");
return;
}
@@ -1662,10 +1687,12 @@ static void read_packet(int fd, int revents, void *data)
return;
}
ircd_log(LOG_ERROR, "dbuf_put - length %d, ERRNO %d", length, ERRNO);
dbuf_put(&cptr->recvQ, readbuf, length);
/* parse some of what we have (inducing fakelag, etc) */
parse_client_queued(cptr);
if (!(DoingDNS(cptr) || DoingAuth(cptr)))
parse_client_queued(cptr);
/* excess flood check */
if (IsPerson(cptr) && DBufLength(&cptr->recvQ) > get_recvq(cptr))
@@ -1686,6 +1713,13 @@ static void read_packet(int fd, int revents, void *data)
}
}
/* When auth is finished, go back and parse all prior input. */
void finish_auth(aClient *acptr)
{
SetAccess(acptr);
parse_client_queued(acptr);
}
/*
* Check all connections for new connections and input data that is to be
* processed. Also check for connections with data queued and whether we can
@@ -1884,15 +1918,6 @@ int read_message(time_t delay, fdlist *listp)
** ...room for writing, empty some queue then...
*/
ClearBlocked(cptr);
if (IsConnecting(cptr)) {
#ifdef USE_SSL
if ((cptr->serv) && (cptr->serv->conf->options & CONNECT_SSL))
{
Debug((DEBUG_DEBUG, "ircd_SSL_client_handshake(%s)", cptr->name));
write_err = ircd_SSL_client_handshake(cptr);
}
#endif
}
if (!write_err)
{
if (DoList(cptr) && IsSendable(cptr))
@@ -1948,7 +1973,7 @@ deadsocket:
else if (IsSSLConnectHandshake(cptr))
{
Debug((DEBUG_ERROR, "ssl: completed_connection", cptr->name));
completed_connection(cptr);
completed_connection(cptr->fd, FD_SELECT_READ, cptr);
} else if (IsSSLStartTLSHandshake(cptr))
{
SetUnknown(cptr);
@@ -2143,7 +2168,7 @@ int connect_server(ConfigItem_link *aconf, aClient *by, struct hostent *hp)
add_client_to_list(cptr);
nextping = TStime();
#if 0 // ifdef USE_SSL
#ifdef USE_SSL
if (IsSSL(cptr) && (aconf->options & CONNECT_SSL))
fd_setselect(cptr->fd, FD_SELECT_READ, ircd_SSL_client_handshake, cptr);
else
+24 -2
View File
@@ -85,8 +85,30 @@ int deliver_it(aClient *cptr, char *str, int len)
}
#ifdef USE_SSL
if (cptr->flags & FLAGS_SSL)
retval = ircd_SSL_write(cptr, str, len);
if (IsSSL(cptr) && cptr->ssl != NULL)
{
retval = SSL_write(cptr->ssl, str, len);
if (retval < 0)
{
switch (SSL_get_error(cptr->ssl, retval))
{
case SSL_ERROR_WANT_READ:
/* retry later */
return 0;
case SSL_ERROR_WANT_WRITE:
SET_ERRNO(P_EWOULDBLOCK);
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_SSL:
if (ERRNO == P_EAGAIN)
break;
default:
return 0;
}
}
}
else
#endif
retval = send(cptr->fd, str, len, 0);
+25 -77
View File
@@ -448,78 +448,15 @@ char *ssl_get_cipher(SSL *ssl)
return (buf);
}
int ircd_SSL_read(aClient *acptr, void *buf, int sz)
void ircd_SSL_client_handshake(int fd, int revents, void *data)
{
int len, ssl_err, ssl_errno;
len = SSL_read((SSL *)acptr->ssl, buf, sz);
if (len <= 0)
{
switch(ssl_err = SSL_get_error((SSL *)acptr->ssl, len)) {
case SSL_ERROR_SYSCALL:
if (ERRNO == P_EWOULDBLOCK || ERRNO == P_EAGAIN ||
ERRNO == P_EINTR) {
case SSL_ERROR_WANT_READ:
SET_ERRNO(P_EWOULDBLOCK);
Debug((DEBUG_ERROR, "ircd_SSL_read: returning EWOULDBLOCK and 0 for %s - %s", acptr->name,
ssl_err == SSL_ERROR_WANT_READ ? "SSL_ERROR_WANT_READ" : "SSL_ERROR_SYSCALL"
));
return -1;
}
case SSL_ERROR_SSL:
if(ERRNO == EAGAIN)
return -1;
default:
ssl_errno = ERRNO;
Debug((DEBUG_ERROR, "ircd_SSL_read: returning fatal_ssl_error for %s",
acptr->name));
return fatal_ssl_error(ssl_err, SAFE_SSL_READ, ssl_errno, acptr);
}
}
Debug((DEBUG_ERROR, "ircd_SSL_read for %s (%p, %i): success", acptr->name, buf, sz));
return len;
}
int ircd_SSL_write(aClient *acptr, const void *buf, int sz)
{
int len, ssl_err, ssl_errno;
aClient *acptr = data;
len = SSL_write((SSL *)acptr->ssl, buf, sz);
if (len <= 0)
{
switch(ssl_err = SSL_get_error((SSL *)acptr->ssl, len)) {
case SSL_ERROR_SYSCALL:
if (ERRNO == P_EWOULDBLOCK || ERRNO == P_EAGAIN ||
ERRNO == P_EINTR)
{
SET_ERRNO(P_EWOULDBLOCK);
return -1;
}
return -1;
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;
default:
ssl_errno = ERRNO;
Debug((DEBUG_ERROR, "ircd_SSL_write: returning fatal_ssl_error for %s", acptr->name));
return fatal_ssl_error(ssl_err, SAFE_SSL_WRITE, ssl_errno, acptr);
}
}
Debug((DEBUG_ERROR, "ircd_SSL_write for %s (%p, %i): success", acptr->name, buf, sz));
return len;
}
int ircd_SSL_client_handshake(aClient *acptr)
{
acptr->ssl = SSL_new(ctx_client);
if (!acptr->ssl)
{
sendto_realops("Failed to SSL_new(ctx_client)");
return FALSE;
return;
}
SSL_set_fd(acptr->ssl, acptr->fd);
SSL_set_connect_state(acptr->ssl);
@@ -550,22 +487,26 @@ int ircd_SSL_client_handshake(aClient *acptr)
acptr->flags |= FLAGS_SSL;
switch (ircd_SSL_connect(acptr))
{
case -1:
return -1;
case -1:
case 0:
Debug((DEBUG_DEBUG, "SetSSLConnectHandshake(%s)", get_client_name(acptr, TRUE)));
SetSSLConnectHandshake(acptr);
return 0;
case 1:
return;
case 1:
Debug((DEBUG_DEBUG, "SSL_init_finished should finish this job (%s)", get_client_name(acptr, TRUE)));
/* SSL_init_finished in s_bsd will finish the job */
return 1;
return;
default:
return -1;
return;
}
}
static void ircd_SSL_accept_retry(int fd, int revents, void *data)
{
aClient *acptr = data;
ircd_SSL_accept(acptr, fd);
}
int ircd_SSL_accept(aClient *acptr, int fd) {
int ssl_err;
@@ -575,11 +516,15 @@ int ircd_SSL_accept(aClient *acptr, int fd) {
case SSL_ERROR_SYSCALL:
if (ERRNO == P_EINTR || ERRNO == P_EWOULDBLOCK
|| ERRNO == P_EAGAIN)
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
Debug((DEBUG_DEBUG, "ircd_SSL_accept(%s), - %s", get_client_name(acptr, TRUE), ssl_error_str(ssl_err, ERRNO)));
/* handshake will be completed later . . */
return 1;
case SSL_ERROR_WANT_READ:
fd_setselect(fd, FD_SELECT_READ, ircd_SSL_accept_retry, acptr);
fd_setselect(fd, FD_SELECT_WRITE, NULL, acptr);
return 1;
case SSL_ERROR_WANT_WRITE:
fd_setselect(fd, FD_SELECT_READ, NULL, acptr);
fd_setselect(fd, FD_SELECT_WRITE, ircd_SSL_accept_retry, acptr);
return 1;
default:
return fatal_ssl_error(ssl_err, SAFE_SSL_ACCEPT, ERRNO, acptr);
@@ -587,6 +532,9 @@ int ircd_SSL_accept(aClient *acptr, int fd) {
/* NOTREACHED */
return -1;
}
start_of_normal_client_handshake(acptr);
return 1;
}