Coverage Report

Created: 2024-02-25 06:29

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