/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 */ |