X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/a63e399c19e5fbd6a7b49e40e91ddaa0a1c050b8..0e52880760189a58d23f57918208843af2c9ce49:/src/s_auth.c diff --git a/src/s_auth.c b/src/s_auth.c index d245470..83407b3 100644 --- a/src/s_auth.c +++ b/src/s_auth.c @@ -39,18 +39,52 @@ #include "s_conf.h" #include "client.h" #include "common.h" -#include "irc_string.h" -#include "sprintf_irc.h" +#include "match.h" #include "ircd.h" #include "numeric.h" #include "packet.h" #include "res.h" -#include "s_log.h" +#include "logger.h" #include "s_stats.h" #include "send.h" #include "hook.h" #include "blacklist.h" +struct AuthRequest +{ + rb_dlink_node node; + struct Client *client; /* pointer to client struct for request */ + struct DNSQuery dns_query; /* DNS Query */ + unsigned int flags; /* current state of request */ + rb_fde_t *F; /* file descriptor for auth queries */ + time_t timeout; /* time when query expires */ + uint16_t lport; + uint16_t rport; +}; + +/* + * flag values for AuthRequest + * NAMESPACE: AM_xxx - Authentication Module + */ +#define AM_AUTH_CONNECTING (1 << 0) +#define AM_AUTH_PENDING (1 << 1) +#define AM_DNS_PENDING (1 << 2) + +#define SetDNSPending(x) ((x)->flags |= AM_DNS_PENDING) +#define ClearDNSPending(x) ((x)->flags &= ~AM_DNS_PENDING) +#define IsDNSPending(x) ((x)->flags & AM_DNS_PENDING) + +#define SetAuthConnect(x) ((x)->flags |= AM_AUTH_CONNECTING) +#define ClearAuthConnect(x) ((x)->flags &= ~AM_AUTH_CONNECTING) +#define IsAuthConnect(x) ((x)->flags & AM_AUTH_CONNECTING) + +#define SetAuthPending(x) ((x)->flags |= AM_AUTH_PENDING) +#define ClearAuthPending(x) ((x)->flags &= AM_AUTH_PENDING) +#define IsAuthPending(x) ((x)->flags & AM_AUTH_PENDING) + +#define ClearAuth(x) ((x)->flags &= ~(AM_AUTH_PENDING | AM_AUTH_CONNECTING)) +#define IsDoingAuth(x) ((x)->flags & (AM_AUTH_PENDING | AM_AUTH_CONNECTING)) + /* * a bit different approach * this replaces the original sendheader macros @@ -103,7 +137,7 @@ init_auth(void) /* This hook takes a struct Client for its argument */ memset(&auth_poll_list, 0, sizeof(auth_poll_list)); rb_event_addish("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1); - auth_heap = rb_bh_create(sizeof(struct AuthRequest), LCLIENT_HEAP_SIZE); + auth_heap = rb_bh_create(sizeof(struct AuthRequest), LCLIENT_HEAP_SIZE, "auth_heap"); } /* @@ -114,7 +148,7 @@ make_auth_request(struct Client *client) { struct AuthRequest *request = rb_bh_alloc(auth_heap); client->localClient->auth_request = request; - request->fd = -1; + request->F = NULL; request->client = client; request->timeout = rb_current_time() + ConfigFileEntry.connect_timeout; return request; @@ -145,8 +179,6 @@ release_auth_client(struct AuthRequest *auth) client->localClient->auth_request = NULL; rb_dlinkDelete(&auth->node, &auth_poll_list); free_auth_request(auth); - if(client->localClient->F->fd > highest_fd) - highest_fd = client->localClient->F->fd; /* * When a client has auth'ed, we want to start reading what it sends @@ -154,9 +186,8 @@ release_auth_client(struct AuthRequest *auth) * -- adrian */ client->localClient->allow_read = MAX_FLOOD; - rb_setflush(client->localClient->F->fd, 1000, flood_recalc, client); rb_dlinkAddTail(client, &client->node, &global_client_list); - read_packet(client->localClient->F->fd, client); + read_packet(client->localClient->F, client); } /* @@ -202,7 +233,7 @@ auth_dns_callback(void *vptr, struct DNSReply *reply) good = 0; } } -#ifdef IPV6 +#ifdef RB_IPV6 else if(auth->client->localClient->ip.ss_family == AF_INET6) { struct sockaddr_in6 *ip, *ip_fwd; @@ -225,7 +256,7 @@ auth_dns_callback(void *vptr, struct DNSReply *reply) if(good && strlen(reply->h_name) <= HOSTLEN) { - strlcpy(auth->client->host, reply->h_name, sizeof(auth->client->host)); + rb_strlcpy(auth->client->host, reply->h_name, sizeof(auth->client->host)); sendheader(auth->client, REPORT_FIN_DNS); } else if (strlen(reply->h_name) > HOSTLEN) @@ -243,10 +274,10 @@ auth_dns_callback(void *vptr, struct DNSReply *reply) static void auth_error(struct AuthRequest *auth) { - ++ServerStats->is_abad; + ++ServerStats.is_abad; - rb_close(auth->fd); - auth->fd = -1; + rb_close(auth->F); + auth->F = NULL; ClearAuth(auth); sendheader(auth->client, REPORT_FAIL_ID); @@ -265,33 +296,31 @@ auth_error(struct AuthRequest *auth) static int start_auth_query(struct AuthRequest *auth) { - struct irc_sockaddr_storage localaddr; - socklen_t locallen = sizeof(struct irc_sockaddr_storage); - int fd; + struct rb_sockaddr_storage localaddr, destaddr; + socklen_t locallen = sizeof(struct rb_sockaddr_storage); + rb_fde_t *F; int family; if(IsAnyDead(auth->client)) return 0; family = auth->client->localClient->ip.ss_family; - if((fd = rb_socket(family, SOCK_STREAM, 0, "ident")) == -1) + if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) { - report_error("creating auth stream socket %s:%s", - get_client_name(auth->client, SHOW_IP), - log_client_name(auth->client, SHOW_IP), errno); - ++ServerStats->is_abad; + ilog_error("creating auth stream socket"); + ++ServerStats.is_abad; return 0; } /* * TBD: this is a pointless arbitrary limit .. we either have a socket or not. -nenolod */ - if((rb_get_maxconnections() - 10) < fd) + if((maxconnections - 10) < rb_get_fd(F)) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Can't allocate fd for auth on %s", get_client_name(auth->client, SHOW_IP)); - rb_close(fd); + rb_close(F); return 0; } @@ -305,25 +334,49 @@ start_auth_query(struct AuthRequest *auth) * and machines with multiple IP addresses are common now */ memset(&localaddr, 0, locallen); - getsockname(auth->client->localClient->F->fd, - (struct sockaddr *) &localaddr, &locallen); + if(getsockname(rb_get_fd(auth->client->localClient->F), + (struct sockaddr *) &localaddr, &locallen) == -1) + { + /* can happen if connection was just closed */ + rb_close(F); + return 0; + } - mangle_mapped_sockaddr((struct sockaddr *)&localaddr); -#ifdef IPV6 + /* XXX mangle_mapped_sockaddr((struct sockaddr *)&localaddr); */ +#ifdef RB_IPV6 if(localaddr.ss_family == AF_INET6) { + auth->lport = ntohs(((struct sockaddr_in6 *)&localaddr)->sin6_port); ((struct sockaddr_in6 *)&localaddr)->sin6_port = 0; - } else + } + else #endif - ((struct sockaddr_in *)&localaddr)->sin_port = 0; + { + auth->lport = ntohs(((struct sockaddr_in *)&localaddr)->sin_port); + ((struct sockaddr_in *)&localaddr)->sin_port = 0; + } + + destaddr = auth->client->localClient->ip; +#ifdef RB_IPV6 + if(localaddr.ss_family == AF_INET6) + { + auth->rport = ntohs(((struct sockaddr_in6 *)&destaddr)->sin6_port); + ((struct sockaddr_in6 *)&destaddr)->sin6_port = htons(113); + } + else +#endif + { + auth->rport = ntohs(((struct sockaddr_in *)&destaddr)->sin_port); + ((struct sockaddr_in *)&destaddr)->sin_port = htons(113); + } - auth->fd = fd; + auth->F = F; SetAuthConnect(auth); - rb_connect_tcp(fd, auth->client->sockhost, 113, - (struct sockaddr *) &localaddr, GET_SS_LEN(localaddr), + rb_connect_tcp(F, (struct sockaddr *)&destaddr, + (struct sockaddr *) &localaddr, GET_SS_LEN(&localaddr), auth_connect_callback, auth, - localaddr.ss_family, GlobalSetOptions.ident_timeout); + GlobalSetOptions.ident_timeout); return 1; /* We suceed here for now */ } @@ -435,13 +488,13 @@ timeout_auth_queries_event(void *notused) if(auth->timeout < rb_current_time()) { - if(auth->fd >= 0) - rb_close(auth->fd); + if(auth->F != NULL) + rb_close(auth->F); if(IsDoingAuth(auth)) { ClearAuth(auth); - ++ServerStats->is_abad; + ++ServerStats.is_abad; sendheader(auth->client, REPORT_FAIL_ID); auth->client->localClient->auth_request = NULL; } @@ -470,45 +523,30 @@ timeout_auth_queries_event(void *notused) * problems arise. -avalon */ static void -auth_connect_callback(int fd, int error, void *data) +auth_connect_callback(rb_fde_t *F, int error, void *data) { struct AuthRequest *auth = data; - struct sockaddr_in us; - struct sockaddr_in them; char authbuf[32]; - socklen_t ulen = sizeof(struct sockaddr_in); - socklen_t tlen = sizeof(struct sockaddr_in); /* Check the error */ - if(error != COMM_OK) + if(error != RB_OK) { /* We had an error during connection :( */ auth_error(auth); return; } - if(getsockname - (auth->client->localClient->F->fd, (struct sockaddr *) &us, - (socklen_t *) & ulen) - || getpeername(auth->client->localClient->F->fd, - (struct sockaddr *) &them, (socklen_t *) & tlen)) - { - ilog(L_IOERROR, "auth get{sock,peer}name error for %s:%m", - log_client_name(auth->client, SHOW_IP)); - auth_error(auth); - return; - } rb_snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", - (unsigned int) ntohs(them.sin_port), (unsigned int) ntohs(us.sin_port)); + auth->rport, auth->lport); - if(write(auth->fd, authbuf, strlen(authbuf)) == -1) + if(rb_write(auth->F, authbuf, strlen(authbuf)) != strlen(authbuf)) { auth_error(auth); return; } ClearAuthConnect(auth); SetAuthPending(auth); - read_auth_reply(auth->fd, auth); + read_auth_reply(auth->F, auth); } @@ -521,7 +559,7 @@ auth_connect_callback(int fd, int error, void *data) #define AUTH_BUFSIZ 128 static void -read_auth_reply(int fd, void *data) +read_auth_reply(rb_fde_t *F, void *data) { struct AuthRequest *auth = data; char *s = NULL; @@ -530,11 +568,11 @@ read_auth_reply(int fd, void *data) int count; char buf[AUTH_BUFSIZ + 1]; /* buffer to read auth reply into */ - len = read(auth->fd, buf, AUTH_BUFSIZ); + len = rb_read(F, buf, AUTH_BUFSIZ); - if(len < 0 && ignoreErrno(errno)) + if(len < 0 && rb_ignore_errno(errno)) { - rb_setselect(fd, FDLIST_IDLECLIENT, COMM_SELECT_READ, read_auth_reply, auth, 0); + rb_setselect(F, RB_SELECT_READ, read_auth_reply, auth); return; } @@ -565,20 +603,20 @@ read_auth_reply(int fd, void *data) } } - rb_close(auth->fd); - auth->fd = -1; + rb_close(auth->F); + auth->F = NULL; ClearAuth(auth); if(s == NULL) { - ++ServerStats->is_abad; + ++ServerStats.is_abad; strcpy(auth->client->username, "unknown"); sendheader(auth->client, REPORT_FAIL_ID); } else { sendheader(auth->client, REPORT_FIN_ID); - ++ServerStats->is_asuc; + ++ServerStats.is_asuc; SetGotId(auth->client); } @@ -606,8 +644,8 @@ delete_auth_queries(struct Client *target_p) if(IsDNSPending(auth)) delete_resolver_queries(&auth->dns_query); - if(auth->fd >= 0) - rb_close(auth->fd); + if(auth->F != NULL) + rb_close(auth->F); rb_dlinkDelete(&auth->node, &auth_poll_list); free_auth_request(auth);