X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-login.c;h=078954024a887bf1495ee8a0672e01530c93359f;hp=2de4bd584bec73e4a081d284a67c5d52332b5392;hb=f369177617a0f54e34a1af6fa44d1d1e3f953aeb;hpb=6e8cf51bb216f956e7a6fdb5c61b0f2799bf8d2d diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index 2de4bd58..07895402 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -20,15 +20,17 @@ #include #include #include +#include +#include #include "ngircd.h" -#include "resolve.h" #include "conn-func.h" #include "conf.h" -#include "client.h" #include "channel.h" +#include "io.h" #include "log.h" #include "messages.h" +#include "pam.h" #include "parse.h" #include "irc.h" #include "irc-info.h" @@ -39,11 +41,17 @@ 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 command "PASS". @@ -356,7 +364,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) * RFC 1459: announce the new client only after receiving the * USER command, first we need more information! */ if (Req->argc < 7) { - LogDebug("Client \"%s\" is beeing registered (RFC 1459) ...", + LogDebug("Client \"%s\" is being registered (RFC 1459) ...", Client_Mask(c)); Client_SetType(c, CLIENT_GOTNICK); } else @@ -403,6 +411,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req) #else Client_SetUser(Client, Req->argv[0], false); #endif + Client_SetOrigUser(Client, Req->argv[0]); /* "Real name" or user info text: Don't set it to the empty * string, the original ircd can't deal with such "real names" @@ -435,6 +444,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req) Req->prefix); Client_SetUser(c, Req->argv[0], true); + Client_SetOrigUser(c, Req->argv[0]); Client_SetHostname(c, Req->argv[1]); Client_SetInfo(c, Req->argv[3]); @@ -577,6 +587,7 @@ IRC_WEBIRC(CLIENT *Client, REQUEST *Req) Client_Conn(Client), Req->argv[1], Req->argv[2], Req->argv[3]); Client_SetUser(Client, Req->argv[1], true); + Client_SetOrigUser(Client, Req->argv[1]); Client_SetHostname(Client, Req->argv[2]); return CONNECTED; } /* IRC_WEBIRC */ @@ -759,18 +770,108 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) static bool Hello_User(CLIENT * Client) { +#ifdef PAM + int pipefd[2], result; + CONN_ID conn; + pid_t pid; + + assert(Client != NULL); + conn = Client_Conn(Client); + + pid = Proc_Fork(Conn_GetProcStat(conn), pipefd, cb_Read_Auth_Result); + if (pid > 0) { + LogDebug("Authenticator for connection %d created (PID %d).", + conn, pid); + return CONNECTED; + } else { + /* Sub process */ + signal(SIGTERM, Proc_GenericSignalHandler); + Log_Init_Subprocess("Auth"); + if (Conf_NoPAM) { + result = (Client_Password(Client)[0] == '\0'); + } else + result = PAM_Authenticate(Client); + write(pipefd[1], &result, sizeof(result)); + Log_Exit_Subprocess("Auth"); + exit(0); + } +#else assert(Client != NULL); - /* Check password ... */ + /* Check global server password ... */ if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) { /* Bad password! */ - Log(LOG_ERR, - "Client \"%s\" rejected (connection %d): Bad password!", - Client_Mask(Client), Client_Conn(Client)); - Conn_Close(Client_Conn(Client), NULL, "Bad password", true); + Reject_Client(Client); return DISCONNECTED; } + return Hello_User_PostAuth(Client); +#endif +} + +#ifdef PAM + +/** + * Read result of the authenticatior sub-process from pipe + */ +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; + + /* Make sure authenticator sub-process is dead now ... */ + Proc_Kill(proc); + + if (len != sizeof(result)) { + Log(LOG_CRIT, "Auth: Got malformed result!"); + Reject_Client(client); + return; + } + + if (result == true) + (void)Hello_User_PostAuth(client); + else + Reject_Client(client); +} + +#endif + + +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); +} + + +static bool +Hello_User_PostAuth(CLIENT *Client) +{ Introduce_Client(NULL, Client, CLIENT_USER); if (!IRC_WriteStrClient @@ -804,7 +905,7 @@ Hello_User(CLIENT * Client) IRC_SetPenalty(Client, 1); return CONNECTED; -} /* Hello_User */ +} static void @@ -840,10 +941,16 @@ Introduce_Client(CLIENT *From, CLIENT *Client, int Type) Client_Modes(Client), Client_ID(From), Client_ID(Client_Introducer(Client)), Client_Hops(Client), Client_Hops(Client) > 1 ? "s": ""); - } else + } 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,