Coverage Report

Created: 2025-07-11 07:47

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