Line data Source code
1 : /*
2 : * libtelnet - TELNET protocol handling library
3 : *
4 : * Sean Middleditch
5 : * sean@sourcemud.org
6 : *
7 : * The author or authors of this code dedicate any and all copyright interest
8 : * in this code to the public domain. We make this dedication for the benefit
9 : * of the public at large and to the detriment of our heirs and successors. We
10 : * intend this dedication to be an overt act of relinquishment in perpetuity of
11 : * all present and future rights to this code under copyright law.
12 : */
13 :
14 : #ifdef HAVE_CONFIG_H
15 : #include <config.h>
16 : #endif
17 : #include <stdlib.h>
18 : #include <string.h>
19 : #include <stdio.h>
20 : #include <errno.h>
21 : #include <string.h>
22 : #include <stdarg.h>
23 :
24 : /* Win32 compatibility */
25 : #if defined(_WIN32)
26 : # define vsnprintf _vsnprintf
27 : # define __func__ __FUNCTION__
28 : # define ZLIB_WINAPI 1
29 : # if defined(_MSC_VER)
30 : /* va_copy() is directly supported starting in Visual Studio 2013
31 : * https://msdn.microsoft.com/en-us/library/kb57fad8(v=vs.110).aspx
32 : * https://msdn.microsoft.com/en-us/library/kb57fad8(v=vs.120).aspx
33 : */
34 : # if _MSC_VER <= 1700
35 : # define va_copy(dest, src) (dest = src)
36 : # endif
37 : # endif
38 : #endif
39 :
40 : #if defined(HAVE_ZLIB)
41 : # include <zlib.h>
42 : #endif
43 :
44 : #include "libtelnet.h"
45 :
46 : /* inlinable functions */
47 : #if defined(__GNUC__) || __STDC_VERSION__ >= 199901L
48 : # define INLINE __inline__
49 : #else
50 : # define INLINE
51 : #endif
52 :
53 : /* helper for Q-method option tracking */
54 : #define Q_US(q) ((q).state & 0x0F)
55 : #define Q_HIM(q) (((q).state & 0xF0) >> 4)
56 : #define Q_MAKE(us,him) ((us) | ((him) << 4))
57 :
58 : /* helper for the negotiation routines */
59 : #define NEGOTIATE_EVENT(telnet,cmd,opt) \
60 : ev.type = (cmd); \
61 : ev.neg.telopt = (opt); \
62 : (telnet)->eh((telnet), &ev, (telnet)->ud);
63 :
64 : /* telnet state codes */
65 : enum telnet_state_t {
66 : TELNET_STATE_DATA = 0,
67 : TELNET_STATE_EOL,
68 : TELNET_STATE_IAC,
69 : TELNET_STATE_WILL,
70 : TELNET_STATE_WONT,
71 : TELNET_STATE_DO,
72 : TELNET_STATE_DONT,
73 : TELNET_STATE_SB,
74 : TELNET_STATE_SB_DATA,
75 : TELNET_STATE_SB_DATA_IAC
76 : };
77 : typedef enum telnet_state_t telnet_state_t;
78 :
79 : /* telnet state tracker */
80 : struct telnet_t {
81 : /* user data */
82 : void *ud;
83 : /* telopt support table */
84 : const telnet_telopt_t *telopts;
85 : /* event handler */
86 : telnet_event_handler_t eh;
87 : #if defined(HAVE_ZLIB)
88 : /* zlib (mccp2) compression */
89 : z_stream *z;
90 : #endif
91 : /* RFC1143 option negotiation states */
92 : struct telnet_rfc1143_t *q;
93 : /* sub-request buffer */
94 : char *buffer;
95 : /* current size of the buffer */
96 : size_t buffer_size;
97 : /* current buffer write position (also length of buffer data) */
98 : size_t buffer_pos;
99 : /* current state */
100 : enum telnet_state_t state;
101 : /* option flags */
102 : unsigned char flags;
103 : /* current subnegotiation telopt */
104 : unsigned char sb_telopt;
105 : /* length of RFC1143 queue */
106 : unsigned char q_size;
107 : };
108 :
109 : /* RFC1143 option negotiation state */
110 : typedef struct telnet_rfc1143_t {
111 : unsigned char telopt;
112 : unsigned char state;
113 : } telnet_rfc1143_t;
114 :
115 : /* RFC1143 state names */
116 : #define Q_NO 0
117 : #define Q_YES 1
118 : #define Q_WANTNO 2
119 : #define Q_WANTYES 3
120 : #define Q_WANTNO_OP 4
121 : #define Q_WANTYES_OP 5
122 :
123 : /* telnet NVT EOL sequences */
124 : static const char CRLF[] = { '\r', '\n' };
125 : static const char CRNUL[] = { '\r', '\0' };
126 :
127 : /* buffer sizes */
128 : static const size_t _buffer_sizes[] = { 0, 512, 2048, 8192, 16384, };
129 : static const size_t _buffer_sizes_count = sizeof(_buffer_sizes) /
130 : sizeof(_buffer_sizes[0]);
131 :
132 : /* error generation function */
133 0 : static telnet_error_t _error(telnet_t *telnet, unsigned line,
134 : const char* func, telnet_error_t err, int fatal, const char *fmt,
135 : ...) {
136 : telnet_event_t ev;
137 : char buffer[512];
138 : va_list va;
139 :
140 : /* format informational text */
141 0 : va_start(va, fmt);
142 0 : vsnprintf(buffer, sizeof(buffer), fmt, va);
143 0 : va_end(va);
144 :
145 : /* send error event to the user */
146 0 : ev.type = fatal ? TELNET_EV_ERROR : TELNET_EV_WARNING;
147 0 : ev.error.file = __FILE__;
148 0 : ev.error.func = func;
149 0 : ev.error.line = line;
150 0 : ev.error.msg = buffer;
151 0 : telnet->eh(telnet, &ev, telnet->ud);
152 :
153 0 : return err;
154 : }
155 :
156 : #if defined(HAVE_ZLIB)
157 : /* initialize the zlib box for a telnet box; if deflate is non-zero, it
158 : * initializes zlib for delating (compression), otherwise for inflating
159 : * (decompression). returns TELNET_EOK on success, something else on
160 : * failure.
161 : */
162 : telnet_error_t _init_zlib(telnet_t *telnet, int deflate, int err_fatal) {
163 : z_stream *z;
164 : int rs;
165 :
166 : /* if compression is already enabled, fail loudly */
167 : if (telnet->z != 0)
168 : return _error(telnet, __LINE__, __func__, TELNET_EBADVAL,
169 : err_fatal, "cannot initialize compression twice");
170 :
171 : /* allocate zstream box */
172 : if ((z= (z_stream *)calloc(1, sizeof(z_stream))) == 0)
173 : return _error(telnet, __LINE__, __func__, TELNET_ENOMEM, err_fatal,
174 : "malloc() failed: %s", strerror(errno));
175 :
176 : /* initialize */
177 : if (deflate) {
178 : if ((rs = deflateInit(z, Z_DEFAULT_COMPRESSION)) != Z_OK) {
179 : free(z);
180 : return _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS,
181 : err_fatal, "deflateInit() failed: %s", zError(rs));
182 : }
183 : telnet->flags |= TELNET_PFLAG_DEFLATE;
184 : } else {
185 : if ((rs = inflateInit(z)) != Z_OK) {
186 : free(z);
187 : return _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS,
188 : err_fatal, "inflateInit() failed: %s", zError(rs));
189 : }
190 : telnet->flags &= ~TELNET_PFLAG_DEFLATE;
191 : }
192 :
193 : telnet->z = z;
194 :
195 : return TELNET_EOK;
196 : }
197 : #endif /* defined(HAVE_ZLIB) */
198 :
199 : /* push bytes out, compressing them first if need be */
200 0 : static void _send(telnet_t *telnet, const char *buffer,
201 : size_t size) {
202 : telnet_event_t ev;
203 :
204 : #if defined(HAVE_ZLIB)
205 : /* if we have a deflate (compression) zlib box, use it */
206 : if (telnet->z != 0 && telnet->flags & TELNET_PFLAG_DEFLATE) {
207 : char deflate_buffer[1024];
208 :
209 :
210 : /* initialize z state */
211 : telnet->z->next_in = (unsigned char *)buffer;
212 : telnet->z->avail_in = (unsigned int)size;
213 : telnet->z->next_out = (unsigned char *)deflate_buffer;
214 : telnet->z->avail_out = sizeof(deflate_buffer);
215 :
216 : /* deflate until buffer exhausted and all output is produced */
217 : while (telnet->z->avail_in > 0 || telnet->z->avail_out == 0) {
218 : int rs;
219 : /* compress */
220 : if ((rs = deflate(telnet->z, Z_SYNC_FLUSH)) != Z_OK) {
221 : _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, 1,
222 : "deflate() failed: %s", zError(rs));
223 : deflateEnd(telnet->z);
224 : free(telnet->z);
225 : telnet->z = 0;
226 : break;
227 : }
228 :
229 : /* send event */
230 : ev.type = TELNET_EV_SEND;
231 : ev.data.buffer = deflate_buffer;
232 : ev.data.size = sizeof(deflate_buffer) - telnet->z->avail_out;
233 : telnet->eh(telnet, &ev, telnet->ud);
234 :
235 : /* prepare output buffer for next run */
236 : telnet->z->next_out = (unsigned char *)deflate_buffer;
237 : telnet->z->avail_out = sizeof(deflate_buffer);
238 : }
239 :
240 : /* do not continue with remaining code */
241 : return;
242 : }
243 : #endif /* defined(HAVE_ZLIB) */
244 :
245 0 : ev.type = TELNET_EV_SEND;
246 0 : ev.data.buffer = buffer;
247 0 : ev.data.size = size;
248 0 : telnet->eh(telnet, &ev, telnet->ud);
249 0 : }
250 :
251 : /* to send bags of unsigned chars */
252 : #define _sendu(t, d, s) _send((t), (const char*)(d), (s))
253 :
254 : /* check if we support a particular telopt; if us is non-zero, we
255 : * check if we (local) supports it, otherwise we check if he (remote)
256 : * supports it. return non-zero if supported, zero if not supported.
257 : */
258 0 : static INLINE int _check_telopt(telnet_t *telnet, unsigned char telopt,
259 : int us) {
260 : int i;
261 :
262 : /* if we have no telopts table, we obviously don't support it */
263 0 : if (telnet->telopts == 0)
264 0 : return 0;
265 :
266 : /* loop unti found or end marker (us and him both 0) */
267 0 : for (i = 0; telnet->telopts[i].telopt != -1; ++i) {
268 0 : if (telnet->telopts[i].telopt == telopt) {
269 0 : if (us && telnet->telopts[i].us == TELNET_WILL)
270 0 : return 1;
271 0 : else if (!us && telnet->telopts[i].him == TELNET_DO)
272 0 : return 1;
273 : else
274 0 : return 0;
275 : }
276 : }
277 :
278 : /* not found, so not supported */
279 0 : return 0;
280 : }
281 :
282 : /* retrieve RFC1143 option state */
283 0 : static INLINE telnet_rfc1143_t _get_rfc1143(telnet_t *telnet,
284 : unsigned char telopt) {
285 : telnet_rfc1143_t empty;
286 : int i;
287 :
288 : /* search for entry */
289 0 : for (i = 0; i != telnet->q_size; ++i) {
290 0 : if (telnet->q[i].telopt == telopt) {
291 0 : return telnet->q[i];
292 : }
293 : }
294 :
295 : /* not found, return empty value */
296 0 : empty.telopt = telopt;
297 0 : empty.state = 0;
298 0 : return empty;
299 : }
300 :
301 : /* save RFC1143 option state */
302 0 : static INLINE void _set_rfc1143(telnet_t *telnet, unsigned char telopt,
303 : char us, char him) {
304 : telnet_rfc1143_t *qtmp;
305 : int i;
306 :
307 : /* search for entry */
308 0 : for (i = 0; i != telnet->q_size; ++i) {
309 0 : if (telnet->q[i].telopt == telopt) {
310 0 : telnet->q[i].state = Q_MAKE(us,him);
311 0 : if (telopt != TELNET_TELOPT_BINARY)
312 0 : return;
313 0 : telnet->flags &= ~(TELNET_FLAG_TRANSMIT_BINARY |
314 : TELNET_FLAG_RECEIVE_BINARY);
315 0 : if (us == Q_YES)
316 0 : telnet->flags |= TELNET_FLAG_TRANSMIT_BINARY;
317 0 : if (him == Q_YES)
318 0 : telnet->flags |= TELNET_FLAG_RECEIVE_BINARY;
319 0 : return;
320 : }
321 : }
322 :
323 : /* we're going to need to track state for it, so grow the queue
324 : * by 4 (four) elements and put the telopt into it; bail on allocation
325 : * error. we go by four because it seems like a reasonable guess as
326 : * to the number of enabled options for most simple code, and it
327 : * allows for an acceptable number of reallocations for complex code.
328 : */
329 0 : if ((qtmp = (telnet_rfc1143_t *)realloc(telnet->q,
330 0 : sizeof(telnet_rfc1143_t) * (telnet->q_size + 4))) == 0) {
331 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
332 0 : "realloc() failed: %s", strerror(errno));
333 0 : return;
334 : }
335 0 : memset(&qtmp[telnet->q_size], 0, sizeof(telnet_rfc1143_t) * 4);
336 0 : telnet->q = qtmp;
337 0 : telnet->q[telnet->q_size].telopt = telopt;
338 0 : telnet->q[telnet->q_size].state = Q_MAKE(us, him);
339 0 : telnet->q_size += 4;
340 : }
341 :
342 : /* send negotiation bytes */
343 0 : static INLINE void _send_negotiate(telnet_t *telnet, unsigned char cmd,
344 : unsigned char telopt) {
345 : unsigned char bytes[3];
346 0 : bytes[0] = TELNET_IAC;
347 0 : bytes[1] = cmd;
348 0 : bytes[2] = telopt;
349 0 : _sendu(telnet, bytes, 3);
350 0 : }
351 :
352 : /* negotiation handling magic for RFC1143 */
353 0 : static void _negotiate(telnet_t *telnet, unsigned char telopt) {
354 : telnet_event_t ev;
355 : telnet_rfc1143_t q;
356 :
357 : /* in PROXY mode, just pass it thru and do nothing */
358 0 : if (telnet->flags & TELNET_FLAG_PROXY) {
359 0 : switch ((int)telnet->state) {
360 0 : case TELNET_STATE_WILL:
361 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
362 0 : break;
363 0 : case TELNET_STATE_WONT:
364 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
365 0 : break;
366 0 : case TELNET_STATE_DO:
367 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
368 0 : break;
369 0 : case TELNET_STATE_DONT:
370 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
371 0 : break;
372 : }
373 0 : return;
374 : }
375 :
376 : /* lookup the current state of the option */
377 0 : q = _get_rfc1143(telnet, telopt);
378 :
379 : /* start processing... */
380 0 : switch ((int)telnet->state) {
381 : /* request to enable option on remote end or confirm DO */
382 0 : case TELNET_STATE_WILL:
383 0 : switch (Q_HIM(q)) {
384 0 : case Q_NO:
385 0 : if (_check_telopt(telnet, telopt, 0)) {
386 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
387 0 : _send_negotiate(telnet, TELNET_DO, telopt);
388 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
389 : } else
390 0 : _send_negotiate(telnet, TELNET_DONT, telopt);
391 0 : break;
392 0 : case Q_WANTNO:
393 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
394 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
395 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
396 : "DONT answered by WILL");
397 0 : break;
398 0 : case Q_WANTNO_OP:
399 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
400 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
401 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
402 : "DONT answered by WILL");
403 0 : break;
404 0 : case Q_WANTYES:
405 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_YES);
406 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
407 0 : break;
408 0 : case Q_WANTYES_OP:
409 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
410 0 : _send_negotiate(telnet, TELNET_DONT, telopt);
411 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
412 0 : break;
413 : }
414 0 : break;
415 :
416 : /* request to disable option on remote end, confirm DONT, reject DO */
417 0 : case TELNET_STATE_WONT:
418 0 : switch (Q_HIM(q)) {
419 0 : case Q_YES:
420 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
421 0 : _send_negotiate(telnet, TELNET_DONT, telopt);
422 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
423 0 : break;
424 0 : case Q_WANTNO:
425 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
426 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
427 0 : break;
428 0 : case Q_WANTNO_OP:
429 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
430 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
431 0 : break;
432 0 : case Q_WANTYES:
433 : case Q_WANTYES_OP:
434 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_NO);
435 0 : break;
436 : }
437 0 : break;
438 :
439 : /* request to enable option on local end or confirm WILL */
440 0 : case TELNET_STATE_DO:
441 0 : switch (Q_US(q)) {
442 0 : case Q_NO:
443 0 : if (_check_telopt(telnet, telopt, 1)) {
444 0 : _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
445 0 : _send_negotiate(telnet, TELNET_WILL, telopt);
446 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
447 : } else
448 0 : _send_negotiate(telnet, TELNET_WONT, telopt);
449 0 : break;
450 0 : case Q_WANTNO:
451 0 : _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
452 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
453 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
454 : "WONT answered by DO");
455 0 : break;
456 0 : case Q_WANTNO_OP:
457 0 : _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
458 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
459 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
460 : "WONT answered by DO");
461 0 : break;
462 0 : case Q_WANTYES:
463 0 : _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q));
464 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
465 0 : break;
466 0 : case Q_WANTYES_OP:
467 0 : _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
468 0 : _send_negotiate(telnet, TELNET_WONT, telopt);
469 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt);
470 0 : break;
471 : }
472 0 : break;
473 :
474 : /* request to disable option on local end, confirm WONT, reject WILL */
475 0 : case TELNET_STATE_DONT:
476 0 : switch (Q_US(q)) {
477 0 : case Q_YES:
478 0 : _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
479 0 : _send_negotiate(telnet, TELNET_WONT, telopt);
480 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt);
481 0 : break;
482 0 : case Q_WANTNO:
483 0 : _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
484 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt);
485 0 : break;
486 0 : case Q_WANTNO_OP:
487 0 : _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
488 0 : _send_negotiate(telnet, TELNET_WILL, telopt);
489 0 : NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt);
490 0 : break;
491 0 : case Q_WANTYES:
492 : case Q_WANTYES_OP:
493 0 : _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q));
494 0 : break;
495 : }
496 0 : break;
497 : }
498 : }
499 :
500 : /* process an ENVIRON/NEW-ENVIRON subnegotiation buffer
501 : *
502 : * the algorithm and approach used here is kind of a hack,
503 : * but it reduces the number of memory allocations we have
504 : * to make.
505 : *
506 : * we copy the bytes back into the buffer, starting at the very
507 : * beginning, which makes it easy to handle the ENVIRON ESC
508 : * escape mechanism as well as ensure the variable name and
509 : * value strings are NUL-terminated, all while fitting inside
510 : * of the original buffer.
511 : */
512 0 : static int _environ_telnet(telnet_t *telnet, unsigned char type,
513 : char* buffer, size_t size) {
514 : telnet_event_t ev;
515 0 : struct telnet_environ_t *values = 0;
516 : char *c, *last, *out;
517 : size_t index, count;
518 :
519 : /* if we have no data, just pass it through */
520 0 : if (size == 0) {
521 0 : return 0;
522 : }
523 :
524 : /* first byte must be a valid command */
525 0 : if ((unsigned)buffer[0] != TELNET_ENVIRON_SEND &&
526 0 : (unsigned)buffer[0] != TELNET_ENVIRON_IS &&
527 0 : (unsigned)buffer[0] != TELNET_ENVIRON_INFO) {
528 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
529 : "telopt %d subneg has invalid command", type);
530 0 : return 0;
531 : }
532 :
533 : /* store ENVIRON command */
534 0 : ev.environ.cmd = buffer[0];
535 :
536 : /* if we have no arguments, send an event with no data end return */
537 0 : if (size == 1) {
538 : /* no list of variables given */
539 0 : ev.environ.values = 0;
540 0 : ev.environ.size = 0;
541 :
542 : /* invoke event with our arguments */
543 0 : ev.type = TELNET_EV_ENVIRON;
544 0 : telnet->eh(telnet, &ev, telnet->ud);
545 :
546 0 : return 1;
547 : }
548 :
549 : /* very second byte must be VAR or USERVAR, if present */
550 0 : if ((unsigned)buffer[1] != TELNET_ENVIRON_VAR &&
551 0 : (unsigned)buffer[1] != TELNET_ENVIRON_USERVAR) {
552 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
553 : "telopt %d subneg missing variable type", type);
554 0 : return 0;
555 : }
556 :
557 : /* ensure last byte is not an escape byte (makes parsing later easier) */
558 0 : if ((unsigned)buffer[size - 1] == TELNET_ENVIRON_ESC) {
559 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
560 : "telopt %d subneg ends with ESC", type);
561 0 : return 0;
562 : }
563 :
564 : /* count arguments; each valid entry starts with VAR or USERVAR */
565 0 : count = 0;
566 0 : for (c = buffer + 1; c < buffer + size; ++c) {
567 0 : if (*c == TELNET_ENVIRON_VAR || *c == TELNET_ENVIRON_USERVAR) {
568 0 : ++count;
569 0 : } else if (*c == TELNET_ENVIRON_ESC) {
570 : /* skip the next byte */
571 0 : ++c;
572 : }
573 : }
574 :
575 : /* allocate argument array, bail on error */
576 0 : if ((values = (struct telnet_environ_t *)calloc(count,
577 : sizeof(struct telnet_environ_t))) == 0) {
578 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
579 0 : "calloc() failed: %s", strerror(errno));
580 0 : return 0;
581 : }
582 :
583 : /* parse argument array strings */
584 0 : out = buffer;
585 0 : c = buffer + 1;
586 0 : for (index = 0; index != count; ++index) {
587 : /* remember the variable type (will be VAR or USERVAR) */
588 0 : values[index].type = *c++;
589 :
590 : /* scan until we find an end-marker, and buffer up unescaped
591 : * bytes into our buffer */
592 0 : last = out;
593 0 : while (c < buffer + size) {
594 : /* stop at the next variable or at the value */
595 0 : if ((unsigned)*c == TELNET_ENVIRON_VAR ||
596 0 : (unsigned)*c == TELNET_ENVIRON_VALUE ||
597 0 : (unsigned)*c == TELNET_ENVIRON_USERVAR) {
598 : break;
599 : }
600 :
601 : /* buffer next byte (taking into account ESC) */
602 0 : if (*c == TELNET_ENVIRON_ESC) {
603 0 : ++c;
604 : }
605 :
606 0 : *out++ = *c++;
607 : }
608 0 : *out++ = '\0';
609 :
610 : /* store the variable name we have just received */
611 0 : values[index].var = last;
612 0 : values[index].value = "";
613 :
614 : /* if we got a value, find the next end marker and
615 : * store the value; otherwise, store empty string */
616 0 : if (c < buffer + size && *c == TELNET_ENVIRON_VALUE) {
617 0 : ++c;
618 0 : last = out;
619 0 : while (c < buffer + size) {
620 : /* stop when we find the start of the next variable */
621 0 : if ((unsigned)*c == TELNET_ENVIRON_VAR ||
622 0 : (unsigned)*c == TELNET_ENVIRON_USERVAR) {
623 : break;
624 : }
625 :
626 : /* buffer next byte (taking into account ESC) */
627 0 : if (*c == TELNET_ENVIRON_ESC) {
628 0 : ++c;
629 : }
630 :
631 0 : *out++ = *c++;
632 : }
633 0 : *out++ = '\0';
634 :
635 : /* store the variable value */
636 0 : values[index].value = last;
637 : }
638 : }
639 :
640 : /* pass values array and count to event */
641 0 : ev.environ.values = values;
642 0 : ev.environ.size = count;
643 :
644 : /* invoke event with our arguments */
645 0 : ev.type = TELNET_EV_ENVIRON;
646 0 : telnet->eh(telnet, &ev, telnet->ud);
647 :
648 : /* clean up */
649 0 : free(values);
650 0 : return 1;
651 : }
652 :
653 : /* process an MSSP subnegotiation buffer */
654 0 : static int _mssp_telnet(telnet_t *telnet, char* buffer, size_t size) {
655 : telnet_event_t ev;
656 : struct telnet_environ_t *values;
657 0 : char *var = 0;
658 : char *c, *last, *out;
659 : size_t i, count;
660 : unsigned char next_type;
661 :
662 : /* if we have no data, just pass it through */
663 0 : if (size == 0) {
664 0 : return 0;
665 : }
666 :
667 : /* first byte must be a VAR */
668 0 : if ((unsigned)buffer[0] != TELNET_MSSP_VAR) {
669 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
670 : "MSSP subnegotiation has invalid data");
671 0 : return 0;
672 : }
673 :
674 : /* count the arguments, any part that starts with VALUE */
675 0 : for (count = 0, i = 0; i != size; ++i) {
676 0 : if ((unsigned)buffer[i] == TELNET_MSSP_VAL) {
677 0 : ++count;
678 : }
679 : }
680 :
681 : /* allocate argument array, bail on error */
682 0 : if ((values = (struct telnet_environ_t *)calloc(count,
683 : sizeof(struct telnet_environ_t))) == 0) {
684 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
685 0 : "calloc() failed: %s", strerror(errno));
686 0 : return 0;
687 : }
688 :
689 0 : ev.mssp.values = values;
690 0 : ev.mssp.size = count;
691 :
692 : /* allocate strings in argument array */
693 0 : out = last = buffer;
694 0 : next_type = buffer[0];
695 0 : for (i = 0, c = buffer + 1; c < buffer + size;) {
696 : /* search for end marker */
697 0 : while (c < buffer + size && (unsigned)*c != TELNET_MSSP_VAR &&
698 0 : (unsigned)*c != TELNET_MSSP_VAL) {
699 0 : *out++ = *c++;
700 : }
701 0 : *out++ = '\0';
702 :
703 : /* if it's a variable name, just store the name for now */
704 0 : if (next_type == TELNET_MSSP_VAR) {
705 0 : var = last;
706 0 : } else if (next_type == TELNET_MSSP_VAL && var != 0) {
707 0 : values[i].var = var;
708 0 : values[i].value = last;
709 0 : ++i;
710 : } else {
711 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
712 : "invalid MSSP subnegotiation data");
713 0 : free(values);
714 0 : return 0;
715 : }
716 :
717 : /* remember our next type and increment c for next loop run */
718 0 : last = out;
719 0 : next_type = *c++;
720 : }
721 :
722 : /* invoke event with our arguments */
723 0 : ev.type = TELNET_EV_MSSP;
724 0 : telnet->eh(telnet, &ev, telnet->ud);
725 :
726 : /* clean up */
727 0 : free(values);
728 :
729 0 : return 0;
730 : }
731 :
732 : /* parse ZMP command subnegotiation buffers */
733 0 : static int _zmp_telnet(telnet_t *telnet, const char* buffer, size_t size) {
734 : telnet_event_t ev;
735 : char **argv;
736 : const char *c;
737 : size_t i, argc;
738 :
739 : /* make sure this is a valid ZMP buffer */
740 0 : if (size == 0 || buffer[size - 1] != 0) {
741 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
742 : "incomplete ZMP frame");
743 0 : return 0;
744 : }
745 :
746 : /* count arguments */
747 0 : for (argc = 0, c = buffer; c != buffer + size; ++argc)
748 0 : c += strlen(c) + 1;
749 :
750 : /* allocate argument array, bail on error */
751 0 : if ((argv = (char **)calloc(argc, sizeof(char *))) == 0) {
752 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
753 0 : "calloc() failed: %s", strerror(errno));
754 0 : return 0;
755 : }
756 :
757 : /* populate argument array */
758 0 : for (i = 0, c = buffer; i != argc; ++i) {
759 0 : argv[i] = (char *)c;
760 0 : c += strlen(c) + 1;
761 : }
762 :
763 : /* invoke event with our arguments */
764 0 : ev.type = TELNET_EV_ZMP;
765 0 : ev.zmp.argv = (const char**)argv;
766 0 : ev.zmp.argc = argc;
767 0 : telnet->eh(telnet, &ev, telnet->ud);
768 :
769 : /* clean up */
770 0 : free(argv);
771 0 : return 0;
772 : }
773 :
774 : /* parse TERMINAL-TYPE command subnegotiation buffers */
775 0 : static int _ttype_telnet(telnet_t *telnet, const char* buffer, size_t size) {
776 : telnet_event_t ev;
777 :
778 : /* make sure request is not empty */
779 0 : if (size == 0) {
780 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
781 : "incomplete TERMINAL-TYPE request");
782 0 : return 0;
783 : }
784 :
785 : /* make sure request has valid command type */
786 0 : if (buffer[0] != TELNET_TTYPE_IS &&
787 0 : buffer[0] != TELNET_TTYPE_SEND) {
788 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
789 : "TERMINAL-TYPE request has invalid type");
790 0 : return 0;
791 : }
792 :
793 : /* send proper event */
794 0 : if (buffer[0] == TELNET_TTYPE_IS) {
795 : char *name;
796 :
797 : /* allocate space for name */
798 0 : if ((name = (char *)malloc(size)) == 0) {
799 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
800 0 : "malloc() failed: %s", strerror(errno));
801 0 : return 0;
802 : }
803 0 : memcpy(name, buffer + 1, size - 1);
804 0 : name[size - 1] = '\0';
805 :
806 0 : ev.type = TELNET_EV_TTYPE;
807 0 : ev.ttype.cmd = TELNET_TTYPE_IS;
808 0 : ev.ttype.name = name;
809 0 : telnet->eh(telnet, &ev, telnet->ud);
810 :
811 : /* clean up */
812 0 : free(name);
813 : } else {
814 0 : ev.type = TELNET_EV_TTYPE;
815 0 : ev.ttype.cmd = TELNET_TTYPE_SEND;
816 0 : ev.ttype.name = 0;
817 0 : telnet->eh(telnet, &ev, telnet->ud);
818 : }
819 :
820 0 : return 0;
821 : }
822 :
823 : /* process a subnegotiation buffer; return non-zero if the current buffer
824 : * must be aborted and reprocessed due to COMPRESS2 being activated
825 : */
826 0 : static int _subnegotiate(telnet_t *telnet) {
827 : telnet_event_t ev;
828 :
829 : /* standard subnegotiation event */
830 0 : ev.type = TELNET_EV_SUBNEGOTIATION;
831 0 : ev.sub.telopt = telnet->sb_telopt;
832 0 : ev.sub.buffer = telnet->buffer;
833 0 : ev.sub.size = telnet->buffer_pos;
834 0 : telnet->eh(telnet, &ev, telnet->ud);
835 :
836 0 : switch (telnet->sb_telopt) {
837 : #if defined(HAVE_ZLIB)
838 : /* received COMPRESS2 begin marker, setup our zlib box and
839 : * start handling the compressed stream if it's not already.
840 : */
841 : case TELNET_TELOPT_COMPRESS2:
842 : if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) {
843 : if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
844 : return 0;
845 :
846 : /* notify app that compression was enabled */
847 : ev.type = TELNET_EV_COMPRESS;
848 : ev.compress.state = 1;
849 : telnet->eh(telnet, &ev, telnet->ud);
850 : return 1;
851 : }
852 : return 0;
853 : #endif /* defined(HAVE_ZLIB) */
854 :
855 : /* specially handled subnegotiation telopt types */
856 0 : case TELNET_TELOPT_ZMP:
857 0 : return _zmp_telnet(telnet, telnet->buffer, telnet->buffer_pos);
858 0 : case TELNET_TELOPT_TTYPE:
859 0 : return _ttype_telnet(telnet, telnet->buffer, telnet->buffer_pos);
860 0 : case TELNET_TELOPT_ENVIRON:
861 : case TELNET_TELOPT_NEW_ENVIRON:
862 0 : return _environ_telnet(telnet, telnet->sb_telopt, telnet->buffer,
863 : telnet->buffer_pos);
864 0 : case TELNET_TELOPT_MSSP:
865 0 : return _mssp_telnet(telnet, telnet->buffer, telnet->buffer_pos);
866 0 : default:
867 0 : return 0;
868 : }
869 : }
870 :
871 : /* initialize a telnet state tracker */
872 0 : telnet_t *telnet_init(const telnet_telopt_t *telopts,
873 : telnet_event_handler_t eh, unsigned char flags, void *user_data) {
874 : /* allocate structure */
875 0 : struct telnet_t *telnet = (telnet_t*)calloc(1, sizeof(telnet_t));
876 0 : if (telnet == 0)
877 0 : return 0;
878 :
879 : /* initialize data */
880 0 : telnet->ud = user_data;
881 0 : telnet->telopts = telopts;
882 0 : telnet->eh = eh;
883 0 : telnet->flags = flags;
884 :
885 0 : return telnet;
886 : }
887 :
888 : /* free up any memory allocated by a state tracker */
889 0 : void telnet_free(telnet_t *telnet) {
890 : /* free sub-request buffer */
891 0 : if (telnet->buffer != 0) {
892 0 : free(telnet->buffer);
893 0 : telnet->buffer = 0;
894 0 : telnet->buffer_size = 0;
895 0 : telnet->buffer_pos = 0;
896 : }
897 :
898 : #if defined(HAVE_ZLIB)
899 : /* free zlib box */
900 : if (telnet->z != 0) {
901 : if (telnet->flags & TELNET_PFLAG_DEFLATE)
902 : deflateEnd(telnet->z);
903 : else
904 : inflateEnd(telnet->z);
905 : free(telnet->z);
906 : telnet->z = 0;
907 : }
908 : #endif /* defined(HAVE_ZLIB) */
909 :
910 : /* free RFC1143 queue */
911 0 : if (telnet->q) {
912 0 : free(telnet->q);
913 0 : telnet->q = 0;
914 0 : telnet->q_size = 0;
915 : }
916 :
917 : /* free the telnet structure itself */
918 0 : free(telnet);
919 0 : }
920 :
921 : /* push a byte into the telnet buffer */
922 0 : static telnet_error_t _buffer_byte(telnet_t *telnet,
923 : unsigned char byte) {
924 : char *new_buffer;
925 :
926 :
927 : /* check if we're out of room */
928 0 : if (telnet->buffer_pos == telnet->buffer_size) {
929 : size_t i;
930 : /* find the next buffer size */
931 0 : for (i = 0; i != _buffer_sizes_count; ++i) {
932 0 : if (_buffer_sizes[i] == telnet->buffer_size) {
933 0 : break;
934 : }
935 : }
936 :
937 : /* overflow -- can't grow any more */
938 0 : if (i >= _buffer_sizes_count - 1) {
939 0 : _error(telnet, __LINE__, __func__, TELNET_EOVERFLOW, 0,
940 : "subnegotiation buffer size limit reached");
941 0 : return TELNET_EOVERFLOW;
942 : }
943 :
944 : /* (re)allocate buffer */
945 0 : new_buffer = (char *)realloc(telnet->buffer, _buffer_sizes[i + 1]);
946 0 : if (new_buffer == 0) {
947 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
948 : "realloc() failed");
949 0 : return TELNET_ENOMEM;
950 : }
951 :
952 0 : telnet->buffer = new_buffer;
953 0 : telnet->buffer_size = _buffer_sizes[i + 1];
954 : }
955 :
956 : /* push the byte, all set */
957 0 : telnet->buffer[telnet->buffer_pos++] = byte;
958 0 : return TELNET_EOK;
959 : }
960 :
961 0 : static void _process(telnet_t *telnet, const char *buffer, size_t size) {
962 : telnet_event_t ev;
963 : unsigned char byte;
964 : size_t i, start;
965 0 : for (i = start = 0; i != size; ++i) {
966 0 : byte = buffer[i];
967 0 : switch (telnet->state) {
968 : /* regular data */
969 0 : case TELNET_STATE_DATA:
970 : /* on an IAC byte, pass through all pending bytes and
971 : * switch states */
972 0 : if (byte == TELNET_IAC) {
973 0 : if (i != start) {
974 0 : ev.type = TELNET_EV_DATA;
975 0 : ev.data.buffer = buffer + start;
976 0 : ev.data.size = i - start;
977 0 : telnet->eh(telnet, &ev, telnet->ud);
978 : }
979 0 : telnet->state = TELNET_STATE_IAC;
980 0 : } else if (byte == '\r' &&
981 0 : (telnet->flags & TELNET_FLAG_NVT_EOL) &&
982 0 : !(telnet->flags & TELNET_FLAG_RECEIVE_BINARY)) {
983 0 : if (i != start) {
984 0 : ev.type = TELNET_EV_DATA;
985 0 : ev.data.buffer = buffer + start;
986 0 : ev.data.size = i - start;
987 0 : telnet->eh(telnet, &ev, telnet->ud);
988 : }
989 0 : telnet->state = TELNET_STATE_EOL;
990 : }
991 0 : break;
992 :
993 : /* NVT EOL to be translated */
994 0 : case TELNET_STATE_EOL:
995 0 : if (byte != '\n') {
996 0 : byte = '\r';
997 0 : ev.type = TELNET_EV_DATA;
998 0 : ev.data.buffer = (char*)&byte;
999 0 : ev.data.size = 1;
1000 0 : telnet->eh(telnet, &ev, telnet->ud);
1001 0 : byte = buffer[i];
1002 : }
1003 : // any byte following '\r' other than '\n' or '\0' is invalid,
1004 : // so pass both \r and the byte
1005 0 : start = i;
1006 0 : if (byte == '\0')
1007 0 : ++start;
1008 : /* state update */
1009 0 : telnet->state = TELNET_STATE_DATA;
1010 0 : break;
1011 :
1012 : /* IAC command */
1013 0 : case TELNET_STATE_IAC:
1014 0 : switch (byte) {
1015 : /* subnegotiation */
1016 0 : case TELNET_SB:
1017 0 : telnet->state = TELNET_STATE_SB;
1018 0 : break;
1019 : /* negotiation commands */
1020 0 : case TELNET_WILL:
1021 0 : telnet->state = TELNET_STATE_WILL;
1022 0 : break;
1023 0 : case TELNET_WONT:
1024 0 : telnet->state = TELNET_STATE_WONT;
1025 0 : break;
1026 0 : case TELNET_DO:
1027 0 : telnet->state = TELNET_STATE_DO;
1028 0 : break;
1029 0 : case TELNET_DONT:
1030 0 : telnet->state = TELNET_STATE_DONT;
1031 0 : break;
1032 : /* IAC escaping */
1033 0 : case TELNET_IAC:
1034 : /* event */
1035 0 : ev.type = TELNET_EV_DATA;
1036 0 : ev.data.buffer = (char*)&byte;
1037 0 : ev.data.size = 1;
1038 0 : telnet->eh(telnet, &ev, telnet->ud);
1039 :
1040 : /* state update */
1041 0 : start = i + 1;
1042 0 : telnet->state = TELNET_STATE_DATA;
1043 0 : break;
1044 : /* some other command */
1045 0 : default:
1046 : /* event */
1047 0 : ev.type = TELNET_EV_IAC;
1048 0 : ev.iac.cmd = byte;
1049 0 : telnet->eh(telnet, &ev, telnet->ud);
1050 :
1051 : /* state update */
1052 0 : start = i + 1;
1053 0 : telnet->state = TELNET_STATE_DATA;
1054 : }
1055 0 : break;
1056 :
1057 : /* negotiation commands */
1058 0 : case TELNET_STATE_WILL:
1059 : case TELNET_STATE_WONT:
1060 : case TELNET_STATE_DO:
1061 : case TELNET_STATE_DONT:
1062 0 : _negotiate(telnet, byte);
1063 0 : start = i + 1;
1064 0 : telnet->state = TELNET_STATE_DATA;
1065 0 : break;
1066 :
1067 : /* subnegotiation -- determine subnegotiation telopt */
1068 0 : case TELNET_STATE_SB:
1069 0 : telnet->sb_telopt = byte;
1070 0 : telnet->buffer_pos = 0;
1071 0 : telnet->state = TELNET_STATE_SB_DATA;
1072 0 : break;
1073 :
1074 : /* subnegotiation -- buffer bytes until end request */
1075 0 : case TELNET_STATE_SB_DATA:
1076 : /* IAC command in subnegotiation -- either IAC SE or IAC IAC */
1077 0 : if (byte == TELNET_IAC) {
1078 0 : telnet->state = TELNET_STATE_SB_DATA_IAC;
1079 0 : } else if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS && byte == TELNET_WILL) {
1080 : /* In 1998 MCCP used TELOPT 85 and the protocol defined an invalid
1081 : * subnegotiation sequence (IAC SB 85 WILL SE) to start compression.
1082 : * Subsequently MCCP version 2 was created in 2000 using TELOPT 86
1083 : * and a valid subnegotiation (IAC SB 86 IAC SE). libtelnet for now
1084 : * just captures and discards MCCPv1 sequences.
1085 : */
1086 0 : start = i + 2;
1087 0 : telnet->state = TELNET_STATE_DATA;
1088 : /* buffer the byte, or bail if we can't */
1089 0 : } else if (_buffer_byte(telnet, byte) != TELNET_EOK) {
1090 0 : start = i + 1;
1091 0 : telnet->state = TELNET_STATE_DATA;
1092 : }
1093 0 : break;
1094 :
1095 : /* IAC escaping inside a subnegotiation */
1096 0 : case TELNET_STATE_SB_DATA_IAC:
1097 0 : switch (byte) {
1098 : /* end subnegotiation */
1099 0 : case TELNET_SE:
1100 : /* return to default state */
1101 0 : start = i + 1;
1102 0 : telnet->state = TELNET_STATE_DATA;
1103 :
1104 : /* process subnegotiation */
1105 0 : if (_subnegotiate(telnet) != 0) {
1106 : /* any remaining bytes in the buffer are compressed.
1107 : * we have to re-invoke telnet_recv to get those
1108 : * bytes inflated and abort trying to process the
1109 : * remaining compressed bytes in the current _process
1110 : * buffer argument
1111 : */
1112 0 : telnet_recv(telnet, &buffer[start], size - start);
1113 0 : return;
1114 : }
1115 0 : break;
1116 : /* escaped IAC byte */
1117 0 : case TELNET_IAC:
1118 : /* push IAC into buffer */
1119 0 : if (_buffer_byte(telnet, TELNET_IAC) !=
1120 : TELNET_EOK) {
1121 0 : start = i + 1;
1122 0 : telnet->state = TELNET_STATE_DATA;
1123 : } else {
1124 0 : telnet->state = TELNET_STATE_SB_DATA;
1125 : }
1126 0 : break;
1127 : /* something else -- protocol error. attempt to process
1128 : * content in subnegotiation buffer, then evaluate the
1129 : * given command as an IAC code.
1130 : */
1131 0 : default:
1132 0 : _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0,
1133 : "unexpected byte after IAC inside SB: %d",
1134 : byte);
1135 :
1136 : /* enter IAC state */
1137 0 : start = i + 1;
1138 0 : telnet->state = TELNET_STATE_IAC;
1139 :
1140 : /* process subnegotiation; see comment in
1141 : * TELNET_STATE_SB_DATA_IAC about invoking telnet_recv()
1142 : */
1143 0 : if (_subnegotiate(telnet) != 0) {
1144 0 : telnet_recv(telnet, &buffer[start], size - start);
1145 0 : return;
1146 : } else {
1147 : /* recursive call to get the current input byte processed
1148 : * as a regular IAC command. we could use a goto, but
1149 : * that would be gross.
1150 : */
1151 0 : _process(telnet, (char *)&byte, 1);
1152 : }
1153 0 : break;
1154 : }
1155 0 : break;
1156 : }
1157 : }
1158 :
1159 : /* pass through any remaining bytes */
1160 0 : if (telnet->state == TELNET_STATE_DATA && i != start) {
1161 0 : ev.type = TELNET_EV_DATA;
1162 0 : ev.data.buffer = buffer + start;
1163 0 : ev.data.size = i - start;
1164 0 : telnet->eh(telnet, &ev, telnet->ud);
1165 : }
1166 : }
1167 :
1168 : /* push a bytes into the state tracker */
1169 0 : void telnet_recv(telnet_t *telnet, const char *buffer,
1170 : size_t size) {
1171 : #if defined(HAVE_ZLIB)
1172 : /* if we have an inflate (decompression) zlib stream, use it */
1173 : if (telnet->z != 0 && !(telnet->flags & TELNET_PFLAG_DEFLATE)) {
1174 : char inflate_buffer[1024];
1175 :
1176 :
1177 : /* initialize zlib state */
1178 : telnet->z->next_in = (unsigned char*)buffer;
1179 : telnet->z->avail_in = (unsigned int)size;
1180 : telnet->z->next_out = (unsigned char *)inflate_buffer;
1181 : telnet->z->avail_out = sizeof(inflate_buffer);
1182 :
1183 : /* inflate until buffer exhausted and all output is produced */
1184 : while (telnet->z->avail_in > 0 || telnet->z->avail_out == 0) {
1185 : int rs;
1186 : /* reset output buffer */
1187 :
1188 : /* decompress */
1189 : rs = inflate(telnet->z, Z_SYNC_FLUSH);
1190 :
1191 : /* process the decompressed bytes on success */
1192 : if (rs == Z_OK || rs == Z_STREAM_END)
1193 : _process(telnet, inflate_buffer, sizeof(inflate_buffer) -
1194 : telnet->z->avail_out);
1195 : else
1196 : _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, 1,
1197 : "inflate() failed: %s", zError(rs));
1198 :
1199 : /* prepare output buffer for next run */
1200 : telnet->z->next_out = (unsigned char *)inflate_buffer;
1201 : telnet->z->avail_out = sizeof(inflate_buffer);
1202 :
1203 : /* on error (or on end of stream) disable further inflation */
1204 : if (rs != Z_OK) {
1205 : telnet_event_t ev;
1206 :
1207 : /* disable compression */
1208 : inflateEnd(telnet->z);
1209 : free(telnet->z);
1210 : telnet->z = 0;
1211 :
1212 : /* send event */
1213 : ev.type = TELNET_EV_COMPRESS;
1214 : ev.compress.state = 0;
1215 : telnet->eh(telnet, &ev, telnet->ud);
1216 :
1217 : break;
1218 : }
1219 : }
1220 :
1221 : /* COMPRESS2 is not negotiated, just process */
1222 : } else
1223 : #endif /* defined(HAVE_ZLIB) */
1224 0 : _process(telnet, buffer, size);
1225 0 : }
1226 :
1227 : /* send an iac command */
1228 0 : void telnet_iac(telnet_t *telnet, unsigned char cmd) {
1229 : unsigned char bytes[2];
1230 0 : bytes[0] = TELNET_IAC;
1231 0 : bytes[1] = cmd;
1232 0 : _sendu(telnet, bytes, 2);
1233 0 : }
1234 :
1235 : /* send negotiation */
1236 0 : void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
1237 : unsigned char telopt) {
1238 : telnet_rfc1143_t q;
1239 :
1240 : /* if we're in proxy mode, just send it now */
1241 0 : if (telnet->flags & TELNET_FLAG_PROXY) {
1242 : unsigned char bytes[3];
1243 0 : bytes[0] = TELNET_IAC;
1244 0 : bytes[1] = cmd;
1245 0 : bytes[2] = telopt;
1246 0 : _sendu(telnet, bytes, 3);
1247 0 : return;
1248 : }
1249 :
1250 : /* get current option states */
1251 0 : q = _get_rfc1143(telnet, telopt);
1252 :
1253 0 : switch (cmd) {
1254 : /* advertise willingess to support an option */
1255 0 : case TELNET_WILL:
1256 0 : switch (Q_US(q)) {
1257 0 : case Q_NO:
1258 0 : _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
1259 0 : _send_negotiate(telnet, TELNET_WILL, telopt);
1260 0 : break;
1261 0 : case Q_WANTNO:
1262 0 : _set_rfc1143(telnet, telopt, Q_WANTNO_OP, Q_HIM(q));
1263 0 : break;
1264 0 : case Q_WANTYES_OP:
1265 0 : _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q));
1266 0 : break;
1267 : }
1268 0 : break;
1269 :
1270 : /* force turn-off of locally enabled option */
1271 0 : case TELNET_WONT:
1272 0 : switch (Q_US(q)) {
1273 0 : case Q_YES:
1274 0 : _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
1275 0 : _send_negotiate(telnet, TELNET_WONT, telopt);
1276 0 : break;
1277 0 : case Q_WANTYES:
1278 0 : _set_rfc1143(telnet, telopt, Q_WANTYES_OP, Q_HIM(q));
1279 0 : break;
1280 0 : case Q_WANTNO_OP:
1281 0 : _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q));
1282 0 : break;
1283 : }
1284 0 : break;
1285 :
1286 : /* ask remote end to enable an option */
1287 0 : case TELNET_DO:
1288 0 : switch (Q_HIM(q)) {
1289 0 : case Q_NO:
1290 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
1291 0 : _send_negotiate(telnet, TELNET_DO, telopt);
1292 0 : break;
1293 0 : case Q_WANTNO:
1294 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO_OP);
1295 0 : break;
1296 0 : case Q_WANTYES_OP:
1297 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES);
1298 0 : break;
1299 : }
1300 0 : break;
1301 :
1302 : /* demand remote end disable an option */
1303 0 : case TELNET_DONT:
1304 0 : switch (Q_HIM(q)) {
1305 0 : case Q_YES:
1306 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
1307 0 : _send_negotiate(telnet, TELNET_DONT, telopt);
1308 0 : break;
1309 0 : case Q_WANTYES:
1310 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES_OP);
1311 0 : break;
1312 0 : case Q_WANTNO_OP:
1313 0 : _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO);
1314 0 : break;
1315 : }
1316 0 : break;
1317 : }
1318 : }
1319 :
1320 : /* send non-command data (escapes IAC bytes) */
1321 0 : void telnet_send(telnet_t *telnet, const char *buffer,
1322 : size_t size) {
1323 : size_t i, l;
1324 :
1325 0 : for (l = i = 0; i != size; ++i) {
1326 : /* dump prior portion of text, send escaped bytes */
1327 0 : if (buffer[i] == (char)TELNET_IAC) {
1328 : /* dump prior text if any */
1329 0 : if (i != l) {
1330 0 : _send(telnet, buffer + l, i - l);
1331 : }
1332 0 : l = i + 1;
1333 :
1334 : /* send escape */
1335 0 : telnet_iac(telnet, TELNET_IAC);
1336 : }
1337 : }
1338 :
1339 : /* send whatever portion of buffer is left */
1340 0 : if (i != l) {
1341 0 : _send(telnet, buffer + l, i - l);
1342 : }
1343 0 : }
1344 :
1345 : /* send non-command text (escapes IAC bytes and does NVT translation) */
1346 0 : void telnet_send_text(telnet_t *telnet, const char *buffer,
1347 : size_t size) {
1348 : size_t i, l;
1349 :
1350 0 : for (l = i = 0; i != size; ++i) {
1351 : /* dump prior portion of text, send escaped bytes */
1352 0 : if (buffer[i] == (char)TELNET_IAC) {
1353 : /* dump prior text if any */
1354 0 : if (i != l) {
1355 0 : _send(telnet, buffer + l, i - l);
1356 : }
1357 0 : l = i + 1;
1358 :
1359 : /* send escape */
1360 0 : telnet_iac(telnet, TELNET_IAC);
1361 : }
1362 : /* special characters if not in BINARY mode */
1363 0 : else if (!(telnet->flags & TELNET_FLAG_TRANSMIT_BINARY) &&
1364 0 : (buffer[i] == '\r' || buffer[i] == '\n')) {
1365 : /* dump prior portion of text */
1366 0 : if (i != l) {
1367 0 : _send(telnet, buffer + l, i - l);
1368 : }
1369 0 : l = i + 1;
1370 :
1371 : /* automatic translation of \r -> CRNUL */
1372 0 : if (buffer[i] == '\r') {
1373 0 : _send(telnet, CRNUL, 2);
1374 : }
1375 : /* automatic translation of \n -> CRLF */
1376 : else {
1377 0 : _send(telnet, CRLF, 2);
1378 : }
1379 : }
1380 : }
1381 :
1382 : /* send whatever portion of buffer is left */
1383 0 : if (i != l) {
1384 0 : _send(telnet, buffer + l, i - l);
1385 : }
1386 0 : }
1387 :
1388 : /* send subnegotiation header */
1389 0 : void telnet_begin_sb(telnet_t *telnet, unsigned char telopt) {
1390 : unsigned char sb[3];
1391 0 : sb[0] = TELNET_IAC;
1392 0 : sb[1] = TELNET_SB;
1393 0 : sb[2] = telopt;
1394 0 : _sendu(telnet, sb, 3);
1395 0 : }
1396 :
1397 :
1398 : /* send complete subnegotiation */
1399 0 : void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt,
1400 : const char *buffer, size_t size) {
1401 : unsigned char bytes[5];
1402 0 : bytes[0] = TELNET_IAC;
1403 0 : bytes[1] = TELNET_SB;
1404 0 : bytes[2] = telopt;
1405 0 : bytes[3] = TELNET_IAC;
1406 0 : bytes[4] = TELNET_SE;
1407 :
1408 0 : _sendu(telnet, bytes, 3);
1409 0 : telnet_send(telnet, buffer, size);
1410 0 : _sendu(telnet, bytes + 3, 2);
1411 :
1412 : #if defined(HAVE_ZLIB)
1413 : /* if we're a proxy and we just sent the COMPRESS2 marker, we must
1414 : * make sure all further data is compressed if not already.
1415 : */
1416 : if (telnet->flags & TELNET_FLAG_PROXY &&
1417 : telopt == TELNET_TELOPT_COMPRESS2) {
1418 : telnet_event_t ev;
1419 :
1420 : if (_init_zlib(telnet, 1, 1) != TELNET_EOK)
1421 : return;
1422 :
1423 : /* notify app that compression was enabled */
1424 : ev.type = TELNET_EV_COMPRESS;
1425 : ev.compress.state = 1;
1426 : telnet->eh(telnet, &ev, telnet->ud);
1427 : }
1428 : #endif /* defined(HAVE_ZLIB) */
1429 0 : }
1430 :
1431 0 : void telnet_begin_compress2(telnet_t *telnet) {
1432 : #if defined(HAVE_ZLIB)
1433 : static const unsigned char compress2[] = { TELNET_IAC, TELNET_SB,
1434 : TELNET_TELOPT_COMPRESS2, TELNET_IAC, TELNET_SE };
1435 :
1436 : telnet_event_t ev;
1437 :
1438 : /* attempt to create output stream first, bail if we can't */
1439 : if (_init_zlib(telnet, 1, 0) != TELNET_EOK)
1440 : return;
1441 :
1442 : /* send compression marker. we send directly to the event handler
1443 : * instead of passing through _send because _send would result in
1444 : * the compress marker itself being compressed.
1445 : */
1446 : ev.type = TELNET_EV_SEND;
1447 : ev.data.buffer = (const char*)compress2;
1448 : ev.data.size = sizeof(compress2);
1449 : telnet->eh(telnet, &ev, telnet->ud);
1450 :
1451 : /* notify app that compression was successfully enabled */
1452 : ev.type = TELNET_EV_COMPRESS;
1453 : ev.compress.state = 1;
1454 : telnet->eh(telnet, &ev, telnet->ud);
1455 : #endif /* defined(HAVE_ZLIB) */
1456 0 : }
1457 :
1458 : /* send formatted data with \r and \n translation in addition to IAC IAC */
1459 0 : int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va) {
1460 : char buffer[1024];
1461 0 : char *output = buffer;
1462 : int rs, i, l;
1463 :
1464 : /* format */
1465 : va_list va2;
1466 0 : va_copy(va2, va);
1467 0 : rs = vsnprintf(buffer, sizeof(buffer), fmt, va);
1468 0 : if (rs >= sizeof(buffer)) {
1469 0 : output = (char*)malloc(rs + 1);
1470 0 : if (output == 0) {
1471 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
1472 0 : "malloc() failed: %s", strerror(errno));
1473 0 : va_end(va2);
1474 0 : va_end(va);
1475 0 : return -1;
1476 : }
1477 0 : rs = vsnprintf(output, rs + 1, fmt, va2);
1478 : }
1479 0 : va_end(va2);
1480 0 : va_end(va);
1481 :
1482 : /* send */
1483 0 : for (l = i = 0; i != rs; ++i) {
1484 : /* special characters */
1485 0 : if (output[i] == (char)TELNET_IAC || output[i] == '\r' ||
1486 0 : output[i] == '\n') {
1487 : /* dump prior portion of text */
1488 0 : if (i != l)
1489 0 : _send(telnet, output + l, i - l);
1490 0 : l = i + 1;
1491 :
1492 : /* IAC -> IAC IAC */
1493 0 : if (output[i] == (char)TELNET_IAC)
1494 0 : telnet_iac(telnet, TELNET_IAC);
1495 : /* automatic translation of \r -> CRNUL */
1496 0 : else if (output[i] == '\r')
1497 0 : _send(telnet, CRNUL, 2);
1498 : /* automatic translation of \n -> CRLF */
1499 0 : else if (output[i] == '\n')
1500 0 : _send(telnet, CRLF, 2);
1501 : }
1502 : }
1503 :
1504 : /* send whatever portion of output is left */
1505 0 : if (i != l) {
1506 0 : _send(telnet, output + l, i - l);
1507 : }
1508 :
1509 : /* free allocated memory, if any */
1510 0 : if (output != buffer) {
1511 0 : free(output);
1512 : }
1513 :
1514 0 : return rs;
1515 : }
1516 :
1517 : /* see telnet_vprintf */
1518 0 : int telnet_printf(telnet_t *telnet, const char *fmt, ...) {
1519 : va_list va;
1520 : int rs;
1521 :
1522 0 : va_start(va, fmt);
1523 0 : rs = telnet_vprintf(telnet, fmt, va);
1524 0 : va_end(va);
1525 :
1526 0 : return rs;
1527 : }
1528 :
1529 : /* send formatted data through telnet_send */
1530 0 : int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va) {
1531 : char buffer[1024];
1532 0 : char *output = buffer;
1533 : int rs;
1534 :
1535 : /* format; allocate more space if necessary */
1536 : va_list va2;
1537 0 : va_copy(va2, va);
1538 0 : rs = vsnprintf(buffer, sizeof(buffer), fmt, va);
1539 0 : if (rs >= sizeof(buffer)) {
1540 0 : output = (char*)malloc(rs + 1);
1541 0 : if (output == 0) {
1542 0 : _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
1543 0 : "malloc() failed: %s", strerror(errno));
1544 0 : va_end(va);
1545 0 : va_end(va2);
1546 0 : return -1;
1547 : }
1548 0 : rs = vsnprintf(output, rs + 1, fmt, va2);
1549 : }
1550 0 : va_end(va2);
1551 0 : va_end(va);
1552 :
1553 : /* send out the formatted data */
1554 0 : telnet_send(telnet, output, rs);
1555 :
1556 : /* release allocated memory, if any */
1557 0 : if (output != buffer) {
1558 0 : free(output);
1559 : }
1560 :
1561 0 : return rs;
1562 : }
1563 :
1564 : /* see telnet_raw_vprintf */
1565 0 : int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) {
1566 : va_list va;
1567 : int rs;
1568 :
1569 0 : va_start(va, fmt);
1570 0 : rs = telnet_raw_vprintf(telnet, fmt, va);
1571 0 : va_end(va);
1572 :
1573 0 : return rs;
1574 : }
1575 :
1576 : /* begin NEW-ENVIRON subnegotation */
1577 0 : void telnet_begin_newenviron(telnet_t *telnet, unsigned char cmd) {
1578 0 : telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON);
1579 0 : telnet_send(telnet, (const char *)&cmd, 1);
1580 0 : }
1581 :
1582 : /* send a NEW-ENVIRON value */
1583 0 : void telnet_newenviron_value(telnet_t *telnet, unsigned char type,
1584 : const char *string) {
1585 0 : telnet_send(telnet, (const char*)&type, 1);
1586 :
1587 0 : if (string != 0) {
1588 0 : telnet_send(telnet, string, strlen(string));
1589 : }
1590 0 : }
1591 :
1592 : /* send TERMINAL-TYPE SEND command */
1593 0 : void telnet_ttype_send(telnet_t *telnet) {
1594 : static const unsigned char SEND[] = { TELNET_IAC, TELNET_SB,
1595 : TELNET_TELOPT_TTYPE, TELNET_TTYPE_SEND, TELNET_IAC, TELNET_SE };
1596 0 : _sendu(telnet, SEND, sizeof(SEND));
1597 0 : }
1598 :
1599 : /* send TERMINAL-TYPE IS command */
1600 0 : void telnet_ttype_is(telnet_t *telnet, const char* ttype) {
1601 : static const unsigned char IS[] = { TELNET_IAC, TELNET_SB,
1602 : TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS };
1603 0 : _sendu(telnet, IS, sizeof(IS));
1604 0 : _send(telnet, ttype, strlen(ttype));
1605 0 : telnet_finish_sb(telnet);
1606 0 : }
1607 :
1608 : /* send ZMP data */
1609 0 : void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv) {
1610 : size_t i;
1611 :
1612 : /* ZMP header */
1613 0 : telnet_begin_zmp(telnet, argv[0]);
1614 :
1615 : /* send out each argument, including trailing NUL byte */
1616 0 : for (i = 1; i != argc; ++i)
1617 0 : telnet_zmp_arg(telnet, argv[i]);
1618 :
1619 : /* ZMP footer */
1620 0 : telnet_finish_zmp(telnet);
1621 0 : }
1622 :
1623 : /* send ZMP data using varargs */
1624 0 : void telnet_send_vzmpv(telnet_t *telnet, va_list va) {
1625 : const char* arg;
1626 :
1627 : /* ZMP header */
1628 0 : telnet_begin_sb(telnet, TELNET_TELOPT_ZMP);
1629 :
1630 : /* send out each argument, including trailing NUL byte */
1631 0 : while ((arg = va_arg(va, const char *)) != 0)
1632 0 : telnet_zmp_arg(telnet, arg);
1633 :
1634 : /* ZMP footer */
1635 0 : telnet_finish_zmp(telnet);
1636 0 : }
1637 :
1638 : /* see telnet_send_vzmpv */
1639 0 : void telnet_send_zmpv(telnet_t *telnet, ...) {
1640 : va_list va;
1641 :
1642 0 : va_start(va, telnet);
1643 0 : telnet_send_vzmpv(telnet, va);
1644 0 : va_end(va);
1645 0 : }
1646 :
1647 : /* begin a ZMP command */
1648 0 : void telnet_begin_zmp(telnet_t *telnet, const char *cmd) {
1649 0 : telnet_begin_sb(telnet, TELNET_TELOPT_ZMP);
1650 0 : telnet_zmp_arg(telnet, cmd);
1651 0 : }
1652 :
1653 : /* send a ZMP argument */
1654 0 : void telnet_zmp_arg(telnet_t *telnet, const char* arg) {
1655 0 : telnet_send(telnet, arg, strlen(arg) + 1);
1656 0 : }
|