X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fs_bsd.c;h=c63f5654d947983684e94d23c1aa959c369ca64b;hb=refs%2Fheads%2Fupstream;hp=71706e518536ee58478860c4cac23cf851cffd57;hpb=ef4270d668183cf9e9a3d96cab7f305c5c5f1aa7;p=ircu2.10.12-pk.git diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index 71706e5..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" @@ -182,7 +183,7 @@ int init_connection_limits(void) if (0 == limit) return 1; if (limit < 0) { - fprintf(stderr, "error setting max fd's to %d\n", limit); + fprintf(stderr, "error setting max fds to %d: %s\n", limit, strerror(errno)); } else if (limit > 0) { fprintf(stderr, "ircd fd table too big\nHard Limit: %d IRC max: %d\n", @@ -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; @@ -352,7 +376,7 @@ static int completed_connection(struct Client* cptr) * Make us timeout after twice the timeout for DNS look ups */ cli_lasttime(cptr) = CurrentTime; - SetFlag(cptr, FLAG_PINGSENT); + ClearPingSent(cptr); sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s", cli_name(&me), cli_serv(&me)->timestamp, 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,16 +618,24 @@ 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) { - if (!IsServer(cptr)) - cli_lasttime(cptr) = CurrentTime; + cli_lasttime(cptr) = CurrentTime; + ClearPingSent(cptr); + ClrFlag(cptr, FLAG_NONL); if (cli_lasttime(cptr) > cli_since(cptr)) cli_since(cptr) = cli_lasttime(cptr); - ClrFlag(cptr, FLAG_PINGSENT); - ClrFlag(cptr, FLAG_NONL); } break; case IO_BLOCKED: @@ -597,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 :) @@ -616,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); /* @@ -636,7 +687,13 @@ static int read_packet(struct Client *cptr, int socket_ready) if (DBufLength(&(cli_recvQ(cptr))) < 510) SetFlag(cptr, FLAG_NONL); else + { + /* More than 512 bytes in the line - drop the input and yell + * at the client. + */ DBufClear(&(cli_recvQ(cptr))); + send_reply(cptr, ERR_INPUTTOOLONG); + } } else if (client_dopacket(cptr, dolen) == CPTR_KILLED) return CPTR_KILLED; @@ -850,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()