Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/header/FtpLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "SingleCommandTextProtocol.h"
4
#include "PayloadLayer.h"
5
6
/// @file
7
8
/// @namespace pcpp
9
/// @brief The main namespace for the PcapPlusPlus lib
10
namespace pcpp
11
{
12
  /// Class for general FTP message
13
  class FtpLayer : public SingleCommandTextProtocol
14
  {
15
  protected:
16
    FtpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
17
0
        : SingleCommandTextProtocol(data, dataLen, prevLayer, packet, FTP) {};
18
    FtpLayer(const std::string& command, const std::string& option)
19
0
        : SingleCommandTextProtocol(command, option, FTP) {};
20
21
  public:
22
    /// A static method that checks whether the port is considered as FTP control
23
    /// @param[in] port The port number to be checked
24
    static bool isFtpPort(uint16_t port)
25
106k
    {
26
106k
      return port == 21;
27
106k
    }
28
29
    /// A static method that checks whether the port is considered as FTP data
30
    /// @param[in] port The port number to be checked
31
    static bool isFtpDataPort(uint16_t port)
32
106k
    {
33
106k
      return port == 20;
34
106k
    }
35
36
    // overridden methods
37
38
    /// FTP is the always last so does nothing for this layer
39
    void parseNextLayer() override
40
0
    {}
41
42
    /// @return Get the size of the layer
43
    size_t getHeaderLen() const override
44
0
    {
45
0
      return m_DataLen;
46
0
    }
47
48
    /// Does nothing for this layer
49
    void computeCalculateFields() override
50
0
    {}
51
52
    /// @return The OSI layer level of FTP (Application Layer).
53
    OsiModelLayer getOsiModelLayer() const override
54
0
    {
55
0
      return OsiModelApplicationLayer;
56
0
    }
57
  };
58
59
  /// Class for representing the request messages of FTP Layer
60
  class FtpRequestLayer : public FtpLayer
61
  {
62
  public:
63
    /// Enum for FTP command codes
64
    enum class FtpCommand : int
65
    {
66
      /// Unknown command
67
      UNK,
68
      /// Abort an active file transfer.
69
      ABOR = ('A') | ('B' << 8) | ('O' << 16) | ('R' << 24),
70
      /// Account information.
71
      ACCT = ('A') | ('C' << 8) | ('C' << 16) | ('T' << 24),
72
      /// Authentication/Security Data
73
      ADAT = ('A') | ('D' << 8) | ('A' << 16) | ('T' << 24),
74
      /// Allocate sufficient disk space to receive a file.
75
      ALLO = ('A') | ('L' << 8) | ('L' << 16) | ('O' << 24),
76
      /// Append (with create)
77
      APPE = ('A') | ('P' << 8) | ('P' << 16) | ('E' << 24),
78
      /// Authentication/Security Mechanism
79
      AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24),
80
      /// Get the available space
81
      AVBL = ('A') | ('V' << 8) | ('B' << 16) | ('L' << 24),
82
      /// Clear Command Channel
83
      CCC = ('C') | ('C' << 8) | ('C' << 16),
84
      /// Change to Parent Directory.
85
      CDUP = ('C') | ('D' << 8) | ('U' << 16) | ('P' << 24),
86
      /// Confidentiality Protection Command
87
      CONF = ('C') | ('O' << 8) | ('N' << 16) | ('F' << 24),
88
      /// Client / Server Identification
89
      CSID = ('C') | ('S' << 8) | ('I' << 16) | ('D' << 24),
90
      /// Change working directory.
91
      CWD = ('C') | ('W' << 8) | ('D' << 16),
92
      /// Delete file.
93
      DELE = ('D') | ('E' << 8) | ('L' << 16) | ('E' << 24),
94
      /// Get the directory size
95
      DSIZ = ('D') | ('S' << 8) | ('I' << 16) | ('Z' << 24),
96
      /// Privacy Protected Channel
97
      ENC = ('E') | ('N' << 8) | ('C' << 16),
98
      /// Specifies an extended address and port to which the server should connect.
99
      EPRT = ('E') | ('P' << 8) | ('R' << 16) | ('T' << 24),
100
      /// Enter extended passive mode.
101
      EPSV = ('E') | ('P' << 8) | ('S' << 16) | ('V' << 24),
102
      /// Get the feature list implemented by the server.
103
      FEAT = ('F') | ('E' << 8) | ('A' << 16) | ('T' << 24),
104
      /// Returns usage documentation on a command if specified, else a general help document is returned.
105
      HELP = ('H') | ('E' << 8) | ('L' << 16) | ('P' << 24),
106
      /// Identify desired virtual host on server, by name.
107
      HOST = ('H') | ('O' << 8) | ('S' << 16) | ('T' << 24),
108
      /// Language Negotiation
109
      LANG = ('L') | ('A' << 8) | ('N' << 16) | ('G' << 24),
110
      /// Returns information of a file or directory if specified, else information of the current working
111
      /// directory is returned.
112
      LIST = ('L') | ('I' << 8) | ('S' << 16) | ('T' << 24),
113
      /// Specifies a long address and port to which the server should connect.
114
      LPRT = ('L') | ('P' << 8) | ('R' << 16) | ('T' << 24),
115
      /// Enter long passive mode.
116
      LPSV = ('L') | ('P' << 8) | ('S' << 16) | ('V' << 24),
117
      /// Return the last-modified time of a specified file.
118
      MDTM = ('M') | ('D' << 8) | ('T' << 16) | ('M' << 24),
119
      /// Modify the creation time of a file.
120
      MFCT = ('M') | ('F' << 8) | ('C' << 16) | ('T' << 24),
121
      /// Modify fact (the last modification time, creation time, UNIX group/owner/mode of a file).
122
      MFF = ('M') | ('F' << 8) | ('F' << 16),
123
      /// Modify the last modification time of a file.
124
      MFMT = ('M') | ('F' << 8) | ('M' << 16) | ('T' << 24),
125
      /// Integrity Protected Command
126
      MIC = ('M') | ('I' << 8) | ('C' << 16),
127
      /// Make directory.
128
      MKD = ('M') | ('K' << 8) | ('D' << 16),
129
      /// Lists the contents of a directory in a standardized machine-readable format.
130
      MLSD = ('M') | ('L' << 8) | ('S' << 16) | ('D' << 24),
131
      /// Provides data about exactly the object named on its command line in a standardized machine-readable
132
      /// format.
133
      MLST = ('M') | ('L' << 8) | ('S' << 16) | ('T' << 24),
134
      /// Sets the transfer mode (Stream, Block, or Compressed).
135
      MODE = ('M') | ('O' << 8) | ('D' << 16) | ('E' << 24),
136
      /// Returns a list of file names in a specified directory.
137
      NLST = ('N') | ('L' << 8) | ('S' << 16) | ('T' << 24),
138
      /// No operation (dummy packet; used mostly on keepalives).
139
      NOOP = ('N') | ('O' << 8) | ('O' << 16) | ('P' << 24),
140
      /// Select options for a feature (for example OPTS UTF8 ON).
141
      OPTS = ('O') | ('P' << 8) | ('T' << 16) | ('S' << 24),
142
      /// Authentication password.
143
      PASS = ('P') | ('A' << 8) | ('S' << 16) | ('S' << 24),
144
      /// Enter passive mode.
145
      PASV = ('P') | ('A' << 8) | ('S' << 16) | ('V' << 24),
146
      /// Protection Buffer Size
147
      PBSZ = ('P') | ('B' << 8) | ('S' << 16) | ('Z' << 24),
148
      /// Specifies an address and port to which the server should connect.
149
      PORT = ('P') | ('O' << 8) | ('R' << 16) | ('T' << 24),
150
      /// Data Channel Protection Level.
151
      PROT = ('P') | ('R' << 8) | ('O' << 16) | ('T' << 24),
152
      /// Print working directory. Returns the current directory of the host.
153
      PWD = ('P') | ('W' << 8) | ('D' << 16),
154
      /// Disconnect.
155
      QUIT = ('Q') | ('U' << 8) | ('I' << 16) | ('T' << 24),
156
      /// Re initializes the connection.
157
      REIN = ('R') | ('E' << 8) | ('I' << 16) | ('N' << 24),
158
      /// Restart transfer from the specified point.
159
      REST = ('R') | ('E' << 8) | ('S' << 16) | ('T' << 24),
160
      /// Retrieve a copy of the file
161
      RETR = ('R') | ('E' << 8) | ('T' << 16) | ('R' << 24),
162
      /// Remove a directory.
163
      RMD = ('R') | ('M' << 8) | ('D' << 16),
164
      /// Remove a directory tree
165
      RMDA = ('R') | ('M' << 8) | ('D' << 16) | ('A' << 24),
166
      /// Rename from.
167
      RNFR = ('R') | ('N' << 8) | ('F' << 16) | ('R' << 24),
168
      /// Rename to.
169
      RNTO = ('R') | ('N' << 8) | ('T' << 16) | ('O' << 24),
170
      /// Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP
171
      /// output for complete list of supported commands.
172
      SITE = ('S') | ('I' << 8) | ('T' << 16) | ('E' << 24),
173
      /// Return the size of a file.
174
      SIZE = ('S') | ('I' << 8) | ('Z' << 16) | ('E' << 24),
175
      /// Mount file structure.
176
      SMNT = ('S') | ('M' << 8) | ('N' << 16) | ('T' << 24),
177
      /// Use single port passive mode (only one TCP port number for both control connections and passive-mode
178
      /// data connections)
179
      SPSV = ('S') | ('P' << 8) | ('S' << 16) | ('V' << 24),
180
      /// Returns information on the server status, including the status of the current connection
181
      STAT = ('S') | ('T' << 8) | ('A' << 16) | ('T' << 24),
182
      /// Accept the data and to store the data as a file at the server site
183
      STOR = ('S') | ('T' << 8) | ('O' << 16) | ('R' << 24),
184
      /// Store file uniquely.
185
      STOU = ('S') | ('T' << 8) | ('O' << 16) | ('U' << 24),
186
      /// Set file transfer structure.
187
      STRU = ('S') | ('T' << 8) | ('R' << 16) | ('U' << 24),
188
      /// Return system type.
189
      SYST = ('S') | ('Y' << 8) | ('S' << 16) | ('T' << 24),
190
      /// Get a thumbnail of a remote image file
191
      THMB = ('T') | ('H' << 8) | ('M' << 16) | ('B' << 24),
192
      /// Sets the transfer mode (ASCII/Binary).
193
      TYPE = ('T') | ('Y' << 8) | ('P' << 16) | ('E' << 24),
194
      /// Authentication username.
195
      USER = ('U') | ('S' << 8) | ('E' << 16) | ('R' << 24),
196
      /// Change to the parent of the current working directory
197
      XCUP = ('X') | ('C' << 8) | ('U' << 16) | ('P' << 24),
198
      /// Make a directory
199
      XMKD = ('X') | ('M' << 8) | ('K' << 16) | ('D' << 24),
200
      /// Print the current working directory
201
      XPWD = ('X') | ('P' << 8) | ('W' << 16) | ('D' << 24),
202
      ///
203
      XRCP = ('X') | ('R' << 8) | ('C' << 16) | ('P' << 24),
204
      /// Remove the directory
205
      XRMD = ('X') | ('R' << 8) | ('M' << 16) | ('D' << 24),
206
      ///
207
      XRSQ = ('X') | ('R' << 8) | ('S' << 16) | ('Q' << 24),
208
      /// Send, mail if cannot
209
      XSEM = ('X') | ('S' << 8) | ('E' << 16) | ('M' << 24),
210
      /// Send to terminal
211
      XSEN = ('X') | ('S' << 8) | ('E' << 16) | ('N' << 24)
212
    };
213
214
    /// A constructor that creates the layer from an existing packet raw data
215
    /// @param[in] data A pointer to the raw data
216
    /// @param[in] dataLen Size of the data in bytes
217
    /// @param[in] prevLayer A pointer to the previous layer
218
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
219
    FtpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
220
0
        : FtpLayer(data, dataLen, prevLayer, packet) {};
221
222
    /// A constructor that creates layer with provided input values
223
    /// @param[in] command FTP command
224
    /// @param[in] option Argument of the command
225
    explicit FtpRequestLayer(const FtpCommand& command, const std::string& option = "")
226
0
        : FtpLayer(getCommandAsString(command), option) {};
227
228
    /// Set the command of request message
229
    /// @param[in] code Value to set command
230
    /// @return True if the operation is successful, false otherwise
231
    bool setCommand(FtpCommand code);
232
233
    /// Get the command of request message
234
    /// @return FtpCommand Value of the command
235
    FtpCommand getCommand() const;
236
237
    /// Get the command of request message as string
238
    /// @return std::string Value of the command as string
239
    std::string getCommandString() const;
240
241
    /// Set the command argument of request message
242
    /// @param[in] value Value to set command argument
243
    /// @return True if the operation is successful, false otherwise
244
    bool setCommandOption(const std::string& value);
245
246
    /// Get the command argument of request message
247
    /// @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not
248
    /// @return std::string Value of command argument
249
    std::string getCommandOption(bool removeEscapeCharacters = true) const;
250
251
    /// Convert the command info to readable string
252
    /// @param[in] code Command code to convert
253
    /// @return std::string Returns the command info as readable string
254
    static std::string getCommandInfo(FtpCommand code);
255
256
    /// Convert the command to readable string
257
    /// @param[in] code Command code to convert
258
    /// @return std::string Returns the command as readable string
259
    static std::string getCommandAsString(FtpCommand code);
260
261
    // overridden methods
262
263
    /// @return Returns the protocol info as readable string
264
    std::string toString() const override;
265
  };
266
267
  /// Class for representing the response messages of FTP Layer
268
  class FtpResponseLayer : public FtpLayer
269
  {
270
  public:
271
    /// Enum for FTP response codes
272
    enum class FtpStatusCode : int
273
    {
274
      /// Unknown status code
275
      UNKNOWN,
276
      /// Restart marker reply
277
      RESTART_MARKER = 110,
278
      /// Service ready in nnn minutes
279
      SERVICE_READY_IN_MIN = 120,
280
      /// Data connection already open; transfer starting
281
      DATA_ALREADY_OPEN_START_TRANSFER = 125,
282
      /// File status okay; about to open data connection
283
      FILE_OK = 150,
284
      /// Command okay
285
      COMMAND_OK = 200,
286
      /// Command not implemented, superfluous at this site
287
      COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS = 202,
288
      /// System status, or system help reply
289
      SYSTEM_STATUS = 211,
290
      /// Directory status
291
      DIR_STATUS = 212,
292
      /// File status
293
      FILE_STATUS = 213,
294
      /// Help message
295
      HELP_MESSAGE = 214,
296
      /// NAME system type
297
      NAME_SYSTEM_TYPE = 215,
298
      /// Service ready for new user
299
      SERVICE_READY_FOR_USER = 220,
300
      /// Service closing control connection
301
      SERVICE_CLOSING_CONTROL = 221,
302
      /// Data connection open; no transfer in progress
303
      DATA_OPEN_NO_TRANSFER = 225,
304
      /// Closing data connection
305
      CLOSING_DATA = 226,
306
      /// Entering Passive Mode
307
      ENTERING_PASSIVE = 227,
308
      /// Entering Extended Passive Mode
309
      ENTERING_EXTENDED_PASSIVE = 229,
310
      /// User logged in, proceed
311
      USER_LOG_IN_PROCEED = 230,
312
      /// User logged in, authorized by security data exchange
313
      USER_LOG_IN_AUTHORIZED = 232,
314
      /// Security data exchange complete
315
      SEC_DATA_EXCHANGE_COMPLETE = 234,
316
      /// Security data exchange completed successfully
317
      SEC_DATA_EXCHANGE_COMPLETE_SUCCESS = 235,
318
      /// Requested file action okay, completed
319
      REQ_FILE_OK_COMPLETE = 250,
320
      /// PATHNAME created
321
      PATHNAME_CREATED = 257,
322
      /// User name okay, need password
323
      USER_OK_NEED_PASSWORD = 331,
324
      /// Need account for login
325
      NEED_ACCOUNT = 332,
326
      /// Requested security mechanism is ok
327
      REQ_SEC_MECHANISM_OK = 334,
328
      /// Security data is acceptable, more is required
329
      SEC_IS_ACCEPTABLE = 335,
330
      /// Username okay, need password. Challenge is ...
331
      USER_OK_NEED_PASS_CHALLENGE = 336,
332
      /// Requested file action pending further information
333
      FILE_PENDING_ACTION = 350,
334
      /// Service not available, closing control connection
335
      SERVICE_NOT_AVAILABLE = 421,
336
      /// Can't open data connection
337
      CANT_OPEN_DATA_CONNECTION = 425,
338
      /// Connection closed; transfer aborted
339
      CONNECTION_CLOSED = 426,
340
      /// Need some unavailable resource to process security
341
      NEED_UNAVAILABLE_RESOURCE_TO_SEC = 431,
342
      /// Requested file action not taken
343
      REQ_FILE_ACTION_NOT_TAKEN = 450,
344
      /// Requested action aborted: local error in processing
345
      REQ_ACTION_ABORTED = 451,
346
      /// Requested action not taken. Insufficient storage space in system
347
      REQ_ACTION_NOT_TAKEN = 452,
348
      /// Syntax error, command unrecognized
349
      SYNTAX_ERROR_COMMAND_UNRECOGNIZED = 500,
350
      /// Syntax error in parameters or arguments
351
      SYNTAX_ERROR_PARAMETER_OR_ARGUMENT = 501,
352
      /// Command not implemented
353
      COMMAND_NOT_IMPLEMENTED = 502,
354
      /// Bad sequence of commands
355
      BAD_SEQUENCE_COMMANDS = 503,
356
      /// Command not implemented for that parameter
357
      COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = 504,
358
      /// Network protocol not supported
359
      NETWORK_PROTOCOL_NOT_SUPPORTED = 522,
360
      /// Not logged in
361
      NOT_LOGGED_IN = 530,
362
      /// Need account for storing files
363
      NEED_ACCOUNT_FOR_STORE_FILE = 532,
364
      /// Command protection level denied for policy reasons
365
      COMMAND_PROTECTION_DENIED = 533,
366
      /// Request denied for policy reasons
367
      REQUEST_DENIED = 534,
368
      /// Failed security check (hash, sequence, etc)
369
      FAILED_SEC_CHECK = 535,
370
      /// Requested PROT level not supported by mechanism
371
      REQ_PROT_LEVEL_NOT_SUPPORTED = 536,
372
      /// Command protection level not supported by security mechanism
373
      COMMAND_PROTECTION_LEVEL_NOT_SUPPORTED = 537,
374
      /// Requested action not taken: File unavailable
375
      FILE_UNAVAILABLE = 550,
376
      /// Requested action aborted: page type unknown
377
      PAGE_TYPE_UNKNOWN = 551,
378
      /// Requested file action aborted: Exceeded storage allocation
379
      EXCEED_STORAGE_ALLOCATION = 552,
380
      /// Requested action not taken: File name not allowed
381
      FILENAME_NOT_ALLOWED = 553,
382
      /// Integrity protected reply
383
      INTEGRITY_PROTECTED = 631,
384
      /// Confidentiality and integrity protected reply
385
      CONFIDENTIALITY_AND_INTEGRITY_PROTECTED = 632,
386
      /// Confidentiality protected reply
387
      CONFIDENTIALITY_PROTECTED = 633
388
    };
389
390
    /// A constructor that creates the layer from an existing packet raw data
391
    /// @param[in] data A pointer to the raw data
392
    /// @param[in] dataLen Size of the data in bytes
393
    /// @param[in] prevLayer A pointer to the previous layer
394
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
395
    FtpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
396
0
        : FtpLayer(data, dataLen, prevLayer, packet) {};
397
398
    /// A constructor that creates layer with provided input values
399
    /// @param[in] code Status code
400
    /// @param[in] option Argument of the status code
401
    explicit FtpResponseLayer(const FtpStatusCode& code, const std::string& option = "")
402
0
        : FtpLayer(std::to_string(int(code)), option) {};
403
404
    /// Set the status code of response message
405
    /// @param[in] code Value to set status code
406
    /// @return True if the operation is successful, false otherwise
407
    bool setStatusCode(FtpStatusCode code);
408
409
    /// Get the status code of response message
410
    /// @return FtpStatusCode Value of the status code
411
    FtpStatusCode getStatusCode() const;
412
413
    /// Get the status code of response message as string
414
    /// @return std::string Value of the status code as string
415
    std::string getStatusCodeString() const;
416
417
    /// Set the argument of response message
418
    /// @param[in] value Value to set argument
419
    /// @return True if the operation is successful, false otherwise
420
    bool setStatusOption(const std::string& value);
421
422
    /// Get the argument of response message
423
    /// @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not
424
    /// @return std::string Value of argument
425
    std::string getStatusOption(bool removeEscapeCharacters = true) const;
426
427
    /// Convert the status code to readable string
428
    /// @param[in] code Status code to convert
429
    /// @return std::string Returns the status info as readable string
430
    static std::string getStatusCodeAsString(FtpStatusCode code);
431
432
    // overridden methods
433
434
    /// @return Returns the protocol info as readable string
435
    std::string toString() const override;
436
  };
437
438
  /// Class for representing the data of FTP Layer
439
  class FtpDataLayer : public PayloadLayer
440
  {
441
  public:
442
    /// A constructor that creates the layer from an existing packet raw data
443
    /// @param[in] data A pointer to the raw data
444
    /// @param[in] dataLen Size of the data in bytes
445
    /// @param[in] prevLayer A pointer to the previous layer
446
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
447
    FtpDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
448
1.18k
        : PayloadLayer(data, dataLen, prevLayer, packet)
449
1.18k
    {
450
1.18k
      m_Protocol = FTP;
451
1.18k
    };
452
453
    /// @return Returns the protocol info as readable string
454
    std::string toString() const override;
455
  };
456
}  // namespace pcpp