ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/auth.c
(Generate patch)

Comparing:
ircd-hybrid-7.2/src/s_auth.c (file contents), Revision 1000 by michael, Mon Aug 24 13:37:39 2009 UTC vs.
ircd-hybrid/trunk/src/s_auth.c (file contents), Revision 3250 by michael, Sun Mar 30 20:47:30 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  s_auth.c: Functions for querying a users ident.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file s_auth.c
23 > * \brief Functions for querying a users ident.
24 > * \version $Id$
25   */
26  
27   /*
# Line 32 | Line 34
34   *     any messages from it.
35   *     --Bleep  Thomas Helvey <tomh@inxpress.net>
36   */
37 +
38   #include "stdinc.h"
36 #include "tools.h"
39   #include "list.h"
40 + #include "ircd_defs.h"
41 + #include "fdlist.h"
42   #include "s_auth.h"
43 < #include "s_conf.h"
40 < #include "balloc.h"
43 > #include "conf.h"
44   #include "client.h"
42 #include "common.h"
45   #include "event.h"
44 #include "fdlist.h"              /* fdlist_add */
46   #include "hook.h"
47   #include "irc_string.h"
47 #include "sprintf_irc.h"
48   #include "ircd.h"
49 #include "numeric.h"
49   #include "packet.h"
50   #include "irc_res.h"
51   #include "s_bsd.h"
52 < #include "s_log.h"
52 > #include "log.h"
53   #include "send.h"
54 < #include "memory.h"
54 > #include "mempool.h"
55 >
56  
57 < static const char *HeaderMessages[] = {
58 <  ":%s NOTICE AUTH :*** Looking up your hostname...",
59 <  ":%s NOTICE AUTH :*** Found your hostname",
60 <  ":%s NOTICE AUTH :*** Couldn't look up your hostname",
61 <  ":%s NOTICE AUTH :*** Checking Ident",
62 <  ":%s NOTICE AUTH :*** Got Ident response",
63 <  ":%s NOTICE AUTH :*** No Ident response",
64 <  ":%s NOTICE AUTH :*** Your forward and reverse DNS do not match, ignoring hostname.",
65 <  ":%s NOTICE AUTH :*** Your hostname is too long, ignoring hostname"
57 > static const char *HeaderMessages[] =
58 > {
59 >  ":*** Looking up your hostname...",
60 >  ":*** Found your hostname",
61 >  ":*** Couldn't look up your hostname",
62 >  ":*** Checking Ident",
63 >  ":*** Got Ident response",
64 >  ":*** No Ident response",
65 >  ":*** Your forward and reverse DNS do not match, ignoring hostname.",
66 >  ":*** Your hostname is too long, ignoring hostname"
67   };
68  
69 < enum {
69 > enum
70 > {
71    REPORT_DO_DNS,
72    REPORT_FIN_DNS,
73    REPORT_FAIL_DNS,
# Line 76 | Line 78 | enum {
78    REPORT_HOST_TOOLONG
79   };
80  
81 < #define sendheader(c, i) sendto_one((c), HeaderMessages[(i)], me.name)
81 > #define sendheader(c, i) sendto_one_notice((c), &me, HeaderMessages[(i)])
82  
81 static BlockHeap *auth_heap = NULL;
83   static dlink_list auth_doing_list = { NULL, NULL, 0 };
84  
85   static EVH timeout_auth_queries_event;
86  
87   static PF read_auth_reply;
88   static CNCB auth_connect_callback;
88 static CBFUNC start_auth;
89  
90 < struct Callback *auth_cb = NULL;
91 <
92 < /* init_auth()
90 > /* auth_init
91   *
92   * Initialise the auth code
93   */
94   void
95 < init_auth(void)
95 > auth_init(void)
96   {
99  auth_heap = BlockHeapCreate("auth", sizeof(struct AuthRequest), AUTH_HEAP_SIZE);
100  auth_cb = register_callback("start_auth", start_auth);
97    eventAddIsh("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1);
98   }
99  
# Line 107 | Line 103 | init_auth(void)
103   static struct AuthRequest *
104   make_auth_request(struct Client *client)
105   {
106 <  struct AuthRequest *request = BlockHeapAlloc(auth_heap);
106 >  struct AuthRequest *request = &client->localClient->auth;
107 >
108 >  memset(request, 0, sizeof(*request));
109  
110 <  client->localClient->auth = request;
111 <  request->client           = client;
114 <  request->timeout          = CurrentTime + CONNECTTIMEOUT;
110 >  request->client  = client;
111 >  request->timeout = CurrentTime + CONNECTTIMEOUT;
112  
113    return request;
114   }
# Line 129 | Line 126 | release_auth_client(struct AuthRequest *
126    if (IsDoingAuth(auth) || IsDNSPending(auth))
127      return;
128  
129 <  client->localClient->auth = NULL;
130 <  dlinkDelete(&auth->node, &auth_doing_list);
131 <  BlockHeapFree(auth_heap, auth);
129 >  if (IsInAuth(auth))
130 >  {
131 >    dlinkDelete(&auth->node, &auth_doing_list);
132 >    ClearInAuth(auth);
133 >  }
134  
135    /*
136     * When a client has auth'ed, we want to start reading what it sends
# Line 143 | Line 142 | release_auth_client(struct AuthRequest *
142  
143    dlinkAdd(client, &client->node, &global_client_list);
144  
145 <  client->since  = client->lasttime = client->firsttime = CurrentTime;
145 >  client->localClient->since     = CurrentTime;
146 >  client->localClient->lasttime  = CurrentTime;
147 >  client->localClient->firsttime = CurrentTime;
148    client->flags |= FLAGS_FINISHED_AUTH;
149  
150    read_packet(&client->localClient->fd, client);
151   }
152 <
152 >
153   /*
154   * auth_dns_callback - called when resolver query finishes
155   * if the query resulted in a successful search, name will contain
# Line 163 | Line 164 | auth_dns_callback(void *vptr, const stru
164  
165    ClearDNSPending(auth);
166  
167 <  if (name != NULL)
167 >  if (name)
168    {
169      const struct sockaddr_in *v4, *v4dns;
170   #ifdef IPV6
# Line 176 | Line 177 | auth_dns_callback(void *vptr, const stru
177      {
178        v6 = (const struct sockaddr_in6 *)&auth->client->localClient->ip;
179        v6dns = (const struct sockaddr_in6 *)addr;
180 +
181        if (memcmp(&v6->sin6_addr, &v6dns->sin6_addr, sizeof(struct in6_addr)) != 0)
182        {
183          sendheader(auth->client, REPORT_IP_MISMATCH);
# Line 187 | Line 189 | auth_dns_callback(void *vptr, const stru
189      {
190        v4 = (const struct sockaddr_in *)&auth->client->localClient->ip;
191        v4dns = (const struct sockaddr_in *)addr;
192 <      if(v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
192 >
193 >      if (v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
194        {
195          sendheader(auth->client, REPORT_IP_MISMATCH);
196          good = 0;
197        }
198      }
199 +
200      if (good && strlen(name) <= HOSTLEN)
201      {
202        strlcpy(auth->client->host, name,
203 <              sizeof(auth->client->host));
203 >              sizeof(auth->client->host));
204        sendheader(auth->client, REPORT_FIN_DNS);
205      }
206      else if (strlen(name) > HOSTLEN)
# Line 226 | Line 230 | auth_error(struct AuthRequest *auth)
230   }
231  
232   /*
233 < * start_auth_query - Flag the client to show that an attempt to
233 > * start_auth_query - Flag the client to show that an attempt to
234   * contact the ident server on
235   * the client's host.  The connect and subsequently the socket are all put
236   * into 'non-blocking' mode.  Should the connect or any later phase of the
# Line 248 | Line 252 | start_auth_query(struct AuthRequest *aut
252    if (comm_open(&auth->fd, auth->client->localClient->ip.ss.ss_family,
253                  SOCK_STREAM, 0, "ident") == -1)
254    {
255 <    report_error(L_ALL, "creating auth stream socket %s:%s",
256 <        get_client_name(auth->client, SHOW_IP), errno);
257 <    ilog(L_ERROR, "Unable to create auth socket for %s",
255 >    report_error(L_ALL, "creating auth stream socket %s:%s",
256 >                 get_client_name(auth->client, SHOW_IP), errno);
257 >    ilog(LOG_TYPE_IRCD, "Unable to create auth socket for %s",
258          get_client_name(auth->client, SHOW_IP));
259      ++ServerStats.is_abad;
260      return 0;
# Line 258 | Line 262 | start_auth_query(struct AuthRequest *aut
262  
263    sendheader(auth->client, REPORT_DO_ID);
264  
265 <  /*
265 >  /*
266     * get the local address of the client and bind to that to
267     * make the auth request.  This used to be done only for
268     * ifdef VIRTUAL_HOST, but needs to be done for all clients
# Line 280 | Line 284 | start_auth_query(struct AuthRequest *aut
284   #endif
285    localaddr.ss_port = htons(0);
286  
287 <  comm_connect_tcp(&auth->fd, auth->client->sockhost, 113,
288 <      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
289 <      auth, auth->client->localClient->ip.ss.ss_family,
287 >  comm_connect_tcp(&auth->fd, auth->client->sockhost, 113,
288 >      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
289 >      auth, auth->client->localClient->ip.ss.ss_family,
290        GlobalSetOptions.ident_timeout);
291    return 1; /* We suceed here for now */
292   }
293  
294   /*
295   * GetValidIdent - parse ident query reply from identd server
296 < *
296 > *
297   * Inputs        - pointer to ident buf
298   * Output        - NULL if no valid ident found, otherwise pointer to name
299   * Side effects  -
# Line 322 | Line 326 | GetValidIdent(char *buf)
326  
327    /* All this to get rid of a sscanf() fun. */
328    remotePortString = buf;
329 <  
329 >
330    if ((colon1Ptr = strchr(remotePortString,':')) == NULL)
331      return 0;
332    *colon1Ptr = '\0';
# Line 332 | Line 336 | GetValidIdent(char *buf)
336      return 0;
337    *colon2Ptr = '\0';
338    colon2Ptr++;
339 <  
339 >
340    if ((commaPtr = strchr(remotePortString, ',')) == NULL)
341      return 0;
342    *commaPtr = '\0';
# Line 340 | Line 344 | GetValidIdent(char *buf)
344  
345    if ((remp = atoi(remotePortString)) == 0)
346      return 0;
347 <              
347 >
348    if ((locp = atoi(commaPtr)) == 0)
349      return 0;
350  
# Line 356 | Line 360 | GetValidIdent(char *buf)
360   }
361  
362   /*
363 < * start_auth
363 > * start_auth
364   *
365   * inputs       - pointer to client to auth
366   * output       - NONE
367   * side effects - starts auth (identd) and dns queries for a client
368   */
369 < static void *
370 < start_auth(va_list args)
369 > void
370 > start_auth(struct Client *client_p)
371   {
368  struct Client *client = va_arg(args, struct Client *);
372    struct AuthRequest *auth = NULL;
373  
374 <  assert(client != NULL);
374 >  assert(client_p);
375  
376 <  auth = make_auth_request(client);
377 <  dlinkAdd(auth, &auth->node, &auth_doing_list);
376 >  auth = make_auth_request(client_p);
377 >  SetInAuth(auth);
378 >  dlinkAddTail(auth, &auth->node, &auth_doing_list);
379  
380 <  sendheader(client, REPORT_DO_DNS);
380 >  sendheader(client_p, REPORT_DO_DNS);
381  
382    SetDNSPending(auth);
383  
# Line 383 | Line 387 | start_auth(va_list args)
387      start_auth_query(auth);
388    }
389  
390 <  gethost_byaddr(auth_dns_callback, auth, &client->localClient->ip);
387 <
388 <  return NULL;
390 >  gethost_byaddr(auth_dns_callback, auth, &client_p->localClient->ip);
391   }
392  
393   /*
# Line 395 | Line 397 | start_auth(va_list args)
397   static void
398   timeout_auth_queries_event(void *notused)
399   {
400 <  dlink_node *ptr = NULL, *next_ptr = NULL;
400 >  dlink_node *ptr = NULL, *ptr_next = NULL;
401  
402 <  DLINK_FOREACH_SAFE(ptr, next_ptr, auth_doing_list.head)
402 >  DLINK_FOREACH_SAFE(ptr, ptr_next, auth_doing_list.head)
403    {
404      struct AuthRequest *auth = ptr->data;
405  
406      if (auth->timeout > CurrentTime)
407 <      continue;
407 >      break;
408  
409      if (IsDoingAuth(auth))
410 <    {  
410 >    {
411        ++ServerStats.is_abad;
412        fd_close(&auth->fd);
413        ClearAuth(auth);
# Line 419 | Line 421 | timeout_auth_queries_event(void *notused
421        sendheader(auth->client, REPORT_FAIL_DNS);
422      }
423  
424 <    ilog(L_INFO, "DNS/AUTH timeout %s",
424 >    ilog(LOG_TYPE_IRCD, "DNS/AUTH timeout %s",
425           get_client_name(auth->client, SHOW_IP));
426      release_auth_client(auth);
427    }
# Line 445 | Line 447 | auth_connect_callback(fde_t *fd, int err
447    char authbuf[32];
448    socklen_t ulen = sizeof(struct irc_ssaddr);
449    socklen_t tlen = sizeof(struct irc_ssaddr);
450 <  u_int16_t uport, tport;
450 >  uint16_t uport, tport;
451   #ifdef IPV6
452    struct sockaddr_in6 *v6;
453   #else
# Line 458 | Line 460 | auth_connect_callback(fde_t *fd, int err
460      return;
461    }
462  
463 <  if (getsockname(auth->client->localClient->fd.fd, (struct sockaddr *) &us,
464 <      (socklen_t *) &ulen) ||
463 <      getpeername(auth->client->localClient->fd.fd, (struct sockaddr *) &them,
464 <      (socklen_t *) &tlen))
463 >  if (getsockname(auth->client->localClient->fd.fd, (struct sockaddr *)&us, &ulen) ||
464 >      getpeername(auth->client->localClient->fd.fd, (struct sockaddr *)&them, &tlen))
465    {
466 <    ilog(L_INFO, "auth get{sock,peer}name error for %s",
467 <        get_client_name(auth->client, SHOW_IP));
466 >    ilog(LOG_TYPE_IRCD, "auth get{sock,peer}name error for %s",
467 >         get_client_name(auth->client, SHOW_IP));
468      auth_error(auth);
469      return;
470    }
# Line 484 | Line 484 | auth_connect_callback(fde_t *fd, int err
484    us.ss_len = ulen;
485    them.ss_len = tlen;
486   #endif
487 <  
488 <  ircsprintf(authbuf, "%u , %u\r\n", tport, uport);
487 >
488 >  snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", tport, uport);
489  
490    if (send(fd->fd, authbuf, strlen(authbuf), 0) == -1)
491    {
# Line 497 | Line 497 | auth_connect_callback(fde_t *fd, int err
497   }
498  
499   /*
500 < * read_auth_reply - read the reply (if any) from the ident server
500 > * read_auth_reply - read the reply (if any) from the ident server
501   * we connected to.
502   * We only give it one shot, if the reply isn't good the first time
503   * fail the authentication entirely. --Bleep
# Line 525 | Line 525 | read_auth_reply(fde_t *fd, void *data)
525     *
526     *    --nenolod
527     */
528 #ifndef _WIN32
528    len = read(fd->fd, buf, AUTH_BUFSIZ);
529 < #else
531 <  len = recv(fd->fd, buf, AUTH_BUFSIZ, 0);
532 < #endif
533 <  
529 >
530    if (len < 0)
531    {
536 #ifdef _WIN32
537    errno = WSAGetLastError();
538 #endif
532      if (ignoreErrno(errno))
533        comm_setselect(fd, COMM_SELECT_READ, read_auth_reply, auth, 0);
534      else
# Line 591 | Line 584 | read_auth_reply(fde_t *fd, void *data)
584   /*
585   * delete_auth()
586   */
587 < void
587 > void
588   delete_auth(struct AuthRequest *auth)
589   {
590    if (IsDNSPending(auth))
# Line 600 | Line 593 | delete_auth(struct AuthRequest *auth)
593    if (IsDoingAuth(auth))
594      fd_close(&auth->fd);
595  
596 <  dlinkDelete(&auth->node, &auth_doing_list);
597 <  BlockHeapFree(auth_heap, auth);
596 >  if (IsInAuth(auth))
597 >  {
598 >    dlinkDelete(&auth->node, &auth_doing_list);
599 >    ClearInAuth(auth);
600 >  }
601   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)