diff options
Diffstat (limited to 'src/protocoltelnet.cpp')
-rw-r--r-- | src/protocoltelnet.cpp | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/src/protocoltelnet.cpp b/src/protocoltelnet.cpp new file mode 100644 index 0000000..7beea5b --- /dev/null +++ b/src/protocoltelnet.cpp | |||
@@ -0,0 +1,315 @@ | |||
1 | #include "protocoltelnet.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | ProtocolTelnet::ProtocolTelnet() | ||
5 | { | ||
6 | nTermType = termUnInited; | ||
7 | bEchoOn = true; | ||
8 | } | ||
9 | |||
10 | ProtocolTelnet::~ProtocolTelnet() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | bool ProtocolTelnet::onNewConnection() | ||
15 | { | ||
16 | Connection *pCon = getConnection(); | ||
17 | |||
18 | pCon->appendOutput( (char)IAC ); | ||
19 | pCon->appendOutput( (char)WILL ); | ||
20 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
21 | |||
22 | pCon->appendOutput( (char)IAC ); | ||
23 | pCon->appendOutput( (char)DO ); | ||
24 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
25 | |||
26 | pCon->appendOutput( (char)IAC ); | ||
27 | pCon->appendOutput( (char)DONT ); | ||
28 | pCon->appendOutput( (char)TERMTYPE ); | ||
29 | |||
30 | // pCon->appendOutput( IAC ); | ||
31 | // pCon->appendOutput( SB ); | ||
32 | // pCon->appendOutput( TERMTYPE ); | ||
33 | // pCon->appendOutput( 1 ); | ||
34 | // pCon->appendOutput( IAC ); | ||
35 | // pCon->appendOutput( SE ); | ||
36 | |||
37 | pCon->appendOutput( (char)IAC ); | ||
38 | pCon->appendOutput( (char)DONT ); | ||
39 | pCon->appendOutput( (char)ECHO ); | ||
40 | |||
41 | pCon->appendOutput( (char)IAC ); | ||
42 | pCon->appendOutput( (char)WILL ); | ||
43 | pCon->appendOutput( (char)ECHO ); | ||
44 | |||
45 | // 255(IAC),251(WILL),3 | ||
46 | } | ||
47 | |||
48 | bool ProtocolTelnet::onNewData() | ||
49 | { | ||
50 | Connection *pCon = getConnection(); | ||
51 | if( !pCon->hasInput() ) | ||
52 | { | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | int nInSize = pCon->getInputAmnt(); | ||
57 | char *lpInStr = (char *)pCon->getInput(); | ||
58 | |||
59 | // Here we interpret the basic commands and un-encapsulate them, so to | ||
60 | // speak. We'll allow this, even if the terminal is in raw mode, we | ||
61 | // just won't send anything in response... | ||
62 | for( int j = 0; j < nInSize; j++ ) | ||
63 | { | ||
64 | switch( (unsigned char)lpInStr[j] ) | ||
65 | { | ||
66 | case '\r': | ||
67 | fbEdited.appendData('\n'); | ||
68 | if( bEchoOn ) pCon->appendOutput("\n\r"); | ||
69 | break; | ||
70 | |||
71 | case '\n': | ||
72 | break; | ||
73 | |||
74 | case '\177': // backspace | ||
75 | if( fbEdited.getLength() > 0 ) | ||
76 | { | ||
77 | fbEdited.usedData( -1 ); // Delete one char from the end | ||
78 | if( bEchoOn ) pCon->appendOutput(ESC "[D"); // Move the cursor back one | ||
79 | if( bEchoOn ) pCon->appendOutput(ESC "[P"); // Delete one character | ||
80 | } | ||
81 | break; | ||
82 | |||
83 | case '\x1B': // escape sequence | ||
84 | if( (unsigned char)lpInStr[j+1] == '[' ) | ||
85 | { | ||
86 | switch( (unsigned char)lpInStr[j+2] ) | ||
87 | { | ||
88 | case 'A': // Up | ||
89 | break; | ||
90 | |||
91 | case 'B': // Down | ||
92 | break; | ||
93 | |||
94 | case 'C': // Right | ||
95 | break; | ||
96 | |||
97 | case 'D': // Left | ||
98 | break; | ||
99 | } | ||
100 | j+=2; | ||
101 | } | ||
102 | break; | ||
103 | |||
104 | case 0: // NOP: No operation | ||
105 | break; | ||
106 | |||
107 | case IAC: // IAC: Interpret as command | ||
108 | switch( lpInStr[j+1] ) | ||
109 | { | ||
110 | case SE: // SE: End of subnegotiation parameters. | ||
111 | break; | ||
112 | |||
113 | case NOP: // NOP: No operation | ||
114 | break; | ||
115 | |||
116 | case DM: // DM: Data mark. Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. | ||
117 | break; | ||
118 | |||
119 | case BRK: // BRK: Break. Indicates that the "break" or "attention" key was hit. | ||
120 | break; | ||
121 | |||
122 | case IP: // IP: Suspend, interrupt or abort the process to which the NVT is connected. | ||
123 | break; | ||
124 | |||
125 | case AO: // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. | ||
126 | break; | ||
127 | |||
128 | case AYT: // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. | ||
129 | break; | ||
130 | |||
131 | case EC: // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. | ||
132 | break; | ||
133 | |||
134 | case EL: // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. | ||
135 | break; | ||
136 | |||
137 | case GA: // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. | ||
138 | break; | ||
139 | |||
140 | case SB: // SB: Subnegotiation of the indicated option follows. | ||
141 | switch( lpInStr[j+2] ) | ||
142 | { | ||
143 | case TERMTYPE: | ||
144 | if( lpInStr[j+3] == 0 ) | ||
145 | { | ||
146 | for( int k = 0; j+4+k < nInSize; k++ ) | ||
147 | { | ||
148 | if( (unsigned char)lpInStr[j+4+k] == IAC && | ||
149 | (unsigned char)lpInStr[j+5+k] == SE ) | ||
150 | { | ||
151 | lpInStr[j+4+k] = 0; | ||
152 | //@TODO: Do something with the term type... | ||
153 | printf("Term type: %s\n", &lpInStr[j+4] ); | ||
154 | j += 5+k; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | else | ||
159 | { | ||
160 | } | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | //printf("unknown subnegotiation parameters! (%d)\n", lpInStr[j+2] ); | ||
165 | break; | ||
166 | } | ||
167 | break; | ||
168 | |||
169 | case WILL: // WILL: Indicates the desire to begin performing | ||
170 | switch( lpInStr[j+2] ) | ||
171 | { | ||
172 | case SUPPRESSGA: | ||
173 | j += 2; | ||
174 | // pCon->usedInput( 3 ); | ||
175 | break; | ||
176 | |||
177 | case TERMTYPE: | ||
178 | j += 2; | ||
179 | // pCon->usedInput( 3 ); | ||
180 | break; | ||
181 | |||
182 | case ECHO: | ||
183 | j += 2; | ||
184 | // pCon->usedInput( 3 ); | ||
185 | break; | ||
186 | |||
187 | case NAWS: | ||
188 | default: | ||
189 | pCon->appendOutput( (char)ESC[0] ); | ||
190 | pCon->appendOutput( (char)DONT ); | ||
191 | pCon->appendOutput( lpInStr[j+2] ); | ||
192 | //printf("unknown will command used! (%d)\n", lpInStr[j+2] ); | ||
193 | j += 2; | ||
194 | break; | ||
195 | } | ||
196 | break; | ||
197 | |||
198 | case WONT: // WONT: Indicates the refusal to perform | ||
199 | switch( lpInStr[j+2] ) | ||
200 | { | ||
201 | case ECHO: | ||
202 | j += 2; | ||
203 | // pCon->usedInput( 3 ); | ||
204 | break; | ||
205 | |||
206 | default: | ||
207 | //printf("unknown wont command used! (%d)\n", lpInStr[j+2] ); | ||
208 | j += 2; | ||
209 | break; | ||
210 | } | ||
211 | break; | ||
212 | |||
213 | case DO: // DO: Indicates the request that the other party perform | ||
214 | switch( lpInStr[j+2] ) | ||
215 | { | ||
216 | case ECHO: | ||
217 | j += 2; | ||
218 | break; | ||
219 | |||
220 | case SUPPRESSGA: | ||
221 | j += 2; | ||
222 | break; | ||
223 | |||
224 | default: | ||
225 | pCon->appendOutput( (char)ESC[0] ); | ||
226 | pCon->appendOutput( (char)DONT ); | ||
227 | pCon->appendOutput( lpInStr[j+2] ); | ||
228 | //printf("unknown do command used! (%d)\n", lpInStr[j+2] ); | ||
229 | j += 2; | ||
230 | break; | ||
231 | } | ||
232 | // pCon->usedInput( 3 ); | ||
233 | break; | ||
234 | |||
235 | case DONT: // DONT: Indicates the demand that the other party stop performing | ||
236 | switch( lpInStr[j+2] ) | ||
237 | { | ||
238 | case ECHO: | ||
239 | j += 2; | ||
240 | // pCon->usedInput( 3 ); | ||
241 | break; | ||
242 | |||
243 | default: | ||
244 | printf("unknown dont command used! (%d)\n", lpInStr[j+2] ); | ||
245 | j += 2; | ||
246 | break; | ||
247 | } | ||
248 | break; | ||
249 | } | ||
250 | break; | ||
251 | |||
252 | default: | ||
253 | fbEdited.appendData( lpInStr[j] ); | ||
254 | if( bEchoOn ) pCon->appendOutput( lpInStr[j] ); | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | pCon->usedInput( pCon->getInputAmnt() ); | ||
260 | |||
261 | return true; | ||
262 | } | ||
263 | |||
264 | char *ProtocolTelnet::getLine( bool bFullOnly ) | ||
265 | { | ||
266 | int i = fbEdited.findChar('\n'); | ||
267 | |||
268 | if( i < 0 ) | ||
269 | { | ||
270 | if( bFullOnly == false ) | ||
271 | { | ||
272 | i = fbEdited.getLength(); | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | return NULL; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | char *lpStr = new char[i+1]; | ||
281 | strncpy( lpStr, fbEdited.getData(), i ); | ||
282 | lpStr[i] = '\0'; | ||
283 | |||
284 | fbEdited.usedData( i+1 ); | ||
285 | |||
286 | return lpStr; | ||
287 | } | ||
288 | |||
289 | char *ProtocolTelnet::peekLine( bool bFullOnly ) | ||
290 | { | ||
291 | int i = fbEdited.findChar('\n'); | ||
292 | |||
293 | if( i < 0 ) | ||
294 | { | ||
295 | if( bFullOnly == false ) | ||
296 | { | ||
297 | i = fbEdited.getLength(); | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | return NULL; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | char *lpStr = new char[i+1]; | ||
306 | strncpy( lpStr, fbEdited.getData(), i ); | ||
307 | lpStr[i] = '\0'; | ||
308 | |||
309 | return lpStr; | ||
310 | } | ||
311 | |||
312 | void ProtocolTelnet::setEcho( bool bEchoOn ) | ||
313 | { | ||
314 | this->bEchoOn = bEchoOn; | ||
315 | } | ||