Coverage Report

Created: 2024-02-25 06:29

/src/PcapPlusPlus/Packet++/header/TelnetLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "Layer.h"
4
5
/// @file
6
7
/**
8
 * \namespace pcpp
9
 * \brief The main namespace for the PcapPlusPlus lib
10
 */
11
namespace pcpp
12
{
13
14
/**
15
 * Class for representing the Telnet Layer
16
 */
17
class TelnetLayer : public Layer
18
{
19
  private:
20
  // Position iterator for next command
21
  size_t lastPositionOffset;
22
23
  // Checks if position is a data field
24
  bool isDataField(uint8_t *pos) const;
25
  // Checks if position is a command field
26
  bool isCommandField(uint8_t *pos) const;
27
  // Returns distance to next IAC
28
  size_t distanceToNextIAC(uint8_t *startPos, size_t maxLength);
29
  // Returns length of provided field
30
  size_t getFieldLen(uint8_t *startPos, size_t maxLength);
31
  // Get position of next data field
32
  uint8_t *getNextDataField(uint8_t *pos, size_t len);
33
  // Get position of next command field
34
  uint8_t *getNextCommandField(uint8_t *pos, size_t len);
35
  // Get options of provided field
36
  int16_t getSubCommand(uint8_t *pos, size_t len);
37
  // Get data of provided field
38
  uint8_t *getCommandData(uint8_t *pos, size_t &slen);
39
40
  public:
41
  /**
42
   * Telnet Command Indicator
43
   */
44
  enum class TelnetCommand : int
45
  {
46
    /// Indicator to parser reached end of packet
47
    TelnetCommandEndOfPacket = -1,
48
49
    /// End of file
50
    EndOfFile = 236,
51
    /// Suspend current process
52
    Suspend,
53
    /// Abort Process
54
    Abort,
55
    /// End of Record
56
    EndOfRecordCommand,
57
    /// Marks the end of a Telnet option subnegotiation, used with the SB code to specify more specific option
58
    /// parameters.
59
    SubnegotiationEnd,
60
    /// Null command; does nothing.
61
    NoOperation,
62
    /// Used to mark the end of a sequence of data that the recipient should scan for urgent Telnet commands.
63
    DataMark,
64
    /// Represents the pressing of the “break” or “attention” key on the terminal.
65
    Break,
66
    /// Tells the recipient to interrupt, abort, suspend or terminate the process currently in use.
67
    InterruptProcess,
68
    /// Instructs the remote host to continue running the current process, but discard all remaining output from it.
69
    /// This may be needed if a program starts to send unexpectedly large amounts of data to the user.
70
    AbortOutput,
71
    /// May be used to check that the remote host is still “alive”. When this character is sent the remote host
72
    /// returns some type of output to indicate that it is still functioning.
73
    AreYouThere,
74
    /// Instructs the recipient to delete the last undeleted character from the data stream. Used to “undo” the
75
    /// sending of a character.
76
    EraseCharacter,
77
    /// Tells the recipient to delete all characters from the data stream back to (but not including) the last end
78
    /// of line (CR+LF) sequence.
79
    EraseLine,
80
    /// Used in Telnet half-duplex mode to signal the other device that it may transmit.
81
    GoAhead,
82
    /// Marks the beginning of a Telnet option subnegotiation, used when an option requires the client and server to
83
    /// exchange parameters.
84
    Subnegotiation,
85
    /// Indicates that the device sending this code is willing to perform or continue performing a particular
86
    /// option.
87
    WillPerform,
88
    /// Indicates that the device sending this code is either not willing to perform a particular option, or is now
89
    /// refusing to continue to perform it.
90
    WontPerform,
91
    /// Requests that the other device perform a particular option or confirms the expectation that the other device
92
    /// will perform that option.
93
    DoPerform,
94
    /// Specifies that the other party not perform an option, or confirms a device’s expectation that the other
95
    /// party not perform an option.
96
    DontPerform,
97
    /// Precedes command values 240 through 254 as described above. A pair of IAC bytes in a row represents the data
98
    /// value 255.
99
    InterpretAsCommand
100
  };
101
102
  /**
103
   * Telnet Options
104
   */
105
  enum class TelnetOption : int
106
  {
107
    /// Internal return for no option detected
108
    TelnetOptionNoOption = -1,
109
110
    /// Binary Transmission RFC856 https://www.iana.org/go/rfc856
111
    TransmitBinary = 0,
112
    /// Echo RFC857 https://www.iana.org/go/rfc857
113
    Echo,
114
    /// Reconnection
115
    Reconnection,
116
    /// Suppress Go Ahead RFC858 https://www.iana.org/go/rfc858
117
    SuppressGoAhead,
118
    /// Negotiate approximate message size
119
    ApproxMsgSizeNegotiation,
120
    /// Status RFC859 https://www.iana.org/go/rfc859
121
    Status,
122
    /// Timing Mark RFC860 https://www.iana.org/go/rfc860
123
    TimingMark,
124
    /// RCTE, Remote Controlled Transmission and Echo RFC726 https://www.iana.org/go/rfc726
125
    RemoteControlledTransAndEcho,
126
    /// Output Line Width
127
    OutputLineWidth,
128
    /// Output Page Size
129
    OutputPageSize,
130
    /// NAOCRD, Negotiate About Output Carriage-Return Disposition RFC652 https://www.iana.org/go/rfc652
131
    OutputCarriageReturnDisposition,
132
    /// NAOHTS, Negotiate About Output Horizontal Tabstops RFC653 https://www.iana.org/go/rfc653
133
    OutputHorizontalTabStops,
134
    /// NAOHTD, Negotiate About Output Horizontal Tab Disposition RFC654 https://www.iana.org/go/rfc654
135
    OutputHorizontalTabDisposition,
136
    /// NAOFFD, Negotiate About Output Formfeed Disposition RFC655 https://www.iana.org/go/rfc655
137
    OutputFormfeedDisposition,
138
    /// NAOVTS, Negotiate About Vertical Tabstops RFC656 https://www.iana.org/go/rfc656
139
    OutputVerticalTabStops,
140
    /// NAOVTD, Negotiate About Output Vertcial Tab Disposition RFC657 https://www.iana.org/go/rfc657
141
    OutputVerticalTabDisposition,
142
    /// NAOLFD, Negotiate About Output Linefeed Disposition RFC658 https://www.iana.org/go/rfc658
143
    OutputLinefeedDisposition,
144
    /// Extended ASCII RFC698 https://www.iana.org/go/rfc698
145
    ExtendedASCII,
146
    /// Logout RFC727 https://www.iana.org/go/rfc727
147
    Logout,
148
    /// BM, Byte Macro RFC735 https://www.iana.org/go/rfc735
149
    ByteMacro,
150
    /// Data Entry Terminal RFC1043 - RFC732 https://www.iana.org/go/rfc1043 https://www.iana.org/go/rfc732
151
    DataEntryTerminal,
152
    /// SUPDUP RFC736 - RFC734 https://www.iana.org/go/rfc736 https://www.iana.org/go/rfc734
153
    SUPDUP,
154
    /// SUPDUP Output RFC749 https://www.iana.org/go/rfc749
155
    SUPDUPOutput,
156
    /// Send Location RFC779 https://www.iana.org/go/rfc779
157
    SendLocation,
158
    /// Terminal Type RFC1091 https://www.iana.org/go/rfc1091
159
    TerminalType,
160
    /// End of record RFC885 https://www.iana.org/go/rfc885
161
    EndOfRecordOption,
162
    /// TUID, TACACS User Identification RFC927 https://www.iana.org/go/rfc927
163
    TACACSUserIdentification,
164
    /// OUTMRK, Output Marking RFC933 https://www.iana.org/go/rfc933
165
    OutputMarking,
166
    /// TTYLOC, Terminal Location Number RFC946 https://www.iana.org/go/rfc946
167
    TerminalLocationNumber,
168
    /// Telnet 3270 Regime RFC1041 https://www.iana.org/go/rfc1041
169
    Telnet3270Regime,
170
    /// X.3 PAD RFC1053 https://www.iana.org/go/rfc1053
171
    X3Pad,
172
    /// NAWS, Negotiate About Window Size RFC1073 https://www.iana.org/go/rfc1073
173
    NegotiateAboutWindowSize,
174
    /// Terminal Speed RFC1079 https://www.iana.org/go/rfc1079
175
    TerminalSpeed,
176
    /// Remote Flow Control RFC1372 https://www.iana.org/go/rfc1372
177
    RemoteFlowControl,
178
    /// Line Mode RFC1184 https://www.iana.org/go/rfc1184
179
    Linemode,
180
    /// X Display Location RFC1096 https://www.iana.org/go/rfc1096
181
    XDisplayLocation,
182
    /// Environment Option RFC1408 https://www.iana.org/go/rfc1408
183
    EnvironmentOption,
184
    /// Authentication Option RFC2941 https://www.iana.org/go/rfc2941
185
    AuthenticationOption,
186
    /// Encryption Option RFC2946 https://www.iana.org/go/rfc2946
187
    EncryptionOption,
188
    /// New Environment Option RFC1572 https://www.iana.org/go/rfc1572
189
    NewEnvironmentOption,
190
    /// TN3270E RFC2355 https://www.iana.org/go/rfc2355
191
    TN3270E,
192
    /// X Server Authentication
193
    XAuth,
194
    /// Charset RFC2066 https://www.iana.org/go/rfc2066
195
    Charset,
196
    /// RSP, Telnet Remote Serial Port
197
    TelnetRemoteSerialPort,
198
    /// Com Port Control Option RFC2217 https://www.iana.org/go/rfc2217
199
    ComPortControlOption,
200
    /// Telnet Suppress Local Echo
201
    TelnetSuppressLocalEcho,
202
    /// Telnet Start TLS
203
    TelnetStartTLS,
204
    /// Kermit RFC2840 https://www.iana.org/go/rfc2840
205
    Kermit,
206
    /// Send URL
207
    SendURL,
208
    /// Forward X Server
209
    ForwardX,
210
211
    /// Telnet Option Pragma Logon
212
    TelOptPragmaLogon = 138,
213
    /// Telnet Option SSPI Logon
214
    TelOptSSPILogon,
215
    /// Telnet Option Pragma Heartbeat
216
    TelOptPragmaHeartbeat,
217
218
    /// Extended option list
219
    ExtendedOptions = 255
220
  };
221
222
  /**
223
   * A constructor that creates the layer from an existing packet raw data
224
   * @param[in] data A pointer to the raw data
225
   * @param[in] dataLen Size of the data in bytes
226
   * @param[in] prevLayer A pointer to the previous layer
227
   * @param[in] packet A pointer to the Packet instance where layer will be stored in
228
   */
229
  TelnetLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet)
230
6.43k
  {
231
6.43k
    m_Protocol = Telnet;
232
6.43k
    lastPositionOffset = SIZE_MAX;
233
6.43k
  };
234
235
  /**
236
   * Get the Telnet data as readable string
237
   * @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not
238
   * @return Full payload as readable string, empty if Telnet packet contains control commands/options.
239
   */
240
  std::string getDataAsString(bool removeEscapeCharacters = true);
241
242
  /**
243
   * Get the total number of detected Telnet commands
244
   * @return size_t The number of Telnet commands
245
   */
246
  size_t getTotalNumberOfCommands();
247
248
  /**
249
   * Returns the number of occurrences of provided command
250
   * @param[in] command Telnet command to count
251
   * @return size_t Number of occurrences of command
252
   */
253
  size_t getNumberOfCommands(TelnetCommand command);
254
255
  /**
256
   * Returns the first command of packet
257
   * @return TelnetCommand First detected command value, TelnetCommandEndOfPacket if there is no command field
258
   */
259
  TelnetCommand getFirstCommand();
260
261
  /**
262
   * Returns the next command of packet. Uses an internal iterator. The iterator resets when reached end of packet.
263
   * @return TelnetCommand Detected command value, TelnetCommandEndOfPacket if reached the end of packet.
264
   */
265
  TelnetCommand getNextCommand();
266
267
  /**
268
   * Returns the option of current command. Uses an internal iterator. Iterator can be moved with getNextCommand
269
   * @return TelnetOption Option of current command
270
   */
271
  TelnetOption getOption();
272
273
  /**
274
   * Returns the option of provided command. It will return option of first occurrence of the command
275
   * @param[in] command Telnet command to search
276
   * @return TelnetOption Option of the command. Returns TelnetOptionNoOption if the provided command not found.
277
   */
278
  TelnetOption getOption(TelnetCommand command);
279
280
  /**
281
   * Returns the data of current command. Uses an internal iterator. Iterator can be moved with getNextCommand
282
   * @param[out] length Length of the data of current command
283
   * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command.
284
   */
285
  uint8_t *getOptionData(size_t &length);
286
287
  /**
288
   * Returns the data of provided command. It will return data of first occurrence of the command
289
   * @param[in] command Telnet command to search
290
   * @param[out] length Length of the data of current command
291
   * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command or if can't
292
   * find the command.
293
   */
294
  uint8_t *getOptionData(TelnetCommand command, size_t &length);
295
296
  /**
297
   * Convert the Telnet Command to readable string
298
   * @param[in] val Value of the command
299
   * @return The Telnet Command as readable string
300
   */
301
  static std::string getTelnetCommandAsString(TelnetCommand val);
302
303
  /**
304
   * Convert the Telnet option to readable string
305
   * @param[in] val Value of the option
306
   * @return The Telnet Option as readable string
307
   */
308
  static std::string getTelnetOptionAsString(TelnetOption val);
309
310
  /**
311
   * A static method that checks whether the port is considered as Telnet
312
   * @param[in] port The port number to be checked
313
   */
314
210k
  static bool isTelnetPort(uint16_t port) { return port == 23; }
315
316
  /**
317
   * A static method that takes a byte array and detects whether it is a Telnet message
318
   * @param[in] data A byte array
319
   * @param[in] dataSize The byte array size (in bytes)
320
   * @return True if the data is identified as Telnet message
321
   */
322
107k
  static bool isDataValid(const uint8_t *data, size_t dataSize) { return data && dataSize; }
323
324
  // overridden methods
325
326
  /// Parses the next layer. Telnet is the always last so does nothing for this layer
327
6.43k
  void parseNextLayer() {}
328
329
  /**
330
   * @return Get the size of the layer
331
   */
332
1.12k
  size_t getHeaderLen() const { return m_DataLen; }
333
334
  /// Does nothing for this layer
335
1.12k
  void computeCalculateFields() {}
336
337
  /**
338
   * @return The OSI layer level of Telnet (Application Layer).
339
   */
340
1.12k
  OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
341
342
  /**
343
   * @return Returns the protocol info as readable string
344
   */
345
  std::string toString() const;
346
};
347
348
} // namespace pcpp