Skip to content

Commit

Permalink
Add support for the starttls command.
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanGuthrie committed Mar 11, 2015
1 parent 30a4479 commit 997880e
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 22 deletions.
9 changes: 5 additions & 4 deletions Makefile
Expand Up @@ -16,7 +16,7 @@
CC=g++
CXXFLAGS=-g -Wall -Wextra -pthread
CXXTESTFLAGS=$(CXXFLAGS) -DTEST
LDFLAGS=-lpthread -lcrypt -lclotho -lboost_system
LDFLAGS=-lpthread -lcrypt -lclotho -lboost_system -lgnutls

%.d: %.cpp
@set -e; rm -f $@; \
Expand Down Expand Up @@ -68,7 +68,8 @@ SOURCES=imapd.cpp \
closehandler.cpp \
searchhandler.cpp \
fetchhandler.cpp \
storehandler.cpp
storehandler.cpp \
starttlshandler.cpp

imapd: imapd.o imapsession.o imapunixuser.o imapuser.o sasl.o base64.o mailstorembox.o \
mailstore.o idletimer.o asynchronousaction.o delayedmessage.o \
Expand All @@ -78,7 +79,7 @@ imapd: imapd.o imapsession.o imapunixuser.o imapuser.o sasl.o base64.o mailstore
createhandler.o deletehandler.o renamehandler.o subscribehandler.o \
listhandler.o statushandler.o appendhandler.o selecthandler.o checkhandler.o \
expungehandler.o copyhandler.o closehandler.o searchhandler.o fetchhandler.o \
storehandler.o
storehandler.o starttlshandler.o

testidletimer.o: idletimer.cpp Makefile
$(CC) $(CXXTESTFLAGS) -c -o $@ $<
Expand All @@ -95,7 +96,7 @@ locking-test: locking-test.o mailstorelocktest.o imapmasterlocktest.o locktestma
loginhandler.o namespacehandler.o createhandler.o deletehandler.o renamehandler.o \
subscribehandler.o listhandler.o statushandler.o appendhandler.o selecthandler.o \
checkhandler.o expungehandler.o copyhandler.o closehandler.o searchhandler.o \
fetchhandler.o storehandler.o
fetchhandler.o storehandler.o starttlshandler.o

include $(SOURCES:.cpp=.d)

Expand Down
10 changes: 9 additions & 1 deletion imapmaster.cpp
Expand Up @@ -35,9 +35,12 @@ ImapMaster::ImapMaster(std::string fqdn, unsigned login_timeout, unsigned idle_t
m_badLoginPause = bad_login_pause;
m_maxRetries = max_retries;
m_retryDelaySeconds = retry_seconds;
m_keyfile = "./test-priv.pem";
m_certfile = "./test-cert.pem";
m_cafile = "./test-cert.pem";
m_crlfile = "./test-crl.pem";

ImapSession::buildSymbolTables();

}

ImapMaster::~ImapMaster(void) {
Expand Down Expand Up @@ -65,6 +68,11 @@ Namespace *ImapMaster::mailStore(ImapSession *session) {
}


bool ImapMaster::isLoginEnabledByPolicy(void) const {
return true; // Use this for testing
return false;
}

ImapSession *ImapMaster::newSession(SessionDriver *driver, Server *server) {
return new ImapSession(this, driver, server);
}
Expand Down
13 changes: 12 additions & 1 deletion imapmaster.hpp
Expand Up @@ -34,7 +34,8 @@ class ImapMaster : public ServerMaster {

ImapUser *userInfo(const char *userid);
Namespace *mailStore(ImapSession *session);
bool isAnonymousEnabled() { return false; } // SYZYGY ANONYMOUS
bool isAnonymousEnabled() { return false; }
bool isLoginEnabledByPolicy(void) const;
// This will send the specified message out the specified socket
// after the specified number of seconds and then set that session
// up to receive again
Expand All @@ -50,6 +51,12 @@ class ImapMaster : public ServerMaster {
unsigned badLoginPause(void) const { return m_badLoginPause; }
unsigned maxRetries(void) const { return m_maxRetries; }
unsigned retryDelaySeconds(void) const { return m_retryDelaySeconds; }

const std::string &keyfile(void) const { return m_keyfile; }
const std::string &certfile(void) const { return m_certfile; }
const std::string &cafile(void) const { return m_cafile; }
const std::string &crlfile(void) const { return m_crlfile; }

#if 0
void idleTimer(SessionDriver *driver, unsigned seconds);
void scheduleAsynchronousAction(SessionDriver *driver, unsigned seconds);
Expand All @@ -69,6 +76,10 @@ class ImapMaster : public ServerMaster {
unsigned m_badLoginPause;
unsigned m_maxRetries;
unsigned m_retryDelaySeconds;
std::string m_keyfile;
std::string m_certfile;
std::string m_cafile;
std::string m_crlfile;
};

#endif //_IMAPMASTER_HPP_INCLUDED_
28 changes: 15 additions & 13 deletions imapsession.cpp
Expand Up @@ -60,6 +60,7 @@
#include "searchhandler.hpp"
#include "fetchhandler.hpp"
#include "storehandler.hpp"
#include "starttlshandler.hpp"

#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
Expand Down Expand Up @@ -379,8 +380,8 @@ void ImapSession::buildSymbolTables() {
symbolToInsert.levels[2] = false;
symbolToInsert.levels[3] = false;
symbolToInsert.sendUpdatedStatus = true;
symbolToInsert.handler = unimplementedHandler;
m_symbols.insert(IMAPSYMBOLS::value_type("STARTTTLS", symbolToInsert));
symbolToInsert.handler = startTlsHandler;
m_symbols.insert(IMAPSYMBOLS::value_type("STARTTLS", symbolToInsert));
symbolToInsert.handler = authenticateHandler;
m_symbols.insert(IMAPSYMBOLS::value_type("AUTHENTICATE", symbolToInsert));
symbolToInsert.handler = loginHandler;
Expand Down Expand Up @@ -464,7 +465,6 @@ ImapSession::ImapSession(ImapMaster *master, SessionDriver *driver, Server *serv
m_server = server;
m_state = ImapNotAuthenticated;
m_userData = NULL;
m_loginDisabled = false;
m_lineBuffer = NULL; // going with a static allocation for now
m_lineBuffPtr = 0;
m_lineBuffLen = 0;
Expand Down Expand Up @@ -915,16 +915,14 @@ void ImapSession::handleOneLine(INPUT_DATA_STRUCT &input) {


std::string ImapSession::capabilityString() {
std::string capability;
#if 0 // SYZYGY AUTH ANONYMOUS LOGINDISABLED all are determined by the server state as much as the session
capability.Format("CAPABILITY IMAP4rev1 CHILDREN NAMESPACE AUTH=PLAIN%s%s",
m_AnonymousEnabled ? " AUTH=ANONYMOUS" : "",
m_LoginDisabled ? " LOGINDISABLED" : "");
#else // !0
capability = "CAPABILITY IMAP4rev1 CHILDREN NAMESPACE AUTH=PLAIN";
#endif // !0

return capability;
std::ostringstream capability;
// AUTH ANONYMOUS LOGINDISABLED all are determined by the server state as much as the session

capability << "CAPABILITY IMAP4rev1 CHILDREN NAMESPACE" <<
(m_master->isAnonymousEnabled() ? " AUTH=ANONYMOUS" : "") <<
(isLoginEnabled() ? " AUTH=PLAIN" : " LOGINDISABLED");

return capability.str();
}


Expand All @@ -941,6 +939,10 @@ void ImapSession::closeMailbox(ImapState newState) {
m_state = newState;
}

bool ImapSession::isLoginEnabled(void) const {
return m_master->isLoginEnabledByPolicy() || m_driver->isConnectionEncrypted();
}

void ImapSession::responseText(void) {
m_responseText[0] = '\0';
}
Expand Down
3 changes: 1 addition & 2 deletions imapsession.hpp
Expand Up @@ -161,7 +161,7 @@ class ImapSession : public InternetSession {
Namespace *store(void) const { return m_store; }
void store(Namespace *mailstore) { m_store = mailstore; }
ParseBuffer *parseBuffer(void) const { return m_parseBuffer; }
bool loginDisabled(void) const { return m_loginDisabled; }
bool isLoginEnabled(void) const;
MailStore::MAIL_STORE_RESULT mboxErrorCode(MailStore::MAIL_STORE_RESULT code) { m_mboxErrorCode = code; return code; }
MailStore::MAIL_STORE_RESULT mboxErrorCode(void) const { return m_mboxErrorCode; }
const uint8_t *lineBuffer(void) const { return m_lineBuffer; }
Expand All @@ -182,7 +182,6 @@ class ImapSession : public InternetSession {

private:
// These are configuration items
bool m_loginDisabled;
static bool m_anonymousEnabled;
unsigned m_failedLoginPause;
SessionDriver *m_driver;
Expand Down
2 changes: 1 addition & 1 deletion loginhandler.cpp
Expand Up @@ -66,7 +66,7 @@ IMAP_RESULTS LoginHandler::execute(void) {
*/
IMAP_RESULTS LoginHandler::receiveData(INPUT_DATA_STRUCT &input) {
IMAP_RESULTS result = IMAP_OK;
if (m_session->loginDisabled()) {
if (!m_session->isLoginEnabled()) {
m_session->responseText("Login Disabled");
return IMAP_NO;
}
Expand Down
40 changes: 40 additions & 0 deletions starttlshandler.cpp
@@ -0,0 +1,40 @@
/*
* Copyright 2013 Jonathan R. Guthrie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "starttlshandler.hpp"
#include "imapmaster.hpp"

ImapHandler *startTlsHandler(ImapSession *session, INPUT_DATA_STRUCT &input) {
(void) input;
return new StartTlsHandler(session);
}

/*--------------------------------------------------------------------------------------*/
/* Handles the STARTTLS command */
/*--------------------------------------------------------------------------------------*/
IMAP_RESULTS StartTlsHandler::receiveData(INPUT_DATA_STRUCT &input) {
IMAP_RESULTS result;
(void) input;
if (m_session->driver()->isConnectionEncrypted()) {
m_session->responseText("Unrecognized Command");
result = IMAP_BAD;
}
else {
m_session->driver()->startTls(m_session->master()->keyfile(), m_session->master()->certfile(), m_session->master()->cafile(), m_session->master()->crlfile());
result = IMAP_OK;
}
return result;
}
31 changes: 31 additions & 0 deletions starttlshandler.hpp
@@ -0,0 +1,31 @@
/*
* Copyright 2013 Jonathan R. Guthrie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if !defined(_STARTTLSHANDLER_HPP_INCLUDED)
#define _STARTTLSHANDLER_HPP_INCLUDED

#include "imaphandler.hpp"

ImapHandler *startTlsHandler(ImapSession *, INPUT_DATA_STRUCT &input);

class StartTlsHandler : public ImapHandler {
public:
StartTlsHandler(ImapSession *session) : ImapHandler(session) {}
virtual ~StartTlsHandler() {}
virtual IMAP_RESULTS receiveData(INPUT_DATA_STRUCT &input);
};

#endif // !defined(_STARTTLSHANDLER_HPP_INCLUDED)

0 comments on commit 997880e

Please sign in to comment.