/** * @file operator-starttls.cc * @brief Implementation of the STARTTLS command - based on sslserver * @author Andreas Aardal Hanssen, Erwin Hoffmann * @date 2002-2005, 2023 */ #include "depot.h" #include "iodevice.h" #include "iofactory.h" #include "operators.h" #include "recursivedescent.h" #include "session.h" #include #include #include #include using namespace Binc; StarttlsOperator::StarttlsOperator(void) {} StarttlsOperator::~StarttlsOperator(void) {} const std::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")) { std::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" << std::endl; bincClient << command.getTag() << " OK STARTTLS completed" << std::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; }