]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/irc-login.c
Introduce_Client() => Client_Introduce(), and move it to client.c
[ngircd-alex.git] / src / ngircd / irc-login.c
index 2e99d66eeade7dfa36c25b6dd36f88a9c94f1c1e..53069f00ff24c7e749db0e18a53f0d65ccbfc1d4 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
@@ -27,6 +27,7 @@
 
 #include "ngircd.h"
 #include "conn-func.h"
+#include "class.h"
 #include "conf.h"
 #include "channel.h"
 #include "io.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
@@ -273,7 +268,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
 
 #ifndef STRICT_RFC
                        if (Conf_AuthPing) {
-                               Conn_SetAuthPing(Client_Conn(Client), random());
+                               Conn_SetAuthPing(Client_Conn(Client), rand());
                                IRC_WriteStrClient(Client, "PING :%ld",
                                        Conn_GetAuthPing(Client_Conn(Client)));
                                LogDebug("Connection %d: sent AUTH PING %ld ...",
@@ -395,7 +390,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;
        }
@@ -487,7 +482,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 +596,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 */
 
@@ -653,32 +648,37 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
        CLIENT *target;
        char quitmsg[LINE_LEN];
 
-       assert( Client != NULL );
-       assert( Req != NULL );
+       assert(Client != NULL);
+       assert(Req != NULL);
 
        /* Wrong number of arguments? */
-       if( Req->argc > 1 )
-               return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+       if (Req->argc > 1)
+               return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+                                         Client_ID(Client), Req->command);
 
        if (Req->argc == 1)
                strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
 
-       if ( Client_Type( Client ) == CLIENT_SERVER )
-       {
+       if (Client_Type(Client) == CLIENT_SERVER) {
                /* Server */
-               target = Client_Search( Req->prefix );
-               if( ! target )
-               {
-                       Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
+               target = Client_Search(Req->prefix);
+               if (!target) {
+                       Log(LOG_WARNING,
+                           "Got QUIT from %s for unknown client!?",
+                           Client_ID(Client));
                        return CONNECTED;
                }
 
-               Client_Destroy( target, "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
-
-               return CONNECTED;
-       }
-       else
-       {
+               if (target != Client) {
+                       Client_Destroy(target, "Got QUIT command.",
+                                      Req->argc == 1 ? quitmsg : NULL, true);
+                       return CONNECTED;
+               } else {
+                       Conn_Close(Client_Conn(Client), "Got QUIT command.",
+                                  Req->argc == 1 ? quitmsg : NULL, true);
+                       return DISCONNECTED;
+               }
+       } else {
                if (Req->argc == 1 && quitmsg[0] != '\"') {
                        /* " " to avoid confusion */
                        strlcpy(quitmsg, "\"", sizeof quitmsg);
@@ -687,7 +687,8 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
                }
 
                /* User, Service, or not yet registered */
-               Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
+               Conn_Close(Client_Conn(Client), "Got QUIT command.",
+                          Req->argc == 1 ? quitmsg : NULL, true);
 
                return DISCONNECTED;
        }
@@ -883,15 +884,16 @@ 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
+       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
+               LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
+                        conn, time(NULL) - Conn_LastPing(conn));
+
        return CONNECTED;
 } /* IRC_PONG */
 
@@ -938,10 +940,19 @@ Hello_User(CLIENT * Client)
                 * passwords supplied are classified as "wrong". */
                if(Client_Password(Client)[0] == '\0')
                        return Hello_User_PostAuth(Client);
-               Reject_Client(Client);
+               Client_Reject(Client, "Non-empty password", false);
                return DISCONNECTED;
        }
 
+       if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) {
+               /* Clients are not required to send a password and to be PAM-
+                * authenticated at all. If not, they won't become "identified"
+                * and keep the "~" in their supplied user name.
+                * Therefore it is sensible to either set Conf_PAMisOptional or
+                * to enable IDENT lookups -- not both. */
+               return Hello_User_PostAuth(Client);
+       }
+
        /* 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,
@@ -953,6 +964,7 @@ Hello_User(CLIENT * Client)
        } else {
                /* Sub process */
                Log_Init_Subprocess("Auth");
+               Conn_CloseAllSockets(NONE);
                result = PAM_Authenticate(Client);
                if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
                        Log_Subprocess(LOG_ERR,
@@ -964,7 +976,7 @@ Hello_User(CLIENT * Client)
        /* Check global server password ... */
        if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
                /* Bad password! */
-               Reject_Client(Client);
+               Client_Reject(Client, "Bad server password", false);
                return DISCONNECTED;
        }
        return Hello_User_PostAuth(Client);
@@ -1003,12 +1015,13 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
 
        /* Read result from pipe */
        len = Proc_Read(proc, &result, sizeof(result));
+       Proc_Close(proc);
        if (len == 0)
                return;
 
        if (len != sizeof(result)) {
                Log(LOG_CRIT, "Auth: Got malformed result!");
-               Reject_Client(client);
+               Client_Reject(client, "Internal error", false);
                return;
        }
 
@@ -1016,31 +1029,12 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
                Client_SetUser(client, Client_OrigUser(client), true);
                (void)Hello_User_PostAuth(client);
        } else
-               Reject_Client(client);
+               Client_Reject(client, "Bad password", false);
 }
 
 #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.
  *
@@ -1053,7 +1047,12 @@ Reject_Client(CLIENT *Client)
 static bool
 Hello_User_PostAuth(CLIENT *Client)
 {
-       Introduce_Client(NULL, Client, CLIENT_USER);
+       assert(Client != NULL);
+
+       if (Class_HandleServerBans(Client) != CONNECTED)
+               return DISCONNECTED;
+
+       Client_Introduce(NULL, Client, CLIENT_USER);
 
        if (!IRC_WriteStrClient
            (Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
@@ -1096,114 +1095,23 @@ Hello_User_PostAuth(CLIENT *Client)
  * @param Reason       Reason for the KILL.
  */
 static void
-Kill_Nick( char *Nick, char *Reason )
+Kill_Nick(char *Nick, char *Reason)
 {
        REQUEST r;
 
-       assert( Nick != NULL );
-       assert( Reason != NULL );
+       assert (Nick != NULL);
+       assert (Reason != NULL);
 
-       r.prefix = (char *)Client_ThisServer( );
+       r.prefix = NULL;
        r.argv[0] = Nick;
        r.argv[1] = Reason;
        r.argc = 2;
 
-       Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
-       IRC_KILL( Client_ThisServer( ), &r );
-} /* Kill_Nick */
-
+       Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
+           Nick, Reason);
 
-/**
- * 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 */
+       IRC_KILL(Client_ThisServer(), &r);
+} /* Kill_Nick */
 
 
 /* -eof- */