Coverage Report

Created: 2023-01-17 06:15

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