X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fs_bsd.c;h=c63f5654d947983684e94d23c1aa959c369ca64b;hb=c13fbd5384338be6c99d529db9b6ba787afcb1c0;hp=63e9081c51da376193f3a01b9884c8e76b2da4be;hpb=6a896dc3a06393ec254a43bd5ac4b7e282d4a968;p=ircu2.10.12-pk.git diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index 63e9081..c63f565 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -53,6 +53,7 @@ #include "s_misc.h" #include "s_user.h" #include "send.h" +#include "ssl.h" #include "struct.h" #include "sys.h" #include "uping.h" @@ -238,7 +239,7 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) /* * Set the TOS bits - this is nonfatal if it doesn't stick. */ - if (!os_set_tos(cli_fd(cptr), FEAT_TOS_SERVER)) { + if (!os_set_tos(cli_fd(cptr), feature_int(FEAT_TOS_SERVER))) { report_error(TOS_ERROR_MSG, cli_name(cptr), errno); } if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) { @@ -248,6 +249,7 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) cli_fd(cptr) = -1; return 0; } + if (!socket_add(&(cli_socket(cptr)), client_sock_callback, (void*) cli_connect(cptr), (result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING, @@ -258,6 +260,21 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) cli_fd(cptr) = -1; return 0; } + + if(aconf->usessl) { + struct SSLConnection *ssl = ssl_create_connect(cli_fd(cptr), cptr, SSLData_Client); + cli_connect(cptr)->con_ssl = ssl; + if(ssl_handshake(ssl)) { + unsigned int events = 0; + if(ssl_wantread(ssl)) + events |= SOCK_EVENT_READABLE; + if(ssl_wantwrite(ssl)) + events |= SOCK_EVENT_WRITABLE; + socket_events(&(cli_socket(cptr)), SOCK_ACTION_SET | events); + result = IO_BLOCKED; + } + } + cli_freeflag(cptr) |= FREEFLAG_SOCKET; return 1; } @@ -274,9 +291,16 @@ unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf) { unsigned int bytes_written = 0; unsigned int bytes_count = 0; + IOResult result; assert(0 != cptr); - switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) { + if(cli_connect(cptr)->con_ssl) { + result = ssl_send_encrypt(cli_connect(cptr)->con_ssl, buf, &bytes_count, &bytes_written); + } else { + result = os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written); + } + + switch (result) { case IO_SUCCESS: ClrFlag(cptr, FLAG_BLOCKED); @@ -302,7 +326,7 @@ unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf) * @param cptr Client to which we have connected, with all ConfItem structs attached. * @return Zero on failure (caller should exit_client()), non-zero on success. */ -static int completed_connection(struct Client* cptr) +int completed_connection(struct Client* cptr) { struct ConfItem *aconf; time_t newts; @@ -403,6 +427,11 @@ void close_connection(struct Client *cptr) else ServerStats->is_ni++; + if(cli_connect(cptr)->con_ssl) { + ssl_free_connection(cli_connect(cptr)->con_ssl); + cli_connect(cptr)->con_ssl = NULL; + } + if (-1 < cli_fd(cptr)) { flush_connections(cptr); LocalClientArray[cli_fd(cptr)] = 0; @@ -540,8 +569,20 @@ void add_connection(struct Listener* listener, int fd) { ++listener->ref_count; Count_newunknown(UserStats); - /* if we've made it this far we can put the client on the auth query pile */ - start_auth(new_client); + + if(listener_ssl(listener)) { + struct Connection* con = cli_connect(new_client); + con->con_ssl = ssl_start_handshake_listener(listener->ssl_listener, fd, new_client, SSLData_Client); + unsigned int events = 0; + if(ssl_wantread(con->con_ssl)) + events |= SOCK_EVENT_READABLE; + if(ssl_wantwrite(con->con_ssl)) + events |= SOCK_EVENT_WRITABLE; + socket_events(&(cli_socket(new_client)), SOCK_ACTION_SET | events); + } else { + /* if we've made it this far we can put the client on the auth query pile */ + start_auth(new_client); + } } /** Determines whether to tell the events engine we're interested in @@ -577,7 +618,16 @@ static int read_packet(struct Client *cptr, int socket_ready) if (socket_ready && !(IsUser(cptr) && DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))) { - switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) { + + /* Handle SSL Sockets + */ + int recvret; + if(cli_connect(cptr)->con_ssl) { + recvret = ssl_recv_decrypt(cli_connect(cptr)->con_ssl, readbuf, sizeof(readbuf), &length); + } else { + recvret = os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length); + } + switch (recvret) { case IO_SUCCESS: if (length) { @@ -596,7 +646,7 @@ static int read_packet(struct Client *cptr, int socket_ready) return 0; } } - + /* * For server connections, we process as many as we can without * worrying about the time of day or anything :) @@ -615,11 +665,13 @@ static int read_packet(struct Client *cptr, int socket_ready) if (length > 0 && dbuf_put(&(cli_recvQ(cptr)), readbuf, length) == 0) return exit_client(cptr, cptr, &me, "dbuf_put fail"); - if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD)) + int HasUnlimitFlood = HasPriv(cptr, PRIV_UNLIMIT_FLOOD); + + if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD) && !HasUnlimitFlood) return exit_client(cptr, cptr, &me, "Excess Flood"); while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && - (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10)) + (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10 || HasUnlimitFlood)) { dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE); /* @@ -855,13 +907,21 @@ static void client_sock_callback(struct Event* ev) break; case ET_CONNECT: /* socket connection completed */ - if (!completed_connection(cptr) || IsDead(cptr)) + if(cli_connect(cptr)->con_ssl) { + ssl_start_handshake_connect(cli_connect(cptr)->con_ssl); + } + else if (!completed_connection(cptr) || IsDead(cptr)) fallback = cli_info(cptr); break; case ET_ERROR: /* an error occurred */ fallback = cli_info(cptr); cli_error(cptr) = ev_data(ev); + /* If the OS told us we have a bad file descriptor, we should + * record that for future reference. + */ + if (cli_error(cptr) == EBADF) + cli_fd(cptr) = -1; if (s_state(&(con_socket(con))) == SS_CONNECTING) { completed_connection(cptr); /* for some reason, the os_get_sockerr() in completed_connect()