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