OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "bin/secure_socket.h" | 5 #include "bin/secure_socket.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3)); | 114 Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3)); |
115 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); | 115 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); |
116 Dart_Handle certificate_name_object = | 116 Dart_Handle certificate_name_object = |
117 ThrowIfError(Dart_GetNativeArgument(args, 5)); | 117 ThrowIfError(Dart_GetNativeArgument(args, 5)); |
118 bool request_client_certificate = | 118 bool request_client_certificate = |
119 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6)); | 119 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6)); |
120 bool require_client_certificate = | 120 bool require_client_certificate = |
121 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7)); | 121 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7)); |
122 bool send_client_certificate = | 122 bool send_client_certificate = |
123 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8)); | 123 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8)); |
124 Dart_Handle client_protocols_handle = | |
125 ThrowIfError(Dart_GetNativeArgument(args, 9)); | |
124 | 126 |
125 const char* host_name = NULL; | 127 const char* host_name = NULL; |
126 // TODO(whesse): Is truncating a Dart string containing \0 what we want? | 128 // TODO(whesse): Is truncating a Dart string containing \0 what we want? |
127 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); | 129 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); |
128 | 130 |
129 RawAddr raw_addr; | 131 RawAddr raw_addr; |
130 SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr); | 132 SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr); |
131 | 133 |
132 int64_t port; | 134 int64_t port; |
133 if (!DartUtils::GetInt64Value(port_object, &port)) { | 135 if (!DartUtils::GetInt64Value(port_object, &port)) { |
134 FATAL("The range of port_object was checked in Dart - it cannot fail here"); | 136 FATAL("The range of port_object was checked in Dart - it cannot fail here"); |
135 } | 137 } |
136 | 138 |
137 const char* certificate_name = NULL; | 139 const char* certificate_name = NULL; |
138 if (Dart_IsString(certificate_name_object)) { | 140 if (Dart_IsString(certificate_name_object)) { |
139 ThrowIfError(Dart_StringToCString(certificate_name_object, | 141 ThrowIfError(Dart_StringToCString(certificate_name_object, |
140 &certificate_name)); | 142 &certificate_name)); |
141 } | 143 } |
142 // If this is a server connection, it must have a certificate to connect with. | 144 // If this is a server connection, it must have a certificate to connect with. |
143 ASSERT(!is_server || certificate_name != NULL); | 145 ASSERT(!is_server || certificate_name != NULL); |
144 | 146 |
147 | |
148 | |
149 Dart_TypedData_Type protocols_type; | |
150 uint8_t* protocol_string = NULL; | |
151 intptr_t protocol_string_len = 0; | |
152 | |
153 ASSERT(!Dart_IsNull(client_protocols_handle)); | |
154 Dart_Handle result = Dart_TypedDataAcquireData( | |
155 client_protocols_handle, | |
156 &protocols_type, | |
157 reinterpret_cast<void**>(&protocol_string), | |
158 &protocol_string_len); | |
159 if (Dart_IsError(result)) { | |
160 Dart_PropagateError(result); | |
161 } | |
162 | |
163 if (protocols_type != Dart_TypedData_kUint8) { | |
164 Dart_TypedDataReleaseData(client_protocols_handle); | |
165 Dart_PropagateError( | |
166 Dart_NewApiError("Unexpected type for protocols")); | |
167 } | |
168 | |
145 GetFilter(args)->Connect(host_name, | 169 GetFilter(args)->Connect(host_name, |
146 &raw_addr, | 170 &raw_addr, |
147 static_cast<int>(port), | 171 static_cast<int>(port), |
148 is_server, | 172 is_server, |
149 certificate_name, | 173 certificate_name, |
150 request_client_certificate, | 174 request_client_certificate, |
151 require_client_certificate, | 175 require_client_certificate, |
152 send_client_certificate); | 176 send_client_certificate, |
177 protocol_string, | |
178 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
| |
179 Dart_TypedDataReleaseData(client_protocols_handle); | |
153 } | 180 } |
154 | 181 |
155 | 182 |
156 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { | 183 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { |
157 SSLFilter* filter = GetFilter(args); | 184 SSLFilter* filter = GetFilter(args); |
158 SetFilter(args, NULL); | 185 SetFilter(args, NULL); |
159 filter->Destroy(); | 186 filter->Destroy(); |
160 delete filter; | 187 delete filter; |
161 } | 188 } |
162 | 189 |
163 | 190 |
164 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) { | 191 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) { |
165 GetFilter(args)->Handshake(); | 192 GetFilter(args)->Handshake(); |
166 } | 193 } |
167 | 194 |
168 | 195 |
196 void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)( | |
197 Dart_NativeArguments args) { | |
198 GetFilter(args)->GetSelectedProtocol(args); | |
199 } | |
200 | |
201 | |
169 void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) { | 202 void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) { |
170 bool use_session_cache = | 203 bool use_session_cache = |
171 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1)); | 204 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1)); |
172 bool request_client_certificate = | 205 bool request_client_certificate = |
173 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2)); | 206 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2)); |
174 bool require_client_certificate = | 207 bool require_client_certificate = |
175 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)); | 208 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)); |
176 GetFilter(args)->Renegotiate(use_session_cache, | 209 GetFilter(args)->Renegotiate(use_session_cache, |
177 request_client_certificate, | 210 request_client_certificate, |
178 require_client_certificate); | 211 require_client_certificate); |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 } | 684 } |
652 | 685 |
653 | 686 |
654 void SSLFilter::Connect(const char* host_name, | 687 void SSLFilter::Connect(const char* host_name, |
655 RawAddr* raw_addr, | 688 RawAddr* raw_addr, |
656 int port, | 689 int port, |
657 bool is_server, | 690 bool is_server, |
658 const char* certificate_name, | 691 const char* certificate_name, |
659 bool request_client_certificate, | 692 bool request_client_certificate, |
660 bool require_client_certificate, | 693 bool require_client_certificate, |
661 bool send_client_certificate) { | 694 bool send_client_certificate, |
695 uint8_t *protocols, | |
696 intptr_t protocols_len) { | |
662 is_server_ = is_server; | 697 is_server_ = is_server; |
663 if (in_handshake_) { | 698 if (in_handshake_) { |
664 FATAL("Connect called twice on the same _SecureFilter."); | 699 FATAL("Connect called twice on the same _SecureFilter."); |
665 } | 700 } |
666 | 701 |
667 if (!is_server && certificate_name != NULL) { | 702 if (!is_server && certificate_name != NULL) { |
668 client_certificate_name_ = strdup(certificate_name); | 703 client_certificate_name_ = strdup(certificate_name); |
669 } | 704 } |
670 | 705 |
671 filter_ = SSL_ImportFD(NULL, filter_); | 706 filter_ = SSL_ImportFD(NULL, filter_); |
672 if (filter_ == NULL) { | 707 if (filter_ == NULL) { |
673 ThrowPRException("TlsException", "Failed SSL_ImportFD call"); | 708 ThrowPRException("TlsException", "Failed SSL_ImportFD call"); |
674 } | 709 } |
675 | 710 |
711 | |
712 SECStatus status; | |
713 | |
714 if (protocols_len > 0) { | |
715 status = SSL_OptionSet(filter_, SSL_ENABLE_ALPN, PR_TRUE); | |
716 ASSERT(status == SECSuccess); | |
717 | |
718 status = SSL_SetNextProtoNego(filter_, protocols, protocols_len); | |
719 ASSERT(status == SECSuccess); | |
720 } | |
721 | |
676 SSLVersionRange vrange; | 722 SSLVersionRange vrange; |
677 vrange.min = SSL_LIBRARY_VERSION_3_0; | 723 vrange.min = SSL_LIBRARY_VERSION_3_0; |
678 vrange.max = SSL_LIBRARY_VERSION_TLS_1_2; | 724 vrange.max = SSL_LIBRARY_VERSION_TLS_1_2; |
679 SSL_VersionRangeSet(filter_, &vrange); | 725 SSL_VersionRangeSet(filter_, &vrange); |
680 | 726 |
681 SECStatus status; | |
682 if (is_server) { | 727 if (is_server) { |
683 CERTCertificate* certificate = NULL; | 728 CERTCertificate* certificate = NULL; |
684 if (strstr(certificate_name, "CN=") != NULL) { | 729 if (strstr(certificate_name, "CN=") != NULL) { |
685 // Look up certificate using the distinguished name (DN) certificate_name. | 730 // Look up certificate using the distinguished name (DN) certificate_name. |
686 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); | 731 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); |
687 if (certificate_database == NULL) { | 732 if (certificate_database == NULL) { |
688 ThrowPRException("CertificateException", | 733 ThrowPRException("CertificateException", |
689 "Certificate database cannot be loaded"); | 734 "Certificate database cannot be loaded"); |
690 } | 735 } |
691 certificate = CERT_FindCertByNameString(certificate_database, | 736 certificate = CERT_FindCertByNameString(certificate_database, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
816 ThrowPRException("HandshakeException", | 861 ThrowPRException("HandshakeException", |
817 "Handshake error in server"); | 862 "Handshake error in server"); |
818 } else { | 863 } else { |
819 ThrowPRException("HandshakeException", | 864 ThrowPRException("HandshakeException", |
820 "Handshake error in client"); | 865 "Handshake error in client"); |
821 } | 866 } |
822 } | 867 } |
823 } | 868 } |
824 } | 869 } |
825 | 870 |
871 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) { | |
872 // Space for the selected protocol. | |
873 const intptr_t kBufferSize = 256; | |
874 unsigned char buffer[kBufferSize + 1]; | |
875 | |
876 unsigned int outLength = 0; | |
877 SSLNextProtoState outState; | |
878 | |
879 SECStatus status = SSL_GetNextProto( | |
880 filter_, &outState, buffer, &outLength, kBufferSize); | |
881 if (status == SECSuccess) { | |
882 if (outState == SSL_NEXT_PROTO_SELECTED || | |
883 outState == SSL_NEXT_PROTO_NEGOTIATED) { | |
884 ASSERT(outLength <= kBufferSize); | |
885 buffer[outLength] = '\0'; | |
886 Dart_Handle protocol_string = DartUtils::NewString( | |
887 reinterpret_cast<const char *>(&buffer[0])); | |
888 if (Dart_IsError(protocol_string)) { | |
889 ThrowPRException("HandshakeException", | |
890 "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.
| |
891 } else { | |
892 Dart_SetReturnValue(args, protocol_string); | |
893 } | |
894 } else if (outState == SSL_NEXT_PROTO_NO_OVERLAP) { | |
895 ThrowPRException("HandshakeException", | |
896 "Client and Server could not agree upon a protocol"); | |
897 } else if (outState == SSL_NEXT_PROTO_NO_SUPPORT) { | |
898 // A value of `null` denotes that the client did not support protocol | |
899 // negogiation. | |
900 Dart_SetReturnValue(args, Dart_Null()); | |
901 } else { | |
902 UNREACHABLE(); | |
903 } | |
904 } else { | |
905 ThrowPRException("HandshakeException", | |
906 "Could not retrieve selected protocol via ALPN"); | |
907 } | |
908 } | |
909 | |
826 | 910 |
827 void SSLFilter::Renegotiate(bool use_session_cache, | 911 void SSLFilter::Renegotiate(bool use_session_cache, |
828 bool request_client_certificate, | 912 bool request_client_certificate, |
829 bool require_client_certificate) { | 913 bool require_client_certificate) { |
830 SECStatus status; | 914 SECStatus status; |
831 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the | 915 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the |
832 // SSL_REQUEST_CERTIFICATE option is also set, so set it. | 916 // SSL_REQUEST_CERTIFICATE option is also set, so set it. |
833 request_client_certificate = | 917 request_client_certificate = |
834 request_client_certificate || require_client_certificate; | 918 request_client_certificate || require_client_certificate; |
835 | 919 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
960 } | 1044 } |
961 if (bytes_processed > 0) { | 1045 if (bytes_processed > 0) { |
962 memio_PutWriteResult(secret, bytes_processed); | 1046 memio_PutWriteResult(secret, bytes_processed); |
963 } | 1047 } |
964 } | 1048 } |
965 return bytes_processed; | 1049 return bytes_processed; |
966 } | 1050 } |
967 | 1051 |
968 } // namespace bin | 1052 } // namespace bin |
969 } // namespace dart | 1053 } // namespace dart |
OLD | NEW |