[BACK]Return to login.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/login.c, Revision 1.1

1.1     ! tomglok     1: /*
        !             2:  * ngIRCd -- The Next Generation IRC Daemon
        !             3:  * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
        !             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 2 of the License, or
        !             8:  * (at your option) any later version.
        !             9:  * Please read the file COPYING, README and AUTHORS for more information.
        !            10:  */
        !            11:
        !            12: #include "portab.h"
        !            13:
        !            14: /**
        !            15:  * @file
        !            16:  * Functions to deal with client logins
        !            17:  */
        !            18:
        !            19: #include <assert.h>
        !            20: #include <stdlib.h>
        !            21: #include <stdio.h>
        !            22: #include <string.h>
        !            23: #include <unistd.h>
        !            24:
        !            25: #include "conn.h"
        !            26: #include "class.h"
        !            27: #include "client-cap.h"
        !            28: #include "channel.h"
        !            29: #include "conf.h"
        !            30: #include "parse.h"
        !            31: #include "log.h"
        !            32: #include "messages.h"
        !            33: #include "ngircd.h"
        !            34: #include "irc-info.h"
        !            35: #include "irc-mode.h"
        !            36: #include "irc-write.h"
        !            37:
        !            38: #include "login.h"
        !            39:
        !            40: #ifdef PAM
        !            41:
        !            42: #include "io.h"
        !            43: #include "pam.h"
        !            44:
        !            45: static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
        !            46:
        !            47: #endif
        !            48:
        !            49: /**
        !            50:  * Initiate client login.
        !            51:  *
        !            52:  * This function is called after the daemon received the required NICK and
        !            53:  * USER commands of a new client. If the daemon is compiled with support for
        !            54:  * PAM, the authentication sub-processs is forked; otherwise the global server
        !            55:  * password is checked.
        !            56:  *
        !            57:  * @param Client The client logging in.
        !            58:  * @returns CONNECTED or DISCONNECTED.
        !            59:  */
        !            60: GLOBAL bool
        !            61: Login_User(CLIENT * Client)
        !            62: {
        !            63: #ifdef PAM
        !            64:        int pipefd[2], result;
        !            65:        pid_t pid;
        !            66: #endif
        !            67:        CONN_ID conn;
        !            68:
        !            69:        assert(Client != NULL);
        !            70:        conn = Client_Conn(Client);
        !            71:
        !            72: #ifndef STRICT_RFC
        !            73:        if (Conf_AuthPing) {
        !            74:                /* Did we receive the "auth PONG" already? */
        !            75:                if (Conn_GetAuthPing(conn)) {
        !            76:                        Client_SetType(Client, CLIENT_WAITAUTHPING);
        !            77:                        LogDebug("Connection %d: Waiting for AUTH PONG ...", conn);
        !            78:                        return CONNECTED;
        !            79:                }
        !            80:        }
        !            81: #endif
        !            82:
        !            83:        /* Still waiting for "CAP END" command? */
        !            84:        if (Client_Cap(Client) & CLIENT_CAP_PENDING) {
        !            85:                Client_SetType(Client, CLIENT_WAITCAPEND);
        !            86:                LogDebug("Connection %d: Waiting for CAP END ...", conn);
        !            87:                return CONNECTED;
        !            88:        }
        !            89:
        !            90: #ifdef PAM
        !            91:        if (!Conf_PAM) {
        !            92:                /* Don't do any PAM authentication at all if PAM is not
        !            93:                 * enabled, instead emulate the behavior of the daemon
        !            94:                 * compiled without PAM support. */
        !            95:                if (strcmp(Conn_Password(conn), Conf_ServerPwd) == 0)
        !            96:                        return Login_User_PostAuth(Client);
        !            97:                Client_Reject(Client, "Bad server password", false);
        !            98:                return DISCONNECTED;
        !            99:        }
        !           100:
        !           101:        if (Conf_PAMIsOptional &&
        !           102:            strcmp(Conn_Password(conn), "") == 0) {
        !           103:                /* Clients are not required to send a password and to be PAM-
        !           104:                 * authenticated at all. If not, they won't become "identified"
        !           105:                 * and keep the "~" in their supplied user name.
        !           106:                 * Therefore it is sensible to either set Conf_PAMisOptional or
        !           107:                 * to enable IDENT lookups -- not both. */
        !           108:                return Login_User_PostAuth(Client);
        !           109:        }
        !           110:
        !           111:        if (Conf_PAM) {
        !           112:                /* Fork child process for PAM authentication; and make sure that the
        !           113:                 * process timeout is set higher than the login timeout! */
        !           114:                pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
        !           115:                                cb_Read_Auth_Result, Conf_PongTimeout + 1);
        !           116:                if (pid > 0) {
        !           117:                        LogDebug("Authenticator for connection %d created (PID %d).",
        !           118:                                 conn, pid);
        !           119:                        return CONNECTED;
        !           120:                } else {
        !           121:                        /* Sub process */
        !           122:                        Log_Init_Subprocess("Auth");
        !           123:                        Conn_CloseAllSockets(NONE);
        !           124:                        result = PAM_Authenticate(Client);
        !           125:                        if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
        !           126:                                Log_Subprocess(LOG_ERR,
        !           127:                                               "Failed to pipe result to parent!");
        !           128:                        Log_Exit_Subprocess("Auth");
        !           129:                        exit(0);
        !           130:                }
        !           131:        } else return CONNECTED;
        !           132: #else
        !           133:        /* Check global server password ... */
        !           134:        if (strcmp(Conn_Password(conn), Conf_ServerPwd) != 0) {
        !           135:                /* Bad password! */
        !           136:                Client_Reject(Client, "Bad server password", false);
        !           137:                return DISCONNECTED;
        !           138:        }
        !           139:        return Login_User_PostAuth(Client);
        !           140: #endif
        !           141: }
        !           142:
        !           143: /**
        !           144:  * Finish client registration.
        !           145:  *
        !           146:  * Introduce the new client to the network and send all "hello messages"
        !           147:  * to it after authentication has been succeeded.
        !           148:  *
        !           149:  * @param Client The client logging in.
        !           150:  * @return CONNECTED or DISCONNECTED.
        !           151:  */
        !           152: GLOBAL bool
        !           153: Login_User_PostAuth(CLIENT *Client)
        !           154: {
        !           155:        REQUEST Req;
        !           156:        char modes[CLIENT_MODE_LEN + 1];
        !           157:
        !           158:        assert(Client != NULL);
        !           159:
        !           160:        if (Class_HandleServerBans(Client) != CONNECTED)
        !           161:                return DISCONNECTED;
        !           162:
        !           163:        Client_Introduce(NULL, Client, CLIENT_USER);
        !           164:
        !           165:        if (!IRC_WriteStrClient
        !           166:            (Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
        !           167:                return false;
        !           168:        if (!IRC_WriteStrClient
        !           169:            (Client, RPL_YOURHOST_MSG, Client_ID(Client),
        !           170:             Client_ID(Client_ThisServer()), PACKAGE_VERSION, HOST_CPU,
        !           171:             HOST_VENDOR, HOST_OS))
        !           172:                return false;
        !           173:        if (!IRC_WriteStrClient
        !           174:            (Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr))
        !           175:                return false;
        !           176:        if (!IRC_WriteStrClient
        !           177:            (Client, RPL_MYINFO_MSG, Client_ID(Client),
        !           178:             Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES,
        !           179:             CHANMODES))
        !           180:                return false;
        !           181:
        !           182:        /* Features supported by this server (005 numeric, ISUPPORT),
        !           183:         * see <http://www.irc.org/tech_docs/005.html> for details. */
        !           184:        if (!IRC_Send_ISUPPORT(Client))
        !           185:                return DISCONNECTED;
        !           186:
        !           187:        if (!IRC_Send_LUSERS(Client))
        !           188:                return DISCONNECTED;
        !           189:        if (!IRC_Show_MOTD(Client))
        !           190:                return DISCONNECTED;
        !           191:
        !           192:        /* Set default user modes */
        !           193:        if (Conf_DefaultUserModes[0]) {
        !           194:                snprintf(modes, sizeof(modes), "+%s", Conf_DefaultUserModes);
        !           195:                Req.prefix = Client_ID(Client_ThisServer());
        !           196:                Req.command = "MODE";
        !           197:                Req.argc = 2;
        !           198:                Req.argv[0] = Client_ID(Client);
        !           199:                Req.argv[1] = modes;
        !           200:                IRC_MODE(Client, &Req);
        !           201:        } else
        !           202:                IRC_SetPenalty(Client, 1);
        !           203:
        !           204:        return CONNECTED;
        !           205: }
        !           206:
        !           207: #ifdef PAM
        !           208:
        !           209: /**
        !           210:  * Read result of the authenticator sub-process from pipe
        !           211:  *
        !           212:  * @param r_fd         File descriptor of the pipe.
        !           213:  * @param events       (ignored IO specification)
        !           214:  */
        !           215: static void
        !           216: cb_Read_Auth_Result(int r_fd, UNUSED short events)
        !           217: {
        !           218:        char user[CLIENT_USER_LEN], *ptr;
        !           219:        CONN_ID conn;
        !           220:        CLIENT *client;
        !           221:        int result;
        !           222:        size_t len;
        !           223:        PROC_STAT *proc;
        !           224:
        !           225:        LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events);
        !           226:        conn = Conn_GetFromProc(r_fd);
        !           227:        if (conn == NONE) {
        !           228:                /* Ops, none found? Probably the connection has already
        !           229:                 * been closed!? We'll ignore that ... */
        !           230:                io_close(r_fd);
        !           231:                LogDebug("Auth: Got callback for unknown connection!?");
        !           232:                return;
        !           233:        }
        !           234:        proc = Conn_GetProcStat(conn);
        !           235:        client = Conn_GetClient(conn);
        !           236:
        !           237:        /* Read result from pipe */
        !           238:        len = Proc_Read(proc, &result, sizeof(result));
        !           239:        Proc_Close(proc);
        !           240:        if (len == 0)
        !           241:                return;
        !           242:
        !           243:        if (len != sizeof(result)) {
        !           244:                Log(LOG_CRIT, "Auth: Got malformed result!");
        !           245:                Client_Reject(client, "Internal error", false);
        !           246:                return;
        !           247:        }
        !           248:
        !           249:        if (result == true) {
        !           250:                /* Authentication succeeded, now set the correct user name
        !           251:                 * supplied by the client (without prepended '~' for exmaple),
        !           252:                 * but cut it at the first '@' character: */
        !           253:                strlcpy(user, Client_OrigUser(client), sizeof(user));
        !           254:                ptr = strchr(user, '@');
        !           255:                if (ptr)
        !           256:                        *ptr = '\0';
        !           257:                Client_SetUser(client, user, true);
        !           258:                (void)Login_User_PostAuth(client);
        !           259:        } else
        !           260:                Client_Reject(client, "Bad password", false);
        !           261: }
        !           262:
        !           263: #endif
        !           264:
        !           265: /* -eof- */

CVSweb