Coverage Report

Created: 2026-03-07 06:49

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.18k
  {
17
3.18k
    size_t val = 0;
18
3.18k
    std::string field = getCommandString();
19
20
17.0k
    for (size_t idx = 0; idx < std::min(field.size(), static_cast<size_t>(8)); ++idx)
21
13.8k
    {
22
13.8k
      val |= static_cast<size_t>(field.c_str()[idx]) << (idx * 8);
23
13.8k
    }
24
25
3.18k
    return static_cast<SmtpCommand>(val);
26
3.18k
  }
27
28
  std::string SmtpRequestLayer::getCommandString() const
29
3.18k
  {
30
3.18k
    return getCommandInternal();
31
3.18k
  }
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.18k
  {
55
3.18k
    switch (code)
56
3.18k
    {
57
258
    case SmtpCommand::DATA:
58
258
      return "Starting mail body";
59
108
    case SmtpCommand::EHLO:
60
108
      return "Initiate conversation";
61
0
    case SmtpCommand::EXPN:
62
0
      return "Expand the mailing list";
63
44
    case SmtpCommand::HELO:
64
44
      return "Initiate conversation";
65
6
    case SmtpCommand::HELP:
66
6
      return "Ask information";
67
114
    case SmtpCommand::MAIL:
68
114
      return "Sender indication";
69
0
    case SmtpCommand::NOOP:
70
0
      return "No operation";
71
6
    case SmtpCommand::QUIT:
72
6
      return "Close conversation";
73
290
    case SmtpCommand::RCPT:
74
290
      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
474
    case SmtpCommand::AUTH:
90
474
      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.88k
    default:
106
1.88k
      return "Unknown command";
107
3.18k
    }
108
3.18k
  }
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.18k
  {
126
3.18k
    return "SMTP request layer, command: " + getCommandInfo(getCommand());
127
3.18k
  }
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.54k
  {
139
2.54k
    return static_cast<SmtpStatusCode>(atoi(getCommandInternal().c_str()));
140
2.54k
  }
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.54k
  {
169
2.54k
    switch (code)
170
2.54k
    {
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
168
    case SmtpStatusCode::SERVICE_READY:
176
168
      return "Service ready";
177
36
    case SmtpStatusCode::SERVICE_CLOSE:
178
36
      return "Service closing transmission channel";
179
92
    case SmtpStatusCode::AUTH_SUCCESS:
180
92
      return "Authentication successful";
181
370
    case SmtpStatusCode::COMPLETED:
182
370
      return "Requested mail action okay, completed";
183
240
    case SmtpStatusCode::WILL_FORWARD:
184
240
      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
160
    case SmtpStatusCode::AUTH_INPUT:
188
160
      return "AUTH input";
189
68
    case SmtpStatusCode::MAIL_INPUT:
190
68
      return "Start mail input; end with <CRLF>.<CRLF>";
191
30
    case SmtpStatusCode::SERVICE_UNAVAILABLE:
192
30
      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
14
    case SmtpStatusCode::ABORT_LOCAL_ERROR:
198
14
      return "Requested action aborted: local error in processing";
199
62
    case SmtpStatusCode::INSUFFICIENT_STORAGE:
200
62
      return "Requested action not taken: insufficient system storage";
201
14
    case SmtpStatusCode::TEMP_AUTH_FAILED:
202
14
      return "Temporary authentication failed";
203
14
    case SmtpStatusCode::PARAM_NOT_ACCOMMODATED:
204
14
      return "Server unable to accommodate parameters";
205
42
    case SmtpStatusCode::CMD_NOT_RECOGNIZED:
206
42
      return "Syntax error, command unrecognized";
207
6
    case SmtpStatusCode::SYNTAX_ERROR_PARAM:
208
6
      return "Syntax error in parameters or arguments";
209
96
    case SmtpStatusCode::CMD_NOT_IMPLEMENTED:
210
96
      return "Command not implemented";
211
274
    case SmtpStatusCode::CMD_BAD_SEQUENCE:
212
274
      return "Bad sequence of commands";
213
60
    case SmtpStatusCode::PARAM_NOT_IMPLEMENTED:
214
60
      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
62
    case SmtpStatusCode::AUTH_TOO_WEAK:
222
62
      return "Authentication mechanism is too weak";
223
62
    case SmtpStatusCode::AUTH_CRED_INVALID:
224
62
      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
64
    case SmtpStatusCode::USER_NOT_LOCAL:
230
64
      return "User not local; please try <forward-path>";
231
44
    case SmtpStatusCode::EXCEED_STORAGE:
232
44
      return "Requested mail action aborted: exceeded storage allocation";
233
30
    case SmtpStatusCode::NAME_NOT_ALLOWED:
234
30
      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
300
    default:
240
300
      return "Unknown status code";
241
2.54k
    }
242
2.54k
  }
243
244
  std::string SmtpResponseLayer::toString() const
245
2.54k
  {
246
2.54k
    return "SMTP response layer, status code: " + getStatusCodeAsString(getStatusCode());
247
2.54k
  }
248
249
}  // namespace pcpp