X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fs_auth.c;h=5ac17026e57bf808463d022eaf7bafa8773e4aca;hb=fda30451cac5936729c683d38a700f4928812c6f;hp=01c207af95ef495ef56ef6337afce96c1337e4c7;hpb=73b227d6b3e2c89d655e23aedf9a318bc192212b;p=ircu2.10.12-pk.git diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 01c207a..5ac1702 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -35,6 +35,7 @@ #include "ircd.h" #include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_events.h" #include "ircd_features.h" #include "ircd_log.h" #include "ircd_osdep.h" @@ -102,6 +103,118 @@ static struct AuthRequest* AuthIncompleteList = 0; enum { AUTH_TIMEOUT = 60 }; +static void release_auth_client(struct Client* client); +static void unlink_auth_request(struct AuthRequest* request, + struct AuthRequest** list); +void free_auth_request(struct AuthRequest* auth); + +/* + * auth_timeout - timeout a given auth request + */ +static void auth_timeout_callback(struct Event* ev) +{ + struct AuthRequest* auth; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + auth = t_data(ev_timer(ev)); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + auth->flags &= ~AM_TIMEOUT; + + if (!(auth->flags & AM_FREE_MASK)) { + Debug((DEBUG_LIST, "Freeing auth from timeout callback; %p [%p]", auth, + ev_timer(ev))); + MyFree(auth); /* done with it, finally */ + } + } else { + assert(ev_type(ev) == ET_EXPIRE); + + destroy_auth_request(auth, 1); + } +} + +/* + * auth_sock_callback - called when an event occurs on the socket + */ +static void auth_sock_callback(struct Event* ev) +{ + struct AuthRequest* auth; + + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); + + auth = s_data(ev_socket(ev)); + + switch (ev_type(ev)) { + case ET_DESTROY: /* being destroyed */ + auth->flags &= ~AM_SOCKET; + + if (!(auth->flags & AM_FREE_MASK)) { + Debug((DEBUG_LIST, "Freeing auth from sock callback; %p [%p]", auth, + ev_socket(ev))); + MyFree(auth); /* done with it finally */ + } + break; + + case ET_CONNECT: /* socket connection completed */ + Debug((DEBUG_LIST, "Connection completed for auth %p [%p]; sending query", + auth, ev_socket(ev))); + socket_state(&auth->socket, SS_CONNECTED); + send_auth_query(auth); + break; + + case ET_READ: /* socket is readable */ + case ET_EOF: /* end of file on socket */ + case ET_ERROR: /* error on socket */ + Debug((DEBUG_LIST, "Auth socket %p [%p] readable", auth, ev_socket(ev))); + read_auth_reply(auth); + break; + + default: +#ifndef NDEBUG + abort(); /* unrecognized event */ +#endif + break; + } +} + +/* + * destroy_auth_request - stop an auth request completely + */ +void destroy_auth_request(struct AuthRequest* auth, int send_reports) +{ + struct AuthRequest** authList; + + if (IsDoingAuth(auth)) { + authList = &AuthPollList; + if (-1 < auth->fd) { + close(auth->fd); + auth->fd = -1; + socket_del(&auth->socket); + } + + if (send_reports && IsUserPort(auth->client)) + sendheader(auth->client, REPORT_FAIL_ID); + } else + authList = &AuthIncompleteList; + + if (IsDNSPending(auth)) { + delete_resolver_queries(auth); + if (send_reports && IsUserPort(auth->client)) + sendheader(auth->client, REPORT_FAIL_DNS); + } + + if (send_reports) + log_write(LS_RESOLVER, L_INFO, 0, "DNS/AUTH timeout %s", + get_client_name(auth->client, HIDE_IP)); + + release_auth_client(auth->client); + unlink_auth_request(auth, authList); + free_auth_request(auth); +} + /* * make_auth_request - allocate a new auth request */ @@ -111,9 +224,12 @@ static struct AuthRequest* make_auth_request(struct Client* client) (struct AuthRequest*) MyMalloc(sizeof(struct AuthRequest)); assert(0 != auth); memset(auth, 0, sizeof(struct AuthRequest)); + auth->flags = AM_TIMEOUT; auth->fd = -1; auth->client = client; - auth->timeout = CurrentTime + AUTH_TIMEOUT; + cli_auth(client) = auth; + timer_add(&auth->timeout, auth_timeout_callback, (void*) auth, TT_RELATIVE, + AUTH_TIMEOUT); return auth; } @@ -122,9 +238,13 @@ static struct AuthRequest* make_auth_request(struct Client* client) */ void free_auth_request(struct AuthRequest* auth) { - if (-1 < auth->fd) + if (-1 < auth->fd) { close(auth->fd); - MyFree(auth); + Debug((DEBUG_LIST, "Deleting auth socket for %p", auth->client)); + socket_del(&auth->socket); + } + Debug((DEBUG_LIST, "Deleting auth timeout timer for %p", auth->client)); + timer_del(&auth->timeout); } /* @@ -162,12 +282,14 @@ static void link_auth_request(struct AuthRequest* request, static void release_auth_client(struct Client* client) { assert(0 != client); + cli_auth(client) = 0; cli_lasttime(client) = cli_since(client) = CurrentTime; if (cli_fd(client) > HighestFd) HighestFd = cli_fd(client); LocalClientArray[cli_fd(client)] = client; add_client_to_list(client); + socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE); Debug((DEBUG_INFO, "Auth: release_auth_client %s@%s[%s]", cli_username(client), cli_sockhost(client), cli_sock_ip(client))); } @@ -263,6 +385,7 @@ static void auth_error(struct AuthRequest* auth, int kill) assert(0 != auth); close(auth->fd); auth->fd = -1; + socket_del(&auth->socket); if (IsUserPort(auth->client)) sendheader(auth->client, REPORT_FAIL_ID); @@ -301,6 +424,7 @@ static int start_auth_query(struct AuthRequest* auth) struct sockaddr_in remote_addr; struct sockaddr_in local_addr; int fd; + IOResult result; assert(0 != auth); assert(0 != auth->client); @@ -353,7 +477,10 @@ static int start_auth_query(struct AuthRequest* auth) remote_addr.sin_port = htons(113); remote_addr.sin_family = AF_INET; - if (!os_connect_nonb(fd, &remote_addr)) { + if ((result = os_connect_nonb(fd, &remote_addr)) == IO_FAILURE || + !socket_add(&auth->socket, auth_sock_callback, (void*) auth, + result == IO_SUCCESS ? SS_CONNECTED : SS_CONNECTING, + SOCK_EVENT_READABLE, fd)) { ServerStats->is_abad++; /* * No error report from this... @@ -364,9 +491,13 @@ static int start_auth_query(struct AuthRequest* auth) return 0; } + auth->flags |= AM_SOCKET; auth->fd = fd; SetAuthConnect(auth); + if (result == IO_SUCCESS) + send_auth_query(auth); /* this does a SetAuthPending(auth) for us */ + return 1; } @@ -524,6 +655,8 @@ void start_auth(struct Client* client) auth = make_auth_request(client); assert(0 != auth); + Debug((DEBUG_INFO, "Beginning auth request on client %p", client)); + if (!feature_bool(FEAT_NODNS)) { if (LOOPBACK == inet_netof(cli_ip(client))) strcpy(cli_sockhost(client), cli_name(&me)); @@ -545,69 +678,28 @@ void start_auth(struct Client* client) HOSTLEN); if (IsUserPort(auth->client)) sendheader(client, REPORT_FIN_DNSC); + Debug((DEBUG_LIST, "DNS entry for %p was cached", auth->client)); } else SetDNSPending(auth); } } - if (start_auth_query(auth)) + if (start_auth_query(auth)) { + Debug((DEBUG_LIST, "identd query for %p initiated successfully", + auth->client)); link_auth_request(auth, &AuthPollList); - else if (IsDNSPending(auth)) + } else if (IsDNSPending(auth)) { + Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " + "waiting on DNS", auth->client)); link_auth_request(auth, &AuthIncompleteList); - else { + } else { + Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " + "no DNS pending; releasing immediately", auth->client)); free_auth_request(auth); release_auth_client(client); } } -/* - * timeout_auth_queries - timeout resolver and identd requests - * allow clients through if requests failed - */ -void timeout_auth_queries(time_t now) -{ - struct AuthRequest* auth; - struct AuthRequest* auth_next = 0; - - for (auth = AuthPollList; auth; auth = auth_next) { - auth_next = auth->next; - if (auth->timeout < CurrentTime) { - if (-1 < auth->fd) { - close(auth->fd); - auth->fd = -1; - } - - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_ID); - if (IsDNSPending(auth)) { - delete_resolver_queries(auth); - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_DNS); - } - log_write(LS_RESOLVER, L_INFO, 0, "DNS/AUTH timeout %s", - get_client_name(auth->client, HIDE_IP)); - - release_auth_client(auth->client); - unlink_auth_request(auth, &AuthPollList); - free_auth_request(auth); - } - } - for (auth = AuthIncompleteList; auth; auth = auth_next) { - auth_next = auth->next; - if (auth->timeout < CurrentTime) { - delete_resolver_queries(auth); - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_DNS); - log_write(LS_RESOLVER, L_INFO, 0, "DNS timeout %s", - get_client_name(auth->client, HIDE_IP)); - - release_auth_client(auth->client); - unlink_auth_request(auth, &AuthIncompleteList); - free_auth_request(auth); - } - } -} - /* * send_auth_query - send the ident server a query giving "theirport , ourport" * The write is only attempted *once* so it is deemed to be a fail if the @@ -660,14 +752,19 @@ void read_auth_reply(struct AuthRequest* auth) assert(0 != auth); assert(0 != auth->client); + assert(auth = cli_auth(auth->client)); if (IO_SUCCESS == os_recv_nonb(auth->fd, buf, BUFSIZE, &len)) { buf[len] = '\0'; + Debug((DEBUG_LIST, "Auth %p [%p] reply: %s", auth, &auth->socket, buf)); username = check_ident_reply(buf); + Debug((DEBUG_LIST, "Username: %s", username)); } close(auth->fd); auth->fd = -1; + Debug((DEBUG_LIST, "Deleting auth [%p] socket %p", auth, &auth->socket)); + socket_del(&auth->socket); ClearAuth(auth); if (!EmptyString(username)) {