Coverage Report

Created: 2023-01-17 06:15

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