/src/PcapPlusPlus/Packet++/header/SmtpLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef PACKETPP_SMTP_LAYER |
2 | | #define PACKETPP_SMTP_LAYER |
3 | | |
4 | | #include "PayloadLayer.h" |
5 | | #include "SingleCommandTextProtocol.h" |
6 | | |
7 | | /// @file |
8 | | |
9 | | /** |
10 | | * \namespace pcpp |
11 | | * \brief The main namespace for the PcapPlusPlus lib |
12 | | */ |
13 | | namespace pcpp |
14 | | { |
15 | | /** |
16 | | * Class for general SMTP message |
17 | | */ |
18 | | class SmtpLayer : public SingleCommandTextProtocol |
19 | | { |
20 | | protected: |
21 | | SmtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) |
22 | | : SingleCommandTextProtocol(data, dataLen, prevLayer, packet) |
23 | 585 | { |
24 | 585 | m_Protocol = SMTP; |
25 | 585 | }; |
26 | | |
27 | | SmtpLayer(const std::string &command, const std::string &option) : SingleCommandTextProtocol(command, option) |
28 | 0 | { |
29 | 0 | m_Protocol = SMTP; |
30 | 0 | }; |
31 | | |
32 | | public: |
33 | | /** |
34 | | * A static method that checks whether the port is considered as SMTP control |
35 | | * @param[in] port The port number to be checked |
36 | | * @return True if this an SMTP port (25 or 587) |
37 | | */ |
38 | 196k | static bool isSmtpPort(uint16_t port) { return port == 25 || port == 587; } |
39 | | |
40 | | // overridden methods |
41 | | |
42 | | /// SMTP is the always last so does nothing for this layer |
43 | 585 | void parseNextLayer() {} |
44 | | |
45 | | /** |
46 | | * @return Get the size of the layer |
47 | | */ |
48 | 117 | size_t getHeaderLen() const { return m_DataLen; } |
49 | | |
50 | | /// Does nothing for this layer |
51 | 117 | void computeCalculateFields() {} |
52 | | |
53 | | /** |
54 | | * @return The OSI layer level of SMTP (Application Layer). |
55 | | */ |
56 | 117 | OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } |
57 | | }; |
58 | | |
59 | | /** |
60 | | * Class for representing the request messages of SMTP Layer |
61 | | */ |
62 | | class SmtpRequestLayer : public SmtpLayer |
63 | | { |
64 | | public: |
65 | | /** |
66 | | * Enum for SMTP command codes |
67 | | */ |
68 | | enum class SmtpCommand : uint64_t |
69 | | { |
70 | | /// Unknown command |
71 | | UNK, |
72 | | /// Starting mail body |
73 | | DATA = ('D') | ('A' << 8) | ('T' << 16) | ('A' << 24), |
74 | | /// Initiate conversation |
75 | | EHLO = ('E') | ('H' << 8) | ('L' << 16) | ('O' << 24), |
76 | | /// Expand the mailing list |
77 | | EXPN = ('E') | ('X' << 8) | ('P' << 16) | ('N' << 24), |
78 | | /// Initiate conversation |
79 | | HELO = ('H') | ('E' << 8) | ('L' << 16) | ('O' << 24), |
80 | | /// Ask information |
81 | | HELP = ('H') | ('E' << 8) | ('L' << 16) | ('P' << 24), |
82 | | /// Sender indication |
83 | | MAIL = ('M') | ('A' << 8) | ('I' << 16) | ('L' << 24), |
84 | | /// No operation |
85 | | NOOP = ('N') | ('O' << 8) | ('O' << 16) | ('P' << 24), |
86 | | /// Close conversation |
87 | | QUIT = ('Q') | ('U' << 8) | ('I' << 16) | ('T' << 24), |
88 | | /// Receiver indication |
89 | | RCPT = ('R') | ('C' << 8) | ('P' << 16) | ('T' << 24), |
90 | | /// Abort transaction |
91 | | RSET = ('R') | ('S' << 8) | ('E' << 16) | ('T' << 24), |
92 | | /// Identify user |
93 | | VRFY = ('V') | ('R' << 8) | ('F' << 16) | ('Y' << 24), |
94 | | /// Start TLS handshake |
95 | | STARTTLS = (('S') | ('T' << 8) | ('A' << 16) | ('R' << 24) | |
96 | | static_cast<uint64_t>(('T') | ('T' << 8) | ('L' << 16) | ('S' << 24)) << 32), |
97 | | /// Reverse the role of sender and receiver |
98 | | TURN = ('T') | ('U' << 8) | ('R' << 16) | ('N' << 24), |
99 | | /// Send mail to terminal |
100 | | SEND = ('S') | ('E' << 8) | ('N' << 16) | ('D' << 24), |
101 | | /// Send mail to terminal or to mailbox |
102 | | SOML = ('S') | ('O' << 8) | ('M' << 16) | ('L' << 24), |
103 | | /// Send mail to terminal and mailbox |
104 | | SAML = ('S') | ('A' << 8) | ('M' << 16) | ('L' << 24), |
105 | | /// Authenticate client and server |
106 | | AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24), |
107 | | /// Reverse the role of sender and receiver |
108 | | ATRN = ('A') | ('T' << 8) | ('R' << 16) | ('N' << 24), |
109 | | /// Submit mail contents |
110 | | BDAT = ('B') | ('D' << 8) | ('A' << 16) | ('T' << 24), |
111 | | /// Request to start SMTP queue processing |
112 | | ETRN = ('E') | ('T' << 8) | ('R' << 16) | ('N' << 24), |
113 | | /// Release status of the channel |
114 | | XADR = ('X') | ('A' << 8) | ('D' << 16) | ('R' << 24), |
115 | | /// Release status of the circuit checking facility |
116 | | XCIR = ('X') | ('C' << 8) | ('I' << 16) | ('R' << 24), |
117 | | /// Release status of the number of messages in channel queues |
118 | | XSTA = ('X') | ('S' << 8) | ('T' << 16) | ('A' << 24), |
119 | | /// Release status of whether a compiled configuration and character set are in use |
120 | | XGEN = ('X') | ('G' << 8) | ('E' << 16) | ('N' << 24) |
121 | | }; |
122 | | |
123 | | /** A constructor that creates the layer from an existing packet raw data |
124 | | * @param[in] data A pointer to the raw data |
125 | | * @param[in] dataLen Size of the data in bytes |
126 | | * @param[in] prevLayer A pointer to the previous layer |
127 | | * @param[in] packet A pointer to the Packet instance where layer will be stored in |
128 | | */ |
129 | | SmtpRequestLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) |
130 | 175 | : SmtpLayer(data, dataLen, prevLayer, packet){}; |
131 | | |
132 | | /** |
133 | | * A constructor that creates layer with provided input values |
134 | | * @param[in] command SMTP command |
135 | | * @param[in] option Argument of the command |
136 | | */ |
137 | | explicit SmtpRequestLayer(const SmtpCommand &command, const std::string &option = "") |
138 | 0 | : SmtpLayer(getCommandAsString(command), option){}; |
139 | | |
140 | | /** |
141 | | * Set the command of request message |
142 | | * @param[in] code Value to set command |
143 | | * @return True if the operation is successful, false otherwise |
144 | | */ |
145 | | bool setCommand(SmtpCommand code); |
146 | | |
147 | | /** |
148 | | * Get the command of request message |
149 | | * @return Value of the command |
150 | | */ |
151 | | SmtpCommand getCommand() const; |
152 | | |
153 | | /** |
154 | | * Get the command of request message as string |
155 | | * @return Value of the command as string |
156 | | */ |
157 | | std::string getCommandString() const; |
158 | | |
159 | | /** |
160 | | * Set the command argument of request message |
161 | | * @param[in] value Value to set command argument |
162 | | * @return True if the operation is successful, false otherwise |
163 | | */ |
164 | | bool setCommandOption(const std::string &value); |
165 | | |
166 | | /** |
167 | | * Get the command argument of request message |
168 | | * @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not |
169 | | * @return Value of command argument |
170 | | */ |
171 | | std::string getCommandOption(bool removeEscapeCharacters = true) const; |
172 | | |
173 | | /** |
174 | | * Convert the command info to readable string |
175 | | * @param[in] code Command code to convert |
176 | | * @return Returns the command info as readable string |
177 | | */ |
178 | | static std::string getCommandInfo(SmtpCommand code); |
179 | | |
180 | | /** |
181 | | * Convert the command to readable string |
182 | | * @param[in] code Command code to convert |
183 | | * @return Returns the command as readable string |
184 | | */ |
185 | | static std::string getCommandAsString(SmtpCommand code); |
186 | | |
187 | | // overridden methods |
188 | | |
189 | | /** |
190 | | * @return Returns the protocol info as readable string |
191 | | */ |
192 | | std::string toString() const; |
193 | | }; |
194 | | |
195 | | /** |
196 | | * Class for representing the response messages of SMTP Layer |
197 | | */ |
198 | | class SmtpResponseLayer : public SmtpLayer |
199 | | { |
200 | | public: |
201 | | /** |
202 | | * Enum for SMTP response codes |
203 | | */ |
204 | | enum class SmtpStatusCode : int |
205 | | { |
206 | | /// System status, or system help reply |
207 | | SYSTEM_STATUS = 211, |
208 | | /// Help message |
209 | | HELP_MESSAGE = 214, |
210 | | /// \<domain\> Service ready |
211 | | SERVICE_READY = 220, |
212 | | /// \<domain\> Service closing transmission channel |
213 | | SERVICE_CLOSE = 221, |
214 | | /// Authentication successful |
215 | | AUTH_SUCCESS = 235, |
216 | | /// Requested mail action okay, completed |
217 | | COMPLETED = 250, |
218 | | /// User not local; will forward to <forward-path> |
219 | | WILL_FORWARD = 251, |
220 | | /// Cannot VRFY user, but will accept message and attempt delivery |
221 | | CANNOT_VERIFY = 252, |
222 | | /// AUTH input |
223 | | AUTH_INPUT = 334, |
224 | | /// Start mail input; end with \<CRLF\>.\<CRLF\> |
225 | | MAIL_INPUT = 354, |
226 | | /// \<domain\> Service not available, closing transmission channel |
227 | | SERVICE_UNAVAILABLE = 421, |
228 | | /// A password transition is needed |
229 | | PASS_NEEDED = 432, |
230 | | /// Requested mail action not taken: mailbox unavailable (mail busy or temporarily blocked) |
231 | | MAILBOX_UNAVAILABLE_TEMP = 450, |
232 | | /// Requested action aborted: local error in processing |
233 | | ABORT_LOCAL_ERROR = 451, |
234 | | /// Requested action not taken: insufficient system storage |
235 | | INSUFFICIENT_STORAGE = 452, |
236 | | /// Temporary authentication failed |
237 | | TEMP_AUTH_FAILED = 454, |
238 | | /// Server unable to accommodate parameters |
239 | | PARAM_NOT_ACCOMMODATED = 455, |
240 | | /// Syntax error, command unrecognized |
241 | | CMD_NOT_RECOGNIZED = 500, |
242 | | /// Syntax error in parameters or arguments |
243 | | SYNTAX_ERROR_PARAM = 501, |
244 | | /// Command not implemented |
245 | | CMD_NOT_IMPLEMENTED = 502, |
246 | | /// Bad sequence of commands |
247 | | CMD_BAD_SEQUENCE = 503, |
248 | | /// Command parameter not implemented |
249 | | PARAM_NOT_IMPLEMENTED = 504, |
250 | | /// Server does not accept mail |
251 | | MAIL_NOT_ACCEPTED = 521, |
252 | | /// Encryption needed |
253 | | ENCRYPT_NEED = 523, |
254 | | /// Authentication required |
255 | | AUTH_REQUIRED = 530, |
256 | | /// Authentication mechanism is too weak |
257 | | AUTH_TOO_WEAK = 534, |
258 | | /// Authentication credentials invalid |
259 | | AUTH_CRED_INVALID = 535, |
260 | | /// Encryption required for requested authentication mechanism |
261 | | ENCRYPT_REQUIRED = 538, |
262 | | /// Requested action not taken: mailbox unavailable |
263 | | MAILBOX_UNAVAILABLE = 550, |
264 | | /// User not local; please try <forward-path> |
265 | | USER_NOT_LOCAL = 551, |
266 | | /// Requested mail action aborted: exceeded storage allocation |
267 | | EXCEED_STORAGE = 552, |
268 | | /// Requested action not taken: mailbox name not allowed |
269 | | NAME_NOT_ALLOWED = 553, |
270 | | /// Transaction failed |
271 | | TRANSACTION_FAIL = 554, |
272 | | /// Domain does not accept mail |
273 | | DOMAIN_NOT_ACCEPT = 556 |
274 | | }; |
275 | | |
276 | | /** A constructor that creates the layer from an existing packet raw data |
277 | | * @param[in] data A pointer to the raw data |
278 | | * @param[in] dataLen Size of the data in bytes |
279 | | * @param[in] prevLayer A pointer to the previous layer |
280 | | * @param[in] packet A pointer to the Packet instance where layer will be stored in |
281 | | */ |
282 | | SmtpResponseLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) |
283 | 410 | : SmtpLayer(data, dataLen, prevLayer, packet){}; |
284 | | |
285 | | /** |
286 | | * A constructor that creates layer with provided input values |
287 | | * @param[in] code Status code |
288 | | * @param[in] option Argument of the status code |
289 | | */ |
290 | | explicit SmtpResponseLayer(const SmtpStatusCode &code, const std::string &option = "") |
291 | 0 | : SmtpLayer(std::to_string(int(code)), option){}; |
292 | | |
293 | | /** |
294 | | * Set the status code of response message |
295 | | * @param[in] code Value to set status code |
296 | | * @return True if the operation is successful, false otherwise |
297 | | */ |
298 | | bool setStatusCode(SmtpStatusCode code); |
299 | | |
300 | | /** |
301 | | * Get the status code of response message |
302 | | * @return Value of the status code |
303 | | */ |
304 | | SmtpStatusCode getStatusCode() const; |
305 | | |
306 | | /** |
307 | | * Get the status code of response message as string |
308 | | * @return Value of the status code as string |
309 | | */ |
310 | | std::string getStatusCodeString() const; |
311 | | |
312 | | /** |
313 | | * Set the argument of response message |
314 | | * @param[in] value Value to set argument |
315 | | * @return True if the operation is successful, false otherwise |
316 | | */ |
317 | | bool setStatusOption(const std::string &value); |
318 | | |
319 | | /** |
320 | | * Get the argument of response message |
321 | | * @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not |
322 | | * @return Value of argument |
323 | | */ |
324 | | std::string getStatusOption(bool removeEscapeCharacters = true) const; |
325 | | |
326 | | /** |
327 | | * Convert the status code to readable string |
328 | | * @param[in] code Status code to convert |
329 | | * @return Returns the status info as readable string |
330 | | */ |
331 | | static std::string getStatusCodeAsString(SmtpStatusCode code); |
332 | | |
333 | | // overridden methods |
334 | | |
335 | | /** |
336 | | * @return Returns the protocol info as readable string |
337 | | */ |
338 | | std::string toString() const; |
339 | | }; |
340 | | } // namespace pcpp |
341 | | |
342 | | #endif /* PACKETPP_SMTP_LAYER */ |