1 /*
2 * Copyright (c) 1993-2021 Paul Mattes.
3 * Copyright (c) 2004, Don Russell.
4 * Copyright (c) 1990, Jeff Sparkes.
5 * Copyright (c) 1989, Georgia Tech Research Corporation (GTRC), Atlanta,
6 * GA 30332.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * * Neither the names of Paul Mattes, Don Russell, Jeff Sparkes, GTRC
18 * nor their contributors may be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY PAUL MATTES, DON RUSSELL, JEFF SPARKES AND
22 * GTRC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PAUL MATTES,
25 * DON RUSSELL, JEFF SPARKES OR GTRC BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * telnet.c
36 * This module initializes and manages a telnet socket to
37 * the given IBM host.
38 */
39
40 #include "globals.h"
41
42 #if !defined(_WIN32) /*[*/
43 # include <sys/ioctl.h>
44 # include <netinet/in.h>
45 #endif /*]*/
46 #define TELCMDS 1
47 #define TELOPTS 1
48 #include "arpa_telnet.h"
49 #if !defined(_WIN32) /*[*/
50 # include <arpa/inet.h>
51 #endif /*]*/
52 #include <errno.h>
53 #include <fcntl.h>
54 #if !defined(_WIN32) /*[*/
55 # include <netdb.h>
56 #endif /*]*/
57 #include <stdint.h>
58 #include "tn3270e.h"
59 #include "3270ds.h"
60
61 #include "appres.h"
62
63 #include "actions.h"
64 #include "b3270proto.h"
65 #include "b8.h"
66 #include "ctlrc.h"
67 #include "host.h"
68 #include "indent_s.h"
69 #include "kybd.h"
70 #include "lazya.h"
71 #include "linemode.h"
72 #include "names.h"
73 #include "nvt.h"
74 #include "popups.h"
75 #include "proxy.h"
76 #include "resolver.h"
77 #include "sio.h"
78 #include "sioc.h"
79 #include "split_host.h"
80 #include "stats.h"
81 #include "status.h"
82 #include "task.h"
83 #include "telnet.h"
84 #include "telnet_core.h"
85 #include "telnet_gui.h"
86 #include "telnet_private.h"
87 #include "telnet_sio.h"
88 #include "tls_passwd_gui.h"
89 #include "trace.h"
90 #include "unicodec.h"
91 #include "utils.h"
92 #include "w3misc.h"
93 #include "xio.h"
94
95 #if !defined(TELOPT_NAWS) /*[*/
96 # define TELOPT_NAWS 31
97 #endif /*]*/
98
99 #if !defined(TELOPT_STARTTLS) /*[*/
100 # define TELOPT_STARTTLS 46
101 #endif /*]*/
102 #define TLS_FOLLOWS 1
103
104 #define BUFSZ 32768
105 #define TRACELINE 72
106
107 #define N_OPTS 256
108
109 /* Globals */
110 char *hostname = NULL;
111 time_t ns_time;
112 int ns_brcvd;
113 int ns_rrcvd;
114 int ns_bsent;
115 int ns_rsent;
116 unsigned char *obuf; /* 3270 output buffer */
117 unsigned char *obptr = (unsigned char *) NULL;
118 bool linemode = true;
119 #if defined(LOCAL_PROCESS) /*[*/
120 bool local_process = false;
121 #endif /*]*/
122 char *termtype;
123 struct timeval net_last_recv_ts;
124
125 const char *telquals[3] = { "IS", "SEND", "INFO" };
126
127 /* Statics */
128 static socket_t sock = INVALID_SOCKET; /* active socket */
129 #if defined(_WIN32) /*[*/
130 static HANDLE sock_handle = INVALID_HANDLE_VALUE;
131 #endif /*]*/
132 static unsigned char myopts[N_OPTS], hisopts[N_OPTS];
133 /* telnet option flags */
134 static bool did_ne_send;
135 static bool deferred_will_ttype;
136 static unsigned char *ibuf = (unsigned char *) NULL;
137 /* 3270 input buffer */
138 static unsigned char *ibptr;
139 static int ibuf_size = 0; /* size of ibuf */
140 static unsigned char *obuf_base = NULL;
141 static int obuf_size = 0;
142 static unsigned char *netrbuf = NULL;
143 /* network input buffer */
144 static unsigned char *sbbuf = NULL;
145 /* telnet sub-option buffer */
146 static unsigned char *sbptr;
147 static unsigned char telnet_state;
148 static int syncing;
149 #if !defined(_WIN32) /*[*/
150 static ioid_t output_id = NULL_IOID;
151 #endif /*]*/
152 static ioid_t connect_timeout_id = NULL_IOID; /* explicit Connect timeout */
153 static ioid_t nop_timeout_id = NULL_IOID;
154 static char ttype_tmpval[13];
155
156 static unsigned short e_xmit_seq; /* transmit sequence number */
157 static int response_required;
158
159 static size_t nvt_data = 0;
160 static int tn3270e_negotiated = 0;
161 static enum { E_UNBOUND, E_3270, E_NVT, E_SSCP } tn3270e_submode = E_UNBOUND;
162 static int tn3270e_bound = 0;
163 static unsigned char *bind_image = NULL;
164 static size_t bind_image_len = 0;
165 static char *plu_name = NULL;
166 static int maxru_sec = 0;
167 static int maxru_pri = 0;
168 static int bind_rd = 0;
169 static int bind_cd = 0;
170 static int bind_ra = 0;
171 static int bind_ca = 0;
172 #define BIND_DIMS_PRESENT 0x1 /* BIND included screen dimensions */
173 #define BIND_DIMS_ALT 0x2 /* BIND included alternate size */
174 #define BIND_DIMS_VALID 0x4 /* BIND screen sizes were valid */
175 static unsigned bind_state = 0;
176 static char **lus = NULL;
177 static char **curr_lu = NULL;
178 static char *try_lu = NULL;
179
180 static proxytype_t proxy_type = PT_NONE;
181 static bool proxy_pending = false;
182 static char *proxy_user = NULL;
183 static char *proxy_host = NULL;
184 static char *proxy_portname = NULL;
185 static unsigned short proxy_port = 0;
186
187 static b8_t e_funcs; /* negotiated TN3270E functions */
188
189 static bool secure_connection;
190 static char *net_accept;
191
192 static enum cstate starttls_pending = NOT_CONNECTED;
193
194 static bool telnet_fsm(unsigned char c);
195 static void net_rawout(unsigned const char *buf, size_t len);
196 static void check_in3270(void);
197 static void store3270in(unsigned char c);
198 static void check_linemode(bool init);
199 static int non_blocking(bool on);
200 static void net_connected(void);
201 static void connection_complete(void);
202 static int tn3270e_negotiate(void);
203 static int process_eor(void);
204 static const char *tn3270e_function_names(const unsigned char *, int);
205 static void tn3270e_subneg_send(unsigned char, b8_t *);
206 static void tn3270e_fdecode(const unsigned char *, int, b8_t *);
207 static void tn3270e_ack(void);
208 static void tn3270e_nak(enum pds);
209 static void net_starttls_continue(void);
210
211 static const char *nnn(int c);
212
213 static void net_hexnvt_out_framed(unsigned char *buf, int len, bool framed);
214
215 /* telnet states */
216 #define TNS_DATA 0 /* receiving data */
217 #define TNS_IAC 1 /* got an IAC */
218 #define TNS_WILL 2 /* got an IAC WILL */
219 #define TNS_WONT 3 /* got an IAC WONT */
220 #define TNS_DO 4 /* got an IAC DO */
221 #define TNS_DONT 5 /* got an IAC DONT */
222 #define TNS_SB 6 /* got an IAC SB */
223 #define TNS_SB_IAC 7 /* got an IAC after an IAC SB */
224
225 /* telnet predefined messages */
226 static unsigned char do_opt[] = {
227 IAC, DO, '_' };
228 static unsigned char dont_opt[] = {
229 IAC, DONT, '_' };
230 static unsigned char will_opt[] = {
231 IAC, WILL, '_' };
232 static unsigned char wont_opt[] = {
233 IAC, WONT, '_' };
234 static unsigned char functions_req[] = {
235 IAC, SB, TELOPT_TN3270E, TN3270E_OP_FUNCTIONS };
236
237 static const char *reason_code[8] = { "CONN-PARTNER", "DEVICE-IN-USE",
238 "INV-ASSOCIATE", "INV-NAME", "INV-DEVICE-TYPE", "TYPE-NAME-ERROR",
239 "UNKNOWN-ERROR", "UNSUPPORTED-REQ" };
240 # define rsn(n) (((n) <= TN3270E_REASON_UNSUPPORTED_REQ)? \
241 reason_code[(n)]: "??")
242 static const char *function_name[5] = { "BIND-IMAGE", "DATA-STREAM-CTL",
243 "RESPONSES", "SCS-CTL-CODES", "SYSREQ" };
244 # define fnn(n) (((n) <= TN3270E_FUNC_SYSREQ)? \
245 function_name[(n)]: "??")
246 static const char *data_type[9] = { "3270-DATA", "SCS-DATA", "RESPONSE",
247 "BIND-IMAGE", "UNBIND", "NVT-DATA", "REQUEST", "SSCP-LU-DATA",
248 "PRINT-EOJ" };
249 # define e_dt(n) (((n) <= TN3270E_DT_PRINT_EOJ)? \
250 data_type[(n)]: "??")
251 static const char *req_flag[1] = { " ERR-COND-CLEARED" };
252 # define e_rq(fn, n) (((fn) == TN3270E_DT_REQUEST)? \
253 (((n) <= TN3270E_RQF_ERR_COND_CLEARED)? \
254 req_flag[(n)]: " ??"): "")
255 static const char *hrsp_flag[3] = { "NO-RESPONSE", "ERROR-RESPONSE",
256 "ALWAYS-RESPONSE" };
257 # define e_hrsp(n) (((n) <= TN3270E_RSF_ALWAYS_RESPONSE)? \
258 hrsp_flag[(n)]: "??")
259 static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
260 # define e_trsp(n) (((n) <= TN3270E_RSF_NEGATIVE_RESPONSE)? \
261 trsp_flag[(n)]: "??")
262 # define e_rsp(fn, n) (((fn) == TN3270E_DT_RESPONSE)? e_trsp(n): e_hrsp(n))
263 const char *state_name[NUM_CSTATE] = {
264 CstateNotConnected,
265 CstateReconnecting,
266 CstateTlsPasswordPending,
267 CstateResolving,
268 CstateTcpPending,
269 CstateTlsPending,
270 CstateProxyPending,
271 CstateTelnetPending,
272 CstateConnectedNvt,
273 CstateConnectedNvtCharmode,
274 CstateConnected3270,
275 CstateConnectedUnbound,
276 CstateConnectedEnvt,
277 CstateConnectedSscp,
278 CstateConnectedTn3270e
279 };
280
281 #if !defined(_WIN32) /*[*/
282 # define XMIT_ROWS ((appres.c3270.altscreen)? MODEL_2_ROWS: maxROWS)
283 # define XMIT_COLS ((appres.c3270.altscreen)? MODEL_2_COLS: maxCOLS)
284 #else /*][*/
285 # define XMIT_ROWS maxROWS
286 # define XMIT_COLS maxCOLS
287 #endif /*]*/
288
289 sio_t sio = NULL;
290
291 static void continue_tls(unsigned char *sbbuf, int len);
292 static bool refused_tls = false;
293 static bool nested_tls = false;
294 static bool any_host_data = false;
295 static bool need_tls_follows = false;
296
297 static bool net_connect_pending;
298
299 #if !defined(_WIN32) /*[*/
300 static void output_possible(iosrc_t fd, ioid_t id);
301 #endif /*]*/
302
303 #if defined(_WIN32) /*[*/
304 # define socket_errno() WSAGetLastError()
305 # define socket_strerror(n) win32_strerror(n)
306 # define SE_EWOULDBLOCK WSAEWOULDBLOCK
307 # define SE_ECONNRESET WSAECONNRESET
308 # define SE_EINTR WSAEINTR
309 # define SE_EAGAIN WSAEINPROGRESS
310 # define SE_EPIPE WSAECONNABORTED
311 # define SE_EINPROGRESS WSAEINPROGRESS
312 # define SOCK_IOCTL(s, f, v) ioctlsocket(s, f, (DWORD *)v)
313 # define IOCTL_T u_long
314 #else /*][*/
315 # define socket_errno() errno
316 # define socket_strerror(n) strerror(n)
317 # define SE_EWOULDBLOCK EWOULDBLOCK
318 # define SE_ECONNRESET ECONNRESET
319 # define SE_EINTR EINTR
320 # define SE_EAGAIN EAGAIN
321 # define SE_EPIPE EPIPE
322 # if defined(EINPROGRESS) /*[*/
323 # define SE_EINPROGRESS EINPROGRESS
324 # endif /*]*/
325 # define SOCK_IOCTL ioctl
326 # define IOCTL_T int
327 #endif /*]*/
328
329 #if defined(SE_EINPROGRESS) /*[*/
330 # define IS_EINPROGRESS(e) ((e) == SE_EINPROGRESS)
331 #else /*][*/
332 # define IS_EINPROGRESS(e) false
333 #endif /*]*/
334
335 typedef union {
336 struct sockaddr sa;
337 struct sockaddr_in sin;
338 #if defined(X3270_IPV6) /*[*/
339 struct sockaddr_in6 sin6;
340 #endif /*]*/
341 } sockaddr_46_t;
342
343 #define NUM_HA 4
344 static sockaddr_46_t haddr[NUM_HA];
345 static socklen_t ha_len[NUM_HA] = {
346 sizeof(haddr[0]), sizeof(haddr[0]), sizeof(haddr[0]), sizeof(haddr[0])
347 };
348 static int num_ha = 0;
349 static int ha_ix = 0;
350 static int resolver_pipe[2] = { -1, -1 };
351 static int resolver_slot = -1;
352 static iosrc_t resolver_event = INVALID_IOSRC;
353
354 #if defined(_WIN32) /*[*/
355 void
popup_a_sockerr(const char * fmt,...)356 popup_a_sockerr(const char *fmt, ...)
357 {
358 va_list args;
359 char *buffer;
360
361 va_start(args, fmt);
362 buffer = vlazyaf(fmt, args);
363 va_end(args);
364 connect_error("%s: %s", buffer, win32_strerror(socket_errno()));
365 }
366 #else /*][*/
367 void
popup_a_sockerr(const char * fmt,...)368 popup_a_sockerr(const char *fmt, ...)
369 {
370 va_list args;
371 char *buffer;
372
373 va_start(args, fmt);
374 buffer = vlazyaf(fmt, args);
375 va_end(args);
376 connect_errno(errno, "%s", buffer);
377 }
378 #endif /*]*/
379
380 /* The host connection timed out. */
381 static void
connect_timed_out(ioid_t id _is_unused)382 connect_timed_out(ioid_t id _is_unused)
383 {
384 connect_error("Host connection timed out");
385 connect_timeout_id = NULL_IOID;
386 host_disconnect(true);
387 }
388
389 /* Connect to one of the addresses in haddr[]. */
390 static iosrc_t
connect_to(int ix,bool noisy,bool * pending)391 connect_to(int ix, bool noisy, bool *pending)
392 {
393 int on = 1;
394 char hn[256];
395 char pn[256];
396 char *errmsg;
397 #if defined(OMTU) /*[*/
398 int mtu = OMTU;
399 #endif /*]*/
400 # define close_fail { SOCK_CLOSE(sock); \
401 sock = INVALID_SOCKET; \
402 return INVALID_IOSRC; \
403 }
404
405 /* create the socket */
406 if ((sock = socket(haddr[ix].sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) ==
407 INVALID_SOCKET) {
408 popup_a_sockerr("socket");
409 return INVALID_IOSRC;
410 }
411
412 /* set options for inline out-of-band data and keepalives */
413 if (setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
414 sizeof(on)) < 0) {
415 popup_a_sockerr("setsockopt(SO_OOBINLINE)");
416 close_fail;
417 }
418 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
419 sizeof(on)) < 0) {
420 popup_a_sockerr("setsockopt(SO_KEEPALIVE)");
421 close_fail;
422 }
423 #if defined(OMTU) /*[*/
424 if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,
425 sizeof(mtu)) < 0) {
426 popup_a_sockerr("setsockopt(SO_SNDBUF)");
427 close_fail;
428 }
429 #endif /*]*/
430
431 /* set the socket to be non-delaying */
432 if (non_blocking(true) < 0) {
433 close_fail;
434 }
435
436 #if !defined(_WIN32) /*[*/
437 /* don't share the socket with our children */
438 fcntl(sock, F_SETFD, 1);
439 #endif /*]*/
440
441 /* Init TLS. */
442 if (HOST_FLAG(TLS_HOST)) {
443 if (!sio_supported()) {
444 popup_an_error("TLS not supported\n");
445 close_fail;
446 }
447 }
448
449 if (numeric_host_and_port(&haddr[ix].sa, ha_len[ix], hn, sizeof(hn), pn,
450 sizeof(pn), &errmsg)) {
451 vtrace("Trying %s, port %s...\n", hn, pn);
452 telnet_gui_connecting(hn, pn);
453 }
454
455 /* Set an explicit timeout, if configured. */
456 if (appres.connect_timeout) {
457 connect_timeout_id = AddTimeOut(appres.connect_timeout * 1000,
458 connect_timed_out);
459 }
460
461 /* connect */
462 if (connect(sock, &haddr[ix].sa, ha_len[ix]) == -1) {
463 if (socket_errno() == SE_EWOULDBLOCK ||
464 IS_EINPROGRESS(socket_errno())) {
465 vtrace("TCP connection pending.\n");
466 *pending = true;
467 #if !defined(_WIN32) /*[*/
468 output_id = AddOutput(sock, output_possible);
469 #endif /*]*/
470 } else {
471 if (noisy) {
472 popup_a_sockerr(AnConnect "() to %s%s, port %d",
473 (proxy_type != PT_NONE)? "proxy ": "",
474 (proxy_type != PT_NONE)? proxy_host : hostname,
475 (proxy_type != PT_NONE)? proxy_port : current_port);
476 }
477 close_fail;
478 }
479 } else {
480 net_connected();
481
482 /* net_connected() can cause the connection to fail. */
483 if (sock == INVALID_SOCKET) {
484 close_fail;
485 }
486 }
487
488 /* all done */
489 #if defined(_WIN32) /*[*/
490 sock_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
491 if (sock_handle == NULL) {
492 fprintf(stderr, "Cannot create socket handle: %s\n",
493 win32_strerror(GetLastError()));
494 x3270_exit(1);
495 }
496 if (WSAEventSelect(sock, sock_handle, FD_READ | FD_CONNECT | FD_CLOSE)
497 != 0) {
498 fprintf(stderr, "WSAEventSelect failed: %s\n",
499 win32_strerror(GetLastError()));
500 x3270_exit(1);
501 }
502
503 return sock_handle;
504 #else /*][*/
505 return sock;
506 #endif /*]*/
507 }
508
509 /* Complete a connection, now that the hostname has been resolved. */
510 static net_connect_t
finish_connect(iosrc_t * iosrc)511 finish_connect(iosrc_t *iosrc)
512 {
513 iosrc_t s;
514
515 /* Set up the TLS context, whether this is an TLS host or not. */
516 if (sio_supported()) {
517 bool pending = false;
518
519 sio = sio_init_wrapper(NULL, HOST_FLAG(NO_VERIFY_CERT_HOST),
520 net_accept, &pending);
521 if (sio == NULL) {
522 if (pending) {
523 net_connect_pending = true;
524 return NC_TLS_PASS;
525 }
526 net_disconnect(false);
527 return NC_FAILED;
528 }
529 }
530
531 /* Try each of the haddrs. */
532 ha_ix = 0;
533 while (ha_ix < num_ha) {
534 bool pending = false;
535
536 if ((s = connect_to(ha_ix, (ha_ix == num_ha - 1),
537 &pending)) != INVALID_IOSRC) {
538 *iosrc = s;
539 return pending? NC_CONNECT_PENDING: NC_CONNECTED;
540 }
541 ha_ix++;
542 }
543
544 /* Ran out. */
545 return NC_FAILED;
546 }
547
548 /* There is data on the resolver pipe. */
549 static void
resolve_done(iosrc_t fd,ioid_t id)550 resolve_done(iosrc_t fd, ioid_t id)
551 {
552 int nr;
553 char slot_byte;
554 int slot;
555 int rv;
556 char *errmsg;
557 iosrc_t iosrc = INVALID_IOSRC;
558 net_connect_t nc;
559
560 /* Read the data, which is the slot number. */
561 nr = read(resolver_pipe[0], &slot_byte, 1);
562 if (nr < 0) {
563 popup_an_errno(errno, "Resolver pipe");
564 return;
565 }
566 if (nr == 0) {
567 popup_an_error("Resolver pipe EOF");
568 }
569
570 /* Might be a canceled request. */
571 slot = (int)slot_byte;
572 if (slot != resolver_slot) {
573 vtrace("Cleaning up canceled resolver slot %d\n", slot);
574 cleanup_host_and_port(slot);
575 return;
576 }
577
578 rv = collect_host_and_port(slot, &haddr[0].sa, sizeof(haddr[0]), ha_len,
579 ¤t_port, &errmsg, NUM_HA, &num_ha);
580 if (RHP_IS_ERROR(rv)) {
581 connect_error("%s", errmsg);
582 return;
583 }
584 vtrace("Resolution complete, %d address%s\n", num_ha,
585 (num_ha == 1)? "": "es");
586
587 /* Proceed with the connection. */
588 nc = finish_connect(&iosrc);
589 if (nc == NC_FAILED) {
590 host_disconnect(true);
591 } else {
592 host_continue_connect(iosrc, nc);
593 }
594 }
595
596 /*
597 * net_connect
598 * Establish a telnet socket to the given host passed as an argument.
599 * Called only once and is responsible for setting up the telnet
600 * variables. Returns the file descriptor of the connected socket.
601 */
602 net_connect_t
net_connect(const char * host,char * portname,char * accept,bool ls,iosrc_t * iosrc)603 net_connect(const char *host, char *portname, char *accept, bool ls,
604 iosrc_t *iosrc)
605 {
606 struct servent *sp;
607 struct hostent *hp;
608 char passthru_haddr[8];
609 int passthru_len = 0;
610 unsigned short passthru_port = 0;
611 char *errmsg;
612
613 if (sizeof(state_name)/sizeof(state_name[0]) != NUM_CSTATE) {
614 Error("telnet cstate_name has the wrong number of elements");
615 }
616
617 *iosrc = INVALID_IOSRC;
618
619 if (netrbuf == NULL) {
620 netrbuf = (unsigned char *)Malloc(BUFSZ);
621 }
622
623 linemode_init();
624 ns_brcvd = 0;
625 ns_rrcvd = 0;
626 ns_bsent = 0;
627 ns_rsent = 0;
628
629 environ_init();
630
631 environ_init();
632
633 Replace(hostname, NewString(host));
634 net_accept = accept;
635
636 starttls_pending = NOT_CONNECTED;
637 st_changed(ST_SECURE, false);
638
639 /* set up temporary termtype */
640 net_set_default_termtype();
641
642 /* get the passthru host and port number */
643 if (HOST_FLAG(PASSTHRU_HOST)) {
644 const char *hn;
645
646 hn = getenv("INTERNET_HOST");
647 if (hn == NULL) {
648 hn = "internet-gateway";
649 }
650
651 hp = gethostbyname(hn);
652 if (hp == (struct hostent *) 0) {
653 connect_error("Unknown passthru host: %s", hn);
654 return NC_FAILED;
655 }
656 memmove(passthru_haddr, hp->h_addr, hp->h_length);
657 passthru_len = hp->h_length;
658
659 sp = getservbyname("telnet-passthru","tcp");
660 if (sp != NULL) {
661 passthru_port = sp->s_port;
662 } else {
663 passthru_port = htons(3514);
664 }
665 } else if (appres.proxy != NULL) {
666 proxytype_t pt;
667 unsigned long lport;
668 char *ptr;
669 struct servent *sp;
670
671 pt = proxy_setup(appres.proxy, &proxy_user, &proxy_host,
672 &proxy_portname);
673 if (pt == PT_ERROR) {
674 return NC_FAILED;
675 }
676
677 lport = strtoul(portname, &ptr, 0);
678 if (ptr == portname || *ptr != '\0' || lport == 0L ||
679 lport & ~0xffff) {
680 if (!(sp = getservbyname(portname, "tcp"))) {
681 connect_error("Unknown port number or service: %s",
682 portname);
683 return NC_FAILED;
684 }
685 current_port = ntohs(sp->s_port);
686 } else {
687 current_port = (unsigned short)lport;
688 }
689 proxy_type = pt;
690 proxy_pending = true;
691 }
692
693 /* fill in the socket address of the given host */
694 memset((char *) &haddr, 0, sizeof(haddr));
695 if (HOST_FLAG(PASSTHRU_HOST)) {
696 /*
697 * XXX: We don't try multiple addresses for the passthru
698 * host.
699 */
700 haddr[0].sin.sin_family = AF_INET;
701 memmove(&haddr[0].sin.sin_addr, passthru_haddr, passthru_len);
702 haddr[0].sin.sin_port = passthru_port;
703 ha_len[0] = sizeof(struct sockaddr_in);
704 num_ha = 1;
705 ha_ix = 0;
706 } else if (proxy_pending) {
707 /*
708 * XXX: We don't try multiple addresses for a proxy
709 * host.
710 */
711 rhp_t rv;
712 int nr;
713
714 rv = resolve_host_and_port(proxy_host, proxy_portname, &proxy_port,
715 &haddr[0].sa, sizeof(haddr[0]), &ha_len[0], &errmsg, 1, &nr);
716 if (RHP_IS_ERROR(rv)) {
717 connect_error("%s", errmsg);
718 return NC_FAILED;
719 }
720 num_ha = 1;
721 ha_ix = 0;
722 } else {
723 #if defined(LOCAL_PROCESS) /*[*/
724 if (ls) {
725 local_process = true;
726 } else {
727 #endif /*]*/
728 rhp_t rv;
729
730 if (resolver_pipe[0] == -1) {
731 int rv;
732
733 #if !defined(_WIN32) /*[*/
734 rv = pipe(resolver_pipe);
735 #else /*][*/
736 rv = _pipe(resolver_pipe, 512, _O_BINARY);
737 #endif /*]*/
738 if (rv < 0) {
739 connect_error("resolver pipe: %s", strerror(errno));
740 return NC_FAILED;
741 }
742 #if !defined(_WIN32) /*[*/
743 AddInput(resolver_pipe[0], resolve_done);
744 #else /*][*/
745 resolver_event = CreateEvent(NULL, FALSE, FALSE, NULL);
746 AddInput(resolver_event, resolve_done);
747 #endif /*]*/
748 }
749
750 #if defined(LOCAL_PROCESS) /*[*/
751 local_process = false;
752 #endif /*]*/
753 rv = resolve_host_and_port_a(host, portname, ¤t_port,
754 &haddr[0].sa, sizeof(haddr[0]), ha_len, &errmsg, NUM_HA,
755 &num_ha, &resolver_slot, resolver_pipe[1], resolver_event);
756 if (RHP_IS_ERROR(rv)) {
757 connect_error("%s", errmsg);
758 return NC_FAILED;
759 }
760 ha_ix = 0;
761
762 if (rv == RHP_PENDING) {
763 vtrace("Resolver slot is %d\n", resolver_slot);
764 return NC_RESOLVING;
765 }
766 #if defined(LOCAL_PROCESS) /*[*/
767 }
768 #endif /*]*/
769 }
770
771 #if defined(LOCAL_PROCESS) /*[*/
772 if (local_process) {
773 int amaster;
774 struct winsize w;
775
776 w.ws_row = XMIT_ROWS;
777 w.ws_col = XMIT_COLS;
778 w.ws_xpixel = 0;
779 w.ws_ypixel = 0;
780
781 switch (forkpty(&amaster, NULL, NULL, &w)) {
782 case -1: /* failed */
783 connect_errno(errno, "forkpty");
784 close_fail;
785 case 0: /* child */
786 putenv("TERM=xterm");
787 if (strchr(host, ' ') != NULL) {
788 execlp("/bin/sh", "sh", "-c", host, NULL);
789 } else {
790 char *arg1;
791
792 arg1 = strrchr(host, '/');
793 execlp(host, (arg1 == NULL)? host: arg1 + 1, NULL);
794 }
795 perror(host);
796 _exit(1);
797 break;
798 default: /* parent */
799 sock = amaster;
800 fcntl(sock, F_SETFD, 1);
801 connection_complete();
802 host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
803 host_set_flag(NO_TELNET_HOST);
804 break;
805 }
806 *iosrc = sock;
807 return NC_CONNECTED;
808 }
809 #endif /*]*/
810
811 return finish_connect(iosrc);
812 }
813 #undef close_fail
814
815 /* Set up the LU list. */
816 static void
setup_lus(void)817 setup_lus(void)
818 {
819 char *lu;
820 char *comma;
821 int n_lus = 1;
822 int i;
823
824 connected_lu = NULL;
825 connected_type = NULL;
826
827 if (!luname[0]) {
828 Replace(lus, NULL);
829 curr_lu = NULL;
830 try_lu = NULL;
831 return;
832 }
833
834 /*
835 * Count the commas in the LU name. That plus one is the
836 * number of LUs to try.
837 */
838 lu = luname;
839 while ((comma = strchr(lu, ',')) != NULL) {
840 n_lus++;
841 lu++;
842 }
843
844 /*
845 * Allocate enough memory to construct an argv[] array for
846 * the LUs.
847 */
848 Replace(lus,
849 (char **)Malloc((n_lus+1) * sizeof(char *) + strlen(luname) + 1));
850
851 /* Copy each LU into the array. */
852 lu = (char *)(lus + n_lus + 1);
853 strcpy(lu, luname);
854 i = 0;
855 do {
856 lus[i++] = lu;
857 comma = strchr(lu, ',');
858 if (comma != NULL) {
859 *comma = '\0';
860 lu = comma + 1;
861 }
862 } while (comma != NULL);
863 lus[i] = NULL;
864 curr_lu = lus;
865 try_lu = *curr_lu;
866 }
867
868 /* Send a periodic TELNET NOP. */
869 static void
send_nop(ioid_t id _is_unused)870 send_nop(ioid_t id _is_unused)
871 {
872 static unsigned char nop[] = { IAC, NOP };
873
874 vtrace("SENT NOP\n");
875 net_rawout(nop, sizeof(nop));
876 if (cstate != NOT_CONNECTED) {
877 nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
878 } else {
879 nop_timeout_id = NULL_IOID;
880 }
881 }
882
883 static void
net_connected_complete(void)884 net_connected_complete(void)
885 {
886 /* Done with TLS or proxy. */
887 if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
888 host_in3270(CONNECTED_NVT);
889 } else {
890 change_cstate(TELNET_PENDING, "net_connected_complete");
891 }
892 st_changed(ST_SECURE, false);
893
894 /* set up telnet options */
895 memset((char *)myopts, 0, sizeof(myopts));
896 memset((char *)hisopts, 0, sizeof(hisopts));
897 did_ne_send = false;
898 deferred_will_ttype = false;
899 b8_zero(&e_funcs);
900 b8_set_bit(&e_funcs, TN3270E_FUNC_BIND_IMAGE);
901 b8_set_bit(&e_funcs, TN3270E_FUNC_RESPONSES);
902 b8_set_bit(&e_funcs, TN3270E_FUNC_SYSREQ);
903 e_xmit_seq = 0;
904 response_required = TN3270E_RSF_NO_RESPONSE;
905 need_tls_follows = false;
906 telnet_state = TNS_DATA;
907 ibptr = ibuf;
908
909 /* clear statistics and flags */
910 time(&ns_time);
911 ns_brcvd = 0;
912 ns_rrcvd = 0;
913 ns_bsent = 0;
914 ns_rsent = 0;
915 syncing = 0;
916 tn3270e_negotiated = 0;
917 tn3270e_submode = E_UNBOUND;
918 tn3270e_bound = 0;
919
920 setup_lus();
921
922 check_linemode(true);
923
924 /* write out the passthru hostname and port nubmer */
925 if (HOST_FLAG(PASSTHRU_HOST)) {
926 char *buf;
927
928 buf = xs_buffer("%s %d\r\n", hostname, current_port);
929 send(sock, buf, (int)strlen(buf), 0);
930 Free(buf);
931 }
932
933 /* set up NOP transmission */
934 if (appres.nop_seconds != 0) {
935 nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
936 }
937 }
938
939 static void
net_connected(void)940 net_connected(void)
941 {
942 bool data = false;
943
944 /* Cancel the timeout. */
945 if (connect_timeout_id != NULL_IOID) {
946 RemoveTimeOut(connect_timeout_id);
947 connect_timeout_id = NULL_IOID;
948 }
949
950 if (cstate != TLS_PENDING) {
951 vtrace("Connected to %s, port %u.\n", hostname, current_port);
952 }
953
954 if (proxy_pending) {
955 proxy_negotiate_ret_t ret;
956
957 /* Don't do this again. */
958 proxy_pending = false;
959
960 /* Negotiate with the proxy. */
961 vtrace("Connected to proxy server %s, port %u.\n", proxy_host,
962 proxy_port);
963
964 change_cstate(PROXY_PENDING, "net_connected");
965
966 ret = proxy_negotiate(sock, proxy_user, hostname, current_port, false);
967 if (ret == PX_FAILURE) {
968 host_disconnect(true);
969 return;
970 }
971 if (ret == PX_WANTMORE) {
972 vtrace("Proxy needs more data\n");
973 return;
974 }
975 }
976
977 /* Set up TLS. */
978 if (HOST_FLAG(TLS_HOST) && sio != NULL && !secure_connection) {
979 sio_negotiate_ret_t rv;
980 char *session, *cert;
981
982 change_cstate(TLS_PENDING, "net_connected");
983
984 rv = sio_negotiate(sio, sock, hostname, &data);
985 if (rv == SIG_FAILURE) {
986 /* No need to trace the error, it was already displayed. */
987 connect_error("%s", sio_last_error());
988 host_disconnect(true);
989 return;
990 }
991 if (rv == SIG_WANTMORE) {
992 vtrace("Need more TLS data\n");
993 return;
994 }
995
996 secure_connection = true;
997 session = indent_s(sio_session_info(sio));
998 cert = indent_s(sio_server_cert_info(sio));
999 vtrace("Connection is now secure.\n"
1000 "Provider: %s\n"
1001 "Session:\n%s\nServer certificate:\n%s\n",
1002 sio_provider(), session, cert);
1003 Free(session);
1004 Free(cert);
1005 st_changed(ST_SECURE, true);
1006
1007 /* Tell everyone else again. */
1008 host_connected();
1009 }
1010
1011 net_connected_complete();
1012
1013 if (data) {
1014 vtrace("Reading extra data after negotiation\n");
1015 net_input(INVALID_IOSRC, NULL_IOID);
1016 }
1017 }
1018
1019 /*
1020 * net_password_continue
1021 * Called by the password GUI when a password has been entered.
1022 */
1023 void
net_password_continue(const char * password)1024 net_password_continue(const char *password)
1025 {
1026 bool pending;
1027 iosrc_t s;
1028
1029 if (!net_connect_pending) {
1030 /* Connection is gone. */
1031 return;
1032 }
1033 net_connect_pending = false;
1034
1035 /* Try initializing sio again, with a new password. */
1036 if ((sio = sio_init_wrapper(password, HOST_FLAG(NO_VERIFY_CERT_HOST),
1037 net_accept, &pending)) == NULL) {
1038 if (pending) {
1039 /* Still pending, try again. */
1040 net_connect_pending = true;
1041 }
1042 return;
1043 }
1044
1045 /* Try connecting. */
1046 while (ha_ix < num_ha) {
1047 s = connect_to(ha_ix, (ha_ix == num_ha - 1), &pending);
1048 if (s != INVALID_IOSRC) {
1049 host_newfd(s);
1050 host_new_connection(pending);
1051 break;
1052 }
1053 ha_ix++;
1054 }
1055 }
1056
1057 /*
1058 * remove_output
1059 * Cancel the callback for output available.
1060 */
1061 static void
remove_output(void)1062 remove_output(void)
1063 {
1064 #if !defined(_WIN32) /*[*/
1065 if (output_id != NULL_IOID) {
1066 RemoveInput(output_id);
1067 output_id = NULL_IOID;
1068 }
1069 #endif /*]*/
1070 }
1071
1072 /*
1073 * connection_complete
1074 * The connection appears to be complete (output is possible or input
1075 * appeared ready but recv() returned EWOULDBLOCK). Complete the
1076 * connection-completion processing.
1077 */
1078 static void
connection_complete(void)1079 connection_complete(void)
1080 {
1081 host_connected();
1082 net_connected();
1083 remove_output();
1084 }
1085
1086 #if !defined(_WIN32) /*[*/
1087 /*
1088 * output_possible
1089 * Output is possible on the socket. Used only when a connection is
1090 * pending, to determine that the connection is complete.
1091 */
1092 static void
output_possible(iosrc_t fd _is_unused,ioid_t id _is_unused)1093 output_possible(iosrc_t fd _is_unused, ioid_t id _is_unused)
1094 {
1095 #if defined(CONNECT_GETPEERNAME) /*[*/
1096 sockaddr_46_t sa;
1097 socklen_t len = sizeof(sa);
1098 # define COMPLETE_CONNECT(s) getpeername(s, &sa.sa, &len)
1099 # else /*][*/
1100 # define COMPLETE_CONNECT(s) connect(s, &haddr[ha_ix].sa, sizeof(haddr[0]))
1101 #endif /*]*/
1102
1103 vtrace("Output possible\n");
1104
1105 /*
1106 * Try a connect() again to see if the connection completed sucessfully.
1107 * On some systems, such as Linux, this is harmless and succeeds.
1108 * On others, such as MacOS, this is mostly harmless and fails
1109 * with EISCONN.
1110 *
1111 * On Solaris, we do a getpeername() instead of a connect(). The second
1112 * connect() would fail with EINVAL there.
1113 */
1114 if (COMPLETE_CONNECT(sock) < 0) {
1115 if (errno != EISCONN) {
1116 vtrace("RCVD socket error %d (%s)\n", socket_errno(),
1117 strerror(errno));
1118 popup_a_sockerr("Connection%s failed",
1119 proxy_pending? " to proxy server": "");
1120 host_disconnect(true);
1121 return;
1122 }
1123 }
1124
1125 if (cstate == TCP_PENDING) {
1126 connection_complete();
1127 }
1128 remove_output();
1129 }
1130 #endif /*]*/
1131
1132
1133 /*
1134 * net_disconnect
1135 * Shut down the socket.
1136 */
1137 void
net_disconnect(bool including_tls)1138 net_disconnect(bool including_tls)
1139 {
1140 if (including_tls && sio != NULL) {
1141 sio_close(sio);
1142 sio = NULL;
1143 secure_connection = false;
1144 st_changed(ST_SECURE, false);
1145 }
1146 if (CONNECTED) {
1147 shutdown(sock, 2);
1148 }
1149 SOCK_CLOSE(sock);
1150 sock = INVALID_SOCKET;
1151 #if defined(_WIN32) /*[*/
1152 CloseHandle(sock_handle);
1153 sock_handle = INVALID_HANDLE_VALUE;
1154 #endif /*]*/
1155 vtrace("SENT disconnect\n");
1156
1157 /* Cancel proxy. */
1158 if (proxy_type != PT_NONE) {
1159 proxy_close();
1160 proxy_type = PT_NONE;
1161 proxy_pending = false;
1162 }
1163
1164 /* Cancel the timeout. */
1165 if (connect_timeout_id != NULL_IOID) {
1166 RemoveTimeOut(connect_timeout_id);
1167 connect_timeout_id = NULL_IOID;
1168 }
1169
1170 /* Cancel NOPs. */
1171 if (nop_timeout_id != NULL_IOID) {
1172 RemoveTimeOut(nop_timeout_id);
1173 nop_timeout_id = NULL_IOID;
1174 }
1175
1176 /* We're not connected to an LU any more. */
1177 status_lu(NULL);
1178
1179 /* We have no more interest in output buffer space. */
1180 remove_output();
1181
1182 /* If we refused TLS and never entered 3270 mode, say so. */
1183 if (refused_tls && !any_host_data) {
1184 if (!appres.tls.starttls) {
1185 connect_error("Connection failed:\n"
1186 "Host requested STARTTLS but STARTTLS disabled");
1187 } else if (nested_tls) {
1188 connect_error("Connection failed:\n"
1189 "Host requested nested STARTTLS");
1190 } else {
1191 connect_error("Connection failed:\n"
1192 "Host requested STARTTLS but TLS not supported");
1193 }
1194 }
1195 refused_tls = false;
1196 nested_tls = false;
1197 any_host_data = false;
1198 starttls_pending = NOT_CONNECTED;
1199
1200 net_connect_pending = false;
1201
1202 change_cstate(NOT_CONNECTED, "net_disconnect");
1203 }
1204
1205 /*
1206 * net_input
1207 * Called by the toolkit whenever there is input available on the
1208 * socket. Reads the data, processes the special telnet commands
1209 * and calls process_ds to process the 3270 data stream.
1210 */
1211 void
net_input(iosrc_t fd _is_unused,ioid_t id _is_unused)1212 net_input(iosrc_t fd _is_unused, ioid_t id _is_unused)
1213 {
1214 register unsigned char *cp;
1215 int nr;
1216 bool ignore_tls = false;
1217
1218 #if defined(_WIN32) /*[*/
1219 WSANETWORKEVENTS events;
1220
1221 /*
1222 * Make the socket non-blocking.
1223 * Note that WSAEventSelect does this automatically (and won't allow
1224 * us to change it back to blocking), except on Wine.
1225 */
1226 if (sock != INVALID_SOCKET && non_blocking(true) < 0) {
1227 host_disconnect(true);
1228 return;
1229 }
1230 #endif /*]*/
1231 if (sock == INVALID_SOCKET) {
1232 return;
1233 }
1234
1235 #if defined(_WIN32) /*[*/
1236 if (WSAEnumNetworkEvents(sock, sock_handle, &events) != 0) {
1237 popup_an_error("WSAEnumNetworkEvents failed: %s",
1238 win32_strerror(WSAGetLastError()));
1239 host_disconnect(true);
1240 return;
1241 }
1242 vtrace("net_input: NetworkEvents 0x%lx%s%s%s\n",
1243 events.lNetworkEvents,
1244 (events.lNetworkEvents & FD_CONNECT) ? " CONNECT": "",
1245 (events.lNetworkEvents & FD_CLOSE) ? " CLOSE": "",
1246 (events.lNetworkEvents & FD_READ) ? " READ": "");
1247 if (cstate == TCP_PENDING) {
1248 if (events.lNetworkEvents & FD_CONNECT) {
1249 if (events.iErrorCode[FD_CONNECT_BIT] != 0) {
1250 connect_error("Connection%s failed: %s",
1251 proxy_pending? " to proxy server": "",
1252 win32_strerror(events.iErrorCode[FD_CONNECT_BIT]));
1253 host_disconnect(true);
1254 return;
1255 } else {
1256 connection_complete();
1257 if (sock == INVALID_SOCKET) {
1258 return;
1259 }
1260 }
1261 } else {
1262 vtrace("Spurious net_input call\n");
1263 return;
1264 }
1265 }
1266 #endif /*]*/
1267
1268 if (cstate == PROXY_PENDING) {
1269 /* More proxy data available. */
1270 proxy_negotiate_ret_t ret = proxy_continue();
1271
1272 if (ret == PX_WANTMORE) {
1273 vtrace("Proxy needs more data\n");
1274 return;
1275 }
1276 if (ret == PX_FAILURE) {
1277 host_disconnect(true);
1278 return;
1279 }
1280 net_connected_complete();
1281 }
1282
1283 if (cstate == TLS_PENDING) {
1284 /* More TLS data available. Process it. */
1285 if (starttls_pending != NOT_CONNECTED) {
1286 net_starttls_continue();
1287 } else {
1288 net_connected();
1289 }
1290 return;
1291 }
1292
1293 if (HOST_FLAG(TLS_HOST) && sio != NULL && !secure_connection) {
1294 /* Set up TLS tunnel after proxy connection. */
1295 net_connected();
1296 if (cstate == NOT_CONNECTED) {
1297 return;
1298 }
1299 }
1300
1301 nvt_data = 0;
1302
1303 vtrace("Reading host socket%s\n", secure_connection? " via TLS": "");
1304
1305 if (secure_connection) {
1306 /*
1307 * OpenSSL does not like getting refused connections
1308 * when it hasn't done any I/O yet. So peek ahead to
1309 * see if it's worth getting it involved at all.
1310 */
1311 if (cstate == TLS_PENDING &&
1312 (nr = recv(sock, (char *) netrbuf, 1, MSG_PEEK)) <= 0) {
1313 ignore_tls = true;
1314 } else {
1315 nr = sio_read(sio, (char *) netrbuf, BUFSZ);
1316 }
1317 } else {
1318 #if defined(LOCAL_PROCESS) /*[*/
1319 if (local_process) {
1320 nr = read(sock, (char *) netrbuf, BUFSZ);
1321 } else
1322 #endif /*]*/
1323 {
1324 nr = recv(sock, (char *) netrbuf, BUFSZ, 0);
1325 }
1326 }
1327 gettimeofday(&net_last_recv_ts, NULL);
1328 vtrace("Host socket read complete nr=%d\n", nr);
1329 if (nr < 0) {
1330 if ((secure_connection && nr == SIO_EWOULDBLOCK) ||
1331 (!secure_connection && socket_errno() == SE_EWOULDBLOCK)) {
1332 vtrace("EWOULDBLOCK\n");
1333 return;
1334 }
1335 if (secure_connection && !ignore_tls) {
1336 connect_error("%s", sio_last_error());
1337 host_disconnect(true);
1338 return;
1339 }
1340 if (cstate == TCP_PENDING && socket_errno() == SE_EAGAIN) {
1341 connection_complete();
1342 return;
1343 }
1344 #if defined(LOCAL_PROCESS) /*[*/
1345 if (errno == EIO && local_process) {
1346 vtrace("RCVD local process disconnect\n");
1347 host_disconnect(false);
1348 return;
1349 }
1350 #endif /*]*/
1351 vtrace("RCVD socket error %d (%s)\n", socket_errno(),
1352 socket_strerror(socket_errno()));
1353 if (cstate == TCP_PENDING) {
1354 if (ha_ix == num_ha - 1) {
1355 popup_a_sockerr(AnConnect "() to %s%s, port %d",
1356 (proxy_type != PT_NONE)? "proxy ": "",
1357 (proxy_type != PT_NONE)? proxy_host : hostname,
1358 (proxy_type != PT_NONE)? proxy_port : current_port);
1359 } else {
1360 bool pending;
1361 iosrc_t s;
1362
1363 net_disconnect(false);
1364 while (++ha_ix < num_ha) {
1365 s = connect_to(ha_ix, (ha_ix == num_ha - 1), &pending);
1366 if (s != INVALID_IOSRC) {
1367 host_newfd(s);
1368 host_new_connection(pending);
1369 return;
1370 }
1371 }
1372 }
1373 } else if (socket_errno() != SE_ECONNRESET) {
1374 popup_a_sockerr("Socket read");
1375 }
1376 host_disconnect(true);
1377 return;
1378 } else if (nr == 0) {
1379 /* Host disconnected. */
1380 vtrace("RCVD disconnect\n");
1381 host_disconnect(false);
1382 return;
1383 }
1384
1385 /* Process the data. */
1386
1387 if (cstate == TCP_PENDING) {
1388 host_connected();
1389 net_connected();
1390 remove_output();
1391 }
1392
1393 trace_netdata('<', netrbuf, nr);
1394
1395 ns_brcvd += nr;
1396 stats_poke();
1397 for (cp = netrbuf; cp < (netrbuf + nr); cp++) {
1398 #if defined(LOCAL_PROCESS) /*[*/
1399 if (local_process) {
1400 /* More to do here, probably. */
1401 if (cstate == TELNET_PENDING) {
1402 host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
1403 hisopts[TELOPT_ECHO] = 1;
1404 check_linemode(false);
1405 kybdlock_clr(KL_AWAITING_FIRST, "telnet_fsm");
1406 status_reset();
1407 ps_process();
1408 }
1409 nvt_process((unsigned int) *cp);
1410 } else {
1411 #endif /*]*/
1412 if (!telnet_fsm(*cp)) {
1413 ctlr_dbcs_postprocess();
1414 host_disconnect(true);
1415 return;
1416 }
1417 #if defined(LOCAL_PROCESS) /*[*/
1418 }
1419 #endif /*]*/
1420 }
1421
1422 if (IN_NVT) {
1423 ctlr_dbcs_postprocess();
1424 }
1425 net_nvt_break();
1426
1427 #if defined(_WIN32) /*[*/
1428 if (events.lNetworkEvents & FD_CLOSE) {
1429 vtrace("RCVD disconnect\n");
1430 host_disconnect(false);
1431 }
1432 #endif /*]*/
1433
1434 /* See if it's time to roll over the trace file. */
1435 trace_rollover_check();
1436 }
1437
1438 /*
1439 * set16
1440 * Put a 16-bit value in a buffer.
1441 * Returns the number of bytes required.
1442 */
1443 static size_t
set16(char * buf,int n)1444 set16(char *buf, int n)
1445 {
1446 char *b0 = buf;
1447
1448 n %= 256 * 256;
1449 if ((n / 256) == IAC) {
1450 *(unsigned char *)buf++ = IAC;
1451 }
1452 *buf++ = (n / 256);
1453 n %= 256;
1454 if (n == IAC) {
1455 *(unsigned char *)buf++ = IAC;
1456 }
1457 *buf++ = n;
1458 return buf - b0;
1459 }
1460
1461 /*
1462 * send_naws
1463 * Send a Telnet window size sub-option negotation.
1464 */
1465 static void
send_naws(void)1466 send_naws(void)
1467 {
1468 char naws_msg[14];
1469 size_t naws_len = 0;
1470
1471 snprintf(naws_msg, sizeof(naws_msg), "%c%c%c", IAC, SB, TELOPT_NAWS);
1472 naws_len += 3;
1473 naws_len += set16(naws_msg + naws_len, XMIT_COLS);
1474 naws_len += set16(naws_msg + naws_len, XMIT_ROWS);
1475 sprintf(naws_msg + naws_len, "%c%c", IAC, SE);
1476 naws_len += 2;
1477 net_rawout((unsigned char *)naws_msg, naws_len);
1478 vtrace("SENT %s NAWS %d %d %s\n", cmd(SB), XMIT_COLS, XMIT_ROWS, cmd(SE));
1479 }
1480
1481
1482 /* Advance 'try_lu' to the next desired LU name. */
1483 static void
next_lu(void)1484 next_lu(void)
1485 {
1486 if (curr_lu != NULL && (try_lu = *++curr_lu) == NULL) {
1487 curr_lu = NULL;
1488 }
1489 }
1490
1491 #if defined(EBCDIC_HOST) /*[*/
1492 /*
1493 * force_ascii
1494 * Force the argument string to ASCII. On ASCII (or ASCII-derived) hosts,
1495 * this is a no-op. On EBCDIC-based hosts, translation is necessary.
1496 */
1497 static const char *
force_ascii(const char * s)1498 force_ascii(const char *s)
1499 {
1500 static char buf[256];
1501 unsigned char c, e;
1502 int i;
1503
1504 i = 0;
1505 while ((c = *s++) && i < sizeof(buf) - 1) {
1506 e = ebc2asc0[c];
1507 if (e) {
1508 buf[i++] = e;
1509 } else {
1510 buf[i++] = 0x3f; /* '?' */
1511 }
1512 }
1513 buf[i] = '\0';
1514 return buf;
1515 }
1516 #else /*][*/
1517 #define force_ascii(s) (s)
1518 #endif /*]*/
1519
1520 #if defined(EBCDIC_HOST) /*[*/
1521 /*
1522 * force_local
1523 * Force the argument string from ASCII to the local character set. On
1524 * ASCII (or ASCII-derived) hosts, this is a no-op. On EBCDIC-based
1525 * hosts, translation is necessary.
1526 *
1527 * Does the translation in-place.
1528 */
1529 void
force_local(char * s)1530 force_local(char *s)
1531 {
1532 unsigned char c, e;
1533
1534 while ((c = *s) != '\0') {
1535 e = asc2ebc0[c];
1536 if (e) {
1537 *s = e;
1538 } else {
1539 *s = '?';
1540 }
1541 s++;
1542 }
1543 }
1544 #else /*][*/
1545 #define force_local(s)
1546 #endif /*]*/
1547
1548 /*
1549 * telnet_fsm
1550 * Telnet finite-state machine.
1551 * Returns true for okay, false for errors.
1552 */
1553 static bool
telnet_fsm(unsigned char c)1554 telnet_fsm(unsigned char c)
1555 {
1556 char *see_chr;
1557 size_t sl;
1558
1559 switch (telnet_state) {
1560 case TNS_DATA: /* normal data processing */
1561 if (!HOST_FLAG(NO_TELNET_HOST) && c == IAC) {
1562 /* got a telnet command */
1563 telnet_state = TNS_IAC;
1564 net_nvt_break();
1565 break;
1566 }
1567 if (cstate == TELNET_PENDING) {
1568 /* now can assume NVT mode */
1569 if (linemode) {
1570 linemode_buf_init();
1571 }
1572 host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
1573 kybdlock_clr(KL_AWAITING_FIRST, "telnet_fsm");
1574 status_reset();
1575 ps_process();
1576 }
1577 if (IN_NVT && !IN_E) {
1578 if (!nvt_data) {
1579 vtrace("<.. ");
1580 nvt_data = 4;
1581 }
1582 see_chr = ctl_see((int) c);
1583 nvt_data += (sl = strlen(see_chr));
1584 if (nvt_data >= TRACELINE) {
1585 vtrace(" ...\n... ");
1586 nvt_data = 4 + sl;
1587 }
1588 vtrace("%s", see_chr);
1589 if (!syncing) {
1590 if (linemode && appres.linemode.onlcr && c == '\n') {
1591 nvt_process((unsigned int) '\r');
1592 }
1593 nvt_process((unsigned int) c);
1594 }
1595 } else {
1596 store3270in(c);
1597 }
1598 break;
1599 case TNS_IAC: /* process a telnet command */
1600 if (c != EOR && c != IAC) {
1601 vtrace("RCVD %s ", cmd(c));
1602 }
1603 switch (c) {
1604 case IAC: /* escaped IAC, insert it */
1605 if (IN_NVT && !IN_E) {
1606 if (!nvt_data) {
1607 vtrace("<.. ");
1608 nvt_data = 4;
1609 }
1610 see_chr = ctl_see((int) c);
1611 nvt_data += (sl = strlen(see_chr));
1612 if (nvt_data >= TRACELINE) {
1613 vtrace(" ...\n ...");
1614 nvt_data = 4 + sl;
1615 }
1616 vtrace("%s", see_chr);
1617 nvt_process((unsigned int) c);
1618 } else {
1619 store3270in(c);
1620 }
1621 telnet_state = TNS_DATA;
1622 break;
1623 case EOR: /* eor, process accumulated input */
1624 if (IN_3270 || (IN_E && tn3270e_negotiated)) {
1625 ns_rrcvd++;
1626 stats_poke();
1627 if (process_eor()) {
1628 return false;
1629 }
1630 } else {
1631 Warning("EOR received when not in 3270 mode, ignored.");
1632 }
1633 vtrace("RCVD EOR\n");
1634 ibptr = ibuf;
1635 telnet_state = TNS_DATA;
1636 break;
1637 case WILL:
1638 telnet_state = TNS_WILL;
1639 break;
1640 case WONT:
1641 telnet_state = TNS_WONT;
1642 break;
1643 case DO:
1644 telnet_state = TNS_DO;
1645 break;
1646 case DONT:
1647 telnet_state = TNS_DONT;
1648 break;
1649 case SB:
1650 telnet_state = TNS_SB;
1651 if (sbbuf == NULL) {
1652 sbbuf = (unsigned char *)Malloc(1024);
1653 }
1654 sbptr = sbbuf;
1655 break;
1656 case DM:
1657 vtrace("\n");
1658 if (syncing) {
1659 syncing = 0;
1660 #if !defined(_WIN32) /*[*/
1661 x_except_on(sock);
1662 #else /*][*/
1663 x_except_on(sock_handle);
1664 #endif /*]*/
1665 }
1666 telnet_state = TNS_DATA;
1667 break;
1668 case GA:
1669 case NOP:
1670 vtrace("\n");
1671 telnet_state = TNS_DATA;
1672 break;
1673 default:
1674 vtrace("???\n");
1675 telnet_state = TNS_DATA;
1676 break;
1677 }
1678 break;
1679 case TNS_WILL: /* telnet WILL DO OPTION command */
1680 vtrace("%s\n", opt(c));
1681 switch (c) {
1682 case TELOPT_SGA:
1683 case TELOPT_BINARY:
1684 case TELOPT_EOR:
1685 case TELOPT_TTYPE:
1686 case TELOPT_ECHO:
1687 case TELOPT_TN3270E:
1688 if (c != TELOPT_TN3270E || !HOST_FLAG(NON_TN3270E_HOST)) {
1689 if (!hisopts[c]) {
1690 hisopts[c] = 1;
1691 do_opt[2] = c;
1692 net_rawout(do_opt, sizeof(do_opt));
1693 vtrace("SENT %s %s\n", cmd(DO), opt(c));
1694
1695 /* For UTS, volunteer to do EOR when they do. */
1696 if (c == TELOPT_EOR && !myopts[c]) {
1697 myopts[c] = 1;
1698 will_opt[2] = c;
1699 net_rawout(will_opt, sizeof(will_opt));
1700 vtrace("SENT %s %s\n", cmd(WILL), opt(c));
1701 }
1702
1703 check_in3270();
1704 check_linemode(false);
1705 }
1706 break;
1707 }
1708 default:
1709 dont_opt[2] = c;
1710 net_rawout(dont_opt, sizeof(dont_opt));
1711 vtrace("SENT %s %s\n", cmd(DONT), opt(c));
1712 break;
1713 }
1714 telnet_state = TNS_DATA;
1715 break;
1716 case TNS_WONT: /* telnet WONT DO OPTION command */
1717 vtrace("%s\n", opt(c));
1718 if (hisopts[c]) {
1719 hisopts[c] = 0;
1720 dont_opt[2] = c;
1721 net_rawout(dont_opt, sizeof(dont_opt));
1722 vtrace("SENT %s %s\n", cmd(DONT), opt(c));
1723 check_in3270();
1724 check_linemode(false);
1725 }
1726 telnet_state = TNS_DATA;
1727 break;
1728 case TNS_DO: /* telnet PLEASE DO OPTION command */
1729 vtrace("%s\n", opt(c));
1730 switch (c) {
1731 case TELOPT_BINARY:
1732 case TELOPT_EOR:
1733 case TELOPT_TTYPE:
1734 case TELOPT_SGA:
1735 case TELOPT_NAWS:
1736 case TELOPT_TM:
1737 case TELOPT_TN3270E:
1738 case TELOPT_STARTTLS:
1739 if (c == TELOPT_STARTTLS &&
1740 (!sio_supported() ||
1741 !appres.tls.starttls ||
1742 secure_connection)) {
1743 refused_tls = true;
1744 if (secure_connection) {
1745 nested_tls = true;
1746 }
1747 goto wont;
1748 }
1749 case TELOPT_NEW_ENVIRON:
1750 if (c == TELOPT_TN3270E && HOST_FLAG(NON_TN3270E_HOST)) {
1751 goto wont;
1752 }
1753 if (c == TELOPT_TM && !appres.bsd_tm) {
1754 goto wont;
1755 }
1756 if (c == TELOPT_NEW_ENVIRON && !appres.new_environ) {
1757 goto wont;
1758 }
1759 if (c == TELOPT_TTYPE && myopts[TELOPT_NEW_ENVIRON] &&
1760 !did_ne_send) {
1761 /*
1762 * Defer sending WILL TTYPE until after the host asks for SB
1763 * NEW_ENVIRON SEND.
1764 */
1765 myopts[c] = 1;
1766 deferred_will_ttype = true;
1767 break;
1768 }
1769
1770 if (!myopts[c]) {
1771 if (c != TELOPT_TM) {
1772 myopts[c] = 1;
1773 }
1774 will_opt[2] = c;
1775 net_rawout(will_opt, sizeof(will_opt));
1776 vtrace("SENT %s %s\n", cmd(WILL), opt(c));
1777 check_in3270();
1778 check_linemode(false);
1779 }
1780 if (c == TELOPT_NAWS) {
1781 send_naws();
1782 }
1783 if (c == TELOPT_STARTTLS) {
1784 static unsigned char follows_msg[] = {
1785 IAC, SB, TELOPT_STARTTLS, TLS_FOLLOWS, IAC, SE
1786 };
1787
1788 /*
1789 * Send IAC SB STARTTLS FOLLOWS IAC SE to announce that what
1790 * follows is TLS.
1791 */
1792 net_rawout(follows_msg, sizeof(follows_msg));
1793 vtrace("SENT %s %s FOLLOWS %s\n", cmd(SB),
1794 opt(TELOPT_STARTTLS), cmd(SE));
1795 need_tls_follows = true;
1796 }
1797 break;
1798 default:
1799 wont:
1800 wont_opt[2] = c;
1801 net_rawout(wont_opt, sizeof(wont_opt));
1802 vtrace("SENT %s %s\n", cmd(WONT), opt(c));
1803 break;
1804 }
1805 telnet_state = TNS_DATA;
1806 break;
1807 case TNS_DONT: /* telnet PLEASE DON'T DO OPTION command */
1808 vtrace("%s\n", opt(c));
1809 if (myopts[c]) {
1810 myopts[c] = 0;
1811 wont_opt[2] = c;
1812 net_rawout(wont_opt, sizeof(wont_opt));
1813 vtrace("SENT %s %s\n", cmd(WONT), opt(c));
1814 check_in3270();
1815 check_linemode(false);
1816 }
1817 if (c == TELOPT_TTYPE && deferred_will_ttype) {
1818 deferred_will_ttype = false;
1819 }
1820 telnet_state = TNS_DATA;
1821 break;
1822 case TNS_SB: /* telnet sub-option string command */
1823 if (c == IAC) {
1824 telnet_state = TNS_SB_IAC;
1825 } else {
1826 *sbptr++ = c;
1827 }
1828 break;
1829 case TNS_SB_IAC: /* telnet sub-option string command */
1830 *sbptr++ = c;
1831 if (c == SE) {
1832 telnet_state = TNS_DATA;
1833 if (sbbuf[0] == TELOPT_TTYPE && sbbuf[1] == TELQUAL_SEND) {
1834 size_t tt_len, tb_len;
1835 char *tt_out;
1836
1837 vtrace("%s %s\n", opt(sbbuf[0]), telquals[sbbuf[1]]);
1838 if (lus != NULL && try_lu == NULL) {
1839 /* None of the LUs worked. */
1840 connect_error("Cannot connect to specified LU");
1841 return false;
1842 }
1843
1844 tt_len = strlen(termtype);
1845 if (try_lu != NULL && *try_lu) {
1846 tt_len += strlen(try_lu) + 1;
1847 connected_lu = try_lu;
1848 } else {
1849 connected_lu = NULL;
1850 }
1851
1852 tb_len = 4 + tt_len + 2;
1853 tt_out = Malloc(tb_len + 1);
1854 sprintf(tt_out, "%c%c%c%c%s%s%s%c%c",
1855 IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
1856 force_ascii(termtype),
1857 (try_lu != NULL && *try_lu)? "@": "",
1858 (try_lu != NULL && *try_lu)? force_ascii(try_lu) : "",
1859 IAC, SE);
1860 net_hexnvt_out_framed((unsigned char *)tt_out, tb_len, true);
1861 Free(tt_out);
1862
1863 status_lu(connected_lu);
1864
1865 vtrace("SENT %s %s %s %s%s%s %s\n", cmd(SB), opt(TELOPT_TTYPE),
1866 telquals[TELQUAL_IS], termtype,
1867 (try_lu != NULL && *try_lu)? "@": "",
1868 (try_lu != NULL && *try_lu)? try_lu: "",
1869 cmd(SE));
1870
1871 /* Advance to the next LU name. */
1872 next_lu();
1873 } else if (myopts[TELOPT_TN3270E] && sbbuf[0] == TELOPT_TN3270E) {
1874 if (tn3270e_negotiate()) {
1875 return false;
1876 }
1877 } else if (sio_supported() &&
1878 sio != NULL &&
1879 need_tls_follows &&
1880 myopts[TELOPT_STARTTLS] &&
1881 sbbuf[0] == TELOPT_STARTTLS) {
1882 continue_tls(sbbuf, (int)(sbptr - sbbuf));
1883 } else if (sbbuf[0] == TELOPT_NEW_ENVIRON &&
1884 sbbuf[1] == TELQUAL_SEND && appres.new_environ) {
1885 unsigned char *reply_buf;
1886 size_t reply_buflen;
1887 char *trace_in;
1888 char *trace_out;
1889
1890 if (!telnet_new_environ(sbbuf + 2, (sbptr - sbbuf - 3),
1891 &reply_buf, &reply_buflen, &trace_in,
1892 &trace_out)) {
1893 vtrace("%s %s [error]\n", opt(sbbuf[0]),
1894 telquals[sbbuf[1]]);
1895 } else {
1896 vtrace("%s\n", trace_in);
1897 Free(trace_in);
1898 net_rawout(reply_buf, reply_buflen);
1899 Free(reply_buf);
1900 vtrace("SENT %s\n", trace_out);
1901 Free(trace_out);
1902 }
1903
1904 /*
1905 * Remember that we did a NEW_ENVIRON SEND, so we won't defer a
1906 * future DO TTYPE.
1907 */
1908 did_ne_send = true;
1909
1910 /* Now respond to DO TTYPE. */
1911 if (deferred_will_ttype && myopts[TELOPT_TTYPE]) {
1912 will_opt[2] = TELOPT_TTYPE;
1913 net_rawout(will_opt, sizeof(will_opt));
1914 vtrace("SENT %s %s\n", cmd(WILL), opt(TELOPT_TTYPE));
1915 check_in3270();
1916 check_linemode(false);
1917 deferred_will_ttype = false;
1918 }
1919 }
1920
1921 } else {
1922 telnet_state = TNS_SB;
1923 }
1924 break;
1925 }
1926 return true;
1927 }
1928
1929 /* Send a TN3270E terminal type request. */
1930 static void
tn3270e_request(void)1931 tn3270e_request(void)
1932 {
1933 size_t tt_len, tb_len;
1934 char *tt_out;
1935 char *t;
1936 char *xtn;
1937
1938 /* Convert 3279 to 3278, per the RFC. */
1939 xtn = NewString(termtype);
1940 if (!strncmp(xtn, "IBM-3279", 8)) {
1941 xtn[7] = '8';
1942 }
1943
1944 tt_len = strlen(termtype);
1945 if (try_lu != NULL && *try_lu) {
1946 tt_len += strlen(try_lu) + 1;
1947 }
1948
1949 tb_len = 5 + tt_len + 2;
1950 tt_out = Malloc(tb_len + 1);
1951 t = tt_out;
1952 t += sprintf(tt_out, "%c%c%c%c%c%s",
1953 IAC, SB, TELOPT_TN3270E, TN3270E_OP_DEVICE_TYPE, TN3270E_OP_REQUEST,
1954 force_ascii(xtn));
1955
1956 if (try_lu != NULL && *try_lu) {
1957 t += sprintf(t, "%c%s", TN3270E_OP_CONNECT, force_ascii(try_lu));
1958 }
1959
1960 sprintf(t, "%c%c", IAC, SE);
1961
1962 net_hexnvt_out_framed((unsigned char *)tt_out, tb_len, true);
1963 Free(tt_out);
1964
1965 vtrace("SENT %s %s DEVICE-TYPE REQUEST %s%s%s %s\n",
1966 cmd(SB), opt(TELOPT_TN3270E), xtn,
1967 (try_lu != NULL && *try_lu)? " CONNECT ": "",
1968 (try_lu != NULL && *try_lu)? try_lu: "",
1969 cmd(SE));
1970
1971 Free(xtn);
1972 }
1973
1974 /*
1975 * Back off of TN3270E.
1976 */
1977 static void
backoff_tn3270e(const char * why)1978 backoff_tn3270e(const char *why)
1979 {
1980 vtrace("Aborting TN3270E: %s\n", why);
1981
1982 /* Tell the host 'no'. */
1983 wont_opt[2] = TELOPT_TN3270E;
1984 net_rawout(wont_opt, sizeof(wont_opt));
1985 vtrace("SENT %s %s\n", cmd(WONT), opt(TELOPT_TN3270E));
1986
1987 /* Restore the LU list; we may need to run it again in TN3270 mode. */
1988 setup_lus();
1989
1990 /* Reset our internal state. */
1991 myopts[TELOPT_TN3270E] = 0;
1992 check_in3270();
1993 }
1994
1995 /*
1996 * Negotiation of TN3270E options.
1997 * Returns 0 if okay, -1 if we have to give up altogether.
1998 */
1999 static int
tn3270e_negotiate(void)2000 tn3270e_negotiate(void)
2001 {
2002 #define LU_MAX 32
2003 static char reported_lu[LU_MAX+1];
2004 static char reported_type[LU_MAX+1];
2005 int sblen;
2006 b8_t e_rcvd;
2007
2008 /* Find out how long the subnegotiation buffer is. */
2009 for (sblen = 0; ; sblen++) {
2010 if (sbbuf[sblen] == SE) {
2011 break;
2012 }
2013 }
2014
2015 vtrace("TN3270E ");
2016
2017 switch (sbbuf[1]) {
2018 case TN3270E_OP_SEND:
2019 if (sbbuf[2] == TN3270E_OP_DEVICE_TYPE) {
2020 /* Host wants us to send our device type. */
2021 vtrace("SEND DEVICE-TYPE SE\n");
2022 tn3270e_request();
2023 } else {
2024 vtrace("SEND ??%u SE\n", sbbuf[2]);
2025 }
2026 break;
2027
2028 case TN3270E_OP_DEVICE_TYPE:
2029 /* Device type negotiation. */
2030 vtrace("DEVICE-TYPE ");
2031 switch (sbbuf[2]) {
2032 case TN3270E_OP_IS: {
2033 int tnlen, snlen;
2034
2035 /* Device type success. */
2036
2037 /* Isolate the terminal type and session. */
2038 tnlen = 0;
2039 while (sbbuf[3+tnlen] != SE &&
2040 sbbuf[3+tnlen] != TN3270E_OP_CONNECT) {
2041 tnlen++;
2042 }
2043 snlen = 0;
2044 if (sbbuf[3+tnlen] == TN3270E_OP_CONNECT) {
2045 while(sbbuf[3+tnlen+1+snlen] != SE) {
2046 snlen++;
2047 }
2048 }
2049
2050 /* Remember the LU. */
2051 if (tnlen) {
2052 if (tnlen > LU_MAX) {
2053 tnlen = LU_MAX;
2054 }
2055 strncpy(reported_type, (char *)&sbbuf[3], tnlen);
2056 reported_type[tnlen] = '\0';
2057 force_local(reported_type);
2058 connected_type = reported_type;
2059 }
2060 if (snlen) {
2061 if (snlen > LU_MAX) {
2062 snlen = LU_MAX;
2063 }
2064 strncpy(reported_lu, (char *)&sbbuf[3+tnlen+1], snlen);
2065 reported_lu[snlen] = '\0';
2066 force_local(reported_lu);
2067 connected_lu = reported_lu;
2068 }
2069
2070 vtrace("IS %s CONNECT %s SE\n", tnlen? connected_type: "",
2071 snlen? connected_lu: "");
2072
2073 if (snlen) {
2074 status_lu(connected_lu);
2075 }
2076
2077 /* Tell them what we can do. */
2078 tn3270e_subneg_send(TN3270E_OP_REQUEST, &e_funcs);
2079 break;
2080 }
2081 case TN3270E_OP_REJECT:
2082 /* Device type failure. */
2083 vtrace("REJECT REASON %s SE\n", rsn(sbbuf[4]));
2084 if (sbbuf[4] == TN3270E_REASON_UNSUPPORTED_REQ) {
2085 backoff_tn3270e("Host rejected request type");
2086 break;
2087 }
2088
2089 next_lu();
2090 if (try_lu != NULL) {
2091 /* Try the next LU. */
2092 tn3270e_request();
2093 } else if (lus != NULL) {
2094 /* No more LUs to try. Give up. */
2095 backoff_tn3270e("Host rejected resource(s)");
2096 } else {
2097 backoff_tn3270e("Device type rejected");
2098 }
2099
2100 break;
2101 default:
2102 vtrace("??%u SE\n", sbbuf[2]);
2103 break;
2104 }
2105 break;
2106
2107 case TN3270E_OP_FUNCTIONS:
2108 /* Functions negotiation. */
2109 vtrace("FUNCTIONS ");
2110
2111 switch (sbbuf[2]) {
2112 case TN3270E_OP_REQUEST:
2113 /* Host is telling us what functions they want. */
2114 vtrace("REQUEST %s SE\n",
2115 tn3270e_function_names(sbbuf+3, sblen-3));
2116
2117 tn3270e_fdecode(sbbuf+3, sblen-3, &e_rcvd);
2118 if (b8_none_added(&e_funcs, &e_rcvd)) {
2119 /* They want what we want, or less. Done. */
2120 b8_copy(&e_funcs, &e_rcvd);
2121 tn3270e_subneg_send(TN3270E_OP_IS, &e_funcs);
2122 tn3270e_negotiated = 1;
2123 vtrace("TN3270E option negotiation complete.\n");
2124 check_in3270();
2125 } else {
2126 /*
2127 * They want us to do something we can't.
2128 * Request the common subset.
2129 */
2130 b8_and(&e_funcs, &e_funcs, &e_rcvd);
2131 tn3270e_subneg_send(TN3270E_OP_REQUEST, &e_funcs);
2132 }
2133 break;
2134
2135 case TN3270E_OP_IS:
2136 /* They accept our last request, or a subset thereof. */
2137 vtrace("IS %s SE\n", tn3270e_function_names(sbbuf+3, sblen-3));
2138 tn3270e_fdecode(sbbuf+3, sblen-3, &e_rcvd);
2139 if (b8_none_added(&e_funcs, &e_rcvd)) {
2140 /* They want what we want, or less. Done. */
2141 b8_copy(&e_funcs, &e_rcvd);
2142 } else {
2143 /*
2144 * They've added something. Abandon TN3270E,
2145 * they're brain dead.
2146 */
2147 backoff_tn3270e("Host illegally added function(s)");
2148 break;
2149 }
2150 tn3270e_negotiated = 1;
2151 vtrace("TN3270E option negotiation complete.\n");
2152
2153 /*
2154 * If the host does not support BIND_IMAGE, then we
2155 * must go straight to 3270 mode. We do not implicitly
2156 * unlock the keyboard, though -- that requires a
2157 * Write command from the host.
2158 */
2159 if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2160 tn3270e_submode = E_3270;
2161 }
2162
2163 check_in3270();
2164 break;
2165
2166 default:
2167 vtrace("??%u SE\n", sbbuf[2]);
2168 break;
2169 }
2170 break;
2171
2172 default:
2173 vtrace("??%u SE\n", sbbuf[1]);
2174 }
2175
2176 /* Good enough for now. */
2177 return 0;
2178 }
2179
2180 /* Expand a string of TN3270E function codes into text. */
2181 static const char *
tn3270e_function_names(const unsigned char * buf,int len)2182 tn3270e_function_names(const unsigned char *buf, int len)
2183 {
2184 int i;
2185 static char text_buf[1024];
2186 char *s = text_buf;
2187
2188 if (!len) {
2189 return("(null)");
2190 }
2191 for (i = 0; i < len; i++) {
2192 s += sprintf(s, "%s%s", (s == text_buf)? "": " ", fnn(buf[i]));
2193 }
2194 return text_buf;
2195 }
2196
2197 /* Expand the current TN3270E function codes into text. */
2198 const char *
tn3270e_current_opts(void)2199 tn3270e_current_opts(void)
2200 {
2201 int i;
2202 static char text_buf[1024];
2203 char *s = text_buf;
2204
2205 if (b8_is_zero(&e_funcs) || !IN_E) {
2206 return NULL;
2207 }
2208 for (i = 0; i < MX8; i++) {
2209 if (b8_bit_is_set(&e_funcs, i)) {
2210 s += sprintf(s, "%s%s", (s == text_buf)? "": " ", fnn(i));
2211 }
2212 }
2213 return text_buf;
2214 }
2215
2216 /* Transmit a TN3270E FUNCTIONS REQUEST or FUNCTIONS IS message. */
2217 static void
tn3270e_subneg_send(unsigned char op,b8_t * funcs)2218 tn3270e_subneg_send(unsigned char op, b8_t *funcs)
2219 {
2220 unsigned char proto_buf[7 + MX8];
2221 int proto_len;
2222 int i;
2223
2224 /* Construct the buffers. */
2225 memcpy(proto_buf, functions_req, 4);
2226 proto_buf[4] = op;
2227 proto_len = 5;
2228 for (i = 0; i < MX8; i++) {
2229 if (b8_bit_is_set(funcs, (i))) {
2230 proto_buf[proto_len++] = i;
2231 }
2232 }
2233
2234 /* Complete and send out the protocol message. */
2235 proto_buf[proto_len++] = IAC;
2236 proto_buf[proto_len++] = SE;
2237 net_rawout(proto_buf, proto_len);
2238
2239 /* Complete and send out the trace text. */
2240 vtrace("SENT %s %s FUNCTIONS %s %s %s\n",
2241 cmd(SB), opt(TELOPT_TN3270E),
2242 (op == TN3270E_OP_REQUEST)? "REQUEST": "IS",
2243 tn3270e_function_names(proto_buf + 5, proto_len - 7),
2244 cmd(SE));
2245 }
2246
2247 /* Translate a string of TN3270E functions into a bitmap. */
2248 static void
tn3270e_fdecode(const unsigned char * buf,int len,b8_t * r)2249 tn3270e_fdecode(const unsigned char *buf, int len, b8_t *r)
2250 {
2251 int i;
2252
2253 b8_zero(r);
2254 for (i = 0; i < len; i++) {
2255 b8_set_bit(r, buf[i]);
2256 }
2257 }
2258
2259 static int
maxru(unsigned char c)2260 maxru(unsigned char c)
2261 {
2262 if (!(c & 0x80)) {
2263 return 0;
2264 }
2265 return ((c >> 4) & 0x0f) * (1 << (c & 0xf));
2266 }
2267
2268 static void
process_bind(unsigned char * buf,size_t buflen)2269 process_bind(unsigned char *buf, size_t buflen)
2270 {
2271 size_t namelen;
2272 size_t dest_ix = 0;
2273
2274 /* Save the raw image. */
2275 Replace(bind_image, (unsigned char *)Malloc(buflen));
2276 memcpy(bind_image, buf, buflen);
2277 bind_image_len = buflen;
2278
2279 /* Clean up the derived state. */
2280 if (plu_name == NULL) {
2281 plu_name = Malloc(mb_max_len(BIND_PLU_NAME_MAX + 1));
2282 }
2283 memset(plu_name, '\0', mb_max_len(BIND_PLU_NAME_MAX + 1));
2284 maxru_sec = 0;
2285 maxru_pri = 0;
2286 bind_rd = 0;
2287 bind_cd = 0;
2288 bind_ra = 0;
2289 bind_ca = 0;
2290 bind_state = 0;
2291
2292 /* Make sure it's a BIND. */
2293 if (buflen < 1 || buf[0] != BIND_RU) {
2294 return;
2295 }
2296
2297 /* Extract the maximum RUs. */
2298 if (buflen > BIND_OFF_MAXRU_SEC) {
2299 maxru_sec = maxru(buf[BIND_OFF_MAXRU_SEC]);
2300 }
2301 if (buflen > BIND_OFF_MAXRU_PRI) {
2302 maxru_pri = maxru(buf[BIND_OFF_MAXRU_PRI]);
2303 }
2304
2305 /* Extract the screen size. */
2306 if (buflen > BIND_OFF_SSIZE) {
2307 int bind_ss = buf[BIND_OFF_SSIZE];
2308
2309 switch (bind_ss) {
2310 case 0x00:
2311 case 0x02:
2312 bind_rd = MODEL_2_ROWS;
2313 bind_cd = MODEL_2_COLS;
2314 bind_ra = MODEL_2_ROWS;
2315 bind_ca = MODEL_2_COLS;
2316 bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2317 break;
2318 case 0x03:
2319 bind_rd = MODEL_2_ROWS;
2320 bind_cd = MODEL_2_COLS;
2321 bind_ra = maxROWS;
2322 bind_ca = maxCOLS;
2323 bind_state = BIND_DIMS_PRESENT | BIND_DIMS_VALID;
2324 break;
2325 case 0x7e:
2326 bind_rd = buf[BIND_OFF_RD];
2327 bind_cd = buf[BIND_OFF_CD];
2328 bind_ra = buf[BIND_OFF_RD];
2329 bind_ca = buf[BIND_OFF_CD];
2330 bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2331 break;
2332 case 0x7f:
2333 bind_rd = buf[BIND_OFF_RD];
2334 bind_cd = buf[BIND_OFF_CD];
2335 bind_ra = buf[BIND_OFF_RA];
2336 bind_ca = buf[BIND_OFF_CA];
2337 bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2338 break;
2339 default:
2340 bind_state = 0;
2341 break;
2342 }
2343 }
2344
2345 /* Validate and implement the screen size. */
2346 if (appres.bind_limit && (bind_state & BIND_DIMS_PRESENT)) {
2347 if (bind_rd > maxROWS || bind_cd > maxCOLS) {
2348 popup_an_error("Ignoring invalid BIND image screen "
2349 "size parameters:\n"
2350 " BIND Default Rows-Cols %ux%u > Maximum %ux%u",
2351 bind_rd, bind_cd, maxROWS, maxCOLS);
2352 bind_state &= ~BIND_DIMS_VALID;
2353 } else if (bind_rd < MODEL_2_ROWS || bind_cd < MODEL_2_COLS) {
2354 popup_an_error("Ignoring invalid BIND image screen "
2355 "size parameters:\n"
2356 " BIND Default Rows-Cols %ux%u < Minimum %ux%u",
2357 bind_rd, bind_cd, MODEL_2_ROWS, MODEL_2_COLS);
2358 bind_state &= ~BIND_DIMS_VALID;
2359 } else if (bind_ra > maxROWS || bind_ca > maxCOLS) {
2360 popup_an_error("Ignoring invalid BIND image screen "
2361 "size parameters:\n"
2362 " BIND Alternate Rows-Cols %ux%u > Maximum %ux%u",
2363 bind_ra, bind_ca, maxROWS, maxCOLS);
2364 bind_state &= ~BIND_DIMS_VALID;
2365 } else if (bind_ra < MODEL_2_ROWS || bind_ca < MODEL_2_COLS) {
2366 popup_an_error("Ignoring invalid BIND image screen "
2367 "size parameters:\n"
2368 " BIND Alternate Rows-Cols %ux%u < Minimum %ux%u",
2369 bind_ra, bind_ca, MODEL_2_ROWS, MODEL_2_COLS);
2370 bind_state &= ~BIND_DIMS_VALID;
2371 } else {
2372 defROWS = bind_rd;
2373 defCOLS = bind_cd;
2374 altROWS = bind_ra;
2375 altCOLS = bind_ca;
2376 }
2377 }
2378
2379 ctlr_erase(false);
2380
2381 /* Extract the PLU name. */
2382 if (buflen > BIND_OFF_PLU_NAME_LEN) {
2383 namelen = buf[BIND_OFF_PLU_NAME_LEN];
2384 if (namelen > BIND_PLU_NAME_MAX) {
2385 namelen = BIND_PLU_NAME_MAX;
2386 }
2387 if ((namelen > 0) && (buflen > BIND_OFF_PLU_NAME + namelen)) {
2388 #if defined(EBCDIC_HOST) /*[*/
2389 memcpy(plu_name, &buf[BIND_OFF_PLU_NAME], namelen);
2390 plu_name[namelen] = '\0';
2391 #else /*][*/
2392 size_t i;
2393
2394 for (i = 0; i < namelen; i++) {
2395 size_t nx;
2396
2397 nx = ebcdic_to_multibyte(buf[BIND_OFF_PLU_NAME + i],
2398 plu_name + dest_ix, mb_max_len(1));
2399 if (nx > 1) {
2400 dest_ix += nx - 1;
2401 }
2402 }
2403 #endif /*]*/
2404 status_lu(plu_name);
2405 }
2406 }
2407
2408 /* A BIND implicitly puts us in 3270 mode. */
2409 tn3270e_submode = E_3270;
2410 }
2411
2412 /* Decode an UNBIND reason. */
2413 static const char *
unbind_reason(unsigned char r)2414 unbind_reason (unsigned char r)
2415 {
2416 switch (r) {
2417 case TN3270E_UNBIND_NORMAL:
2418 return "normal";
2419 case TN3270E_UNBIND_BIND_FORTHCOMING:
2420 return "BIND forthcoming";
2421 case TN3270E_UNBIND_VR_INOPERATIVE:
2422 return "virtual route inoperative";
2423 case TN3270E_UNBIND_RX_INOPERATIVE:
2424 return "route extension inoperative";
2425 case TN3270E_UNBIND_HRESET:
2426 return "hierarchical reset";
2427 case TN3270E_UNBIND_SSCP_GONE:
2428 return "SSCP gone";
2429 case TN3270E_UNBIND_VR_DEACTIVATED:
2430 return "virtual route deactivated";
2431 case TN3270E_UNBIND_LU_FAILURE_PERM:
2432 return "unrecoverable LU failure";
2433 case TN3270E_UNBIND_LU_FAILURE_TEMP:
2434 return "recoverable LU failure";
2435 case TN3270E_UNBIND_CLEANUP:
2436 return "cleanup";
2437 case TN3270E_UNBIND_BAD_SENSE:
2438 return "bad sense code or user-supplied sense code";
2439 default:
2440 return lazyaf("unknown X'%02x'", r);
2441 }
2442 }
2443
2444 static int
process_eor(void)2445 process_eor(void)
2446 {
2447 if (syncing || !(ibptr - ibuf)) {
2448 return(0);
2449 }
2450
2451 if (IN_E) {
2452 tn3270e_header *h = (tn3270e_header *)ibuf;
2453 unsigned char *s;
2454 enum pds rv;
2455
2456 vtrace("RCVD TN3270E(%s%s %s %u)\n",
2457 e_dt(h->data_type),
2458 e_rq(h->data_type, h->request_flag),
2459 e_rsp(h->data_type, h->response_flag),
2460 h->seq_number[0] << 8 | h->seq_number[1]);
2461
2462 switch (h->data_type) {
2463 case TN3270E_DT_3270_DATA:
2464 if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE) &&
2465 !tn3270e_bound) {
2466 return 0;
2467 }
2468 tn3270e_submode = E_3270;
2469 check_in3270();
2470 response_required = h->response_flag;
2471 rv = process_ds(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2472 if (rv < 0 && response_required != TN3270E_RSF_NO_RESPONSE) {
2473 tn3270e_nak(rv);
2474 }
2475 else if (rv == PDS_OKAY_NO_OUTPUT &&
2476 response_required == TN3270E_RSF_ALWAYS_RESPONSE) {
2477 tn3270e_ack();
2478 }
2479 response_required = TN3270E_RSF_NO_RESPONSE;
2480 return 0;
2481 case TN3270E_DT_BIND_IMAGE:
2482 if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2483 return 0;
2484 }
2485 process_bind(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2486 if (bind_state & BIND_DIMS_PRESENT) {
2487 if (bind_state & BIND_DIMS_ALT) {
2488 trace_ds("< BIND PLU-name '%s' "
2489 "MaxSec-RU %d MaxPri-RU %d "
2490 "Rows-Cols Default %dx%d "
2491 "Alternate %dx%d%s%s\n",
2492 plu_name, maxru_sec, maxru_pri,
2493 bind_rd, bind_cd,
2494 bind_ra, bind_ca,
2495 (bind_state & BIND_DIMS_VALID)?
2496 "": " (invalid)",
2497 appres.bind_limit?
2498 "": " (ignored)");
2499 } else {
2500 trace_ds("< BIND PLU-name '%s' "
2501 "MaxSec-RU %d MaxPri-RU %d "
2502 "Rows-Cols Default %dx%d%s%s\n",
2503 plu_name, maxru_sec, maxru_pri,
2504 bind_rd, bind_cd,
2505 (bind_state & BIND_DIMS_VALID)?
2506 "": " (invalid)",
2507 appres.bind_limit?
2508 "": " (ignored)");
2509 }
2510 } else {
2511 trace_ds("< BIND PLU-name '%s' "
2512 "MaxSec-RU %d MaxPri-RU %d\n",
2513 plu_name, maxru_sec, maxru_pri);
2514 }
2515 tn3270e_bound = 1;
2516 check_in3270();
2517 return 0;
2518 case TN3270E_DT_UNBIND:
2519 if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2520 return 0;
2521 }
2522 if ((ibptr - ibuf) > EH_SIZE) {
2523 trace_ds("< UNBIND %s\n", unbind_reason(ibuf[EH_SIZE]));
2524 }
2525 tn3270e_bound = 0;
2526 /* Go back to the connected LU. */
2527 status_lu(connected_lu);
2528 /*
2529 * Undo any screen-sizing effects from a previous BIND.
2530 */
2531 defROWS = MODEL_2_ROWS;
2532 defCOLS = MODEL_2_COLS;
2533 altROWS = maxROWS;
2534 altCOLS = maxCOLS;
2535 ctlr_erase(false);
2536 tn3270e_submode = E_UNBOUND;
2537 check_in3270();
2538 return 0;
2539 case TN3270E_DT_NVT_DATA:
2540 /* In tn3270e NVT mode */
2541 tn3270e_submode = E_NVT;
2542 check_in3270();
2543 for (s = ibuf; s < ibptr; s++) {
2544 nvt_process(*s++);
2545 }
2546 return 0;
2547 case TN3270E_DT_SSCP_LU_DATA:
2548 if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2549 return 0;
2550 }
2551 tn3270e_submode = E_SSCP;
2552 check_in3270();
2553 ctlr_write_sscp_lu(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2554 return 0;
2555 default:
2556 /* Should do something more extraordinary here. */
2557 return 0;
2558 }
2559 } else {
2560 process_ds(ibuf, ibptr - ibuf);
2561 }
2562 return 0;
2563 }
2564
2565 /*
2566 * net_exception
2567 * Called when there is an exceptional condition on the socket.
2568 */
2569 void
net_exception(iosrc_t fd _is_unused,ioid_t id _is_unused)2570 net_exception(iosrc_t fd _is_unused, ioid_t id _is_unused)
2571 {
2572 #if defined(LOCAL_PROCESS) /*[*/
2573 if (local_process) {
2574 vtrace("RCVD exception\n");
2575 } else
2576 #endif /*[*/
2577 {
2578 vtrace("RCVD urgent data indication\n");
2579 if (!syncing) {
2580 syncing = 1;
2581 x_except_off();
2582 }
2583 }
2584 }
2585
2586 /*
2587 * Flavors of Network Output:
2588 *
2589 * 3270 mode
2590 * net_output send a 3270 record
2591 *
2592 * NVT mode; call each other in turn
2593 * net_sendc net_cookout for 1 byte
2594 * net_sends net_cookout for a null-terminated string
2595 * net_cookout send user data with cooked-mode processing, NVT mode
2596 * net_cookedout send user data, NVT mode, already cooked
2597 * net_rawout send telnet protocol data, NVT mode
2598 *
2599 */
2600
2601 /*
2602 * net_cookedout
2603 * Send user data out in NVT mode, without cooked-mode processing.
2604 */
2605 void
net_cookedout(const char * buf,size_t len)2606 net_cookedout(const char *buf, size_t len)
2607 {
2608 if (toggled(TRACING)) {
2609 size_t i;
2610
2611 vtrace(">");
2612 for (i = 0; i < len; i++) {
2613 vtrace(" %s", ctl_see((int)*(buf+i)));
2614 }
2615 vtrace("\n");
2616 }
2617 net_rawout((unsigned const char *)buf, len);
2618 }
2619
2620 /*
2621 * net_cookout
2622 * Send output in NVT mode, including cooked-mode processing if
2623 * appropriate.
2624 */
2625 void
net_cookout(const char * buf,size_t len)2626 net_cookout(const char *buf, size_t len)
2627 {
2628 if (!IN_NVT || (kybdlock & KL_AWAITING_FIRST)) {
2629 return;
2630 }
2631
2632 if (linemode) {
2633 linemode_out(buf, len);
2634 } else {
2635 net_cookedout(buf, len);
2636 }
2637 }
2638
2639 /*
2640 * net_rawout
2641 * Send out raw telnet data. We assume that there will always be enough
2642 * space to buffer what we want to transmit, so we don't handle EAGAIN or
2643 * EWOULDBLOCK.
2644 */
2645 static void
net_rawout(unsigned const char * buf,size_t len)2646 net_rawout(unsigned const char *buf, size_t len)
2647 {
2648 int nw;
2649
2650 trace_netdata('>', buf, len);
2651
2652 while (len) {
2653 #if defined(OMTU) /*[*/
2654 size_t n2w = len;
2655 int pause = 0;
2656
2657 if (n2w > OMTU) {
2658 n2w = OMTU;
2659 pause = 1;
2660 }
2661 #else
2662 # define n2w len
2663 #endif
2664 if (secure_connection) {
2665 nw = sio_write(sio, (const char *) buf, (int)n2w);
2666 } else
2667 #if defined(LOCAL_PROCESS) /*[*/
2668 if (local_process) {
2669 nw = write(sock, (const char *) buf, (int)n2w);
2670 } else
2671 #endif /*]*/
2672 {
2673 nw = send(sock, (const char *) buf, (int)n2w, 0);
2674 }
2675 if (nw < 0) {
2676 if (secure_connection) {
2677 connect_error("%s", sio_last_error());
2678 host_disconnect(false);
2679 return;
2680 }
2681 vtrace("RCVD socket error %d (%s)\n", socket_errno(),
2682 socket_strerror(socket_errno()));
2683 if (socket_errno() == SE_EPIPE || socket_errno() == SE_ECONNRESET) {
2684 host_disconnect(false);
2685 return;
2686 } else if (socket_errno() == SE_EINTR) {
2687 goto bot;
2688 } else {
2689 popup_a_sockerr("Socket write");
2690 host_disconnect(true);
2691 return;
2692 }
2693 }
2694 ns_bsent += nw;
2695 stats_poke();
2696 len -= nw;
2697 buf += nw;
2698 bot:
2699 #if defined(OMTU) /*[*/
2700 if (pause) {
2701 sleep(1);
2702 }
2703 #endif /*]*/
2704 ;
2705 }
2706 }
2707
2708 /*
2709 * net_hexnvt_out_framed
2710 * Send uncontrolled user data to the host in NVT mode, performing IAC
2711 * and CR quoting as necessary.
2712 */
2713 static void
net_hexnvt_out_framed(unsigned char * buf,int len,bool framed)2714 net_hexnvt_out_framed(unsigned char *buf, int len, bool framed)
2715 {
2716 unsigned char *tbuf;
2717 unsigned char *xbuf;
2718 bool first = true;
2719
2720 if (!len) {
2721 return;
2722 }
2723
2724 if (HOST_FLAG(NO_TELNET_HOST)) {
2725 net_rawout(buf, len);
2726 return;
2727 }
2728
2729 /* Expand it. */
2730 tbuf = xbuf = (unsigned char *)Malloc(2*len);
2731 while (len) {
2732 unsigned char c = *buf++;
2733
2734 *tbuf++ = c;
2735 len--;
2736 if (framed && (first || len == 1)) {
2737 /* Don't quote initial IAC or trailing IAC SE. */
2738 first = false;
2739 continue;
2740 }
2741 if (c == IAC) {
2742 *tbuf++ = IAC;
2743 } else if (c == '\r' && (!len || *buf != '\n')) {
2744 *tbuf++ = '\0';
2745 }
2746 first = false;
2747 }
2748
2749 /* Send it to the host. */
2750 net_rawout(xbuf, tbuf - xbuf);
2751 Free(xbuf);
2752 }
2753
2754 /*
2755 * net_hexnvt_out
2756 * Send uncontrolled user data to the host in NVT mode, performing IAC
2757 * and CR quoting as necessary.
2758 */
2759 void
net_hexnvt_out(unsigned char * buf,int len)2760 net_hexnvt_out(unsigned char *buf, int len)
2761 {
2762 net_hexnvt_out_framed(buf, len, false);
2763 }
2764
2765 /*
2766 * check_in3270
2767 * Check for switches between NVT, SSCP-LU and 3270 modes.
2768 */
2769 static void
check_in3270(void)2770 check_in3270(void)
2771 {
2772 enum cstate new_cstate = NOT_CONNECTED;
2773
2774 if (myopts[TELOPT_TN3270E]) {
2775 if (!tn3270e_negotiated) {
2776 new_cstate = CONNECTED_UNBOUND;
2777 } else switch (tn3270e_submode) {
2778 case E_UNBOUND:
2779 new_cstate = CONNECTED_UNBOUND;
2780 break;
2781 case E_NVT:
2782 new_cstate = CONNECTED_E_NVT;
2783 break;
2784 case E_3270:
2785 new_cstate = CONNECTED_TN3270E;
2786 break;
2787 case E_SSCP:
2788 new_cstate = CONNECTED_SSCP;
2789 break;
2790 }
2791 } else if (myopts[TELOPT_BINARY] &&
2792 myopts[TELOPT_EOR] &&
2793 myopts[TELOPT_TTYPE] &&
2794 hisopts[TELOPT_BINARY] &&
2795 hisopts[TELOPT_EOR]) {
2796 new_cstate = CONNECTED_3270;
2797 } else if (cstate == TELNET_PENDING) {
2798 /* Nothing has happened, yet. */
2799 return;
2800 } else if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
2801 new_cstate = linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR;
2802 } else {
2803 new_cstate = TELNET_PENDING;
2804 }
2805
2806 if (new_cstate != cstate) {
2807 int was_in_e = IN_E;
2808
2809 /*
2810 * If we've now switched between non-TN3270E mode and
2811 * TN3270E mode, reset the LU list so we can try again
2812 * in the new mode.
2813 */
2814 if (lus != NULL && was_in_e != IN_E) {
2815 curr_lu = lus;
2816 try_lu = *curr_lu;
2817 }
2818
2819 /* Allocate the initial 3270 input buffer. */
2820 if (new_cstate >= TELNET_PENDING && !ibuf_size) {
2821 ibuf = (unsigned char *)Malloc(BUFSIZ);
2822 ibuf_size = BUFSIZ;
2823 ibptr = ibuf;
2824 }
2825
2826 /* Reinitialize line mode. */
2827 if ((new_cstate == CONNECTED_NVT && linemode) ||
2828 new_cstate == CONNECTED_E_NVT) {
2829 linemode_buf_init();
2830 }
2831
2832 /* If we fell out of TN3270E, remove the state. */
2833 if (!myopts[TELOPT_TN3270E]) {
2834 tn3270e_negotiated = 0;
2835 tn3270e_submode = E_UNBOUND;
2836 tn3270e_bound = 0;
2837 }
2838 vtrace("Now operating in %s mode.\n", state_name[new_cstate]);
2839 if (FULL_SESSION) {
2840 any_host_data = true;
2841 }
2842 host_in3270(new_cstate);
2843 }
2844 }
2845
2846 /*
2847 * store3270in
2848 * Store a character in the 3270 input buffer, checking for buffer
2849 * overflow and reallocating ibuf if necessary.
2850 */
2851 static void
store3270in(unsigned char c)2852 store3270in(unsigned char c)
2853 {
2854 if (ibptr - ibuf >= ibuf_size) {
2855 ibuf_size += BUFSIZ;
2856 ibuf = (unsigned char *)Realloc((char *)ibuf, ibuf_size);
2857 ibptr = ibuf + ibuf_size - BUFSIZ;
2858 }
2859 *ibptr++ = c;
2860 }
2861
2862 /*
2863 * space3270out
2864 * Ensure that <n> more characters will fit in the 3270 output buffer.
2865 * Allocates the buffer in BUFSIZ chunks.
2866 * Allocates hidden space at the front of the buffer for TN3270E.
2867 */
2868 void
space3270out(size_t n)2869 space3270out(size_t n)
2870 {
2871 size_t nc = 0; /* amount of data currently in obuf */
2872 unsigned more = 0;
2873
2874 if (obuf_size) {
2875 nc = obptr - obuf;
2876 }
2877
2878 while ((nc + n + EH_SIZE) > (obuf_size + more)) {
2879 more += BUFSIZ;
2880 }
2881
2882 if (more) {
2883 obuf_size += more;
2884 obuf_base = (unsigned char *)Realloc((char *)obuf_base, obuf_size);
2885 obuf = obuf_base + EH_SIZE;
2886 obptr = obuf + nc;
2887 }
2888 }
2889
2890 /*
2891 * check_linemode
2892 * Set the global variable 'linemode', which says whether we are in
2893 * character-by-character mode or line mode.
2894 */
2895 static void
check_linemode(bool init)2896 check_linemode(bool init)
2897 {
2898 bool wasline = linemode;
2899
2900 /*
2901 * The next line is a deliberate kluge to effectively ignore the SGA
2902 * option. If the host will echo for us, we assume
2903 * character-at-a-time; otherwise we assume fully cooked by us.
2904 *
2905 * This allows certain IBM hosts which volunteer SGA but refuse
2906 * ECHO to operate more-or-less normally, at the expense of
2907 * implementing the (hopefully useless) "character-at-a-time, local
2908 * echo" mode.
2909 *
2910 * We still implement "switch to line mode" and "switch to character
2911 * mode" properly by asking for both SGA and ECHO to be off or on, but
2912 * we basically ignore the reply for SGA.
2913 */
2914 linemode = !hisopts[TELOPT_ECHO] /* && !hisopts[TELOPT_SGA] */;
2915
2916 if (init || linemode != wasline) {
2917 if (cstate == CONNECTED_NVT || cstate == CONNECTED_NVT_CHAR) {
2918 host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
2919 }
2920 st_changed(ST_LINE_MODE, linemode);
2921 if (!init) {
2922 vtrace("Operating in %s mode.\n",
2923 linemode? "line": "character-at-a-time");
2924 }
2925 if (IN_NVT) {
2926 if (linemode) {
2927 linemode_buf_init();
2928 } else {
2929 linemode_dump();
2930 }
2931 }
2932 }
2933 }
2934
2935 /*
2936 * nnn
2937 * Expands a number to a character string, for displaying unknown telnet
2938 * commands and options.
2939 */
2940 static const char *
nnn(int c)2941 nnn(int c)
2942 {
2943 return lazyaf("%d", c);
2944 }
2945
2946 /*
2947 * cmd
2948 * Expands a TELNET command into a character string.
2949 */
2950 const char *
cmd(int c)2951 cmd(int c)
2952 {
2953 if (TELCMD_OK(c)) {
2954 return TELCMD(c);
2955 } else {
2956 return nnn(c);
2957 }
2958 }
2959
2960 /*
2961 * opt
2962 * Expands a TELNET option into a character string.
2963 */
2964 const char *
opt(unsigned char c)2965 opt(unsigned char c)
2966 {
2967 if (TELOPT_OK(c)) {
2968 return TELOPT(c);
2969 } else if (c == TELOPT_TN3270E) {
2970 return "TN3270E";
2971 } else if (c == TELOPT_STARTTLS) {
2972 return "START-TLS";
2973 } else {
2974 return nnn((int)c);
2975 }
2976 }
2977
2978
2979 #define LINEDUMP_MAX 32
2980
2981 void
trace_netdata(char direction,unsigned const char * buf,size_t len)2982 trace_netdata(char direction, unsigned const char *buf, size_t len)
2983 {
2984 size_t offset;
2985
2986 if (!toggled(TRACING)) {
2987 return;
2988 }
2989 for (offset = 0; offset < len; offset++) {
2990 if (!(offset % LINEDUMP_MAX)) {
2991 ntvtrace("%s%c 0x%-3x ", (offset? "\n": ""), direction,
2992 (unsigned)offset);
2993 }
2994 ntvtrace("%02x", buf[offset]);
2995 }
2996 ntvtrace("\n");
2997 }
2998
2999 /*
3000 * net_output
3001 * Send 3270 output over the network:
3002 * - Prepend TN3270E header
3003 * - Expand IAC to IAC IAC
3004 * - Append IAC EOR
3005 */
3006 void
net_output(void)3007 net_output(void)
3008 {
3009 static unsigned char *xobuf = NULL;
3010 static int xobuf_len = 0;
3011 int need_resize = 0;
3012 unsigned char *nxoptr, *xoptr;
3013
3014 #define BSTART ((IN_TN3270E || IN_SSCP)? obuf_base: obuf)
3015
3016 /* Set the TN3720E header. */
3017 if (IN_TN3270E || IN_SSCP) {
3018 tn3270e_header *h = (tn3270e_header *)obuf_base;
3019
3020 /* Check for sending a TN3270E response. */
3021 if (response_required == TN3270E_RSF_ALWAYS_RESPONSE) {
3022 tn3270e_ack();
3023 response_required = TN3270E_RSF_NO_RESPONSE;
3024 }
3025
3026 /* Set the outbound TN3270E header. */
3027 h->data_type = IN_TN3270E? TN3270E_DT_3270_DATA:
3028 TN3270E_DT_SSCP_LU_DATA;
3029 h->request_flag = 0;
3030 h->response_flag = 0;
3031 h->seq_number[0] = (e_xmit_seq >> 8) & 0xff;
3032 h->seq_number[1] = e_xmit_seq & 0xff;
3033
3034 vtrace("SENT TN3270E(%s NO-RESPONSE %u)\n",
3035 IN_TN3270E? "3270-DATA": "SSCP-LU-DATA", e_xmit_seq);
3036 if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_RESPONSES)) {
3037 e_xmit_seq = (e_xmit_seq + 1) & 0x7fff;
3038 }
3039 }
3040
3041 /* Reallocate the expanded output buffer. */
3042 while (xobuf_len < (obptr - BSTART + 1) * 2) {
3043 xobuf_len += BUFSZ;
3044 need_resize++;
3045 }
3046 if (need_resize) {
3047 Replace(xobuf, (unsigned char *)Malloc(xobuf_len));
3048 }
3049
3050 /* Copy and expand IACs. */
3051 xoptr = xobuf;
3052 nxoptr = BSTART;
3053 while (nxoptr < obptr) {
3054 if ((*xoptr++ = *nxoptr++) == IAC) {
3055 *xoptr++ = IAC;
3056 }
3057 }
3058
3059 /* Append the IAC EOR and transmit. */
3060 *xoptr++ = IAC;
3061 *xoptr++ = EOR;
3062 net_rawout(xobuf, xoptr - xobuf);
3063
3064 vtrace("SENT EOR\n");
3065 ns_rsent++;
3066 stats_poke();
3067 #undef BSTART
3068 }
3069
3070 /* Send a TN3270E positive response to the server. */
3071 static void
tn3270e_ack(void)3072 tn3270e_ack(void)
3073 {
3074 unsigned char rsp_buf[10];
3075 tn3270e_header *h_in = (tn3270e_header *)ibuf;
3076 int rsp_len = 0;
3077
3078 rsp_len = 0;
3079 rsp_buf[rsp_len++] = TN3270E_DT_RESPONSE; /* data_type */
3080 rsp_buf[rsp_len++] = 0; /* request_flag */
3081 rsp_buf[rsp_len++] = TN3270E_RSF_POSITIVE_RESPONSE; /* response_flag */
3082 rsp_buf[rsp_len++] = h_in->seq_number[0]; /* seq_number[0] */
3083 if (h_in->seq_number[0] == IAC) {
3084 rsp_buf[rsp_len++] = IAC;
3085 }
3086 rsp_buf[rsp_len++] = h_in->seq_number[1]; /* seq_number[1] */
3087 if (h_in->seq_number[1] == IAC) {
3088 rsp_buf[rsp_len++] = IAC;
3089 }
3090 rsp_buf[rsp_len++] = TN3270E_POS_DEVICE_END;
3091 rsp_buf[rsp_len++] = IAC;
3092 rsp_buf[rsp_len++] = EOR;
3093 vtrace("SENT TN3270E(RESPONSE POSITIVE-RESPONSE %u) DEVICE-END\n",
3094 h_in->seq_number[0] << 8 | h_in->seq_number[1]);
3095 net_rawout(rsp_buf, rsp_len);
3096 }
3097
3098 /* Send a TN3270E negative response to the server. */
3099 static void
tn3270e_nak(enum pds rv)3100 tn3270e_nak(enum pds rv)
3101 {
3102 unsigned char rsp_buf[10];
3103 tn3270e_header *h_in = (tn3270e_header *)ibuf;
3104 int rsp_len = 0;
3105 char *neg = NULL;
3106
3107 rsp_buf[rsp_len++] = TN3270E_DT_RESPONSE; /* data_type */
3108 rsp_buf[rsp_len++] = 0; /* request_flag */
3109 rsp_buf[rsp_len++] = TN3270E_RSF_NEGATIVE_RESPONSE; /* response_flag */
3110 rsp_buf[rsp_len++] = h_in->seq_number[0]; /* seq_number[0] */
3111 if (h_in->seq_number[0] == IAC) {
3112 rsp_buf[rsp_len++] = IAC;
3113 }
3114 rsp_buf[rsp_len++] = h_in->seq_number[1]; /* seq_number[1] */
3115 if (h_in->seq_number[1] == IAC) {
3116 rsp_buf[rsp_len++] = IAC;
3117 }
3118 switch (rv) {
3119 default:
3120 case PDS_BAD_CMD:
3121 rsp_buf[rsp_len++] = TN3270E_NEG_COMMAND_REJECT;
3122 neg = "COMMAND-REJECT";
3123 break;
3124 case PDS_BAD_ADDR:
3125 rsp_buf[rsp_len++] = TN3270E_NEG_OPERATION_CHECK;
3126 neg = "OPERATION-CHECK";
3127 break;
3128 }
3129 rsp_buf[rsp_len++] = IAC;
3130 rsp_buf[rsp_len++] = EOR;
3131 vtrace("SENT TN3270E(RESPONSE NEGATIVE-RESPONSE %u) %s\n",
3132 h_in->seq_number[0] << 8 | h_in->seq_number[1], neg);
3133 net_rawout(rsp_buf, rsp_len);
3134 }
3135
3136 /* Add a dummy TN3270E header to the output buffer. */
3137 bool
net_add_dummy_tn3270e(void)3138 net_add_dummy_tn3270e(void)
3139 {
3140 tn3270e_header *h;
3141
3142 if (!IN_E || tn3270e_submode == E_UNBOUND) {
3143 return false;
3144 }
3145
3146 space3270out(EH_SIZE);
3147 h = (tn3270e_header *)obptr;
3148
3149 switch (tn3270e_submode) {
3150 case E_UNBOUND:
3151 break;
3152 case E_NVT:
3153 h->data_type = TN3270E_DT_NVT_DATA;
3154 break;
3155 case E_SSCP:
3156 h->data_type = TN3270E_DT_SSCP_LU_DATA;
3157 break;
3158 case E_3270:
3159 h->data_type = TN3270E_DT_3270_DATA;
3160 break;
3161 }
3162 h->request_flag = 0;
3163 h->response_flag = TN3270E_RSF_NO_RESPONSE;
3164 h->seq_number[0] = 0;
3165 h->seq_number[1] = 0;
3166 obptr += EH_SIZE;
3167 return true;
3168 }
3169
3170 /*
3171 * Add IAC EOR to a buffer.
3172 */
3173 void
net_add_eor(unsigned char * buf,size_t len)3174 net_add_eor(unsigned char *buf, size_t len)
3175 {
3176 buf[len++] = IAC;
3177 buf[len++] = EOR;
3178 }
3179
3180 /*
3181 * net_sendc
3182 * Send a character of user data over the network in NVT mode.
3183 */
3184 void
net_sendc(char c)3185 net_sendc(char c)
3186 {
3187 if (c == '\r' && !linemode
3188 #if defined(LOCAL_PROCESS) /*[*/
3189 && !local_process
3190 #endif /*]*/
3191 ) {
3192 /* CR must be quoted */
3193 net_cookout("\r\0", 2);
3194 } else {
3195 net_cookout(&c, 1);
3196 }
3197 }
3198
3199 /*
3200 * net_sends
3201 * Send a null-terminated string of user data in NVT mode.
3202 */
3203 void
net_sends(const char * s)3204 net_sends(const char *s)
3205 {
3206 net_cookout(s, strlen(s));
3207 }
3208
3209 /*
3210 * External entry points to negotiate line or character mode.
3211 */
3212 void
net_linemode(void)3213 net_linemode(void)
3214 {
3215 if (!CONNECTED) {
3216 return;
3217 }
3218 if (!HOST_FLAG(NO_TELNET_HOST)) {
3219 if (hisopts[TELOPT_ECHO]) {
3220 dont_opt[2] = TELOPT_ECHO;
3221 net_rawout(dont_opt, sizeof(dont_opt));
3222 vtrace("SENT %s %s\n", cmd(DONT), opt(TELOPT_ECHO));
3223 }
3224 if (hisopts[TELOPT_SGA]) {
3225 dont_opt[2] = TELOPT_SGA;
3226 net_rawout(dont_opt, sizeof(dont_opt));
3227 vtrace("SENT %s %s\n", cmd(DONT), opt(TELOPT_SGA));
3228 }
3229 } else {
3230 hisopts[TELOPT_ECHO] = 0;
3231 hisopts[TELOPT_SGA] = 0;
3232 check_linemode(false);
3233 }
3234 }
3235
3236 void
net_charmode(void)3237 net_charmode(void)
3238 {
3239 if (!CONNECTED) {
3240 return;
3241 }
3242 if (!HOST_FLAG(NO_TELNET_HOST)) {
3243 if (!hisopts[TELOPT_ECHO]) {
3244 do_opt[2] = TELOPT_ECHO;
3245 net_rawout(do_opt, sizeof(do_opt));
3246 vtrace("SENT %s %s\n", cmd(DO), opt(TELOPT_ECHO));
3247 }
3248 if (!hisopts[TELOPT_SGA]) {
3249 do_opt[2] = TELOPT_SGA;
3250 net_rawout(do_opt, sizeof(do_opt));
3251 vtrace("SENT %s %s\n", cmd(DO), opt(TELOPT_SGA));
3252 }
3253 } else {
3254 hisopts[TELOPT_ECHO] = 1;
3255 hisopts[TELOPT_SGA] = 1;
3256 check_linemode(false);
3257 }
3258 }
3259
3260 /*
3261 * net_break
3262 * Send telnet break, which is used to implement 3270 ATTN.
3263 *
3264 */
3265 void
net_break(char c)3266 net_break(char c)
3267 {
3268 if (!HOST_FLAG(NO_TELNET_HOST)) {
3269 static unsigned char buf[] = { IAC, BREAK };
3270
3271 /* I don't know if we should first send TELNET synch ? */
3272 net_rawout(buf, sizeof(buf));
3273 vtrace("SENT BREAK\n");
3274 } else if (c != '\0') {
3275 net_rawout((unsigned char *)&c, 1);
3276 }
3277 }
3278
3279 /*
3280 * net_interrupt
3281 * Send telnet IP.
3282 *
3283 */
3284 void
net_interrupt(char c)3285 net_interrupt(char c)
3286 {
3287 if (!HOST_FLAG(NO_TELNET_HOST)) {
3288 static unsigned char buf[] = { IAC, IP };
3289
3290 /* I don't know if we should first send TELNET synch ? */
3291 net_rawout(buf, sizeof(buf));
3292 vtrace("SENT IP\n");
3293 } else if (c != '\0') {
3294 net_rawout((unsigned char *)&c, 1);
3295 }
3296 }
3297
3298 /*
3299 * net_abort
3300 * Send telnet AO.
3301 *
3302 */
3303 void
net_abort(void)3304 net_abort(void)
3305 {
3306 static unsigned char buf[] = { IAC, AO };
3307
3308 if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_SYSREQ)) {
3309 /*
3310 * I'm not sure yet what to do here. Should the host respond
3311 * to the AO by sending us SSCP-LU data (and putting us into
3312 * SSCP-LU mode), or should we put ourselves in it?
3313 * Time, and testers, will tell.
3314 */
3315 switch (tn3270e_submode) {
3316 case E_UNBOUND:
3317 case E_NVT:
3318 break;
3319 case E_SSCP:
3320 net_rawout(buf, sizeof(buf));
3321 vtrace("SENT AO\n");
3322 if (tn3270e_bound || !b8_bit_is_set(&e_funcs,
3323 TN3270E_FUNC_BIND_IMAGE)) {
3324 tn3270e_submode = E_3270;
3325 check_in3270();
3326 }
3327 break;
3328 case E_3270:
3329 net_rawout(buf, sizeof(buf));
3330 vtrace("SENT AO\n");
3331 tn3270e_submode = E_SSCP;
3332 check_in3270();
3333 break;
3334 }
3335 }
3336 }
3337
3338 /*
3339 * Construct a string to reproduce the current TELNET options.
3340 * Returns a bool indicating whether it is necessary.
3341 */
3342 bool
net_snap_options(void)3343 net_snap_options(void)
3344 {
3345 bool any = false;
3346 int i;
3347 static unsigned char ttype_str[] = {
3348 IAC, DO, TELOPT_TTYPE,
3349 IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
3350 };
3351
3352 if (!CONNECTED) {
3353 return false;
3354 }
3355
3356 obptr = obuf;
3357
3358 /* Do TTYPE first. */
3359 if (myopts[TELOPT_TTYPE]) {
3360 unsigned j;
3361
3362 space3270out(sizeof(ttype_str));
3363 for (j = 0; j < sizeof(ttype_str); j++) {
3364 *obptr++ = ttype_str[j];
3365 }
3366 }
3367
3368 /* Do the other options. */
3369 for (i = 0; i < N_OPTS; i++) {
3370 space3270out(6);
3371 if (i == TELOPT_TTYPE) {
3372 continue;
3373 }
3374 if (hisopts[i]) {
3375 *obptr++ = IAC;
3376 *obptr++ = WILL;
3377 *obptr++ = (unsigned char)i;
3378 any = true;
3379 }
3380 if (myopts[i]) {
3381 *obptr++ = IAC;
3382 *obptr++ = DO;
3383 *obptr++ = (unsigned char)i;
3384 any = true;
3385 }
3386 }
3387
3388 /* If we're in TN3270E mode, snap the subnegotations as well. */
3389 if (myopts[TELOPT_TN3270E]) {
3390 any = true;
3391
3392 space3270out(5 +
3393 ((connected_type != NULL)? strlen(connected_type): 0) +
3394 ((connected_lu != NULL)? + strlen(connected_lu): 0) +
3395 2);
3396 *obptr++ = IAC;
3397 *obptr++ = SB;
3398 *obptr++ = TELOPT_TN3270E;
3399 *obptr++ = TN3270E_OP_DEVICE_TYPE;
3400 *obptr++ = TN3270E_OP_IS;
3401 if (connected_type != NULL) {
3402 memcpy(obptr, connected_type, strlen(connected_type));
3403 obptr += strlen(connected_type);
3404 }
3405 if (connected_lu != NULL) {
3406 *obptr++ = TN3270E_OP_CONNECT;
3407 memcpy(obptr, connected_lu, strlen(connected_lu));
3408 obptr += strlen(connected_lu);
3409 }
3410 *obptr++ = IAC;
3411 *obptr++ = SE;
3412
3413 space3270out(38);
3414 memcpy(obptr, functions_req, 4);
3415 obptr += 4;
3416 *obptr++ = TN3270E_OP_IS;
3417 for (i = 0; i < MX8; i++) {
3418 if (b8_bit_is_set(&e_funcs, i)) {
3419 *obptr++ = i;
3420 }
3421 }
3422 *obptr++ = IAC;
3423 *obptr++ = SE;
3424
3425 if (tn3270e_bound) {
3426 tn3270e_header *h;
3427 size_t i;
3428 int xlen = 0;
3429
3430 for (i = 0; i < bind_image_len; i++) {
3431 if (bind_image[i] == 0xff)
3432 xlen++;
3433 }
3434
3435 space3270out(EH_SIZE + bind_image_len + xlen + 3);
3436 h = (tn3270e_header *)obptr;
3437 h->data_type = TN3270E_DT_BIND_IMAGE;
3438 h->request_flag = 0;
3439 h->response_flag = 0;
3440 h->seq_number[0] = 0;
3441 h->seq_number[1] = 0;
3442 obptr += EH_SIZE;
3443 for (i = 0; i < bind_image_len; i++) {
3444 if (bind_image[i] == 0xff) {
3445 *obptr++ = 0xff;
3446 }
3447 *obptr++ = bind_image[i];
3448 }
3449 *obptr++ = IAC;
3450 *obptr++ = EOR;
3451 }
3452 }
3453 return any;
3454 }
3455
3456 /*
3457 * Set blocking/non-blocking mode on the socket. On error, pops up an error
3458 * message, but does not close the socket.
3459 */
3460 static int
non_blocking(bool on)3461 non_blocking(bool on)
3462 {
3463 #if !defined(BLOCKING_CONNECT_ONLY) /*[*/
3464 # if defined(FIONBIO) /*[*/
3465 IOCTL_T i = on? 1: 0;
3466
3467 vtrace("Making host socket %sblocking\n", on? "non-": "");
3468 if (sock == INVALID_SOCKET) {
3469 return 0;
3470 }
3471
3472 if (SOCK_IOCTL(sock, FIONBIO, &i) < 0) {
3473 popup_a_sockerr("ioctl(FIONBIO, %d)", on);
3474 return -1;
3475 }
3476 # else /*][*/
3477 int f;
3478
3479 vtrace("Making host socket %sblocking\n", on? "non-": "");
3480 if (sock == INVALID_SOCKET) {
3481 return 0;
3482 }
3483
3484 if ((f = fcntl(sock, F_GETFL, 0)) == -1) {
3485 connect_errno(errno, "fcntl(F_GETFL)");
3486 return -1;
3487 }
3488 if (on) {
3489 f |= O_NDELAY;
3490 } else {
3491 f &= ~O_NDELAY;
3492 }
3493 if (fcntl(sock, F_SETFL, f) < 0) {
3494 connect_errno(errno, "fcntl(F_SETFL)");
3495 return -1;
3496 }
3497 # endif /*]*/
3498 #endif /*]*/
3499 return 0;
3500 }
3501
3502 /* Continue TLS negotiation in response to a STARTTLS. */
3503 static void
net_starttls_continue(void)3504 net_starttls_continue(void)
3505 {
3506 sio_negotiate_ret_t ret;
3507 bool data = false;
3508 char *session, *cert;
3509
3510 /* Negotiate the session. */
3511 ret = sio_negotiate(sio, sock, hostname, &data);
3512 if (ret == SIG_FAILURE) {
3513 connect_error("%s", sio_last_error());
3514 host_disconnect(true);
3515 return;
3516 }
3517 if (ret == SIG_WANTMORE) {
3518 vtrace("Need more TLS data\n");
3519 if (starttls_pending == NOT_CONNECTED) {
3520 starttls_pending = cstate;
3521 change_cstate(TLS_PENDING, "net_starttls_continue");
3522 }
3523 return;
3524 }
3525
3526 secure_connection = true;
3527
3528 /* Success. */
3529 session = indent_s(sio_session_info(sio));
3530 cert = indent_s(sio_server_cert_info(sio));
3531 vtrace("TLS negotiated connection complete. "
3532 "Connection is now secure.\n"
3533 "Provider: %s\n"
3534 "Session:\n%s\nServer certificate:\n%s\n",
3535 sio_provider(), session, cert);
3536 Free(session);
3537 Free(cert);
3538 st_changed(ST_SECURE, true);
3539
3540 if (starttls_pending == TELNET_PENDING) {
3541 /*
3542 * TLS negotiation happened before 3270 negotiation (which is the usual
3543 * case). Tell the world that we are (still) connected, now in secure
3544 * mode.
3545 */
3546 host_connected();
3547 } else {
3548 /*
3549 * The host negotiated TLS while in some other state. Try to restore
3550 * it.
3551 */
3552 if (cHALF_CONNECTED(starttls_pending)) {
3553 st_changed(ST_NEGOTIATING, true);
3554 } else {
3555 st_changed(ST_3270_MODE, true);
3556 }
3557 }
3558 starttls_pending = NOT_CONNECTED;
3559
3560 if (data) {
3561 /* Got extra data with the negotiation. */
3562 vtrace("Reading extra data after negotiation\n");
3563 net_input(INVALID_IOSRC, NULL_IOID);
3564 }
3565 }
3566
3567 /* Process a STARTTLS subnegotiation. */
3568 static void
continue_tls(unsigned char * sbbuf,int len)3569 continue_tls(unsigned char *sbbuf, int len)
3570 {
3571 /* Whatever happens, we're not expecting another SB STARTTLS. */
3572 need_tls_follows = false;
3573
3574 /* Make sure the option is FOLLOWS. */
3575 if (len < 2 || sbbuf[1] != TLS_FOLLOWS) {
3576 /* Trace the junk. */
3577 vtrace("%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3578 connect_error("TLS negotiation failure");
3579 host_disconnect(true);
3580 return;
3581 }
3582
3583 /* Trace what we got. */
3584 vtrace("%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3585
3586 /* Negotiate. */
3587 net_starttls_continue();
3588 }
3589
3590 /* Return the current BIND application name, if any. */
3591 const char *
net_query_bind_plu_name(void)3592 net_query_bind_plu_name(void)
3593 {
3594 /*
3595 * Return the PLU name, if we're in TN3270E 3270 mode and have
3596 * negotiated the BIND-IMAGE option.
3597 */
3598 if ((cstate == CONNECTED_TN3270E) &&
3599 b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
3600 return plu_name? plu_name: "";
3601 } else {
3602 return "";
3603 }
3604 }
3605
3606 /* Return the current connection state. */
3607 const char *
net_query_connection_state(void)3608 net_query_connection_state(void)
3609 {
3610 return state_name[cstate];
3611 }
3612
3613 /* Return the LU name. */
3614 const char *
net_query_lu_name(void)3615 net_query_lu_name(void)
3616 {
3617 if (CONNECTED && connected_lu != NULL) {
3618 return connected_lu;
3619 } else {
3620 return "";
3621 }
3622 }
3623
3624 /* Return the hostname and port. */
3625 const char *
net_query_host(void)3626 net_query_host(void)
3627 {
3628 if (CONNECTED) {
3629 #if defined(LOCAL_PROCESS) /*[*/
3630 if (local_process) {
3631 return lazyaf("process %s", hostname);
3632 }
3633 #endif /*]*/
3634 return lazyaf("host %s %u", hostname, current_port);
3635 } else {
3636 return "";
3637 }
3638 }
3639
3640 /* Return the TLS state. */
3641 const char *
net_query_tls(void)3642 net_query_tls(void)
3643 {
3644 static char *not_secure = "not secure";
3645
3646 if (CONNECTED) {
3647 if (!secure_connection) {
3648 return not_secure;
3649 }
3650 return lazyaf("secure %s",
3651 net_secure_unverified()? "host-unverified": "host-verified");
3652 } else {
3653 return "";
3654 }
3655 }
3656
3657 /* Return the local address for the socket. */
3658 int
net_getsockname(void * buf,int * len)3659 net_getsockname(void *buf, int *len)
3660 {
3661 if (sock == INVALID_SOCKET) {
3662 return -1;
3663 }
3664 return getsockname(sock, buf, (socklen_t *)(void *)len);
3665 }
3666
3667 /* Return a text version of the current proxy type, or NULL. */
3668 const char *
net_proxy_type(void)3669 net_proxy_type(void)
3670 {
3671 if (proxy_type != PT_NONE) {
3672 return proxy_type_name(proxy_type);
3673 } else {
3674 return NULL;
3675 }
3676 }
3677
3678 /* Return the current proxy user, or NULL. */
3679 const char *
net_proxy_user(void)3680 net_proxy_user(void)
3681 {
3682 if (proxy_type != PT_NONE) {
3683 return proxy_user;
3684 } else {
3685 return NULL;
3686 }
3687 }
3688
3689 /* Return the current proxy host, or NULL. */
3690 const char *
net_proxy_host(void)3691 net_proxy_host(void)
3692 {
3693 if (proxy_type != PT_NONE) {
3694 return proxy_host;
3695 } else {
3696 return NULL;
3697 }
3698 }
3699
3700 /* Return the current proxy port, or NULL. */
3701 const char *
net_proxy_port(void)3702 net_proxy_port(void)
3703 {
3704 if (proxy_type != PT_NONE) {
3705 return proxy_portname;
3706 } else {
3707 return NULL;
3708 }
3709 }
3710
3711 /* Return the SNA binding state. */
3712 bool
net_bound(void)3713 net_bound(void)
3714 {
3715 return (IN_E && tn3270e_bound);
3716 }
3717
3718 /* Format TELNET options. */
3719 static const char *
net_opts(unsigned char opts[])3720 net_opts(unsigned char opts[])
3721 {
3722 int i;
3723 char *ret = NULL;
3724 size_t sl = 0;
3725
3726 for (i = 0; i < N_OPTS; i++) {
3727 if (opts[i]) {
3728 const char *o = opt(i);
3729
3730 ret = (char *)Realloc(ret, sl + 1 + strlen(o) + 1);
3731 if (sl) {
3732 ret[sl++] = ' ';
3733 }
3734 strcpy(ret + sl, o);
3735 sl += strlen(o);
3736 }
3737 }
3738 return ret;
3739 }
3740
3741 /* Return my TELNET options. */
3742 const char *
net_myopts(void)3743 net_myopts(void)
3744 {
3745 return net_opts(myopts);
3746 }
3747
3748 /* Return his TELNET options. */
3749 const char *
net_hisopts(void)3750 net_hisopts(void)
3751 {
3752 return net_opts(hisopts);
3753 }
3754
3755 /*
3756 * Set the default termtype.
3757 *
3758 * This is called at init time, whenever we disconnect, and whenever the screen
3759 * dimensions change (which by definition happens while we are disconnected).
3760 * It sets 'termtype' to the default value, assuming an extended data stream
3761 * host. When we connect to a particular host, we may use a different value
3762 * (such as without the -E, for the S: prefix).
3763 */
3764 void
net_set_default_termtype(void)3765 net_set_default_termtype(void)
3766 {
3767 if (appres.termname) {
3768 termtype = appres.termname;
3769 } else if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
3770 termtype = "xterm";
3771 } else if (ov_rows || ov_cols) {
3772 termtype = "IBM-DYNAMIC";
3773 } else if (HOST_FLAG(STD_DS_HOST)) {
3774 snprintf(ttype_tmpval, sizeof(ttype_tmpval), "IBM-327%c-%d",
3775 mode.m3279? '9': '8', model_num);
3776 termtype = ttype_tmpval;
3777 } else {
3778 termtype = full_model_name;
3779 }
3780
3781 st_changed(ST_TERMINAL_NAME, true);
3782 }
3783
3784 /* Handle an ST_REMODEL indication. */
3785 static void
net_remodel(bool ignored _is_unused)3786 net_remodel(bool ignored _is_unused)
3787 {
3788 net_set_default_termtype();
3789 }
3790
3791 bool
net_secure_unverified(void)3792 net_secure_unverified(void)
3793 {
3794 return secure_connection && sio_secure_unverified(sio);
3795 }
3796
3797 const char *
net_session_info(void)3798 net_session_info(void)
3799 {
3800 if (sio == NULL) {
3801 return NULL;
3802 }
3803 return sio_session_info(sio);
3804 }
3805
3806 const char *
net_server_cert_info(void)3807 net_server_cert_info(void)
3808 {
3809 if (sio == NULL) {
3810 return NULL;
3811 }
3812 return sio_server_cert_info(sio);
3813 }
3814
3815 bool
net_secure_connection(void)3816 net_secure_connection(void)
3817 {
3818 return secure_connection;
3819 }
3820
3821 unsigned
net_sio_supported(void)3822 net_sio_supported(void)
3823 {
3824 return sio_supported();
3825 }
3826
3827 const char *
net_sio_provider(void)3828 net_sio_provider(void)
3829 {
3830 return sio_provider();
3831 }
3832
3833 /*
3834 * Change the NOP transmit interval.
3835 */
3836 void
net_nop_seconds(void)3837 net_nop_seconds(void)
3838 {
3839 /* Cancel first. */
3840 if (nop_timeout_id != NULL_IOID) {
3841 RemoveTimeOut(nop_timeout_id);
3842 nop_timeout_id = NULL_IOID;
3843 }
3844
3845 if (appres.nop_seconds == 0) {
3846 return;
3847 }
3848
3849 /* Restart with the new interval. */
3850 if (cstate >= TELNET_PENDING) {
3851 nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
3852 }
3853 }
3854
3855 /* Break NVT data tracing. */
3856 void
net_nvt_break(void)3857 net_nvt_break(void)
3858 {
3859 if (nvt_data) {
3860 vtrace("\n");
3861 nvt_data = 0;
3862 }
3863 }
3864
3865 /* Module registration. */
3866 void
net_register(void)3867 net_register(void)
3868 {
3869 /* Register for state changes. */
3870 register_schange(ST_REMODEL, net_remodel);
3871 }
3872