X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_client.c;h=35150704897b399a4c0323b17e473859437f105b;hp=c24b6e4a26d6cd6a881ad5c7daa1a5fedb45ea61;hb=5d20c4fb3582a0e6cbf8513c94c60e4cd326716d;hpb=ed3883d21bb4ddfc21ec9d154e14e84c85db164d diff --git a/apps/s_client.c b/apps/s_client.c index c24b6e4a26..3515070489 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -108,8 +108,35 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ #include +#include #include #include #include @@ -142,6 +169,10 @@ typedef unsigned int u_int; #undef FIONBIO #endif +#if defined(OPENSSL_SYS_BEOS_R5) +#include +#endif + #undef PROG #define PROG s_client_main @@ -156,6 +187,7 @@ typedef unsigned int u_int; extern int verify_depth; extern int verify_error; +extern int verify_return_error; #ifdef FIONBIO static int c_nbio=0; @@ -171,6 +203,69 @@ static BIO *bio_c_out=NULL; static int c_quiet=0; static int c_ign_eof=0; +#ifndef OPENSSL_NO_PSK +/* Default PSK identity and key */ +static char *psk_identity="Client_identity"; +static char *psk_key=NULL; /* by default PSK is not used */ + +static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, unsigned char *psk, + unsigned int max_psk_len) + { + unsigned int psk_len = 0; + int ret; + BIGNUM *bn=NULL; + + if (c_debug) + BIO_printf(bio_c_out, "psk_client_cb\n"); + if (!hint) + { + /* no ServerKeyExchange message*/ + if (c_debug) + BIO_printf(bio_c_out,"NULL received PSK identity hint, continuing anyway\n"); + } + else if (c_debug) + BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint); + + /* lookup PSK identity and PSK key based on the given identity hint here */ + ret = BIO_snprintf(identity, max_identity_len, psk_identity); + if (ret < 0 || (unsigned int)ret > max_identity_len) + goto out_err; + if (c_debug) + BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity, ret); + ret=BN_hex2bn(&bn, psk_key); + if (!ret) + { + BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", psk_key); + if (bn) + BN_free(bn); + return 0; + } + + if ((unsigned int)BN_num_bytes(bn) > max_psk_len) + { + BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n", + max_psk_len, BN_num_bytes(bn)); + BN_free(bn); + return 0; + } + + psk_len=BN_bn2bin(bn, psk); + BN_free(bn); + if (psk_len == 0) + goto out_err; + + if (c_debug) + BIO_printf(bio_c_out, "created PSK len=%d\n", psk_len); + + return psk_len; + out_err: + if (c_debug) + BIO_printf(bio_err, "Error in PSK client callback\n"); + return 0; + } +#endif + static void sc_usage(void) { BIO_printf(bio_err,"usage: s_client args\n"); @@ -204,6 +299,10 @@ static void sc_usage(void) BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); BIO_printf(bio_err," -quiet - no s_client output\n"); BIO_printf(bio_err," -ign_eof - ignore input eof (default when -quiet)\n"); +#ifndef OPENSSL_NO_PSK + BIO_printf(bio_err," -psk_identity arg - PSK identity\n"); + BIO_printf(bio_err," -psk arg - PSK in hex (without 0x)\n"); +#endif BIO_printf(bio_err," -ssl2 - just use SSLv2\n"); BIO_printf(bio_err," -ssl3 - just use SSLv3\n"); BIO_printf(bio_err," -tls1 - just use TLSv1\n"); @@ -236,16 +335,17 @@ typedef struct tlsextctx_st { } tlsextctx; -static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { +static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) + { tlsextctx * p = (tlsextctx *) arg; - const unsigned char * hn= SSL_get_servername(s, TLSEXT_TYPE_SERVER_host); + const char * hn= SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); if (SSL_get_servername_type(s) != -1) p->ack = !SSL_session_reused(s) && hn != NULL; else - BIO_printf(bio_err,"SSL_get_tlsext_hostname does not work\n"); + BIO_printf(bio_err,"Can't use SSL_get_servername\n"); - return SSL_ERROR_NONE; -} + return SSL_TLSEXT_ERR_OK; + } #endif int MAIN(int, char **); @@ -253,7 +353,7 @@ int MAIN(int, char **); int MAIN(int argc, char **argv) { int off=0; - SSL *con=NULL,*con2=NULL; + SSL *con=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; @@ -277,15 +377,18 @@ int MAIN(int argc, char **argv) int starttls_proto = 0; int prexit = 0, vflags = 0; const SSL_METHOD *meth=NULL; - int socketType=SOCK_STREAM; + int socket_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; ENGINE *e=NULL; #endif -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) struct timeval tv; +#if defined(OPENSSL_SYS_BEOS_R5) + int stdin_set = 0; +#endif #endif #ifndef OPENSSL_NO_TLSEXT @@ -296,7 +399,7 @@ int MAIN(int argc, char **argv) struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; - long mtu = 0; + long socket_mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); @@ -376,6 +479,8 @@ int MAIN(int argc, char **argv) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; + else if (strcmp(*argv,"-verify_return_error") == 0) + verify_return_error = 1; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) @@ -403,6 +508,27 @@ int MAIN(int argc, char **argv) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; +#ifndef OPENSSL_NO_PSK + else if (strcmp(*argv,"-psk_identity") == 0) + { + if (--argc < 1) goto bad; + psk_identity=*(++argv); + } + else if (strcmp(*argv,"-psk") == 0) + { + size_t j; + + if (--argc < 1) goto bad; + psk_key=*(++argv); + for (j = 0; j < strlen(psk_key); j++) + { + if (isxdigit((int)psk_key[j])) + continue; + BIO_printf(bio_err,"Not a hex number '%s'\n",*argv); + goto bad; + } + } +#endif #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); @@ -419,14 +545,14 @@ int MAIN(int argc, char **argv) else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); - socketType=SOCK_DGRAM; + socket_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; - mtu = atol(*(++argv)); + socket_mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) @@ -598,6 +724,14 @@ bad: goto end; } +#ifndef OPENSSL_NO_PSK + if (psk_key != NULL) + { + if (c_debug) + BIO_printf(bio_c_out, "PSK key given, setting client callback\n"); + SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); + } +#endif if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else @@ -605,7 +739,7 @@ bad: /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ - if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); + if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) @@ -634,22 +768,25 @@ bad: store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); #ifndef OPENSSL_NO_TLSEXT - if (servername != NULL) { + if (servername != NULL) + { tlsextcbp.biodebug = bio_err; SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); - } + } #endif con=SSL_new(ctx); #ifndef OPENSSL_NO_TLSEXT - if (servername != NULL){ - if (!SSL_set_tlsext_hostname(con,servername)){ + if (servername != NULL) + { + if (!SSL_set_tlsext_host_name(con,servername)) + { BIO_printf(bio_err,"Unable to set TLS servername extension.\n"); ERR_print_errors(bio_err); goto end; + } } - } #endif #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) @@ -661,7 +798,7 @@ bad: re_start: - if (init_client(&s,host,port,socketType) == 0) + if (init_client(&s,host,port,socket_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); @@ -698,7 +835,7 @@ re_start: BIO_ctrl_set_connected(sbio, 1, &peer); - if ( enable_timeouts) + if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; @@ -709,10 +846,10 @@ re_start: BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } - if ( mtu > 0) + if (socket_mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); - SSL_set_mtu(con, mtu); + SSL_set_mtu(con, socket_mtu); } else /* want to do MTU discovery */ @@ -791,9 +928,10 @@ re_start: { in_init=0; #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 "); - } + if (servername != NULL && !SSL_session_reused(con)) + { + BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not "); + } #endif print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; @@ -821,22 +959,22 @@ re_start: if (!ssl_pending) { -#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined (OPENSSL_SYS_BEOS_R5) if (tty_on) { - if (read_tty) FD_SET(fileno(stdin),&readfds); - if (write_tty) FD_SET(fileno(stdout),&writefds); + if (read_tty) openssl_fdset(fileno(stdin),&readfds); + if (write_tty) openssl_fdset(fileno(stdout),&writefds); } if (read_ssl) - FD_SET(SSL_get_fd(con),&readfds); + openssl_fdset(SSL_get_fd(con),&readfds); if (write_ssl) - FD_SET(SSL_get_fd(con),&writefds); + openssl_fdset(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) - FD_SET(SSL_get_fd(con),&readfds); + openssl_fdset(SSL_get_fd(con),&readfds); if (write_ssl) - FD_SET(SSL_get_fd(con),&writefds); + openssl_fdset(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", @@ -881,6 +1019,25 @@ re_start: } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } +#elif defined(OPENSSL_SYS_BEOS_R5) + /* Under BeOS-R5 the situation is similar to DOS */ + i=0; + stdin_set = 0; + (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); + if(!write_tty) { + if(read_tty) { + tv.tv_sec = 1; + tv.tv_usec = 0; + i=select(width,(void *)&readfds,(void *)&writefds, + NULL,&tv); + if (read(fileno(stdin), sbuf, 0) >= 0) + stdin_set = 1; + if (!i && (stdin_set != 1 || !read_tty)) + continue; + } else i=select(width,(void *)&readfds,(void *)&writefds, + NULL,NULL); + } + (void)fcntl(fileno(stdin), F_SETFL, 0); #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); @@ -961,8 +1118,8 @@ re_start: goto shut; } } -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) - /* Assume Windows/DOS can always write */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) + /* Assume Windows/DOS/BeOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) @@ -1050,6 +1207,8 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240 #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) +#elif defined(OPENSSL_SYS_BEOS_R5) + else if (stdin_set) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif @@ -1105,13 +1264,18 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240 } } shut: + if (in_init) + print_stuff(bio_c_out,con,full_log); SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: - if(prexit) print_stuff(bio_c_out,con,1); - if (con != NULL) SSL_free(con); - if (con2 != NULL) SSL_free(con2); + if (con != NULL) + { + if (prexit != 0) + print_stuff(bio_c_out,con,1); + SSL_free(con); + } if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert);