lay it out a bit better
[ghsmtp.git] / Session.hpp
blob153410da30dade3b7c9c35fdf9e4ed15b621cd27
1 #ifndef SESSION_DOT_HPP
2 #define SESSION_DOT_HPP
4 #include <random>
5 #include <string>
6 #include <string_view>
7 #include <unordered_map>
8 #include <vector>
10 #include "CDB.hpp"
11 #include "DNS-fcrdns.hpp"
12 #include "Domain.hpp"
13 #include "Mailbox.hpp"
14 #include "MessageStore.hpp"
15 #include "SPF.hpp"
16 #include "SRS0.hpp"
17 #include "Send.hpp"
18 #include "Sock.hpp"
19 #include "TLD.hpp"
21 namespace Config {
22 constexpr size_t kibibyte = 1024;
23 constexpr size_t mebibyte = kibibyte * kibibyte;
24 constexpr size_t max_msg_size_initial = 15 * mebibyte;
25 constexpr size_t max_msg_size_bro = 150 * mebibyte;
26 } // namespace Config
28 class Session {
29 public:
30 using parameters_t = std::unordered_map<std::string, std::string>;
32 Session(Session const&) = delete;
33 Session& operator=(Session const&) = delete;
35 explicit Session(
36 fs::path config_path,
37 std::function<void(void)> read_hook = []() {},
38 int fd_in = STDIN_FILENO,
39 int fd_out = STDOUT_FILENO);
41 void greeting();
42 void ehlo(std::string_view client_identity) { lo_("EHLO", client_identity); }
43 void helo(std::string_view client_identity) { lo_("HELO", client_identity); }
44 void mail_from(Mailbox&& reverse_path, parameters_t const& parameters);
45 void rcpt_to(Mailbox&& forward_path, parameters_t const& parameters);
47 bool msg_new();
48 bool msg_write(char const* s, std::streamsize count);
50 bool data_start();
51 void data_done();
52 void data_size_error();
53 void data_error();
55 bool bdat_start(size_t n);
56 void bdat_done(size_t n, bool last);
57 void bdat_size_error();
58 void bdat_seq_error();
59 void bdat_io_error();
61 void rset();
62 void noop(std::string_view str);
63 void vrfy(std::string_view str);
64 void help(std::string_view str);
65 void quit() __attribute__((noreturn));
66 void auth() __attribute__((noreturn));
67 void error(std::string_view log_msg);
68 void cmd_unrecognized(std::string_view log_msg);
69 void bare_lf() __attribute__((noreturn));
71 void max_out() __attribute__((noreturn));
72 void time_out() __attribute__((noreturn));
73 void starttls();
75 bool maxed_out() { return sock_.maxed_out(); }
76 bool timed_out() { return sock_.timed_out(); }
77 std::istream& in() { return sock_.in(); }
79 void flush();
80 void last_in_group_(std::string_view verb);
82 size_t max_msg_size() const { return max_msg_size_; }
83 void max_msg_size(size_t max);
85 void log_stats() { sock_.log_stats(); }
87 enum class SpamStatus : bool { ham, spam };
89 private:
90 friend struct Session_test;
92 std::tuple<SpamStatus, std::string> spam_status_();
94 std::string added_headers_(MessageStore const& msg);
96 std::ostream& out_() { return sock_.out(); }
97 void lo_(char const* verb, std::string_view client_identity);
99 void bad_host_(char const* msg) const __attribute__((noreturn));
101 std::string const& server_id_() const { return server_identity_.ascii(); }
103 void new_bounce_(std::string loc);
104 void deliver_();
106 // clear per transaction data, preserve per connection data
107 void reset_();
109 bool verify_ip_address_(std::string& error_msg);
110 bool verify_ip_address_dnsbl_(std::string& error_msg);
111 bool verify_client_(Domain const& client_identity, std::string& error_msg);
112 bool verify_recipient_(Mailbox const& recipient);
113 bool verify_sender_(Mailbox const& sender, std::string& error_msg);
114 bool verify_sender_domain_(Domain const& sender, std::string& error_msg);
115 bool verify_sender_domain_uribl_(std::string_view sender,
116 std::string& error_msg);
117 bool verify_sender_spf_(Mailbox const& sender);
118 bool verify_from_params_(parameters_t const& parameters);
119 bool verify_rcpt_params_(parameters_t const& parameters);
121 bool is_forwarding_() const
123 return forward_path_.empty() && !fwd_path_.empty();
126 void exit_() __attribute__((noreturn));
128 private:
129 fs::path config_path_;
130 DNS::Resolver res_;
131 Sock sock_;
133 // forwarding and replies
134 SRS0 srs_;
135 Send send_;
136 std::vector<Mailbox> fwd_path_; // for each "rcpt to"
137 std::vector<SRS0::from_to> rep_path_; // for each reply being forwarded
139 // per connection/session
140 Domain server_identity_; // who we identify as
141 std::vector<Domain> client_fcrdns_; // who they look-up as
142 std::vector<Domain> server_fcrdns_; // who we look-up as
143 std::string client_; // (fcrdns_ [sock_.them_c_str()])
145 // per transaction
146 Domain client_identity_; // from ehlo/helo
147 Mailbox reverse_path_; // "mail from"
148 std::vector<Mailbox> forward_path_; // for each "rcpt to"
149 std::string spf_received_;
150 std::unique_ptr<MessageStore> msg_;
152 TLD tld_db_;
154 std::random_device random_device_;
156 // White and black lists for domains.
157 CDB white_;
158 CDB black_;
159 CDB forward_;
161 // Domains we receive mail for.
162 CDB accept_domains_;
164 size_t max_msg_size_;
166 int n_unrecognized_cmds_{0};
168 SPF::Result spf_result_;
169 Domain spf_sender_domain_;
171 // RFC 5321 section 3.3. Mail Transactions
172 enum class xact_step : int8_t {
173 helo,
174 mail,
175 rcpt,
176 data,
177 bdat, // RFC 3030
178 rset, // must now send RSET
181 // per transaction
182 xact_step state_ = xact_step::helo;
184 bool binarymime_{false};
185 bool extensions_{false};
186 bool smtputf8_{false};
187 bool prdr_{false};
189 // per connection
190 bool fcrdns_whitelisted_{false};
191 bool ip_whitelisted_{false};
194 #endif // SESSION_DOT_HPP