Account for tokens changing during a session

master
Thor 4 years ago
parent 70163c1cce
commit 63508980ab
  1. 1
      include/mail.hpp
  2. 33
      include/protocol/protocol.hpp
  3. 13
      src/bogofilter-smtpd.cpp
  4. 53
      src/protocol/protocol.cpp

@ -16,6 +16,7 @@ namespace mail {
struct session_t {
bool has_header = 0;
protocol::token::string_t token;
message_t message;
};

@ -18,16 +18,14 @@ namespace protocol {
using handler_t = std::function<void(protocol_t&, const message_t&)>;
using handler_map_t = std::map<token::pattern_t, handler_t>;
struct session_key_t {
std::string session;
std::string token;
};
bool operator==(const session_key_t& l, const session_key_t& r);
using session_key_t = token::string_t;
session_key_t session_key_from(const token::list_t& tokens);
session_key_t session_key_from(const message_t& message);
token::string_t session_token_from(const token::list_t& tokens);
token::string_t session_token_from(const message_t& message);
class protocol_t {
public:
void set_handlers(const handler_map_t handlers);
@ -36,11 +34,11 @@ namespace protocol {
void send(const token::list_t& tokens);
// TODO: Move these methods to a separate session_t class!
void send_result(const session_key_t& session_key, token::list_t tokens);
void proceed(const session_key_t& session_key);
void junk(const session_key_t& session_key);
void fail(const session_key_t& session_key);
void submit_message(const session_key_t& session_key, const std::vector<std::string>& header, const std::vector<std::string>& body);
void send_result(const session_key_t& session_key, const token::string_t& session_token, token::list_t tokens);
void proceed(const session_key_t& session_key, const token::string_t& session_token);
void junk(const session_key_t& session_key, const token::string_t& session_token);
void fail(const session_key_t& session_key, const token::string_t& session_token);
void submit_message(const session_key_t& session_key, const token::string_t& session_token, const std::vector<std::string>& header, const std::vector<std::string>& body);
protected:
virtual void emit(const std::string& output) { };
@ -50,7 +48,7 @@ namespace protocol {
size_t max_pattern_length;
std::string version;
void send_data_line(const session_key_t& session_key, const std::string& data_line);
void send_data_line(const session_key_t& session_key, const token::string_t& session_token, const std::string& data_line);
};
class ios_protocol_t : public protocol_t {
@ -65,17 +63,6 @@ namespace protocol {
std::istream& in;
std::ostream& out;
};
}
namespace std {
template<> struct hash<protocol::session_key_t> {
std::size_t operator()(protocol::session_key_t const& session) const noexcept {
auto session_hash = std::hash<std::string>{}(session.session);
auto token_hash = std::hash<std::string>{}(session.token);
return session_hash ^ (token_hash << 1);
}
};
}
#endif

@ -25,8 +25,9 @@ void on_ready(protocol::protocol_t& protocol, protocol::message_t message) {
void on_data(protocol::protocol_t& protocol, protocol::message_t message) {
debug && cerr << "New message" << endl;
auto session_key = protocol::session_key_from(message);
auto session_token = protocol::session_token_from(message);
sessions.emplace(session_key, mail::session_t{});
protocol.proceed(session_key);
protocol.proceed(session_key, session_token);
}
void on_data_line(protocol::protocol_t& protocol, protocol::message_t message) {
@ -34,6 +35,7 @@ void on_data_line(protocol::protocol_t& protocol, protocol::message_t message) {
auto tokens = protocol::token::decompose(message.input);
auto session_key = protocol::session_key_from(tokens);
auto session_token = protocol::session_token_from(tokens);
try {
auto& session = sessions.at(session_key);
auto& data_line = tokens.at(7);
@ -60,21 +62,22 @@ void on_data_line(protocol::protocol_t& protocol, protocol::message_t message) {
session.message.body.push_back(data_line);
} catch(out_of_range& e) {
debug && cerr << "Unknown session key" << endl;
protocol.fail(session_key);
protocol.fail(session_key, session_token);
}
}
void on_commit(protocol::protocol_t& protocol, protocol::message_t message) {
debug && cerr << "Message committed" << endl;
auto session_key = protocol::session_key_from(message);
auto session_token = protocol::session_token_from(message);
try {
auto& session = sessions.at(session_key);
protocol.submit_message(session_key, session.message.header, session.message.body);
protocol.submit_message(session_key, session_token, session.message.header, session.message.body);
sessions.erase(session_key);
protocol.proceed(session_key);
protocol.proceed(session_key, session_token);
} catch(out_of_range& e) {
debug && cerr << "Unknown session key" << endl;
protocol.fail(session_key);
protocol.fail(session_key, session_token);
}
}

@ -51,12 +51,12 @@ namespace protocol {
}
}
void protocol_t::send_result(const session_key_t& session_key, token::list_t tokens) {
void protocol_t::send_result(const session_key_t& session_key, const token::string_t& session_token, token::list_t tokens) {
token::list_t result{"filter-result"};
if(version < "0.5") {
result.insert(result.end(), {session_key.token, session_key.session});
result.insert(result.end(), {session_token, session_key});
} else {
result.insert(result.end(), {session_key.session, session_key.token});
result.insert(result.end(), {session_key, session_token});
}
for(auto& token : tokens) {
result.push_back(token);
@ -64,39 +64,39 @@ namespace protocol {
send(result);
}
void protocol_t::proceed(const session_key_t& session_key) {
send_result(session_key, {"proceed"});
void protocol_t::proceed(const session_key_t& session_key, const token::string_t& session_token) {
send_result(session_key, session_token, {"proceed"});
}
void protocol_t::junk(const session_key_t& session_key) {
send_result(session_key, {"junk"});
void protocol_t::junk(const session_key_t& session_key, const token::string_t& session_token) {
send_result(session_key, session_token, {"junk"});
}
void protocol_t::fail(const session_key_t& session_key) {
send_result(session_key, {"disconnect", "451 Aborted"});
void protocol_t::fail(const session_key_t& session_key, const token::string_t& session_token) {
send_result(session_key, session_token, {"disconnect", "451 Aborted"});
}
void protocol_t::send_data_line(const session_key_t& session_key, const string& data_line) {
send({"filter-dataline", session_key.session, session_key.token, data_line});
void protocol_t::send_data_line(const session_key_t& session_key, const token::string_t& session_token, const string& data_line) {
send({"filter-dataline", session_key, session_token, data_line});
}
void protocol_t::submit_message(const session_key_t& session_key, const vector<string>& header, const vector<string>& body) {
void protocol_t::submit_message(const session_key_t& session_key, const token::string_t& session_token, const vector<string>& header, const vector<string>& body) {
for(auto& data_line : header) {
send_data_line(session_key, data_line);
send_data_line(session_key, session_token, data_line);
}
send_data_line(session_key, "");
send_data_line(session_key, session_token, "");
for(auto& data_line : body) {
if(data_line == ".") {
send_data_line(session_key, "..");
send_data_line(session_key, session_token, "..");
continue;
}
send_data_line(session_key, data_line);
send_data_line(session_key, session_token, data_line);
}
send_data_line(session_key, ".");
send_data_line(session_key, session_token, ".");
}
ios_protocol_t::ios_protocol_t(std::istream& in, std::ostream& out) :
@ -114,18 +114,21 @@ namespace protocol {
}
}
bool operator==(const session_key_t& l, const session_key_t& r) {
return l.session == r.session && l.token == r.token;
}
session_key_t session_key_from(const token::list_t& tokens) {
auto session_id = tokens.at(5);
auto session_token = tokens.at(6);
return {session_id, session_token};
return tokens.at(5);
}
session_key_t session_key_from(const message_t& message) {
auto tokens = token::decompose(message.input);
auto tokens = token::decompose(message.input, 6);
return session_key_from(tokens);
}
token::string_t session_token_from(const token::list_t& tokens) {
return tokens.at(6);
}
token::string_t session_token_from(const message_t& message) {
auto tokens = token::decompose(message.input, 7);
return session_token_from(tokens);
}
}

Loading…
Cancel
Save