X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=apps%2Fs_client.c;h=872496c3a244dbc8eea279301125b226c70f0bce;hb=09d62b336d9e2a11b330d45d4f0f3f37cbb0d674;hp=8a7613d5c7c0d6b1e91494fb7164ad9eece5cff7;hpb=dffa752023318b2fcccac2857ff133d5d11e5801;p=openssl.git diff --git a/apps/s_client.c b/apps/s_client.c index 8a7613d5c7..872496c3a2 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -74,6 +74,7 @@ static void print_stuff(BIO *berr, SSL *con, int full); static int ocsp_resp_cb(SSL *s, void *arg); #endif static int ldap_ExtendedResponse_parse(const char *buf, long rem); +static char *base64encode (const void *buf, size_t len); static int saved_errno; @@ -590,12 +591,14 @@ typedef enum OPTION_choice { OPT_V_ENUM, OPT_X_ENUM, OPT_S_ENUM, - OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN, + OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS, + OPT_DANE_TLSA_DOMAIN, #ifndef OPENSSL_NO_CT OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, OPT_ENABLE_PHA, + OPT_SCTP_LABEL_BUG, OPT_R_ENUM } OPTION_CHOICE; @@ -608,6 +611,8 @@ const OPTIONS s_client_options[] = { {"bind", OPT_BIND, 's', "bind local address for connection"}, {"proxy", OPT_PROXY, 's', "Connect to via specified proxy to the real server"}, + {"proxy_user", OPT_PROXY_USER, 's', "UserID for proxy authentication"}, + {"proxy_pass", OPT_PROXY_PASS, 's', "Proxy authentication password source"}, #ifdef AF_UNIX {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"}, #endif @@ -750,6 +755,7 @@ const OPTIONS s_client_options[] = { #endif #ifndef OPENSSL_NO_SCTP {"sctp", OPT_SCTP, '-', "Use SCTP"}, + {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"}, #endif #ifndef OPENSSL_NO_SSL_TRACE {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"}, @@ -894,8 +900,10 @@ int s_client_main(int argc, char **argv) STACK_OF(X509_CRL) *crls = NULL; const SSL_METHOD *meth = TLS_client_method(); const char *CApath = NULL, *CAfile = NULL; - char *cbuf = NULL, *sbuf = NULL; - char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL; + char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; + char *proxystr = NULL, *proxyuser = NULL; + char *proxypassarg = NULL, *proxypass = NULL; + char *connectstr = NULL, *bindstr = NULL; char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; char *chCApath = NULL, *chCAfile = NULL, *host = NULL; char *port = OPENSSL_strdup(PORT); @@ -976,6 +984,9 @@ int s_client_main(int argc, char **argv) #endif char *psksessf = NULL; int enable_pha = 0; +#ifndef OPENSSL_NO_SCTP + int sctp_label_bug = 0; +#endif FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -1075,6 +1086,12 @@ int s_client_main(int argc, char **argv) proxystr = opt_arg(); starttls_proto = PROTO_CONNECT; break; + case OPT_PROXY_USER: + proxyuser = opt_arg(); + break; + case OPT_PROXY_PASS: + proxypassarg = opt_arg(); + break; #ifdef AF_UNIX case OPT_UNIX: connect_type = use_unix; @@ -1321,6 +1338,11 @@ int s_client_main(int argc, char **argv) case OPT_SCTP: #ifndef OPENSSL_NO_SCTP protocol = IPPROTO_SCTP; +#endif + break; + case OPT_SCTP_LABEL_BUG: +#ifndef OPENSSL_NO_SCTP + sctp_label_bug = 1; #endif break; case OPT_TIMEOUT: @@ -1619,7 +1641,17 @@ int s_client_main(int argc, char **argv) #endif if (!app_passwd(passarg, NULL, &pass, NULL)) { - BIO_printf(bio_err, "Error getting password\n"); + BIO_printf(bio_err, "Error getting private key password\n"); + goto end; + } + + if (!app_passwd(proxypassarg, NULL, &proxypass, NULL)) { + BIO_printf(bio_err, "Error getting proxy password\n"); + goto end; + } + + if (proxypass != NULL && proxyuser == NULL) { + BIO_printf(bio_err, "Error: Must specify proxy_user with proxy_pass\n"); goto end; } @@ -1707,6 +1739,11 @@ int s_client_main(int argc, char **argv) } } +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP && sctp_label_bug == 1) + SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG); +#endif + if (min_version != 0 && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) goto end; @@ -2322,7 +2359,33 @@ int s_client_main(int argc, char **argv) BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); - BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr); + BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n", connectstr); + /* + * Workaround for broken proxies which would otherwise close + * the connection when entering tunnel mode (eg Squid 2.6) + */ + BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n"); + + /* Support for basic (base64) proxy authentication */ + if (proxyuser != NULL) { + size_t l; + char *proxyauth, *proxyauthenc; + + l = strlen(proxyuser); + if (proxypass != NULL) + l += strlen(proxypass); + proxyauth = app_malloc(l + 2, "Proxy auth string"); + BIO_snprintf(proxyauth, l + 2, "%s:%s", proxyuser, + (proxypass != NULL) ? proxypass : ""); + proxyauthenc = base64encode(proxyauth, strlen(proxyauth)); + BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", + proxyauthenc); + OPENSSL_clear_free(proxyauth, strlen(proxyauth)); + OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc)); + } + + /* Terminate the HTTP CONNECT request */ + BIO_printf(fbio, "\r\n"); (void)BIO_flush(fbio); /* * The first line is the HTTP response. According to RFC 7230, @@ -2535,12 +2598,16 @@ int s_client_main(int argc, char **argv) /* STARTTLS command requires CAPABILITIES... */ BIO_printf(fbio, "CAPABILITIES\r\n"); (void)BIO_flush(fbio); - /* wait for multi-line CAPABILITIES response */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - if (strstr(mbuf, "STARTTLS")) - foundit = 1; - } while (mbuf_len > 1 && mbuf[0] != '.'); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* no point in trying to parse the CAPABILITIES response if there is none */ + if (strstr(mbuf, "101") != NULL) { + /* wait for multi-line CAPABILITIES response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 1 && mbuf[0] != '.'); + } (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); @@ -3031,9 +3098,7 @@ int s_client_main(int argc, char **argv) BIO_printf(bio_err, "RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len = 0; - } - - if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) + } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) && cmdletters) { BIO_printf(bio_err, "KEYUPDATE\n"); SSL_key_update(con, @@ -3124,6 +3189,8 @@ int s_client_main(int argc, char **argv) OPENSSL_clear_free(cbuf, BUFSIZZ); OPENSSL_clear_free(sbuf, BUFSIZZ); OPENSSL_clear_free(mbuf, BUFSIZZ); + if (proxypass != NULL) + OPENSSL_clear_free(proxypass, strlen(proxypass)); release_engine(e); BIO_free(bio_c_out); bio_c_out = NULL; @@ -3245,6 +3312,10 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_printf(bio, "Expansion: %s\n", expansion ? SSL_COMP_get_name(expansion) : "NONE"); #endif +#ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_send(SSL_get_wbio(s))) + BIO_printf(bio_err, "Using Kernel TLS for sending\n"); +#endif #ifdef SSL_DEBUG { @@ -3459,4 +3530,27 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem) return ret; } +/* + * BASE64 encoder: used only for encoding basic proxy authentication credentials + */ +static char *base64encode (const void *buf, size_t len) +{ + int i; + size_t outl; + char *out; + + /* Calculate size of encoded data */ + outl = (len / 3); + if (len % 3 > 0) + outl++; + outl <<= 2; + out = app_malloc(outl + 1, "base64 encode buffer"); + + i = EVP_EncodeBlock((unsigned char *)out, buf, len); + assert(i <= (int)outl); + if (i < 0) + *out = '\0'; + return out; +} + #endif /* OPENSSL_NO_SOCK */