]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc-login.c
Simplify check for valid user names in IRC_USER().
[ngircd-alex.git] / src / ngircd / irc-login.c
index edaefd61cfc119fbd26de3a26d55eb65bc0146d0..99cd26f45818a1fa3a42bb36c67f58a4c7ac86b2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "imp.h"
 #include <assert.h>
-#include <stdio.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
-#include <signal.h>
-#include <unistd.h>
 
-#include "ngircd.h"
 #include "conn-func.h"
+#include "class.h"
 #include "conf.h"
 #include "channel.h"
-#include "io.h"
 #include "log.h"
+#include "login.h"
 #include "messages.h"
-#include "pam.h"
 #include "parse.h"
 #include "irc.h"
 #include "irc-info.h"
 #include "exp.h"
 #include "irc-login.h"
 
-
-static bool Hello_User PARAMS(( CLIENT *Client ));
-static bool Hello_User_PostAuth PARAMS(( CLIENT *Client ));
 static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
-static void Introduce_Client PARAMS((CLIENT *To, CLIENT *Client, int Type));
-static void Reject_Client PARAMS((CLIENT *Client));
-
-static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix,
-                                      void *i));
-
-#ifdef PAM
-static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
-#endif
 
 /**
  * Handler for the IRC "PASS" command.
@@ -103,7 +88,7 @@ IRC_PASS( CLIENT *Client, REQUEST *Req )
                                          Client_ID(Client));
        }
 
-       Client_SetPassword(Client, Req->argv[0]);
+       Conn_SetPassword(Client_Conn(Client), Req->argv[0]);
 
        /* Protocol version */
        if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) {
@@ -285,7 +270,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
                        /* If we received a valid USER command already then
                         * register the new client! */
                        if( Client_Type( Client ) == CLIENT_GOTUSER )
-                               return Hello_User( Client );
+                               return Login_User( Client );
                        else
                                Client_SetType( Client, CLIENT_GOTNICK );
                } else {
@@ -395,7 +380,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
                                 Client_Mask(c));
                        Client_SetType(c, CLIENT_GOTNICK);
                } else
-                       Introduce_Client(Client, c, CLIENT_USER);
+                       Client_Introduce(Client, c, CLIENT_USER);
 
                return CONNECTED;
        }
@@ -416,9 +401,7 @@ GLOBAL bool
 IRC_USER(CLIENT * Client, REQUEST * Req)
 {
        CLIENT *c;
-#ifdef IDENTAUTH
        char *ptr;
-#endif
 
        assert(Client != NULL);
        assert(Req != NULL);
@@ -436,7 +419,20 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
                                                  Client_ID(Client),
                                                  Req->command);
 
-               /* User name */
+               /* User name: only alphanumeric characters and limited
+                  punctuation is allowed.*/
+               ptr = Req->argv[0];
+               while (*ptr) {
+                       if (!isalnum(*ptr) &&
+                           *ptr != '+' && *ptr != '-' &&
+                           *ptr != '.' && *ptr != '_') {
+                               Conn_Close(Client_Conn(Client), NULL,
+                                          "Invalid user name", true);
+                               return DISCONNECTED;
+                       }
+                       ptr++;
+               }
+
 #ifdef IDENTAUTH
                ptr = Client_User(Client);
                if (!ptr || !*ptr || *ptr == '~')
@@ -457,7 +453,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
                LogDebug("Connection %d: got valid USER command ...",
                    Client_Conn(Client));
                if (Client_Type(Client) == CLIENT_GOTNICK)
-                       return Hello_User(Client);
+                       return Login_User(Client);
                else
                        Client_SetType(Client, CLIENT_GOTUSER);
                return CONNECTED;
@@ -487,7 +483,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
                /* RFC 1459 style user registration?
                 * Introduce client to network: */
                if (Client_Type(c) == CLIENT_GOTNICK)
-                       Introduce_Client(Client, c, CLIENT_USER);
+                       Client_Introduce(Client, c, CLIENT_USER);
 
                return CONNECTED;
        } else if (Client_Type(Client) == CLIENT_USER) {
@@ -601,7 +597,7 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
                return CONNECTED;
        }
 
-       Introduce_Client(Client, c, CLIENT_SERVICE);
+       Client_Introduce(Client, c, CLIENT_SERVICE);
        return CONNECTED;
 } /* IRC_SERVICE */
 
@@ -880,7 +876,7 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
                if (auth_ping == atoi(Req->argv[0])) {
                        Conn_SetAuthPing(conn, 0);
                        if (Client_Type(Client) == CLIENT_WAITAUTHPING)
-                               Hello_User(Client);
+                               Login_User(Client);
                } else
                        if (!IRC_WriteStrClient(Client,
                                        "To connect, type /QUOTE PONG %ld",
@@ -889,210 +885,18 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
        }
 #endif
 
-#ifdef DEBUG
-       if (conn > NONE)
-               Log(LOG_DEBUG,
-                       "Connection %d: received PONG. Lag: %ld seconds.", conn,
-                       time(NULL) - Conn_LastPing(Client_Conn(Client)));
-       else
-                Log(LOG_DEBUG,
-                       "Connection %d: received PONG.", conn);
-#endif
-       return CONNECTED;
-} /* IRC_PONG */
-
-
-/**
- * Initiate client registration.
- *
- * This function is called after the daemon received the required NICK and
- * USER commands of a new client. If the daemon is compiled with support for
- * PAM, the authentication sub-processs is forked; otherwise the global server
- * password is checked.
- *
- * @param Client       The client logging in.
- * @returns            CONNECTED or DISCONNECTED.
- */
-static bool
-Hello_User(CLIENT * Client)
-{
-#ifdef PAM
-       int pipefd[2], result;
-       pid_t pid;
-#endif
-       CONN_ID conn;
-
-       assert(Client != NULL);
-       conn = Client_Conn(Client);
-
-#ifndef STRICT_RFC
-       if (Conf_AuthPing) {
-               /* Did we receive the "auth PONG" already? */
-               if (Conn_GetAuthPing(conn)) {
-                       Client_SetType(Client, CLIENT_WAITAUTHPING);
-                       LogDebug("Connection %d: Waiting for AUTH PONG ...", conn);
-                       return CONNECTED;
-               }
-       }
-#endif
-
-#ifdef PAM
-       if (!Conf_PAM) {
-               /* Don't do any PAM authentication at all, instead emulate
-                * the beahiour of the daemon compiled without PAM support:
-                * because there can't be any "server password", all
-                * passwords supplied are classified as "wrong". */
-               if(Client_Password(Client)[0] == '\0')
-                       return Hello_User_PostAuth(Client);
-               Reject_Client(Client);
-               return DISCONNECTED;
-       }
-
-       /* Fork child process for PAM authentication; and make sure that the
-        * process timeout is set higher than the login timeout! */
-       pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
-                       cb_Read_Auth_Result, Conf_PongTimeout + 1);
-       if (pid > 0) {
-               LogDebug("Authenticator for connection %d created (PID %d).",
-                        conn, pid);
-               return CONNECTED;
-       } else {
-               /* Sub process */
-               Log_Init_Subprocess("Auth");
-               result = PAM_Authenticate(Client);
-               if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
-                       Log_Subprocess(LOG_ERR,
-                                      "Failed to pipe result to parent!");
-               Log_Exit_Subprocess("Auth");
-               exit(0);
-       }
-#else
-       /* Check global server password ... */
-       if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
-               /* Bad password! */
-               Reject_Client(Client);
-               return DISCONNECTED;
-       }
-       return Hello_User_PostAuth(Client);
-#endif
-}
-
-
-#ifdef PAM
-
-/**
- * Read result of the authenticatior sub-process from pipe
- *
- * @param r_fd         File descriptor of the pipe.
- * @param events       (ignored IO specification)
- */
-static void
-cb_Read_Auth_Result(int r_fd, UNUSED short events)
-{
-       CONN_ID conn;
-       CLIENT *client;
-       int result;
-       size_t len;
-       PROC_STAT *proc;
-
-       LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events);
-       conn = Conn_GetFromProc(r_fd);
-       if (conn == NONE) {
-               /* Ops, none found? Probably the connection has already
-                * been closed!? We'll ignore that ... */
-               io_close(r_fd);
-               LogDebug("Auth: Got callback for unknown connection!?");
-               return;
-       }
-       proc = Conn_GetProcStat(conn);
-       client = Conn_GetClient(conn);
-
-       /* Read result from pipe */
-       len = Proc_Read(proc, &result, sizeof(result));
-       if (len == 0)
-               return;
-
-       if (len != sizeof(result)) {
-               Log(LOG_CRIT, "Auth: Got malformed result!");
-               Reject_Client(client);
-               return;
-       }
-
-       if (result == true) {
-               Client_SetUser(client, Client_OrigUser(client), true);
-               (void)Hello_User_PostAuth(client);
+       if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
+               Log(LOG_INFO,
+                   "Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
+                   Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
+                   Client_UserCount(), Channel_CountVisible(NULL));
+               Conn_UpdatePing(conn);
        } else
-               Reject_Client(client);
-}
-
-#endif
-
-
-/**
- * Reject a client because of wrong password.
- *
- * This function is called either when the global server password or a password
- * checked using PAM has been wrong.
- *
- * @param Client       The client to reject.
- */
-static void
-Reject_Client(CLIENT *Client)
-{
-       Log(LOG_ERR,
-           "User \"%s\" rejected (connection %d): Access denied!",
-           Client_Mask(Client), Client_Conn(Client));
-       Conn_Close(Client_Conn(Client), NULL,
-                  "Access denied! Bad password?", true);
-}
-
-
-/**
- * Finish client registration.
- *
- * Introduce the new client to the network and send all "hello messages"
- * to it after authentication has been succeeded.
- *
- * @param Client       The client logging in.
- * @returns            CONNECTED or DISCONNECTED.
- */
-static bool
-Hello_User_PostAuth(CLIENT *Client)
-{
-       Introduce_Client(NULL, Client, CLIENT_USER);
-
-       if (!IRC_WriteStrClient
-           (Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
-               return false;
-       if (!IRC_WriteStrClient
-           (Client, RPL_YOURHOST_MSG, Client_ID(Client),
-            Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU,
-            TARGET_VENDOR, TARGET_OS))
-               return false;
-       if (!IRC_WriteStrClient
-           (Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr))
-               return false;
-       if (!IRC_WriteStrClient
-           (Client, RPL_MYINFO_MSG, Client_ID(Client),
-            Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES,
-            CHANMODES))
-               return false;
-
-       /* Features supported by this server (005 numeric, ISUPPORT),
-        * see <http://www.irc.org/tech_docs/005.html> for details. */
-       if (!IRC_Send_ISUPPORT(Client))
-               return DISCONNECTED;
-
-       if (!IRC_Send_LUSERS(Client))
-               return DISCONNECTED;
-       if (!IRC_Show_MOTD(Client))
-               return DISCONNECTED;
-
-       /* Suspend the client for a second ... */
-       IRC_SetPenalty(Client, 1);
+               LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
+                        conn, time(NULL) - Conn_LastPing(conn));
 
        return CONNECTED;
-}
+} /* IRC_PONG */
 
 
 /**
@@ -1121,97 +925,4 @@ Kill_Nick(char *Nick, char *Reason)
 } /* Kill_Nick */
 
 
-/**
- * Introduce a new user or service client in the network.
- *
- * @param From         Remote server introducing the client or NULL (local).
- * @param Client       New client.
- * @param Type         Type of the client (CLIENT_USER or CLIENT_SERVICE).
- */
-static void
-Introduce_Client(CLIENT *From, CLIENT *Client, int Type)
-{
-       /* Set client type (user or service) */
-       Client_SetType(Client, Type);
-
-       if (From) {
-               if (Conf_IsService(Conf_GetServer(Client_Conn(From)),
-                                  Client_ID(Client)))
-                       Client_SetType(Client, CLIENT_SERVICE);
-               LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).",
-                        Client_TypeText(Client), Client_Mask(Client),
-                        Client_Modes(Client), Client_ID(From),
-                        Client_ID(Client_Introducer(Client)),
-                        Client_Hops(Client), Client_Hops(Client) > 1 ? "s": "");
-       } else {
-               Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).",
-                   Client_TypeText(Client), Client_Mask(Client),
-                   Client_Conn(Client));
-               Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s",
-                                Client_ID(Client), Client_User(Client),
-                                Client_Hostname(Client),
-                                Conn_IPA(Client_Conn(Client)),
-                                Client_TypeText(Client));
-       }
-
-       /* Inform other servers */
-       IRC_WriteStrServersPrefixFlag_CB(From,
-                               From != NULL ? From : Client_ThisServer(),
-                               '\0', cb_introduceClient, (void *)Client);
-} /* Introduce_Client */
-
-
-/**
- * Introduce a new user or service client to a remote server.
- *
- * This function differentiates between RFC1459 and RFC2813 server links and
- * generates the appropriate commands to register the new user or service.
- *
- * @param To           The remote server to inform.
- * @param Prefix       Prefix for the generated commands.
- * @param data         CLIENT structure of the new client.
- */
-static void
-cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data)
-{
-       CLIENT *c = (CLIENT *)data;
-       CONN_ID conn;
-       char *modes, *user, *host;
-
-       modes = Client_Modes(c);
-       user = Client_User(c) ? Client_User(c) : "-";
-       host = Client_Hostname(c) ? Client_Hostname(c) : "-";
-
-       conn = Client_Conn(To);
-       if (Conn_Options(conn) & CONN_RFC1459) {
-               /* RFC 1459 mode: separate NICK and USER commands */
-               Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c),
-                             Client_Hops(c) + 1);
-               Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
-                             Client_ID(c), user, host,
-                             Client_ID(Client_Introducer(c)), Client_Info(c));
-               if (modes[0])
-                       Conn_WriteStr(conn, ":%s MODE %s +%s",
-                                     Client_ID(c), Client_ID(c), modes);
-       } else {
-               /* RFC 2813 mode: one combined NICK or SERVICE command */
-               if (Client_Type(c) == CLIENT_SERVICE
-                   && strchr(Client_Flags(To), 'S'))
-                       IRC_WriteStrClientPrefix(To, Prefix,
-                                        "SERVICE %s %d * +%s %d :%s",
-                                        Client_Mask(c),
-                                        Client_MyToken(Client_Introducer(c)),
-                                        Client_Modes(c), Client_Hops(c) + 1,
-                                        Client_Info(c));
-               else
-                       IRC_WriteStrClientPrefix(To, Prefix,
-                                        "NICK %s %d %s %s %d +%s :%s",
-                                        Client_ID(c), Client_Hops(c) + 1,
-                                        user, host,
-                                        Client_MyToken(Client_Introducer(c)),
-                                        modes, Client_Info(c));
-       }
-} /* cb_introduceClient */
-
-
 /* -eof- */