Coverage Report

Created: 2026-02-14 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/SmtpLayer.cpp
Line
Count
Source
1
#define LOG_MODULE PacketLogModuleSmtpLayer
2
3
#include "SmtpLayer.h"
4
5
#include <algorithm>
6
7
namespace pcpp
8
{
9
  // ----------------- Class SmtpRequestLayer -----------------
10
  bool SmtpRequestLayer::setCommand(SmtpCommand code)
11
0
  {
12
0
    return setCommandInternal(getCommandAsString(code));
13
0
  }
14
15
  SmtpRequestLayer::SmtpCommand SmtpRequestLayer::getCommand() const
16
3.38k
  {
17
3.38k
    size_t val = 0;
18
3.38k
    std::string field = getCommandString();
19
20
18.1k
    for (size_t idx = 0; idx < std::min(field.size(), static_cast<size_t>(8)); ++idx)
21
14.8k
    {
22
14.8k
      val |= static_cast<size_t>(field.c_str()[idx]) << (idx * 8);
23
14.8k
    }
24
25
3.38k
    return static_cast<SmtpCommand>(val);
26
3.38k
  }
27
28
  std::string SmtpRequestLayer::getCommandString() const
29
3.38k
  {
30
3.38k
    return getCommandInternal();
31
3.38k
  }
32
33
  bool SmtpRequestLayer::setCommandOption(const std::string& value)
34
0
  {
35
0
    return setCommandOptionInternal(value);
36
0
  }
37
38
  std::string SmtpRequestLayer::getCommandOption(bool removeEscapeCharacters) const
39
0
  {
40
0
    std::string option = getCommandOptionInternal();
41
0
    if (!removeEscapeCharacters)
42
0
    {
43
0
      return option;
44
0
    }
45
46
0
    std::string optionWithEscapeChars;
47
0
    std::copy_if(option.begin(), option.end(), std::back_inserter(optionWithEscapeChars),
48
0
                 [](char ch) { return ch < 127 && ch > 31; });
49
50
0
    return optionWithEscapeChars;
51
0
  }
52
53
  std::string SmtpRequestLayer::getCommandInfo(SmtpCommand code)
54
3.38k
  {
55
3.38k
    switch (code)
56
3.38k
    {
57
294
    case SmtpCommand::DATA:
58
294
      return "Starting mail body";
59
102
    case SmtpCommand::EHLO:
60
102
      return "Initiate conversation";
61
0
    case SmtpCommand::EXPN:
62
0
      return "Expand the mailing list";
63
60
    case SmtpCommand::HELO:
64
60
      return "Initiate conversation";
65
8
    case SmtpCommand::HELP:
66
8
      return "Ask information";
67
118
    case SmtpCommand::MAIL:
68
118
      return "Sender indication";
69
0
    case SmtpCommand::NOOP:
70
0
      return "No operation";
71
6
    case SmtpCommand::QUIT:
72
6
      return "Close conversation";
73
276
    case SmtpCommand::RCPT:
74
276
      return "Receiver indication";
75
0
    case SmtpCommand::RSET:
76
0
      return "Abort transaction";
77
0
    case SmtpCommand::VRFY:
78
0
      return "Identify user";
79
0
    case SmtpCommand::STARTTLS:
80
0
      return "Start TLS handshake";
81
0
    case SmtpCommand::TURN:
82
0
      return "Reverse the role of sender and receiver";
83
0
    case SmtpCommand::SEND:
84
0
      return "Send mail to terminal";
85
0
    case SmtpCommand::SOML:
86
0
      return "Send mail to terminal or to mailbox";
87
0
    case SmtpCommand::SAML:
88
0
      return "Send mail to terminal and mailbox";
89
660
    case SmtpCommand::AUTH:
90
660
      return "Authenticate client and server";
91
0
    case SmtpCommand::ATRN:
92
0
      return "Reverse the role of sender and receiver";
93
0
    case SmtpCommand::BDAT:
94
0
      return "Submit mail contents";
95
0
    case SmtpCommand::ETRN:
96
0
      return "Request to start SMTP queue processing";
97
0
    case SmtpCommand::XADR:
98
0
      return "Release status of the channel";
99
0
    case SmtpCommand::XCIR:
100
0
      return "Release status of the circuit checking facility";
101
0
    case SmtpCommand::XSTA:
102
0
      return "Release status of the number of messages in channel queues";
103
0
    case SmtpCommand::XGEN:
104
0
      return "Release status of whether a compiled configuration and character set are in use";
105
1.86k
    default:
106
1.86k
      return "Unknown command";
107
3.38k
    }
108
3.38k
  }
109
110
  std::string SmtpRequestLayer::getCommandAsString(SmtpCommand code)
111
0
  {
112
0
    std::stringstream oss;
113
0
    for (size_t idx = 0; idx < 8; ++idx)
114
0
    {
115
0
      char val = (uint64_t(code) >> (8 * idx)) & UINT8_MAX;
116
0
      if (val)  // Dont push if it is a null character
117
0
      {
118
0
        oss << val;
119
0
      }
120
0
    }
121
0
    return oss.str();
122
0
  }
123
124
  std::string SmtpRequestLayer::toString() const
125
3.38k
  {
126
3.38k
    return "SMTP request layer, command: " + getCommandInfo(getCommand());
127
3.38k
  }
128
129
  // ----------------- Class SmtpResponseLayer -----------------
130
  bool SmtpResponseLayer::setStatusCode(SmtpStatusCode code)
131
0
  {
132
0
    std::ostringstream oss;
133
0
    oss << int(code);
134
0
    return setCommandInternal(oss.str());
135
0
  }
136
137
  SmtpResponseLayer::SmtpStatusCode SmtpResponseLayer::getStatusCode() const
138
2.46k
  {
139
2.46k
    return static_cast<SmtpStatusCode>(atoi(getCommandInternal().c_str()));
140
2.46k
  }
141
142
  std::string SmtpResponseLayer::getStatusCodeString() const
143
0
  {
144
0
    return getCommandInternal();
145
0
  }
146
147
  bool SmtpResponseLayer::setStatusOption(const std::string& value)
148
0
  {
149
0
    return setCommandOptionInternal(value);
150
0
  }
151
152
  std::string SmtpResponseLayer::getStatusOption(bool removeEscapeCharacters) const
153
0
  {
154
0
    std::string option = getCommandOptionInternal();
155
0
    if (!removeEscapeCharacters)
156
0
    {
157
0
      return option;
158
0
    }
159
160
0
    std::string optionWithEscapeChars;
161
0
    std::copy_if(option.begin(), option.end(), std::back_inserter(optionWithEscapeChars),
162
0
                 [](char ch) { return ch < 127 && ch > 31; });
163
164
0
    return optionWithEscapeChars;
165
0
  }
166
167
  std::string SmtpResponseLayer::getStatusCodeAsString(SmtpStatusCode code)
168
2.46k
  {
169
2.46k
    switch (code)
170
2.46k
    {
171
6
    case SmtpStatusCode::SYSTEM_STATUS:
172
6
      return "System status, or system help reply";
173
62
    case SmtpStatusCode::HELP_MESSAGE:
174
62
      return "Help message";
175
180
    case SmtpStatusCode::SERVICE_READY:
176
180
      return "Service ready";
177
38
    case SmtpStatusCode::SERVICE_CLOSE:
178
38
      return "Service closing transmission channel";
179
78
    case SmtpStatusCode::AUTH_SUCCESS:
180
78
      return "Authentication successful";
181
340
    case SmtpStatusCode::COMPLETED:
182
340
      return "Requested mail action okay, completed";
183
280
    case SmtpStatusCode::WILL_FORWARD:
184
280
      return "User not local; will forward to <forward-path>";
185
20
    case SmtpStatusCode::CANNOT_VERIFY:
186
20
      return "Cannot VRFY user, but will accept message and attempt delivery";
187
118
    case SmtpStatusCode::AUTH_INPUT:
188
118
      return "AUTH input";
189
68
    case SmtpStatusCode::MAIL_INPUT:
190
68
      return "Start mail input; end with <CRLF>.<CRLF>";
191
14
    case SmtpStatusCode::SERVICE_UNAVAILABLE:
192
14
      return "Service not available, closing transmission channel";
193
2
    case SmtpStatusCode::PASS_NEEDED:
194
2
      return "A password transition is needed";
195
6
    case SmtpStatusCode::MAILBOX_UNAVAILABLE_TEMP:
196
6
      return "Requested mail action not taken: mailbox unavailable (mail busy or temporarily blocked)";
197
22
    case SmtpStatusCode::ABORT_LOCAL_ERROR:
198
22
      return "Requested action aborted: local error in processing";
199
64
    case SmtpStatusCode::INSUFFICIENT_STORAGE:
200
64
      return "Requested action not taken: insufficient system storage";
201
14
    case SmtpStatusCode::TEMP_AUTH_FAILED:
202
14
      return "Temporary authentication failed";
203
2
    case SmtpStatusCode::PARAM_NOT_ACCOMMODATED:
204
2
      return "Server unable to accommodate parameters";
205
32
    case SmtpStatusCode::CMD_NOT_RECOGNIZED:
206
32
      return "Syntax error, command unrecognized";
207
6
    case SmtpStatusCode::SYNTAX_ERROR_PARAM:
208
6
      return "Syntax error in parameters or arguments";
209
120
    case SmtpStatusCode::CMD_NOT_IMPLEMENTED:
210
120
      return "Command not implemented";
211
334
    case SmtpStatusCode::CMD_BAD_SEQUENCE:
212
334
      return "Bad sequence of commands";
213
62
    case SmtpStatusCode::PARAM_NOT_IMPLEMENTED:
214
62
      return "Command parameter not implemented";
215
14
    case SmtpStatusCode::MAIL_NOT_ACCEPTED:
216
14
      return "Server does not accept mail";
217
14
    case SmtpStatusCode::ENCRYPT_NEED:
218
14
      return "Encryption needed";
219
30
    case SmtpStatusCode::AUTH_REQUIRED:
220
30
      return "Authentication required";
221
30
    case SmtpStatusCode::AUTH_TOO_WEAK:
222
30
      return "Authentication mechanism is too weak";
223
30
    case SmtpStatusCode::AUTH_CRED_INVALID:
224
30
      return "Authentication credentials invalid";
225
2
    case SmtpStatusCode::ENCRYPT_REQUIRED:
226
2
      return "Encryption required for requested authentication mechanism";
227
62
    case SmtpStatusCode::MAILBOX_UNAVAILABLE:
228
62
      return "Requested action not taken: mailbox unavailable";
229
62
    case SmtpStatusCode::USER_NOT_LOCAL:
230
62
      return "User not local; please try <forward-path>";
231
34
    case SmtpStatusCode::EXCEED_STORAGE:
232
34
      return "Requested mail action aborted: exceeded storage allocation";
233
6
    case SmtpStatusCode::NAME_NOT_ALLOWED:
234
6
      return "Requested action not taken: mailbox name not allowed";
235
14
    case SmtpStatusCode::TRANSACTION_FAIL:
236
14
      return "Transaction failed";
237
2
    case SmtpStatusCode::DOMAIN_NOT_ACCEPT:
238
2
      return "Domain does not accept mail";
239
294
    default:
240
294
      return "Unknown status code";
241
2.46k
    }
242
2.46k
  }
243
244
  std::string SmtpResponseLayer::toString() const
245
2.46k
  {
246
2.46k
    return "SMTP response layer, status code: " + getStatusCodeAsString(getStatusCode());
247
2.46k
  }
248
249
}  // namespace pcpp