--- apps/s_client.c.org 2009-12-16 15:28:28.000000000 -0500 +++ apps/s_client.c 2010-11-16 12:07:02.274824820 -0500 @@ -329,8 +329,8 @@ static void sc_usage(void) BIO_printf(bio_err," -starttls prot - use the STARTTLS command before starting TLS\n"); BIO_printf(bio_err," for those protocols that support it, where\n"); BIO_printf(bio_err," 'prot' defines which one to assume. Currently,\n"); - BIO_printf(bio_err," only \"smtp\", \"pop3\", \"imap\", \"ftp\" and \"xmpp\"\n"); - BIO_printf(bio_err," are supported.\n"); + BIO_printf(bio_err," only \"smtp\", \"pop3\", \"imap\", \"ftp\", \"xmpp\", and\n"); + BIO_printf(bio_err," \"telnet\" are supported.\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); #endif @@ -375,7 +375,8 @@ enum PROTO_POP3, PROTO_IMAP, PROTO_FTP, - PROTO_XMPP + PROTO_XMPP, + PROTO_TELNET }; int MAIN(int, char **); @@ -688,6 +689,8 @@ int MAIN(int argc, char **argv) starttls_proto = PROTO_FTP; else if (strcmp(*argv, "xmpp") == 0) starttls_proto = PROTO_XMPP; + else if (strcmp(*argv, "telnet") == 0) + starttls_proto = PROTO_TELNET; else goto bad; } @@ -1200,6 +1203,45 @@ SSL_set_tlsext_status_ids(con, ids); goto shut; mbuf[0] = 0; } + else if (starttls_proto == PROTO_TELNET) + { + static const unsigned char tls_do[] = + { + 255 /* IAC */, + 253 /* DO */, + 46 /* START_TLS */ + }; + static const unsigned char tls_will[] = + { + 255 /* IAC */, + 251 /* WILL */, + 46 /* START_TLS */ + }; + static const unsigned char tls_follows[] = + { + 255 /* IAC */, + 250 /* SB */, + 46 /* START_TLS */, + 1 /* FOLLOWS */, + 255 /* IAC */, + 240 /* SE */ + }; + int bytes; + + /* Telnet server should demand we issue START_TLS */ + bytes = BIO_read(sbio,mbuf,BUFSIZZ); + if (!(bytes == 3 && memcmp(mbuf, tls_do, 3) == 0)) + goto shut; + /* Agree to issue START_TLS and send the FOLLOWS sub-command */ + BIO_write(sbio, tls_will, 3); + BIO_write(sbio, tls_follows, 6); + (void)BIO_flush(sbio); + /* Telnet server also sent the FOLLOWS sub-command */ + bytes = BIO_read(sbio,mbuf,BUFSIZZ); + if (!(bytes == 6 && memcmp(mbuf, tls_follows, 6) == 0)) + goto shut; + /* Any traffic after this point must be TLS negotiation */ + } for (;;) {