00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "stdinc.h"
00036 #include "tools.h"
00037 #include "list.h"
00038 #include "s_auth.h"
00039 #include "s_conf.h"
00040 #include "client.h"
00041 #include "common.h"
00042 #include "event.h"
00043 #include "fdlist.h"
00044 #include "hook.h"
00045 #include "irc_string.h"
00046 #include "sprintf_irc.h"
00047 #include "ircd.h"
00048 #include "numeric.h"
00049 #include "packet.h"
00050 #include "irc_res.h"
00051 #include "s_bsd.h"
00052 #include "s_log.h"
00053 #include "s_stats.h"
00054 #include "send.h"
00055 #include "memory.h"
00056
00057 static const char *HeaderMessages[] = {
00058 ":%s NOTICE AUTH :*** Looking up your hostname...",
00059 ":%s NOTICE AUTH :*** Found your hostname",
00060 ":%s NOTICE AUTH :*** Couldn't look up your hostname",
00061 ":%s NOTICE AUTH :*** Checking Ident",
00062 ":%s NOTICE AUTH :*** Got Ident response",
00063 ":%s NOTICE AUTH :*** No Ident response",
00064 ":%s NOTICE AUTH :*** Your forward and reverse DNS do not match, ignoring hostname.",
00065 ":%s NOTICE AUTH :*** Your hostname is too long, ignoring hostname"
00066 };
00067
00068 enum {
00069 REPORT_DO_DNS,
00070 REPORT_FIN_DNS,
00071 REPORT_FAIL_DNS,
00072 REPORT_DO_ID,
00073 REPORT_FIN_ID,
00074 REPORT_FAIL_ID,
00075 REPORT_IP_MISMATCH,
00076 REPORT_HOST_TOOLONG
00077 };
00078
00079 #define sendheader(c, i) sendto_one((c), HeaderMessages[(i)], me.name)
00080
00081
00082
00083
00084
00085
00086
00087 static dlink_list auth_doing_dns_list = { NULL, NULL, 0 };
00088 static dlink_list auth_doing_ident_list = { NULL, NULL, 0 };
00089
00090 static EVH timeout_auth_queries_event;
00091
00092 static PF read_auth_reply;
00093 static CNCB auth_connect_callback;
00094 static CBFUNC start_auth;
00095
00096 struct Callback *auth_cb = NULL;
00097
00098
00099
00100
00101
00102 void
00103 init_auth(void)
00104 {
00105 auth_cb = register_callback("start_auth", start_auth);
00106 eventAddIsh("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1);
00107 }
00108
00109
00110
00111
00112 static struct AuthRequest *
00113 make_auth_request(struct Client *client)
00114 {
00115 struct AuthRequest *request = MyMalloc(sizeof(struct AuthRequest));
00116
00117 request->client = client;
00118 request->timeout = CurrentTime + CONNECTTIMEOUT;
00119
00120 return request;
00121 }
00122
00123
00124
00125
00126
00127
00128 void
00129 release_auth_client(struct Client *client)
00130 {
00131
00132
00133
00134
00135
00136 client->localClient->allow_read = MAX_FLOOD;
00137 comm_setflush(&client->localClient->fd, 1000, flood_recalc, client);
00138
00139 if ((client->node.prev != NULL) || (client->node.next != NULL))
00140 {
00141 sendto_realops_flags(UMODE_ALL, L_OPER,
00142 "already linked %s at %s:%d", client->name,
00143 __FILE__, __LINE__);
00144 ilog(L_ERROR, "already linked %s at %s:%d", client->name,
00145 __FILE__, __LINE__);
00146 assert(0==5);
00147 }
00148 else
00149 dlinkAdd(client, &client->node, &global_client_list);
00150
00151 client->since = client->lasttime = client->firsttime = CurrentTime;
00152 client->flags |= FLAGS_FINISHED_AUTH;
00153
00154 read_packet(&client->localClient->fd, client);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164 static void
00165 auth_dns_callback(void *vptr, struct DNSReply *reply)
00166 {
00167 struct AuthRequest *auth = (struct AuthRequest *)vptr;
00168
00169 dlinkDelete(&auth->dns_node, &auth_doing_dns_list);
00170 ClearDNSPending(auth);
00171
00172 if (reply != NULL)
00173 {
00174 struct sockaddr_in *v4, *v4dns;
00175 #ifdef IPV6
00176 struct sockaddr_in6 *v6, *v6dns;
00177 #endif
00178 int good = 1;
00179
00180 #ifdef IPV6
00181 if (auth->client->localClient->ip.ss.ss_family == AF_INET6)
00182 {
00183 v6 = (struct sockaddr_in6 *)&auth->client->localClient->ip;
00184 v6dns = (struct sockaddr_in6 *)&reply->addr;
00185 if (memcmp(&v6->sin6_addr, &v6dns->sin6_addr, sizeof(struct in6_addr)) != 0)
00186 {
00187 sendheader(auth->client, REPORT_IP_MISMATCH);
00188 good = 0;
00189 }
00190 }
00191 else
00192 #endif
00193 {
00194 v4 = (struct sockaddr_in *)&auth->client->localClient->ip;
00195 v4dns = (struct sockaddr_in *)&reply->addr;
00196 if(v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
00197 {
00198 sendheader(auth->client, REPORT_IP_MISMATCH);
00199 good = 0;
00200 }
00201 }
00202 if (good && strlen(reply->h_name) <= HOSTLEN)
00203 {
00204 strlcpy(auth->client->host, reply->h_name,
00205 sizeof(auth->client->host));
00206 sendheader(auth->client, REPORT_FIN_DNS);
00207 }
00208 else if (strlen(reply->h_name) > HOSTLEN)
00209 sendheader(auth->client, REPORT_HOST_TOOLONG);
00210 }
00211 else
00212 sendheader(auth->client, REPORT_FAIL_DNS);
00213
00214 MyFree(auth->client->localClient->dns_query);
00215 auth->client->localClient->dns_query = NULL;
00216
00217 if (!IsDoingAuth(auth))
00218 {
00219 struct Client *client_p = auth->client;
00220 MyFree(auth);
00221 release_auth_client(client_p);
00222 }
00223 }
00224
00225
00226
00227
00228 static void
00229 auth_error(struct AuthRequest *auth)
00230 {
00231 ++ServerStats->is_abad;
00232
00233 fd_close(&auth->fd);
00234
00235 dlinkDelete(&auth->ident_node, &auth_doing_ident_list);
00236 ClearAuth(auth);
00237
00238 sendheader(auth->client, REPORT_FAIL_ID);
00239
00240 if (!IsDNSPending(auth) && !IsCrit(auth))
00241 {
00242 release_auth_client(auth->client);
00243 MyFree(auth);
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 static int
00256 start_auth_query(struct AuthRequest *auth)
00257 {
00258 struct irc_ssaddr localaddr;
00259 socklen_t locallen = sizeof(struct irc_ssaddr);
00260 #ifdef IPV6
00261 struct sockaddr_in6 *v6;
00262 #else
00263 struct sockaddr_in *v4;
00264 #endif
00265
00266
00267 if (comm_open(&auth->fd, auth->client->localClient->ip.ss.ss_family,
00268 SOCK_STREAM, 0, "ident") == -1)
00269 {
00270 report_error(L_ALL, "creating auth stream socket %s:%s",
00271 get_client_name(auth->client, SHOW_IP), errno);
00272 ilog(L_ERROR, "Unable to create auth socket for %s",
00273 get_client_name(auth->client, SHOW_IP));
00274 ++ServerStats->is_abad;
00275 return 0;
00276 }
00277
00278 sendheader(auth->client, REPORT_DO_ID);
00279
00280
00281
00282
00283
00284
00285
00286
00287 memset(&localaddr, 0, locallen);
00288 getsockname(auth->client->localClient->fd.fd, (struct sockaddr*)&localaddr,
00289 &locallen);
00290
00291 #ifdef IPV6
00292 remove_ipv6_mapping(&localaddr);
00293 v6 = (struct sockaddr_in6 *)&localaddr;
00294 v6->sin6_port = htons(0);
00295 #else
00296 localaddr.ss_len = locallen;
00297 v4 = (struct sockaddr_in *)&localaddr;
00298 v4->sin_port = htons(0);
00299 #endif
00300 localaddr.ss_port = htons(0);
00301
00302 SetDoingAuth(auth);
00303 dlinkAdd(auth, &auth->ident_node, &auth_doing_ident_list);
00304
00305 comm_connect_tcp(&auth->fd, auth->client->sockhost, 113,
00306 (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
00307 auth, auth->client->localClient->ip.ss.ss_family,
00308 GlobalSetOptions.ident_timeout);
00309 return 1;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 static char *
00335 GetValidIdent(char *buf)
00336 {
00337 int remp = 0;
00338 int locp = 0;
00339 char* colon1Ptr;
00340 char* colon2Ptr;
00341 char* colon3Ptr;
00342 char* commaPtr;
00343 char* remotePortString;
00344
00345
00346 remotePortString = buf;
00347
00348 if ((colon1Ptr = strchr(remotePortString,':')) == NULL)
00349 return 0;
00350 *colon1Ptr = '\0';
00351 colon1Ptr++;
00352
00353 if ((colon2Ptr = strchr(colon1Ptr,':')) == NULL)
00354 return 0;
00355 *colon2Ptr = '\0';
00356 colon2Ptr++;
00357
00358 if ((commaPtr = strchr(remotePortString, ',')) == NULL)
00359 return 0;
00360 *commaPtr = '\0';
00361 commaPtr++;
00362
00363 if ((remp = atoi(remotePortString)) == 0)
00364 return 0;
00365
00366 if ((locp = atoi(commaPtr)) == 0)
00367 return 0;
00368
00369
00370 if (strstr(colon1Ptr, "USERID") == NULL)
00371 return 0;
00372
00373 if ((colon3Ptr = strchr(colon2Ptr,':')) == NULL)
00374 return 0;
00375 *colon3Ptr = '\0';
00376 colon3Ptr++;
00377 return (colon3Ptr);
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387 static void *
00388 start_auth(va_list args)
00389 {
00390 struct Client *client = va_arg(args, struct Client *);
00391 struct AuthRequest *auth = NULL;
00392
00393 assert(client != NULL);
00394
00395 auth = make_auth_request(client);
00396 SetCrit(auth);
00397
00398 client->localClient->dns_query = MyMalloc(sizeof(struct DNSQuery));
00399 client->localClient->dns_query->ptr = auth;
00400 client->localClient->dns_query->callback = auth_dns_callback;
00401
00402 sendheader(client, REPORT_DO_DNS);
00403
00404 if (ConfigFileEntry.disable_auth == 0)
00405 start_auth_query(auth);
00406
00407
00408
00409
00410 SetDNSPending(auth);
00411 dlinkAdd(auth, &auth->dns_node, &auth_doing_dns_list);
00412 ClearCrit(auth);
00413 gethost_byaddr(&client->localClient->ip, client->localClient->dns_query);
00414
00415 return NULL;
00416 }
00417
00418
00419
00420
00421
00422 static void
00423 timeout_auth_queries_event(void *notused)
00424 {
00425 dlink_node *ptr;
00426 dlink_node *next_ptr;
00427 struct AuthRequest* auth;
00428
00429 DLINK_FOREACH_SAFE(ptr, next_ptr, auth_doing_ident_list.head)
00430 {
00431 auth = ptr->data;
00432
00433 if (auth->timeout <= CurrentTime)
00434 {
00435 fd_close(&auth->fd);
00436
00437 ++ServerStats->is_abad;
00438 sendheader(auth->client, REPORT_FAIL_ID);
00439
00440 if (IsDNSPending(auth))
00441 {
00442 struct Client *client_p = auth->client;
00443
00444 dlinkDelete(&auth->dns_node, &auth_doing_dns_list);
00445 if (client_p->localClient->dns_query != NULL)
00446 {
00447 delete_resolver_queries(client_p->localClient->dns_query);
00448 MyFree(client_p->localClient->dns_query);
00449 }
00450 auth->client->localClient->dns_query = NULL;
00451 sendheader(client_p, REPORT_FAIL_DNS);
00452 }
00453
00454 ilog(L_INFO, "DNS/AUTH timeout %s",
00455 get_client_name(auth->client, SHOW_IP));
00456
00457 dlinkDelete(&auth->ident_node, &auth_doing_ident_list);
00458 release_auth_client(auth->client);
00459 MyFree(auth);
00460 }
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 static void
00476 auth_connect_callback(fde_t *fd, int error, void *data)
00477 {
00478 struct AuthRequest *auth = data;
00479 struct irc_ssaddr us;
00480 struct irc_ssaddr them;
00481 char authbuf[32];
00482 socklen_t ulen = sizeof(struct irc_ssaddr);
00483 socklen_t tlen = sizeof(struct irc_ssaddr);
00484 u_int16_t uport, tport;
00485 #ifdef IPV6
00486 struct sockaddr_in6 *v6;
00487 #else
00488 struct sockaddr_in *v4;
00489 #endif
00490
00491 if (error != COMM_OK)
00492 {
00493 auth_error(auth);
00494 return;
00495 }
00496
00497 if (getsockname(auth->client->localClient->fd.fd, (struct sockaddr *) &us,
00498 (socklen_t *) &ulen) ||
00499 getpeername(auth->client->localClient->fd.fd, (struct sockaddr *) &them,
00500 (socklen_t *) &tlen))
00501 {
00502 ilog(L_INFO, "auth get{sock,peer}name error for %s",
00503 get_client_name(auth->client, SHOW_IP));
00504 auth_error(auth);
00505 return;
00506 }
00507
00508 #ifdef IPV6
00509 v6 = (struct sockaddr_in6 *)&us;
00510 uport = ntohs(v6->sin6_port);
00511 v6 = (struct sockaddr_in6 *)&them;
00512 tport = ntohs(v6->sin6_port);
00513 remove_ipv6_mapping(&us);
00514 remove_ipv6_mapping(&them);
00515 #else
00516 v4 = (struct sockaddr_in *)&us;
00517 uport = ntohs(v4->sin_port);
00518 v4 = (struct sockaddr_in *)&them;
00519 tport = ntohs(v4->sin_port);
00520 us.ss_len = ulen;
00521 them.ss_len = tlen;
00522 #endif
00523
00524 ircsprintf(authbuf, "%u , %u\r\n", tport, uport);
00525
00526 if (send(fd->fd, authbuf, strlen(authbuf), 0) == -1)
00527 {
00528 auth_error(auth);
00529 return;
00530 }
00531
00532 read_auth_reply(&auth->fd, auth);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541 #define AUTH_BUFSIZ 128
00542
00543 static void
00544 read_auth_reply(fde_t *fd, void *data)
00545 {
00546 struct AuthRequest *auth = data;
00547 char *s = NULL;
00548 char *t = NULL;
00549 int len;
00550 int count;
00551 char buf[AUTH_BUFSIZ + 1];
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 #ifndef _WIN32
00565 len = read(fd->fd, buf, AUTH_BUFSIZ);
00566 #else
00567 len = recv(fd->fd, buf, AUTH_BUFSIZ, 0);
00568 #endif
00569
00570 if (len < 0)
00571 {
00572 #ifdef _WIN32
00573 errno = WSAGetLastError();
00574 #endif
00575 if (ignoreErrno(errno))
00576 comm_setselect(fd, COMM_SELECT_READ, read_auth_reply, auth, 0);
00577 else
00578 auth_error(auth);
00579 return;
00580 }
00581
00582 if (len > 0)
00583 {
00584 buf[len] = '\0';
00585
00586 if ((s = GetValidIdent(buf)))
00587 {
00588 t = auth->client->username;
00589
00590 while (*s == '~' || *s == '^')
00591 s++;
00592
00593 for (count = USERLEN; *s && count; s++)
00594 {
00595 if (*s == '@')
00596 break;
00597 if (!IsSpace(*s) && *s != ':' && *s != '[')
00598 {
00599 *t++ = *s;
00600 count--;
00601 }
00602 }
00603
00604 *t = '\0';
00605 }
00606 }
00607
00608 fd_close(fd);
00609
00610 dlinkDelete(&auth->ident_node, &auth_doing_ident_list);
00611 ClearAuth(auth);
00612
00613 if (s == NULL)
00614 {
00615 sendheader(auth->client, REPORT_FAIL_ID);
00616 ++ServerStats->is_abad;
00617 }
00618 else
00619 {
00620 sendheader(auth->client, REPORT_FIN_ID);
00621 ++ServerStats->is_asuc;
00622 SetGotId(auth->client);
00623 }
00624
00625 if (!IsDNSPending(auth) && !IsCrit(auth))
00626 {
00627 release_auth_client(auth->client);
00628 MyFree(auth);
00629 }
00630 }
00631
00632
00633
00634
00635 void
00636 delete_auth(struct Client *target_p)
00637 {
00638 dlink_node *ptr;
00639 dlink_node *next_ptr;
00640 struct AuthRequest *auth;
00641
00642 if (!IsUnknown(target_p))
00643 return;
00644
00645 if (target_p->localClient->dns_query != NULL)
00646 DLINK_FOREACH_SAFE(ptr, next_ptr, auth_doing_dns_list.head)
00647 {
00648 auth = ptr->data;
00649
00650 if (auth->client == target_p)
00651 {
00652 delete_resolver_queries(target_p->localClient->dns_query);
00653 MyFree(target_p->localClient->dns_query);
00654 target_p->localClient->dns_query = NULL;
00655
00656 dlinkDelete(&auth->dns_node, &auth_doing_dns_list);
00657
00658 if (!IsDoingAuth(auth))
00659 {
00660 MyFree(auth);
00661 return;
00662 }
00663 }
00664 }
00665
00666 DLINK_FOREACH_SAFE(ptr, next_ptr, auth_doing_ident_list.head)
00667 {
00668 auth = ptr->data;
00669
00670 if (auth->client == target_p)
00671 {
00672 fd_close(&auth->fd);
00673
00674 dlinkDelete(&auth->ident_node, &auth_doing_ident_list);
00675 MyFree(auth);
00676 }
00677 }
00678 }