2a00dd1a781c46a4e180fd54da9de05de54266ed
[ircu2.10.12-pk.git] / ircd / s_auth.c
1 /************************************************************************
2  *   IRC - Internet Relay Chat, src/s_auth.c
3  *   Copyright (C) 1992 Darren Reed
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 1, or (at your option)
8  *   any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * Changes:
20  *   July 6, 1999 - Rewrote most of the code here. When a client connects
21  *     to the server and passes initial socket validation checks, it
22  *     is owned by this module (auth) which returns it to the rest of the
23  *     server when dns and auth queries are finished. Until the client is
24  *     released, the server does not know it exists and does not process
25  *     any messages from it.
26  *     --Bleep  Thomas Helvey <tomh@inxpress.net>
27  *
28  *  December 26, 2005 - Rewrite the flag handling and integrate that with
29  *     an IRCnet-style IAuth protocol.
30  *     -- Michael Poole
31  */
32 /** @file
33  * @brief Implementation of DNS and ident lookups.
34  * @version $Id$
35  */
36 #include "config.h"
37
38 #include "s_auth.h"
39 #include "class.h"
40 #include "client.h"
41 #include "IPcheck.h"
42 #include "ircd.h"
43 #include "ircd_alloc.h"
44 #include "ircd_chattr.h"
45 #include "ircd_events.h"
46 #include "ircd_features.h"
47 #include "ircd_log.h"
48 #include "ircd_osdep.h"
49 #include "ircd_reply.h"
50 #include "ircd_snprintf.h"
51 #include "ircd_string.h"
52 #include "list.h"
53 #include "msg.h"        /* for MAXPARA */
54 #include "numeric.h"
55 #include "numnicks.h"
56 #include "querycmds.h"
57 #include "random.h"
58 #include "res.h"
59 #include "s_bsd.h"
60 #include "s_conf.h"
61 #include "s_debug.h"
62 #include "s_misc.h"
63 #include "s_user.h"
64 #include "send.h"
65
66 #include <errno.h>
67 #include <string.h>
68 #include <stdlib.h>
69 #include <unistd.h>
70 #include <fcntl.h>
71 #include <sys/socket.h>
72 #include <sys/ioctl.h>
73
74 /** Pending operations during registration. */
75 enum AuthRequestFlag {
76     AR_AUTH_PENDING,    /**< ident connecting or waiting for response */
77     AR_DNS_PENDING,     /**< dns request sent, waiting for response */
78     AR_CAP_PENDING,     /**< in middle of CAP negotiations */
79     AR_NEEDS_PONG,      /**< user has not PONGed */
80     AR_NEEDS_USER,      /**< user must send USER command */
81     AR_NEEDS_NICK,      /**< user must send NICK command */
82     AR_LAST_SCAN = AR_NEEDS_NICK, /**< maximum flag to scan through */
83     AR_IAUTH_PENDING,   /**< iauth request sent, waiting for response */
84     AR_IAUTH_HURRY,     /**< we told iauth to hurry up */
85     AR_IAUTH_USERNAME,  /**< iauth sent a username (preferred or forced) */
86     AR_IAUTH_FUSERNAME, /**< iauth sent a forced username */
87     AR_PASSWORD_CHECKED, /**< client password already checked */
88     AR_NUM_FLAGS
89 };
90
91 DECLARE_FLAGSET(AuthRequestFlags, AR_NUM_FLAGS);
92
93 /** Stores registration state of a client. */
94 struct AuthRequest {
95   struct AuthRequest* next;       /**< linked list node ptr */
96   struct AuthRequest* prev;       /**< linked list node ptr */
97   struct Client*      client;     /**< pointer to client struct for request */
98   struct irc_sockaddr local;      /**< local endpoint address */
99   struct irc_in_addr  original;   /**< original client IP address */
100   struct Socket       socket;     /**< socket descriptor for auth queries */
101   struct Timer        timeout;    /**< timeout timer for ident and dns queries */
102   struct AuthRequestFlags flags;  /**< current state of request */
103   unsigned int        cookie;     /**< cookie the user must PONG */
104   unsigned short      port;       /**< client's remote port number */
105 };
106
107 /** Array of message text (with length) pairs for AUTH status
108  * messages.  Indexed using #ReportType.
109  */
110 static struct {
111   const char*  message;
112   unsigned int length;
113 } HeaderMessages [] = {
114 #define MSG(STR) { STR, sizeof(STR) - 1 }
115   MSG("NOTICE AUTH :*** Looking up your hostname\r\n"),
116   MSG("NOTICE AUTH :*** Found your hostname\r\n"),
117   MSG("NOTICE AUTH :*** Couldn't look up your hostname\r\n"),
118   MSG("NOTICE AUTH :*** Checking Ident\r\n"),
119   MSG("NOTICE AUTH :*** Got ident response\r\n"),
120   MSG("NOTICE AUTH :*** No ident response\r\n"),
121   MSG("NOTICE AUTH :*** \r\n"),
122   MSG("NOTICE AUTH :*** Your forward and reverse DNS do not match, "
123     "ignoring hostname.\r\n"),
124   MSG("NOTICE AUTH :*** Invalid hostname\r\n")
125 #undef MSG
126 };
127
128 /** Enum used to index messages in the HeaderMessages[] array. */
129 typedef enum {
130   REPORT_DO_DNS,
131   REPORT_FIN_DNS,
132   REPORT_FAIL_DNS,
133   REPORT_DO_ID,
134   REPORT_FIN_ID,
135   REPORT_FAIL_ID,
136   REPORT_FAIL_IAUTH,
137   REPORT_IP_MISMATCH,
138   REPORT_INVAL_DNS
139 } ReportType;
140
141 /** Sends response \a r (from #ReportType) to client \a c. */
142 #define sendheader(c, r) \
143    send(cli_fd(c), HeaderMessages[(r)].message, HeaderMessages[(r)].length, 0)
144
145 /** Enumeration of IAuth connection flags. */
146 enum IAuthFlag
147 {
148   IAUTH_BLOCKED,                        /**< socket buffer full */
149   IAUTH_CLOSING,                        /**< candidate to be disposed */
150   /* The following flags are controlled by iauth's "O" options command. */
151   IAUTH_ADDLINFO,                       /**< Send additional info
152                                          * (password and username). */
153   IAUTH_FIRST_OPTION = IAUTH_ADDLINFO,  /**< First flag that is a policy option. */
154   IAUTH_REQUIRED,                       /**< IAuth completion required for registration. */
155   IAUTH_TIMEOUT,                        /**< Refuse new connections if IAuth is behind. */
156   IAUTH_EXTRAWAIT,                      /**< Give IAuth extra time to answer. */
157   IAUTH_UNDERNET,                       /**< Enable Undernet extensions. */
158   IAUTH_LAST_FLAG                       /**< total number of flags */
159 };
160 /** Declare a bitset structure indexed by IAuthFlag. */
161 DECLARE_FLAGSET(IAuthFlags, IAUTH_LAST_FLAG);
162
163 /** Describes state of an IAuth connection. */
164 struct IAuth {
165   struct MsgQ i_sendQ;                  /**< messages queued to send */
166   struct Socket i_socket;               /**< main socket to iauth */
167   struct Socket i_stderr;               /**< error socket for iauth */
168   struct IAuthFlags i_flags;            /**< connection state/status/flags */
169   uint64_t i_recvB;                     /**< bytes received */
170   uint64_t i_sendB;                     /**< bytes sent */
171   time_t started;                       /**< time that this instance was started */
172   unsigned int i_recvM;                 /**< messages received */
173   unsigned int i_sendM;                 /**< messages sent */
174   unsigned int i_count;                 /**< characters used in i_buffer */
175   unsigned int i_errcount;              /**< characters used in i_errbuf */
176   int i_debug;                          /**< debug level */
177   char i_buffer[BUFSIZE+1];             /**< partial unprocessed line from server */
178   char i_errbuf[BUFSIZE+1];             /**< partial unprocessed error line */
179   char *i_version;                      /**< iauth version string */
180   struct SLink *i_config;               /**< configuration string list */
181   struct SLink *i_stats;                /**< statistics string list */
182   char **i_argv;                        /**< argument list */
183 };
184
185 /** Return whether flag \a flag is set on \a iauth. */
186 #define IAuthHas(iauth, flag) ((iauth) && FlagHas(&(iauth)->i_flags, flag))
187 /** Set flag \a flag on \a iauth. */
188 #define IAuthSet(iauth, flag) FlagSet(&(iauth)->i_flags, flag)
189 /** Clear flag \a flag from \a iauth. */
190 #define IAuthClr(iauth, flag) FlagClr(&(iauth)->i_flags, flag)
191 /** Get connected flag for \a iauth. */
192 #define i_GetConnected(iauth) ((iauth) && s_fd(i_socket(iauth)) > -1)
193
194 /** Return socket event generator for \a iauth. */
195 #define i_socket(iauth) (&(iauth)->i_socket)
196 /** Return stderr socket for \a iauth. */
197 #define i_stderr(iauth) (&(iauth)->i_stderr)
198 /** Return outbound message queue for \a iauth. */
199 #define i_sendQ(iauth) (&(iauth)->i_sendQ)
200 /** Return debug level for \a iauth. */
201 #define i_debug(iauth) ((iauth)->i_debug)
202
203 /** Active instance of IAuth. */
204 static struct IAuth *iauth;
205 /** Freelist of AuthRequest structures. */
206 static struct AuthRequest *auth_freelist;
207
208 static void iauth_sock_callback(struct Event *ev);
209 static void iauth_stderr_callback(struct Event *ev);
210 static int sendto_iauth(struct Client *cptr, const char *format, ...);
211 static int preregister_user(struct Client *cptr);
212 typedef int (*iauth_cmd_handler)(struct IAuth *iauth, struct Client *cli,
213                                  int parc, char **params);
214
215 /** Set username for user associated with \a auth.
216  * @param[in] auth Client authorization request to work on.
217  * @return Zero if client is kept, CPTR_KILLED if client rejected.
218  */
219 static int auth_set_username(struct AuthRequest *auth)
220 {
221   struct Client *sptr = auth->client;
222   struct User   *user = cli_user(sptr);
223   char *d;
224   char *s;
225   int   rlen = USERLEN;
226   int   killreason;
227   short upper = 0;
228   short lower = 0;
229   short pos = 0;
230   short leadcaps = 0;
231   short other = 0;
232   short digits = 0;
233   short digitgroups = 0;
234   char  ch;
235   char  last;
236
237   if (FlagHas(&auth->flags, AR_IAUTH_USERNAME))
238   {
239       ircd_strncpy(cli_user(sptr)->username, cli_username(sptr), USERLEN);
240   }
241   else
242   {
243     /* Copy username from source to destination.  Since they may be the
244      * same, and we may prefix with a '~', use a buffer character (ch)
245      * to hold the next character to copy.
246      */
247     s = IsIdented(sptr) ? cli_username(sptr) : user->username;
248     last = *s++;
249     d = user->username;
250     if (HasFlag(sptr, FLAG_DOID) && !IsIdented(sptr))
251     {
252       *d++ = '~';
253       --rlen;
254     }
255     while (last && !IsCntrl(last) && rlen--)
256     {
257       ch = *s++;
258       *d++ = IsUserChar(last) ? last : '_';
259       last = (ch != '~') ? ch : '_';
260     }
261     *d = 0;
262   }
263
264   /* If username is empty or just ~, reject. */
265   if ((user->username[0] == '\0')
266       || ((user->username[0] == '~') && (user->username[1] == '\0')))
267     return exit_client(sptr, sptr, &me, "USER: Bogus userid.");
268
269   /* Check for K- or G-line. */
270   killreason = find_kill(sptr);
271   if (killreason) {
272     ServerStats->is_ref++;
273     return exit_client(sptr, sptr, &me,
274                        (killreason == -1 ? "K-lined" : "G-lined"));
275   }
276
277   if (!FlagHas(&auth->flags, AR_IAUTH_FUSERNAME))
278   {
279     /* Check for mixed case usernames, meaning probably hacked.  Jon2 3-94
280      * Explanations of rules moved to where it is checked     Entrope 2-06
281      */
282     s = d = user->username + (user->username[0] == '~');
283     for (last = '\0';
284          (ch = *d++) != '\0';
285          pos++, last = ch)
286     {
287       if (IsLower(ch))
288       {
289         lower++;
290       }
291       else if (IsUpper(ch))
292       {
293         upper++;
294         /* Accept caps as leading if we haven't seen lower case or digits yet. */
295         if ((leadcaps || pos == 0) && !lower && !digits)
296           leadcaps++;
297       }
298       else if (IsDigit(ch))
299       {
300         digits++;
301         if (pos == 0 || !IsDigit(last))
302         {
303           digitgroups++;
304           /* If more than two groups of digits, reject. */
305           if (digitgroups > 2)
306             goto badid;
307         }
308       }
309       else if (ch == '-' || ch == '_' || ch == '.')
310       {
311         other++;
312         /* If -_. exist at start, consecutively, or more than twice, reject. */
313         if (pos == 0 || last == '-' || last == '_' || last == '.' || other > 2)
314           goto badid;
315       }
316       else /* All other punctuation is rejected. */
317         goto badid;
318     }
319
320     /* If mixed case, first must be capital, but no more than three;
321      * but if three capitals, they must all be leading. */
322     if (lower && upper && (!leadcaps || leadcaps > 3 ||
323                            (upper > 2 && upper > leadcaps)))
324       goto badid;
325     /* If two different groups of digits, one must be either at the
326      * start or end. */
327     if (digitgroups == 2 && !(IsDigit(s[0]) || IsDigit(ch)))
328       goto badid;
329     /* Must have at least one letter. */
330     if (!lower && !upper)
331       goto badid;
332     /* Final character must not be punctuation. */
333     if (!IsAlnum(last))
334       goto badid;
335   }
336
337   return 0;
338
339 badid:
340   /* If we confirmed their username, and it is what they claimed,
341    * accept it. */
342   if (IsIdented(sptr) && !strcmp(cli_username(sptr), user->username))
343     return 0;
344
345   ServerStats->is_ref++;
346   send_reply(sptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
347              ":Your username is invalid.");
348   send_reply(sptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
349              ":Connect with your real username, in lowercase.");
350   send_reply(sptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
351              ":If your mail address were foo@bar.com, your username "
352              "would be foo.");
353   return exit_client(sptr, sptr, &me, "USER: Bad username");
354 }
355
356 /** Check whether an authorization request is complete.
357  * This means that no flags from 0 to #AR_LAST_SCAN are set on \a auth.
358  * If #AR_IAUTH_PENDING is set, optionally go into "hurry" state.  If
359  * 0 through #AR_LAST_SCAN and #AR_IAUTH_PENDING are all clear,
360  * destroy \a auth, clear the password, set the username, and register
361  * the client.
362  * @param[in] auth Authorization request to check.
363  * @return Zero if client is kept, CPTR_KILLED if client rejected.
364  */
365 static int check_auth_finished(struct AuthRequest *auth)
366 {
367   enum AuthRequestFlag flag;
368   int res;
369
370   /* Check non-iauth registration blocking flags. */
371   for (flag = 0; flag <= AR_LAST_SCAN; ++flag)
372     if (FlagHas(&auth->flags, flag))
373     {
374       Debug((DEBUG_INFO, "Auth %p [%d] still has flag %d", auth,
375              cli_fd(auth->client), flag));
376       return 0;
377     }
378
379   /* If appropriate, do preliminary assignment to connection class. */
380   if (IsUserPort(auth->client)
381       && !FlagHas(&auth->flags, AR_IAUTH_HURRY)
382       && preregister_user(auth->client))
383     return CPTR_KILLED;
384
385   /* If we have not done so, check client password.  Do this as soon
386    * as possible so that iauth's challenge/response (which uses PASS
387    * for responses) is not confused with the client's password.
388    */
389   if (IsUserPort(auth->client)
390       && !FlagHas(&auth->flags, AR_PASSWORD_CHECKED))
391   {
392     struct ConfItem *aconf;
393
394     aconf = cli_confs(auth->client)->value.aconf;
395     if (aconf
396         && !EmptyString(aconf->passwd)
397         && strcmp(cli_passwd(auth->client), aconf->passwd))
398     {
399       ServerStats->is_ref++;
400       send_reply(auth->client, ERR_PASSWDMISMATCH);
401       return exit_client(auth->client, auth->client, &me, "Bad Password");
402     }
403     FlagSet(&auth->flags, AR_PASSWORD_CHECKED);
404   }
405
406   /* Check if iauth is done. */
407   if (FlagHas(&auth->flags, AR_IAUTH_PENDING))
408   {
409     /* Switch auth request to hurry-up state. */
410     if (!FlagHas(&auth->flags, AR_IAUTH_HURRY))
411     {
412       /* Set "hurry" flag in auth request. */
413       FlagSet(&auth->flags, AR_IAUTH_HURRY);
414
415       /* If iauth wants it, send notification. */
416       if (IAuthHas(iauth, IAUTH_UNDERNET))
417         sendto_iauth(auth->client, "H %s", get_client_class(auth->client));
418
419       /* If iauth wants it, give client more time. */
420       if (IAuthHas(iauth, IAUTH_EXTRAWAIT))
421         cli_firsttime(auth->client) = CurrentTime;
422     }
423
424     Debug((DEBUG_INFO, "Auth %p [%d] still has flag %d", auth,
425            cli_fd(auth->client), AR_IAUTH_PENDING));
426     return 0;
427   }
428   else
429     FlagSet(&auth->flags, AR_IAUTH_HURRY);
430
431   if (IsUserPort(auth->client))
432   {
433     memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
434     res = auth_set_username(auth);
435     if (res == 0)
436       res = register_user(auth->client, auth->client);
437   }
438   else
439     res = 0;
440   if (res == 0)
441     destroy_auth_request(auth);
442   return res;
443 }
444
445 /** Verify that a hostname is valid, i.e., only contains characters
446  * valid for a hostname and that a hostname is not too long.
447  * @param host Hostname to check.
448  * @param maxlen Maximum length of hostname, not including NUL terminator.
449  * @return Non-zero if the hostname is valid.
450  */
451 static int
452 auth_verify_hostname(const char *host, int maxlen)
453 {
454   int i;
455
456   /* Walk through the host name */
457   for (i = 0; host[i]; i++)
458     /* If it's not a hostname character or if it's too long, return false */
459     if (!IsHostChar(host[i]) || i >= maxlen)
460       return 0;
461
462   return 1; /* it's a valid hostname */
463 }
464
465 /** Check whether a client already has a CONF_CLIENT configuration
466  * item.
467  *
468  * @return A pointer to the client's first CONF_CLIENT, or NULL if
469  *   there are none.
470  */
471 static struct ConfItem *find_conf_client(struct Client *cptr)
472 {
473   struct SLink *list;
474
475   for (list = cli_confs(cptr); list != NULL; list = list->next) {
476     struct ConfItem *aconf;
477     aconf = list->value.aconf;
478     if (aconf->status & CONF_CLIENT)
479       return aconf;
480   }
481
482   return NULL;
483 }
484
485 /** Assign a client to a connection class.
486  * @param[in] cptr Client to assign to a class.
487  * @return Zero if client is kept, CPTR_KILLED if rejected.
488  */
489 static int preregister_user(struct Client *cptr)
490 {
491   static time_t last_too_many1;
492   static time_t last_too_many2;
493
494   ircd_strncpy(cli_user(cptr)->host, cli_sockhost(cptr), HOSTLEN);
495   ircd_strncpy(cli_user(cptr)->realhost, cli_sockhost(cptr), HOSTLEN);
496
497   if (find_conf_client(cptr)) {
498     return 0;
499   }
500
501   switch (conf_check_client(cptr))
502   {
503   case ACR_OK:
504     break;
505   case ACR_NO_AUTHORIZATION:
506     sendto_opmask_butone(0, SNO_UNAUTH, "Unauthorized connection from %s.",
507                          get_client_name(cptr, HIDE_IP));
508     ++ServerStats->is_ref;
509     return exit_client(cptr, cptr, &me,
510                        "No Authorization - use another server");
511   case ACR_TOO_MANY_IN_CLASS:
512     sendto_opmask_butone_ratelimited(0, SNO_TOOMANY, &last_too_many1,
513                                      "Too many connections in class %s for %s.",
514                                      get_client_class(cptr),
515                                      get_client_name(cptr, SHOW_IP));
516     ++ServerStats->is_ref;
517     return exit_client(cptr, cptr, &me,
518                        "Sorry, your connection class is full - try "
519                        "again later or try another server");
520   case ACR_TOO_MANY_FROM_IP:
521     sendto_opmask_butone_ratelimited(0, SNO_TOOMANY, &last_too_many2,
522                                      "Too many connections from same IP for %s.",
523                                      get_client_name(cptr, SHOW_IP));
524     ++ServerStats->is_ref;
525     return exit_client(cptr, cptr, &me,
526                        "Too many connections from your host");
527   case ACR_ALREADY_AUTHORIZED:
528     /* Can this ever happen? */
529   case ACR_BAD_SOCKET:
530     ++ServerStats->is_ref;
531     IPcheck_connect_fail(cptr);
532     return exit_client(cptr, cptr, &me, "Unknown error -- Try again");
533   }
534   return 0;
535 }
536
537 /** Send the ident server a query giving "theirport , ourport". The
538  * write is only attempted *once* so it is deemed to be a fail if the
539  * entire write doesn't write all the data given.  This shouldn't be a
540  * problem since the socket should have a write buffer far greater
541  * than this message to store it in should problems arise. -avalon
542  * @param[in] auth The request to send.
543  */
544 static void send_auth_query(struct AuthRequest* auth)
545 {
546   char               authbuf[32];
547   unsigned int       count;
548
549   assert(0 != auth);
550
551   ircd_snprintf(0, authbuf, sizeof(authbuf), "%hu , %hu\r\n",
552                 auth->port, auth->local.port);
553
554   if (IO_SUCCESS != os_send_nonb(s_fd(&auth->socket), authbuf, strlen(authbuf), &count)) {
555     close(s_fd(&auth->socket));
556     socket_del(&auth->socket);
557     s_fd(&auth->socket) = -1;
558     ++ServerStats->is_abad;
559     if (IsUserPort(auth->client))
560       sendheader(auth->client, REPORT_FAIL_ID);
561     FlagClr(&auth->flags, AR_AUTH_PENDING);
562     check_auth_finished(auth);
563   }
564 }
565
566 /** Enum used to index ident reply fields in a human-readable way. */
567 enum IdentReplyFields {
568   IDENT_PORT_NUMBERS,
569   IDENT_REPLY_TYPE,
570   IDENT_OS_TYPE,
571   IDENT_INFO,
572   USERID_TOKEN_COUNT
573 };
574
575 /** Parse an ident reply line and extract the userid from it.
576  * @param[in] reply The ident reply line.
577  * @return The userid, or NULL on parse failure.
578  */
579 static char* check_ident_reply(char* reply)
580 {
581   char* token;
582   char* end;
583   char* vector[USERID_TOKEN_COUNT];
584   int count = token_vector(reply, ':', vector, USERID_TOKEN_COUNT);
585
586   if (USERID_TOKEN_COUNT != count)
587     return 0;
588   /*
589    * second token is the reply type
590    */
591   token = vector[IDENT_REPLY_TYPE];
592   if (EmptyString(token))
593     return 0;
594
595   while (IsSpace(*token))
596     ++token;
597
598   if (0 != strncmp(token, "USERID", 6))
599     return 0;
600
601   /*
602    * third token is the os type
603    */
604   token = vector[IDENT_OS_TYPE];
605   if (EmptyString(token))
606     return 0;
607   while (IsSpace(*token))
608    ++token;
609
610   /*
611    * Unless "OTHER" is specified as the operating system
612    * type, the server is expected to return the "normal"
613    * user identification of the owner of this connection.
614    * "Normal" in this context may be taken to mean a string
615    * of characters which uniquely identifies the connection
616    * owner such as a user identifier assigned by the system
617    * administrator and used by such user as a mail
618    * identifier, or as the "user" part of a user/password
619    * pair used to gain access to system resources.  When an
620    * operating system is specified (e.g., anything but
621    * "OTHER"), the user identifier is expected to be in a
622    * more or less immediately useful form - e.g., something
623    * that could be used as an argument to "finger" or as a
624    * mail address.
625    */
626   if (0 == strncmp(token, "OTHER", 5))
627     return 0;
628   /*
629    * fourth token is the username
630    */
631   token = vector[IDENT_INFO];
632   if (EmptyString(token))
633     return 0;
634   while (IsSpace(*token))
635     ++token;
636   /*
637    * look for the end of the username, terminators are '\0, @, <SPACE>, :'
638    */
639   for (end = token; *end; ++end) {
640     if (IsSpace(*end) || '@' == *end || ':' == *end)
641       break;
642   }
643   *end = '\0';
644   return token;
645 }
646
647 /** Read the reply (if any) from the ident server we connected to.  We
648  * only give it one shot, if the reply isn't good the first time fail
649  * the authentication entirely. --Bleep
650  * @param[in] auth The request to read.
651  */
652 static void read_auth_reply(struct AuthRequest* auth)
653 {
654   char*        username = 0;
655   unsigned int len;
656   /*
657    * rfc1453 sez we MUST accept 512 bytes
658    */
659   char   buf[BUFSIZE + 1];
660
661   assert(0 != auth);
662   assert(0 != auth->client);
663   assert(auth == cli_auth(auth->client));
664
665   if (IO_SUCCESS == os_recv_nonb(s_fd(&auth->socket), buf, BUFSIZE, &len)) {
666     buf[len] = '\0';
667     Debug((DEBUG_INFO, "Auth %p [%d] reply: %s", auth, cli_fd(auth->client), buf));
668     username = check_ident_reply(buf);
669     Debug((DEBUG_INFO, "Username: %s", username));
670   }
671
672   Debug((DEBUG_INFO, "Deleting auth [%d] socket %p", auth, cli_fd(auth->client)));
673   close(s_fd(&auth->socket));
674   socket_del(&auth->socket);
675   s_fd(&auth->socket) = -1;
676
677   if (EmptyString(username)) {
678     if (IsUserPort(auth->client))
679       sendheader(auth->client, REPORT_FAIL_ID);
680     ++ServerStats->is_abad;
681   } else {
682     if (IsUserPort(auth->client))
683       sendheader(auth->client, REPORT_FIN_ID);
684     ++ServerStats->is_asuc;
685     if (!FlagHas(&auth->flags, AR_IAUTH_USERNAME)) {
686       ircd_strncpy(cli_username(auth->client), username, USERLEN);
687       SetGotId(auth->client);
688     }
689     if (IAuthHas(iauth, IAUTH_UNDERNET))
690       sendto_iauth(auth->client, "u %s", username);
691   }
692
693   FlagClr(&auth->flags, AR_AUTH_PENDING);
694   check_auth_finished(auth);
695 }
696
697 /** Handle socket I/O activity.
698  * @param[in] ev A socket event whos associated data is the active
699  *   struct AuthRequest.
700  */
701 static void auth_sock_callback(struct Event* ev)
702 {
703   struct AuthRequest* auth;
704
705   assert(0 != ev_socket(ev));
706   assert(0 != s_data(ev_socket(ev)));
707
708   auth = (struct AuthRequest*) s_data(ev_socket(ev));
709
710   switch (ev_type(ev)) {
711   case ET_DESTROY: /* being destroyed */
712     break;
713
714   case ET_CONNECT: /* socket connection completed */
715     Debug((DEBUG_INFO, "Connection completed for auth %p [%d]; sending query",
716            auth, cli_fd(auth->client)));
717     socket_state(&auth->socket, SS_CONNECTED);
718     send_auth_query(auth);
719     break;
720
721   case ET_READ: /* socket is readable */
722   case ET_EOF: /* end of file on socket */
723   case ET_ERROR: /* error on socket */
724     Debug((DEBUG_INFO, "Auth socket %p [%p] readable", auth, ev_socket(ev)));
725     read_auth_reply(auth);
726     break;
727
728   default:
729     assert(0 && "Unrecognized event in auth_socket_callback().");
730     break;
731   }
732 }
733
734 /** Stop an auth request completely.
735  * @param[in] auth The struct AuthRequest to cancel.
736  */
737 void destroy_auth_request(struct AuthRequest* auth)
738 {
739   Debug((DEBUG_INFO, "Deleting auth request for %p", auth->client));
740
741   if (FlagHas(&auth->flags, AR_DNS_PENDING)) {
742     delete_resolver_queries(auth);
743   }
744
745   if (-1 < s_fd(&auth->socket)) {
746     close(s_fd(&auth->socket));
747     socket_del(&auth->socket);
748     s_fd(&auth->socket) = -1;
749   }
750
751   if (t_active(&auth->timeout))
752     timer_del(&auth->timeout);
753
754   cli_auth(auth->client) = NULL;
755   auth->next = auth_freelist;
756   auth_freelist = auth;
757 }
758
759 /** Handle a 'ping' (authorization) timeout for a client.
760  * @param[in] cptr The client whose session authorization has timed out.
761  * @return Zero if client is kept, CPTR_KILLED if client rejected.
762  */
763 int auth_ping_timeout(struct Client *cptr)
764 {
765   struct AuthRequest *auth;
766   enum AuthRequestFlag flag;
767
768   auth = cli_auth(cptr);
769
770   /* Check whether the auth request is gone (more likely, it never
771    * existed, as in an outbound server connection). */
772   if (!auth)
773       return exit_client_msg(cptr, cptr, &me, "Registration Timeout");
774
775   /* Check for a user-controlled timeout. */
776   for (flag = 0; flag <= AR_LAST_SCAN; ++flag) {
777     if (FlagHas(&auth->flags, flag)) {
778       /* Display message if they have sent a NICK and a USER but no
779        * nospoof PONG.
780        */
781       if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username) {
782         send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
783                    ":Your client may not be compatible with this server.");
784         send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
785                    ":Compatible clients are available at %s",
786                    feature_str(FEAT_URL_CLIENTS));
787       }
788       return exit_client_msg(cptr, cptr, &me, "Registration Timeout");
789     }
790   }
791
792   /* Check for iauth timeout. */
793   if (FlagHas(&auth->flags, AR_IAUTH_PENDING)) {
794     if (IAuthHas(iauth, IAUTH_REQUIRED)) {
795       sendheader(cptr, REPORT_FAIL_IAUTH);
796       return exit_client_msg(cptr, cptr, &me, "Authorization Timeout");
797     }
798     sendto_iauth(cptr, "T");
799     FlagClr(&auth->flags, AR_IAUTH_PENDING);
800     return check_auth_finished(auth);
801   }
802
803   assert(0 && "Unexpectedly reached end of auth_ping_timeout()");
804   return 0;
805 }
806
807 /** Timeout a given auth request.
808  * @param[in] ev A timer event whose associated data is the expired
809  *   struct AuthRequest.
810  */
811 static void auth_timeout_callback(struct Event* ev)
812 {
813   struct AuthRequest* auth;
814
815   assert(0 != ev_timer(ev));
816   assert(0 != t_data(ev_timer(ev)));
817
818   auth = (struct AuthRequest*) t_data(ev_timer(ev));
819
820   if (ev_type(ev) == ET_EXPIRE) {
821     /* Report the timeout in the log. */
822     log_write(LS_RESOLVER, L_INFO, 0, "Registration timeout %s",
823               get_client_name(auth->client, HIDE_IP));
824
825     /* Notify client if ident lookup failed. */
826     if (FlagHas(&auth->flags, AR_AUTH_PENDING)) {
827       FlagClr(&auth->flags, AR_AUTH_PENDING);
828       if (IsUserPort(auth->client))
829         sendheader(auth->client, REPORT_FAIL_ID);
830     }
831
832     /* Likewise if dns lookup failed. */
833     if (FlagHas(&auth->flags, AR_DNS_PENDING)) {
834       FlagClr(&auth->flags, AR_DNS_PENDING);
835       delete_resolver_queries(auth);
836       if (IsUserPort(auth->client))
837         sendheader(auth->client, REPORT_FAIL_DNS);
838     }
839
840     /* Try to register the client. */
841     check_auth_finished(auth);
842   }
843 }
844
845 /** Handle a complete DNS lookup.  Send the client on it's way to a
846  * connection completion, regardless of success or failure -- unless
847  * there was a mismatch and KILL_IPMISMATCH is set.
848  * @param[in] vptr The pending struct AuthRequest.
849  * @param[in] addr IP address being resolved.
850  * @param[in] h_name Resolved name, or NULL if lookup failed.
851  */
852 static void auth_dns_callback(void* vptr, const struct irc_in_addr *addr, const char *h_name)
853 {
854   struct AuthRequest* auth = (struct AuthRequest*) vptr;
855   assert(0 != auth);
856
857   FlagClr(&auth->flags, AR_DNS_PENDING);
858   if (!addr) {
859     /* DNS entry was missing for the IP. */
860     if (IsUserPort(auth->client))
861       sendheader(auth->client, REPORT_FAIL_DNS);
862     sendto_iauth(auth->client, "d");
863   } else if (!irc_in_addr_valid(addr)
864              || (irc_in_addr_cmp(&cli_ip(auth->client), addr)
865                  && irc_in_addr_cmp(&auth->original, addr))) {
866     /* IP for hostname did not match client's IP. */
867     sendto_opmask_butone(0, SNO_IPMISMATCH, "IP# Mismatch: %s != %s[%s]",
868                          cli_sock_ip(auth->client), h_name,
869                          ircd_ntoa(addr));
870     if (IsUserPort(auth->client))
871       sendheader(auth->client, REPORT_IP_MISMATCH);
872     if (feature_bool(FEAT_KILL_IPMISMATCH)) {
873       exit_client(auth->client, auth->client, &me, "IP mismatch");
874       return;
875     }
876   } else if (!auth_verify_hostname(h_name, HOSTLEN)) {
877     /* Hostname did not look valid. */
878     if (IsUserPort(auth->client))
879       sendheader(auth->client, REPORT_INVAL_DNS);
880     sendto_iauth(auth->client, "d");
881   } else {
882     /* Hostname and mappings checked out. */
883     if (IsUserPort(auth->client))
884       sendheader(auth->client, REPORT_FIN_DNS);
885     ircd_strncpy(cli_sockhost(auth->client), h_name, HOSTLEN);
886     sendto_iauth(auth->client, "N %s", h_name);
887   }
888   check_auth_finished(auth);
889 }
890
891 /** Flag the client to show an attempt to contact the ident server on
892  * the client's host.  Should the connect or any later phase of the
893  * identifying process fail, it is aborted and the user is given a
894  * username of "unknown".
895  * @param[in] auth The request for which to start the ident lookup.
896  */
897 static void start_auth_query(struct AuthRequest* auth)
898 {
899   struct irc_sockaddr remote_addr;
900   struct irc_sockaddr local_addr;
901   int                 fd;
902   IOResult            result;
903
904   assert(0 != auth);
905   assert(0 != auth->client);
906
907   /*
908    * get the local address of the client and bind to that to
909    * make the auth request.  This used to be done only for
910    * ifdef VIRTUAL_HOST, but needs to be done for all clients
911    * since the ident request must originate from that same address--
912    * and machines with multiple IP addresses are common now
913    */
914   memcpy(&local_addr, &auth->local, sizeof(local_addr));
915   local_addr.port = 0;
916   memcpy(&remote_addr.addr, &cli_ip(auth->client), sizeof(remote_addr.addr));
917   remote_addr.port = 113;
918   fd = os_socket(&local_addr, SOCK_STREAM, "auth query", 0);
919   if (fd < 0) {
920     ++ServerStats->is_abad;
921     if (IsUserPort(auth->client))
922       sendheader(auth->client, REPORT_FAIL_ID);
923     return;
924   }
925   if (IsUserPort(auth->client))
926     sendheader(auth->client, REPORT_DO_ID);
927
928   if ((result = os_connect_nonb(fd, &remote_addr)) == IO_FAILURE ||
929       !socket_add(&auth->socket, auth_sock_callback, (void*) auth,
930                   result == IO_SUCCESS ? SS_CONNECTED : SS_CONNECTING,
931                   SOCK_EVENT_READABLE, fd)) {
932     ++ServerStats->is_abad;
933     if (IsUserPort(auth->client))
934       sendheader(auth->client, REPORT_FAIL_ID);
935     close(fd);
936     return;
937   }
938
939   FlagSet(&auth->flags, AR_AUTH_PENDING);
940   if (result == IO_SUCCESS)
941     send_auth_query(auth);
942 }
943
944 /** Initiate DNS lookup for a client.
945  * @param[in] auth The auth request for which to start the DNS lookup.
946  */
947 static void start_dns_query(struct AuthRequest *auth)
948 {
949   if (feature_bool(FEAT_NODNS)) {
950     sendto_iauth(auth->client, "d");
951     return;
952   }
953
954   if (irc_in_addr_is_loopback(&cli_ip(auth->client))) {
955     strcpy(cli_sockhost(auth->client), cli_name(&me));
956     sendto_iauth(auth->client, "N %s", cli_sockhost(auth->client));
957     return;
958   }
959
960   if (IsUserPort(auth->client))
961     sendheader(auth->client, REPORT_DO_DNS);
962
963   FlagSet(&auth->flags, AR_DNS_PENDING);
964   gethost_byaddr(&cli_ip(auth->client), auth_dns_callback, auth);
965 }
966
967 /** Initiate IAuth check for a client.
968  * @param[in] auth The auth request for which to star the IAuth check.
969  */
970 static void start_iauth_query(struct AuthRequest *auth)
971 {
972   FlagSet(&auth->flags, AR_IAUTH_PENDING);
973   if (!sendto_iauth(auth->client, "C %s %hu %s %hu",
974                     cli_sock_ip(auth->client), auth->port,
975                     ircd_ntoa(&auth->local.addr), auth->local.port))
976     FlagClr(&auth->flags, AR_IAUTH_PENDING);
977 }
978
979 /** Starts auth (identd) and dns queries for a client.
980  * @param[in] client The client for which to start queries.
981  */
982 void start_auth(struct Client* client)
983 {
984   struct irc_sockaddr remote;
985   struct AuthRequest* auth;
986
987   assert(0 != client);
988   Debug((DEBUG_INFO, "Beginning auth request on client %p", client));
989
990   /* Register with event handlers. */
991   cli_lasttime(client) = CurrentTime;
992   cli_since(client) = CurrentTime;
993   if (cli_fd(client) > HighestFd)
994     HighestFd = cli_fd(client);
995   LocalClientArray[cli_fd(client)] = client;
996   socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
997
998   /* Allocate the AuthRequest. */
999   auth = auth_freelist;
1000   if (auth)
1001       auth_freelist = auth->next;
1002   else
1003       auth = MyMalloc(sizeof(*auth));
1004   assert(0 != auth);
1005   memset(auth, 0, sizeof(*auth));
1006   auth->client = client;
1007   cli_auth(client) = auth;
1008   s_fd(&auth->socket) = -1;
1009   timer_add(timer_init(&auth->timeout), auth_timeout_callback, (void*) auth,
1010             TT_RELATIVE, feature_int(FEAT_AUTH_TIMEOUT));
1011
1012   /* Try to get socket endpoint addresses. */
1013   if (!os_get_sockname(cli_fd(client), &auth->local)
1014       || !os_get_peername(cli_fd(client), &remote)) {
1015     ++ServerStats->is_abad;
1016     if (IsUserPort(auth->client))
1017       sendheader(auth->client, REPORT_FAIL_ID);
1018     exit_client(auth->client, auth->client, &me, "Socket local/peer lookup failed");
1019     return;
1020   }
1021   auth->port = remote.port;
1022
1023   /* Try to start DNS lookup. */
1024   start_dns_query(auth);
1025
1026   /* Try to start ident lookup. */
1027   start_auth_query(auth);
1028
1029   /* Set required client inputs for users. */
1030   if (IsUserPort(client)) {
1031     cli_user(client) = make_user(client);
1032     cli_user(client)->server = &me;
1033     FlagSet(&auth->flags, AR_NEEDS_USER);
1034     FlagSet(&auth->flags, AR_NEEDS_NICK);
1035
1036     /* Try to start iauth lookup. */
1037     start_iauth_query(auth);
1038   }
1039
1040   /* Add client to GlobalClientList. */
1041   add_client_to_list(client);
1042
1043   /* Check which auth events remain pending. */
1044   check_auth_finished(auth);
1045 }
1046
1047 /** Mark that a user has PONGed while unregistered.
1048  * @param[in] auth Authorization request for client.
1049  * @param[in] cookie PONG cookie value sent by client.
1050  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1051  */
1052 int auth_set_pong(struct AuthRequest *auth, unsigned int cookie)
1053 {
1054   assert(auth != NULL);
1055   if (!FlagHas(&auth->flags, AR_NEEDS_PONG))
1056     return 0;
1057   if (cookie != auth->cookie)
1058   {
1059     send_reply(auth->client, SND_EXPLICIT | ERR_BADPING,
1060                ":To connect, type /QUOTE PONG %u", auth->cookie);
1061     return 0;
1062   }
1063   cli_lasttime(auth->client) = CurrentTime;
1064   FlagClr(&auth->flags, AR_NEEDS_PONG);
1065   return check_auth_finished(auth);
1066 }
1067
1068 /** Record a user's claimed username and userinfo.
1069  * @param[in] auth Authorization request for client.
1070  * @param[in] username Client's asserted username.
1071  * @param[in] hostname Third argument of USER command (client's
1072  *   hostname, per RFC 1459).
1073  * @param[in] servername Fourth argument of USER command (server's
1074  *   name, per RFC 1459).
1075  * @param[in] userinfo Client's asserted self-description.
1076  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1077  */
1078 int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo)
1079 {
1080   struct Client *cptr;
1081
1082   assert(auth != NULL);
1083   if (FlagHas(&auth->flags, AR_IAUTH_HURRY))
1084     return 0;
1085   FlagClr(&auth->flags, AR_NEEDS_USER);
1086   cptr = auth->client;
1087   ircd_strncpy(cli_info(cptr), userinfo, REALLEN);
1088   ircd_strncpy(cli_user(cptr)->username, username, USERLEN);
1089   ircd_strncpy(cli_user(cptr)->host, cli_sockhost(cptr), HOSTLEN);
1090   if (IAuthHas(iauth, IAUTH_UNDERNET))
1091     sendto_iauth(cptr, "U %s %s %s :%s", username, hostname, servername, userinfo);
1092   else if (IAuthHas(iauth, IAUTH_ADDLINFO))
1093     sendto_iauth(cptr, "U %s", username);
1094   return check_auth_finished(auth);
1095 }
1096
1097 /** Handle authorization-related aspects of initial nickname selection.
1098  * This is called after verifying that the nickname is available.
1099  * @param[in] auth Authorization request for client.
1100  * @param[in] nickname Client's requested nickname.
1101  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1102  */
1103 int auth_set_nick(struct AuthRequest *auth, const char *nickname)
1104 {
1105   assert(auth != NULL);
1106   FlagClr(&auth->flags, AR_NEEDS_NICK);
1107   /*
1108    * If the client hasn't gotten a cookie-ping yet,
1109    * choose a cookie and send it. -record!jegelhof@cloud9.net
1110    */
1111   if (!auth->cookie) {
1112     do {
1113       auth->cookie = ircrandom();
1114     } while (!auth->cookie);
1115     sendrawto_one(auth->client, "PING :%u", auth->cookie);
1116     FlagSet(&auth->flags, AR_NEEDS_PONG);
1117   }
1118   if (IAuthHas(iauth, IAUTH_UNDERNET))
1119     sendto_iauth(auth->client, "n %s", nickname);
1120   return check_auth_finished(auth);
1121 }
1122
1123 /** Record a user's password.
1124  * @param[in] auth Authorization request for client.
1125  * @param[in] password Client's password.
1126  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1127  */
1128 int auth_set_password(struct AuthRequest *auth, const char *password)
1129 {
1130   assert(auth != NULL);
1131   if (IAuthHas(iauth, IAUTH_ADDLINFO))
1132     sendto_iauth(auth->client, "P :%s", password);
1133   return 0;
1134 }
1135
1136 /** Send exit notification for \a cptr to iauth.
1137  * @param[in] cptr Client who is exiting.
1138  */
1139 void auth_send_exit(struct Client *cptr)
1140 {
1141   sendto_iauth(cptr, "D");
1142 }
1143
1144 /** Forward an XREPLY on to iauth.
1145  * @param[in] sptr Source of the XREPLY.
1146  * @param[in] routing Routing information for the original XQUERY.
1147  * @param[in] reply Contents of the reply.
1148  */
1149 void auth_send_xreply(struct Client *sptr, const char *routing,
1150                       const char *reply)
1151 {
1152   sendto_iauth(NULL, "X %#C %s :%s", sptr, routing, reply);
1153 }
1154
1155 /** Mark that a user has started capabilities negotiation.
1156  * This blocks authorization until auth_cap_done() is called.
1157  * @param[in] auth Authorization request for client.
1158  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1159  */
1160 int auth_cap_start(struct AuthRequest *auth)
1161 {
1162   assert(auth != NULL);
1163   FlagSet(&auth->flags, AR_CAP_PENDING);
1164   return 0;
1165 }
1166
1167 /** Mark that a user has completed capabilities negotiation.
1168  * This unblocks authorization if auth_cap_start() was called.
1169  * @param[in] auth Authorization request for client.
1170  * @return Zero if client should be kept, CPTR_KILLED if rejected.
1171  */
1172 int auth_cap_done(struct AuthRequest *auth)
1173 {
1174   assert(auth != NULL);
1175   FlagClr(&auth->flags, AR_CAP_PENDING);
1176   return check_auth_finished(auth);
1177 }
1178
1179 /** Attempt to spawn the process for an IAuth instance.
1180  * @param[in] iauth IAuth descriptor.
1181  * @param[in] automatic If non-zero, apply sanity checks against
1182  *   excessive automatic restarts.
1183  * @return 0 on success, non-zero on failure.
1184  */
1185 int iauth_do_spawn(struct IAuth *iauth, int automatic)
1186 {
1187   pid_t cpid;
1188   int s_io[2];
1189   int s_err[2];
1190   int res;
1191
1192   if (automatic && CurrentTime - iauth->started < 5)
1193   {
1194     sendto_opmask_butone(NULL, SNO_AUTH, "IAuth crashed fast, leaving it dead.");
1195     return -1;
1196   }
1197
1198   /* Record time we tried to spawn the iauth process. */
1199   iauth->started = CurrentTime;
1200
1201   /* Attempt to allocate a pair of sockets. */
1202   res = os_socketpair(s_io);
1203   if (res) {
1204     res = errno;
1205     Debug((DEBUG_INFO, "Unable to create IAuth socketpair: %s", strerror(res)));
1206     return res;
1207   }
1208
1209   /* Mark the parent's side of the pair (element 0) as non-blocking. */
1210   res = os_set_nonblocking(s_io[0]);
1211   if (!res) {
1212     res = errno;
1213     Debug((DEBUG_INFO, "Unable to make IAuth socket non-blocking: %s", strerror(res)));
1214     close(s_io[1]);
1215     close(s_io[0]);
1216     return res;
1217   }
1218
1219   /* Initialize the socket structure to talk to the child. */
1220   res = socket_add(i_socket(iauth), iauth_sock_callback, iauth,
1221                    SS_CONNECTED, SOCK_EVENT_READABLE, s_io[0]);
1222   if (!res) {
1223     res = errno;
1224     Debug((DEBUG_INFO, "Unable to register IAuth socket: %s", strerror(res)));
1225     close(s_io[1]);
1226     close(s_io[0]);
1227     return res;
1228   }
1229
1230   /* Allocate another pair for stderr. */
1231   res = os_socketpair(s_err);
1232   if (res) {
1233     res = errno;
1234     Debug((DEBUG_INFO, "Unable to create IAuth stderr: %s", strerror(res)));
1235     socket_del(i_socket(iauth));
1236     close(s_io[1]);
1237     close(s_io[0]);
1238     return res;
1239   }
1240
1241   /* Mark parent side of this pair non-blocking, too. */
1242   res = os_set_nonblocking(s_err[0]);
1243   if (!res) {
1244     res = errno;
1245     Debug((DEBUG_INFO, "Unable to make IAuth stderr non-blocking: %s", strerror(res)));
1246     close(s_err[1]);
1247     close(s_err[0]);
1248     socket_del(i_socket(iauth));
1249     close(s_io[1]);
1250     close(s_io[0]);
1251     return res;
1252   }
1253
1254   /* And set up i_stderr(iauth). */
1255   res = socket_add(i_stderr(iauth), iauth_stderr_callback, iauth,
1256                    SS_CONNECTED, SOCK_EVENT_READABLE, s_err[0]);
1257   if (!res) {
1258     res = errno;
1259     Debug((DEBUG_INFO, "Unable to register IAuth stderr: %s", strerror(res)));
1260     close(s_err[1]);
1261     close(s_err[0]);
1262     socket_del(i_socket(iauth));
1263     close(s_io[1]);
1264     close(s_io[0]);
1265     return res;
1266   }
1267
1268   /* Attempt to fork a child process. */
1269   cpid = fork();
1270   if (cpid < 0) {
1271     /* Error forking the child, still in parent. */
1272     res = errno;
1273     Debug((DEBUG_INFO, "Unable to fork IAuth child: %s", strerror(res)));
1274     socket_del(i_stderr(iauth));
1275     close(s_err[1]);
1276     close(s_err[0]);
1277     socket_del(i_socket(iauth));
1278     close(s_io[1]);
1279     close(s_io[0]);
1280     return res;
1281   }
1282
1283   if (cpid > 0) {
1284     /* We are the parent process.  Close the child's sockets. */
1285     close(s_io[1]);
1286     close(s_err[1]);
1287     /* Send our server name (supposedly for proxy checking purposes)
1288      * and maximum number of connections (for allocation hints).
1289      * Need to use conf_get_local() since &me may not be fully
1290      * initialized the first time we run.
1291      */
1292     sendto_iauth(NULL, "M %s %d", conf_get_local()->name, MAXCONNECTIONS);
1293     /* Indicate success (until the child dies). */
1294     return 0;
1295   }
1296
1297   /* We are the child process.
1298    * Duplicate our end of the socket to stdin, stdout and stderr.
1299    * Then close all the higher-numbered FDs and exec the process.
1300    */
1301   if (dup2(s_io[1], 0) == 0
1302       && dup2(s_io[1], 1) == 1
1303       && dup2(s_err[1], 2) == 2) {
1304     close_connections(0);
1305     execvp(iauth->i_argv[0], iauth->i_argv);
1306   }
1307
1308   /* If we got here, something was seriously wrong. */
1309   exit(EXIT_FAILURE);
1310 }
1311
1312 /** See if an %IAuth program must be spawned.
1313  * If a process is already running with the specified options, keep it.
1314  * Otherwise spawn a new child process to perform the %IAuth function.
1315  * @param[in] argc Number of parameters to use when starting process.
1316  * @param[in] argv Array of parameters to start process.
1317  * @return 0 on failure, 1 on new process, 2 on reuse of existing process.
1318  */
1319 int auth_spawn(int argc, char *argv[])
1320 {
1321   int ii;
1322
1323   if (iauth) {
1324     int same = 1;
1325
1326     /* Check that incoming arguments all match pre-existing arguments. */
1327     for (ii = 0; same && (ii < argc); ++ii) {
1328       if (NULL == iauth->i_argv[ii]
1329           || 0 != strcmp(iauth->i_argv[ii], argv[ii]))
1330         same = 0;
1331     }
1332     /* Check that we have no more pre-existing arguments. */
1333     if (same && iauth->i_argv[ii])
1334       same = 0;
1335     /* If they are the same and still connected, clear the "closing" flag and exit. */
1336     if (same && i_GetConnected(iauth)) {
1337       Debug((DEBUG_INFO, "Reusing existing IAuth process"));
1338       IAuthClr(iauth, IAUTH_CLOSING);
1339       return 2;
1340     }
1341     auth_close_unused();
1342   }
1343
1344   /* Need to initialize a new connection. */
1345   iauth = MyCalloc(1, sizeof(*iauth));
1346   msgq_init(i_sendQ(iauth));
1347   /* Populate iauth's argv array. */
1348   iauth->i_argv = MyCalloc(argc + 1, sizeof(iauth->i_argv[0]));
1349   for (ii = 0; ii < argc; ++ii)
1350     DupString(iauth->i_argv[ii], argv[ii]);
1351   iauth->i_argv[ii] = NULL;
1352   /* Try to spawn it, and handle the results. */
1353   if (iauth_do_spawn(iauth, 0))
1354     return 0;
1355   IAuthClr(iauth, IAUTH_CLOSING);
1356   return 1;
1357 }
1358
1359 /** Mark all %IAuth connections as closing. */
1360 void auth_mark_closing(void)
1361 {
1362   if (iauth)
1363     IAuthSet(iauth, IAUTH_CLOSING);
1364 }
1365
1366 /** Complete disconnection of an %IAuth connection.
1367  * @param[in] iauth %Connection to fully close.
1368  */
1369 static void iauth_disconnect(struct IAuth *iauth)
1370 {
1371   if (iauth == NULL)
1372     return;
1373
1374   /* Close main socket. */
1375   if (s_fd(i_socket(iauth)) != -1) {
1376     close(s_fd(i_socket(iauth)));
1377     socket_del(i_socket(iauth));
1378     s_fd(i_socket(iauth)) = -1;
1379   }
1380
1381   /* Close error socket. */
1382   if (s_fd(i_stderr(iauth)) != -1) {
1383     close(s_fd(i_stderr(iauth)));
1384     socket_del(i_stderr(iauth));
1385     s_fd(i_stderr(iauth)) = -1;
1386   }
1387 }
1388
1389 /** Close all %IAuth connections marked as closing. */
1390 void auth_close_unused(void)
1391 {
1392   if (IAuthHas(iauth, IAUTH_CLOSING)) {
1393     int ii;
1394     iauth_disconnect(iauth);
1395     if (iauth->i_argv) {
1396       for (ii = 0; iauth->i_argv[ii]; ++ii)
1397         MyFree(iauth->i_argv[ii]);
1398       MyFree(iauth->i_argv);
1399     }
1400     MyFree(iauth);
1401   }
1402 }
1403
1404 /** Send queued output to \a iauth.
1405  * @param[in] iauth Writable connection with queued data.
1406  */
1407 static void iauth_write(struct IAuth *iauth)
1408 {
1409   unsigned int bytes_tried, bytes_sent;
1410   IOResult iores;
1411
1412   if (IAuthHas(iauth, IAUTH_BLOCKED))
1413     return;
1414   while (MsgQLength(i_sendQ(iauth)) > 0) {
1415     iores = os_sendv_nonb(s_fd(i_socket(iauth)), i_sendQ(iauth), &bytes_tried, &bytes_sent);
1416     switch (iores) {
1417     case IO_SUCCESS:
1418       msgq_delete(i_sendQ(iauth), bytes_sent);
1419       iauth->i_sendB += bytes_sent;
1420       if (bytes_tried == bytes_sent)
1421         break;
1422       /* If bytes_sent < bytes_tried, fall through to IO_BLOCKED. */
1423     case IO_BLOCKED:
1424       IAuthSet(iauth, IAUTH_BLOCKED);
1425       socket_events(i_socket(iauth), SOCK_ACTION_ADD | SOCK_EVENT_WRITABLE);
1426       return;
1427     case IO_FAILURE:
1428       iauth_disconnect(iauth);
1429       return;
1430     }
1431   }
1432   /* We were able to flush all events, so remove notification. */
1433   socket_events(i_socket(iauth), SOCK_ACTION_DEL | SOCK_EVENT_WRITABLE);
1434 }
1435
1436 /** Send a message to iauth.
1437  * @param[in] cptr Optional client context for message.
1438  * @param[in] format Format string for message.
1439  * @return Non-zero on successful send or buffering, zero on failure.
1440  */
1441 static int sendto_iauth(struct Client *cptr, const char *format, ...)
1442 {
1443   struct VarData vd;
1444   struct MsgBuf *mb;
1445
1446   /* Do not send requests when we have no iauth. */
1447   if (!i_GetConnected(iauth))
1448     return 0;
1449   /* Do not send for clients in the NORMAL state. */
1450   if (cptr
1451       && (format[0] != 'D')
1452       && (!cli_auth(cptr) || !FlagHas(&cli_auth(cptr)->flags, AR_IAUTH_PENDING)))
1453     return 0;
1454
1455   /* Build the message buffer. */
1456   vd.vd_format = format;
1457   va_start(vd.vd_args, format);
1458   if (0 == cptr)
1459     mb = msgq_make(NULL, "-1 %v", &vd);
1460   else
1461     mb = msgq_make(NULL, "%d %v", cli_fd(cptr), &vd);
1462   va_end(vd.vd_args);
1463
1464   /* Tack it onto the iauth sendq and try to write it. */
1465   ++iauth->i_sendM;
1466   msgq_add(i_sendQ(iauth), mb, 0);
1467   msgq_clean(mb);
1468   iauth_write(iauth);
1469   return 1;
1470 }
1471
1472 /** Send text to interested operators (SNO_AUTH server notice).
1473  * @param[in] iauth Active IAuth session.
1474  * @param[in] cli Client referenced by command.
1475  * @param[in] parc Number of parameters (1).
1476  * @param[in] params Text to send.
1477  * @return Zero.
1478  */
1479 static int iauth_cmd_snotice(struct IAuth *iauth, struct Client *cli,
1480                              int parc, char **params)
1481 {
1482   sendto_opmask_butone(NULL, SNO_AUTH, "%s", params[0]);
1483   return 0;
1484 }
1485
1486 /** Set the debug level for the session.
1487  * @param[in] iauth Active IAuth session.
1488  * @param[in] cli Client referenced by command.
1489  * @param[in] parc Number of parameters (1).
1490  * @param[in] params String starting with an integer.
1491  * @return Zero.
1492  */
1493 static int iauth_cmd_debuglevel(struct IAuth *iauth, struct Client *cli,
1494                                 int parc, char **params)
1495 {
1496   int new_level;
1497
1498   new_level = parc > 0 ? atoi(params[0]) : 0;
1499   if (i_debug(iauth) > 0 || new_level > 0) {
1500     /* The "ia_dbg" name is borrowed from (IRCnet) ircd. */
1501     sendto_opmask_butone(NULL, SNO_AUTH, "ia_dbg = %d", new_level);
1502   }
1503   i_debug(iauth) = new_level;
1504   return 0;
1505 }
1506
1507 /** Set policy options for the session.
1508  * Old policy is forgotten, and any of the following characters in \a
1509  * params enable the corresponding policy:
1510  * \li A IAUTH_ADDLINFO
1511  * \li R IAUTH_REQUIRED
1512  * \li T IAUTH_TIMEOUT
1513  * \li W IAUTH_EXTRAWAIT
1514  * \li U IAUTH_UNDERNET
1515  *
1516  * @param[in] iauth Active IAuth session.
1517  * @param[in] cli Client referenced by command.
1518  * @param[in] parc Number of parameters (1).
1519  * @param[in] params Zero or more policy options.
1520  * @return Zero.
1521  */
1522 static int iauth_cmd_policy(struct IAuth *iauth, struct Client *cli,
1523                             int parc, char **params)
1524 {
1525   enum IAuthFlag flag;
1526   char *p;
1527
1528   /* Erase old policy first. */
1529   for (flag = IAUTH_FIRST_OPTION; flag < IAUTH_LAST_FLAG; ++flag)
1530     IAuthClr(iauth, flag);
1531
1532   if (parc > 0) /* only try to parse if we were given a policy string */
1533     /* Parse new policy set. */
1534     for (p = params[0]; *p; p++) switch (*p) {
1535     case 'A': IAuthSet(iauth, IAUTH_ADDLINFO); break;
1536     case 'R': IAuthSet(iauth, IAUTH_REQUIRED); break;
1537     case 'T': IAuthSet(iauth, IAUTH_TIMEOUT); break;
1538     case 'W': IAuthSet(iauth, IAUTH_EXTRAWAIT); break;
1539     case 'U': IAuthSet(iauth, IAUTH_UNDERNET); break;
1540     }
1541
1542   /* Optionally notify operators. */
1543   if (i_debug(iauth) > 0)
1544     sendto_opmask_butone(NULL, SNO_AUTH, "iauth options: %s", params[0]);
1545   return 0;
1546 }
1547
1548 /** Set the iauth program version number.
1549  * @param[in] iauth Active IAuth session.
1550  * @param[in] cli Client referenced by command.
1551  * @param[in] parc Number of parameters (1).
1552  * @param[in] params Version number or name.
1553  * @return Zero.
1554  */
1555 static int iauth_cmd_version(struct IAuth *iauth, struct Client *cli,
1556                              int parc, char **params)
1557 {
1558   MyFree(iauth->i_version);
1559   DupString(iauth->i_version, parc > 0 ? params[0] : "<NONE>");
1560   sendto_opmask_butone(NULL, SNO_AUTH, "iauth version %s running.",
1561                        iauth->i_version);
1562   return 0;
1563 }
1564
1565 /** Paste a parameter list together into a single string.
1566  * @param[in] parc Number of parameters.
1567  * @param[in] params Parameter list to paste together.
1568  * @return Pasted parameter list.
1569  */
1570 static char *paste_params(int parc, char **params)
1571 {
1572   char *str, *tmp;
1573   int len = 0, lengths[MAXPARA], i;
1574
1575   /* Compute the length... */
1576   for (i = 0; i < parc; i++)
1577     len += lengths[i] = strlen(params[i]);
1578
1579   /* Allocate memory, accounting for string lengths, spaces (parc - 1), a
1580    * sentinel, and the trailing \0
1581    */
1582   str = MyMalloc(len + parc + 1);
1583
1584   /* Build the pasted string */
1585   for (tmp = str, i = 0; i < parc; i++) {
1586     if (i) /* add space separator... */
1587       *(tmp++) = ' ';
1588     if (i == parc - 1) /* add colon sentinel */
1589       *(tmp++) = ':';
1590
1591     /* Copy string component... */
1592     memcpy(tmp, params[i], lengths[i]);
1593     tmp += lengths[i]; /* move to end of string */
1594   }
1595
1596   /* terminate the string... */
1597   *tmp = '\0';
1598
1599   return str; /* return the pasted string */
1600 }
1601
1602 /** Clear cached iauth configuration information.
1603  * @param[in] iauth Active IAuth session.
1604  * @param[in] cli Client referenced by command.
1605  * @param[in] parc Number of parameters (0).
1606  * @param[in] params Parameter list (ignored).
1607  * @return Zero.
1608  */
1609 static int iauth_cmd_newconfig(struct IAuth *iauth, struct Client *cli,
1610                                int parc, char **params)
1611 {
1612   struct SLink *head;
1613   struct SLink *next;
1614
1615   head = iauth->i_config;
1616   iauth->i_config = NULL;
1617   for (; head; head = next) {
1618     next = head->next;
1619     MyFree(head->value.cp);
1620     free_link(head);
1621   }
1622   sendto_opmask_butone(NULL, SNO_AUTH, "New iauth configuration.");
1623   return 0;
1624 }
1625
1626 /** Append iauth configuration information.
1627  * @param[in] iauth Active IAuth session.
1628  * @param[in] cli Client referenced by command.
1629  * @param[in] parc Number of parameters.
1630  * @param[in] params Description of configuration element.
1631  * @return Zero.
1632  */
1633 static int iauth_cmd_config(struct IAuth *iauth, struct Client *cli,
1634                             int parc, char **params)
1635 {
1636   struct SLink *node;
1637
1638   if (iauth->i_config) {
1639     for (node = iauth->i_config; node->next; node = node->next) ;
1640     node = node->next = make_link();
1641   } else {
1642     node = iauth->i_config = make_link();
1643   }
1644   node->value.cp = paste_params(parc, params);
1645   node->next = 0; /* must be explicitly cleared */
1646   return 0;
1647 }
1648
1649 /** Clear cached iauth configuration information.
1650  * @param[in] iauth Active IAuth session.
1651  * @param[in] cli Client referenced by command.
1652  * @param[in] parc Number of parameters (0).
1653  * @param[in] params Parameter list (ignored).
1654  * @return Zero.
1655  */
1656 static int iauth_cmd_newstats(struct IAuth *iauth, struct Client *cli,
1657                               int parc, char **params)
1658 {
1659   struct SLink *head;
1660   struct SLink *next;
1661
1662   head = iauth->i_stats;
1663   iauth->i_stats = NULL;
1664   for (; head; head = next) {
1665     next = head->next;
1666     MyFree(head->value.cp);
1667     free_link(head);
1668   }
1669   sendto_opmask_butone(NULL, SNO_AUTH, "New iauth statistics.");
1670   return 0;
1671 }
1672
1673 /** Append iauth statistics information.
1674  * @param[in] iauth Active IAuth session.
1675  * @param[in] cli Client referenced by command.
1676  * @param[in] parc Number of parameters.
1677  * @param[in] params Statistics element.
1678  * @return Zero.
1679  */
1680 static int iauth_cmd_stats(struct IAuth *iauth, struct Client *cli,
1681                            int parc, char **params)
1682 {
1683   struct SLink *node;
1684   if (iauth->i_stats) {
1685     for (node = iauth->i_stats; node->next; node = node->next) ;
1686     node = node->next = make_link();
1687   } else {
1688     node = iauth->i_stats = make_link();
1689   }
1690   node->value.cp = paste_params(parc, params);
1691   node->next = 0; /* must be explicitly cleared */
1692   return 0;
1693 }
1694
1695 /** Set client's username to a trusted string even if it breaks the rules.
1696  * @param[in] iauth Active IAuth session.
1697  * @param[in] cli Client referenced by command.
1698  * @param[in] parc Number of parameters (1).
1699  * @param[in] params Forced username.
1700  * @return One.
1701  */
1702 static int iauth_cmd_username_forced(struct IAuth *iauth, struct Client *cli,
1703                                      int parc, char **params)
1704 {
1705   assert(cli_auth(cli) != NULL);
1706   FlagClr(&cli_auth(cli)->flags, AR_AUTH_PENDING);
1707   if (!EmptyString(params[0])) {
1708     ircd_strncpy(cli_username(cli), params[0], USERLEN);
1709     SetGotId(cli);
1710     FlagSet(&cli_auth(cli)->flags, AR_IAUTH_USERNAME);
1711     FlagSet(&cli_auth(cli)->flags, AR_IAUTH_FUSERNAME);
1712   }
1713   return 1;
1714 }
1715
1716 /** Set client's username to a trusted string.
1717  * @param[in] iauth Active IAuth session.
1718  * @param[in] cli Client referenced by command.
1719  * @param[in] parc Number of parameters (1).
1720  * @param[in] params Trusted username.
1721  * @return One.
1722  */
1723 static int iauth_cmd_username_good(struct IAuth *iauth, struct Client *cli,
1724                                    int parc, char **params)
1725 {
1726   assert(cli_auth(cli) != NULL);
1727   FlagClr(&cli_auth(cli)->flags, AR_AUTH_PENDING);
1728   if (!EmptyString(params[0])) {
1729     ircd_strncpy(cli_username(cli), params[0], USERLEN);
1730     SetGotId(cli);
1731     FlagSet(&cli_auth(cli)->flags, AR_IAUTH_USERNAME);
1732   }
1733   return 1;
1734 }
1735
1736 /** Set client's username to an untrusted string.
1737  * @param[in] iauth Active IAuth session.
1738  * @param[in] cli Client referenced by command.
1739  * @param[in] parc Number of parameters (1).
1740  * @param[in] params Untrusted username.
1741  * @return One.
1742  */
1743 static int iauth_cmd_username_bad(struct IAuth *iauth, struct Client *cli,
1744                                   int parc, char **params)
1745 {
1746   assert(cli_auth(cli) != NULL);
1747   FlagClr(&cli_auth(cli)->flags, AR_AUTH_PENDING);
1748   if (!EmptyString(params[0]))
1749     ircd_strncpy(cli_user(cli)->username, params[0], USERLEN);
1750   return 1;
1751 }
1752
1753 /** Set client's hostname.
1754  * @param[in] iauth Active IAuth session.
1755  * @param[in] cli Client referenced by command.
1756  * @param[in] parc Number of parameters (1).
1757  * @param[in] params New hostname for client.
1758  * @return Non-zero if \a cli authorization should be checked for completion.
1759  */
1760 static int iauth_cmd_hostname(struct IAuth *iauth, struct Client *cli,
1761                               int parc, char **params)
1762 {
1763   struct AuthRequest *auth;
1764
1765   if (EmptyString(params[0])) {
1766     sendto_iauth(cli, "E Missing :Missing hostname parameter");
1767     return 0;
1768   }
1769
1770   auth = cli_auth(cli);
1771   assert(auth != NULL);
1772
1773   /* If a DNS request is pending, abort it. */
1774   if (FlagHas(&auth->flags, AR_DNS_PENDING)) {
1775     FlagClr(&auth->flags, AR_DNS_PENDING);
1776     delete_resolver_queries(auth);
1777     if (IsUserPort(cli))
1778       sendheader(cli, REPORT_FIN_DNS);
1779   }
1780   /* Set hostname from params. */
1781   ircd_strncpy(cli_sockhost(cli), params[0], HOSTLEN);
1782   /* If we have gotten here, the user is in a "hurry" state and has
1783    * been pre-registered.  Their hostname was set during that, and
1784    * needs to be overwritten now.
1785    */
1786   if (FlagHas(&auth->flags, AR_IAUTH_HURRY)) {
1787     ircd_strncpy(cli_user(cli)->host, cli_sockhost(cli), HOSTLEN);
1788     ircd_strncpy(cli_user(cli)->realhost, cli_sockhost(cli), HOSTLEN);
1789   }
1790   return 1;
1791 }
1792
1793 /** Set client's IP address.
1794  * @param[in] iauth Active IAuth session.
1795  * @param[in] cli Client referenced by command.
1796  * @param[in] parc Number of parameters (1).
1797  * @param[in] params New IP address for client in dotted quad or
1798  *   standard IPv6 format.
1799  * @return Zero.
1800  */
1801 static int iauth_cmd_ip_address(struct IAuth *iauth, struct Client *cli,
1802                                 int parc, char **params)
1803 {
1804   struct irc_in_addr addr;
1805   struct AuthRequest *auth;
1806
1807   if (EmptyString(params[0])) {
1808     sendto_iauth(cli, "E Missing :Missing IP address parameter");
1809     return 0;
1810   }
1811
1812   /* Get AuthRequest for client. */
1813   auth = cli_auth(cli);
1814   assert(auth != NULL);
1815
1816   /* Parse the client's new IP address. */
1817   if (!ircd_aton(&addr, params[0])) {
1818     sendto_iauth(cli, "E Invalid :Unable to parse IP address [%s]", params[0]);
1819     return 0;
1820   }
1821
1822   /* If this is the first IP override, save the client's original
1823    * address in case we get a DNS response later.
1824    */
1825   if (!irc_in_addr_valid(&auth->original))
1826     memcpy(&auth->original, &cli_ip(cli), sizeof(auth->original));
1827
1828   /* Undo original IP connection in IPcheck. */
1829   IPcheck_connect_fail(cli);
1830   ClearIPChecked(cli);
1831
1832   /* Update the IP and charge them as a remote connect. */
1833   memcpy(&cli_ip(cli), &addr, sizeof(cli_ip(cli)));
1834   IPcheck_remote_connect(cli, 0);
1835
1836   return 0;
1837 }
1838
1839 /** Find a ConfItem structure for a named connection class.
1840  * @param[in] class_name Name of configuration class to find.
1841  * @return A ConfItem of type CONF_CLIENT for the class, or NULL on failure.
1842  */
1843 static struct ConfItem *auth_find_class_conf(const char *class_name)
1844 {
1845   static struct ConfItem *aconf_list;
1846   struct ConnectionClass *class;
1847   struct ConfItem *aconf;
1848
1849   /* Make sure the configuration class is valid. */
1850   class = find_class(class_name);
1851   if (!class || !class->valid)
1852     return NULL;
1853
1854   /* Look for an existing ConfItem for the class. */
1855   for (aconf = aconf_list; aconf; aconf = aconf->next)
1856     if (aconf->conn_class == class)
1857       break;
1858
1859   /* If no ConfItem, create one. */
1860   if (!aconf) {
1861     aconf = make_conf(CONF_CLIENT);
1862     if (!aconf) {
1863       sendto_opmask_butone(NULL, SNO_AUTH,
1864                            "Unable to allocate ConfItem for class %s!",
1865                            ConClass(class));
1866       return NULL;
1867     }
1868     /* make_conf() "helpfully" links the conf into GlobalConfList,
1869      * which we do not want, so undo that.  (Ugh.)
1870      */
1871     if (aconf == GlobalConfList) {
1872       GlobalConfList = aconf->next;
1873     }
1874     /* Back to business as usual. */
1875     aconf->conn_class = class;
1876     aconf->next = aconf_list;
1877     aconf_list = aconf;
1878   }
1879
1880   return aconf;
1881 }
1882
1883 /** Accept a client in IAuth.
1884  * @param[in] iauth Active IAuth session.
1885  * @param[in] cli Client referenced by command.
1886  * @param[in] parc Number of parameters.
1887  * @param[in] params Optional class name for client.
1888  * @return Negative (CPTR_KILLED) if the connection is refused, one otherwise.
1889  */
1890 static int iauth_cmd_done_client(struct IAuth *iauth, struct Client *cli,
1891                                  int parc, char **params)
1892 {
1893   static time_t warn_time;
1894
1895   /* Clear iauth pending flag. */
1896   assert(cli_auth(cli) != NULL);
1897   FlagClr(&cli_auth(cli)->flags, AR_IAUTH_PENDING);
1898
1899   /* If a connection class was specified (and usable), assign the client to it. */
1900   if (!EmptyString(params[0])) {
1901     struct ConfItem *aconf;
1902
1903     aconf = auth_find_class_conf(params[0]);
1904     if (aconf) {
1905       enum AuthorizationCheckResult acr;
1906
1907       acr = attach_conf(cli, aconf);
1908       switch (acr) {
1909       case ACR_OK:
1910         /* There should maybe be some way to set FLAG_DOID here.. */
1911         break;
1912       case ACR_TOO_MANY_IN_CLASS:
1913         ++ServerStats->is_ref;
1914         return exit_client(cli, cli, &me,
1915                            "Sorry, your connection class is full - try "
1916                            "again later or try another server");
1917       default:
1918         log_write(LS_IAUTH, L_ERROR, 0, "IAuth: Unexpected AuthorizationCheckResult %d from attach_conf()", acr);
1919         break;
1920       }
1921     } else
1922       sendto_opmask_butone_ratelimited(NULL, SNO_AUTH, &warn_time,
1923                                        "iauth tried to use undefined class [%s]",
1924                                        params[0]);
1925   }
1926
1927   return 1;
1928 }
1929
1930 /** Accept a client in IAuth and assign them to an account.
1931  * @param[in] iauth Active IAuth session.
1932  * @param[in] cli Client referenced by command.
1933  * @param[in] parc Number of parameters.
1934  * @param[in] params Account name and optional class name for client.
1935  * @return Negative if the connection is refused, otherwise non-zero
1936  *   if \a cli authorization should be checked for completion.
1937  */
1938 static int iauth_cmd_done_account(struct IAuth *iauth, struct Client *cli,
1939                                   int parc, char **params)
1940 {
1941   size_t len;
1942
1943   /* Sanity check. */
1944   if (EmptyString(params[0])) {
1945     sendto_iauth(cli, "E Missing :Missing account parameter");
1946     return 0;
1947   }
1948   /* Check length of account name. */
1949   len = strcspn(params[0], ": ");
1950   if (len > ACCOUNTLEN) {
1951     sendto_iauth(cli, "E Invalid :Account parameter too long");
1952     return 0;
1953   }
1954   /* If account has a creation timestamp, use it. */
1955   assert(cli_user(cli) != NULL);
1956   if (params[0][len] == ':') {
1957     cli_user(cli)->acc_create = strtoul(params[0] + len + 1, NULL, 10);
1958     params[0][len] = '\0';
1959   }
1960
1961   /* Copy account name to User structure. */
1962   ircd_strncpy(cli_user(cli)->account, params[0], ACCOUNTLEN);
1963   SetAccount(cli);
1964
1965   /* Fall through to the normal "done" handler. */
1966   return iauth_cmd_done_client(iauth, cli, parc - 1, params + 1);
1967 }
1968
1969 /** Reject a client's connection.
1970  * @param[in] iauth Active IAuth session.
1971  * @param[in] cli Client referenced by command.
1972  * @param[in] parc Number of parameters (1).
1973  * @param[in] params Optional kill message.
1974  * @return Zero.
1975  */
1976 static int iauth_cmd_kill(struct IAuth *iauth, struct Client *cli,
1977                           int parc, char **params)
1978 {
1979   if (cli_auth(cli))
1980     FlagClr(&cli_auth(cli)->flags, AR_IAUTH_PENDING);
1981   if (EmptyString(params[0]))
1982     params[0] = "Access denied";
1983   exit_client(cli, cli, &me, params[0]);
1984   return 0;
1985 }
1986
1987 /** Change a client's usermode.
1988  * @param[in] iauth Active IAuth session.
1989  * @param[in] cli Client referenced by command.
1990  * @param[in] parc Number of parameters (at least one).
1991  * @param[in] params Usermode arguments for client (with the first
1992  *   starting with '+').
1993  * @return Zero.
1994  */
1995 static int iauth_cmd_usermode(struct IAuth *iauth, struct Client *cli,
1996                               int parc, char **params)
1997 {
1998   if (params[0][0] == '+')
1999   {
2000     set_user_mode(cli, cli, parc + 2, params - 2, ALLOWMODES_ANY);
2001   }
2002   return 0;
2003 }
2004
2005
2006 /** Send a challenge string to the client.
2007  * @param[in] iauth Active IAuth session.
2008  * @param[in] cli Client referenced by command.
2009  * @param[in] parc Number of parameters (1).
2010  * @param[in] params Challenge message for client.
2011  * @return Zero.
2012  */
2013 static int iauth_cmd_challenge(struct IAuth *iauth, struct Client *cli,
2014                                int parc, char **params)
2015 {
2016   if (!EmptyString(params[0]))
2017     sendrawto_one(cli, "NOTICE AUTH :*** %s", params[0]);
2018   return 0;
2019 }
2020
2021 /** Send an extension query to a specified remote server.
2022  * @param[in] iauth Active IAuth session.
2023  * @param[in] cli Client referenced by command.
2024  * @param[in] parc Number of parameters (3).
2025  * @param[in] params Remote server, routing information, and query.
2026  * @return Zero.
2027  */
2028 static int iauth_cmd_xquery(struct IAuth *iauth, struct Client *cli,
2029                             int parc, char **params)
2030 {
2031   char *serv;
2032   const char *routing;
2033   const char *query;
2034   struct Client *acptr;
2035
2036   /* Process parameters */
2037   if (EmptyString(params[0])) {
2038     sendto_iauth(cli, "E Missing :Missing server parameter");
2039     return 0;
2040   } else
2041     serv = params[0];
2042
2043   if (EmptyString(params[1])) {
2044     sendto_iauth(cli, "E Missing :Missing routing parameter");
2045     return 0;
2046   } else
2047     routing = params[1];
2048
2049   if (EmptyString(params[2])) {
2050     sendto_iauth(cli, "E Missing :Missing query parameter");
2051     return 0;
2052   } else
2053     query = params[2];
2054
2055   /* Try to find the specified server */
2056   if (!(acptr = find_match_server(serv))) {
2057     sendto_iauth(cli, "x %s %s :Server not online", serv, routing);
2058     return 0;
2059   }
2060
2061   /* If it's to us, do nothing; otherwise, forward the query */
2062   if (!IsMe(acptr))
2063     /* The "iauth:" prefix helps ircu route the reply to iauth */
2064     sendcmdto_one(&me, CMD_XQUERY, acptr, "%C iauth:%s :%s", acptr, routing,
2065                   query);
2066
2067   return 0;
2068 }
2069
2070 /** Parse a \a message from \a iauth.
2071  * @param[in] iauth Active IAuth session.
2072  * @param[in] message Message to be parsed.
2073  */
2074 static void iauth_parse(struct IAuth *iauth, char *message)
2075 {
2076   char *params[MAXPARA + 1]; /* leave space for NULL */
2077   int parc = 0;
2078   iauth_cmd_handler handler;
2079   struct AuthRequest *auth;
2080   struct Client *cli;
2081   int has_cli;
2082   int id;
2083
2084   /* Find command handler... */
2085   switch (*(message++)) {
2086   case '>': handler = iauth_cmd_snotice; has_cli = 0; break;
2087   case 'G': handler = iauth_cmd_debuglevel; has_cli = 0; break;
2088   case 'O': handler = iauth_cmd_policy; has_cli = 0; break;
2089   case 'V': handler = iauth_cmd_version; has_cli = 0; break;
2090   case 'a': handler = iauth_cmd_newconfig; has_cli = 0; break;
2091   case 'A': handler = iauth_cmd_config; has_cli = 0; break;
2092   case 's': handler = iauth_cmd_newstats; has_cli = 0; break;
2093   case 'S': handler = iauth_cmd_stats; has_cli = 0; break;
2094   case 'X': handler = iauth_cmd_xquery; has_cli = 0; break;
2095   case 'o': handler = iauth_cmd_username_forced; has_cli = 1; break;
2096   case 'U': handler = iauth_cmd_username_good; has_cli = 1; break;
2097   case 'u': handler = iauth_cmd_username_bad; has_cli = 1; break;
2098   case 'N': handler = iauth_cmd_hostname; has_cli = 1; break;
2099   case 'I': handler = iauth_cmd_ip_address; has_cli = 1; break;
2100   case 'M': handler = iauth_cmd_usermode; has_cli = 1; break;
2101   case 'C': handler = iauth_cmd_challenge; has_cli = 1; break;
2102   case 'D': handler = iauth_cmd_done_client; has_cli = 1; break;
2103   case 'R': handler = iauth_cmd_done_account; has_cli = 1; break;
2104   case 'k': /* The 'k' command indicates the user should be booted
2105              * off without telling opers.  There is no way to
2106              * signal that to exit_client(), so we fall through to
2107              * the case that we do implement.
2108              */
2109   case 'K': handler = iauth_cmd_kill; has_cli = 2; break;
2110   case 'r': /* we handle termination directly */ return;
2111   default:  sendto_iauth(NULL, "E Garbage :[%s]", message); return;
2112   }
2113
2114   while (parc < MAXPARA) {
2115     while (IsSpace(*message)) /* skip leading whitespace */
2116       message++;
2117
2118     if (!*message) /* hit the end of the string, break out */
2119       break;
2120
2121     if (*message == ':') { /* found sentinel... */
2122       params[parc++] = message + 1;
2123       break; /* it's the last parameter anyway */
2124     }
2125
2126     params[parc++] = message; /* save the parameter */
2127     while (*message && !IsSpace(*message))
2128       message++; /* find the end of the parameter */
2129
2130     if (*message) /* terminate the parameter */
2131       *(message++) = '\0';
2132   }
2133
2134   params[parc] = NULL; /* terminate the parameter list */
2135
2136   /* Check to see if the command specifies a client... */
2137   if (!has_cli) {
2138     /* Handler does not need a client. */
2139     handler(iauth, NULL, parc, params);
2140   } else {
2141     /* Try to find the client associated with the request. */
2142     id = strtol(params[0], NULL, 10);
2143     if (parc < 3)
2144       sendto_iauth(NULL, "E Missing :Need <id> <ip> <port>");
2145     else if (id < 0 || id > HighestFd || !(cli = LocalClientArray[id]))
2146       /* Client no longer exists (or never existed). */
2147       sendto_iauth(NULL, "E Gone :[%s %s %s]", params[0], params[1],
2148                    params[2]);
2149     else if ((!(auth = cli_auth(cli)) ||
2150               !FlagHas(&auth->flags, AR_IAUTH_PENDING)) &&
2151              has_cli == 1)
2152       /* Client is done with IAuth checks. */
2153       sendto_iauth(cli, "E Done :[%s %s %s]", params[0], params[1], params[2]);
2154     else {
2155       struct irc_sockaddr addr;
2156       int res;
2157
2158       /* Parse IP address and port number from parameters */
2159       res = ipmask_parse(params[1], &addr.addr, NULL);
2160       addr.port = strtol(params[2], NULL, 10);
2161
2162       /* Check IP address and port number against expected. */
2163       if (0 == res ||
2164           irc_in_addr_cmp(&addr.addr, &cli_ip(cli)) ||
2165           (auth && addr.port != auth->port))
2166         /* Report mismatch to iauth. */
2167         sendto_iauth(cli, "E Mismatch :[%s] != [%s]", params[1],
2168                      ircd_ntoa(&cli_ip(cli)));
2169       else if (handler(iauth, cli, parc - 3, params + 3) > 0)
2170         /* Handler indicated a possible state change. */
2171         check_auth_finished(auth);
2172     }
2173   }
2174 }
2175
2176 /** Read input from \a iauth.
2177  * Reads up to SERVER_TCP_WINDOW bytes per pass.
2178  * @param[in] iauth Readable connection.
2179  */
2180 static void iauth_read(struct IAuth *iauth)
2181 {
2182   static char readbuf[SERVER_TCP_WINDOW];
2183   unsigned int length, count;
2184   char *sol;
2185   char *eol;
2186
2187   /* Copy partial data to readbuf, append new data. */
2188   length = iauth->i_count;
2189   memcpy(readbuf, iauth->i_buffer, length);
2190   if (IO_SUCCESS != os_recv_nonb(s_fd(i_socket(iauth)),
2191                                  readbuf + length,
2192                                  sizeof(readbuf) - length - 1,
2193                                  &count))
2194     return;
2195   readbuf[length += count] = '\0';
2196
2197   /* Parse each complete line. */
2198   for (sol = readbuf; (eol = strchr(sol, '\n')) != NULL; sol = eol + 1) {
2199     *eol = '\0';
2200     if (*(eol - 1) == '\r') /* take out carriage returns, too... */
2201       *(eol - 1) = '\0';
2202
2203     /* If spammy debug, send the message to opers. */
2204     if (i_debug(iauth) > 1)
2205       sendto_opmask_butone(NULL, SNO_AUTH, "Parsing: \"%s\"", sol);
2206
2207     /* Parse the line... */
2208     iauth_parse(iauth, sol);
2209   }
2210
2211   /* Put unused data back into connection's buffer. */
2212   iauth->i_count = strlen(sol);
2213   if (iauth->i_count > BUFSIZE)
2214     iauth->i_count = BUFSIZE;
2215   memcpy(iauth->i_buffer, sol, iauth->i_count);
2216 }
2217
2218 /** Handle socket activity for an %IAuth connection.
2219  * @param[in] ev &Socket event; the IAuth connection is the user data
2220  *   pointer for the socket.
2221  */
2222 static void iauth_sock_callback(struct Event *ev)
2223 {
2224   struct IAuth *iauth;
2225
2226   assert(0 != ev_socket(ev));
2227   iauth = (struct IAuth*) s_data(ev_socket(ev));
2228   assert(0 != iauth);
2229
2230   switch (ev_type(ev)) {
2231   case ET_DESTROY:
2232     /* Hm, what happened here? */
2233     if (!IAuthHas(iauth, IAUTH_CLOSING))
2234       iauth_do_spawn(iauth, 1);
2235     break;
2236   case ET_READ:
2237     iauth_read(iauth);
2238     break;
2239   case ET_WRITE:
2240     IAuthClr(iauth, IAUTH_BLOCKED);
2241     iauth_write(iauth);
2242     break;
2243   case ET_ERROR:
2244     log_write(LS_IAUTH, L_ERROR, 0, "IAuth socket error: %s", strerror(ev_data(ev)));
2245     /* and fall through to the ET_EOF case */
2246   case ET_EOF:
2247     iauth_disconnect(iauth);
2248     break;
2249   default:
2250     assert(0 && "Unrecognized event type");
2251     break;
2252   }
2253 }
2254
2255 /** Read error input from \a iauth.
2256  * @param[in] iauth Readable connection.
2257  */
2258 static void iauth_read_stderr(struct IAuth *iauth)
2259 {
2260   static char readbuf[SERVER_TCP_WINDOW];
2261   unsigned int length, count;
2262   char *sol;
2263   char *eol;
2264
2265   /* Copy partial data to readbuf, append new data. */
2266   length = iauth->i_errcount;
2267   memcpy(readbuf, iauth->i_errbuf, length);
2268   if (IO_SUCCESS != os_recv_nonb(s_fd(i_stderr(iauth)),
2269                                  readbuf + length,
2270                                  sizeof(readbuf) - length - 1,
2271                                  &count))
2272     return;
2273   readbuf[length += count] = '\0';
2274
2275   /* Send each complete line to SNO_AUTH. */
2276   for (sol = readbuf; (eol = strchr(sol, '\n')) != NULL; sol = eol + 1) {
2277     *eol = '\0';
2278     if (*(eol - 1) == '\r') /* take out carriage returns, too... */
2279       *(eol - 1) = '\0';
2280     Debug((DEBUG_ERROR, "IAuth error: %s", sol));
2281     log_write(LS_IAUTH, L_ERROR, 0, "IAuth error: %s", sol);
2282     sendto_opmask_butone(NULL, SNO_AUTH, "%s", sol);
2283   }
2284
2285   /* Put unused data back into connection's buffer. */
2286   iauth->i_errcount = strlen(sol);
2287   if (iauth->i_errcount > BUFSIZE)
2288     iauth->i_errcount = BUFSIZE;
2289   memcpy(iauth->i_errbuf, sol, iauth->i_errcount);
2290 }
2291
2292 /** Handle error socket activity for an %IAuth connection.
2293  * @param[in] ev &Socket event; the IAuth connection is the user data
2294  *   pointer for the socket.
2295  */
2296 static void iauth_stderr_callback(struct Event *ev)
2297 {
2298   struct IAuth *iauth;
2299
2300   assert(0 != ev_socket(ev));
2301   iauth = (struct IAuth*) s_data(ev_socket(ev));
2302   assert(0 != iauth);
2303
2304   switch (ev_type(ev)) {
2305   case ET_DESTROY:
2306     /* We do not restart iauth here: the stdout handler does that for us. */
2307     break;
2308   case ET_READ:
2309     iauth_read_stderr(iauth);
2310     break;
2311   case ET_ERROR:
2312     log_write(LS_IAUTH, L_ERROR, 0, "IAuth stderr error: %s", strerror(ev_data(ev)));
2313     /* and fall through to the ET_EOF case */
2314   case ET_EOF:
2315     iauth_disconnect(iauth);
2316     break;
2317   default:
2318     assert(0 && "Unrecognized event type");
2319     break;
2320   }
2321 }
2322
2323 /** Report active iauth's configuration to \a cptr.
2324  * @param[in] cptr Client requesting statistics.
2325  * @param[in] sd Stats descriptor for request.
2326  * @param[in] param Extra parameter from user (may be NULL).
2327  */
2328 void report_iauth_conf(struct Client *cptr, const struct StatDesc *sd, char *param)
2329 {
2330     struct SLink *link;
2331
2332     if (iauth) for (link = iauth->i_config; link; link = link->next)
2333     {
2334         send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":%s",
2335                    link->value.cp);
2336     }
2337 }
2338
2339 /** Report active iauth's statistics to \a cptr.
2340  * @param[in] cptr Client requesting statistics.
2341  * @param[in] sd Stats descriptor for request.
2342  * @param[in] param Extra parameter from user (may be NULL).
2343  */
2344  void report_iauth_stats(struct Client *cptr, const struct StatDesc *sd, char *param)
2345 {
2346     struct SLink *link;
2347
2348     if (iauth) for (link = iauth->i_stats; link; link = link->next)
2349     {
2350         send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":%s",
2351                    link->value.cp);
2352     }
2353 }