Branch data Line data Source code
1 : : // $Id: NVT.cc 6916 2009-09-24 20:48:36Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <stdlib.h>
8 : :
9 : : #include "NVT.h"
10 : : #include "NetVar.h"
11 : : #include "Event.h"
12 : : #include "TCP.h"
13 : :
14 : : #define IS_3_BYTE_OPTION(c) (c >= 251 && c <= 254)
15 : :
16 : : #define TELNET_OPT_SB 250
17 : : #define TELNET_OPT_SE 240
18 : :
19 : : #define TELNET_OPT_IS 0
20 : : #define TELNET_OPT_SEND 1
21 : :
22 : : #define TELNET_OPT_WILL 251
23 : : #define TELNET_OPT_WONT 252
24 : : #define TELNET_OPT_DO 253
25 : : #define TELNET_OPT_DONT 254
26 : :
27 : : #define TELNET_IAC 255
28 : :
29 : 0 : TelnetOption::TelnetOption(NVT_Analyzer* arg_endp, unsigned int arg_code)
30 : : {
31 : 0 : endp = arg_endp;
32 : 0 : code = arg_code;
33 : 0 : flags = 0;
34 : 0 : active = 0;
35 : 0 : }
36 : :
37 : 0 : void TelnetOption::RecvOption(unsigned int type)
38 : : {
39 : 0 : TelnetOption* peer = endp->FindPeerOption(code);
40 [ # # ]: 0 : if ( ! peer )
41 : 0 : internal_error("option peer missing in TelnetOption::RecvOption");
42 : :
43 : : // WILL/WONT/DO/DONT are messages we've *received* from our peer.
44 [ # # # # : 0 : switch ( type ) {
# ]
45 : : case TELNET_OPT_WILL:
46 [ # # ][ # # ]: 0 : if ( SaidDont() || peer->SaidWont() || peer->IsActive() )
[ # # ][ # # ]
47 : 0 : InconsistentOption(type);
48 : :
49 : 0 : peer->SetWill();
50 : :
51 [ # # ]: 0 : if ( SaidDo() )
52 : 0 : peer->SetActive(1);
53 : 0 : break;
54 : :
55 : : case TELNET_OPT_WONT:
56 [ # # ][ # # ]: 0 : if ( peer->SaidWill() && ! SaidDont() )
[ # # ]
57 : 0 : InconsistentOption(type);
58 : :
59 : 0 : peer->SetWont();
60 : :
61 [ # # ]: 0 : if ( SaidDont() )
62 : 0 : peer->SetActive(0);
63 : 0 : break;
64 : :
65 : : case TELNET_OPT_DO:
66 [ # # ][ # # ]: 0 : if ( SaidWont() || peer->SaidDont() || IsActive() )
[ # # ][ # # ]
67 : 0 : InconsistentOption(type);
68 : :
69 : 0 : peer->SetDo();
70 : :
71 [ # # ]: 0 : if ( SaidWill() )
72 : 0 : SetActive(1);
73 : 0 : break;
74 : :
75 : : case TELNET_OPT_DONT:
76 [ # # ][ # # ]: 0 : if ( peer->SaidDo() && ! SaidWont() )
[ # # ]
77 : 0 : InconsistentOption(type);
78 : :
79 : 0 : peer->SetDont();
80 : :
81 [ # # ]: 0 : if ( SaidWont() )
82 : 0 : SetActive(0);
83 : 0 : break;
84 : :
85 : : default:
86 : 0 : internal_error("bad option type in TelnetOption::RecvOption");
87 : : }
88 : 0 : }
89 : :
90 : 0 : void TelnetOption::RecvSubOption(u_char* /* data */, int /* len */)
91 : : {
92 : 0 : }
93 : :
94 : 0 : void TelnetOption::SetActive(int is_active)
95 : : {
96 : 0 : active = is_active;
97 : 0 : }
98 : :
99 : 0 : void TelnetOption::InconsistentOption(unsigned int /* type */)
100 : : {
101 : 0 : endp->Event(inconsistent_option);
102 : 0 : }
103 : :
104 : 0 : void TelnetOption::BadOption()
105 : : {
106 : 0 : endp->Event(bad_option);
107 : 0 : }
108 : :
109 : :
110 : 0 : void TelnetTerminalOption::RecvSubOption(u_char* data, int len)
111 : : {
112 [ # # ]: 0 : if ( len <= 0 )
113 : : {
114 : 0 : BadOption();
115 : 0 : return;
116 : : }
117 : :
118 [ # # ]: 0 : if ( data[0] == TELNET_OPT_SEND )
119 : 0 : return;
120 : :
121 [ # # ]: 0 : if ( data[0] != TELNET_OPT_IS )
122 : : {
123 : 0 : BadOption();
124 : 0 : return;
125 : : }
126 : :
127 : 0 : endp->SetTerminal(data + 1, len - 1);
128 : : }
129 : :
130 : :
131 : : #define ENCRYPT_SET_ALGORITHM 0
132 : : #define ENCRYPT_SUPPORT_ALGORITM 1
133 : : #define ENCRYPT_REPLY 2
134 : : #define ENCRYPT_STARTING_TO_ENCRYPT 3
135 : : #define ENCRYPT_NO_LONGER_ENCRYPTING 4
136 : : #define ENCRYPT_REQUEST_START_TO_ENCRYPT 5
137 : : #define ENCRYPT_REQUEST_NO_LONGER_ENCRYPT 6
138 : : #define ENCRYPT_ENCRYPT_KEY 7
139 : : #define ENCRYPT_DECRYPT_KEY 8
140 : :
141 : 0 : void TelnetEncryptOption::RecvSubOption(u_char* data, int len)
142 : : {
143 [ # # ]: 0 : if ( ! active )
144 : : {
145 : 0 : InconsistentOption(0);
146 : 0 : return;
147 : : }
148 : :
149 [ # # ]: 0 : if ( len <= 0 )
150 : : {
151 : 0 : BadOption();
152 : 0 : return;
153 : : }
154 : :
155 : 0 : unsigned int opt = data[0];
156 : :
157 [ # # ]: 0 : if ( opt == ENCRYPT_REQUEST_START_TO_ENCRYPT )
158 : 0 : ++did_encrypt_request;
159 : :
160 [ # # ]: 0 : else if ( opt == ENCRYPT_STARTING_TO_ENCRYPT )
161 : : {
162 : : TelnetEncryptOption* peer =
163 : 0 : (TelnetEncryptOption*) endp->FindPeerOption(code);
164 : :
165 [ # # ]: 0 : if ( ! peer )
166 : 0 : internal_error("option peer missing in TelnetEncryptOption::RecvSubOption");
167 : :
168 [ # # ][ # # ]: 0 : if ( peer->DidRequest() || peer->DoingEncryption() ||
[ # # ][ # # ]
169 : : peer->Endpoint()->AuthenticationHasBeenAccepted() )
170 : : {
171 : 0 : endp->SetEncrypting(1);
172 : 0 : ++doing_encryption;
173 : : }
174 : : else
175 : 0 : InconsistentOption(0);
176 : : }
177 : : }
178 : :
179 : : #define HERE_IS_AUTHENTICATION 0
180 : : #define SEND_ME_AUTHENTICATION 1
181 : : #define AUTHENTICATION_STATUS 2
182 : : #define AUTHENTICATION_NAME 3
183 : :
184 : : #define AUTH_REJECT 1
185 : : #define AUTH_ACCEPT 2
186 : :
187 : 0 : void TelnetAuthenticateOption::RecvSubOption(u_char* data, int len)
188 : : {
189 [ # # ]: 0 : if ( len <= 0 )
190 : : {
191 : 0 : BadOption();
192 : 0 : return;
193 : : }
194 : :
195 [ # # # # : 0 : switch ( data[0] ) {
# ]
196 : : case HERE_IS_AUTHENTICATION:
197 : : {
198 : : TelnetAuthenticateOption* peer =
199 : 0 : (TelnetAuthenticateOption*) endp->FindPeerOption(code);
200 : :
201 [ # # ]: 0 : if ( ! peer )
202 : 0 : internal_error("option peer missing in TelnetAuthenticateOption::RecvSubOption");
203 : :
204 [ # # ]: 0 : if ( ! peer->DidRequestAuthentication() )
205 : 0 : InconsistentOption(0);
206 : : }
207 : 0 : break;
208 : :
209 : : case SEND_ME_AUTHENTICATION:
210 : 0 : ++authentication_requested;
211 : 0 : break;
212 : :
213 : : case AUTHENTICATION_STATUS:
214 [ # # ]: 0 : if ( len <= 1 )
215 : : {
216 : 0 : BadOption();
217 : 0 : return;
218 : : }
219 : :
220 [ # # ]: 0 : if ( data[1] == AUTH_REJECT )
221 : 0 : endp->AuthenticationRejected();
222 [ # # ]: 0 : else if ( data[1] == AUTH_ACCEPT )
223 : 0 : endp->AuthenticationAccepted();
224 : : else
225 : : {
226 : : // Don't complain, there may be replies we don't
227 : : // know about.
228 : : }
229 : 0 : break;
230 : :
231 : : case AUTHENTICATION_NAME:
232 : : {
233 : 0 : char* auth_name = new char[len];
234 : 0 : safe_strncpy(auth_name, (char*) data + 1, len);
235 : 0 : endp->SetAuthName(auth_name);
236 : : }
237 : 0 : break;
238 : :
239 : : default:
240 : 0 : BadOption();
241 : : }
242 : : }
243 : :
244 : : #define ENVIRON_IS 0
245 : : #define ENVIRON_SEND 1
246 : : #define ENVIRON_INFO 2
247 : :
248 : : #define ENVIRON_VAR 0
249 : : #define ENVIRON_VAL 1
250 : : #define ENVIRON_ESC 2
251 : : #define ENVIRON_USERVAR 3
252 : :
253 : 0 : void TelnetEnvironmentOption::RecvSubOption(u_char* data, int len)
254 : : {
255 [ # # ]: 0 : if ( len <= 0 )
256 : : {
257 : 0 : BadOption();
258 : 0 : return;
259 : : }
260 : :
261 [ # # ]: 0 : if ( data[0] == ENVIRON_SEND )
262 : : //### We should track the dialog and make sure both sides agree.
263 : 0 : return;
264 : :
265 [ # # ][ # # ]: 0 : if ( data[0] != ENVIRON_IS && data[0] != ENVIRON_INFO )
266 : : {
267 : 0 : BadOption();
268 : 0 : return;
269 : : }
270 : :
271 : 0 : --len; // Discard code.
272 : 0 : ++data;
273 : :
274 [ # # ]: 0 : while ( len > 0 )
275 : : {
276 : : int code1, code2;
277 : 0 : char* var_name = ExtractEnv(data, len, code1);
278 : 0 : char* var_val = ExtractEnv(data, len, code2);
279 : :
280 [ # # # # ]: 0 : if ( ! var_name || ! var_val ||
[ # # ][ # # ]
[ # # ]
281 : : (code1 != ENVIRON_VAR && code1 != ENVIRON_USERVAR) ||
282 : : code2 != ENVIRON_VAL )
283 : : {
284 : : // One of var_name/var_val might be set; avoid leak.
285 [ # # ]: 0 : delete [] var_name;
286 [ # # ]: 0 : delete [] var_val;
287 : :
288 : 0 : BadOption();
289 : 0 : break;
290 : : }
291 : :
292 : : static_cast<TCP_ApplicationAnalyzer*>
293 : : (endp->Parent())->SetEnv(endp->IsOrig(),
294 : 0 : var_name, var_val);
295 : : }
296 : : }
297 : :
298 : 0 : char* TelnetEnvironmentOption::ExtractEnv(u_char*& data, int& len, int& code)
299 : : {
300 : 0 : code = data[0];
301 : :
302 [ # # ][ # # ]: 0 : if ( code != ENVIRON_VAR && code != ENVIRON_VAL &&
[ # # ]
303 : : code != ENVIRON_USERVAR )
304 : 0 : return 0;
305 : :
306 : : // Move past code.
307 : 0 : --len;
308 : 0 : ++data;
309 : :
310 : : // Find the end of this piece of the option.
311 : 0 : u_char* data_end = data + len;
312 : : u_char* d;
313 [ # # ]: 0 : for ( d = data; d < data_end; ++d )
314 : : {
315 [ # # ][ # # ]: 0 : if ( *d == ENVIRON_VAR || *d == ENVIRON_VAL || *d == ENVIRON_USERVAR )
[ # # ]
316 : 0 : break;
317 : :
318 [ # # ]: 0 : if ( *d == ENVIRON_ESC )
319 : : {
320 : 0 : ++d; // move past ESC
321 [ # # ]: 0 : if ( d >= data_end )
322 : 0 : return 0;
323 : 0 : break;
324 : : }
325 : : }
326 : :
327 : 0 : int size = d - data;
328 : 0 : char* env = new char[size+1];
329 : :
330 : : // Now copy into env.
331 : 0 : int d_ind = 0;
332 : : int i;
333 [ # # ]: 0 : for ( i = 0; i < size; ++i )
334 : : {
335 [ # # ]: 0 : if ( data[d_ind] == ENVIRON_ESC )
336 : 0 : ++d_ind;
337 : :
338 : 0 : env[i] = data[d_ind];
339 : 0 : ++d_ind;
340 : : }
341 : :
342 : 0 : env[i] = '\0';
343 : :
344 : 0 : data = d;
345 : 0 : len -= size;
346 : :
347 : 0 : return env;
348 : : }
349 : :
350 : 0 : void TelnetBinaryOption::SetActive(int is_active)
351 : : {
352 : 0 : endp->SetBinaryMode(is_active);
353 : 0 : active = is_active;
354 : 0 : }
355 : :
356 : 0 : void TelnetBinaryOption::InconsistentOption(unsigned int /* type */)
357 : : {
358 : : // I don't know why, but this gets turned on redundantly -
359 : : // doesn't do any harm, so ignore it. Example is
360 : : // in ex/redund-binary-opt.trace.
361 : 0 : }
362 : :
363 : :
364 : 0 : NVT_Analyzer::NVT_Analyzer(Connection* conn, bool orig)
365 : 0 : : ContentLine_Analyzer(AnalyzerTag::NVT, conn, orig)
366 : : {
367 : 0 : peer = 0;
368 : 0 : is_suboption = last_was_IAC = pending_IAC = 0;
369 : 0 : IAC_pos = 0;
370 : 0 : num_options = 0;
371 : 0 : authentication_has_been_accepted = encrypting_mode = binary_mode = 0;
372 : 0 : auth_name = 0;
373 : 0 : }
374 : :
375 : 0 : NVT_Analyzer::~NVT_Analyzer()
376 : : {
377 [ # # ][ # # ]: 0 : for ( int i = 0; i < num_options; ++i )
[ # # ]
378 [ # # ][ # # ]: 0 : delete options[i];
[ # # ]
379 : :
380 [ # # ][ # # ]: 0 : delete [] auth_name;
[ # # ]
381 [ # # ][ # # ]: 0 : }
[ # # ]
382 : :
383 : 0 : TelnetOption* NVT_Analyzer::FindOption(unsigned int code)
384 : : {
385 : : int i;
386 [ # # ]: 0 : for ( i = 0; i < num_options; ++i )
387 [ # # ]: 0 : if ( options[i]->Code() == code )
388 : 0 : return options[i];
389 : :
390 : 0 : TelnetOption* opt = 0;
391 [ # # ]: 0 : if ( i < NUM_TELNET_OPTIONS )
392 : : { // Maybe we haven't created this option yet.
393 [ # # # # # : 0 : switch ( code ) {
# ]
394 : : case TELNET_OPTION_BINARY:
395 : 0 : opt = new TelnetBinaryOption(this);
396 : 0 : break;
397 : :
398 : : case TELNET_OPTION_TERMINAL:
399 : 0 : opt = new TelnetTerminalOption(this);
400 : 0 : break;
401 : :
402 : : case TELNET_OPTION_ENCRYPT:
403 : 0 : opt = new TelnetEncryptOption(this);
404 : 0 : break;
405 : :
406 : : case TELNET_OPTION_AUTHENTICATE:
407 : 0 : opt = new TelnetAuthenticateOption(this);
408 : 0 : break;
409 : :
410 : : case TELNET_OPTION_ENVIRON:
411 : 0 : opt = new TelnetEnvironmentOption(this);
412 : : break;
413 : : }
414 : : }
415 : :
416 [ # # ]: 0 : if ( opt )
417 : 0 : options[num_options++] = opt;
418 : :
419 : 0 : return opt;
420 : : }
421 : :
422 : 0 : TelnetOption* NVT_Analyzer::FindPeerOption(unsigned int code)
423 : : {
424 [ # # ]: 0 : assert(peer);
425 : 0 : return peer->FindOption(code);
426 : : }
427 : :
428 : 0 : void NVT_Analyzer::AuthenticationAccepted()
429 : : {
430 : 0 : authentication_has_been_accepted = 1;
431 : 0 : Event(authentication_accepted, PeerAuthName());
432 : 0 : }
433 : :
434 : 0 : void NVT_Analyzer::AuthenticationRejected()
435 : : {
436 : 0 : authentication_has_been_accepted = 0;
437 : 0 : Event(authentication_rejected, PeerAuthName());
438 : 0 : }
439 : :
440 : 0 : const char* NVT_Analyzer::PeerAuthName() const
441 : : {
442 [ # # ]: 0 : assert(peer);
443 : 0 : return peer->AuthName();
444 : : }
445 : :
446 : 0 : void NVT_Analyzer::SetTerminal(const u_char* terminal, int len)
447 : : {
448 [ # # ]: 0 : if ( login_terminal )
449 : : {
450 : 0 : val_list* vl = new val_list;
451 : 0 : vl->append(BuildConnVal());
452 : 0 : vl->append(new StringVal(new BroString(terminal, len, 0)));
453 : :
454 : 0 : ConnectionEvent(login_terminal, vl);
455 : : }
456 : 0 : }
457 : :
458 : 0 : void NVT_Analyzer::SetEncrypting(int mode)
459 : : {
460 : 0 : encrypting_mode = mode;
461 : 0 : SetSkipDeliveries(mode);
462 [ # # ]: 0 : if ( mode )
463 : 0 : Event(activating_encryption);
464 : 0 : }
465 : :
466 : : #define MAX_DELIVER_UNIT 128
467 : :
468 : 0 : void NVT_Analyzer::DoDeliver(int len, const u_char* data)
469 : : {
470 : : // This code is very similar to that for TCP_ContentLine. We
471 : : // don't virtualize out the differences because some of them
472 : : // would require per-character function calls, too expensive.
473 [ # # ]: 0 : if ( pending_IAC )
474 : : {
475 : 0 : ScanOption(seq, len, data);
476 : 0 : return;
477 : : }
478 : :
479 : : // Add data up to IAC or end.
480 [ # # ]: 0 : for ( ; len > 0; --len, ++data )
481 : : {
482 [ # # ]: 0 : if ( offset >= buf_len )
483 : 0 : InitBuffer(buf_len * 2);
484 : :
485 : 0 : int c = data[0];
486 : :
487 [ # # ][ # # ]: 0 : if ( binary_mode && c != TELNET_IAC )
488 : 0 : c &= 0x7f;
489 : :
490 : : #define EMIT_LINE \
491 : : { \
492 : : buf[offset] = '\0'; \
493 : : ForwardStream(offset, buf, IsOrig()); \
494 : : offset = 0; \
495 : : }
496 : :
497 [ # # # # : 0 : switch ( c ) {
# ]
498 : : case '\r':
499 [ # # ]: 0 : if ( CRLFAsEOL() & CR_as_EOL )
500 : 0 : EMIT_LINE
501 : : else
502 : 0 : buf[offset++] = c;
503 : 0 : break;
504 : :
505 : : case '\n':
506 [ # # ]: 0 : if ( last_char == '\r' )
507 : : {
508 [ # # ]: 0 : if ( CRLFAsEOL() & CR_as_EOL )
509 : : // we already emited, skip
510 : : ;
511 : : else
512 : : {
513 : 0 : --offset; // remove '\r'
514 : 0 : EMIT_LINE
515 : : }
516 : : }
517 : :
518 [ # # ]: 0 : else if ( CRLFAsEOL() & LF_as_EOL )
519 : 0 : EMIT_LINE
520 : :
521 : : else
522 : : {
523 [ # # ]: 0 : if ( Conn()->FlagEvent(SINGULAR_LF) )
524 : 0 : Conn()->Weird("line_terminated_with_single_LF");
525 : 0 : buf[offset++] = c;
526 : : }
527 : 0 : break;
528 : :
529 : : case '\0':
530 [ # # ]: 0 : if ( last_char == '\r' )
531 : : // Allow a NUL just after a \r - Solaris
532 : : // Telnet servers generate these, and they
533 : : // appear harmless.
534 : : ;
535 : :
536 [ # # ]: 0 : else if ( flag_NULs )
537 : 0 : CheckNUL();
538 : :
539 : : else
540 : 0 : buf[offset++] = c;
541 : 0 : break;
542 : :
543 : : case TELNET_IAC:
544 : 0 : pending_IAC = 1;
545 : 0 : IAC_pos = offset;
546 : 0 : is_suboption = 0;
547 : 0 : buf[offset++] = c;
548 : 0 : ScanOption(seq, len - 1, data + 1);
549 : 0 : return;
550 : :
551 : : default:
552 : 0 : buf[offset++] = c;
553 : : break;
554 : : }
555 : :
556 [ # # ][ # # ]: 0 : if ( ! (CRLFAsEOL() & CR_as_EOL) &&
[ # # ][ # # ]
[ # # ]
557 : : last_char == '\r' && c != '\n' && c != '\0' )
558 : : {
559 [ # # ]: 0 : if ( Conn()->FlagEvent(SINGULAR_CR) )
560 : 0 : Weird("line_terminated_with_single_CR");
561 : : }
562 : :
563 : 0 : last_char = c;
564 : : }
565 : : }
566 : :
567 : 0 : void NVT_Analyzer::ScanOption(int seq, int len, const u_char* data)
568 : : {
569 [ # # ]: 0 : if ( len <= 0 )
570 : 0 : return;
571 : :
572 [ # # ]: 0 : if ( IAC_pos == offset - 1 )
573 : : { // All we've seen so far is the IAC.
574 : 0 : unsigned int code = data[0];
575 : :
576 [ # # ]: 0 : if ( code == TELNET_IAC )
577 : : {
578 : : // An escaped 255, throw away the second
579 : : // instance and drop the IAC state.
580 : 0 : pending_IAC = 0;
581 : 0 : last_char = code;
582 : : }
583 : :
584 [ # # ]: 0 : else if ( code == TELNET_OPT_SB )
585 : : {
586 : 0 : is_suboption = 1;
587 : 0 : last_was_IAC = 0;
588 : 0 : buf[offset++] = code;
589 : : }
590 : :
591 [ # # ][ # # ]: 0 : else if ( IS_3_BYTE_OPTION(code) )
592 : : {
593 : 0 : is_suboption = 0;
594 : 0 : buf[offset++] = code;
595 : : }
596 : :
597 : : else
598 : : {
599 : : // We've got the whole 2-byte option.
600 : 0 : SawOption(code);
601 : :
602 : : // Throw it and the IAC away.
603 : 0 : --offset;
604 : 0 : pending_IAC = 0;
605 : : }
606 : :
607 : : // Recurse to munch on the remainder.
608 : 0 : DeliverStream(len - 1, data + 1, IsOrig());
609 : 0 : return;
610 : : }
611 : :
612 [ # # ]: 0 : if ( ! is_suboption )
613 : : {
614 : : // We now have the full 3-byte option.
615 : 0 : SawOption(u_char(buf[offset-1]), data[0]);
616 : :
617 : : // Delete the option.
618 : 0 : offset -= 2; // code + IAC
619 : 0 : pending_IAC = 0;
620 : :
621 : 0 : DeliverStream(len - 1, data + 1, IsOrig());
622 : 0 : return;
623 : : }
624 : :
625 : : // A suboption. Spin looking for end.
626 [ # # ]: 0 : for ( ; len > 0; --len, ++data )
627 : : {
628 : 0 : unsigned int code = data[0];
629 : :
630 [ # # ]: 0 : if ( last_was_IAC )
631 : : {
632 : 0 : last_was_IAC = 0;
633 : :
634 [ # # ]: 0 : if ( code == TELNET_IAC )
635 : : {
636 : : // This is an escaped IAC, eat
637 : : // the second copy.
638 : 0 : continue;
639 : : }
640 : :
641 [ # # ]: 0 : if ( code != TELNET_OPT_SE )
642 : : // BSD Telnet treats this case as terminating
643 : : // the suboption, so that's what we do here
644 : : // too. Below we make sure to munch on the
645 : : // new IAC.
646 : 0 : BadOptionTermination(code);
647 : :
648 : 0 : int opt_start = IAC_pos + 2;
649 : 0 : int opt_stop = offset - 1;
650 : 0 : int opt_len = opt_stop - opt_start;
651 : 0 : SawSubOption((const char*)&buf[opt_start], opt_len);
652 : :
653 : : // Delete suboption.
654 : 0 : offset = IAC_pos;
655 : 0 : pending_IAC = is_suboption = 0;
656 : :
657 [ # # ]: 0 : if ( code == TELNET_OPT_SE )
658 : 0 : DeliverStream(len - 1, data + 1, IsOrig());
659 : : else
660 : : {
661 : : // Munch on the new (broken) option.
662 : 0 : pending_IAC = 1;
663 : 0 : IAC_pos = offset;
664 : 0 : buf[offset++] = TELNET_IAC;
665 : 0 : DeliverStream(len, data, IsOrig());
666 : : }
667 : 0 : return;
668 : : }
669 : :
670 : : else
671 : : {
672 : 0 : buf[offset++] = code;
673 : 0 : last_was_IAC = (code == TELNET_IAC);
674 : : }
675 : : }
676 : : }
677 : :
678 : 0 : void NVT_Analyzer::SawOption(unsigned int /* code */)
679 : : {
680 : 0 : }
681 : :
682 : 0 : void NVT_Analyzer::SawOption(unsigned int code, unsigned int subcode)
683 : : {
684 : 0 : TelnetOption* opt = FindOption(subcode);
685 [ # # ]: 0 : if ( opt )
686 : 0 : opt->RecvOption(code);
687 : 0 : }
688 : :
689 : 0 : void NVT_Analyzer::SawSubOption(const char* subopt, int len)
690 : : {
691 : 0 : unsigned int subcode = u_char(subopt[0]);
692 : :
693 : 0 : ++subopt;
694 : 0 : --len;
695 : :
696 : 0 : TelnetOption* opt = FindOption(subcode);
697 [ # # ]: 0 : if ( opt )
698 : 0 : opt->RecvSubOption((u_char*) subopt, len);
699 : 0 : }
700 : :
701 : 0 : void NVT_Analyzer::BadOptionTermination(unsigned int /* code */)
702 : : {
703 : 0 : Event(bad_option_termination);
704 [ + - ][ + - ]: 6 : }
705 : 3 :
|