/** * @file operator-login.cc * @brief Implementation of the rapid LOGIN command * @author Andreas Aardal Hanssen, Erwin Hoffmann * @date 2002-2005, 2023 */ #include "authenticate.h" #include "depot.h" #include "globals.h" #include "iodevice.h" #include "iofactory.h" #include "operators.h" #include "recursivedescent.h" #include "session.h" #include #include #include #include #include #include using namespace Binc; LoginOperator::LoginOperator() {} LoginOperator::~LoginOperator() {} const std::string LoginOperator::getName() const { return "LOGIN"; } Session::State LoginOperator::getState() const { return Session::NONAUTHENTICATED; } Operator::ProcessResult LoginOperator::process(Depot &depot, Request &command) { Session &session = Session::getInstance(); if (!session.command.ssl && !session.hasEnv("ALLOW_NONSSL_PLAINTEXT_LOGINS")) { session.setLastError("Plain text password authentication is disallowd. " "Please enable StartTLS or TLS in your mail client."); return Operator::ProcessResult::NO; } session.setEnv("BINCIMAP_LOGIN", "LOGIN+" + command.getTag()); std::string challenge; switch (authenticate(depot, command.getUserID(), command.getPassword(), challenge)) { case 1: session.setLastError("An internal error occurred when you attempted " "to log in to the IMAP server. Please contact " "your system administrator."); return Operator::ProcessResult::NO; case 2: session.setLastError("Login failed. Either your user name " "or your password was wrong. Please try again, " "and if the problem persists, please contact " "your system administrator."); return Operator::ProcessResult::NO; case 3: bincClient << "* BYE Timeout after " << IDLE_TIMEOUT << " seconds of inactivity." << std::endl; break; case -1: bincClient << "* BYE The server died unexpectedly. Please contact " "your system administrator for more information." << std::endl; break; } // go to logout session.setState(Session::LOGOUT); return Operator::ProcessResult::NOTHING; } Parser::ParseResult LoginOperator::parse(Request &c_in, Parser &p) { constexpr auto ACCEPT = Parser::ParseResult::ACCEPT; Session &session = Session::getInstance(); if (c_in.getUidMode()) return Parser::ParseResult::REJECT; Parser::ParseResult res; if ((res = p.expectSPACE()) != ACCEPT) { session.setLastError("Expected single SPACE after LOGIN"); return res; } std::string userid; if ((res = p.expectAstring(userid)) != ACCEPT) { session.setLastError("Expected userid after LOGIN SPACE"); return res; } c_in.setUserID(userid); if ((res = p.expectSPACE()) != ACCEPT) { session.setLastError("Expected SPACE after LOGIN SPACE userid"); return res; } std::string password; if ((res = p.expectAstring(password)) != ACCEPT) { session.setLastError("Expected password after LOGIN " "SPACE userid SPACE"); return res; } if ((res = p.expectCRLF()) != ACCEPT) { session.setLastError("Expected CRLF after password"); return res; } c_in.setPassword(password); c_in.setName("LOGIN"); return ACCEPT; }