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:
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user