/** -------------------------------------------------------------------- * @file operator-starttls.cc * @brief Implementation of the STARTTLS command - based on sslserver * @author Andreas Aardal Hanssen, Erwin Hoffmann * @date 2002-2005, 2023 * ----------------------------------------------------------------- **/ #include #include #include #include #include "recursivedescent.h" #include "iodevice.h" #include "iofactory.h" #include "session.h" #include "depot.h" #include "operators.h" using namespace ::std; using namespace Binc; //---------------------------------------------------------------------- StarttlsOperator::StarttlsOperator(void) { } //---------------------------------------------------------------------- StarttlsOperator::~StarttlsOperator(void) { } //---------------------------------------------------------------------- const string StarttlsOperator::getName(void) const { return "STARTTLS"; } //---------------------------------------------------------------------- int StarttlsOperator::getState(void) const { return Session::NONAUTHENTICATED | Session::AUTHENTICATED | Session::SELECTED; } //---------------------------------------------------------------------- int StarttlsOperator::goStartTLS (void) const { Session &session = Session::getInstance(); if (getenv("UCSPITLS")) { string fdstr; int fd; fdstr = session.getEnv("SSLCTLFD"); fd = std::stoi(fdstr); if (write(fd,"Y",1) < 1) return NOTHING; bincClient.flush(); // flush all previous received data fdstr = session.getEnv("SSLREADFD"); fd = std::stoi(fdstr); if (fcntl(fd,F_GETFL,0) == -1) return NOTHING; close (0); if (fcntl(fd,F_DUPFD,0) == -1) return NOTHING; close (fd); fdstr = session.getEnv("SSLWRITEFD"); fd = std::stoi(fdstr); if (fcntl(fd,F_GETFL,0) == -1) return NOTHING; close (1); if (fcntl(fd,F_DUPFD,1) == -1) return NOTHING; close (fd); } return ACCEPT; } //------------------------------------------------------------------------ Operator::ProcessResult StarttlsOperator::process(Depot &depot, Request &command) { Session &session = Session::getInstance(); if (session.command.ssl) { session.setLastError("Already in TLS mode"); return BAD; } bincClient << "* ENABLED StartTLS - begin negotiation now" << endl; bincClient << command.getTag() << " OK STARTTLS completed" << endl; if (goStartTLS() == ACCEPT) session.command.ssl = true; else return NO; return NOTHING; } //---------------------------------------------------------------------- Operator::ParseResult StarttlsOperator::parse(Request &c_in) const { Session &session = Session::getInstance(); if (c_in.getUidMode()) return REJECT; Operator::ParseResult res; if ((res = expectCRLF()) != ACCEPT) { session.setLastError("Expected CRLF"); return res; } c_in.setName("STARTTLS"); return ACCEPT; }