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