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

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: Created 6 years, 1 month 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
« no previous file with comments | « dart/runtime/bin/secure_socket.h ('k') | dart/runtime/bin/secure_socket_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 PRErrorCode error_code = PR_GetError(); 53 PRErrorCode error_code = PR_GetError();
54 const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN); 54 const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN);
55 OSError os_error_struct(error_code, error_message, OSError::kNSS); 55 OSError os_error_struct(error_code, error_message, OSError::kNSS);
56 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); 56 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
57 Dart_Handle exception = 57 Dart_Handle exception =
58 DartUtils::NewDartIOException(exception_type, message, os_error); 58 DartUtils::NewDartIOException(exception_type, message, os_error);
59 if (free_message) { 59 if (free_message) {
60 free(const_cast<char*>(message)); 60 free(const_cast<char*>(message));
61 } 61 }
62 Dart_ThrowException(exception); 62 Dart_ThrowException(exception);
63 UNREACHABLE();
63 } 64 }
64 65
65 66
66 static void ThrowCertificateException(const char* format, 67 static void ThrowCertificateException(const char* format,
67 const char* certificate_name) { 68 const char* certificate_name) {
68 int length = strlen(certificate_name); 69 int length = strlen(certificate_name);
69 length += strlen(format); 70 length += strlen(format);
70 char* message = reinterpret_cast<char*>(malloc(length + 1)); 71 char* message = reinterpret_cast<char*>(malloc(length + 1));
71 if (message == NULL) { 72 if (message == NULL) {
72 FATAL("Out of memory formatting CertificateException for throwing"); 73 FATAL("Out of memory formatting CertificateException for throwing");
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3)); 115 Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
115 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); 116 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
116 Dart_Handle certificate_name_object = 117 Dart_Handle certificate_name_object =
117 ThrowIfError(Dart_GetNativeArgument(args, 5)); 118 ThrowIfError(Dart_GetNativeArgument(args, 5));
118 bool request_client_certificate = 119 bool request_client_certificate =
119 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6)); 120 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6));
120 bool require_client_certificate = 121 bool require_client_certificate =
121 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7)); 122 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7));
122 bool send_client_certificate = 123 bool send_client_certificate =
123 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8)); 124 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8));
125 Dart_Handle protocols_handle =
126 ThrowIfError(Dart_GetNativeArgument(args, 9));
124 127
125 const char* host_name = NULL; 128 const char* host_name = NULL;
126 // TODO(whesse): Is truncating a Dart string containing \0 what we want? 129 // TODO(whesse): Is truncating a Dart string containing \0 what we want?
127 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); 130 ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
128 131
129 RawAddr raw_addr; 132 RawAddr raw_addr;
130 SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr); 133 SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr);
131 134
132 int64_t port; 135 int64_t port;
133 if (!DartUtils::GetInt64Value(port_object, &port)) { 136 if (!DartUtils::GetInt64Value(port_object, &port)) {
134 FATAL("The range of port_object was checked in Dart - it cannot fail here"); 137 FATAL("The range of port_object was checked in Dart - it cannot fail here");
135 } 138 }
136 139
137 const char* certificate_name = NULL; 140 const char* certificate_name = NULL;
138 if (Dart_IsString(certificate_name_object)) { 141 if (Dart_IsString(certificate_name_object)) {
139 ThrowIfError(Dart_StringToCString(certificate_name_object, 142 ThrowIfError(Dart_StringToCString(certificate_name_object,
140 &certificate_name)); 143 &certificate_name));
141 } 144 }
142 // If this is a server connection, it must have a certificate to connect with. 145 // If this is a server connection, it must have a certificate to connect with.
143 ASSERT(!is_server || certificate_name != NULL); 146 ASSERT(!is_server || certificate_name != NULL);
144 147
148 // The protocols_handle is guaranteed to be a valid Uint8List.
149 // It will have the correct length encoding of the protocols array.
150 ASSERT(!Dart_IsNull(protocols_handle));
151
145 GetFilter(args)->Connect(host_name, 152 GetFilter(args)->Connect(host_name,
146 &raw_addr, 153 &raw_addr,
147 static_cast<int>(port), 154 static_cast<int>(port),
148 is_server, 155 is_server,
149 certificate_name, 156 certificate_name,
150 request_client_certificate, 157 request_client_certificate,
151 require_client_certificate, 158 require_client_certificate,
152 send_client_certificate); 159 send_client_certificate,
160 protocols_handle);
153 } 161 }
154 162
155 163
156 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { 164 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
157 SSLFilter* filter = GetFilter(args); 165 SSLFilter* filter = GetFilter(args);
158 SetFilter(args, NULL); 166 SetFilter(args, NULL);
159 filter->Destroy(); 167 filter->Destroy();
160 delete filter; 168 delete filter;
161 } 169 }
162 170
163 171
164 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) { 172 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
165 GetFilter(args)->Handshake(); 173 GetFilter(args)->Handshake();
166 } 174 }
167 175
168 176
177 void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
178 Dart_NativeArguments args) {
179 GetFilter(args)->GetSelectedProtocol(args);
180 }
181
182
169 void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) { 183 void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
170 bool use_session_cache = 184 bool use_session_cache =
171 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1)); 185 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
172 bool request_client_certificate = 186 bool request_client_certificate =
173 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2)); 187 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
174 bool require_client_certificate = 188 bool require_client_certificate =
175 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)); 189 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
176 GetFilter(args)->Renegotiate(use_session_cache, 190 GetFilter(args)->Renegotiate(use_session_cache,
177 request_client_certificate, 191 request_client_certificate,
178 require_client_certificate); 192 require_client_certificate);
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 } 665 }
652 666
653 667
654 void SSLFilter::Connect(const char* host_name, 668 void SSLFilter::Connect(const char* host_name,
655 RawAddr* raw_addr, 669 RawAddr* raw_addr,
656 int port, 670 int port,
657 bool is_server, 671 bool is_server,
658 const char* certificate_name, 672 const char* certificate_name,
659 bool request_client_certificate, 673 bool request_client_certificate,
660 bool require_client_certificate, 674 bool require_client_certificate,
661 bool send_client_certificate) { 675 bool send_client_certificate,
676 Dart_Handle protocols_handle) {
662 is_server_ = is_server; 677 is_server_ = is_server;
663 if (in_handshake_) { 678 if (in_handshake_) {
664 FATAL("Connect called twice on the same _SecureFilter."); 679 FATAL("Connect called twice on the same _SecureFilter.");
665 } 680 }
666 681
667 if (!is_server && certificate_name != NULL) { 682 if (!is_server && certificate_name != NULL) {
668 client_certificate_name_ = strdup(certificate_name); 683 client_certificate_name_ = strdup(certificate_name);
669 } 684 }
670 685
671 filter_ = SSL_ImportFD(NULL, filter_); 686 filter_ = SSL_ImportFD(NULL, filter_);
672 if (filter_ == NULL) { 687 if (filter_ == NULL) {
673 ThrowPRException("TlsException", "Failed SSL_ImportFD call"); 688 ThrowPRException("TlsException", "Failed SSL_ImportFD call");
674 } 689 }
675 690
691
692 SECStatus status;
693
694 // Enable ALPN (application layer protocol negogiation) if the caller provides
695 // a valid list of supported protocols.
696 {
697 Dart_TypedData_Type protocols_type;
698 uint8_t* protocol_string = NULL;
699 intptr_t protocol_string_len = 0;
700
701 Dart_Handle result = Dart_TypedDataAcquireData(
702 protocols_handle,
703 &protocols_type,
704 reinterpret_cast<void**>(&protocol_string),
705 &protocol_string_len);
706 if (Dart_IsError(result)) {
707 Dart_PropagateError(result);
708 }
709
710 if (protocols_type != Dart_TypedData_kUint8) {
711 Dart_TypedDataReleaseData(protocols_handle);
712 Dart_PropagateError(Dart_NewApiError(
713 "Unexpected type for protocols (expected valid Uint8List)."));
714 }
715
716 if (protocol_string_len > 0) {
717 status = SSL_OptionSet(filter_, SSL_ENABLE_ALPN, PR_TRUE);
718 ASSERT(status == SECSuccess);
719
720 status = SSL_SetNextProtoNego(filter_,
721 protocol_string,
722 protocol_string_len);
723 ASSERT(status == SECSuccess);
724 }
725
726 Dart_TypedDataReleaseData(protocols_handle);
727 }
728
676 SSLVersionRange vrange; 729 SSLVersionRange vrange;
677 vrange.min = SSL_LIBRARY_VERSION_3_0; 730 vrange.min = SSL_LIBRARY_VERSION_3_0;
678 vrange.max = SSL_LIBRARY_VERSION_TLS_1_2; 731 vrange.max = SSL_LIBRARY_VERSION_TLS_1_2;
679 SSL_VersionRangeSet(filter_, &vrange); 732 SSL_VersionRangeSet(filter_, &vrange);
680 733
681 SECStatus status;
682 if (is_server) { 734 if (is_server) {
683 CERTCertificate* certificate = NULL; 735 CERTCertificate* certificate = NULL;
684 if (strstr(certificate_name, "CN=") != NULL) { 736 if (strstr(certificate_name, "CN=") != NULL) {
685 // Look up certificate using the distinguished name (DN) certificate_name. 737 // Look up certificate using the distinguished name (DN) certificate_name.
686 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); 738 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
687 if (certificate_database == NULL) { 739 if (certificate_database == NULL) {
688 ThrowPRException("CertificateException", 740 ThrowPRException("CertificateException",
689 "Certificate database cannot be loaded"); 741 "Certificate database cannot be loaded");
690 } 742 }
691 certificate = CERT_FindCertByNameString(certificate_database, 743 certificate = CERT_FindCertByNameString(certificate_database,
(...skipping 21 matching lines...) Expand all
713 CERT_DestroyCertificate(certificate); 765 CERT_DestroyCertificate(certificate);
714 if (PR_GetError() == -8177) { 766 if (PR_GetError() == -8177) {
715 ThrowPRException("CertificateException", 767 ThrowPRException("CertificateException",
716 "Certificate database password incorrect"); 768 "Certificate database password incorrect");
717 } else { 769 } else {
718 ThrowCertificateException( 770 ThrowCertificateException(
719 "Cannot find private key for certificate %s", 771 "Cannot find private key for certificate %s",
720 certificate_name); 772 certificate_name);
721 } 773 }
722 } 774 }
775
723 // kt_rsa (key type RSA) is an enum constant from the NSS libraries. 776 // kt_rsa (key type RSA) is an enum constant from the NSS libraries.
724 // TODO(whesse): Allow different key types. 777 // TODO(whesse): Allow different key types.
725 status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa); 778 status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa);
726 CERT_DestroyCertificate(certificate); 779 CERT_DestroyCertificate(certificate);
727 SECKEY_DestroyPrivateKey(key); 780 SECKEY_DestroyPrivateKey(key);
728 if (status != SECSuccess) { 781 if (status != SECSuccess) {
729 ThrowCertificateException( 782 ThrowCertificateException(
730 "Failed SSL_ConfigSecureServer call with certificate %s", 783 "Failed SSL_ConfigSecureServer call with certificate %s",
731 certificate_name); 784 certificate_name);
732 } 785 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 ThrowPRException("HandshakeException", 869 ThrowPRException("HandshakeException",
817 "Handshake error in server"); 870 "Handshake error in server");
818 } else { 871 } else {
819 ThrowPRException("HandshakeException", 872 ThrowPRException("HandshakeException",
820 "Handshake error in client"); 873 "Handshake error in client");
821 } 874 }
822 } 875 }
823 } 876 }
824 } 877 }
825 878
879 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
880 // Space for the selected protocol.
881 const unsigned int kBufferSize = 256;
882 unsigned char buffer[kBufferSize + 1];
883
884 unsigned int outLength = 0;
885 SSLNextProtoState outState;
886
887 SECStatus status = SSL_GetNextProto(
888 filter_, &outState, buffer, &outLength, kBufferSize);
889 if (status == SECSuccess) {
890 if (outState == SSL_NEXT_PROTO_SELECTED ||
891 outState == SSL_NEXT_PROTO_NEGOTIATED) {
892 ASSERT(outLength <= kBufferSize);
893 buffer[outLength] = '\0';
894 Dart_Handle protocol_string = DartUtils::NewString(
895 reinterpret_cast<const char *>(&buffer[0]));
896 if (Dart_IsError(protocol_string)) {
897 ThrowPRException("HandshakeException",
898 "Protocol selected via ALPN, unable to get protocol "
899 "string.");
900 } else {
901 Dart_SetReturnValue(args, protocol_string);
902 }
903 } else if (outState == SSL_NEXT_PROTO_NO_OVERLAP) {
904 ThrowPRException("HandshakeException",
905 "Client and Server could not agree upon a protocol");
906 } else if (outState == SSL_NEXT_PROTO_NO_SUPPORT) {
907 // A value of `null` denotes that the client did not support protocol
908 // negogiation.
909 Dart_SetReturnValue(args, Dart_Null());
910 } else {
911 UNREACHABLE();
912 }
913 } else {
914 ThrowPRException("HandshakeException",
915 "Could not retrieve selected protocol via ALPN");
916 }
917 }
918
826 919
827 void SSLFilter::Renegotiate(bool use_session_cache, 920 void SSLFilter::Renegotiate(bool use_session_cache,
828 bool request_client_certificate, 921 bool request_client_certificate,
829 bool require_client_certificate) { 922 bool require_client_certificate) {
830 SECStatus status; 923 SECStatus status;
831 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the 924 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
832 // SSL_REQUEST_CERTIFICATE option is also set, so set it. 925 // SSL_REQUEST_CERTIFICATE option is also set, so set it.
833 request_client_certificate = 926 request_client_certificate =
834 request_client_certificate || require_client_certificate; 927 request_client_certificate || require_client_certificate;
835 928
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
960 } 1053 }
961 if (bytes_processed > 0) { 1054 if (bytes_processed > 0) {
962 memio_PutWriteResult(secret, bytes_processed); 1055 memio_PutWriteResult(secret, bytes_processed);
963 } 1056 }
964 } 1057 }
965 return bytes_processed; 1058 return bytes_processed;
966 } 1059 }
967 1060
968 } // namespace bin 1061 } // namespace bin
969 } // namespace dart 1062 } // namespace dart
OLDNEW
« no previous file with comments | « dart/runtime/bin/secure_socket.h ('k') | dart/runtime/bin/secure_socket_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698