Chromium Code Reviews| Index: dart/runtime/bin/secure_socket.cc |
| diff --git a/dart/runtime/bin/secure_socket.cc b/dart/runtime/bin/secure_socket.cc |
| index 350bc64afa395e1ca399f5441a3b524712b3ceaf..24c7ba43194db24c8a1675e877d5f679bf4c24ea 100644 |
| --- a/dart/runtime/bin/secure_socket.cc |
| +++ b/dart/runtime/bin/secure_socket.cc |
| @@ -121,6 +121,8 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { |
| DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7)); |
| bool send_client_certificate = |
| DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8)); |
| + Dart_Handle client_protocols_handle = |
| + ThrowIfError(Dart_GetNativeArgument(args, 9)); |
| const char* host_name = NULL; |
| // TODO(whesse): Is truncating a Dart string containing \0 what we want? |
| @@ -142,6 +144,28 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { |
| // If this is a server connection, it must have a certificate to connect with. |
| ASSERT(!is_server || certificate_name != NULL); |
| + |
| + |
| + Dart_TypedData_Type protocols_type; |
| + uint8_t* protocol_string = NULL; |
| + intptr_t protocol_string_len = 0; |
| + |
| + ASSERT(!Dart_IsNull(client_protocols_handle)); |
| + Dart_Handle result = Dart_TypedDataAcquireData( |
| + client_protocols_handle, |
| + &protocols_type, |
| + reinterpret_cast<void**>(&protocol_string), |
| + &protocol_string_len); |
| + if (Dart_IsError(result)) { |
| + Dart_PropagateError(result); |
| + } |
| + |
| + if (protocols_type != Dart_TypedData_kUint8) { |
| + Dart_TypedDataReleaseData(client_protocols_handle); |
| + Dart_PropagateError( |
| + Dart_NewApiError("Unexpected type for protocols")); |
| + } |
| + |
| GetFilter(args)->Connect(host_name, |
| &raw_addr, |
| static_cast<int>(port), |
| @@ -149,7 +173,10 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { |
| certificate_name, |
| request_client_certificate, |
| require_client_certificate, |
| - send_client_certificate); |
| + send_client_certificate, |
| + protocol_string, |
| + protocol_string_len); |
|
kustermann
2014/10/03 13:25:26
If GetFilter(args)->Connect() fails, can it unwind
Søren Gjesse
2014/10/03 15:47:04
As discussed off-line you need to release it befor
kustermann
2014/11/07 16:20:03
Instead of making more calls into the VM & copying
|
| + Dart_TypedDataReleaseData(client_protocols_handle); |
| } |
| @@ -166,6 +193,12 @@ void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) { |
| } |
| +void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)( |
| + Dart_NativeArguments args) { |
| + GetFilter(args)->GetSelectedProtocol(args); |
| +} |
| + |
| + |
| void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) { |
| bool use_session_cache = |
| DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1)); |
| @@ -658,7 +691,9 @@ void SSLFilter::Connect(const char* host_name, |
| const char* certificate_name, |
| bool request_client_certificate, |
| bool require_client_certificate, |
| - bool send_client_certificate) { |
| + bool send_client_certificate, |
| + uint8_t *protocols, |
| + intptr_t protocols_len) { |
| is_server_ = is_server; |
| if (in_handshake_) { |
| FATAL("Connect called twice on the same _SecureFilter."); |
| @@ -673,12 +708,22 @@ void SSLFilter::Connect(const char* host_name, |
| ThrowPRException("TlsException", "Failed SSL_ImportFD call"); |
| } |
| + |
| + SECStatus status; |
| + |
| + if (protocols_len > 0) { |
| + status = SSL_OptionSet(filter_, SSL_ENABLE_ALPN, PR_TRUE); |
| + ASSERT(status == SECSuccess); |
| + |
| + status = SSL_SetNextProtoNego(filter_, protocols, protocols_len); |
| + ASSERT(status == SECSuccess); |
| + } |
| + |
| SSLVersionRange vrange; |
| vrange.min = SSL_LIBRARY_VERSION_3_0; |
| vrange.max = SSL_LIBRARY_VERSION_TLS_1_2; |
| SSL_VersionRangeSet(filter_, &vrange); |
| - SECStatus status; |
| if (is_server) { |
| CERTCertificate* certificate = NULL; |
| if (strstr(certificate_name, "CN=") != NULL) { |
| @@ -823,6 +868,45 @@ void SSLFilter::Handshake() { |
| } |
| } |
| +void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) { |
| + // Space for the selected protocol. |
| + const intptr_t kBufferSize = 256; |
| + unsigned char buffer[kBufferSize + 1]; |
| + |
| + unsigned int outLength = 0; |
| + SSLNextProtoState outState; |
| + |
| + SECStatus status = SSL_GetNextProto( |
| + filter_, &outState, buffer, &outLength, kBufferSize); |
| + if (status == SECSuccess) { |
| + if (outState == SSL_NEXT_PROTO_SELECTED || |
| + outState == SSL_NEXT_PROTO_NEGOTIATED) { |
| + ASSERT(outLength <= kBufferSize); |
| + buffer[outLength] = '\0'; |
| + Dart_Handle protocol_string = DartUtils::NewString( |
| + reinterpret_cast<const char *>(&buffer[0])); |
| + if (Dart_IsError(protocol_string)) { |
| + ThrowPRException("HandshakeException", |
| + "Protocol selected via ALPN was non-UTF8"); |
|
Søren Gjesse
2014/10/03 15:47:04
In principle this could also be an OOM i think, or
kustermann
2014/11/07 16:20:02
Rephrased message.
|
| + } else { |
| + Dart_SetReturnValue(args, protocol_string); |
| + } |
| + } else if (outState == SSL_NEXT_PROTO_NO_OVERLAP) { |
| + ThrowPRException("HandshakeException", |
| + "Client and Server could not agree upon a protocol"); |
| + } else if (outState == SSL_NEXT_PROTO_NO_SUPPORT) { |
| + // A value of `null` denotes that the client did not support protocol |
| + // negogiation. |
| + Dart_SetReturnValue(args, Dart_Null()); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + ThrowPRException("HandshakeException", |
| + "Could not retrieve selected protocol via ALPN"); |
| + } |
| +} |
| + |
| void SSLFilter::Renegotiate(bool use_session_cache, |
| bool request_client_certificate, |