2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 83 SSL accelerator support */
12 #include "ssl/support.h"
14 /* support.cc says this is needed */
20 #include "ip/Address.h"
23 #if HAVE_OPENSSL_SSL_H
24 #include <openssl/ssl.h>
30 extern int socket_read_method(int, char *, int);
31 extern int socket_write_method(int, const char *, int);
35 static int squid_bio_write(BIO
*h
, const char *buf
, int num
);
36 static int squid_bio_read(BIO
*h
, char *buf
, int size
);
37 static int squid_bio_puts(BIO
*h
, const char *str
);
38 //static int squid_bio_gets(BIO *h, char *str, int size);
39 static long squid_bio_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
40 static int squid_bio_create(BIO
*h
);
41 static int squid_bio_destroy(BIO
*data
);
43 static void squid_ssl_info(const SSL
*ssl
, int where
, int ret
);
45 /// Initialization structure for the BIO table with
46 /// Squid-specific methods and BIO method wrappers.
47 static BIO_METHOD SquidMethods
= {
53 NULL
, // squid_bio_gets not supported
57 NULL
// squid_callback_ctrl not supported
61 Ssl::Bio::Create(const int fd
, Ssl::Bio::Type type
)
63 if (BIO
*bio
= BIO_new(&SquidMethods
)) {
64 BIO_int_ctrl(bio
, BIO_C_SET_FD
, type
, fd
);
71 Ssl::Bio::Link(SSL
*ssl
, BIO
*bio
)
73 SSL_set_bio(ssl
, bio
, bio
); // cannot fail
74 SSL_set_info_callback(ssl
, &squid_ssl_info
); // does not provide diagnostic
77 Ssl::Bio::Bio(const int anFd
): fd_(anFd
)
79 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_
);
84 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_
);
87 int Ssl::Bio::write(const char *buf
, int size
, BIO
*table
)
91 const int result
= socket_write_method(fd_
, buf
, size
);
93 const int result
= default_write_method(fd_
, buf
, size
);
95 const int xerrno
= errno
;
96 debugs(83, 5, "FD " << fd_
<< " wrote " << result
<< " <= " << size
);
98 BIO_clear_retry_flags(table
);
100 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
101 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
103 BIO_set_retry_write(table
);
110 Ssl::Bio::read(char *buf
, int size
, BIO
*table
)
114 const int result
= socket_read_method(fd_
, buf
, size
);
116 const int result
= default_read_method(fd_
, buf
, size
);
118 const int xerrno
= errno
;
119 debugs(83, 5, "FD " << fd_
<< " read " << result
<< " <= " << size
);
121 BIO_clear_retry_flags(table
);
123 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
124 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
126 BIO_set_retry_read(table
);
133 Ssl::Bio::readAndBuffer(char *buf
, int size
, BIO
*table
, const char *description
)
137 size
= min((int)rbuf
.potentialSpaceSize(), size
);
139 debugs(83, DBG_IMPORTANT
, "Not enough space to hold " <<
140 rbuf
.contentSize() << "+ byte " << description
);
144 const int bytes
= Ssl::Bio::read(buf
, size
, table
);
145 debugs(83, 5, "read " << bytes
<< " out of " << size
<< " bytes"); // move to Ssl::Bio::read()
148 rbuf
.append(buf
, bytes
);
149 debugs(83, 5, "recorded " << bytes
<< " bytes of " << description
);
154 /// Called whenever the SSL connection state changes, an alert appears, or an
155 /// error occurs. See SSL_set_info_callback().
157 Ssl::Bio::stateChanged(const SSL
*ssl
, int where
, int ret
)
159 // Here we can use (where & STATE) to check the current state.
160 // Many STATE values are possible, including: SSL_CB_CONNECT_LOOP,
161 // SSL_CB_ACCEPT_LOOP, SSL_CB_HANDSHAKE_START, and SSL_CB_HANDSHAKE_DONE.
163 // if (where & SSL_CB_HANDSHAKE_START)
164 // debugs(83, 9, "Trying to establish the SSL connection");
165 // else if (where & SSL_CB_HANDSHAKE_DONE)
166 // debugs(83, 9, "SSL connection established");
168 debugs(83, 7, "FD " << fd_
<< " now: 0x" << std::hex
<< where
<< std::dec
<< ' ' <<
169 SSL_state_string(ssl
) << " (" << SSL_state_string_long(ssl
) << ")");
173 Ssl::Bio::prepReadBuf()
176 rbuf
.init(4096, 65536);
180 Ssl::ClientBio::isClientHello(int state
)
183 state
== SSL3_ST_SR_CLNT_HELLO_A
||
184 state
== SSL23_ST_SR_CLNT_HELLO_A
||
185 state
== SSL23_ST_SR_CLNT_HELLO_B
||
186 state
== SSL3_ST_SR_CLNT_HELLO_B
||
187 state
== SSL3_ST_SR_CLNT_HELLO_C
192 Ssl::ClientBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
194 Ssl::Bio::stateChanged(ssl
, where
, ret
);
198 Ssl::ClientBio::write(const char *buf
, int size
, BIO
*table
)
201 BIO_set_retry_write(table
);
205 return Ssl::Bio::write(buf
, size
, table
);
208 const char *objToString(unsigned char const *bytes
, int len
)
210 static std::string buf
;
212 for (int i
= 0; i
< len
; i
++ ) {
214 snprintf(tmp
, sizeof(tmp
), "%.2x", bytes
[i
]);
221 Ssl::ClientBio::read(char *buf
, int size
, BIO
*table
)
223 if (helloState
< atHelloReceived
) {
224 int bytes
= readAndBuffer(buf
, size
, table
, "TLS client Hello");
229 if (helloState
== atHelloNone
) {
230 helloSize
= features
.parseMsgHead(rbuf
);
231 if (helloSize
== 0) {
232 // Not enough bytes to get hello message size
233 BIO_set_retry_read(table
);
235 } else if (helloSize
< 0) {
236 wrongProtocol
= true;
240 helloState
= atHelloStarted
; //Next state
243 if (helloState
== atHelloStarted
) {
244 const unsigned char *head
= (const unsigned char *)rbuf
.content();
245 const char *s
= objToString(head
, rbuf
.contentSize());
246 debugs(83, 7, "SSL Header: " << s
);
248 if (helloSize
> rbuf
.contentSize()) {
249 BIO_set_retry_read(table
);
253 helloState
= atHelloReceived
;
257 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size
<< "bytes)");
258 BIO_set_retry_read(table
);
262 if (helloState
== atHelloReceived
) {
263 if (rbuf
.hasContent()) {
264 int bytes
= (size
<= rbuf
.contentSize() ? size
: rbuf
.contentSize());
265 memcpy(buf
, rbuf
.content(), bytes
);
269 return Ssl::Bio::read(buf
, size
, table
);
276 Ssl::ServerBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
278 Ssl::Bio::stateChanged(ssl
, where
, ret
);
282 Ssl::ServerBio::setClientFeatures(const Ssl::Bio::sslFeatures
&features
)
284 clientFeatures
= features
;
288 Ssl::ServerBio::read(char *buf
, int size
, BIO
*table
)
291 readAndBuffer(buf
, size
, table
, "TLS server Hello") : Ssl::Bio::read(buf
, size
, table
);
294 // This function makes the required checks to examine if the client hello
295 // message is compatible with the features provided by OpenSSL toolkit.
296 // If the features are compatible and can be supported it tries to rewrite SSL
297 // structure members, to replace the hello message created by openSSL, with the
298 // web client SSL hello message.
299 // This is mostly possible in the cases where the web client uses openSSL
300 // library similar with this one used by squid.
302 adjustSSL(SSL
*ssl
, Ssl::Bio::sslFeatures
&features
)
304 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
306 debugs(83, 5, "No SSLv3 data found!");
310 // If the client supports compression but our context does not support
311 // we can not adjust.
312 #if !defined(OPENSSL_NO_COMP)
313 const bool requireCompression
= (features
.compressMethod
&& ssl
->ctx
->comp_methods
== NULL
);
315 const bool requireCompression
= features
.compressMethod
;
317 if (requireCompression
) {
318 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
322 // Check ciphers list
325 while (token
!= std::string::npos
) {
326 end
= features
.clientRequestedCiphers
.find(':',token
);
328 cipher
.assign(features
.clientRequestedCiphers
, token
, end
- token
);
329 token
= (end
!= std::string::npos
? end
+ 1 : std::string::npos
);
331 STACK_OF(SSL_CIPHER
) *cipher_stack
= SSL_get_ciphers(ssl
);
332 for (int i
= 0; i
< sk_SSL_CIPHER_num(cipher_stack
); i
++) {
333 SSL_CIPHER
*c
= sk_SSL_CIPHER_value(cipher_stack
, i
);
334 const char *cname
= SSL_CIPHER_get_name(c
);
335 if (cipher
.compare(cname
)) {
341 debugs(83, 5, "Client Hello Data supports cipher '"<< cipher
<<"' but we do not support it!");
346 #if !defined(SSL_TLSEXT_HB_ENABLED)
347 if (features
.doHeartBeats
) {
348 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
353 for (std::list
<int>::iterator it
= features
.extensions
.begin(); it
!= features
.extensions
.end(); ++it
) {
354 static int supportedExtensions
[] = {
355 #if defined(TLSEXT_TYPE_server_name)
356 TLSEXT_TYPE_server_name
,
358 #if defined(TLSEXT_TYPE_opaque_prf_input)
359 TLSEXT_TYPE_opaque_prf_input
,
361 #if defined(TLSEXT_TYPE_heartbeat)
362 TLSEXT_TYPE_heartbeat
,
364 #if defined(TLSEXT_TYPE_renegotiate)
365 TLSEXT_TYPE_renegotiate
,
367 #if defined(TLSEXT_TYPE_ec_point_formats)
368 TLSEXT_TYPE_ec_point_formats
,
370 #if defined(TLSEXT_TYPE_elliptic_curves)
371 TLSEXT_TYPE_elliptic_curves
,
373 #if defined(TLSEXT_TYPE_session_ticket)
374 TLSEXT_TYPE_session_ticket
,
376 #if defined(TLSEXT_TYPE_status_request)
377 TLSEXT_TYPE_status_request
,
379 #if defined(TLSEXT_TYPE_use_srtp)
380 TLSEXT_TYPE_use_srtp
,
382 #if 0 //Allow 13172 Firefox supported extension for testing purposes
388 for (int i
= 0; supportedExtensions
[i
] != -1; i
++) {
389 if (*it
== supportedExtensions
[i
]) {
395 debugs(83, 5, "Extension " << *it
<< " does not supported!");
400 SSL3_BUFFER
*wb
=&(ssl
->s3
->wbuf
);
401 if (wb
->len
< (size_t)features
.helloMessage
.length())
404 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
406 //Adjust ssl structure data.
407 // We need to fix the random in SSL struct:
408 memcpy(ssl
->s3
->client_random
, features
.client_random
, SSL3_RANDOM_SIZE
);
409 memcpy(wb
->buf
, features
.helloMessage
.rawContent(), features
.helloMessage
.length());
410 wb
->left
= features
.helloMessage
.length();
412 size_t mainHelloSize
= features
.helloMessage
.length() - 5;
413 const char *mainHello
= features
.helloMessage
.rawContent() + 5;
414 assert((size_t)ssl
->init_buf
->max
> mainHelloSize
);
415 memcpy(ssl
->init_buf
->data
, mainHello
, mainHelloSize
);
416 debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl
->init_num
<< " = "<< mainHelloSize
);
417 ssl
->init_num
= mainHelloSize
;
418 ssl
->s3
->wpend_ret
= mainHelloSize
;
419 ssl
->s3
->wpend_tot
= mainHelloSize
;
427 Ssl::ServerBio::write(const char *buf
, int size
, BIO
*table
)
431 debugs(83, 7, "Hold write, for SSL connection on " << fd_
<< "will not write bytes of size " << size
);
432 BIO_set_retry_write(table
);
436 if (!helloBuild
&& (bumpMode_
== Ssl::bumpPeek
|| bumpMode_
== Ssl::bumpStare
)) {
438 buf
[1] >= 3 //it is an SSL Version3 message
439 && buf
[0] == 0x16 // and it is a Handshake/Hello message
442 //Hello message is the first message we write to server
443 assert(helloMsg
.isEmpty());
445 SSL
*ssl
= fd_table
[fd_
].ssl
;
446 if (clientFeatures
.initialized_
&& ssl
) {
447 if (bumpMode_
== Ssl::bumpPeek
) {
448 if (adjustSSL(ssl
, clientFeatures
))
451 helloMsg
.append(clientFeatures
.helloMessage
);
452 debugs(83, 7, "SSL HELLO message for FD " << fd_
<< ": Random number is adjusted for peek mode");
453 } else { /*Ssl::bumpStare*/
455 if (adjustSSL(ssl
, clientFeatures
)) {
457 helloMsg
.append(clientFeatures
.helloMessage
);
458 debugs(83, 7, "SSL HELLO message for FD " << fd_
<< ": Random number is adjusted for stare mode");
463 // If we do not build any hello message, copy the current
464 if (helloMsg
.isEmpty())
465 helloMsg
.append(buf
, size
);
468 helloMsgSize
= helloMsg
.length();
472 // Do not write yet.....
473 BIO_set_retry_write(table
);
478 if (!helloMsg
.isEmpty()) {
479 debugs(83, 7, "buffered write for FD " << fd_
);
480 int ret
= Ssl::Bio::write(helloMsg
.rawContent(), helloMsg
.length(), table
);
481 helloMsg
.consume(ret
);
482 if (!helloMsg
.isEmpty()) {
483 // We need to retry sendind data.
484 // Say to openSSL to retry sending hello message
485 BIO_set_retry_write(table
);
489 // Sending hello message complete. Do not send more data for now...
492 // spoof openSSL that we write what it ask us to write
495 return Ssl::Bio::write(buf
, size
, table
);
499 Ssl::ServerBio::flush(BIO
*table
)
501 if (!helloMsg
.isEmpty()) {
502 int ret
= Ssl::Bio::write(helloMsg
.rawContent(), helloMsg
.length(), table
);
503 helloMsg
.consume(ret
);
508 Ssl::ServerBio::resumingSession()
510 if (!serverFeatures
.initialized_
)
511 serverFeatures
.get(rbuf
, false);
513 if (!clientFeatures
.sessionId
.isEmpty() && !serverFeatures
.sessionId
.isEmpty())
514 return clientFeatures
.sessionId
== serverFeatures
.sessionId
;
516 // is this a session resuming attempt using TLS tickets?
517 if (clientFeatures
.hasTlsTicket
&&
518 serverFeatures
.tlsTicketsExtension
&&
519 serverFeatures
.hasCcsOrNst
)
525 /// initializes BIO table after allocation
527 squid_bio_create(BIO
*bi
)
529 bi
->init
= 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
536 /// cleans BIO table before deallocation
538 squid_bio_destroy(BIO
*table
)
540 delete static_cast<Ssl::Bio
*>(table
->ptr
);
545 /// wrapper for Bio::write()
547 squid_bio_write(BIO
*table
, const char *buf
, int size
)
549 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(table
->ptr
);
551 return bio
->write(buf
, size
, table
);
554 /// wrapper for Bio::read()
556 squid_bio_read(BIO
*table
, char *buf
, int size
)
558 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(table
->ptr
);
560 return bio
->read(buf
, size
, table
);
563 /// implements puts() via write()
565 squid_bio_puts(BIO
*table
, const char *str
)
568 return squid_bio_write(table
, str
, strlen(str
));
571 /// other BIO manipulations (those without dedicated callbacks in BIO table)
573 squid_bio_ctrl(BIO
*table
, int cmd
, long arg1
, void *arg2
)
575 debugs(83, 5, table
<< ' ' << cmd
<< '(' << arg1
<< ", " << arg2
<< ')');
580 const int fd
= *static_cast<int*>(arg2
);
582 if (arg1
== Ssl::Bio::BIO_TO_SERVER
)
583 bio
= new Ssl::ServerBio(fd
);
585 bio
= new Ssl::ClientBio(fd
);
594 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(table
->ptr
);
597 *static_cast<int*>(arg2
) = bio
->fd();
603 // Should implemented if the SSL_dup openSSL API function
604 // used anywhere in squid.
609 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(table
->ptr
);
616 /* we may also need to implement these:
618 case BIO_C_FILE_SEEK:
619 case BIO_C_FILE_TELL:
621 case BIO_CTRL_GET_CLOSE:
622 case BIO_CTRL_SET_CLOSE:
623 case BIO_CTRL_PENDING:
624 case BIO_CTRL_WPENDING:
631 return 0; /* NOTREACHED */
634 /// wrapper for Bio::stateChanged()
636 squid_ssl_info(const SSL
*ssl
, int where
, int ret
)
638 if (BIO
*table
= SSL_get_rbio(ssl
)) {
639 if (Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(table
->ptr
))
640 bio
->stateChanged(ssl
, where
, ret
);
644 Ssl::Bio::sslFeatures::sslFeatures(): sslVersion(-1), compressMethod(-1), helloMsgSize(0), unknownCiphers(false), doHeartBeats(true), tlsTicketsExtension(false), hasTlsTicket(false), tlsStatusRequest(false), hasCcsOrNst(false), initialized_(false)
646 memset(client_random
, 0, SSL3_RANDOM_SIZE
);
649 int Ssl::Bio::sslFeatures::toSquidSSLVersion() const
651 if (sslVersion
== SSL2_VERSION
)
653 else if (sslVersion
== SSL3_VERSION
)
655 else if (sslVersion
== TLS1_VERSION
)
657 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
658 else if (sslVersion
== TLS1_1_VERSION
)
660 else if (sslVersion
== TLS1_2_VERSION
)
668 Ssl::Bio::sslFeatures::get(const SSL
*ssl
)
670 sslVersion
= SSL_version(ssl
);
671 debugs(83, 7, "SSL version: " << SSL_get_version(ssl
) << " (" << sslVersion
<< ")");
673 #if defined(TLSEXT_NAMETYPE_host_name)
674 if (const char *server
= SSL_get_servername(ssl
, TLSEXT_NAMETYPE_host_name
))
676 debugs(83, 7, "SNI server name: " << serverName
);
679 #if !defined(OPENSSL_NO_COMP)
680 if (ssl
->session
->compress_meth
)
681 compressMethod
= ssl
->session
->compress_meth
;
682 else if (sslVersion
>= 3) //if it is 3 or newer version then compression is disabled
685 debugs(83, 7, "SSL compression: " << compressMethod
);
687 STACK_OF(SSL_CIPHER
) * ciphers
= NULL
;
689 ciphers
= ssl
->session
->ciphers
;
691 ciphers
= ssl
->cipher_list
;
693 for (int i
= 0; i
< sk_SSL_CIPHER_num(ciphers
); ++i
) {
694 SSL_CIPHER
*c
= sk_SSL_CIPHER_value(ciphers
, i
);
696 if (!clientRequestedCiphers
.empty())
697 clientRequestedCiphers
.append(":");
698 clientRequestedCiphers
.append(c
->name
);
702 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers
);
704 if (sslVersion
>=3 && ssl
->s3
&& ssl
->s3
->client_random
[0]) {
705 memcpy(client_random
, ssl
->s3
->client_random
, SSL3_RANDOM_SIZE
);
708 #if 0 /* XXX: OpenSSL 0.9.8k lacks at least some of these tlsext_* fields */
709 //The following extracted for logging purpuses:
710 // TLSEXT_TYPE_ec_point_formats
714 p
= ssl
->session
->tlsext_ecpointformatlist
;
715 len
= ssl
->session
->tlsext_ecpointformatlist_length
;
717 p
= ssl
->tlsext_ecpointformatlist
;
718 len
= ssl
->tlsext_ecpointformatlist_length
;
721 ecPointFormatList
= objToString(p
, len
);
722 debugs(83, 7, "tlsExtension ecPointFormatList of length " << len
<< " :" << ecPointFormatList
);
725 // TLSEXT_TYPE_elliptic_curves
727 p
= ssl
->session
->tlsext_ellipticcurvelist
;
728 len
= ssl
->session
->tlsext_ellipticcurvelist_length
;
730 p
= ssl
->tlsext_ellipticcurvelist
;
731 len
= ssl
->tlsext_ellipticcurvelist_length
;
734 ellipticCurves
= objToString(p
, len
);
735 debugs(83, 7, "tlsExtension ellipticCurveList of length " << len
<<" :" << ellipticCurves
);
737 // TLSEXT_TYPE_opaque_prf_input
740 if (ssl
->s3
&& ssl
->s3
->client_opaque_prf_input
) {
741 p
= (unsigned char *)ssl
->s3
->client_opaque_prf_input
;
742 len
= ssl
->s3
->client_opaque_prf_input_len
;
745 p
= (unsigned char *)ssl
->tlsext_opaque_prf_input
;
746 len
= ssl
->tlsext_opaque_prf_input_len
;
749 debugs(83, 7, "tlsExtension client-opaque-prf-input of length " << len
);
750 opaquePrf
= objToString(p
, len
);
758 Ssl::Bio::sslFeatures::parseMsgHead(const MemBuf
&buf
)
760 const unsigned char *head
= (const unsigned char *)buf
.content();
761 const char *s
= objToString(head
, buf
.contentSize());
762 debugs(83, 7, "SSL Header: " << s
);
763 if (buf
.contentSize() < 5)
766 if (helloMsgSize
> 0)
769 // Check for SSLPlaintext/TLSPlaintext record
770 // RFC6101 section 5.2.1
771 // RFC5246 section 6.2.1
772 if (head
[0] == 0x16) {
773 debugs(83, 7, "SSL version 3 handshake message");
774 // The SSL version exist in the 2nd and 3rd bytes
775 sslVersion
= (head
[1] << 8) | head
[2];
776 debugs(83, 7, "SSL Version :" << std::hex
<< std::setw(8) << std::setfill('0') << sslVersion
);
777 // The hello message size exist in 4th and 5th bytes
778 helloMsgSize
= (head
[3] << 8) + head
[4];
779 debugs(83, 7, "SSL Header Size: " << helloMsgSize
);
781 #if defined(DO_SSLV23)
782 } else if ((head
[0] & 0x80) && head
[2] == 0x01 && head
[3] == 0x03) {
783 debugs(83, 7, "SSL version 2 handshake message with v3 support");
784 sslVersion
= (hello
[3] << 8) | hello
[4];
785 debugs(83, 7, "SSL Version :" << std::hex
<< std::setw(8) << std::setfill('0') << sslVersion
);
786 // The hello message size exist in 2nd byte
787 helloMsgSize
= head
[1];
791 debugs(83, 7, "Not an SSL acceptable handshake message (SSLv2 message?)");
792 return (helloMsgSize
= -1);
795 // Set object as initialized. Even if we did not full parsing yet
796 // The basic features, like the SSL version is set
802 Ssl::Bio::sslFeatures::checkForCcsOrNst(const unsigned char *msg
, size_t size
)
805 const int msgType
= msg
[0];
806 const int msgSslVersion
= (msg
[1] << 8) | msg
[2];
807 debugs(83, 7, "SSL Message Version :" << std::hex
<< std::setw(8) << std::setfill('0') << msgSslVersion
);
808 // Check for Change Cipher Spec message
809 // RFC5246 section 6.2.1
810 if (msgType
== 0x14) {// Change Cipher Spec message found
811 debugs(83, 7, "SSL Change Cipher Spec message found");
814 // Check for New Session Ticket message
815 // RFC5077 section 3.3
816 if (msgType
== 0x04) {// New Session Ticket message found
817 debugs(83, 7, "TLS New Session Ticket message found");
820 // The hello message size exist in 4th and 5th bytes
821 size_t msgLength
= (msg
[3] << 8) + msg
[4];
822 debugs(83, 7, "SSL Message Size: " << msgLength
);
825 if (msgLength
<= size
) {
835 Ssl::Bio::sslFeatures::get(const MemBuf
&buf
, bool record
)
838 if ((msgSize
= parseMsgHead(buf
)) <= 0) {
839 debugs(83, 7, "Not a known SSL handshake message");
843 if (msgSize
> buf
.contentSize()) {
844 debugs(83, 2, "Partial SSL handshake message, can not parse!");
849 helloMessage
.clear();
850 helloMessage
.append(buf
.content(), buf
.contentSize());
853 const unsigned char *msg
= (const unsigned char *)buf
.content();
854 #if defined(DO_SSLV23)
856 return parseV23Hello(msg
, (size_t)msgSize
);
860 // Hello messages require 5 bytes header + 1 byte Msg type + 3 bytes for Msg size
861 if (buf
.contentSize() < 9)
864 // Check for the Handshake/Message type
865 // The type 2 is a ServerHello, the type 1 is a ClientHello
866 // RFC5246 section 7.4
867 if (msg
[5] == 0x2) { // ServerHello message
868 if (parseV3ServerHello(msg
, (size_t)msgSize
)) {
869 hasCcsOrNst
= checkForCcsOrNst(msg
+ msgSize
, buf
.contentSize() - msgSize
);
872 } else if (msg
[5] == 0x1) // ClientHello message,
873 return parseV3Hello(msg
, (size_t)msgSize
);
880 Ssl::Bio::sslFeatures::parseV3ServerHello(const unsigned char *hello
, size_t size
)
882 // Parse a ServerHello Handshake message
883 // RFC5246 section 7.4, 7.4.1.3
884 // The ServerHello starts at hello+5
885 const size_t helloSize
= (hello
[6] << 16) | (hello
[7] << 8) | hello
[8];
886 debugs(83, 7, "ServerHello message size: " << helloSize
);
887 // helloSize should be msgSize + hello Header (4 bytes)
888 if (helloSize
+ 4 > size
) {
889 debugs(83, 2, "ServerHello parse error");
893 // helloSize should be at least 38 bytes long:
894 // (SSL Version + Random + SessionId Length + Cipher Suite + Compression Method)
895 if (helloSize
< 38) {
896 debugs(83, 2, "Too short ServerHello message");
900 debugs(83, 7, "Get fake features from v3 ServerHello message.");
901 // Get the correct version of the sub-hello message
902 sslVersion
= (hello
[9] << 8) | hello
[10];
903 // At the position 43 (MsgHeader(5 bytes) + HelloHeader (6bytes) + SSL3_RANDOM_SIZE (32bytes))
904 const size_t sessIdLen
= (size_t)hello
[43];
905 debugs(83, 7, "Session ID Length: " << sessIdLen
);
907 // The size should be enough to hold at least the following
908 // 5 MsgHelloHeader + 4 (hello header)
909 // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
910 // + sessIdLength + 2 (cipher suite) + 1 (compression method)
911 // = 47 + sessIdLength
912 if (47 + sessIdLen
> size
) {
913 debugs(83, 2, "ciphers length parse error");
917 // The sessionID stored at 44 position, after sessionID length field
918 sessionId
.assign((const char *)(hello
+ 44), sessIdLen
);
920 // Check if there are extensions in hello message
921 // RFC5246 section 7.4.1.4
922 if (size
> 47 + sessIdLen
+ 2) {
924 const unsigned char *pToExtensions
= hello
+ 47 + sessIdLen
;
925 const size_t extensionsLen
= (pToExtensions
[0] << 8) | pToExtensions
[1];
926 // Check if the hello size can hold extensions
927 if (47 + 2 + sessIdLen
+ extensionsLen
> size
) {
928 debugs(83, 2, "Extensions length parse error");
933 const unsigned char *ext
= pToExtensions
;
934 while (ext
+ 4 <= pToExtensions
+ extensionsLen
) {
935 const short extType
= (ext
[0] << 8) | ext
[1];
937 const short extLen
= (ext
[0] << 8) | ext
[1];
939 debugs(83, 7, "TLS Extension: " << std::hex
<< extType
<< " of size:" << extLen
);
940 // SessionTicket TLS Extension, RFC5077 section 3.2
941 if (extType
== 0x23) {
942 tlsTicketsExtension
= true;
951 Ssl::Bio::sslFeatures::parseV3Hello(const unsigned char *hello
, size_t size
)
953 // Parse a ClientHello Handshake message
954 // RFC5246 section 7.4, 7.4.1.2
955 // The ClientHello starts at hello+5
957 debugs(83, 7, "Get fake features from v3 ClientHello message.");
958 const size_t helloSize
= (hello
[6] << 16) | (hello
[7] << 8) | hello
[8];
959 debugs(83, 7, "ClientHello message size: " << helloSize
);
960 // helloSize should be size + hello Header (4 bytes)
961 if (helloSize
+ 4 > size
) {
962 debugs(83, 2, "ClientHello parse error");
966 // helloSize should be at least 38 bytes long:
967 // (SSL Version(2) + Random(32) + SessionId Length(1) + Cipher Suite Length(2) + Compression Method Length(1))
968 if (helloSize
< 38) {
969 debugs(83, 2, "Too short ClientHello message");
973 //For SSLv3 or TLSv1.* protocols we can get some more informations
974 if (hello
[1] == 0x3 && hello
[5] == 0x1 /*HELLO A message*/) {
975 // Get the correct version of the sub-hello message
976 sslVersion
= (hello
[9] << 8) | hello
[10];
977 //Get Client Random number. It starts on the position 11 of hello message
978 memcpy(client_random
, hello
+ 11, SSL3_RANDOM_SIZE
);
979 debugs(83, 7, "Client random: " << objToString(client_random
, SSL3_RANDOM_SIZE
));
981 // At the position 43 (11+SSL3_RANDOM_SIZE)
982 const size_t sessIDLen
= (size_t)hello
[43];
983 debugs(83, 7, "Session ID Length: " << sessIDLen
);
985 // The size should be enough to hold at least the following
986 // 5 MsgHelloHeader + 4 (hello header)
987 // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
988 // + sessIdLength + 2 (cipher suite length) + 1 (compression method length)
989 // = 47 + sessIdLength
990 if (47 + sessIDLen
> size
)
993 // The sessionID stored art 44 position, after sessionID length field
994 sessionId
.assign((const char *)(hello
+ 44), sessIDLen
);
996 //Ciphers list. It is stored after the Session ID.
997 // It is a variable-length vector(RFC5246 section 4.3)
998 const unsigned char *ciphers
= hello
+ 44 + sessIDLen
;
999 const size_t ciphersLen
= (ciphers
[0] << 8) | ciphers
[1];
1000 if (47 + sessIDLen
+ ciphersLen
> size
) {
1001 debugs(83, 2, "ciphers length parse error");
1007 const SSL_METHOD
*method
= SSLv3_method();
1008 const int cs
= method
->put_cipher_by_char(NULL
, NULL
);
1010 for (size_t i
= 0; i
< ciphersLen
; i
+= cs
) {
1011 const SSL_CIPHER
*c
= method
->get_cipher_by_char((ciphers
+ i
));
1013 if (!clientRequestedCiphers
.empty())
1014 clientRequestedCiphers
.append(":");
1015 clientRequestedCiphers
.append(c
->name
);
1017 unknownCiphers
= true;
1020 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers
);
1022 // Compression field: 1 bytes the number of compression methods and
1023 // 1 byte for each compression method
1024 const unsigned char *compression
= ciphers
+ ciphersLen
;
1025 if (compression
[0] > 1)
1029 debugs(83, 7, "SSL compression methods number: " << (int)compression
[0]);
1031 // Parse Extensions, RFC5246 section 7.4.1.4
1032 const unsigned char *pToExtensions
= compression
+ 1 + (int)compression
[0];
1033 if ((size_t)((pToExtensions
- hello
) + 2) < size
) {
1034 const size_t extensionsLen
= (pToExtensions
[0] << 8) | pToExtensions
[1];
1035 if ((pToExtensions
- hello
) + 2 + extensionsLen
> size
) {
1036 debugs(83, 2, "Extensions length parse error");
1041 const unsigned char *ext
= pToExtensions
;
1042 while (ext
+ 4 <= pToExtensions
+ extensionsLen
) {
1043 const short extType
= (ext
[0] << 8) | ext
[1];
1045 const short extLen
= (ext
[0] << 8) | ext
[1];
1047 debugs(83, 7, "TLS Extension: " << std::hex
<< extType
<< " of size:" << extLen
);
1049 if (ext
+ extLen
> pToExtensions
+ extensionsLen
) {
1050 debugs(83, 2, "Extension " << std::hex
<< extType
<< " length parser error");
1054 //The SNI extension has the type 0 (extType == 0)
1055 // RFC6066 sections 3, 10.2
1056 // The two first bytes indicates the length of the SNI data (should be extLen-2)
1057 // The next byte is the hostname type, it should be '0' for normal hostname (ext[2] == 0)
1058 // The 3rd and 4th bytes are the length of the hostname
1059 if (extType
== 0 && ext
[2] == 0) {
1060 const int hostLen
= (ext
[3] << 8) | ext
[4];
1061 serverName
.assign((const char *)(ext
+5), hostLen
);
1062 debugs(83, 7, "Found server name: " << serverName
);
1063 } else if (extType
== 15 && ext
[0] != 0) {
1064 // The heartBeats are the type 15, RFC6520
1065 doHeartBeats
= true;
1066 } else if (extType
== 0x23) {
1067 //SessionTicket TLS Extension RFC5077
1068 tlsTicketsExtension
= true;
1070 hasTlsTicket
= true;
1071 } else if (extType
== 0x05) {
1072 // RFC6066 sections 8, 10.2
1073 tlsStatusRequest
= true;
1074 } else if (extType
== 0x3374) {
1075 // detected TLS next protocol negotiate extension
1076 } else if (extType
== 0x10) {
1077 // Application-Layer Protocol Negotiation Extension, RFC7301
1078 const int listLen
= (ext
[0] << 8) | ext
[1];
1079 if (listLen
< extLen
)
1080 tlsAppLayerProtoNeg
.assign((const char *)(ext
+5), listLen
);
1082 extensions
.push_back(extType
);
1092 Ssl::Bio::sslFeatures::parseV23Hello(const unsigned char *hello
, size_t size
)
1094 #if defined(DO_SSLV23)
1095 debugs(83, 7, "Get fake features from v23 ClientHello message.");
1098 //Ciphers list. It is stored after the Session ID.
1099 const int ciphersLen
= (hello
[5] << 8) | hello
[6];
1100 const unsigned char *ciphers
= hello
+ 11;
1102 if (size
< ciphersLen
+ 11 + SSL3_RANDOM_SIZE
)
1106 const SSL_METHOD
*method
= SSLv23_method();
1107 int cs
= method
->put_cipher_by_char(NULL
, NULL
);
1109 for (int i
= 0; i
< ciphersLen
; i
+= cs
) {
1110 // The v2 hello messages cipher has 3 bytes.
1111 // The v2 cipher has the first byte not null
1112 // Because we are going to sent only v3 message we
1113 // are ignoring these ciphers
1114 if (ciphers
[i
] != 0)
1116 const SSL_CIPHER
*c
= method
->get_cipher_by_char((ciphers
+ i
+ 1));
1118 if (!clientRequestedCiphers
.empty())
1119 clientRequestedCiphers
.append(":");
1120 clientRequestedCiphers
.append(c
->name
);
1124 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers
);
1126 //Get Client Random number. It starts on the position 11 of hello message
1127 memcpy(client_random
, ciphers
+ ciphersLen
, SSL3_RANDOM_SIZE
);
1128 debugs(83, 7, "Client random: " << objToString(client_random
, SSL3_RANDOM_SIZE
));
1138 Ssl::Bio::sslFeatures::applyToSSL(SSL
*ssl
, Ssl::BumpMode bumpMode
) const
1140 // To increase the possibility for bumping after peek mode selection or
1141 // splicing after stare mode selection it is good to set the
1142 // SSL protocol version.
1143 // The SSL_set_ssl_method is not the correct method because it will strict
1144 // SSL version which can be used to the SSL version used for client hello message.
1145 // For example will prevent comunnicating with a tls1.0 server if the
1146 // client sent and tlsv1.2 Hello message.
1147 #if defined(TLSEXT_NAMETYPE_host_name)
1148 if (!serverName
.isEmpty()) {
1149 SSL_set_tlsext_host_name(ssl
, serverName
.c_str());
1152 if (!clientRequestedCiphers
.empty())
1153 SSL_set_cipher_list(ssl
, clientRequestedCiphers
.c_str());
1154 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
1155 if (compressMethod
== 0)
1156 SSL_set_options(ssl
, SSL_OP_NO_COMPRESSION
);
1159 #if defined(TLSEXT_STATUSTYPE_ocsp)
1160 if (tlsStatusRequest
)
1161 SSL_set_tlsext_status_type(ssl
, TLSEXT_STATUSTYPE_ocsp
);
1164 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
1165 if (!tlsAppLayerProtoNeg
.isEmpty()) {
1166 if (bumpMode
== Ssl::bumpPeek
)
1167 SSL_set_alpn_protos(ssl
, (const unsigned char*)tlsAppLayerProtoNeg
.rawContent(), tlsAppLayerProtoNeg
.length());
1169 static const unsigned char supported_protos
[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
1170 SSL_set_alpn_protos(ssl
, supported_protos
, sizeof(supported_protos
));
1177 Ssl::Bio::sslFeatures::print(std::ostream
&os
) const
1179 static std::string buf
;
1180 // TODO: Also print missing features like the HeartBeats and AppLayerProtoNeg
1181 return os
<< "v" << sslVersion
<<
1182 " SNI:" << (serverName
.isEmpty() ? SBuf("-") : serverName
) <<
1183 " comp:" << compressMethod
<<
1184 " Ciphers:" << clientRequestedCiphers
<<
1185 " Random:" << objToString(client_random
, SSL3_RANDOM_SIZE
) <<
1186 " ecPointFormats:" << ecPointFormatList
<<
1187 " ec:" << ellipticCurves
<<
1188 " opaquePrf:" << opaquePrf
;
1191 #endif /* USE_SSL */