Coverage Report

Created: 2025-07-11 07:47

/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