From 2345df95dd2621ecad210faea3db40ee63592e91 Mon Sep 17 00:00:00 2001 From: Martin Prikryl Date: Wed, 10 Jan 2018 16:03:17 +0000 Subject: [PATCH] Bug 1597: It was not possible to work with S3 buckets with a dot in their name https://winscp.net/tracker/1597 Source commit: 5c3c525dbddd2350210f67779f7ebd484f9aebfa --- libs/libs3/src/request.c | 10 +++++++++- libs/neon/src/ne_openssl.c | 4 ++++ libs/neon/src/ne_private.h | 4 ++++ libs/neon/src/ne_session.c | 22 ++++++++++++++++++++++ libs/neon/src/ne_session.h | 4 ++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/libs/libs3/src/request.c b/libs/libs3/src/request.c index b77d47159..39e961bb6 100644 --- a/libs/libs3/src/request.c +++ b/libs/libs3/src/request.c @@ -1075,8 +1075,13 @@ static S3Status compose_uri(char *buffer, int bufferSize, if (bucketContext->bucketName && bucketContext->bucketName[0]) { if (bucketContext->uriStyle == S3UriStyleVirtualHost) { +#ifndef WINSCP + // We cannot change Host: header with neon. + // Instead we tweak host name validation if (strchr(bucketContext->bucketName, '.') == NULL) { +#endif uri_append("%s.%s", bucketContext->bucketName, hostName); +#ifndef WINSCP } else { // We'll use the hostName in the URL, and then explicitly set @@ -1084,6 +1089,7 @@ static S3Status compose_uri(char *buffer, int bufferSize, // works. uri_append("%s", hostName); } +#endif } else { uri_append("%s/%s", hostName, bucketContext->bucketName); @@ -1238,7 +1244,9 @@ static S3Status setup_neon(Request *request, do_add_header(values-> fieldName); \ } - // WINSCP (hostHeader is added implicitly by neon based on uri) + // WINSCP (hostHeader is added implicitly by neon based on uri, but for certificate check, we use base hostname + // as the bucket name can contain dots, for which the certificate check would fail) + ne_set_realhost(request->NeonSession, params->bucketContext.hostName ? params->bucketContext.hostName : defaultHostNameG); append_standard_header(cacheControlHeader); append_standard_header(contentTypeHeader); append_standard_header(md5Header); diff --git a/libs/neon/src/ne_openssl.c b/libs/neon/src/ne_openssl.c index 3d71a8be2..06d9785b7 100644 --- a/libs/neon/src/ne_openssl.c +++ b/libs/neon/src/ne_openssl.c @@ -473,7 +473,11 @@ static int check_certificate(ne_session *sess, SSL *ssl, ne_ssl_certificate *cha /* Check certificate was issued to this server; pass URI of * server. */ memset(&server, 0, sizeof server); + #ifdef WINSCP + ne_fill_real_server_uri(sess, &server); + #else ne_fill_server_uri(sess, &server); + #endif ret = check_identity(&server, cert, NULL); ne_uri_free(&server); if (ret < 0) { diff --git a/libs/neon/src/ne_private.h b/libs/neon/src/ne_private.h index a2c5fcfed..440053e56 100644 --- a/libs/neon/src/ne_private.h +++ b/libs/neon/src/ne_private.h @@ -114,6 +114,10 @@ struct ne_session_s { char *user_agent; /* full User-Agent: header field */ +#ifdef WINSCP + char *realhost; +#endif + #ifdef NE_HAVE_SSL ne_ssl_client_cert *client_cert; ne_ssl_certificate *server_cert; diff --git a/libs/neon/src/ne_session.c b/libs/neon/src/ne_session.c index 92a4a3d48..a676910f2 100644 --- a/libs/neon/src/ne_session.c +++ b/libs/neon/src/ne_session.c @@ -112,6 +112,9 @@ void ne_session_destroy(ne_session *sess) free_proxies(sess); if (sess->user_agent) ne_free(sess->user_agent); +#ifdef WINSCP + if (sess->realhost) ne_free(sess->realhost); +#endif if (sess->socks_user) ne_free(sess->socks_user); if (sess->socks_password) ne_free(sess->socks_password); @@ -455,6 +458,25 @@ void ne_fill_server_uri(ne_session *sess, ne_uri *uri) uri->scheme = ne_strdup(sess->scheme); } +#ifdef WINSCP +void ne_set_realhost(ne_session *sess, const char *realhost) +{ + if (sess->realhost) ne_free(sess->realhost); + sess->realhost = ne_strdup(realhost); +} + +void ne_fill_real_server_uri(ne_session *sess, ne_uri *uri) +{ + ne_fill_server_uri(sess, uri); + + if (sess->realhost) + { + ne_free(uri->host); + uri->host = ne_strdup(sess->realhost); + } +} +#endif + void ne_fill_proxy_uri(ne_session *sess, ne_uri *uri) { if (sess->proxies) { diff --git a/libs/neon/src/ne_session.h b/libs/neon/src/ne_session.h index ce9605c94..163860414 100644 --- a/libs/neon/src/ne_session.h +++ b/libs/neon/src/ne_session.h @@ -318,6 +318,10 @@ void ne_set_connect_timeout(ne_session *sess, int timeout); * where token is any alpha-numeric-y string [a-zA-Z0-9]* */ void ne_set_useragent(ne_session *sess, const char *product); +#ifdef WINSCP +void ne_set_realhost(ne_session *sess, const char *realhost); +#endif + /* Returns non-zero if next-hop server does not claim compliance to * HTTP/1.1 or later. */ int ne_version_pre_http11(ne_session *sess);