Repository: trafficserver Updated Branches: refs/heads/master 63ce14d10 -> c030977ab
TS-2802: add SNI support for origin server connections Set the SNI name when making SSL origin server connections. Update IP address literal parsing to accept ptr+len pairs as well as NUL-terminated strings. This required removing default arguments in the ConstBuffer constructor, since they cause nasty implicit conversions. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/c030977a Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/c030977a Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/c030977a Branch: refs/heads/master Commit: c030977ab94cc05b48e7a578b9fa1de4949b026d Parents: 63ce14d Author: Wei Sun <[email protected]> Authored: Wed Jul 30 08:53:12 2014 -0700 Committer: James Peach <[email protected]> Committed: Wed Jul 30 09:25:26 2014 -0700 ---------------------------------------------------------------------- CHANGES | 3 +++ iocore/net/I_NetVConnection.h | 33 ++++++++++++++++++++++++++++++++- iocore/net/P_UnixNetVConnection.h | 3 +++ iocore/net/SSLNetVConnection.cc | 10 ++++++++++ lib/ts/TsBuffer.h | 14 ++++++-------- lib/ts/ink_inet.cc | 4 ++-- lib/ts/ink_inet.h | 20 +++++++++++++++++--- proxy/ControlBase.cc | 4 ++-- proxy/hdrs/MIME.cc | 2 +- proxy/hdrs/URL.cc | 2 +- proxy/http/HttpSM.cc | 3 +++ 11 files changed, 80 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index a5c7dbd..d21fc8a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 5.1.0 + *) [TS-2802] Add SNI support for origin server connections. + Author: Wei Sun <[email protected]> + *) [TS-2958] url_sig: remove printf's and make redirects use appropriate status codes. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/iocore/net/I_NetVConnection.h ---------------------------------------------------------------------- diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h index 5223267..dcf86a7 100644 --- a/iocore/net/I_NetVConnection.h +++ b/iocore/net/I_NetVConnection.h @@ -159,21 +159,52 @@ struct NetVCOptions { EventType etype; + char * sni_servername; // SSL SNI to origin + /// Reset all values to defaults. void reset(); void set_sock_param(int _recv_bufsize, int _send_bufsize, unsigned long _opt_flags, unsigned long _packet_mark = 0, unsigned long _packet_tos = 0); - NetVCOptions() { + NetVCOptions() : sni_servername(NULL) { reset(); } + ~NetVCOptions() { + ats_free(sni_servername); + } + + void set_sni_servername(const char * name, size_t len) { + IpEndpoint ip; + + ats_free(sni_servername); + sni_servername = NULL; + // Literal IPv4 and IPv6 addresses are not permitted in "HostName".(rfc6066#section-3) + if (ats_ip_pton(ts::ConstBuffer(name, len), &ip) != 0) { + sni_servername = ats_strndup(name, len); + } + } + + NetVCOptions & operator=(const NetVCOptions & opt) { + if (&opt != this) { + ats_free(this->sni_servername); + memcpy(this, &opt, sizeof(opt)); + if (opt.sni_servername) { + this->sni_servername = ats_strdup(opt.sni_servername); + } + } + return *this; + } + /// @name Debugging //@{ /// Convert @a s to its string equivalent. static char const* toString(addr_bind_style s); //@} + +private: + NetVCOptions(const NetVCOptions&); }; /** http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/iocore/net/P_UnixNetVConnection.h ---------------------------------------------------------------------- diff --git a/iocore/net/P_UnixNetVConnection.h b/iocore/net/P_UnixNetVConnection.h index 867b11d..0b7845e 100644 --- a/iocore/net/P_UnixNetVConnection.h +++ b/iocore/net/P_UnixNetVConnection.h @@ -65,6 +65,9 @@ NetVCOptions::reset() packet_tos = 0; etype = ET_NET; + + ats_free(sni_servername); + sni_servername = NULL; } TS_INLINE void http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/iocore/net/SSLNetVConnection.cc ---------------------------------------------------------------------- diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 67aabbc..0f4a6b3 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -648,6 +648,16 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err) { int ret; +#if TS_USE_TLS_SNI + if (options.sni_servername) { + if (SSL_set_tlsext_host_name(ssl, options.sni_servername)) { + Debug("ssl", "using SNI name '%s' for client handshake", options.sni_servername); + } else { + SSLError("failed to set SNI name '%s' for client handshake", options.sni_servername); + } + } +#endif + ret = SSL_connect(ssl); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/lib/ts/TsBuffer.h ---------------------------------------------------------------------- diff --git a/lib/ts/TsBuffer.h b/lib/ts/TsBuffer.h index dbcd72e..1abc6fe 100644 --- a/lib/ts/TsBuffer.h +++ b/lib/ts/TsBuffer.h @@ -53,7 +53,6 @@ namespace ts { size_t _size; ///< Size of memory chunk. /// Default constructor. - /// Elements are in uninitialized state. Buffer(); /** Construct from pointer and size. @@ -62,7 +61,7 @@ namespace ts { */ Buffer( char* ptr, ///< Pointer to buffer. - size_t n = 0 ///< Size of buffer. + size_t n ///< Size of buffer. ); /** Construct from two pointers. @note This presumes a half open range, (start, end] @@ -143,7 +142,6 @@ namespace ts { size_t _size; ///< Size of memory chunk. /// Default constructor. - /// Elements are in uninitialized state. ConstBuffer(); /** Construct from pointer and size. @@ -152,7 +150,7 @@ namespace ts { */ ConstBuffer( char const * ptr, ///< Pointer to buffer. - size_t n = 0///< Size of buffer. + size_t n ///< Size of buffer. ); /** Construct from two pointers. @note This presumes a half open range (start, end] @@ -305,7 +303,7 @@ namespace ts { // ---------------------------------------------------------- // Inline implementations. - inline Buffer::Buffer() { } + inline Buffer::Buffer() : _ptr(NULL), _size(0) { } inline Buffer::Buffer(char* ptr, size_t n) : _ptr(ptr), _size(n) { } inline Buffer& Buffer::set(char* ptr, size_t n) { _ptr = ptr; _size = n; return *this; } inline Buffer::Buffer(char* start, char* end) : _ptr(start), _size(end - start) { } @@ -329,7 +327,7 @@ namespace ts { inline char * Buffer::data() const { return _ptr; } inline size_t Buffer::size() const { return _size; } - inline ConstBuffer::ConstBuffer() { } + inline ConstBuffer::ConstBuffer() : _ptr(NULL), _size(0) { } inline ConstBuffer::ConstBuffer(char const* ptr, size_t n) : _ptr(ptr), _size(n) { } inline ConstBuffer::ConstBuffer(char const* start, char const* end) : _ptr(start), _size(end - start) { } inline ConstBuffer::ConstBuffer(Buffer const& that) : _ptr(that._ptr), _size(that._size) { } @@ -372,7 +370,7 @@ namespace ts { } inline ConstBuffer ConstBuffer::splitOn(char const* p) { - self zret(0); // default to empty return. + self zret; // default to empty return. if (this->contains(p)) { size_t n = p - _ptr; zret.set(_ptr, n); @@ -391,7 +389,7 @@ namespace ts { } inline ConstBuffer ConstBuffer::after(char const* p) const { - return this->contains(p) ? self(p + 1, (_size-(p-_ptr))-1) : self(0); + return this->contains(p) ? self(p + 1, (_size-(p-_ptr))-1) : self(); } inline ConstBuffer ConstBuffer::after(char c) const { return this->after(this->find(c)); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/lib/ts/ink_inet.cc ---------------------------------------------------------------------- diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc index 3221ab2..5cff34f 100644 --- a/lib/ts/ink_inet.cc +++ b/lib/ts/ink_inet.cc @@ -246,10 +246,10 @@ ats_ip_parse(ts::ConstBuffer src, ts::ConstBuffer* addr, ts::ConstBuffer* port) } int -ats_ip_pton(char const* text, sockaddr* ip) { +ats_ip_pton(const ts::ConstBuffer& src, sockaddr* ip) +{ int zret = -1; ts::ConstBuffer addr, port; - ts::ConstBuffer src(text, strlen(text)+1); ats_ip_invalidate(ip); if (0 == ats_ip_parse(src, &addr, &port)) { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/lib/ts/ink_inet.h ---------------------------------------------------------------------- diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h index fcaca0d..30ebc8f 100644 --- a/lib/ts/ink_inet.h +++ b/lib/ts/ink_inet.h @@ -953,7 +953,7 @@ inline char const* ats_ip_nptop( @return 0 on success, non-zero on failure. */ int ats_ip_pton( - char const* text, ///< [in] text. + const ts::ConstBuffer& text, ///< [in] text. sockaddr* addr ///< [out] address ); @@ -972,16 +972,30 @@ inline int ats_ip_pton( char const* text, ///< [in] text. sockaddr_in6* addr ///< [out] address ) { - return ats_ip_pton(text, ats_ip_sa_cast(addr)); + return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), ats_ip_sa_cast(addr)); } inline int ats_ip_pton( - char const* text, ///< [in] text. + const ts::ConstBuffer& text, ///< [in] text. IpEndpoint* addr ///< [out] address ) { return ats_ip_pton(text, &addr->sa); } +inline int ats_ip_pton( + const char * text, ///< [in] text. + IpEndpoint* addr ///< [out] address +) { + return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), &addr->sa); +} + +inline int ats_ip_pton( + const char * text, ///< [in] text. + sockaddr * addr ///< [out] address +) { + return ats_ip_pton(ts::ConstBuffer(text, strlen(text)), addr); +} + /** Get the best address info for @a name. @name is passed to @c getaddrinfo which does a host lookup if @a http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/proxy/ControlBase.cc ---------------------------------------------------------------------- diff --git a/proxy/ControlBase.cc b/proxy/ControlBase.cc index 710f3be..be24137 100644 --- a/proxy/ControlBase.cc +++ b/proxy/ControlBase.cc @@ -350,7 +350,7 @@ struct TextMod : public ControlBase::Modifier { }; -TextMod::TextMod() : text(0) {} +TextMod::TextMod() : text() {} TextMod::~TextMod() { free(text.data()); } @@ -390,7 +390,7 @@ void MultiTextMod::set(char * value) { Tokenizer rangeTok(","); int num_tok = rangeTok.Initialize(value, SHARE_TOKS); for(int i = 0; i < num_tok; i++){ - ts::Buffer text(0); + ts::Buffer text; text.set(ats_strdup(rangeTok[i]), strlen(rangeTok[i])); this->text_vec.push_back(text); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/proxy/hdrs/MIME.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/MIME.cc b/proxy/hdrs/MIME.cc index 2cf3e9b..18976a2 100644 --- a/proxy/hdrs/MIME.cc +++ b/proxy/hdrs/MIME.cc @@ -2160,7 +2160,7 @@ MIMEField* MIMEHdr::get_host_port_values( if (field) { ts::ConstBuffer b(field->m_ptr_value, field->m_len_value); - ts::ConstBuffer host(0), port(0); + ts::ConstBuffer host, port; if (b) { char const* x; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/proxy/hdrs/URL.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/URL.cc b/proxy/hdrs/URL.cc index 65930e9..732e018 100644 --- a/proxy/hdrs/URL.cc +++ b/proxy/hdrs/URL.cc @@ -1167,7 +1167,7 @@ url_parse_internet(HdrHeap* heap, URLImpl* url, char const* cur = *start; char const* base; // Base for host/port field. char const* bracket = 0; // marker for open bracket, if any. - ts::ConstBuffer user(0), passw(0), host(0), port(0); + ts::ConstBuffer user, passw, host, port; static size_t const MAX_COLON = 8; // max # of valid colons. size_t n_colon = 0; char const* last_colon = 0; // pointer to last colon seen. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c030977a/proxy/http/HttpSM.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 5d7239c..e7c6d2f 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -4641,6 +4641,9 @@ HttpSM::do_http_server_open(bool raw) if (scheme_to_use == URL_WKSIDX_HTTPS) { DebugSM("http", "calling sslNetProcessor.connect_re"); + int len = 0; + const char * host = t_state.hdr_info.server_request.host_get(&len); + opt.set_sni_servername(host, len); connect_action_handle = sslNetProcessor.connect_re(this, // state machine &t_state.current.server->addr.sa, // addr + port &opt);
