1 /* TN5250 - An implementation of the 5250 telnet protocol.
2 * Copyright (C) 2001-2008 Scott Klement
3 *
4 * parts of this were copied from telnetstr.c which is (C) 1997 Michael Madore
5 *
6 * This file is part of TN5250.
7 *
8 * TN5250 is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1, or (at your option)
11 * any later version.
12 *
13 * TN5250 is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this software; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 *
23 */
24
25 #include "tn5250-private.h"
26
27 #ifdef HAVE_LIBSSL
28
29 #include <openssl/ssl.h>
30 #include <openssl/err.h>
31 #include <time.h>
32
33 static int ssl_stream_get_next(Tn5250Stream *This,unsigned char *buf,int size);
34 static void ssl_stream_do_verb(Tn5250Stream * This, unsigned char verb, unsigned char what);
35 static int ssl_stream_host_verb(Tn5250Stream * This, unsigned char verb,
36 unsigned char what);
37 static void ssl_stream_sb_var_value(Tn5250Buffer * buf, unsigned char *var, unsigned char *value);
38 static void ssl_stream_sb(Tn5250Stream * This, unsigned char *sb_buf, int sb_len);
39 static void ssl_stream_escape(Tn5250Buffer * buffer);
40 static void ssl_stream_write(Tn5250Stream * This, unsigned char *data, int size);
41 static int ssl_stream_get_byte(Tn5250Stream * This);
42
43 static int ssl_stream_connect(Tn5250Stream * This, const char *to);
44 static int ssl_stream_accept(Tn5250Stream * This, SOCKET_TYPE masterSock);
45 static void ssl_stream_destroy(Tn5250Stream *This);
46 static void ssl_stream_disconnect(Tn5250Stream * This);
47 static int ssl_stream_handle_receive(Tn5250Stream * This);
48 static void ssl_stream_send_packet(Tn5250Stream * This, int length,
49 StreamHeader header,
50 unsigned char *data);
51 static void tn3270_ssl_stream_send_packet(Tn5250Stream * This, int length,
52 StreamHeader header,
53 unsigned char * data);
54 int ssl_stream_passwd_cb(char *buf, int size, int rwflag, Tn5250Stream *This);
55 X509 *ssl_stream_load_cert(Tn5250Stream *This, const char *file);
56
57
58 #define SEND 1
59 #define IS 0
60 #define INFO 2
61 #define VALUE 1
62 #define VAR 0
63 #define VALUE 1
64 #define USERVAR 3
65
66 #define TERMINAL 1
67 #define BINARY 2
68 #define RECORD 4
69 #define DONE 7
70 #define HOST 8
71
72 #define TRANSMIT_BINARY 0
73 #define END_OF_RECORD 25
74 #define TERMINAL_TYPE 24
75 #define TIMING_MARK 6
76 #define NEW_ENVIRON 39
77
78 #define TN3270E 40
79
80 /* Sub-Options for TN3270E negotiation */
81 #define TN3270E_ASSOCIATE 0
82 #define TN3270E_CONNECT 1
83 #define TN3270E_DEVICE_TYPE 2
84 #define TN3270E_FUNCTIONS 3
85 #define TN3270E_IS 4
86 #define TN3270E_REASON 5
87 #define TN3270E_REJECT 6
88 #define TN3270E_REQUEST 7
89 #define TN3270E_SEND 8
90
91 /* Reason codes for TN3270E negotiation */
92 #define TN3270E_CONN_PARTNER 0
93 #define TN3270E_DEVICE_IN_USE 1
94 #define TN3270E_INV_ASSOCIATE 2
95 #define TN3270E_INV_NAME 3
96 #define TN3270E_INV_DEVICE_TYPE 4
97 #define TN3270E_TYPE_NAME_ERROR 5
98 #define TN3270E_UNKNOWN_ERROR 6
99 #define TN3270E_UNSUPPORTED_REQ 7
100
101 /* Function names for TN3270E FUNCTIONS sub-option */
102 #define TN3270E_BIND_IMAGE 0
103 #define TN3270E_DATA_STREAM_CTL 1
104 #define TN3270E_RESPONSES 2
105 #define TN3270E_SCS_CTL_CODES 3
106 #define TN3270E_SYSREQ 4
107
108 #define EOR 239
109 #define SE 240
110 #define SB 250
111 #define WILL 251
112 #define WONT 252
113 #define DO 253
114 #define DONT 254
115 #define IAC 255
116
117 #define TN5250_STREAM_STATE_NO_DATA 0 /* Dummy state */
118 #define TN5250_STREAM_STATE_DATA 1
119 #define TN5250_STREAM_STATE_HAVE_IAC 2
120 #define TN5250_STREAM_STATE_HAVE_VERB 3 /* e.g. DO, DONT, WILL, WONT */
121 #define TN5250_STREAM_STATE_HAVE_SB 4 /* SB data */
122 #define TN5250_STREAM_STATE_HAVE_SB_IAC 5
123
124 /* Internal Telnet option settings (bit-wise flags) */
125 #define RECV_BINARY 1
126 #define SEND_BINARY 2
127 #define RECV_EOR 4
128 #define SEND_EOR 8
129
130 #ifndef HAVE_UCHAR
131 typedef unsigned char UCHAR;
132 #endif
133
134 static const UCHAR hostInitStr[] = {IAC,DO,NEW_ENVIRON,IAC,DO,TERMINAL_TYPE};
135 static const UCHAR hostDoEOR[] = {IAC,DO,END_OF_RECORD};
136 static const UCHAR hostDoBinary[] = {IAC,DO,TRANSMIT_BINARY};
137 static const UCHAR hostDoTN3270E[] = {IAC,DO,TN3270E};
138 static const UCHAR hostSBDevice[] = {IAC,SB,TN3270E,TN3270E_SEND,TN3270E_DEVICE_TYPE,
139 IAC,SE};
140 typedef struct doTable_t {
141 const UCHAR *cmd;
142 unsigned len;
143 } DOTABLE;
144
145 static const DOTABLE host5250DoTable[] = {
146 hostInitStr, sizeof(hostInitStr),
147 hostDoEOR, sizeof(hostDoEOR),
148 hostDoBinary, sizeof(hostDoBinary),
149 NULL, 0
150 };
151
152 static const DOTABLE host3270DoTable[] = {
153 hostInitStr, sizeof(hostInitStr),
154 hostDoEOR, sizeof(hostDoEOR),
155 hostDoBinary, sizeof(hostDoBinary),
156 NULL, 0
157 };
158
159 static const UCHAR SB_Str_NewEnv[]={IAC, SB, NEW_ENVIRON, SEND, USERVAR,
160 'I','B','M','R','S','E','E','D', 0,1,2,3,4,5,6,7,
161 VAR, USERVAR, IAC, SE};
162 static const UCHAR SB_Str_TermType[]={IAC, SB, TERMINAL_TYPE, SEND, IAC, SE};
163
164 /* FIXME: This should be added to Tn5250Stream structure, or something
165 else better than this :) */
166 int errnum;
167
168 #ifdef NDEBUG
169 #define IACVERB_LOG(tag,verb,what)
170 #define TNSB_LOG(sb_buf,sb_len)
171 #define LOGERROR(tag, ecode)
172 #define DUMP_ERR_STACK()
173 #else
174 #define IACVERB_LOG ssl_log_IAC_verb
175 #define TNSB_LOG ssl_log_SB_buf
176 #define LOGERROR ssl_logError
177 #define DUMP_ERR_STACK ssl_log_error_stack
178
ssl_getTelOpt(what)179 static char *ssl_getTelOpt(what)
180 {
181 char *wcp;
182 static char wbuf[12];
183
184 switch (what) {
185 case TERMINAL_TYPE:
186 wcp = "<TERMTYPE>";
187 break;
188 case END_OF_RECORD:
189 wcp = "<END_OF_REC>";
190 break;
191 case TRANSMIT_BINARY:
192 wcp = "<BINARY>";
193 break;
194 case NEW_ENVIRON:
195 wcp = "<NEWENV>";
196 break;
197 case EOR:
198 wcp = "<EOR>";
199 break;
200 default:
201 snprintf(wcp=wbuf, sizeof(wbuf), "<%02X>", what);
202 break;
203 }
204 return wcp;
205 }
206
ssl_log_error_stack(void)207 static void ssl_log_error_stack(void)
208 {
209 FILE *errfp = tn5250_logfile ? tn5250_logfile : stderr;
210
211 ERR_print_errors_fp(errfp);
212 }
213
ssl_logError(char * tag,int ecode)214 static void ssl_logError(char *tag, int ecode)
215 {
216 FILE *errfp = tn5250_logfile ? tn5250_logfile : stderr;
217
218 fprintf(errfp,"%s: ERROR (code=%d) - %s\n", tag, ecode, strerror(ecode));
219 }
220
ssl_log_IAC_verb(char * tag,int verb,int what)221 static void ssl_log_IAC_verb(char *tag, int verb, int what)
222 {
223 char *vcp, vbuf[10];
224
225 if (!tn5250_logfile)
226 return;
227 switch (verb) {
228 case DO: vcp = "<DO>";
229 break;
230 case DONT:
231 vcp = "<DONT>";
232 break;
233 case WILL:
234 vcp = "<WILL>";
235 break;
236 case WONT:
237 vcp = "<WONT>";
238 break;
239 default:
240 sprintf(vcp=vbuf, "<%02X>", verb);
241 break;
242 }
243 fprintf(tn5250_logfile,"%s:<IAC>%s%s\n", tag, vcp, ssl_getTelOpt(what));
244 }
245
ssl_dumpVarVal(UCHAR * buf,int len)246 static int ssl_dumpVarVal(UCHAR *buf, int len)
247 {
248 int c, i;
249
250 for (c=buf[i=0]; i<len && c!=VAR && c!=VALUE && c!=USERVAR; c=buf[++i]) {
251 if (isprint(c))
252 putc(c, tn5250_logfile);
253 else
254 fprintf(tn5250_logfile,"<%02X>", c);
255 }
256 return i;
257 }
258
ssl_dumpNewEnv(unsigned char * buf,int len)259 static int ssl_dumpNewEnv(unsigned char *buf, int len)
260 {
261 int c, i=0, j;
262
263 while (i<len) {
264 switch (c=buf[i]) {
265 case IAC:
266 return i;
267 case VAR:
268 fputs("\n\t<VAR>",tn5250_logfile);
269 if (++i<len && buf[i]==USERVAR) {
270 fputs("<USERVAR>",tn5250_logfile);
271 return i+1;
272 }
273 j = ssl_dumpVarVal(buf+i, len-i);
274 i += j;
275 case USERVAR:
276 fputs("\n\t<USERVAR>",tn5250_logfile);
277 if (!memcmp("IBMRSEED", &buf[++i], 8)) {
278 fputs("IBMRSEED",tn5250_logfile);
279 putc('<',tn5250_logfile);
280 for (j=0, i+=8; j<8; i++, j++) {
281 if (j)
282 putc(' ',tn5250_logfile);
283 fprintf(tn5250_logfile,"%02X",buf[i]);
284 }
285 putc('>',tn5250_logfile);
286 } else {
287 j = ssl_dumpVarVal(buf+i, len-i);
288 i += j;
289 }
290 break;
291 case VALUE:
292 fputs("<VALUE>",tn5250_logfile);
293 i++;
294 j = ssl_dumpVarVal(buf+i, len-i);
295 i += j;
296 break;
297 default:
298 fputs(ssl_getTelOpt(c),tn5250_logfile);
299 } /* switch */
300 } /* while */
301 return i;
302 }
303
ssl_log_SB_buf(unsigned char * buf,int len)304 static void ssl_log_SB_buf(unsigned char *buf, int len)
305 {
306 int c, i, type;
307
308 if (!tn5250_logfile)
309 return;
310 fprintf(tn5250_logfile,ssl_getTelOpt(type=*buf++));
311 switch (c=*buf++) {
312 case IS:
313 fputs("<IS>",tn5250_logfile);
314 break;
315 case SEND:
316 fputs("<SEND>",tn5250_logfile);
317 break;
318 default:
319 fputs(ssl_getTelOpt(c),tn5250_logfile);
320 }
321 len -= 2;
322 i = (type==NEW_ENVIRON) ? ssl_dumpNewEnv(buf,len) : 0;
323 while (i<len) {
324 switch(c=buf[i++]) {
325 case IAC:
326 fputs("<IAC>",tn5250_logfile);
327 if (i<len)
328 fputs(ssl_getTelOpt(buf[i++]), tn5250_logfile);
329 break;
330 default:
331 if (isprint(c))
332 putc(c, tn5250_logfile);
333 else
334 fprintf(tn5250_logfile,"<%02X>", c);
335 }
336 }
337 }
338 #endif /* !NDEBUG */
339
340 /****f* lib5250/tn5250_ssl_stream_init
341 * NAME
342 * tn5250_ssl_stream_init
343 * SYNOPSIS
344 * ret = tn5250_ssl_stream_init (This);
345 * INPUTS
346 * Tn5250Stream * This -
347 * DESCRIPTION
348 * DOCUMENT ME!!!
349 *****/
tn5250_ssl_stream_init(Tn5250Stream * This)350 int tn5250_ssl_stream_init (Tn5250Stream *This)
351 {
352 int len;
353 char methstr[5];
354 SSL_METHOD *meth=NULL;
355
356 TN5250_LOG(("tn5250_ssl_stream_init() entered.\n"));
357
358 /* initialize SSL library */
359
360 SSL_load_error_strings();
361 SSL_library_init();
362
363 /* which SSL method do we use? */
364
365 strcpy(methstr,"auto");
366 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_method")) {
367 strncpy(methstr, tn5250_config_get (This->config, "ssl_method"), 4);
368 methstr[4] = '\0';
369 }
370
371 #ifndef OPENSSL_NO_SSL2
372 if (!strcmp(methstr, "ssl2")) {
373 meth = SSLv2_client_method();
374 TN5250_LOG(("SSL Method = SSLv2_client_method()\n"));
375 } else
376 #endif
377 #ifndef OPENSSL_NO_SSL3
378 if (!strcmp(methstr, "ssl3")) {
379 meth = SSLv3_client_method();
380 TN5250_LOG(("SSL Method = SSLv3_client_method()\n"));
381 } else
382 #endif
383 {
384 meth = SSLv23_client_method();
385 TN5250_LOG(("SSL Method = SSLv23_client_method()\n"));
386 }
387
388 /* create a new SSL context */
389
390 This->ssl_context = SSL_CTX_new(meth);
391 if (This->ssl_context==NULL) {
392 DUMP_ERR_STACK ();
393 return -1;
394 }
395
396 /* if a certificate authority file is defined, load it into this context */
397
398 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_ca_file")) {
399 if (SSL_CTX_load_verify_locations(This->ssl_context,
400 tn5250_config_get (This->config, "ssl_ca_file"), NULL)<1) {
401 DUMP_ERR_STACK ();
402 return -1;
403 }
404 }
405
406 This->userdata = NULL;
407
408 /* if a PEM passphrase is defined, set things up so that it can be used */
409
410 if (This->config!=NULL && tn5250_config_get (This->config,"ssl_pem_pass")){
411 TN5250_LOG(("SSL: Setting password callback\n"));
412 len = strlen(tn5250_config_get (This->config, "ssl_pem_pass"));
413 This->userdata = malloc(len+1);
414 strncpy(This->userdata,
415 tn5250_config_get (This->config, "ssl_pem_pass"), len);
416 SSL_CTX_set_default_passwd_cb(This->ssl_context,
417 (pem_password_cb *)ssl_stream_passwd_cb);
418 SSL_CTX_set_default_passwd_cb_userdata(This->ssl_context, (void *)This);
419
420 }
421
422 /* If a certificate file has been defined, load it into this context as well */
423
424 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_cert_file")){
425
426 if ( tn5250_config_get (This->config, "ssl_check_exp") ) {
427 X509 *client_cert;
428 time_t tnow;
429 int extra_time;
430 TN5250_LOG(("SSL: Checking expiration of client cert\n"));
431 client_cert = ssl_stream_load_cert(This,
432 tn5250_config_get (This->config, "ssl_cert_file"));
433 if (client_cert == NULL) {
434 TN5250_LOG(("SSL: Unable to load client certificate!\n"));
435 return -1;
436 }
437 extra_time = tn5250_config_get_int(This->config, "ssl_check_exp");
438 tnow = time(NULL) + extra_time;
439 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(client_cert), tnow)
440 == -1 ) {
441 if (extra_time > 1) {
442 printf("SSL error: client certificate will be expired\n");
443 TN5250_LOG(("SSL: client certificate will be expired\n"));
444 } else {
445 printf("SSL error: client certificate has expired\n");
446 TN5250_LOG(("SSL: client certificate has expired\n"));
447 }
448 return -1;
449 }
450 X509_free(client_cert);
451 }
452
453 TN5250_LOG(("SSL: Loading certificates from certificate file\n"));
454 if (SSL_CTX_use_certificate_file(This->ssl_context,
455 tn5250_config_get (This->config, "ssl_cert_file"),
456 SSL_FILETYPE_PEM) <= 0) {
457 DUMP_ERR_STACK ();
458 return -1;
459 }
460 TN5250_LOG(("SSL: Loading private keys from certificate file\n"));
461 if (SSL_CTX_use_PrivateKey_file(This->ssl_context,
462 tn5250_config_get (This->config, "ssl_cert_file"),
463 SSL_FILETYPE_PEM) <= 0) {
464 DUMP_ERR_STACK ();
465 return -1;
466 }
467 }
468
469 This->ssl_handle = NULL;
470
471 This->connect = ssl_stream_connect;
472 This->accept = ssl_stream_accept;
473 This->disconnect = ssl_stream_disconnect;
474 This->handle_receive = ssl_stream_handle_receive;
475 This->send_packet = ssl_stream_send_packet;
476 This->destroy = ssl_stream_destroy;
477 This->streamtype = TN5250_STREAM;
478 TN5250_LOG(("tn5250_ssl_stream_init() success.\n"));
479 return 0; /* Ok */
480 }
481
482 /****f* lib5250/tn3270_ssl_stream_init
483 * NAME
484 * tn3270_ssl_stream_init
485 * SYNOPSIS
486 * ret = tn3270_ssl_stream_init (This);
487 * INPUTS
488 * Tn5250Stream * This -
489 * DESCRIPTION
490 * DOCUMENT ME!!!
491 *****/
tn3270_ssl_stream_init(Tn5250Stream * This)492 int tn3270_ssl_stream_init (Tn5250Stream *This)
493 {
494 int len;
495
496 /* initialize SSL library */
497
498 SSL_load_error_strings();
499 SSL_library_init();
500
501 /* create a new SSL context */
502
503 This->ssl_context = SSL_CTX_new(SSLv23_client_method());
504 if (This->ssl_context==NULL) {
505 DUMP_ERR_STACK ();
506 return -1;
507 }
508
509 /* if a certificate authority file is defined, load it into this context */
510
511 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_ca_file")) {
512 if (SSL_CTX_load_verify_locations(This->ssl_context,
513 tn5250_config_get (This->config, "ssl_ca_file"), NULL)<1) {
514 DUMP_ERR_STACK ();
515 return -1;
516 }
517 }
518
519 /* if a certificate authority file is defined, load it into this context */
520
521 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_ca_file")) {
522 if (SSL_CTX_load_verify_locations(This->ssl_context,
523 tn5250_config_get (This->config, "ssl_ca_file"), NULL)<1) {
524 DUMP_ERR_STACK ();
525 return -1;
526 }
527 }
528
529 This->userdata = NULL;
530
531 /* if a PEM passphrase is defined, set things up so that it can be used */
532
533 if (This->config!=NULL && tn5250_config_get (This->config,"ssl_pem_pass")){
534 TN5250_LOG(("SSL: Setting password callback\n"));
535 len = strlen(tn5250_config_get (This->config, "ssl_pem_pass"));
536 This->userdata = malloc(len+1);
537 strncpy(This->userdata,
538 tn5250_config_get (This->config, "ssl_pem_pass"), len);
539 SSL_CTX_set_default_passwd_cb(This->ssl_context,
540 (pem_password_cb *)ssl_stream_passwd_cb);
541 SSL_CTX_set_default_passwd_cb_userdata(This->ssl_context, (void *)This);
542
543 }
544
545 /* If a certificate file has been defined, load it into this context as well */
546
547 if (This->config!=NULL && tn5250_config_get (This->config, "ssl_cert_file")){
548 TN5250_LOG(("SSL: Loading certificates from certificate file\n"));
549 if (SSL_CTX_use_certificate_file(This->ssl_context,
550 tn5250_config_get (This->config, "ssl_cert_file"),
551 SSL_FILETYPE_PEM) <= 0) {
552 DUMP_ERR_STACK ();
553 return -1;
554 }
555 TN5250_LOG(("SSL: Loading private keys from certificate file\n"));
556 if (SSL_CTX_use_PrivateKey_file(This->ssl_context,
557 tn5250_config_get (This->config, "ssl_cert_file"),
558 SSL_FILETYPE_PEM) <= 0) {
559 DUMP_ERR_STACK ();
560 return -1;
561 }
562 }
563
564 This->ssl_handle = NULL;
565 This->connect = ssl_stream_connect;
566 This->accept = ssl_stream_accept;
567 This->disconnect = ssl_stream_disconnect;
568 This->handle_receive = ssl_stream_handle_receive;
569 This->send_packet = tn3270_ssl_stream_send_packet;
570 This->destroy = ssl_stream_destroy;
571 This->streamtype = TN3270E_STREAM;
572 return 0; /* Ok */
573 }
574
575 /****i* lib5250/ssl_stream_connect
576 * NAME
577 * ssl_stream_connect
578 * SYNOPSIS
579 * ret = ssl_stream_connect (This, to);
580 * INPUTS
581 * Tn5250Stream * This -
582 * const char * to -
583 * DESCRIPTION
584 * Connects to server. The `to' parameter is in the form
585 * host[:port].
586 *****/
ssl_stream_connect(Tn5250Stream * This,const char * to)587 static int ssl_stream_connect(Tn5250Stream * This, const char *to)
588 {
589 struct sockaddr_in serv_addr;
590 u_long ioctlarg = 1;
591 char *address;
592 int r;
593 X509 *server_cert;
594 long certvfy;
595
596 TN5250_LOG(("tn5250_ssl_stream_connect() entered.\n"));
597
598 memset((char *) &serv_addr, 0, sizeof(serv_addr));
599 serv_addr.sin_family = AF_INET;
600
601 /* Figure out the internet address. */
602 address = (char *)malloc (strlen (to)+1);
603 strcpy (address, to);
604 if (strchr (address, ':'))
605 *strchr (address, ':') = '\0';
606
607 serv_addr.sin_addr.s_addr = inet_addr(address);
608 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
609 struct hostent *pent = gethostbyname(address);
610 if (pent != NULL)
611 serv_addr.sin_addr.s_addr = *((u_long *) (pent->h_addr));
612 }
613 free (address);
614 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
615 TN5250_LOG(("sslstream: Host lookup failed!\n"));
616 return -1;
617 }
618
619 /* Figure out the port name. */
620 if (strchr (to, ':') != NULL) {
621 const char *port = strchr (to, ':') + 1;
622 serv_addr.sin_port = htons((u_short) atoi(port));
623 if (serv_addr.sin_port == 0) {
624 struct servent *pent = getservbyname(port, "tcp");
625 if (pent != NULL)
626 serv_addr.sin_port = pent->s_port;
627 }
628 if (serv_addr.sin_port == 0) {
629 TN5250_LOG(("sslstream: Port lookup failed!\n"));
630 return -1;
631 }
632 } else {
633 /* No port specified ... use telnet-ssl port. */
634 struct servent *pent = getservbyname ("telnets", "tcp");
635 if (pent == NULL)
636 serv_addr.sin_port = htons(992);
637 else
638 serv_addr.sin_port = pent->s_port;
639 }
640
641 This->ssl_handle = SSL_new(This->ssl_context);
642 if (This->ssl_handle==NULL) {
643 DUMP_ERR_STACK ();
644 TN5250_LOG(("sslstream: SSL_new() failed!\n"));
645 return -1;
646 }
647
648 This->sockfd = socket(AF_INET, SOCK_STREAM, 0);
649 if (WAS_INVAL_SOCK(This->sockfd)) {
650 TN5250_LOG(("sslstream: socket() failed, errno=%d\n", errno));
651 return -1;
652 }
653
654 if ((r=SSL_set_fd(This->ssl_handle, This->sockfd))==0) {
655 errnum = SSL_get_error(This->ssl_handle, r);
656 DUMP_ERR_STACK ();
657 TN5250_LOG(("sslstream: SSL_set_fd() failed, errnum=%d\n", errnum));
658 return errnum;
659 }
660
661 r = connect(This->sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
662 if (WAS_ERROR_RET(r)) {
663 TN5250_LOG(("sslstream: connect() failed, errno=%d\n", errno));
664 return -1;
665 }
666
667 if ((r=SSL_connect(This->ssl_handle)<1)) {
668 errnum = SSL_get_error(This->ssl_handle, r);
669 DUMP_ERR_STACK ();
670 TN5250_LOG(("sslstream: SSL_connect() failed, errnum=%d\n", errnum));
671 return errnum;
672 }
673
674 TN5250_LOG(("Connected with SSL\n"));
675 TN5250_LOG(("Using %s cipher with a %d bit secret key\n",
676 SSL_get_cipher_name(This->ssl_handle),
677 SSL_get_cipher_bits(This->ssl_handle, NULL) ));
678
679 server_cert = SSL_get_peer_certificate (This->ssl_handle);
680
681 if (server_cert == NULL) {
682 TN5250_LOG(("sslstream: Server did not present a certificate!\n"));
683 return -1;
684 }
685 else {
686 time_t tnow = time(NULL);
687 int extra_time= 0;
688 if (This->config!=NULL &&
689 tn5250_config_get(This->config, "ssl_check_exp")!=NULL) {
690 extra_time = tn5250_config_get_int(This->config,
691 "ssl_check_exp");
692 tnow += extra_time;
693 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(server_cert), tnow)
694 == -1 ) {
695 if (extra_time > 1) {
696 printf("SSL error: server certificate will be expired\n");
697 TN5250_LOG(("SSL: server certificate will be expired\n"));
698 } else {
699 printf("SSL error: server certificate has expired\n");
700 TN5250_LOG(("SSL: server certificate has expired\n"));
701 }
702 return -1;
703 }
704 }
705 TN5250_LOG(("SSL Certificate issued by: %s\n",
706 X509_NAME_oneline(X509_get_issuer_name(server_cert), 0,0) ));
707 certvfy = SSL_get_verify_result(This->ssl_handle);
708 if (certvfy == X509_V_OK) {
709 TN5250_LOG(("SSL Certificate successfully verified!\n"));
710 } else {
711 TN5250_LOG(("SSL Certificate verification failed, reason: %d\n",
712 certvfy));
713 if (This->config!=NULL &&
714 tn5250_config_get_bool (This->config, "ssl_verify_server"))
715 return -1;
716 }
717 }
718
719 /* Set socket to non-blocking mode. */
720 TN5250_LOG(("SSL must be Non-Blocking\n"));
721 TN_IOCTL(This->sockfd, FIONBIO, &ioctlarg);
722
723 This->state = TN5250_STREAM_STATE_DATA;
724 TN5250_LOG(("tn5250_ssl_stream_connect() success.\n"));
725 return 0;
726 }
727
728 /****i* lib5250/ssl_stream_accept
729 * NAME
730 * ssl_stream_accept
731 * SYNOPSIS
732 * ret = ssl_stream_accept (This, masterSock);
733 * INPUTS
734 * Tn5250Stream * This -
735 * SOCKET masterSock -
736 * DESCRIPTION
737 * Accepts a connection from the client.
738 *****/
ssl_stream_accept(Tn5250Stream * This,SOCKET_TYPE masterfd)739 static int ssl_stream_accept(Tn5250Stream * This, SOCKET_TYPE masterfd)
740 {
741 int i, len, retCode;
742 struct sockaddr_in serv_addr;
743 fd_set fdr;
744 struct timeval tv;
745 int negotiating;
746
747 #ifndef WINELIB
748 u_long ioctlarg=1L;
749 #endif
750
751 /* FIXME: This routine needs to be converted to use SSL calls
752 I just left it disabled for now. -- SCK */
753
754 #if 0
755 /*
756 len = sizeof(serv_addr);
757 This->sockfd = accept(masterSock, (struct sockaddr *) &serv_addr, &len);
758 if (WAS_INVAL_SOCK(This->sockfd)) {
759 return -1;
760 }
761 */
762 printf("This->sockfd = %d\n", masterfd);
763 This->sockfd = masterfd;
764
765 /* Set socket to non-blocking mode. */
766 TN_IOCTL(This->sockfd, FIONBIO, &ioctlarg);
767
768 This->state = TN5250_STREAM_STATE_DATA;
769 This->status = HOST;
770
771 /* Commence TN5250 negotiations...
772 Send DO options (New Environment, Terminal Type, etc.) */
773
774 if(This->streamtype == TN3270E_STREAM)
775 {
776 retCode = SSL_write(this->ssl_handle, hostDoTN3270E, sizeof(hostDoTN3270E));
777 if (retCode<1) {
778 errnum = SSL_get_error(This->ssl_handle, retCode);
779 fprintf(stderr, "sslstream: %s\n", ERR_error_string(errnum,NULL));
780 return errnum;
781 }
782
783 tv.tv_sec = 5;
784 tv.tv_usec = 0;
785 TN_SELECT(This->sockfd + 1, &fdr, NULL, NULL, &tv);
786 if (FD_ISSET(This->sockfd, &fdr)) {
787
788 if (!ssl_stream_handle_receive(This)) {
789 retCode = errnum;
790 return retCode ? retCode : -1;
791 }
792 } else {
793 return -1;
794 }
795
796 if(This->streamtype == TN3270E_STREAM)
797 {
798 retCode = SSL_write(This->ssl_handle, hostDoTN3270E,sizeof(hostDoTN3270E));
799 if (retCode<1) {
800 errnum = SSL_get_error(This->ssl_handle, retCode);
801 fprintf(stderr,"sslstream: %s\n",ERR_error_string(errnum,NULL));
802 return errnum;
803 }
804
805 FD_ZERO(&fdr);
806 FD_SET(This->sockfd, &fdr);
807 tv.tv_sec = 5;
808 tv.tv_usec = 0;
809 TN_SELECT(This->sockfd + 1, &fdr, NULL, NULL, &tv);
810 if (FD_ISSET(This->sockfd, &fdr)) {
811
812 if (!ssl_stream_handle_receive(This)) {
813 retCode = errnum;
814 return retCode ? retCode : -1;
815 }
816 } else {
817 return -1;
818 }
819
820 FD_ZERO(&fdr);
821 FD_SET(This->sockfd, &fdr);
822 tv.tv_sec = 5;
823 tv.tv_usec = 0;
824 TN_SELECT(This->sockfd + 1, &fdr, NULL, NULL, &tv);
825 if (FD_ISSET(This->sockfd, &fdr)) {
826
827 if (!ssl_stream_handle_receive(This)) {
828 retCode = errnum;
829 return retCode ? retCode : -1;
830 }
831 } else {
832 return -1;
833 }
834 }
835 else
836 {
837 goto neg5250;
838 }
839 }
840 else
841 {
842 neg5250:
843 for (i=0; host5250DoTable[i].cmd; i++) {
844 retCode = SSL_write(This->ssl_handle, host5250DoTable[i].cmd,
845 host5250DoTable[i].len);
846 if (retCode<1) {
847 errnum = SSL_get_error(This->ssl_handle, retCode);
848 fprintf(stderr,"sslstream: %s\n",ERR_error_string(errnum,NULL));
849 return errnum;
850 }
851
852 FD_ZERO(&fdr);
853 FD_SET(This->sockfd, &fdr);
854 tv.tv_sec = 5;
855 tv.tv_usec = 0;
856 TN_SELECT(This->sockfd + 1, &fdr, NULL, NULL, &tv);
857 if (FD_ISSET(This->sockfd, &fdr)) {
858
859 if (!ssl_stream_handle_receive(This)) {
860 retCode = errnum;
861 return retCode ? retCode : -1;
862 }
863 } else {
864 return -1;
865 }
866 }
867 }
868 return 0;
869 #endif
870 return -1;
871 }
872
873 /****i* lib5250/ssl_stream_disconnect
874 * NAME
875 * ssl_stream_disconnect
876 * SYNOPSIS
877 * ssl_stream_disconnect (This);
878 * INPUTS
879 * Tn5250Stream * This -
880 * DESCRIPTION
881 * Disconnect from the remote host.
882 *****/
ssl_stream_disconnect(Tn5250Stream * This)883 static void ssl_stream_disconnect(Tn5250Stream * This)
884 {
885 SSL_shutdown(This->ssl_handle);
886 TN_CLOSE(This->sockfd);
887 }
888
889 /****i* lib5250/ssl_stream_destroy
890 * NAME
891 * ssl_stream_destroy
892 * SYNOPSIS
893 * ssl_stream_destroy (This);
894 * INPUTS
895 * Tn5250Stream * This -
896 * DESCRIPTION
897 * DOCUMENT ME!!!
898 *****/
ssl_stream_destroy(Tn5250Stream * This)899 static void ssl_stream_destroy(Tn5250Stream *This)
900 {
901 /* noop */
902 }
903
904 /****i* lib5250/ssl_stream_get_next
905 * NAME
906 * ssl_stream_get_next
907 * SYNOPSIS
908 * ssl_stream_get_next (This, buf, size);
909 * INPUTS
910 * Tn5250Stream * This -
911 * unsigned char * buf -
912 * int size -
913 * DESCRIPTION
914 * Reads data from the socket, returns the length,
915 * or -2 if disconnected, or -1 if out of data to read.
916 *****/
ssl_stream_get_next(Tn5250Stream * This,unsigned char * buf,int size)917 static int ssl_stream_get_next(Tn5250Stream *This,unsigned char *buf,int size)
918 {
919
920 int rc;
921 fd_set wrwait;
922
923 /* read data.
924 *
925 * Note: it's possible, due to the negotiations that SSL can do below
926 * the surface, that SSL_read() will need to wait for buffer space
927 * to write to. If that happens, we'll use select() to wait for
928 * space and try again.
929 */
930 do {
931 rc = SSL_read(This->ssl_handle, buf, size);
932 if (rc < 1) {
933 errnum = SSL_get_error(This->ssl_handle, rc);
934 switch (errnum) {
935 case SSL_ERROR_WANT_WRITE:
936 FD_ZERO(&wrwait);
937 FD_SET(This->sockfd, &wrwait);
938 select(This->sockfd+1, NULL, &wrwait, NULL, NULL);
939 break;
940 case SSL_ERROR_WANT_READ:
941 return -1;
942 break;
943 default:
944 return -2;
945 break;
946 }
947 }
948 } while (rc<1);
949
950 return rc;
951 }
952
ssl_sendWill(Tn5250Stream * This,unsigned char what)953 static int ssl_sendWill(Tn5250Stream *This, unsigned char what)
954 {
955 UCHAR buff[3]={IAC,WILL};
956 buff[2] = what;
957 TN5250_LOG(("SSL_Write: %x %x %x\n", buff[0], buff[1], buff[2]));
958 return SSL_write(This->ssl_handle, buff, 3);
959 }
960
961 /****i* lib5250/ssl_stream_host_verb
962 * NAME
963 * ssl_stream_host_verb
964 * SYNOPSIS
965 * ssl_stream_host_verb (This, verb, what);
966 * INPUTS
967 * Tn5250Stream * This -
968 * unsigned char verb -
969 * unsigned char what -
970 * DESCRIPTION
971 * Process the telnet DO, DONT, WILL, or WONT escape sequence.
972 *****/
ssl_stream_host_verb(Tn5250Stream * This,unsigned char verb,unsigned char what)973 static int ssl_stream_host_verb(Tn5250Stream * This, unsigned char verb,
974 unsigned char what)
975 {
976 int len, option=0, retval=0;
977
978 IACVERB_LOG("GotVerb(1)",verb,what);
979 switch (verb) {
980 case DO:
981 switch (what) {
982 case END_OF_RECORD:
983 option = SEND_EOR;
984 break;
985
986 case TRANSMIT_BINARY:
987 option = SEND_BINARY;
988 break;
989
990 default:
991 break;
992 } /* DO: switch (what) */
993 break;
994
995 case DONT:
996 case WONT:
997 if(what == TN3270E)
998 {
999 This->streamtype = TN3270_STREAM;
1000 }
1001 break;
1002
1003 case WILL:
1004 switch (what) {
1005 case NEW_ENVIRON:
1006 len = sizeof(SB_Str_NewEnv);
1007 TN5250_LOG(("Sending SB NewEnv..\n"));
1008 retval = SSL_write(This->ssl_handle, SB_Str_NewEnv, len);
1009 break;
1010
1011 case TERMINAL_TYPE:
1012 len = sizeof(SB_Str_TermType);
1013 TN5250_LOG(("Sending SB TermType..\n"));
1014 retval = SSL_write(This->ssl_handle, SB_Str_TermType, len);
1015 break;
1016
1017 case END_OF_RECORD:
1018 option = RECV_EOR;
1019 retval = ssl_sendWill(This, what);
1020 break;
1021
1022 case TRANSMIT_BINARY:
1023 option = RECV_BINARY;
1024 retval = ssl_sendWill(This, what);
1025 break;
1026
1027 default:
1028 break;
1029 } /* WILL: switch (what) */
1030 break;
1031
1032 default:
1033 break;
1034 } /* switch (verb) */
1035
1036 if (retval>0) retval=option;
1037
1038 return(retval);
1039 } /* ssl_stream_host_verb */
1040
1041
1042 /****i* lib5250/ssl_stream_do_verb
1043 * NAME
1044 * ssl_stream_do_verb
1045 * SYNOPSIS
1046 * ssl_stream_do_verb (This, verb, what);
1047 * INPUTS
1048 * Tn5250Stream * This -
1049 * unsigned char verb -
1050 * unsigned char what -
1051 * DESCRIPTION
1052 * Process the telnet DO, DONT, WILL, or WONT escape sequence.
1053 *****/
ssl_stream_do_verb(Tn5250Stream * This,unsigned char verb,unsigned char what)1054 static void ssl_stream_do_verb(Tn5250Stream * This, unsigned char verb, unsigned char what)
1055 {
1056 unsigned char reply[3];
1057 int ret;
1058
1059 IACVERB_LOG("GotVerb(2)", verb, what);
1060 reply[0] = IAC;
1061 reply[2] = what;
1062 switch (verb) {
1063 case DO:
1064 switch (what) {
1065 case TERMINAL_TYPE:
1066 case END_OF_RECORD:
1067 case TRANSMIT_BINARY:
1068 case NEW_ENVIRON:
1069 reply[1] = WILL;
1070 break;
1071
1072 default:
1073 reply[1] = WONT;
1074 break;
1075 }
1076 break;
1077
1078 case DONT:
1079 break;
1080
1081 case WILL:
1082 switch (what) {
1083 case TERMINAL_TYPE:
1084 case END_OF_RECORD:
1085 case TRANSMIT_BINARY:
1086 case NEW_ENVIRON:
1087 reply[1] = DO;
1088 break;
1089
1090 case TIMING_MARK:
1091 TN5250_LOG(("do_verb: IAC WILL TIMING_MARK received.\n"));
1092 default:
1093 reply[1] = DONT;
1094 break;
1095 }
1096 break;
1097
1098 case WONT:
1099 break;
1100 }
1101
1102 /* We should really keep track of states here, but the code has been
1103 * like this for some time, and no complaints.
1104 *
1105 * Actually, I don't even remember what that comment means -JMF */
1106
1107 IACVERB_LOG("GotVerb(3)",verb,what);
1108 TN5250_LOG(("SSL_Write: %x %x %x\n", reply[0], reply[1], reply[2]));
1109 ret = SSL_write(This->ssl_handle, (char *) reply, 3);
1110 if (ret<1) {
1111 errnum = SSL_get_error(This->ssl_handle, ret);
1112 printf("Error writing to socket: %s\n", ERR_error_string(errnum,NULL));
1113 exit(5);
1114 }
1115 }
1116
ssl_stream_host_sb(Tn5250Stream * This,UCHAR * sb_buf,int sb_len)1117 static void ssl_stream_host_sb(Tn5250Stream * This, UCHAR *sb_buf,
1118 int sb_len)
1119 {
1120 int rc;
1121 int i;
1122 int sbType;
1123 int sbParm;
1124 Tn5250Buffer tbuf;
1125 UCHAR deviceResponse[] = {IAC,SB,TN3270E,TN3270E_DEVICE_TYPE,TN3270E_IS};
1126 UCHAR functionResponse[] = {IAC,SB,TN3270E,TN3270E_FUNCTIONS};
1127 char * dummyname = "TN3E002";
1128
1129 if (sb_len <= 0)
1130 return;
1131
1132 TN5250_LOG(("GotSB:<IAC><SB>"));
1133 TNSB_LOG(sb_buf,sb_len);
1134 TN5250_LOG(("<IAC><SE>\n"));
1135 sbType = sb_buf[0];
1136 switch (sbType)
1137 {
1138 case TN3270E:
1139 sb_buf += 1;
1140 sb_len -= 1;
1141 sbParm = sb_buf[0];
1142 switch (sbParm)
1143 {
1144 case TN3270E_DEVICE_TYPE:
1145 sb_buf += 2; /* Device string follows DEVICE_TYPE IS parameter */
1146 sb_len -= 2;
1147 tn5250_buffer_init(&tbuf);
1148 tn5250_buffer_append_data(&tbuf, deviceResponse,
1149 sizeof(deviceResponse));
1150 for(i=0; i<sb_len && sb_buf[i] != IAC; i++)
1151 tn5250_buffer_append_byte(&tbuf, sb_buf[i]);
1152 tn5250_buffer_append_byte(&tbuf, TN3270E_CONNECT);
1153 tn5250_buffer_append_data(&tbuf, dummyname, strlen(dummyname));
1154 tn5250_buffer_append_byte(&tbuf, IAC);
1155 tn5250_buffer_append_byte(&tbuf, SE);
1156 rc = SSL_write(This->ssl_handle, (char *) tn5250_buffer_data(&tbuf),
1157 tn5250_buffer_length(&tbuf));
1158 if (rc<1) {
1159 errnum = SSL_get_error(This->ssl_handle, rc);
1160 printf("Error in SSL_write: %s\n", ERR_error_string(errnum,NULL));
1161 exit(5);
1162 }
1163 break;
1164 case TN3270E_FUNCTIONS:
1165 sb_buf += 2; /* Function list follows FUNCTIONS REQUEST parameter */
1166 sb_len -= 2;
1167 tn5250_buffer_init(&tbuf);
1168 tn5250_buffer_append_data(&tbuf, functionResponse,
1169 sizeof(functionResponse));
1170
1171 tn5250_buffer_append_byte(&tbuf, TN3270E_IS);
1172 for(i=0; i<sb_len && sb_buf[i] != IAC; i++)
1173 {
1174 tn5250_buffer_append_byte(&tbuf, sb_buf[i]);
1175 This->options = This->options | (1 << (sb_buf[i]+1));
1176 }
1177
1178 tn5250_buffer_append_byte(&tbuf, IAC);
1179 tn5250_buffer_append_byte(&tbuf, SE);
1180 rc = SSL_write(This->ssl_handle, (char *) tn5250_buffer_data(&tbuf),
1181 tn5250_buffer_length(&tbuf));
1182 if (rc<1) {
1183 errnum = SSL_get_error(This->ssl_handle, rc);
1184 printf("Error in SSL_write: %s\n", ERR_error_string(errnum,NULL));
1185 exit(5);
1186 }
1187 break;
1188 default:
1189 break;
1190 }
1191 break;
1192 case TERMINAL_TYPE:
1193 sb_buf += 2; /* Assume IS follows SB option type. */
1194 sb_len -= 2;
1195 tn5250_buffer_init(&tbuf);
1196 for (i=0; i<sb_len && sb_buf[i]!=IAC; i++)
1197 tn5250_buffer_append_byte(&tbuf, sb_buf[i]);
1198 tn5250_buffer_append_byte(&tbuf, 0);
1199 tn5250_stream_setenv(This, "TERM", (char *) tbuf.data);
1200 tn5250_buffer_free(&tbuf);
1201 break;
1202 case NEW_ENVIRON:
1203 /* TODO:
1204 * setNewEnvVars(This, sb_buf, sb_len);
1205 */
1206 break;
1207 default:
1208 break;
1209 } /* switch */
1210 } /* ssl_stream_host_sb */
1211
1212 /****i* lib5250/ssl_stream_sb_var_value
1213 * NAME
1214 * ssl_stream_sb_var_value
1215 * SYNOPSIS
1216 * ssl_stream_sb_var_value (buf, var, value);
1217 * INPUTS
1218 * Tn5250Buffer * buf -
1219 * unsigned char * var -
1220 * unsigned char * value -
1221 * DESCRIPTION
1222 * Utility function for constructing replies to NEW_ENVIRON requests.
1223 *****/
ssl_stream_sb_var_value(Tn5250Buffer * buf,unsigned char * var,unsigned char * value)1224 static void ssl_stream_sb_var_value(Tn5250Buffer * buf, unsigned char *var, unsigned char *value)
1225 {
1226 tn5250_buffer_append_byte(buf, VAR);
1227 tn5250_buffer_append_data(buf, var, strlen((char *) var));
1228 tn5250_buffer_append_byte(buf, VALUE);
1229 tn5250_buffer_append_data(buf, value, strlen((char *) value));
1230 }
1231
1232 /****i* lib5250/ssl_stream_sb
1233 * NAME
1234 * ssl_stream_sb
1235 * SYNOPSIS
1236 * ssl_stream_sb (This, sb_buf, sb_len);
1237 * INPUTS
1238 * Tn5250Stream * This -
1239 * unsigned char * sb_buf -
1240 * int sb_len -
1241 * DESCRIPTION
1242 * Handle telnet SB escapes, which are the option-specific negotiations.
1243 *****/
ssl_stream_sb(Tn5250Stream * This,unsigned char * sb_buf,int sb_len)1244 static void ssl_stream_sb(Tn5250Stream * This, unsigned char *sb_buf, int sb_len)
1245 {
1246 Tn5250Buffer out_buf;
1247 int ret;
1248
1249 TN5250_LOG(("GotSB:<IAC><SB>"));
1250 TNSB_LOG(sb_buf,sb_len);
1251 TN5250_LOG(("<IAC><SE>\n"));
1252
1253 tn5250_buffer_init(&out_buf);
1254
1255 if (sb_len <= 0)
1256 return;
1257
1258 if (sb_buf[0] == TERMINAL_TYPE) {
1259 unsigned char *termtype;
1260
1261 if (sb_buf[1] != SEND)
1262 return;
1263
1264 termtype = (unsigned char *) tn5250_stream_getenv(This, "TERM");
1265
1266 tn5250_buffer_append_byte(&out_buf, IAC);
1267 tn5250_buffer_append_byte(&out_buf, SB);
1268 tn5250_buffer_append_byte(&out_buf, TERMINAL_TYPE);
1269 tn5250_buffer_append_byte(&out_buf, IS);
1270 tn5250_buffer_append_data(&out_buf, termtype, strlen((char *) termtype));
1271 tn5250_buffer_append_byte(&out_buf, IAC);
1272 tn5250_buffer_append_byte(&out_buf, SE);
1273
1274 ret = SSL_write(This->ssl_handle, (char *) tn5250_buffer_data(&out_buf),
1275 tn5250_buffer_length(&out_buf));
1276 if (ret<1) {
1277 errnum = SSL_get_error(This->ssl_handle, ret);
1278 printf("Error in SSL_write: %s\n", ERR_error_string(errnum,NULL));
1279 exit(5);
1280 }
1281 TN5250_LOG(("SentSB:<IAC><SB><TERMTYPE><IS>%s<IAC><SE>\n", termtype));
1282
1283 This->status = This->status | TERMINAL;
1284 } else if (sb_buf[0] == NEW_ENVIRON) {
1285 Tn5250ConfigStr *iter;
1286 tn5250_buffer_append_byte(&out_buf, IAC);
1287 tn5250_buffer_append_byte(&out_buf, SB);
1288 tn5250_buffer_append_byte(&out_buf, NEW_ENVIRON);
1289 tn5250_buffer_append_byte(&out_buf, IS);
1290
1291 if (This->config != NULL) {
1292 if ((iter = This->config->vars) != NULL) {
1293 do {
1294 if ((strlen (iter->name) > 4) && (!memcmp (iter->name, "env.", 4))) {
1295 ssl_stream_sb_var_value(&out_buf,
1296 (unsigned char *) iter->name + 4,
1297 (unsigned char *) iter->value);
1298 }
1299 iter = iter->next;
1300 } while (iter != This->config->vars);
1301 }
1302 }
1303 tn5250_buffer_append_byte(&out_buf, IAC);
1304 tn5250_buffer_append_byte(&out_buf, SE);
1305
1306 ret = SSL_write(This->ssl_handle, (char *) tn5250_buffer_data(&out_buf),
1307 tn5250_buffer_length(&out_buf));
1308 if (ret<1) {
1309 errnum = SSL_get_error(This->ssl_handle, ret);
1310 printf("Error in SSL_write: %s\n", ERR_error_string(errnum,NULL));
1311 exit(5);
1312 }
1313 TN5250_LOG(("SentSB:<IAC><SB>"));
1314 TNSB_LOG(&out_buf.data[2], out_buf.len-4);
1315 TN5250_LOG(("<IAC><SE>\n"));
1316 }
1317 tn5250_buffer_free(&out_buf);
1318 }
1319
1320 /****i* lib5250/ssl_stream_get_byte
1321 * NAME
1322 * ssl_stream_get_byte
1323 * SYNOPSIS
1324 * ret = ssl_stream_get_byte (This);
1325 * INPUTS
1326 * Tn5250Stream * This -
1327 * DESCRIPTION
1328 * Returns the next byte from the 5250 data stream, or return -1 if no data
1329 * is waiting on the socket or -2 if disconnected, or -END_OF_RECORD if a
1330 * telnet EOR escape sequence was encountered.
1331 *****/
ssl_stream_get_byte(Tn5250Stream * This)1332 static int ssl_stream_get_byte(Tn5250Stream * This)
1333 {
1334 unsigned char temp;
1335 unsigned char verb;
1336
1337 do {
1338 if (This->state == TN5250_STREAM_STATE_NO_DATA)
1339 This->state = TN5250_STREAM_STATE_DATA;
1340
1341 This->rcvbufpos ++;
1342 if (This->rcvbufpos >= This->rcvbuflen) {
1343 This->rcvbufpos = 0;
1344 This->rcvbuflen = ssl_stream_get_next(This, This->rcvbuf, TN5250_RBSIZE);
1345 if (This->rcvbuflen<0)
1346 return This->rcvbuflen;
1347 }
1348 temp = This->rcvbuf[This->rcvbufpos];
1349
1350 switch (This->state) {
1351 case TN5250_STREAM_STATE_DATA:
1352 if (temp == IAC)
1353 This->state = TN5250_STREAM_STATE_HAVE_IAC;
1354 break;
1355
1356 case TN5250_STREAM_STATE_HAVE_IAC:
1357 switch(temp) {
1358 case IAC:
1359 This->state = TN5250_STREAM_STATE_DATA;
1360 break;
1361
1362 case DO:
1363 case DONT:
1364 case WILL:
1365 case WONT:
1366 verb = temp;
1367 This->state = TN5250_STREAM_STATE_HAVE_VERB;
1368 break;
1369
1370 case SB:
1371 This->state = TN5250_STREAM_STATE_HAVE_SB;
1372 tn5250_buffer_free(&(This->sb_buf));
1373 break;
1374
1375 case EOR:
1376 This->state = TN5250_STREAM_STATE_DATA;
1377 return -END_OF_RECORD;
1378
1379 default:
1380 TN5250_LOG(("GetByte: unknown escape 0x%02x in telnet-ssl stream.\n", temp));
1381 This->state = TN5250_STREAM_STATE_NO_DATA; /* Hopefully a good recovery. */
1382 }
1383 break;
1384
1385 case TN5250_STREAM_STATE_HAVE_VERB:
1386 TN5250_LOG(("HOST, This->status = %d %d\n", HOST, This->status));
1387 if (This->status&HOST) {
1388 temp = ssl_stream_host_verb(This, verb, (UCHAR) temp);
1389 if (temp<1) {
1390 DUMP_ERR_STACK ();
1391 return -2;
1392 }
1393 /* Implement later...
1394 This->options |= temp;
1395 */
1396 } else
1397 ssl_stream_do_verb(This, verb, (UCHAR) temp);
1398 This->state = TN5250_STREAM_STATE_NO_DATA;
1399 break;
1400
1401 case TN5250_STREAM_STATE_HAVE_SB:
1402 if (temp == IAC)
1403 This->state = TN5250_STREAM_STATE_HAVE_SB_IAC;
1404 else
1405 tn5250_buffer_append_byte(&(This->sb_buf), (UCHAR) temp);
1406 break;
1407
1408 case TN5250_STREAM_STATE_HAVE_SB_IAC:
1409 switch (temp) {
1410 case IAC:
1411 tn5250_buffer_append_byte(&(This->sb_buf), IAC);
1412 /* Since the IAC code was escaped, shouldn't we be resetting the
1413 state as in the following statement? Please verify and
1414 uncomment if applicable. GJS 2/25/2000 */
1415 /* This->state = TN5250_STREAM_STATE_HAVE_SB; */
1416 break;
1417
1418 case SE:
1419 if (This->status&HOST)
1420 ssl_stream_host_sb(This, tn5250_buffer_data(&This->sb_buf),
1421 tn5250_buffer_length(&This->sb_buf));
1422 else
1423 ssl_stream_sb(This, tn5250_buffer_data(&(This->sb_buf)),
1424 tn5250_buffer_length(&(This->sb_buf)));
1425
1426 tn5250_buffer_free(&(This->sb_buf));
1427 This->state = TN5250_STREAM_STATE_NO_DATA;
1428 break;
1429
1430 default: /* Should never happen -- server error */
1431 TN5250_LOG(("GetByte: huh? Got IAC SB 0x%02X.\n", temp));
1432 This->state = TN5250_STREAM_STATE_HAVE_SB;
1433 break;
1434 }
1435 break;
1436
1437 default:
1438 TN5250_LOG(("GetByte: huh? Invalid state %d.\n", This->state));
1439 TN5250_ASSERT(0);
1440 break; /* Avoid compiler warning. */
1441 }
1442 } while (This->state != TN5250_STREAM_STATE_DATA);
1443 return (int) temp;
1444 }
1445
1446 /****i* lib5250/ssl_stream_write
1447 * NAME
1448 * ssl_stream_write
1449 * SYNOPSIS
1450 * ssl_stream_write (This, data, size);
1451 * INPUTS
1452 * Tn5250Stream * This -
1453 * unsigned char * data -
1454 * int size -
1455 * DESCRIPTION
1456 * Writes size bytes of data (pointed to by *data) to the 5250 data stream.
1457 * This is also a temporary method to aid in the conversion process.
1458 *****/
ssl_stream_write(Tn5250Stream * This,unsigned char * data,int size)1459 static void ssl_stream_write(Tn5250Stream * This, unsigned char *data, int size)
1460 {
1461 int r;
1462 fd_set fdw;
1463
1464 while (size>0) {
1465
1466 r = SSL_write(This->ssl_handle, data, size);
1467 if (r < 1) {
1468 errnum = SSL_get_error(This->ssl_handle, r);
1469 if ((errnum!=SSL_ERROR_WANT_READ)&&(errnum!=SSL_ERROR_WANT_WRITE)) {
1470 }
1471 FD_ZERO(&fdw);
1472 FD_SET(This->sockfd, &fdw);
1473 if (errnum==SSL_ERROR_WANT_READ)
1474 select(This->sockfd+1, &fdw, NULL, NULL, NULL);
1475 else
1476 select(This->sockfd+1, NULL, &fdw, NULL, NULL);
1477 }
1478 else {
1479 data += r;
1480 size -= r;
1481 }
1482
1483 }
1484
1485 return;
1486 }
1487
1488 /****i* lib5250/ssl_stream_send_packet
1489 * NAME
1490 * ssl_stream_send_packet
1491 * SYNOPSIS
1492 * ssl_stream_send_packet (This, length, flowtype, flags, opcode, data);
1493 * INPUTS
1494 * Tn5250Stream * This -
1495 * int length -
1496 * int flowtype -
1497 * unsigned char flags -
1498 * unsgined char opcode -
1499 * unsigned char * data -
1500 * DESCRIPTION
1501 * Send a packet, prepending a header and escaping any naturally
1502 * occuring IAC characters.
1503 *****/
ssl_stream_send_packet(Tn5250Stream * This,int length,StreamHeader header,unsigned char * data)1504 static void ssl_stream_send_packet(Tn5250Stream * This, int length,
1505 StreamHeader header, unsigned char *data)
1506 {
1507 Tn5250Buffer out_buf;
1508 int n;
1509 int flowtype;
1510 unsigned char flags;
1511 unsigned char opcode;
1512
1513 flowtype = header.h5250.flowtype;
1514 flags = header.h5250.flags;
1515 opcode = header.h5250.opcode;
1516
1517 length = length + 10;
1518
1519 /* Fixed length portion of header */
1520 tn5250_buffer_init(&out_buf);
1521 tn5250_buffer_append_byte(&out_buf, (UCHAR) (((short)length)>>8));
1522 tn5250_buffer_append_byte(&out_buf, (UCHAR) (length & 0xff));
1523 tn5250_buffer_append_byte(&out_buf, 0x12); /* Record type = General data stream (GDS) */
1524 tn5250_buffer_append_byte(&out_buf, 0xa0);
1525 tn5250_buffer_append_byte(&out_buf, (UCHAR)(flowtype >> 8));
1526 tn5250_buffer_append_byte(&out_buf, (UCHAR) (flowtype & 0xff));
1527
1528 /* Variable length portion of header */
1529 tn5250_buffer_append_byte(&out_buf, 4);
1530 tn5250_buffer_append_byte(&out_buf, flags);
1531 tn5250_buffer_append_byte(&out_buf, 0);
1532 tn5250_buffer_append_byte(&out_buf, opcode);
1533 tn5250_buffer_append_data(&out_buf, data, length - 10);
1534
1535 ssl_stream_escape(&out_buf);
1536
1537 tn5250_buffer_append_byte(&out_buf, IAC);
1538 tn5250_buffer_append_byte(&out_buf, EOR);
1539
1540 #ifndef NDEBUG
1541 TN5250_LOG(("SendPacket: length = %d\nSendPacket: data follows.",
1542 tn5250_buffer_length(&out_buf)));
1543 for (n = 0; n < tn5250_buffer_length(&out_buf); n++) {
1544 if ((n % 16) == 0) {
1545 TN5250_LOG(("\nSendPacket: data: "));
1546 }
1547 TN5250_LOG(("%02X ", tn5250_buffer_data(&out_buf)[n]));
1548 }
1549 TN5250_LOG(("\n"));
1550 #endif
1551
1552 ssl_stream_write(This, tn5250_buffer_data(&out_buf), tn5250_buffer_length(&out_buf));
1553 tn5250_buffer_free(&out_buf);
1554 }
1555
1556 void
tn3270_ssl_stream_send_packet(Tn5250Stream * This,int length,StreamHeader header,unsigned char * data)1557 tn3270_ssl_stream_send_packet(Tn5250Stream * This, int length,
1558 StreamHeader header,
1559 unsigned char * data)
1560 {
1561 Tn5250Buffer out_buf;
1562
1563 tn5250_buffer_init(&out_buf);
1564
1565 if(This->streamtype == TN3270E_STREAM)
1566 {
1567 tn5250_buffer_append_byte(&out_buf, header.h3270.data_type);
1568 tn5250_buffer_append_byte(&out_buf, header.h3270.request_flag);
1569 tn5250_buffer_append_byte(&out_buf, header.h3270.response_flag);
1570
1571 tn5250_buffer_append_byte(&out_buf, header.h3270.sequence >> 8);
1572 tn5250_buffer_append_byte(&out_buf, header.h3270.sequence & 0x00ff);
1573 }
1574
1575 tn5250_buffer_append_data(&out_buf, data, length);
1576
1577 ssl_stream_escape(&out_buf);
1578
1579 tn5250_buffer_append_byte(&out_buf, IAC);
1580 tn5250_buffer_append_byte(&out_buf, EOR);
1581
1582 ssl_stream_write(This, tn5250_buffer_data(&out_buf),
1583 tn5250_buffer_length(&out_buf));
1584
1585 tn5250_buffer_free(&out_buf);
1586
1587 }
1588
1589 /****f* lib5250/ssl_stream_handle_receive
1590 * NAME
1591 * ssl_stream_handle_receive
1592 * SYNOPSIS
1593 * ret = ssl_stream_handle_receive (This);
1594 * INPUTS
1595 * Tn5250Stream * This -
1596 * DESCRIPTION
1597 * Read as much data as possible in a non-blocking fasion, form it
1598 * into Tn5250Record structures and queue them for retrieval.
1599 *****/
ssl_stream_handle_receive(Tn5250Stream * This)1600 int ssl_stream_handle_receive(Tn5250Stream * This)
1601 {
1602 int c;
1603
1604 fd_set rdwait;
1605 struct timeval tv;
1606
1607 /*
1608 * note that we have to do this here, not in _get_byte, because
1609 * we need to know that the SSL's internal buffer is empty, and
1610 * that SSL_read is not waiting for space in the write buffer,
1611 * before we can safely call select().
1612 *
1613 * Actually, not sure why we have to do this at all. Doesn't the
1614 * work in terminal_waitevent do this already? -SCK
1615 *
1616 */
1617 if (This->msec_wait > 0) {
1618 tv.tv_sec = This->msec_wait / 1000;
1619 tv.tv_usec = (This->msec_wait % 1000) * 1000;
1620 FD_ZERO(&rdwait);
1621 FD_SET(This->sockfd, &rdwait);
1622 select(This->sockfd+1, &rdwait, NULL, NULL, &tv);
1623 }
1624
1625 /* -1 = no more data, -2 = we've been disconnected */
1626 while ((c = ssl_stream_get_byte(This)) != -1 && c != -2) {
1627
1628 if (c == -END_OF_RECORD && This->current_record != NULL) {
1629 /* End of current packet. */
1630 #ifndef NDEBUG
1631 if (tn5250_logfile!=NULL)
1632 tn5250_record_dump(This->current_record);
1633 #endif
1634 This->records = tn5250_record_list_add(This->records, This->current_record);
1635 This->current_record = NULL;
1636 This->record_count++;
1637 continue;
1638 }
1639 if (This->current_record == NULL) {
1640 /* Start of new packet. */
1641 This->current_record = tn5250_record_new();
1642 }
1643 tn5250_record_append_byte(This->current_record, (unsigned char) c);
1644 }
1645
1646 return (c != -2);
1647 }
1648
1649 /****i* lib5250/ssl_stream_escape
1650 * NAME
1651 * ssl_stream_escape
1652 * SYNOPSIS
1653 * ssl_stream_escape (in);
1654 * INPUTS
1655 * Tn5250Buffer * in -
1656 * DESCRIPTION
1657 * Escape IACs in data before sending it to the host.
1658 *****/
ssl_stream_escape(Tn5250Buffer * in)1659 static void ssl_stream_escape(Tn5250Buffer * in)
1660 {
1661 Tn5250Buffer out;
1662 register unsigned char c;
1663 int n;
1664
1665 tn5250_buffer_init(&out);
1666 for (n = 0; n < tn5250_buffer_length(in); n++) {
1667 c = tn5250_buffer_data(in)[n];
1668 tn5250_buffer_append_byte(&out, c);
1669 if (c == IAC)
1670 tn5250_buffer_append_byte(&out, IAC);
1671 }
1672 tn5250_buffer_free(in);
1673 memcpy(in, &out, sizeof(Tn5250Buffer));
1674 }
1675
1676 /****i* lib5250/ssl_stream_passwd_cb
1677 * NAME
1678 * ssl_stream_passwd_cb
1679 * SYNOPSIS
1680 * ssl_stream_passwd_cb (buf, sizeof(buf), rwflag, userdata);
1681 * INPUTS
1682 * char * buf -
1683 * int size -
1684 * int rwflag -
1685 * void * userdata -
1686 * DESCRIPTION
1687 * This is a callback function that's passed to OpenSSL. When
1688 * OpenSSL needs a password for a Private Key file, it will call
1689 * this function.
1690 *****/
ssl_stream_passwd_cb(char * buf,int size,int rwflag,Tn5250Stream * This)1691 int ssl_stream_passwd_cb(char *buf, int size, int rwflag, Tn5250Stream *This) {
1692
1693 /** FIXME: There might be situations when we want to ask the user for
1694 the passphrase rather than have it supplied by a config option? **/
1695
1696 strncpy(buf, This->userdata, size);
1697 buf[size - 1] = '\0';
1698 return(strlen(buf));
1699
1700 }
1701
ssl_stream_load_cert(Tn5250Stream * This,const char * file)1702 X509 *ssl_stream_load_cert(Tn5250Stream *This, const char *file) {
1703
1704 BIO *cf;
1705 X509 *x;
1706
1707 if ((cf = BIO_new(BIO_s_file())) == NULL) {
1708 DUMP_ERR_STACK();
1709 return NULL;
1710 }
1711
1712 if (BIO_read_filename(cf, file) <= 0) {
1713 DUMP_ERR_STACK();
1714 return NULL;
1715 }
1716
1717 x = PEM_read_bio_X509_AUX(cf, NULL,
1718 (pem_password_cb *)ssl_stream_passwd_cb, This);
1719
1720 BIO_free(cf);
1721
1722 return (x);
1723 }
1724
1725 #endif /* HAVE_LIBSSL */
1726
1727 /* vi:set sts=3 sw=3: */
1728
1729