X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_client.c;h=16f1ac37dbb0ae3dcd32be3cef1f325ee02d35f3;hp=8a57dcfc9fe961207ad495703ae5e36e536f77a7;hb=fc6fc7ff38ead45fa4d64a407a9cf9ce49f8b578;hpb=d70fcb96ac3ed2d6182a966010f4bcdc7e898a67 diff --git a/apps/s_client.c b/apps/s_client.c index 8a57dcfc9f..16f1ac37db 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -206,6 +206,9 @@ static int c_status_req=0; static int c_msg=0; static int c_showcerts=0; +static char *keymatexportlabel=NULL; +static int keymatexportlen=20; + static void sc_usage(void); static void print_stuff(BIO *berr,SSL *con,int full); #ifndef OPENSSL_NO_TLSEXT @@ -328,11 +331,12 @@ static void sc_usage(void) #endif BIO_printf(bio_err," -ssl2 - just use SSLv2\n"); BIO_printf(bio_err," -ssl3 - just use SSLv3\n"); + BIO_printf(bio_err," -tls1_2 - just use TLSv1.2\n"); BIO_printf(bio_err," -tls1_1 - just use TLSv1.1\n"); BIO_printf(bio_err," -tls1 - just use TLSv1\n"); BIO_printf(bio_err," -dtls1 - just use DTLSv1\n"); BIO_printf(bio_err," -mtu - set the link layer MTU\n"); - BIO_printf(bio_err," -no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); + BIO_printf(bio_err," -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); BIO_printf(bio_err," -bugs - Switch on all SSL implementation bug workarounds\n"); BIO_printf(bio_err," -serverpref - Use server's cipher preferences (only SSLv2)\n"); BIO_printf(bio_err," -cipher - preferred cipher to use, use the 'openssl ciphers'\n"); @@ -358,6 +362,9 @@ static void sc_usage(void) # endif #endif BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); + BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); + BIO_printf(bio_err," -keymatexport label - Export keying material using label\n"); + BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n"); } #ifndef OPENSSL_NO_TLSEXT @@ -396,18 +403,18 @@ typedef struct srp_arg_st #define SRP_NUMBER_ITERATIONS_FOR_PRIME 64 -static int SRP_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) +static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) { BN_CTX *bn_ctx = BN_CTX_new(); BIGNUM *p = BN_new(); BIGNUM *r = BN_new(); int ret = g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && - BN_is_prime_ex(N,SRP_NUMBER_ITERATIONS_FOR_PRIME,bn_ctx,NULL) && + BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && p != NULL && BN_rshift1(p, N) && /* p = (N-1)/2 */ - BN_is_prime_ex(p,SRP_NUMBER_ITERATIONS_FOR_PRIME,bn_ctx,NULL) && + BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && r != NULL && /* verify g^((N-1)/2) == -1 (mod N) */ @@ -424,6 +431,21 @@ static int SRP_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) return ret; } +/* This callback is used here for two purposes: + - extended debugging + - making some primality tests for unknown groups + The callback is only called for a non default group. + + An application does not need the call back at all if + only the stanard groups are used. In real life situations, + client and server already share well known groups, + thus there is no need to verify them. + Furthermore, in case that a server actually proposes a group that + is not one of those defined in RFC 5054, it is more appropriate + to add the group to a static list and then compare since + primality tests are rather cpu consuming. +*/ + static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg) { SRP_ARG *srp_arg = (SRP_ARG *)arg; @@ -446,11 +468,11 @@ static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg) if (srp_arg->debug) BIO_printf(bio_err, "SRP param N and g are not known params, going to check deeper.\n"); -/* The srp_moregroups must be used with caution, testing primes costs time. +/* The srp_moregroups is a real debugging feature. Implementors should rather add the value to the known ones. The minimal size has already been tested. */ - if (BN_num_bits(g) <= BN_BITS && SRP_Verify_N_and_g(N,g)) + if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N,g)) return 1; } BIO_printf(bio_err, "SRP param N and g rejected.\n"); @@ -479,13 +501,8 @@ static char * MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg) return pass; } -static char * MS_CALLBACK missing_srp_username_callback(SSL *s, void *arg) - { - SRP_ARG *srp_arg = (SRP_ARG *)arg; - return BUF_strdup(srp_arg->srplogin); - } - #endif + char *srtp_profiles = NULL; # ifndef OPENSSL_NO_NEXTPROTONEG /* This the context that we pass to next_proto_cb */ @@ -538,6 +555,9 @@ int MAIN(int argc, char **argv) { unsigned int off=0, clr=0; SSL *con=NULL; +#ifndef OPENSSL_NO_KRB5 + KSSL_CTX *kctx; +#endif int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; @@ -581,6 +601,7 @@ int MAIN(int argc, char **argv) #endif #ifndef OPENSSL_NO_TLSEXT char *servername = NULL; + char *curves=NULL; tlsextctx tlsextcbp = {NULL,0}; # ifndef OPENSSL_NO_NEXTPROTONEG @@ -602,13 +623,7 @@ int MAIN(int argc, char **argv) SRP_ARG srp_arg = {NULL,NULL,0,0,0,1024}; #endif -#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); -#elif !defined(OPENSSL_NO_SSL3) - meth=SSLv3_client_method(); -#elif !defined(OPENSSL_NO_SSL2) - meth=SSLv2_client_method(); -#endif apps_startup(); c_Pause=0; @@ -743,7 +758,7 @@ int MAIN(int argc, char **argv) psk_key=*(++argv); for (j = 0; j < strlen(psk_key); j++) { - if (isxdigit((int)psk_key[j])) + if (isxdigit((unsigned char)psk_key[j])) continue; BIO_printf(bio_err,"Not a hex number '%s'\n",*argv); goto bad; @@ -790,6 +805,8 @@ int MAIN(int argc, char **argv) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 + else if (strcmp(*argv,"-tls1_2") == 0) + meth=TLSv1_2_client_method(); else if (strcmp(*argv,"-tls1_1") == 0) meth=TLSv1_1_client_method(); else if (strcmp(*argv,"-tls1") == 0) @@ -840,6 +857,8 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; CAfile= *(++argv); } + else if (strcmp(*argv,"-no_tls1_2") == 0) + off|=SSL_OP_NO_TLSv1_2; else if (strcmp(*argv,"-no_tls1_1") == 0) off|=SSL_OP_NO_TLSv1_1; else if (strcmp(*argv,"-no_tls1") == 0) @@ -919,6 +938,11 @@ int MAIN(int argc, char **argv) servername= *(++argv); /* meth=TLSv1_client_method(); */ } + else if (strcmp(*argv,"-curves") == 0) + { + if (--argc < 1) goto bad; + curves= *(++argv); + } #endif #ifndef OPENSSL_NO_JPAKE else if (strcmp(*argv,"-jpake") == 0) @@ -927,7 +951,23 @@ int MAIN(int argc, char **argv) jpake_secret = *++argv; } #endif - else + else if (strcmp(*argv,"-use_srtp") == 0) + { + if (--argc < 1) goto bad; + srtp_profiles = *(++argv); + } + else if (strcmp(*argv,"-keymatexport") == 0) + { + if (--argc < 1) goto bad; + keymatexportlabel= *(++argv); + } + else if (strcmp(*argv,"-keymatexportlen") == 0) + { + if (--argc < 1) goto bad; + keymatexportlen=atoi(*(++argv)); + if (keymatexportlen == 0) goto bad; + } + else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; @@ -1097,6 +1137,8 @@ bad: BIO_printf(bio_c_out, "PSK key given or JPAKE in use, setting client callback\n"); SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); } + if (srtp_profiles != NULL) + SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); #endif if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); @@ -1128,7 +1170,7 @@ bad: #endif SSL_CTX_set_verify(ctx,verify,verify_callback); - if (!set_cert_key_stuff(ctx,cert,key)) + if (!set_cert_key_stuff(ctx,cert,key, NULL)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || @@ -1140,6 +1182,12 @@ bad: } #ifndef OPENSSL_NO_TLSEXT + if (curves != NULL) + if(!SSL_CTX_set1_curves_list(ctx,curves)) { + BIO_printf(bio_err,"error setting curve list\n"); + ERR_print_errors(bio_err); + goto end; + } if (servername != NULL) { tlsextcbp.biodebug = bio_err; @@ -1149,9 +1197,7 @@ bad: #ifndef OPENSSL_NO_SRP if (srp_arg.srplogin) { - if (srp_lateuser) - SSL_CTX_set_srp_missing_srp_username_callback(ctx,missing_srp_username_callback); - else if (!SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) + if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) { BIO_printf(bio_err,"Unable to set SRP username\n"); goto end; @@ -1204,9 +1250,10 @@ bad: } #endif #ifndef OPENSSL_NO_KRB5 - if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) + if (con && (kctx = kssl_ctx_new()) != NULL) { - kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); + SSL_set0_kssl_ctx(con, kctx); + kssl_ctx_setstring(kctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ @@ -1238,7 +1285,7 @@ re_start: } } #endif - if (c_Pause & 0x01) con->debug=1; + if (c_Pause & 0x01) SSL_set_debug(con, 1); if ( SSL_version(con) == DTLS1_VERSION) { @@ -1287,7 +1334,7 @@ re_start: if (c_debug) { - con->debug=1; + SSL_set_debug(con, 1); BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } @@ -1821,6 +1868,14 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240 SSL_renegotiate(con); cbuf_len=0; } +#ifndef OPENSSL_NO_HEARTBEATS + else if ((!c_ign_eof) && (cbuf[0] == 'B')) + { + BIO_printf(bio_err,"HEARTBEATING\n"); + SSL_heartbeat(con); + cbuf_len=0; + } +#endif else { cbuf_len=i; @@ -1882,6 +1937,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) #ifndef OPENSSL_NO_COMP const COMP_METHOD *comp, *expansion; #endif + unsigned char *exportedkeymat; if (full) { @@ -1968,11 +2024,13 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_write(bio,"\n",1); } + ssl_print_sigalgs(bio, s); + BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n", BIO_number_read(SSL_get_rbio(s)), BIO_number_written(SSL_get_wbio(s))); } - BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, ")); + BIO_printf(bio,(SSL_cache_hit(s)?"---\nReused, ":"---\nNew, ")); c=SSL_get_current_cipher(s); BIO_printf(bio,"%s, Cipher is %s\n", SSL_CIPHER_get_version(c), @@ -2006,7 +2064,54 @@ static void print_stuff(BIO *bio, SSL *s, int full) } #endif +#ifdef SSL_DEBUG + { + /* Print out local port of connection: useful for debugging */ + int sock; + struct sockaddr_in ladd; + socklen_t ladd_size = sizeof(ladd); + sock = SSL_get_fd(s); + getsockname(sock, (struct sockaddr *)&ladd, &ladd_size); + BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port)); + } +#endif + + { + SRTP_PROTECTION_PROFILE *srtp_profile=SSL_get_selected_srtp_profile(s); + + if(srtp_profile) + BIO_printf(bio,"SRTP Extension negotiated, profile=%s\n", + srtp_profile->name); + } + SSL_SESSION_print(bio,SSL_get_session(s)); + if (keymatexportlabel != NULL) + { + BIO_printf(bio, "Keying material exporter:\n"); + BIO_printf(bio, " Label: '%s'\n", keymatexportlabel); + BIO_printf(bio, " Length: %i bytes\n", keymatexportlen); + exportedkeymat = OPENSSL_malloc(keymatexportlen); + if (exportedkeymat != NULL) + { + if (!SSL_export_keying_material(s, exportedkeymat, + keymatexportlen, + keymatexportlabel, + strlen(keymatexportlabel), + NULL, 0, 0)) + { + BIO_printf(bio, " Error\n"); + } + else + { + BIO_printf(bio, " Keying material: "); + for (i=0; i