Coverage Report

Created: 2024-02-25 06:29

/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 */