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/auth.c (file contents):
Revision 4340 by michael, Sat Aug 2 16:53:22 2014 UTC vs.
Revision 8361 by michael, Sun Mar 4 14:22:42 2018 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2014 ircd-hybrid development team
4 > *  Copyright (c) 1997-2018 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 15 | 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  
22   /*! \file auth.c
23 < * \brief Functions for querying a users ident.
23 > * \brief Implementation of DNS and ident lookups.
24   * \version $Id$
25   */
26  
# Line 53 | Line 53
53   #include "mempool.h"
54  
55  
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
56   enum
57   {
58    REPORT_DO_DNS,
# Line 74 | Line 62 | enum
62    REPORT_FIN_ID,
63    REPORT_FAIL_ID,
64    REPORT_IP_MISMATCH,
65 <  REPORT_HOST_TOOLONG
65 >  REPORT_HOST_TOOLONG,
66 >  REPORT_HOST_INVALID
67   };
68  
69 < #define sendheader(c, i) sendto_one_notice((c), &me, HeaderMessages[(i)])
69 > static const char *const HeaderMessages[] =
70 > {
71 >  [REPORT_DO_DNS] = ":*** Looking up your hostname",
72 >  [REPORT_FIN_DNS] = ":*** Found your hostname",
73 >  [REPORT_FAIL_DNS] = ":*** Couldn't look up your hostname",
74 >  [REPORT_DO_ID] = ":*** Checking Ident",
75 >  [REPORT_FIN_ID] = ":*** Got Ident response",
76 >  [REPORT_FAIL_ID] = ":*** No Ident response",
77 >  [REPORT_IP_MISMATCH] = ":*** Your forward and reverse DNS do not match, ignoring hostname",
78 >  [REPORT_HOST_TOOLONG] = ":*** Your hostname is too long, ignoring hostname",
79 >  [REPORT_HOST_INVALID] = ":*** Your hostname contains illegal characters, ignoring hostname"
80 > };
81  
82 < static dlink_list auth_pending_list;
83 < static PF read_auth_reply;
84 < static CNCB auth_connect_callback;
82 > #define auth_sendheader(c, i) sendto_one_notice((c), &me, "%s", HeaderMessages[(i)])
83  
84 + static mp_pool_t *auth_pool;
85 + static dlink_list auth_list;
86  
87 < /*
88 < * make_auth_request - allocate a new auth request
87 >
88 > /*! \brief Allocate a new auth request.
89 > * \param client The client being looked up.
90 > * \return The newly allocated auth request.
91   */
92   static struct AuthRequest *
93 < make_auth_request(struct Client *client)
93 > auth_make(struct Client *client)
94   {
95 <  struct AuthRequest *request = &client->localClient->auth;
95 >  struct AuthRequest *auth = mp_pool_get(auth_pool);;
96  
97 <  memset(request, 0, sizeof(*request));
97 >  client->connection->auth = auth;
98 >  auth->client = client;
99 >  auth->timeout = CurrentTime + CONNECTTIMEOUT;
100  
101 <  request->client  = client;
98 <  request->timeout = CurrentTime + CONNECTTIMEOUT;
99 <
100 <  return request;
101 >  return auth;
102   }
103  
104 < /*
105 < * release_auth_client - release auth client from auth system
106 < * this adds the client into the local client lists so it can be read by
106 < * the main io processing loop
104 > /*! \brief Release auth client from auth system. This adds the client into the
105 > *         local client lists so it can be read by the main io processing loop.
106 > * \param auth Pointer to AuthRequest struct to release
107   */
108 < void
109 < release_auth_client(struct AuthRequest *auth)
108 > static void
109 > auth_release_client(struct AuthRequest *auth)
110   {
111 <  struct Client *client = auth->client;
111 >  struct Client *const client = auth->client;
112  
113    if (IsDoingAuth(auth) || IsDNSPending(auth))
114      return;
115  
116 <  if (IsInAuth(auth))
117 <  {
118 <    dlinkDelete(&auth->node, &auth_pending_list);
119 <    ClearInAuth(auth);
120 <  }
116 >  assert(dlinkFind(&auth_list, auth));
117 >  dlinkDelete(&auth->node, &auth_list);
118 >
119 >  mp_pool_release(auth);
120 >  client->connection->auth = NULL;
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);
127 >  client->connection->allow_read = MAX_FLOOD;
128 >  comm_setflush(client->connection->fd, 1000, flood_recalc, client);
129 >
130 >  client->connection->since     = CurrentTime;
131 >  client->connection->lasttime  = CurrentTime;
132 >  client->connection->firsttime = CurrentTime;
133 >  AddFlag(client, FLAGS_FINISHED_AUTH);
134  
135 <  client->localClient->since     = CurrentTime;
131 <  client->localClient->lasttime  = CurrentTime;
132 <  client->localClient->firsttime = CurrentTime;
133 <  client->flags |= FLAGS_FINISHED_AUTH;
135 >  strlcpy(client->realhost, client->host, sizeof(client->realhost));
136  
137 <  read_packet(&client->localClient->fd, client);
137 >  read_packet(client->connection->fd, client);
138   }
139  
140 < /*
141 < * auth_dns_callback - called when resolver query finishes
142 < * if the query resulted in a successful search, name will contain
143 < * a non-NULL pointer, otherwise name will be NULL.
144 < * set the client on it's way to a connection completion, regardless
145 < * of success of failure
140 > /*! Checks if a hostname is valid and doesn't contain illegal characters
141 > * \param hostname The string to verify
142 > * \return 1 if it is valid, 0 if it isn't
143 > */
144 > static int
145 > auth_verify_hostname(const char *hostname)
146 > {
147 >  const char *p = hostname;
148 >
149 >  assert(p);
150 >
151 >  if (EmptyString(p) || *p == '.' || *p == ':')
152 >    return 0;
153 >
154 >  for (; *p; ++p)
155 >    if (!IsHostChar(*p))
156 >      return 0;
157 >
158 >  return 1;
159 > }
160 >
161 > /*! \brief Handle a complete DNS lookup. Send the client on its way to a connection
162 > *         completion, regardless of success or failure.
163 > * \param vptr The pending struct AuthRequest.
164 > * \param addr IP address being resolved.
165 > * \param name Resolved name, or NULL if lookup failed.
166 > * \param namelength String length of the resolved hostname pointed by 'name'
167   */
168   static void
169 < auth_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
169 > auth_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name, size_t namelength)
170   {
171 <  struct AuthRequest *auth = vptr;
171 >  struct AuthRequest *const auth = vptr;
172  
173    ClearDNSPending(auth);
174  
175 <  if (name)
175 >  if (!EmptyString(name))
176    {
177 <    const struct sockaddr_in *v4, *v4dns;
155 < #ifdef IPV6
156 <    const struct sockaddr_in6 *v6, *v6dns;
157 < #endif
158 <    int good = 1;
159 <
160 < #ifdef IPV6
161 <    if (auth->client->localClient->ip.ss.ss_family == AF_INET6)
177 >    if (auth->client->connection->ip.ss.ss_family == AF_INET6)
178      {
179 <      v6 = (const struct sockaddr_in6 *)&auth->client->localClient->ip;
180 <      v6dns = (const struct sockaddr_in6 *)addr;
179 >      const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)&auth->client->connection->ip;
180 >      const struct sockaddr_in6 *const v6dns = (const struct sockaddr_in6 *)addr;
181  
182 <      if (memcmp(&v6->sin6_addr, &v6dns->sin6_addr, sizeof(struct in6_addr)) != 0)
182 >      if (memcmp(&v6->sin6_addr, &v6dns->sin6_addr, sizeof(struct in6_addr)))
183        {
184 <        sendheader(auth->client, REPORT_IP_MISMATCH);
185 <        good = 0;
184 >        auth_sendheader(auth->client, REPORT_IP_MISMATCH);
185 >        auth_release_client(auth);
186 >        return;
187        }
188      }
189      else
173 #endif
190      {
191 <      v4 = (const struct sockaddr_in *)&auth->client->localClient->ip;
192 <      v4dns = (const struct sockaddr_in *)addr;
191 >      const struct sockaddr_in *const v4 = (const struct sockaddr_in *)&auth->client->connection->ip;
192 >      const struct sockaddr_in *const v4dns = (const struct sockaddr_in *)addr;
193  
194        if (v4->sin_addr.s_addr != v4dns->sin_addr.s_addr)
195        {
196 <        sendheader(auth->client, REPORT_IP_MISMATCH);
197 <        good = 0;
196 >        auth_sendheader(auth->client, REPORT_IP_MISMATCH);
197 >        auth_release_client(auth);
198 >        return;
199        }
200      }
201  
202 <    if (good && strlen(name) <= HOSTLEN)
202 >    if (namelength > HOSTLEN)
203 >      auth_sendheader(auth->client, REPORT_HOST_TOOLONG);
204 >    else if (!auth_verify_hostname(name))
205 >      auth_sendheader(auth->client, REPORT_HOST_INVALID);
206 >    else
207      {
208 <      strlcpy(auth->client->host, name,
209 <              sizeof(auth->client->host));
189 <      sendheader(auth->client, REPORT_FIN_DNS);
208 >      strlcpy(auth->client->host, name, sizeof(auth->client->host));
209 >      auth_sendheader(auth->client, REPORT_FIN_DNS);
210      }
191    else if (strlen(name) > HOSTLEN)
192      sendheader(auth->client, REPORT_HOST_TOOLONG);
211    }
212    else
213 <    sendheader(auth->client, REPORT_FAIL_DNS);
213 >    auth_sendheader(auth->client, REPORT_FAIL_DNS);
214  
215 <  release_auth_client(auth);
215 >  auth_release_client(auth);
216   }
217  
218   /*
219 < * authsenderr - handle auth send errors
219 > * auth_error - handle auth send errors
220   */
221   static void
222   auth_error(struct AuthRequest *auth)
223   {
224    ++ServerStats.is_abad;
225  
226 <  fd_close(&auth->fd);
226 >  fd_close(auth->fd);
227 >  auth->fd = NULL;
228  
229    ClearAuth(auth);
230  
231 <  sendheader(auth->client, REPORT_FAIL_ID);
213 <
214 <  release_auth_client(auth);
215 < }
216 <
217 < /*
218 < * start_auth_query - Flag the client to show that an attempt to
219 < * contact the ident server on
220 < * the client's host.  The connect and subsequently the socket are all put
221 < * into 'non-blocking' mode.  Should the connect or any later phase of the
222 < * identifing process fail, it is aborted and the user is given a username
223 < * of "unknown".
224 < */
225 < static int
226 < start_auth_query(struct AuthRequest *auth)
227 < {
228 <  struct irc_ssaddr localaddr;
229 <  socklen_t locallen = sizeof(struct irc_ssaddr);
230 < #ifdef IPV6
231 <  struct sockaddr_in6 *v6;
232 < #else
233 <  struct sockaddr_in *v4;
234 < #endif
235 <
236 <  /* open a socket of the same type as the client socket */
237 <  if (comm_open(&auth->fd, auth->client->localClient->ip.ss.ss_family,
238 <                SOCK_STREAM, 0, "ident") == -1)
239 <  {
240 <    report_error(L_ALL, "creating auth stream socket %s:%s",
241 <                 get_client_name(auth->client, SHOW_IP), errno);
242 <    ilog(LOG_TYPE_IRCD, "Unable to create auth socket for %s",
243 <        get_client_name(auth->client, SHOW_IP));
244 <    ++ServerStats.is_abad;
245 <    return 0;
246 <  }
247 <
248 <  sendheader(auth->client, REPORT_DO_ID);
249 <
250 <  /*
251 <   * get the local address of the client and bind to that to
252 <   * make the auth request.  This used to be done only for
253 <   * ifdef VIRTUAL_HOST, but needs to be done for all clients
254 <   * since the ident request must originate from that same address--
255 <   * and machines with multiple IP addresses are common now
256 <   */
257 <  memset(&localaddr, 0, locallen);
258 <  getsockname(auth->client->localClient->fd.fd, (struct sockaddr*)&localaddr,
259 <      &locallen);
260 <
261 < #ifdef IPV6
262 <  remove_ipv6_mapping(&localaddr);
263 <  v6 = (struct sockaddr_in6 *)&localaddr;
264 <  v6->sin6_port = htons(0);
265 < #else
266 <  localaddr.ss_len = locallen;
267 <  v4 = (struct sockaddr_in *)&localaddr;
268 <  v4->sin_port = htons(0);
269 < #endif
270 <  localaddr.ss_port = htons(0);
271 <
272 <  comm_connect_tcp(&auth->fd, auth->client->sockhost, RFC1413_PORT,
273 <      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
274 <      auth, auth->client->localClient->ip.ss.ss_family,
275 <      GlobalSetOptions.ident_timeout);
276 <  return 1; /* We suceed here for now */
277 < }
278 <
279 < /*
280 < * start_auth
281 < *
282 < * inputs       - pointer to client to auth
283 < * output       - NONE
284 < * side effects - starts auth (identd) and dns queries for a client
285 < */
286 < void
287 < start_auth(struct Client *client_p)
288 < {
289 <  struct AuthRequest *auth = NULL;
290 <
291 <  assert(client_p);
292 <
293 <  auth = make_auth_request(client_p);
294 <  SetInAuth(auth);
295 <  dlinkAddTail(auth, &auth->node, &auth_pending_list);
296 <
297 <  sendheader(client_p, REPORT_DO_DNS);
298 <
299 <  SetDNSPending(auth);
300 <
301 <  if (ConfigGeneral.disable_auth == 0)
302 <  {
303 <    SetDoingAuth(auth);
304 <    start_auth_query(auth);
305 <  }
306 <
307 <  gethost_byaddr(auth_dns_callback, auth, &client_p->localClient->ip);
308 < }
309 <
310 < /*
311 < * timeout_auth_queries - timeout resolver and identd requests
312 < * allow clients through if requests failed
313 < */
314 < static void
315 < timeout_auth_queries_event(void *notused)
316 < {
317 <  dlink_node *ptr = NULL, *ptr_next = NULL;
318 <
319 <  DLINK_FOREACH_SAFE(ptr, ptr_next, auth_pending_list.head)
320 <  {
321 <    struct AuthRequest *auth = ptr->data;
322 <
323 <    if (auth->timeout > CurrentTime)
324 <      break;
325 <
326 <    if (IsDoingAuth(auth))
327 <    {
328 <      ++ServerStats.is_abad;
329 <      fd_close(&auth->fd);
330 <      ClearAuth(auth);
331 <      sendheader(auth->client, REPORT_FAIL_ID);
332 <    }
333 <
334 <    if (IsDNSPending(auth))
335 <    {
336 <      delete_resolver_queries(auth);
337 <      ClearDNSPending(auth);
338 <      sendheader(auth->client, REPORT_FAIL_DNS);
339 <    }
340 <
341 <    ilog(LOG_TYPE_IRCD, "DNS/AUTH timeout %s",
342 <         get_client_name(auth->client, SHOW_IP));
343 <    release_auth_client(auth);
344 <  }
345 < }
346 <
347 < /*
348 < * auth_connect_callback() - deal with the result of comm_connect_tcp()
349 < *
350 < * If the connection failed, we simply close the auth fd and report
351 < * a failure. If the connection suceeded send the ident server a query
352 < * giving "theirport , ourport". The write is only attempted *once* so
353 < * it is deemed to be a fail if the entire write doesn't write all the
354 < * data given.  This shouldnt be a problem since the socket should have
355 < * a write buffer far greater than this message to store it in should
356 < * problems arise. -avalon
357 < */
358 < static void
359 < auth_connect_callback(fde_t *fd, int error, void *data)
360 < {
361 <  struct AuthRequest *auth = data;
362 <  struct irc_ssaddr us;
363 <  struct irc_ssaddr them;
364 <  char authbuf[32];
365 <  socklen_t ulen = sizeof(struct irc_ssaddr);
366 <  socklen_t tlen = sizeof(struct irc_ssaddr);
367 <  uint16_t uport, tport;
368 < #ifdef IPV6
369 <  struct sockaddr_in6 *v6;
370 < #else
371 <  struct sockaddr_in *v4;
372 < #endif
373 <
374 <  if (error != COMM_OK)
375 <  {
376 <    auth_error(auth);
377 <    return;
378 <  }
379 <
380 <  if (getsockname(auth->client->localClient->fd.fd, (struct sockaddr *)&us, &ulen) ||
381 <      getpeername(auth->client->localClient->fd.fd, (struct sockaddr *)&them, &tlen))
382 <  {
383 <    ilog(LOG_TYPE_IRCD, "auth get{sock,peer}name error for %s",
384 <         get_client_name(auth->client, SHOW_IP));
385 <    auth_error(auth);
386 <    return;
387 <  }
388 <
389 < #ifdef IPV6
390 <  v6 = (struct sockaddr_in6 *)&us;
391 <  uport = ntohs(v6->sin6_port);
392 <  v6 = (struct sockaddr_in6 *)&them;
393 <  tport = ntohs(v6->sin6_port);
394 <  remove_ipv6_mapping(&us);
395 <  remove_ipv6_mapping(&them);
396 < #else
397 <  v4 = (struct sockaddr_in *)&us;
398 <  uport = ntohs(v4->sin_port);
399 <  v4 = (struct sockaddr_in *)&them;
400 <  tport = ntohs(v4->sin_port);
401 <  us.ss_len = ulen;
402 <  them.ss_len = tlen;
403 < #endif
404 <
405 <  snprintf(authbuf, sizeof(authbuf), "%u, %u\r\n", tport, uport);
406 <
407 <  if (send(fd->fd, authbuf, strlen(authbuf), 0) == -1)
408 <  {
409 <    auth_error(auth);
410 <    return;
411 <  }
231 >  auth_sendheader(auth->client, REPORT_FAIL_ID);
232  
233 <  comm_setselect(fd, COMM_SELECT_READ, read_auth_reply, auth, 0);
233 >  auth_release_client(auth);
234   }
235  
236   /** Enum used to index ident reply fields in a human-readable way. */
# Line 428 | Line 248 | enum IdentReplyFields
248   * \return The userid, or NULL on parse failure.
249   */
250   static const char *
251 < check_ident_reply(char *reply)
251 > auth_check_ident_reply(char *const reply)
252   {
253    char *token = NULL, *end = NULL;
254    char *vector[USERID_TOKEN_COUNT];
255 <  int count = token_vector(reply, ':', vector, USERID_TOKEN_COUNT);
255 >  const unsigned int count = token_vector(reply, ':', vector, USERID_TOKEN_COUNT);
256  
257    if (USERID_TOKEN_COUNT != count)
258      return NULL;
# Line 503 | Line 323 | check_ident_reply(char *reply)
323    return token;
324   }
325  
326 < /*
327 < * read_auth_reply - read the reply (if any) from the ident server
328 < * we connected to.
329 < * We only give it one shot, if the reply isn't good the first time
330 < * fail the authentication entirely. --Bleep
326 > /*! \brief Read the reply (if any) from the ident server we connected to. We
327 > *         only give it one shot, if the reply isn't good the first time fail
328 > *         the authentication entirely. --Bleep
329 > * \param F The socket/fd to read from.
330 > * \param data The request to read.
331   */
332   static void
333 < read_auth_reply(fde_t *fd, void *data)
333 > auth_read_reply(fde_t *F, void *data)
334   {
335 <  struct AuthRequest *auth = data;
335 >  struct AuthRequest *const auth = data;
336    const char *username = NULL;
337    ssize_t len = 0;
338    char buf[RFC1413_BUFSIZ + 1];
339  
340 <  if ((len = recv(fd->fd, buf, RFC1413_BUFSIZ, 0)) > 0)
340 >  assert(auth->fd == F);
341 >
342 >  if ((len = recv(auth->fd->fd, buf, RFC1413_BUFSIZ, 0)) > 0)
343    {
344      buf[len] = '\0';
345 <    username = check_ident_reply(buf);
345 >    username = auth_check_ident_reply(buf);
346    }
347  
348 <  fd_close(fd);
348 >  fd_close(auth->fd);
349 >  auth->fd = NULL;
350  
351    ClearAuth(auth);
352  
353    if (EmptyString(username))
354    {
355 <    sendheader(auth->client, REPORT_FAIL_ID);
355 >    auth_sendheader(auth->client, REPORT_FAIL_ID);
356      ++ServerStats.is_abad;
357    }
358    else
359    {
360      strlcpy(auth->client->username, username, sizeof(auth->client->username));
361 <    sendheader(auth->client, REPORT_FIN_ID);
361 >    auth_sendheader(auth->client, REPORT_FIN_ID);
362      ++ServerStats.is_asuc;
363 <    SetGotId(auth->client);
363 >    AddFlag(auth->client, FLAGS_GOTID);
364 >  }
365 >
366 >  auth_release_client(auth);
367 > }
368 >
369 > /*
370 > * auth_connect_callback() - deal with the result of comm_connect_tcp()
371 > *
372 > * If the connection failed, we simply close the auth fd and report
373 > * a failure. If the connection suceeded send the ident server a query
374 > * giving "theirport , ourport". The write is only attempted *once* so
375 > * it is deemed to be a fail if the entire write doesn't write all the
376 > * data given.  This shouldnt be a problem since the socket should have
377 > * a write buffer far greater than this message to store it in should
378 > * problems arise. -avalon
379 > */
380 > static void
381 > auth_connect_callback(fde_t *F, int error, void *data)
382 > {
383 >  struct AuthRequest *const auth = data;
384 >  struct irc_ssaddr us;
385 >  struct irc_ssaddr them;
386 >  char authbuf[16];
387 >  ssize_t len = 0;
388 >  socklen_t ulen = sizeof(struct irc_ssaddr);
389 >  socklen_t tlen = sizeof(struct irc_ssaddr);
390 >  uint16_t uport, tport;
391 >  struct sockaddr_in6 *v6;
392 >
393 >  if (error != COMM_OK)
394 >  {
395 >    auth_error(auth);
396 >    return;
397 >  }
398 >
399 >  assert(auth->fd == F);
400 >
401 >  if (getsockname(auth->client->connection->fd->fd, (struct sockaddr *)&us, &ulen) ||
402 >      getpeername(auth->client->connection->fd->fd, (struct sockaddr *)&them, &tlen))
403 >  {
404 >    report_error(L_ALL, "auth get{sock,peer}name error %s:%s",
405 >                 client_get_name(auth->client, SHOW_IP), errno);
406 >    auth_error(auth);
407 >    return;
408 >  }
409 >
410 >  v6 = (struct sockaddr_in6 *)&us;
411 >  uport = ntohs(v6->sin6_port);
412 >  v6 = (struct sockaddr_in6 *)&them;
413 >  tport = ntohs(v6->sin6_port);
414 >
415 >  len = snprintf(authbuf, sizeof(authbuf), "%u, %u\r\n", tport, uport);
416 >
417 >  if (send(F->fd, authbuf, len, 0) != len)
418 >  {
419 >    auth_error(auth);
420 >    return;
421 >  }
422 >
423 >  comm_setselect(F, COMM_SELECT_READ, auth_read_reply, auth, 0);
424 > }
425 >
426 > /*! \brief Flag the client to show an attempt to contact the ident server on
427 > *         the client's host. Should the connect or any later phase of the
428 > *         identifying process fail, it is aborted and the user is given a
429 > *         username of "unknown".
430 > * \param auth The request for which to start the ident lookup.
431 > */
432 > static void
433 > auth_start_query(struct AuthRequest *auth)
434 > {
435 >  struct irc_ssaddr localaddr;
436 >  socklen_t locallen = sizeof(struct irc_ssaddr);
437 >  struct sockaddr_in6 *v6;
438 >
439 >  /* Open a socket of the same type as the client socket */
440 >  int fd = comm_socket(auth->client->connection->ip.ss.ss_family, SOCK_STREAM, 0);
441 >  if (fd == -1)
442 >  {
443 >    report_error(L_ALL, "creating auth stream socket %s:%s",
444 >                 client_get_name(auth->client, SHOW_IP), errno);
445 >    ++ServerStats.is_abad;
446 >    return;
447    }
448  
449 <  release_auth_client(auth);
449 >  auth->fd = fd_open(fd, 1, "ident");
450 >
451 >  SetDoingAuth(auth);
452 >  auth_sendheader(auth->client, REPORT_DO_ID);
453 >
454 >  /*
455 >   * Get the local address of the client and bind to that to
456 >   * make the auth request.
457 >   */
458 >  memset(&localaddr, 0, locallen);
459 >  getsockname(auth->client->connection->fd->fd, (struct sockaddr *)&localaddr, &locallen);
460 >
461 >  remove_ipv6_mapping(&localaddr);
462 >  v6 = (struct sockaddr_in6 *)&localaddr;
463 >  v6->sin6_port = htons(0);
464 >  localaddr.ss_port = htons(0);
465 >
466 >  comm_connect_tcp(auth->fd, auth->client->sockhost, RFC1413_PORT,
467 >      (struct sockaddr *)&localaddr, localaddr.ss_len, auth_connect_callback,
468 >      auth, auth->client->connection->ip.ss.ss_family,
469 >      GlobalSetOptions.ident_timeout);
470 > }
471 >
472 > /*
473 > * auth_start
474 > *
475 > * inputs       - pointer to client to auth
476 > * output       - NONE
477 > * side effects - starts auth (identd) and dns queries for a client
478 > */
479 > void
480 > auth_start(struct Client *client_p)
481 > {
482 >  struct AuthRequest *auth = auth_make(client_p);
483 >
484 >  dlinkAddTail(auth, &auth->node, &auth_list);
485 >
486 >  auth_sendheader(client_p, REPORT_DO_DNS);
487 >
488 >  SetDNSPending(auth);
489 >
490 >  if (ConfigGeneral.disable_auth == 0)
491 >    auth_start_query(auth);
492 >
493 >  gethost_byaddr(auth_dns_callback, auth, &client_p->connection->ip);
494   }
495  
496   /*
497 < * delete_auth()
497 > * auth_delete()
498   */
499   void
500 < delete_auth(struct AuthRequest *auth)
500 > auth_delete(struct AuthRequest *auth)
501   {
502 +  if (IsDoingAuth(auth))
503 +  {
504 +    fd_close(auth->fd);
505 +    auth->fd = NULL;
506 +
507 +    ClearAuth(auth);
508 +  }
509 +
510    if (IsDNSPending(auth))
511 +  {
512      delete_resolver_queries(auth);
513 +    ClearDNSPending(auth);
514 +  }
515  
516 <  if (IsDoingAuth(auth))
517 <    fd_close(&auth->fd);
516 >  assert(dlinkFind(&auth_list, auth));
517 >  dlinkDelete(&auth->node, &auth_list);
518 >  mp_pool_release(auth);
519 > }
520  
521 <  if (IsInAuth(auth))
521 > /*
522 > * auth_timeout_queries - timeout resolver and identd requests
523 > * allow clients through if requests failed
524 > */
525 > static void
526 > auth_timeout_queries(void *notused)
527 > {
528 >  dlink_node *node, *node_next;
529 >
530 >  DLINK_FOREACH_SAFE(node, node_next, auth_list.head)
531    {
532 <    dlinkDelete(&auth->node, &auth_pending_list);
533 <    ClearInAuth(auth);
532 >    struct AuthRequest *auth = node->data;
533 >
534 >    if (auth->timeout > CurrentTime)
535 >      break;
536 >
537 >    if (IsDoingAuth(auth))
538 >    {
539 >      ++ServerStats.is_abad;
540 >
541 >      fd_close(auth->fd);
542 >      auth->fd = NULL;
543 >
544 >      ClearAuth(auth);
545 >
546 >      auth_sendheader(auth->client, REPORT_FAIL_ID);
547 >    }
548 >
549 >    if (IsDNSPending(auth))
550 >    {
551 >      delete_resolver_queries(auth);
552 >      ClearDNSPending(auth);
553 >
554 >      auth_sendheader(auth->client, REPORT_FAIL_DNS);
555 >    }
556 >
557 >    auth_release_client(auth);
558    }
559   }
560  
# Line 571 | Line 567 | auth_init(void)
567   {
568    static struct event timeout_auth_queries =
569    {
570 <    .name = "timeout_auth_queries_event",
571 <    .handler = timeout_auth_queries_event,
570 >    .name = "auth_timeout_queries",
571 >    .handler = auth_timeout_queries,
572      .when = 1
573    };
574  
575 +  auth_pool = mp_pool_new(sizeof(struct AuthRequest), MP_CHUNK_SIZE_AUTH);
576    event_add(&timeout_auth_queries, NULL);
577   }

Comparing ircd-hybrid/trunk/src/auth.c (property svn:keywords):
Revision 4340 by michael, Sat Aug 2 16:53:22 2014 UTC vs.
Revision 8361 by michael, Sun Mar 4 14:22:42 2018 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

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