Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: dart/runtime/bin/secure_socket.cc

Issue 625953002: Support for the ALPN extension of the TLS protocol for Client and Server (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add test for ALPN negotiation Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698