about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ngircd/Makefile.am2
-rw-r--r--src/ngircd/irc-login.c210
-rw-r--r--src/ngircd/login.c234
-rw-r--r--src/ngircd/login.h25
4 files changed, 265 insertions, 206 deletions
diff --git a/src/ngircd/Makefile.am b/src/ngircd/Makefile.am
index cacd1c3c..e96d14be 100644
--- a/src/ngircd/Makefile.am
+++ b/src/ngircd/Makefile.am
@@ -42,6 +42,7 @@ ngircd_SOURCES = \
 	irc-write.c \
 	lists.c \
 	log.c \
+	login.c \
 	match.c \
 	numeric.c \
 	op.c \
@@ -81,6 +82,7 @@ noinst_HEADERS = \
 	irc-write.h \
 	lists.h \
 	log.h \
+	login.h \
 	match.h \
 	messages.h \
 	numeric.h \
diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c
index 53069f00..bf3254c9 100644
--- a/src/ngircd/irc-login.c
+++ b/src/ngircd/irc-login.c
@@ -18,22 +18,16 @@
 
 #include "imp.h"
 #include <assert.h>
-#include <stdio.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"
@@ -42,13 +36,7 @@
 #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 ));
-#ifdef PAM
-static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
-#endif
 
 /**
  * Handler for the IRC "PASS" command.
@@ -280,7 +268,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 {
@@ -452,7 +440,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;
@@ -875,7 +863,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",
@@ -899,196 +887,6 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
 
 
 /**
- * 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);
-		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,
-			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");
-		Conn_CloseAllSockets(NONE);
-		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! */
-		Client_Reject(Client, "Bad server password", false);
-		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));
-	Proc_Close(proc);
-	if (len == 0)
-		return;
-
-	if (len != sizeof(result)) {
-		Log(LOG_CRIT, "Auth: Got malformed result!");
-		Client_Reject(client, "Internal error", false);
-		return;
-	}
-
-	if (result == true) {
-		Client_SetUser(client, Client_OrigUser(client), true);
-		(void)Hello_User_PostAuth(client);
-	} else
-		Client_Reject(client, "Bad password", false);
-}
-
-#endif
-
-
-/**
- * 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)
-{
-	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)))
-		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);
-
-	return CONNECTED;
-}
-
-
-/**
  * Kill all users with a specific nick name in the network.
  *
  * @param Nick		Nick name.
diff --git a/src/ngircd/login.c b/src/ngircd/login.c
new file mode 100644
index 00000000..2c305402
--- /dev/null
+++ b/src/ngircd/login.c
@@ -0,0 +1,234 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2012 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+#include "portab.h"
+
+/**
+ * @file
+ * Functions to deal with client logins
+ */
+
+#include "imp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "class.h"
+#include "client.h"
+#include "channel.h"
+#include "conf.h"
+#include "io.h"
+#include "parse.h"
+#include "log.h"
+#include "messages.h"
+#include "ngircd.h"
+#include "pam.h"
+#include "irc-info.h"
+#include "irc-write.h"
+
+#include "exp.h"
+#include "login.h"
+
+#ifdef PAM
+static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
+#endif
+
+/**
+ * Initiate client login.
+ *
+ * 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.
+ */
+GLOBAL bool
+Login_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 Login_User_PostAuth(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 Login_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,
+			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");
+		Conn_CloseAllSockets(NONE);
+		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! */
+		Client_Reject(Client, "Bad server password", false);
+		return DISCONNECTED;
+	}
+	return Login_User_PostAuth(Client);
+#endif
+}
+
+/**
+ * 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.
+ * @return CONNECTED or DISCONNECTED.
+ */
+GLOBAL bool
+Login_User_PostAuth(CLIENT *Client)
+{
+	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)))
+		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);
+
+	return CONNECTED;
+}
+
+#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));
+	Proc_Close(proc);
+	if (len == 0)
+		return;
+
+	if (len != sizeof(result)) {
+		Log(LOG_CRIT, "Auth: Got malformed result!");
+		Client_Reject(client, "Internal error", false);
+		return;
+	}
+
+	if (result == true) {
+		Client_SetUser(client, Client_OrigUser(client), true);
+		(void)Login_User_PostAuth(client);
+	} else
+		Client_Reject(client, "Bad password", false);
+}
+
+#endif
+
+/* -eof- */
diff --git a/src/ngircd/login.h b/src/ngircd/login.h
new file mode 100644
index 00000000..6e3a21d6
--- /dev/null
+++ b/src/ngircd/login.h
@@ -0,0 +1,25 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2012 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+#ifndef __login_h__
+#define __login_h__
+
+/**
+ * @file
+ * Functions to deal with client logins (header)
+ */
+
+GLOBAL bool Login_User PARAMS((CLIENT * Client));
+GLOBAL bool Login_User_PostAuth PARAMS((CLIENT *Client));
+
+#endif
+
+/* -eof- */