E-MailRelay
gpopserverprotocol.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gpopserverprotocol.h
19///
20
21#ifndef G_POP_SERVER_PROTOCOL_H
22#define G_POP_SERVER_PROTOCOL_H
23
24#include "gdef.h"
25#include "gaddress.h"
26#include "gstatemachine.h"
27#include "gsaslserversecrets.h"
28#include "gpopstore.h"
29#include "gsaslserver.h"
30#include "gstringview.h"
31#include "gtimer.h"
32#include "gexception.h"
33#include <memory>
34
35namespace GPop
36{
37 class ServerProtocol ;
38 class ServerProtocolText ;
39}
40
41//| \class GPop::ServerProtocol
42/// Implements the POP server-side protocol.
43///
44/// Uses the ServerProtocol::Sender as its "sideways"
45/// interface to talk back to the client.
46///
47/// \see RFC-1939
48///
50{
51public:
52 G_EXCEPTION( ProtocolDone , tx("pop protocol done") )
53
54 class Sender /// An interface used by ServerProtocol to send protocol replies.
55 {
56 public:
57 virtual bool protocolSend( std::string_view , std::size_t offset ) = 0 ;
58 virtual ~Sender() = default ;
59 } ;
60
61 class Text /// An interface used by ServerProtocol to provide response text strings.
62 {
63 public:
64 virtual std::string greeting() const = 0 ;
65 virtual std::string quit() const = 0 ;
66 virtual std::string capa() const = 0 ;
67 virtual std::string user( const std::string & id ) const = 0 ;
68 virtual ~Text() = default ;
69 } ;
70
71 struct Config /// A structure containing configuration parameters for ServerProtocol.
72 {
73 bool crlf_only {true} ; // (RFC-2821 2.3.7 does not apply to POP)
74 std::string sasl_server_challenge_domain ;
75 Config & set_crlf_only( bool = true ) ;
76 Config & set_sasl_server_challenge_domain( const std::string & ) ;
77 } ;
78
79 class Security /// An interface used by ServerProtocol to enable TLS.
80 {
81 public:
82 virtual bool securityEnabled() const = 0 ;
83 virtual void securityStart() = 0 ;
84 virtual ~Security() = default ;
85 } ;
86
87 ServerProtocol( Sender & sender , Security & security , Store & store ,
88 const GAuth::SaslServerSecrets & server_secrets , const std::string & sasl_server_config ,
89 const Text & text , const GNet::Address & peer_address , const Config & config ) ;
90 ///< Constructor.
91 ///<
92 ///< The Sender interface is used to send protocol
93 ///< replies back to the client.
94 ///<
95 ///< The Text interface is used to get informational text
96 ///< for returning to the client.
97 ///<
98 ///< All references are kept.
99
100 void init() ;
101 ///< Starts the protocol.
102
103 void apply( const std::string & line ) ;
104 ///< Called on receipt of a string from the client.
105 ///< The string is expected to be CR-LF terminated.
106 ///< Throws ProtocolDone if done.
107
108 void resume() ;
109 ///< Called when the Sender can send again. The Sender returns
110 ///< false from Sender::protocolSend() when blocked, and calls
111 ///< resume() when unblocked.
112
113 void secure() ;
114 ///< Called when the server connection becomes secure.
115
116private:
117 enum class Event
118 {
119 eApop ,
120 eAuth ,
121 eAuthData ,
122 eAuthComplete ,
123 eCapa ,
124 eDele ,
125 eList ,
126 eNoop ,
127 ePass ,
128 eQuit ,
129 eRetr ,
130 eRset ,
131 eSent ,
132 eStat ,
133 eTop ,
134 eUidl ,
135 eUser ,
136 eStls ,
137 eSecure ,
138 eUnknown
139 } ;
140 enum class State
141 {
142 sStart ,
143 sEnd ,
144 sActive ,
145 sData ,
146 sAuth ,
147 s_Any ,
148 s_Same
149 } ;
150 using EventData = const std::string & ;
152
153public:
154 ~ServerProtocol() = default ;
155 ServerProtocol( const ServerProtocol & ) = delete ;
156 ServerProtocol( ServerProtocol && ) = delete ;
157 ServerProtocol & operator=( const ServerProtocol & ) = delete ;
158 ServerProtocol & operator=( ServerProtocol && ) = delete ;
159
160private:
161 void doQuit( const std::string & line , bool & ) ;
162 void doQuitEarly( const std::string & line , bool & ) ;
163 void doStat( const std::string & line , bool & ) ;
164 void doList( const std::string & line , bool & ) ;
165 void doRetr( const std::string & line , bool & ) ;
166 void doDele( const std::string & line , bool & ) ;
167 void doRset( const std::string & line , bool & ) ;
168 void doUser( const std::string & line , bool & ) ;
169 void doPass( const std::string & line , bool & ) ;
170 void doNoop( const std::string & line , bool & ) ;
171 void doNothing( const std::string & line , bool & ) ;
172 void doApop( const std::string & line , bool & ) ;
173 void doTop( const std::string & line , bool & ) ;
174 void doCapa( const std::string & line , bool & ) ;
175 void doStls( const std::string & line , bool & ) ;
176 void doAuth( const std::string & line , bool & ) ;
177 void doAuthData( const std::string & line , bool & ) ;
178 void doAuthComplete( const std::string & line , bool & ) ;
179 void doUidl( const std::string & line , bool & ) ;
180 void sendInit() ;
181 void sendError() ;
182 void sendError( const std::string & ) ;
183 void sendOk() ;
184 int commandNumber( const std::string & , int , std::size_t index = 1U ) const ;
185 void sendList( const std::string & , bool ) ;
186 std::string commandWord( const std::string & ) const ;
187 std::string commandParameter( const std::string & , std::size_t index = 1U ) const ;
188 static std::string commandPart( const std::string & , std::size_t index ) ;
189 static Event commandEvent( std::string_view ) ;
190 void sendContent() ;
191 bool sendContentLine( std::string & , bool & ) ;
192 void sendLine( std::string_view , bool has_crlf = false ) ;
193 void sendLine( std::string && ) ;
194 void sendLines( std::ostringstream & ) ;
195 void readStore( const std::string & ) ;
196 std::string mechanisms() const ;
197 bool mechanismsIncludePlain() const ;
198
199private:
200 const Text & m_text ;
201 Sender & m_sender ;
202 Security & m_security ;
203 Store & m_store ;
204 Config m_config ;
205 std::unique_ptr<StoreUser> m_store_user ;
206 StoreList m_store_list ;
207 std::unique_ptr<GAuth::SaslServer> m_sasl ;
208 GNet::Address m_peer_address ;
209 Fsm m_fsm ;
210 std::string m_user ;
211 std::unique_ptr<std::istream> m_content ;
212 long m_body_limit {-1L} ;
213 bool m_in_body {false} ;
214 bool m_secure {false} ;
215 bool m_sasl_init_apop {false} ;
216} ;
217
218//| \class GPop::ServerProtocolText
219/// A default implementation for the ServerProtocol::Text interface.
220///
222{
223public:
224 explicit ServerProtocolText( const GNet::Address & peer ) ;
225 ///< Constructor.
226
227public:
228 ~ServerProtocolText() override = default ;
229 ServerProtocolText( const ServerProtocolText & ) = delete ;
231 ServerProtocolText & operator=( const ServerProtocolText & ) = delete ;
232 ServerProtocolText & operator=( ServerProtocolText && ) = delete ;
233
234private: // overrides
235 std::string greeting() const override ; // Override from GPop::ServerProtocol::Text.
236 std::string quit() const override ; // Override from GPop::ServerProtocol::Text.
237 std::string capa() const override ; // Override from GPop::ServerProtocol::Text.
238 std::string user( const std::string & id ) const override ; // Override from GPop::ServerProtocol::Text.
239} ;
240
241inline GPop::ServerProtocol::Config & GPop::ServerProtocol::Config::set_crlf_only( bool b ) { crlf_only = b ; return *this ; }
242inline GPop::ServerProtocol::Config & GPop::ServerProtocol::Config::set_sasl_server_challenge_domain( const std::string & s ) { sasl_server_challenge_domain = s ; return *this ; }
243
244#endif
An interface used by GAuth::SaslServer to obtain authentication secrets.
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
A default implementation for the ServerProtocol::Text interface.
ServerProtocolText(const GNet::Address &peer)
Constructor.
An interface used by ServerProtocol to enable TLS.
An interface used by ServerProtocol to send protocol replies.
An interface used by ServerProtocol to provide response text strings.
Implements the POP server-side protocol.
void resume()
Called when the Sender can send again.
void secure()
Called when the server connection becomes secure.
void init()
Starts the protocol.
void apply(const std::string &line)
Called on receipt of a string from the client.
ServerProtocol(Sender &sender, Security &security, Store &store, const GAuth::SaslServerSecrets &server_secrets, const std::string &sasl_server_config, const Text &text, const GNet::Address &peer_address, const Config &config)
Constructor.
A message store.
Definition: gpopstore.h:47
POP3 classes.
Definition: gpop.h:33
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
A structure containing configuration parameters for ServerProtocol.