Coverage Report

Created: 2025-09-27 08:03

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