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/trunk/src/s_auth.c (file contents), Revision 1592 by michael, Sat Oct 27 21:02:32 2012 UTC vs.
ircd-hybrid/trunk/src/auth.c (file contents), Revision 4696 by michael, Fri Oct 3 15:23:02 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 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file auth.c
23 > * \brief Functions for querying a users ident.
24 > * \version $Id$
25   */
26  
27   /*
# Line 37 | Line 39
39   #include "list.h"
40   #include "ircd_defs.h"
41   #include "fdlist.h"
42 < #include "s_auth.h"
42 > #include "auth.h"
43   #include "conf.h"
42 #include "balloc.h"
44   #include "client.h"
45   #include "event.h"
45 #include "hook.h"
46   #include "irc_string.h"
47   #include "ircd.h"
48   #include "packet.h"
49 < #include "irc_res.h"
49 > #include "res.h"
50   #include "s_bsd.h"
51   #include "log.h"
52   #include "send.h"
53 + #include "mempool.h"
54  
55  
56 < static const char *HeaderMessages[] = {
57 <  ":%s NOTICE AUTH :*** Looking up your hostname...",
58 <  ":%s NOTICE AUTH :*** Found your hostname",
59 <  ":%s NOTICE AUTH :*** Couldn't look up your hostname",
60 <  ":%s NOTICE AUTH :*** Checking Ident",
61 <  ":%s NOTICE AUTH :*** Got Ident response",
62 <  ":%s NOTICE AUTH :*** No Ident response",
63 <  ":%s NOTICE AUTH :*** Your forward and reverse DNS do not match, ignoring hostname.",
64 <  ":%s NOTICE AUTH :*** Your hostname is too long, ignoring hostname"
56 > static const char *const HeaderMessages[] =
57 > {
58 >  ":*** Looking up your hostname",
59 >  ":*** Found your hostname",
60 >  ":*** Couldn't look up your hostname",
61 >  ":*** Checking Ident",
62 >  ":*** Got Ident response",
63 >  ":*** No Ident response",
64 >  ":*** Your forward and reverse DNS do not match, ignoring hostname",
65 >  ":*** Your hostname is too long, ignoring hostname"
66   };
67  
68 < enum {
68 > enum
69 > {
70    REPORT_DO_DNS,
71    REPORT_FIN_DNS,
72    REPORT_FAIL_DNS,
# Line 74 | Line 77 | enum {
77    REPORT_HOST_TOOLONG
78   };
79  
80 < #define sendheader(c, i) sendto_one((c), HeaderMessages[(i)], me.name)
78 <
79 < static BlockHeap *auth_heap = NULL;
80 < static dlink_list auth_doing_list = { NULL, NULL, 0 };
81 <
82 < static EVH timeout_auth_queries_event;
80 > #define sendheader(c, i) sendto_one_notice((c), &me, HeaderMessages[(i)])
81  
82 < static PF read_auth_reply;
83 < static CNCB auth_connect_callback;
84 < static CBFUNC start_auth;
82 > static dlink_list auth_pending_list;
83 > static void read_auth_reply(fde_t *, void *);
84 > static void auth_connect_callback(fde_t *, int, void *);
85  
88 struct Callback *auth_cb = NULL;
89
90 /* init_auth()
91 *
92 * Initialise the auth code
93 */
94 void
95 init_auth(void)
96 {
97  auth_heap = BlockHeapCreate("auth", sizeof(struct AuthRequest), AUTH_HEAP_SIZE);
98  auth_cb = register_callback("start_auth", start_auth);
99  eventAddIsh("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1);
100 }
86  
87   /*
88   * make_auth_request - allocate a new auth request
# Line 105 | Line 90 | init_auth(void)
90   static struct AuthRequest *
91   make_auth_request(struct Client *client)
92   {
93 <  struct AuthRequest *request = BlockHeapAlloc(auth_heap);
93 >  struct AuthRequest *request = &client->connection->auth;
94  
95 <  client->localClient->auth = request;
96 <  request->client           = client;
97 <  request->timeout          = CurrentTime + CONNECTTIMEOUT;
95 >  memset(request, 0, sizeof(*request));
96 >
97 >  request->client  = client;
98 >  request->timeout = CurrentTime + CONNECTTIMEOUT;
99  
100    return request;
101   }
# Line 127 | Line 113 | release_auth_client(struct AuthRequest *
113    if (IsDoingAuth(auth) || IsDNSPending(auth))
114      return;
115  
116 <  client->localClient->auth = NULL;
117 <  dlinkDelete(&auth->node, &auth_doing_list);
118 <  BlockHeapFree(auth_heap, auth);
116 >  if (IsInAuth(auth))
117 >  {
118 >    dlinkDelete(&auth->node, &auth_pending_list);
119 >    ClearInAuth(auth);
120 >  }
121  
122    /*
123     * When a client has auth'ed, we want to start reading what it sends
124     * us. This is what read_packet() does.
125     *     -- adrian
126     */
127 <  client->localClient->allow_read = MAX_FLOOD;
128 <  comm_setflush(&client->localClient->fd, 1000, flood_recalc, client);
141 <
142 <  dlinkAdd(client, &client->node, &global_client_list);
127 >  client->connection->allow_read = MAX_FLOOD;
128 >  comm_setflush(&client->connection->fd, 1000, flood_recalc, client);
129  
130 <  client->localClient->since     = CurrentTime;
131 <  client->localClient->lasttime  = CurrentTime;
132 <  client->localClient->firsttime = CurrentTime;
130 >  client->connection->since     = CurrentTime;
131 >  client->connection->lasttime  = CurrentTime;
132 >  client->connection->firsttime = CurrentTime;
133    client->flags |= FLAGS_FINISHED_AUTH;
134  
135 <  read_packet(&client->localClient->fd, client);
135 >  read_packet(&client->connection->fd, client);
136   }
137 <
137 >
138   /*
139   * auth_dns_callback - called when resolver query finishes
140   * if the query resulted in a successful search, name will contain
# Line 157 | Line 143 | release_auth_client(struct AuthRequest *
143   * of success of failure
144   */
145   static void
146 < auth_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
146 > auth_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name, size_t namelength)
147   {
148    struct AuthRequest *auth = vptr;
149  
150    ClearDNSPending(auth);
151  
152 <  if (name != NULL)
152 >  if (!EmptyString(name))
153    {
154      const struct sockaddr_in *v4, *v4dns;
169 #ifdef IPV6
155      const struct sockaddr_in6 *v6, *v6dns;
171 #endif
172    int good = 1;
156  
157 < #ifdef IPV6
175 <    if (auth->client->localClient->ip.ss.ss_family == AF_INET6)
157 >    if (auth->client->connection->ip.ss.ss_family == AF_INET6)
158      {
159 <      v6 = (const struct sockaddr_in6 *)&auth->client->localClient->ip;
159 >      v6 = (const struct sockaddr_in6 *)&auth->client->connection->ip;
160        v6dns = (const struct sockaddr_in6 *)addr;
161 +
162        if (memcmp(&v6->sin6_addr, &v6dns->sin6_addr, sizeof(struct in6_addr)) != 0)
163        {
164          sendheader(auth->client, REPORT_IP_MISMATCH);
165 <        good = 0;
165 >        release_auth_client(auth);
166 >        return;
167        }
168      }
169      else
186 #endif
170      {
171 <      v4 = (const struct sockaddr_in *)&auth->client->localClient->ip;
171 >      v4 = (const struct sockaddr_in *)&auth->client->connection->ip;
172        v4dns = (const struct sockaddr_in *)addr;
173 <      if(v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
173 >
174 >      if (v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
175        {
176          sendheader(auth->client, REPORT_IP_MISMATCH);
177 <        good = 0;
177 >        release_auth_client(auth);
178 >        return;
179        }
180      }
181 <    if (good && strlen(name) <= HOSTLEN)
181 >
182 >    if (namelength > HOSTLEN)
183 >      sendheader(auth->client, REPORT_HOST_TOOLONG);
184 >    else
185      {
186 <      strlcpy(auth->client->host, name,
199 <              sizeof(auth->client->host));
186 >      strlcpy(auth->client->host, name, sizeof(auth->client->host));
187        sendheader(auth->client, REPORT_FIN_DNS);
188      }
202    else if (strlen(name) > HOSTLEN)
203      sendheader(auth->client, REPORT_HOST_TOOLONG);
189    }
190    else
191      sendheader(auth->client, REPORT_FAIL_DNS);
# Line 226 | Line 211 | auth_error(struct AuthRequest *auth)
211   }
212  
213   /*
214 < * start_auth_query - Flag the client to show that an attempt to
214 > * start_auth_query - Flag the client to show that an attempt to
215   * contact the ident server on
216   * the client's host.  The connect and subsequently the socket are all put
217   * into 'non-blocking' mode.  Should the connect or any later phase of the
# Line 238 | Line 223 | start_auth_query(struct AuthRequest *aut
223   {
224    struct irc_ssaddr localaddr;
225    socklen_t locallen = sizeof(struct irc_ssaddr);
241 #ifdef IPV6
226    struct sockaddr_in6 *v6;
243 #else
244  struct sockaddr_in *v4;
245 #endif
227  
228    /* open a socket of the same type as the client socket */
229 <  if (comm_open(&auth->fd, auth->client->localClient->ip.ss.ss_family,
229 >  if (comm_open(&auth->fd, auth->client->connection->ip.ss.ss_family,
230                  SOCK_STREAM, 0, "ident") == -1)
231    {
232 <    report_error(L_ALL, "creating auth stream socket %s:%s",
233 <        get_client_name(auth->client, SHOW_IP), errno);
232 >    report_error(L_ALL, "creating auth stream socket %s:%s",
233 >                 get_client_name(auth->client, SHOW_IP), errno);
234      ilog(LOG_TYPE_IRCD, "Unable to create auth socket for %s",
235          get_client_name(auth->client, SHOW_IP));
236      ++ServerStats.is_abad;
# Line 258 | Line 239 | start_auth_query(struct AuthRequest *aut
239  
240    sendheader(auth->client, REPORT_DO_ID);
241  
242 <  /*
242 >  /*
243     * get the local address of the client and bind to that to
244     * make the auth request.  This used to be done only for
245     * ifdef VIRTUAL_HOST, but needs to be done for all clients
# Line 266 | Line 247 | start_auth_query(struct AuthRequest *aut
247     * and machines with multiple IP addresses are common now
248     */
249    memset(&localaddr, 0, locallen);
250 <  getsockname(auth->client->localClient->fd.fd, (struct sockaddr*)&localaddr,
250 >  getsockname(auth->client->connection->fd.fd, (struct sockaddr*)&localaddr,
251        &locallen);
252  
272 #ifdef IPV6
253    remove_ipv6_mapping(&localaddr);
254    v6 = (struct sockaddr_in6 *)&localaddr;
255    v6->sin6_port = htons(0);
276 #else
277  localaddr.ss_len = locallen;
278  v4 = (struct sockaddr_in *)&localaddr;
279  v4->sin_port = htons(0);
280 #endif
256    localaddr.ss_port = htons(0);
257  
258 <  comm_connect_tcp(&auth->fd, auth->client->sockhost, 113,
259 <      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
260 <      auth, auth->client->localClient->ip.ss.ss_family,
258 >  comm_connect_tcp(&auth->fd, auth->client->sockhost, RFC1413_PORT,
259 >      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
260 >      auth, auth->client->connection->ip.ss.ss_family,
261        GlobalSetOptions.ident_timeout);
262    return 1; /* We suceed here for now */
263   }
264  
265   /*
266 < * GetValidIdent - parse ident query reply from identd server
292 < *
293 < * Inputs        - pointer to ident buf
294 < * Output        - NULL if no valid ident found, otherwise pointer to name
295 < * Side effects  -
296 < */
297 < /*
298 < * A few questions have been asked about this mess, obviously
299 < * it should have been commented better the first time.
300 < * The original idea was to remove all references to libc from ircd-hybrid.
301 < * Instead of having to write a replacement for sscanf(), I did a
302 < * rather gruseome parser here so we could remove this function call.
303 < * Note, that I had also removed a few floating point printfs as well (though
304 < * now we are still stuck with a few...)
305 < * Remember, we have a replacement ircd sprintf, we have bleeps fputs lib
306 < * it would have been nice to remove some unneeded code.
307 < * Oh well. If we don't remove libc stuff totally, then it would be
308 < * far cleaner to use sscanf()
309 < *
310 < * - Dianora
311 < */
312 < static char *
313 < GetValidIdent(char *buf)
314 < {
315 <  int   remp = 0;
316 <  int   locp = 0;
317 <  char* colon1Ptr;
318 <  char* colon2Ptr;
319 <  char* colon3Ptr;
320 <  char* commaPtr;
321 <  char* remotePortString;
322 <
323 <  /* All this to get rid of a sscanf() fun. */
324 <  remotePortString = buf;
325 <  
326 <  if ((colon1Ptr = strchr(remotePortString,':')) == NULL)
327 <    return 0;
328 <  *colon1Ptr = '\0';
329 <  colon1Ptr++;
330 <
331 <  if ((colon2Ptr = strchr(colon1Ptr,':')) == NULL)
332 <    return 0;
333 <  *colon2Ptr = '\0';
334 <  colon2Ptr++;
335 <  
336 <  if ((commaPtr = strchr(remotePortString, ',')) == NULL)
337 <    return 0;
338 <  *commaPtr = '\0';
339 <  commaPtr++;
340 <
341 <  if ((remp = atoi(remotePortString)) == 0)
342 <    return 0;
343 <              
344 <  if ((locp = atoi(commaPtr)) == 0)
345 <    return 0;
346 <
347 <  /* look for USERID bordered by first pair of colons */
348 <  if (strstr(colon1Ptr, "USERID") == NULL)
349 <    return 0;
350 <
351 <  if ((colon3Ptr = strchr(colon2Ptr,':')) == NULL)
352 <    return 0;
353 <  *colon3Ptr = '\0';
354 <  colon3Ptr++;
355 <  return (colon3Ptr);
356 < }
357 <
358 < /*
359 < * start_auth
266 > * start_auth
267   *
268   * inputs       - pointer to client to auth
269   * output       - NONE
270   * side effects - starts auth (identd) and dns queries for a client
271   */
272 < static void *
273 < start_auth(va_list args)
272 > void
273 > start_auth(struct Client *client_p)
274   {
368  struct Client *client = va_arg(args, struct Client *);
275    struct AuthRequest *auth = NULL;
276  
277 <  assert(client != NULL);
277 >  assert(client_p);
278  
279 <  auth = make_auth_request(client);
280 <  dlinkAdd(auth, &auth->node, &auth_doing_list);
279 >  auth = make_auth_request(client_p);
280 >  SetInAuth(auth);
281 >  dlinkAddTail(auth, &auth->node, &auth_pending_list);
282  
283 <  sendheader(client, REPORT_DO_DNS);
283 >  sendheader(client_p, REPORT_DO_DNS);
284  
285    SetDNSPending(auth);
286  
287 <  if (ConfigFileEntry.disable_auth == 0)
287 >  if (ConfigGeneral.disable_auth == 0)
288    {
289      SetDoingAuth(auth);
290      start_auth_query(auth);
291    }
292  
293 <  gethost_byaddr(auth_dns_callback, auth, &client->localClient->ip);
387 <
388 <  return NULL;
293 >  gethost_byaddr(auth_dns_callback, auth, &client_p->connection->ip);
294   }
295  
296   /*
# Line 395 | Line 300 | start_auth(va_list args)
300   static void
301   timeout_auth_queries_event(void *notused)
302   {
303 <  dlink_node *ptr = NULL, *next_ptr = NULL;
303 >  dlink_node *ptr = NULL, *ptr_next = NULL;
304  
305 <  DLINK_FOREACH_SAFE(ptr, next_ptr, auth_doing_list.head)
305 >  DLINK_FOREACH_SAFE(ptr, ptr_next, auth_pending_list.head)
306    {
307      struct AuthRequest *auth = ptr->data;
308  
309      if (auth->timeout > CurrentTime)
310 <      continue;
310 >      break;
311  
312      if (IsDoingAuth(auth))
313 <    {  
313 >    {
314        ++ServerStats.is_abad;
315        fd_close(&auth->fd);
316        ClearAuth(auth);
# Line 419 | Line 324 | timeout_auth_queries_event(void *notused
324        sendheader(auth->client, REPORT_FAIL_DNS);
325      }
326  
422    ilog(LOG_TYPE_IRCD, "DNS/AUTH timeout %s",
423         get_client_name(auth->client, SHOW_IP));
327      release_auth_client(auth);
328    }
329   }
# Line 446 | Line 349 | auth_connect_callback(fde_t *fd, int err
349    socklen_t ulen = sizeof(struct irc_ssaddr);
350    socklen_t tlen = sizeof(struct irc_ssaddr);
351    uint16_t uport, tport;
449 #ifdef IPV6
352    struct sockaddr_in6 *v6;
451 #else
452  struct sockaddr_in *v4;
453 #endif
353  
354    if (error != COMM_OK)
355    {
# Line 458 | Line 357 | auth_connect_callback(fde_t *fd, int err
357      return;
358    }
359  
360 <  if (getsockname(auth->client->localClient->fd.fd, (struct sockaddr *)&us,
361 <      &ulen) ||
463 <      getpeername(auth->client->localClient->fd.fd, (struct sockaddr *)&them,
464 <      &tlen))
360 >  if (getsockname(auth->client->connection->fd.fd, (struct sockaddr *)&us, &ulen) ||
361 >      getpeername(auth->client->connection->fd.fd, (struct sockaddr *)&them, &tlen))
362    {
363      ilog(LOG_TYPE_IRCD, "auth get{sock,peer}name error for %s",
364 <        get_client_name(auth->client, SHOW_IP));
364 >         get_client_name(auth->client, SHOW_IP));
365      auth_error(auth);
366      return;
367    }
368  
472 #ifdef IPV6
369    v6 = (struct sockaddr_in6 *)&us;
370    uport = ntohs(v6->sin6_port);
371    v6 = (struct sockaddr_in6 *)&them;
372    tport = ntohs(v6->sin6_port);
373    remove_ipv6_mapping(&us);
374    remove_ipv6_mapping(&them);
375 < #else
376 <  v4 = (struct sockaddr_in *)&us;
481 <  uport = ntohs(v4->sin_port);
482 <  v4 = (struct sockaddr_in *)&them;
483 <  tport = ntohs(v4->sin_port);
484 <  us.ss_len = ulen;
485 <  them.ss_len = tlen;
486 < #endif
487 <  
488 <  snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", tport, uport);
375 >
376 >  snprintf(authbuf, sizeof(authbuf), "%u, %u\r\n", tport, uport);
377  
378    if (send(fd->fd, authbuf, strlen(authbuf), 0) == -1)
379    {
# Line 493 | Line 381 | auth_connect_callback(fde_t *fd, int err
381      return;
382    }
383  
384 <  read_auth_reply(&auth->fd, auth);
384 >  comm_setselect(fd, COMM_SELECT_READ, read_auth_reply, auth, 0);
385 > }
386 >
387 > /** Enum used to index ident reply fields in a human-readable way. */
388 > enum IdentReplyFields
389 > {
390 >  IDENT_PORT_NUMBERS,
391 >  IDENT_REPLY_TYPE,
392 >  IDENT_OS_TYPE,
393 >  IDENT_INFO,
394 >  USERID_TOKEN_COUNT
395 > };
396 >
397 > /** Parse an ident reply line and extract the userid from it.
398 > * \param reply The ident reply line.
399 > * \return The userid, or NULL on parse failure.
400 > */
401 > static const char *
402 > check_ident_reply(char *reply)
403 > {
404 >  char *token = NULL, *end = NULL;
405 >  char *vector[USERID_TOKEN_COUNT];
406 >  int count = token_vector(reply, ':', vector, USERID_TOKEN_COUNT);
407 >
408 >  if (USERID_TOKEN_COUNT != count)
409 >    return NULL;
410 >
411 >  /*
412 >   * Second token is the reply type
413 >   */
414 >  token = vector[IDENT_REPLY_TYPE];
415 >
416 >  if (EmptyString(token))
417 >    return NULL;
418 >
419 >  while (IsSpace(*token))
420 >    ++token;
421 >
422 >  if (strncmp(token, "USERID", 6))
423 >    return NULL;
424 >
425 >  /*
426 >   * Third token is the os type
427 >   */
428 >  token = vector[IDENT_OS_TYPE];
429 >
430 >  if (EmptyString(token))
431 >    return NULL;
432 >
433 >  while (IsSpace(*token))
434 >   ++token;
435 >
436 >  /*
437 >   * Unless "OTHER" is specified as the operating system type, the server
438 >   * is expected to return the "normal" user identification of the owner
439 >   * of this connection. "Normal" in this context may be taken to mean a
440 >   * string of characters which uniquely identifies the connection owner
441 >   * such as a user identifier assigned by the system administrator and
442 >   * used by such user as a mail identifier, or as the "user" part of a
443 >   * user/password pair used to gain access to system resources. When an
444 >   * operating system is specified (e.g., anything but "OTHER"), the user
445 >   * identifier is expected to be in a more or less immediately useful
446 >   * form - e.g., something that could be used as an argument to "finger"
447 >   * or as a mail address.
448 >   */
449 >  if (!strncmp(token, "OTHER", 5))
450 >    return NULL;
451 >
452 >  /*
453 >   * Fourth token is the username
454 >   */
455 >  token = vector[IDENT_INFO];
456 >
457 >  if (EmptyString(token))
458 >    return NULL;
459 >
460 >  while (IsSpace(*token))
461 >    ++token;
462 >
463 >  while (*token == '~' || *token == '^')
464 >    ++token;
465 >
466 >  /*
467 >   * Look for the end of the username, terminators are '\0, @, <SPACE>, :'
468 >   */
469 >  for (end = token; *end; ++end)
470 >    if (IsSpace(*end) || '@' == *end || ':' == *end)
471 >      break;
472 >  *end = '\0';
473 >
474 >  return token;
475   }
476  
477   /*
478 < * read_auth_reply - read the reply (if any) from the ident server
478 > * read_auth_reply - read the reply (if any) from the ident server
479   * we connected to.
480   * We only give it one shot, if the reply isn't good the first time
481   * fail the authentication entirely. --Bleep
482   */
505 #define AUTH_BUFSIZ 128
506
483   static void
484   read_auth_reply(fde_t *fd, void *data)
485   {
486    struct AuthRequest *auth = data;
487 <  char *s = NULL;
488 <  char *t = NULL;
489 <  int len;
514 <  int count;
515 <  char buf[AUTH_BUFSIZ + 1]; /* buffer to read auth reply into */
516 <
517 <  /* Why?
518 <   * Well, recv() on many POSIX systems is a per-packet operation,
519 <   * and we do not necessarily want this, because on lowspec machines,
520 <   * the ident response may come back fragmented, thus resulting in an
521 <   * invalid ident response, even if the ident response was really OK.
522 <   *
523 <   * So PLEASE do not change this code to recv without being aware of the
524 <   * consequences.
525 <   *
526 <   *    --nenolod
527 <   */
528 <  len = read(fd->fd, buf, AUTH_BUFSIZ);
487 >  const char *username = NULL;
488 >  ssize_t len = 0;
489 >  char buf[RFC1413_BUFSIZ + 1];
490  
491 <  if (len < 0)
531 <  {
532 <    if (ignoreErrno(errno))
533 <      comm_setselect(fd, COMM_SELECT_READ, read_auth_reply, auth, 0);
534 <    else
535 <      auth_error(auth);
536 <    return;
537 <  }
538 <
539 <  if (len > 0)
491 >  if ((len = recv(fd->fd, buf, RFC1413_BUFSIZ, 0)) > 0)
492    {
493      buf[len] = '\0';
494 <
543 <    if ((s = GetValidIdent(buf)))
544 <    {
545 <      t = auth->client->username;
546 <
547 <      while (*s == '~' || *s == '^')
548 <        s++;
549 <
550 <      for (count = USERLEN; *s && count; s++)
551 <      {
552 <        if (*s == '@')
553 <          break;
554 <        if (!IsSpace(*s) && *s != ':' && *s != '[')
555 <        {
556 <          *t++ = *s;
557 <          count--;
558 <        }
559 <      }
560 <
561 <      *t = '\0';
562 <    }
494 >    username = check_ident_reply(buf);
495    }
496  
497    fd_close(fd);
498  
499    ClearAuth(auth);
500  
501 <  if (s == NULL)
501 >  if (EmptyString(username))
502    {
503      sendheader(auth->client, REPORT_FAIL_ID);
504      ++ServerStats.is_abad;
505    }
506    else
507    {
508 +    strlcpy(auth->client->username, username, sizeof(auth->client->username));
509      sendheader(auth->client, REPORT_FIN_ID);
510      ++ServerStats.is_asuc;
511      SetGotId(auth->client);
# Line 584 | Line 517 | read_auth_reply(fde_t *fd, void *data)
517   /*
518   * delete_auth()
519   */
520 < void
520 > void
521   delete_auth(struct AuthRequest *auth)
522   {
523    if (IsDNSPending(auth))
# Line 593 | Line 526 | delete_auth(struct AuthRequest *auth)
526    if (IsDoingAuth(auth))
527      fd_close(&auth->fd);
528  
529 <  dlinkDelete(&auth->node, &auth_doing_list);
530 <  BlockHeapFree(auth_heap, auth);
529 >  if (IsInAuth(auth))
530 >  {
531 >    dlinkDelete(&auth->node, &auth_pending_list);
532 >    ClearInAuth(auth);
533 >  }
534 > }
535 >
536 > /* auth_init
537 > *
538 > * Initialise the auth code
539 > */
540 > void
541 > auth_init(void)
542 > {
543 >  static struct event timeout_auth_queries =
544 >  {
545 >    .name = "timeout_auth_queries_event",
546 >    .handler = timeout_auth_queries_event,
547 >    .when = 1
548 >  };
549 >
550 >  event_add(&timeout_auth_queries, NULL);
551   }

Diff Legend

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