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