X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_client.c;h=3474e6c6a74df4458cdd5583254fcdf43b59a602;hp=58e317a1a2a50c0eed6c0f5fa1851bd70feef0b3;hb=86d4bc3aeaa7bc0f7551b54c6091b736d0b2732b;hpb=5d5ca32fa1b34de7b7c869e9860929d033f9ffd7;ds=sidebyside diff --git a/apps/s_client.c b/apps/s_client.c index 58e317a1a2..3474e6c6a7 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -194,6 +194,9 @@ static int c_nbio=0; #endif static int c_Pause=0; static int c_debug=0; +#ifndef OPENSSL_NO_TLSEXT +static int c_tlsextdebug=0; +#endif static int c_msg=0; static int c_showcerts=0; @@ -321,8 +324,12 @@ static void sc_usage(void) BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); #endif BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); + BIO_printf(bio_err," -sess_out arg - file to write SSL session to\n"); + BIO_printf(bio_err," -sess_in arg - file to read SSL session from\n"); #ifndef OPENSSL_NO_TLSEXT BIO_printf(bio_err," -servername host - Set TLS extension servername in ClientHello\n"); + BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n"); + BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); #endif } @@ -406,6 +413,8 @@ int MAIN(int argc, char **argv) tlsextctx tlsextcbp = {NULL,0}; #endif + char *sess_in = NULL; + char *sess_out = NULL; struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; @@ -480,6 +489,16 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; cert_file= *(++argv); } + else if (strcmp(*argv,"-sess_out") == 0) + { + if (--argc < 1) goto bad; + sess_out = *(++argv); + } + else if (strcmp(*argv,"-sess_in") == 0) + { + if (--argc < 1) goto bad; + sess_in = *(++argv); + } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; @@ -506,6 +525,10 @@ int MAIN(int argc, char **argv) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; +#ifndef OPENSSL_NO_TLSEXT + else if (strcmp(*argv,"-tlsextdebug") == 0) + c_tlsextdebug=1; +#endif #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); @@ -604,6 +627,10 @@ int MAIN(int argc, char **argv) off|=SSL_OP_NO_SSLv2; else if (strcmp(*argv,"-no_comp") == 0) { off|=SSL_OP_NO_COMPRESSION; } +#ifndef OPENSSL_NO_TLSEXT + else if (strcmp(*argv,"-no_ticket") == 0) + { off|=SSL_OP_NO_TICKET; } +#endif else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-cipher") == 0) @@ -791,6 +818,29 @@ bad: #endif con=SSL_new(ctx); + if (sess_in) + { + SSL_SESSION *sess; + BIO *stmp = BIO_new_file(sess_in, "r"); + if (!stmp) + { + BIO_printf(bio_err, "Can't open session file %s\n", + sess_in); + ERR_print_errors(bio_err); + goto end; + } + sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (!sess) + { + BIO_printf(bio_err, "Can't open session file %s\n", + sess_in); + ERR_print_errors(bio_err); + goto end; + } + SSL_set_session(con, sess); + SSL_SESSION_free(sess); + } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { @@ -809,6 +859,11 @@ bad: } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ +#if 0 +#ifdef TLSEXT_TYPE_opaque_prf_input + SSL_set_tlsext_opaque_prf_input(con, "Test client", 11); +#endif +#endif re_start: @@ -847,7 +902,7 @@ re_start: goto end; } - BIO_ctrl_set_connected(sbio, 1, &peer); + (void)BIO_ctrl_set_connected(sbio, 1, &peer); if (enable_timeouts) { @@ -893,6 +948,13 @@ re_start: SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } +#ifndef OPENSSL_NO_TLSEXT + if (c_tlsextdebug) + { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_c_out); + } +#endif SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); @@ -912,14 +974,41 @@ re_start: sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ + /* We do have to handle multi-line responses which may come + in a single packet or not. We therefore have to use + BIO_gets() which does need a buffering BIO. So during + the initial chitchat we do push a buffering BIO into the + chain that is removed again later on to not disturb the + rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { + int foundit=0; + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { - mbuf_len = BIO_read(sbio,mbuf,BUFSIZZ); + mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); + /* STARTTLS command requires EHLO... */ + BIO_printf(fbio,"EHLO openssl.client.net\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line response to end EHLO SMTP response */ + do + { + mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); + if (strstr(mbuf,"STARTTLS")) + foundit=1; + } + while (mbuf_len>3 && mbuf[3]=='-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "didn't found starttls in server response," + " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } @@ -931,18 +1020,44 @@ re_start: } else if (starttls_proto == PROTO_IMAP) { - BIO_read(sbio,mbuf,BUFSIZZ); - BIO_printf(sbio,"0 STARTTLS\r\n"); + int foundit=0; + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); + BIO_gets(fbio,mbuf,BUFSIZZ); + /* STARTTLS command requires CAPABILITY... */ + BIO_printf(fbio,". CAPABILITY\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line CAPABILITY response */ + do + { + mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); + if (strstr(mbuf,"STARTTLS")) + foundit=1; + } + while (mbuf_len>3 && mbuf[0]!='.'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "didn't found STARTTLS in server response," + " try anyway...\n"); + BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { - mbuf_len = BIO_read(sbio,mbuf,BUFSIZZ); + mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } @@ -963,12 +1078,25 @@ re_start: if (in_init) { in_init=0; +#if 0 /* This test doesn't really work as intended (needs to be fixed) */ #ifndef OPENSSL_NO_TLSEXT if (servername != NULL && !SSL_session_reused(con)) { BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not "); } #endif +#endif + if (sess_out) + { + BIO *stmp = BIO_new_file(sess_out, "w"); + if (stmp) + { + PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); + BIO_free(stmp); + } + else + BIO_printf(bio_err, "Error writing session file %s\n", sess_out); + } print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; @@ -1461,6 +1589,6 @@ static void print_stuff(BIO *bio, SSL *s, int full) if (peer != NULL) X509_free(peer); /* flush, or debugging output gets mixed with http response */ - BIO_flush(bio); + (void)BIO_flush(bio); }