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

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

Issue 1319703002: Breaking Change: merge BoringSSL branch into master (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 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
« no previous file with comments | « runtime/bin/secure_socket.h ('k') | 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>
11 #include <string.h> 11 #include <string.h>
12 12
13 #include <key.h> 13 #include <openssl/bio.h>
14 #include <keyt.h> 14 #include <openssl/err.h>
15 #include <nss.h> 15 #include <openssl/safestack.h>
16 #include <pk11pub.h> 16 #include <openssl/ssl.h>
17 #include <prerror.h> 17 #include <openssl/tls1.h>
18 #include <prinit.h> 18 #include <openssl/x509.h>
19 #include <prnetdb.h>
20 #include <secmod.h>
21 #include <ssl.h>
22 #include <sslproto.h>
23 19
24 #include "bin/builtin.h" 20 #include "bin/builtin.h"
25 #include "bin/dartutils.h" 21 #include "bin/dartutils.h"
26 #include "bin/lockers.h" 22 #include "bin/lockers.h"
27 #include "bin/net/nss_memio.h" 23 #include "bin/log.h"
28 #include "bin/socket.h" 24 #include "bin/socket.h"
29 #include "bin/thread.h" 25 #include "bin/thread.h"
30 #include "bin/utils.h" 26 #include "bin/utils.h"
31 #include "platform/utils.h" 27 #include "platform/utils.h"
32 28
33 #include "include/dart_api.h" 29 #include "include/dart_api.h"
34 30
35
36 namespace dart { 31 namespace dart {
37 namespace bin { 32 namespace bin {
38 33
39 bool SSLFilter::library_initialized_ = false; 34 bool SSLFilter::library_initialized_ = false;
40 // To protect library initialization. 35 // To protect library initialization.
41 Mutex* SSLFilter::mutex_ = new Mutex(); 36 Mutex* SSLFilter::mutex_ = new Mutex();
42 // The password is needed when creating secure server sockets. It can 37 int SSLFilter::filter_ssl_index;
43 // be null if only secure client sockets are used.
44 const char* SSLFilter::password_ = NULL;
45 38
46 static const int kSSLFilterNativeFieldIndex = 0; 39 static const int kSSLFilterNativeFieldIndex = 0;
40 static const int kSecurityContextNativeFieldIndex = 0;
41 static const int kX509NativeFieldIndex = 0;
47 42
43 static const bool SSL_LOG_STATUS = false;
44 static const bool SSL_LOG_DATA = false;
48 45
49 /* Handle an error reported from the NSS library. */ 46 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 200;
50 static void ThrowPRException(const char* exception_type, 47
48 /* Handle an error reported from the BoringSSL library. */
49 static void ThrowIOException(const char* exception_type,
51 const char* message, 50 const char* message,
52 bool free_message = false) { 51 bool free_message = false) {
53 PRErrorCode error_code = PR_GetError(); 52 // TODO(24068): Get the error code and message from the error stack.
54 const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN); 53 // There may be more than one error on the stack - should we
55 OSError os_error_struct(error_code, error_message, OSError::kNSS); 54 // concatenate the error messages?
55 int error_code = 0;
56 const char* error_message = "Unknown error from BoringSSL library";
57 OSError os_error_struct(error_code, error_message, OSError::kBoringSSL);
56 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); 58 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
57 Dart_Handle exception = 59 Dart_Handle exception =
58 DartUtils::NewDartIOException(exception_type, message, os_error); 60 DartUtils::NewDartIOException(exception_type, message, os_error);
59 if (free_message) { 61 if (free_message) {
60 free(const_cast<char*>(message)); 62 free(const_cast<char*>(message));
61 } 63 }
62 Dart_ThrowException(exception); 64 Dart_ThrowException(exception);
63 UNREACHABLE(); 65 UNREACHABLE();
64 } 66 }
65 67
66 68
67 static void ThrowCertificateException(const char* format,
68 const char* certificate_name) {
69 int length = strlen(certificate_name);
70 length += strlen(format);
71 char* message = reinterpret_cast<char*>(malloc(length + 1));
72 if (message == NULL) {
73 FATAL("Out of memory formatting CertificateException for throwing");
74 }
75 snprintf(message, length + 1, format, certificate_name);
76 message[length] = '\0';
77 ThrowPRException("CertificateException", message, true);
78 }
79
80
81 static SSLFilter* GetFilter(Dart_NativeArguments args) { 69 static SSLFilter* GetFilter(Dart_NativeArguments args) {
82 SSLFilter* filter; 70 SSLFilter* filter;
83 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); 71 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
84 ASSERT(Dart_IsInstance(dart_this)); 72 ASSERT(Dart_IsInstance(dart_this));
85 ThrowIfError(Dart_GetNativeInstanceField( 73 ThrowIfError(Dart_GetNativeInstanceField(
86 dart_this, 74 dart_this,
87 kSSLFilterNativeFieldIndex, 75 kSSLFilterNativeFieldIndex,
88 reinterpret_cast<intptr_t*>(&filter))); 76 reinterpret_cast<intptr_t*>(&filter)));
89 return filter; 77 return filter;
90 } 78 }
91 79
92 80
93 static void SetFilter(Dart_NativeArguments args, SSLFilter* filter) { 81 static void SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
94 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); 82 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
95 ASSERT(Dart_IsInstance(dart_this)); 83 ASSERT(Dart_IsInstance(dart_this));
96 ThrowIfError(Dart_SetNativeInstanceField( 84 ThrowIfError(Dart_SetNativeInstanceField(
97 dart_this, 85 dart_this,
98 kSSLFilterNativeFieldIndex, 86 kSSLFilterNativeFieldIndex,
99 reinterpret_cast<intptr_t>(filter))); 87 reinterpret_cast<intptr_t>(filter)));
100 } 88 }
101 89
102 90
91 static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) {
92 SSL_CTX* context;
93 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
94 ASSERT(Dart_IsInstance(dart_this));
95 ThrowIfError(Dart_GetNativeInstanceField(
96 dart_this,
97 kSecurityContextNativeFieldIndex,
98 reinterpret_cast<intptr_t*>(&context)));
99 return context;
100 }
101
102
103 static void SetSecurityContext(Dart_NativeArguments args,
104 SSL_CTX* context) {
105 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
106 ASSERT(Dart_IsInstance(dart_this));
107 ThrowIfError(Dart_SetNativeInstanceField(
108 dart_this,
109 kSecurityContextNativeFieldIndex,
110 reinterpret_cast<intptr_t>(context)));
111 }
112
113
114 static X509* GetX509Certificate(Dart_NativeArguments args) {
115 X509* certificate;
116 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
117 ASSERT(Dart_IsInstance(dart_this));
118 ThrowIfError(Dart_GetNativeInstanceField(
119 dart_this,
120 kX509NativeFieldIndex,
121 reinterpret_cast<intptr_t*>(&certificate)));
122 return certificate;
123 }
124
125
126 // Forward declaration.
127 static void SetAlpnProtocolList(Dart_Handle protocols_handle,
128 SSL* ssl,
129 SSL_CTX* context,
130 bool is_server);
131
132
103 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { 133 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
104 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); 134 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
105 SSLFilter* filter = new SSLFilter; 135 SSLFilter* filter = new SSLFilter;
106 SetFilter(args, filter); 136 SetFilter(args, filter);
107 filter->Init(dart_this); 137 filter->Init(dart_this);
108 } 138 }
109 139
110 140
111 void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { 141 void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
112 Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 142 Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
113 Dart_Handle host_sockaddr_storage_object = 143 Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
114 ThrowIfError(Dart_GetNativeArgument(args, 2)); 144 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
115 Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
116 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
117 Dart_Handle certificate_name_object =
118 ThrowIfError(Dart_GetNativeArgument(args, 5));
119 bool request_client_certificate = 145 bool request_client_certificate =
146 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
147 bool require_client_certificate =
148 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
149 bool send_client_certificate =
120 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6)); 150 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6));
121 bool require_client_certificate =
122 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7));
123 bool send_client_certificate =
124 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8));
125 Dart_Handle protocols_handle = 151 Dart_Handle protocols_handle =
126 ThrowIfError(Dart_GetNativeArgument(args, 9)); 152 ThrowIfError(Dart_GetNativeArgument(args, 7));
127 153
128 const char* host_name = NULL; 154 const char* host_name = NULL;
129 // TODO(whesse): Is truncating a Dart string containing \0 what we want? 155 // TODO(whesse): Is truncating a Dart string containing \0 what we want?
130 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); 156 ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
131 157
132 RawAddr raw_addr; 158 SSL_CTX* context = NULL;
133 SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr); 159 if (!Dart_IsNull(context_object)) {
134 160 ThrowIfError(Dart_GetNativeInstanceField(
135 int64_t port; 161 context_object,
136 if (!DartUtils::GetInt64Value(port_object, &port)) { 162 kSecurityContextNativeFieldIndex,
137 FATAL("The range of port_object was checked in Dart - it cannot fail here"); 163 reinterpret_cast<intptr_t*>(&context)));
138 } 164 }
139 165
140 const char* certificate_name = NULL;
141 if (Dart_IsString(certificate_name_object)) {
142 ThrowIfError(Dart_StringToCString(certificate_name_object,
143 &certificate_name));
144 }
145 // If this is a server connection, it must have a certificate to connect with.
146 ASSERT(!is_server || certificate_name != NULL);
147
148 // The protocols_handle is guaranteed to be a valid Uint8List. 166 // The protocols_handle is guaranteed to be a valid Uint8List.
149 // It will have the correct length encoding of the protocols array. 167 // It will have the correct length encoding of the protocols array.
150 ASSERT(!Dart_IsNull(protocols_handle)); 168 ASSERT(!Dart_IsNull(protocols_handle));
151 169
152 GetFilter(args)->Connect(host_name, 170 GetFilter(args)->Connect(host_name,
153 raw_addr, 171 context,
154 static_cast<int>(port),
155 is_server, 172 is_server,
156 certificate_name,
157 request_client_certificate, 173 request_client_certificate,
158 require_client_certificate, 174 require_client_certificate,
159 send_client_certificate, 175 send_client_certificate,
160 protocols_handle); 176 protocols_handle);
161 } 177 }
162 178
163 179
164 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { 180 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
165 SSLFilter* filter = GetFilter(args); 181 SSLFilter* filter = GetFilter(args);
166 SetFilter(args, NULL); 182 SetFilter(args, NULL);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 Dart_Handle callback = 226 Dart_Handle callback =
211 ThrowIfError(Dart_GetNativeArgument(args, 1)); 227 ThrowIfError(Dart_GetNativeArgument(args, 1));
212 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) { 228 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
213 Dart_ThrowException(DartUtils::NewDartArgumentError( 229 Dart_ThrowException(DartUtils::NewDartArgumentError(
214 "Illegal argument to RegisterBadCertificateCallback")); 230 "Illegal argument to RegisterBadCertificateCallback"));
215 } 231 }
216 GetFilter(args)->RegisterBadCertificateCallback(callback); 232 GetFilter(args)->RegisterBadCertificateCallback(callback);
217 } 233 }
218 234
219 235
220 void FUNCTION_NAME(SecureSocket_InitializeLibrary) 236 void FUNCTION_NAME(SecureSocket_PeerCertificate)
221 (Dart_NativeArguments args) { 237 (Dart_NativeArguments args) {
222 Dart_Handle certificate_database_object = 238 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
223 ThrowIfError(Dart_GetNativeArgument(args, 0)); 239 }
224 // Check that the type is string, and get the UTF-8 C string value from it. 240
225 const char* certificate_database = NULL; 241
226 if (Dart_IsString(certificate_database_object)) { 242 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
227 ThrowIfError(Dart_StringToCString(certificate_database_object, 243 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
228 &certificate_database)); 244 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
229 } else if (!Dart_IsNull(certificate_database_object)) { 245 }
230 Dart_ThrowException(DartUtils::NewDartArgumentError( 246
231 "Non-String certificate directory argument to SetCertificateDatabase")); 247
232 } 248 static Dart_Handle WrappedX509Certificate(X509* certificate) {
233 // Leave certificate_database as NULL if no value was provided. 249 if (certificate == NULL) return Dart_Null();
234 250 Dart_Handle x509_type =
235 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 251 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
236 // Check that the type is string or null, 252 if (Dart_IsError(x509_type)) {
237 // and get the UTF-8 C string value from it. 253 return x509_type;
254 }
255 Dart_Handle arguments[] = { NULL };
256 Dart_Handle result =
257 Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
258 if (Dart_IsError(result)) {
259 return result;
260 }
261 ASSERT(Dart_IsInstance(result));
262 Dart_Handle status = Dart_SetNativeInstanceField(
263 result,
264 kX509NativeFieldIndex,
265 reinterpret_cast<intptr_t>(certificate));
266 if (Dart_IsError(status)) {
267 return status;
268 }
269 return result;
270 }
271
272
273 int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) {
274 if (preverify_ok == 1) return 1;
275 Dart_Isolate isolate = Dart_CurrentIsolate();
276 if (isolate == NULL) {
277 FATAL("CertificateCallback called with no current isolate\n");
278 }
279 X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx);
280 int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
281 SSL* ssl = static_cast<SSL*>(
282 X509_STORE_CTX_get_ex_data(store_ctx, ssl_index));
283 SSLFilter* filter = static_cast<SSLFilter*>(
284 SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
285 Dart_Handle callback = filter->bad_certificate_callback();
286 if (Dart_IsNull(callback)) return 0;
287 Dart_Handle args[1];
288 args[0] = WrappedX509Certificate(certificate);
289 if (Dart_IsError(args[0])) {
290 filter->callback_error = args[0];
291 return 0;
292 }
293 Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
294 if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
295 result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
296 "HandshakeException",
297 "BadCertificateCallback returned a value that was not a boolean",
298 Dart_Null()));
299 }
300 if (Dart_IsError(result)) {
301 filter->callback_error = result;
302 return 0;
303 }
304 return DartUtils::GetBooleanValue(result);
305 }
306
307
308 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
309 SSLFilter::InitializeLibrary();
310 SSL_CTX* context = SSL_CTX_new(TLS_method());
311 SSL_CTX_set_verify(context, SSL_VERIFY_PEER, CertificateCallback);
312 SSL_CTX_set_min_version(context, TLS1_VERSION);
313 SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM");
314 SSL_CTX_set_cipher_list_tls11(context, "HIGH:MEDIUM");
315 SetSecurityContext(args, context);
316 // TODO(whesse): Use WeakPersistentHandle to free the SSL_CTX
317 // when the object is GC'd. Also free the alpn_select_cb data pointer,
318 // if non-null (allocated in SetAlpnProtocolList).
319 }
320
321
322 int PasswordCallback(char* buf, int size, int rwflag, void* userdata) {
323 char* password = static_cast<char*>(userdata);
324 if (static_cast<size_t>(size) < strlen(password) + 1) {
325 Log::PrintErr("Password buffer too small.\n");
326 exit(1);
327 // TODO(24182): Find the actual value of size passed in here, and
328 // check for password length longer than this in the Dart function
329 // that passes in the password, so we never have this problem.
330 }
331 strncpy(buf, static_cast<char*>(userdata), size);
332 return strlen(static_cast<char*>(userdata));
333 }
334
335
336 void CheckStatus(int status, const char* message, int line) {
337 // TODO(24183): Take appropriate action on failed calls,
338 // throw exception that includes all messages from the error stack.
339 if (status != 1 && SSL_LOG_STATUS) {
340 int error = ERR_get_error();
341 Log::PrintErr("Failed: %s line %d\n", message, line);
342 char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
343 ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
344 Log::PrintErr("ERROR: %d %s\n", error, error_string);
345 }
346 }
347
348
349 void FUNCTION_NAME(SecurityContext_UsePrivateKey)(Dart_NativeArguments args) {
350 SSL_CTX* context = GetSecurityContext(args);
351 Dart_Handle filename_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
352 const char* filename = NULL;
353 if (Dart_IsString(filename_object)) {
354 ThrowIfError(Dart_StringToCString(filename_object, &filename));
355 } else {
356 Dart_ThrowException(DartUtils::NewDartArgumentError(
357 "File argument to SecurityContext.usePrivateKey is not a String"));
358 }
359 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
238 const char* password = NULL; 360 const char* password = NULL;
239 if (Dart_IsString(password_object)) { 361 if (Dart_IsString(password_object)) {
240 ThrowIfError(Dart_StringToCString(password_object, &password)); 362 ThrowIfError(Dart_StringToCString(password_object, &password));
241 } else if (Dart_IsNull(password_object)) { 363 } else if (Dart_IsNull(password_object)) {
242 // Pass the empty string as the password.
243 password = ""; 364 password = "";
244 } else { 365 } else {
245 Dart_ThrowException(DartUtils::NewDartArgumentError( 366 Dart_ThrowException(DartUtils::NewDartArgumentError(
246 "Password argument to SetCertificateDatabase is not a String or null")); 367 "Password argument to SecurityContext.usePrivateKey is not "
247 } 368 "a String or null"));
248 369 }
249 Dart_Handle builtin_roots_object = 370
371 SSL_CTX_set_default_passwd_cb(context, PasswordCallback);
372 SSL_CTX_set_default_passwd_cb_userdata(context, const_cast<char*>(password));
373 int status = SSL_CTX_use_PrivateKey_file(context,
374 filename,
375 SSL_FILETYPE_PEM);
376 // TODO(24184): Handle different expected errors here - file missing,
377 // incorrect password, file not a PEM, and throw exceptions.
378 // CheckStatus should also throw an exception in uncaught cases.
379 CheckStatus(status, "SSL_CTX_use_PrivateKey_file", __LINE__);
380 SSL_CTX_set_default_passwd_cb_userdata(context, NULL);
381 }
382
383
384 void FUNCTION_NAME(SecurityContext_SetTrustedCertificates)(
385 Dart_NativeArguments args) {
386 SSL_CTX* context = GetSecurityContext(args);
387 Dart_Handle filename_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
388 const char* filename = NULL;
389 if (Dart_IsString(filename_object)) {
390 ThrowIfError(Dart_StringToCString(filename_object, &filename));
391 }
392 Dart_Handle directory_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
393 const char* directory = NULL;
394 if (Dart_IsString(directory_object)) {
395 ThrowIfError(Dart_StringToCString(directory_object, &directory));
396 } else if (Dart_IsNull(directory_object)) {
397 directory = NULL;
398 } else {
399 Dart_ThrowException(DartUtils::NewDartArgumentError(
400 "Directory argument to SecurityContext.usePrivateKey is not "
401 "a String or null"));
402 }
403
404 int status = SSL_CTX_load_verify_locations(context, filename, directory);
405 CheckStatus(status, "SSL_CTX_load_verify_locations", __LINE__);
406 }
407
408
409 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
410 Dart_NativeArguments args) {
411 SSL_CTX* context = GetSecurityContext(args);
412 X509_STORE* store = SSL_CTX_get_cert_store(context);
413 BIO* roots_bio =
414 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem),
415 root_certificates_pem_length);
416 X509* root_cert;
417 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case,
418 // backed by a memory buffer), and returns X509 objects, one by one.
419 // When the end of the bio is reached, it returns null.
420 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) {
421 X509_STORE_add_cert(store, root_cert);
422 }
423 BIO_free(roots_bio);
424 }
425
426
427 void FUNCTION_NAME(SecurityContext_UseCertificateChain)(
428 Dart_NativeArguments args) {
429 SSL_CTX* context = GetSecurityContext(args);
430 Dart_Handle filename_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
431 const char* filename = NULL;
432 if (Dart_IsString(filename_object)) {
433 ThrowIfError(Dart_StringToCString(filename_object, &filename));
434 } else {
435 Dart_ThrowException(DartUtils::NewDartArgumentError(
436 "file argument in SecurityContext.useCertificateChain"
437 " is not a String"));
438 }
439 int status = SSL_CTX_use_certificate_chain_file(context, filename);
440 CheckStatus(status, "SSL_CTX_use_certificate_chain_file", __LINE__);
441 }
442
443
444 void FUNCTION_NAME(SecurityContext_SetClientAuthorities)(
445 Dart_NativeArguments args) {
446 SSL_CTX* context = GetSecurityContext(args);
447 Dart_Handle filename_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
448 const char* filename = NULL;
449 if (Dart_IsString(filename_object)) {
450 ThrowIfError(Dart_StringToCString(filename_object, &filename));
451 } else {
452 Dart_ThrowException(DartUtils::NewDartArgumentError(
453 "file argument in SecurityContext.setClientAuthorities"
454 " is not a String"));
455 }
456 STACK_OF(X509_NAME)* certificate_names;
457 certificate_names = SSL_load_client_CA_file(filename);
458 if (certificate_names != NULL) {
459 SSL_CTX_set_client_CA_list(context, certificate_names);
460 } else {
461 Dart_ThrowException(DartUtils::NewDartArgumentError(
462 "Could not load certificate names from file in SetClientAuthorities"));
463 }
464 }
465
466
467 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
468 Dart_NativeArguments args) {
469 SSL_CTX* context = GetSecurityContext(args);
470 Dart_Handle protocols_handle =
471 ThrowIfError(Dart_GetNativeArgument(args, 1));
472 Dart_Handle is_server_handle =
250 ThrowIfError(Dart_GetNativeArgument(args, 2)); 473 ThrowIfError(Dart_GetNativeArgument(args, 2));
251 // Check that the type is boolean, and get the boolean value from it. 474 if (Dart_IsBoolean(is_server_handle)) {
252 bool builtin_roots = true; 475 bool is_server = DartUtils::GetBooleanValue(is_server_handle);
253 if (Dart_IsBoolean(builtin_roots_object)) { 476 SetAlpnProtocolList(protocols_handle, NULL, context, is_server);
254 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots)); 477 } else {
255 } else { 478 Dart_ThrowException(DartUtils::NewDartArgumentError(
256 Dart_ThrowException(DartUtils::NewDartArgumentError( 479 "Non-boolean is_server argument passed to SetAlpnProtocols"));
257 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); 480 }
258 } 481 }
259 482
260 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); 483
261 } 484 void FUNCTION_NAME(X509_Subject)(
262 485 Dart_NativeArguments args) {
263 486 X509* certificate = GetX509Certificate(args);
264 void FUNCTION_NAME(SecureSocket_PeerCertificate) 487 X509_NAME* subject = X509_get_subject_name(certificate);
265 (Dart_NativeArguments args) { 488 char* subject_string = X509_NAME_oneline(subject, NULL, 0);
266 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); 489 Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_string));
267 } 490 OPENSSL_free(subject_string);
268 491 }
269 492
270 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { 493
271 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); 494 void FUNCTION_NAME(X509_Issuer)(
272 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); 495 Dart_NativeArguments args) {
273 } 496 X509* certificate = GetX509Certificate(args);
274 497 X509_NAME* issuer = X509_get_issuer_name(certificate);
275 498 char* issuer_string = X509_NAME_oneline(issuer, NULL, 0);
499 Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_string));
500 OPENSSL_free(issuer_string);
501 }
502
503 static Dart_Handle ASN1TimeToMilliseconds(ASN1_TIME* aTime) {
504 ASN1_UTCTIME* epoch_start = M_ASN1_UTCTIME_new();
505 ASN1_UTCTIME_set_string(epoch_start, "700101000000Z");
506 int days;
507 int seconds;
508 int result = ASN1_TIME_diff(&days, &seconds, epoch_start, aTime);
509 M_ASN1_UTCTIME_free(epoch_start);
510 if (result != 1) {
511 // TODO(whesse): Propagate an error to Dart.
512 Log::PrintErr("ASN1Time error %d\n", result);
513 }
514 return Dart_NewInteger((86400LL * days + seconds) * 1000LL);
515 }
516
517 void FUNCTION_NAME(X509_StartValidity)(
518 Dart_NativeArguments args) {
519 X509* certificate = GetX509Certificate(args);
520 ASN1_TIME* not_before = X509_get_notBefore(certificate);
521 Dart_SetReturnValue(args, ASN1TimeToMilliseconds(not_before));
522 }
523
524
525 void FUNCTION_NAME(X509_EndValidity)(
526 Dart_NativeArguments args) {
527 X509* certificate = GetX509Certificate(args);
528 ASN1_TIME* not_after = X509_get_notAfter(certificate);
529 Dart_SetReturnValue(args, ASN1TimeToMilliseconds(not_after));
530 }
531
532
276 /** 533 /**
277 * Pushes data through the SSL filter, reading and writing from circular 534 * Pushes data through the SSL filter, reading and writing from circular
278 * buffers shared with Dart. 535 * buffers shared with Dart.
279 * 536 *
280 * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to 537 * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
281 * pass encrypted and plaintext data to and from the C++ SSLFilter object. 538 * pass encrypted and plaintext data to and from the C++ SSLFilter object.
282 * 539 *
283 * ProcessFilter is called with a CObject array containing the pointer to 540 * ProcessFilter is called with a CObject array containing the pointer to
284 * the SSLFilter, encoded as an int, and the start and end positions of the 541 * the SSLFilter, encoded as an int, and the start and end positions of the
285 * valid data in the four circular buffers. The function only reads from 542 * valid data in the four circular buffers. The function only reads from
(...skipping 21 matching lines...) Expand all
307 564
308 if (filter->ProcessAllBuffers(starts, ends, in_handshake)) { 565 if (filter->ProcessAllBuffers(starts, ends, in_handshake)) {
309 CObjectArray* result = new CObjectArray( 566 CObjectArray* result = new CObjectArray(
310 CObject::NewArray(SSLFilter::kNumBuffers * 2)); 567 CObject::NewArray(SSLFilter::kNumBuffers * 2));
311 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) { 568 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
312 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i]))); 569 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
313 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i]))); 570 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
314 } 571 }
315 return result; 572 return result;
316 } else { 573 } else {
317 PRErrorCode error_code = PR_GetError(); 574 // TODO(24185): Extract the BoringSSL OS error here and return it.
318 const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN); 575 int error_code = 1;
576 const char* error_message = "Obsolete PR Error message";
319 CObjectArray* result = new CObjectArray(CObject::NewArray(2)); 577 CObjectArray* result = new CObjectArray(CObject::NewArray(2));
320 result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code))); 578 result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
321 result->SetAt(1, new CObjectString(CObject::NewString(error_message))); 579 result->SetAt(1, new CObjectString(CObject::NewString(error_message)));
322 return result; 580 return result;
323 } 581 }
324 } 582 }
325 583
326 584
327 bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers], 585 bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
328 int ends[kNumBuffers], 586 int ends[kNumBuffers],
(...skipping 29 matching lines...) Expand all
358 int bytes = (i == kReadPlaintext) ? 616 int bytes = (i == kReadPlaintext) ?
359 ProcessReadPlaintextBuffer(end, start - 1) : 617 ProcessReadPlaintextBuffer(end, start - 1) :
360 ProcessWriteEncryptedBuffer(end, start - 1); 618 ProcessWriteEncryptedBuffer(end, start - 1);
361 if (bytes < 0) return false; 619 if (bytes < 0) return false;
362 end += bytes; 620 end += bytes;
363 ASSERT(end < start); 621 ASSERT(end < start);
364 } 622 }
365 ends[i] = end; 623 ends[i] = end;
366 break; 624 break;
367 case kReadEncrypted: 625 case kReadEncrypted:
368 // Read data from circular buffer. 626 case kWritePlaintext:
627 // Read/Write data from circular buffer. If the buffer is empty,
628 // neither if statement's condition is true.
369 if (end < start) { 629 if (end < start) {
370 // Data may be split into two segments. In this case, 630 // Data may be split into two segments. In this case,
371 // the first is [start, size). 631 // the first is [start, size).
372 int bytes = ProcessReadEncryptedBuffer(start, size); 632 int bytes = (i == kReadEncrypted) ?
633 ProcessReadEncryptedBuffer(start, size) :
634 ProcessWritePlaintextBuffer(start, size);
373 if (bytes < 0) return false; 635 if (bytes < 0) return false;
374 start += bytes; 636 start += bytes;
375 ASSERT(start <= size); 637 ASSERT(start <= size);
376 if (start == size) start = 0; 638 if (start == size) start = 0;
377 } 639 }
378 if (start < end) { 640 if (start < end) {
379 int bytes = ProcessReadEncryptedBuffer(start, end); 641 int bytes = (i == kReadEncrypted) ?
642 ProcessReadEncryptedBuffer(start, end) :
643 ProcessWritePlaintextBuffer(start, end);
380 if (bytes < 0) return false; 644 if (bytes < 0) return false;
381 start += bytes; 645 start += bytes;
382 ASSERT(start <= end); 646 ASSERT(start <= end);
383 }
384 starts[i] = start;
385 break;
386 case kWritePlaintext:
387 if (end < start) {
388 // Data is split into two segments, [start, size) and [0, end).
389 int bytes = ProcessWritePlaintextBuffer(start, size, 0, end);
390 if (bytes < 0) return false;
391 start += bytes;
392 if (start >= size) start -= size;
393 } else {
394 int bytes = ProcessWritePlaintextBuffer(start, end, 0, 0);
395 if (bytes < 0) return false;
396 start += bytes;
397 ASSERT(start <= end);
398 } 647 }
399 starts[i] = start; 648 starts[i] = start;
400 break; 649 break;
401 default: 650 default:
402 UNREACHABLE(); 651 UNREACHABLE();
403 } 652 }
404 } 653 }
405 return true; 654 return true;
406 } 655 }
407 656
408 657
409 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
410 PRTime start_validity;
411 PRTime end_validity;
412 SECStatus status =
413 CERT_GetCertTimes(certificate, &start_validity, &end_validity);
414 if (status != SECSuccess) {
415 ThrowPRException("CertificateException",
416 "Cannot get validity times from certificate");
417 }
418 int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
419 int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
420 Dart_Handle subject_name_object =
421 DartUtils::NewString(certificate->subjectName);
422 Dart_Handle issuer_name_object =
423 DartUtils::NewString(certificate->issuerName);
424 Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
425 Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);
426
427 Dart_Handle date_type =
428 DartUtils::GetDartType(DartUtils::kCoreLibURL, "DateTime");
429 Dart_Handle from_milliseconds =
430 DartUtils::NewString("fromMillisecondsSinceEpoch");
431
432 Dart_Handle start_validity_date =
433 Dart_New(date_type, from_milliseconds, 1, &start_epoch_ms_int);
434 Dart_Handle end_validity_date =
435 Dart_New(date_type, from_milliseconds, 1, &end_epoch_ms_int);
436
437 Dart_Handle x509_type =
438 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
439 Dart_Handle arguments[] = { subject_name_object,
440 issuer_name_object,
441 start_validity_date,
442 end_validity_date };
443 return Dart_New(x509_type, Dart_Null(), 4, arguments);
444 }
445
446
447 void SSLFilter::Init(Dart_Handle dart_this) { 658 void SSLFilter::Init(Dart_Handle dart_this) {
448 if (!library_initialized_) { 659 if (!library_initialized_) {
449 InitializeLibrary(NULL, "", true, false); 660 InitializeLibrary();
450 } 661 }
451 ASSERT(string_start_ == NULL); 662 ASSERT(string_start_ == NULL);
452 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start")); 663 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
453 ASSERT(string_start_ != NULL); 664 ASSERT(string_start_ != NULL);
454 ASSERT(string_length_ == NULL); 665 ASSERT(string_length_ == NULL);
455 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length")); 666 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
456 ASSERT(string_length_ != NULL); 667 ASSERT(string_length_ != NULL);
457 ASSERT(bad_certificate_callback_ == NULL); 668 ASSERT(bad_certificate_callback_ == NULL);
458 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null()); 669 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
459 ASSERT(bad_certificate_callback_ != NULL); 670 ASSERT(bad_certificate_callback_ != NULL);
460 671
461 InitializeBuffers(dart_this); 672 InitializeBuffers(dart_this);
462 filter_ = memio_CreateIOLayer(kMemioBufferSize, kMemioBufferSize);
463 } 673 }
464 674
465 675
466 void SSLFilter::InitializeBuffers(Dart_Handle dart_this) { 676 void SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
467 // Create SSLFilter buffers as ExternalUint8Array objects. 677 // Create SSLFilter buffers as ExternalUint8Array objects.
468 Dart_Handle dart_buffers_object = ThrowIfError( 678 Dart_Handle dart_buffers_object = ThrowIfError(
469 Dart_GetField(dart_this, DartUtils::NewString("buffers"))); 679 Dart_GetField(dart_this, DartUtils::NewString("buffers")));
470 Dart_Handle secure_filter_impl_type = 680 Dart_Handle secure_filter_impl_type =
471 Dart_InstanceGetType(dart_this); 681 Dart_InstanceGetType(dart_this);
472 Dart_Handle dart_buffer_size = ThrowIfError( 682 Dart_Handle dart_buffer_size = ThrowIfError(
(...skipping 27 matching lines...) Expand all
500 Dart_SetField(Dart_HandleFromPersistent(dart_buffer_objects_[i]), 710 Dart_SetField(Dart_HandleFromPersistent(dart_buffer_objects_[i]),
501 data_identifier, 711 data_identifier,
502 data)); 712 data));
503 } 713 }
504 } 714 }
505 715
506 716
507 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) { 717 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
508 ASSERT(NULL == handshake_complete_); 718 ASSERT(NULL == handshake_complete_);
509 handshake_complete_ = Dart_NewPersistentHandle(complete); 719 handshake_complete_ = Dart_NewPersistentHandle(complete);
720
510 ASSERT(handshake_complete_ != NULL); 721 ASSERT(handshake_complete_ != NULL);
511 } 722 }
512 723
513 724
514 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) { 725 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
515 ASSERT(bad_certificate_callback_ != NULL); 726 ASSERT(bad_certificate_callback_ != NULL);
516 Dart_DeletePersistentHandle(bad_certificate_callback_); 727 Dart_DeletePersistentHandle(bad_certificate_callback_);
517 bad_certificate_callback_ = Dart_NewPersistentHandle(callback); 728 bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
518 ASSERT(bad_certificate_callback_ != NULL); 729 ASSERT(bad_certificate_callback_ != NULL);
519 } 730 }
520 731
521 732
522 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) { 733 void SSLFilter::InitializeLibrary() {
523 if (!retry) {
524 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
525 }
526 return NULL;
527 }
528
529
530 static const char* builtin_roots_module =
531 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
532 "name=\"Root Certs\" library=\"libnssckbi.so\"";
533 #elif defined(TARGET_OS_MACOS)
534 "name=\"Root Certs\" library=\"libnssckbi.dylib\"";
535 #elif defined(TARGET_OS_WINDOWS)
536 "name=\"Root Certs\" library=\"nssckbi.dll\"";
537 #else
538 #error Automatic target os detection failed.
539 #endif
540
541
542
543 void SSLFilter::InitializeLibrary(const char* certificate_database,
544 const char* password,
545 bool use_builtin_root_certificates,
546 bool report_duplicate_initialization) {
547 MutexLocker locker(mutex_); 734 MutexLocker locker(mutex_);
548 SECStatus status;
549 if (!library_initialized_) { 735 if (!library_initialized_) {
550 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 736 SSL_library_init();
551 // TODO(whesse): Verify there are no UTF-8 issues here. 737 filter_ssl_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
552 if (certificate_database == NULL || certificate_database[0] == '\0') { 738 ASSERT(filter_ssl_index >= 0);
553 status = NSS_NoDB_Init(NULL);
554 if (status != SECSuccess) {
555 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
556 ThrowPRException("TlsException",
557 "Failed NSS_NoDB_Init call.");
558 }
559 if (use_builtin_root_certificates) {
560 SECMODModule* module = SECMOD_LoadUserModule(
561 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
562 if (!module) {
563 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
564 ThrowPRException("TlsException",
565 "Failed to load builtin root certificates.");
566 }
567 }
568 } else {
569 PRUint32 init_flags = NSS_INIT_READONLY;
570 if (!use_builtin_root_certificates) {
571 init_flags |= NSS_INIT_NOMODDB;
572 }
573 status = NSS_Initialize(certificate_database,
574 "",
575 "",
576 SECMOD_DB,
577 init_flags);
578 if (status != SECSuccess) {
579 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
580 ThrowPRException("TlsException",
581 "Failed NSS_Init call.");
582 }
583 password_ = strdup(password); // This one copy persists until Dart exits.
584 PK11_SetPasswordFunc(PasswordCallback);
585 }
586 library_initialized_ = true; 739 library_initialized_ = true;
587
588 status = NSS_SetDomesticPolicy();
589 if (status != SECSuccess) {
590 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
591 ThrowPRException("TlsException",
592 "Failed NSS_SetDomesticPolicy call.");
593 }
594
595 // Enable the same additional ciphers that Chromium does.
596 // See NSSSSLInitSingleton() in Chromium's net/socket/nss_ssl_util.cc.
597 // Explicitly enable exactly those ciphers with keys of at least 80 bits.
598 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
599 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
600 for (int i = 0; i < num_ciphers; i++) {
601 SSLCipherSuiteInfo info;
602 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
603 SECSuccess) {
604 bool enabled = (info.effectiveKeyBits >= 80);
605 // Trim the list of cipher suites in order to keep the size of the
606 // ClientHello down. DSS, ECDH, CAMELLIA, SEED, ECC+3DES, and
607 // HMAC-SHA256 cipher suites are disabled.
608 if (info.symCipher == ssl_calg_camellia ||
609 info.symCipher == ssl_calg_seed ||
610 (info.symCipher == ssl_calg_3des && info.keaType != ssl_kea_rsa) ||
611 info.authAlgorithm == ssl_auth_dsa ||
612 info.macAlgorithm == ssl_hmac_sha256 ||
613 info.nonStandard ||
614 strcmp(info.keaTypeName, "ECDH") == 0) {
615 enabled = false;
616 }
617
618 if (ssl_ciphers[i] == TLS_DHE_DSS_WITH_AES_128_CBC_SHA) {
619 // Enabled to allow servers with only a DSA certificate to function.
620 enabled = true;
621 }
622 SSL_CipherPrefSetDefault(ssl_ciphers[i], enabled);
623 }
624 }
625
626 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
627 if (status != SECSuccess) {
628 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
629 ThrowPRException("TlsException",
630 "Failed SSL_ConfigServerSessionIDCache call.");
631 }
632
633 } else if (report_duplicate_initialization) {
634 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
635 // Like ThrowPRException, without adding an OSError.
636 Dart_ThrowException(DartUtils::NewDartIOException("TlsException",
637 "Called SecureSocket.initialize more than once",
638 Dart_Null()));
639 } 740 }
640 } 741 }
641 742
642 743
643 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) { 744 Dart_Handle SSLFilter::PeerCertificate() {
644 SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter); 745 X509* certificate = SSL_get_peer_certificate(ssl_);
645 Dart_Handle callback = ssl_filter->bad_certificate_callback(); 746 Dart_Handle x509_object = WrappedX509Certificate(certificate);
646 if (Dart_IsNull(callback)) return SECFailure; 747 if (Dart_IsError(x509_object)) {
647 Dart_Handle x509_object = ssl_filter->PeerCertificate(); 748 Dart_PropagateError(x509_object);
648 Dart_Handle result = Dart_InvokeClosure(callback, 1, &x509_object);
649 if (Dart_IsError(result)) {
650 ssl_filter->callback_error = result;
651 return SECFailure;
652 } 749 }
653 // Our wrapper is guaranteed to return a boolean.
654 bool c_result = DartUtils::GetBooleanValue(result);
655 return c_result ? SECSuccess : SECFailure;
656 }
657
658
659 Dart_Handle SSLFilter::PeerCertificate() {
660 CERTCertificate* certificate = SSL_PeerCertificate(filter_);
661 if (certificate == NULL) return Dart_Null();
662 Dart_Handle x509_object = X509FromCertificate(certificate);
663 CERT_DestroyCertificate(certificate);
664 return x509_object; 750 return x509_object;
665 } 751 }
666 752
667 753
668 void SSLFilter::Connect(const char* host_name, 754 int AlpnCallback(SSL *ssl,
669 const RawAddr& raw_addr, 755 const uint8_t **out,
670 int port, 756 uint8_t *outlen,
757 const uint8_t *in,
758 unsigned int inlen,
759 void *arg) {
760 // 'in' and 'arg' are sequences of (length, data) strings with 1-byte lengths.
761 // 'arg' is 0-terminated. Finds the first string in 'arg' that is in 'in'.
762 uint8_t* server_list = static_cast<uint8_t*>(arg);
763 while (*server_list != 0) {
764 uint8_t protocol_length = *server_list++;
765 const uint8_t* client_list = in;
766 while (client_list < in + inlen) {
767 uint8_t client_protocol_length = *client_list++;
768 if (client_protocol_length == protocol_length) {
769 if (0 == memcmp(server_list, client_list, protocol_length)) {
770 *out = client_list;
771 *outlen = client_protocol_length;
772 return SSL_TLSEXT_ERR_OK; // Success
773 }
774 }
775 client_list += client_protocol_length;
776 }
777 server_list += protocol_length;
778 }
779 // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN.
780 return SSL_TLSEXT_ERR_NOACK;
781 }
782
783
784 // Sets the protocol list for ALPN on a SSL object or a context.
785 static void SetAlpnProtocolList(Dart_Handle protocols_handle,
786 SSL* ssl,
787 SSL_CTX* context,
788 bool is_server) {
789 // Enable ALPN (application layer protocol negotiation) if the caller provides
790 // a valid list of supported protocols.
791 Dart_TypedData_Type protocols_type;
792 uint8_t* protocol_string = NULL;
793 uint8_t* protocol_string_copy = NULL;
794 intptr_t protocol_string_len = 0;
795 int status;
796
797 Dart_Handle result = Dart_TypedDataAcquireData(
798 protocols_handle,
799 &protocols_type,
800 reinterpret_cast<void**>(&protocol_string),
801 &protocol_string_len);
802 if (Dart_IsError(result)) {
803 Dart_PropagateError(result);
804 }
805
806 if (protocols_type != Dart_TypedData_kUint8) {
807 Dart_TypedDataReleaseData(protocols_handle);
808 Dart_PropagateError(Dart_NewApiError(
809 "Unexpected type for protocols (expected valid Uint8List)."));
810 }
811
812 if (protocol_string_len > 0) {
813 if (is_server) {
814 // ALPN on server connections must be set on an SSL_CTX object,
815 // not on the SSL object of the individual connection.
816 ASSERT(context != NULL);
817 ASSERT(ssl == NULL);
818 // Because it must be passed as a single void*, terminate
819 // the list of (length, data) strings with a length 0 string.
820 protocol_string_copy =
821 static_cast<uint8_t*>(malloc(protocol_string_len + 1));
822 memmove(protocol_string_copy, protocol_string, protocol_string_len);
823 protocol_string_copy[protocol_string_len] = '\0';
824 SSL_CTX_set_alpn_select_cb(context, AlpnCallback, protocol_string_copy);
825 // TODO(whesse): If this function is called again, free the previous
826 // protocol_string_copy. It may be better to keep this as a native
827 // field on the Dart object, since fetching it from the structure is
828 // not in the public api. Also free this when the context is destroyed.
829 } else {
830 // The function makes a local copy of protocol_string, which it owns.
831 if (ssl != NULL) {
832 ASSERT(context == NULL);
833 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len);
834 } else {
835 ASSERT(context != NULL);
836 ASSERT(ssl == NULL);
837 status = SSL_CTX_set_alpn_protos(
838 context, protocol_string, protocol_string_len);
839 }
840 ASSERT(status == 0); // The function returns a non-standard status.
841 }
842 }
843 Dart_TypedDataReleaseData(protocols_handle);
844 }
845
846
847 void SSLFilter::Connect(const char* hostname,
848 SSL_CTX* context,
671 bool is_server, 849 bool is_server,
672 const char* certificate_name,
673 bool request_client_certificate, 850 bool request_client_certificate,
674 bool require_client_certificate, 851 bool require_client_certificate,
675 bool send_client_certificate, 852 bool send_client_certificate,
676 Dart_Handle protocols_handle) { 853 Dart_Handle protocols_handle) {
677 is_server_ = is_server; 854 is_server_ = is_server;
678 if (in_handshake_) { 855 if (in_handshake_) {
679 FATAL("Connect called twice on the same _SecureFilter."); 856 FATAL("Connect called twice on the same _SecureFilter.");
680 } 857 }
681 858
682 if (!is_server && certificate_name != NULL) { 859 int status;
683 client_certificate_name_ = strdup(certificate_name); 860 int error;
861 BIO* ssl_side;
862 status = BIO_new_bio_pair(&ssl_side, 10000, &socket_side_, 10000);
863 CheckStatus(status, "BIO_new_bio_pair", __LINE__);
864
865 if (context == NULL) {
866 DART_CHECK_VALID(Dart_ThrowException(DartUtils::NewDartArgumentError(
867 "Default SecurityContext not implemented, context cannot be null.")));
684 } 868 }
685 869
686 filter_ = SSL_ImportFD(NULL, filter_); 870 ssl_ = SSL_new(context);
687 if (filter_ == NULL) { 871 SSL_set_bio(ssl_, ssl_side, ssl_side);
688 ThrowPRException("TlsException", "Failed SSL_ImportFD call"); 872 SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY); // TODO(whesse): Is this right?
873 SSL_set_ex_data(ssl_, filter_ssl_index, this);
874
875 if (!is_server_) {
876 SetAlpnProtocolList(protocols_handle, ssl_, NULL, false);
877 // Sets the hostname in the certificate-checking object, so it is checked
878 // against the certificate presented by the server.
879 X509_VERIFY_PARAM* certificate_checking_parameters_ = SSL_get0_param(ssl_);
880 hostname_ = strdup(hostname);
881 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters_, 0);
882 X509_VERIFY_PARAM_set1_host(certificate_checking_parameters_,
883 hostname_, 0);
884 // TODO(24186) free hostname_ if it is not freed when SSL is destroyed.
885 // otherwise, make it a local variable, not a instance field.
689 } 886 }
690 887 if (is_server_) {
691 888 status = SSL_accept(ssl_);
692 SECStatus status; 889 if (SSL_LOG_STATUS) Log::Print("SSL_accept status: %d\n", status);
693 890 if (status != 1) {
694 // Enable ALPN (application layer protocol negogiation) if the caller provides 891 // TODO(whesse): expect a needs-data error here. Handle other errors.
695 // a valid list of supported protocols. 892 error = SSL_get_error(ssl_, status);
696 { 893 if (SSL_LOG_STATUS) Log::Print("SSL_accept error: %d\n", error);
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 } 894 }
709 895 } else {
710 if (protocols_type != Dart_TypedData_kUint8) { 896 status = SSL_connect(ssl_);
711 Dart_TypedDataReleaseData(protocols_handle); 897 if (SSL_LOG_STATUS) Log::Print("SSL_connect status: %d\n", status);
712 Dart_PropagateError(Dart_NewApiError( 898 if (status != 1) {
713 "Unexpected type for protocols (expected valid Uint8List).")); 899 // TODO(whesse): expect a needs-data error here. Handle other errors.
900 error = SSL_get_error(ssl_, status);
901 if (SSL_LOG_STATUS) Log::Print("SSL_connect error: %d\n", error);
714 } 902 }
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 } 903 }
728 904 if (is_server_) {
729 SSLVersionRange vrange;
730 vrange.min = SSL_LIBRARY_VERSION_3_0;
731 vrange.max = SSL_LIBRARY_VERSION_TLS_1_2;
732 SSL_VersionRangeSet(filter_, &vrange);
733
734 if (is_server) {
735 CERTCertificate* certificate = NULL;
736 if (strstr(certificate_name, "CN=") != NULL) {
737 // Look up certificate using the distinguished name (DN) certificate_name.
738 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
739 if (certificate_database == NULL) {
740 ThrowPRException("CertificateException",
741 "Certificate database cannot be loaded");
742 }
743 certificate = CERT_FindCertByNameString(certificate_database,
744 const_cast<char*>(certificate_name));
745 if (certificate == NULL) {
746 ThrowCertificateException(
747 "Cannot find server certificate by distinguished name: %s",
748 certificate_name);
749 }
750 } else {
751 // Look up certificate using the nickname certificate_name.
752 certificate = PK11_FindCertFromNickname(
753 const_cast<char*>(certificate_name),
754 static_cast<void*>(const_cast<char*>(password_)));
755 if (certificate == NULL) {
756 ThrowCertificateException(
757 "Cannot find server certificate by nickname: %s",
758 certificate_name);
759 }
760 }
761 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(
762 certificate,
763 static_cast<void*>(const_cast<char*>(password_)));
764 if (key == NULL) {
765 CERT_DestroyCertificate(certificate);
766 if (PR_GetError() == -8177) {
767 ThrowPRException("CertificateException",
768 "Certificate database password incorrect");
769 } else {
770 ThrowCertificateException(
771 "Cannot find private key for certificate %s",
772 certificate_name);
773 }
774 }
775
776 // kt_rsa (key type RSA) is an enum constant from the NSS libraries.
777 // TODO(whesse): Allow different key types.
778 status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa);
779 CERT_DestroyCertificate(certificate);
780 SECKEY_DestroyPrivateKey(key);
781 if (status != SECSuccess) {
782 ThrowCertificateException(
783 "Failed SSL_ConfigSecureServer call with certificate %s",
784 certificate_name);
785 }
786
787 if (request_client_certificate) { 905 if (request_client_certificate) {
788 status = SSL_OptionSet(filter_, SSL_REQUEST_CERTIFICATE, PR_TRUE); 906 // TODO(24069): Handle client certificates on server side.
789 if (status != SECSuccess) { 907 Dart_ThrowException(DartUtils::NewDartArgumentError(
790 ThrowPRException("TlsException", 908 "requestClientCertificate not implemented."));
791 "Failed SSL_OptionSet(REQUEST_CERTIFICATE) call");
792 }
793 status = SSL_OptionSet(filter_,
794 SSL_REQUIRE_CERTIFICATE,
795 require_client_certificate);
796 if (status != SECSuccess) {
797 ThrowPRException("TlsException",
798 "Failed SSL_OptionSet(REQUIRE_CERTIFICATE) call");
799 }
800 } 909 }
801 } else { // Client. 910 } else { // Client.
802 if (SSL_SetURL(filter_, host_name) == -1) {
803 ThrowPRException("TlsException", "Failed SetURL call");
804 }
805 if (send_client_certificate) { 911 if (send_client_certificate) {
806 SSL_SetPKCS11PinArg(filter_, const_cast<char*>(password_)); 912 // TODO(24070): Handle client certificates on client side.
807 status = SSL_GetClientAuthDataHook( 913 Dart_ThrowException(DartUtils::NewDartArgumentError(
808 filter_, 914 "sendClientCertificate not implemented."));
809 NSS_GetClientAuthData,
810 static_cast<void*>(client_certificate_name_));
811 if (status != SECSuccess) {
812 ThrowPRException("TlsException",
813 "Failed SSL_GetClientAuthDataHook call");
814 }
815 } 915 }
816 } 916 }
817 917 Handshake();
818 // Install bad certificate callback, and pass 'this' to it if it is called.
819 status = SSL_BadCertHook(filter_,
820 BadCertificateCallback,
821 static_cast<void*>(this));
822
823 status = SSL_ResetHandshake(filter_, is_server);
824 if (status != SECSuccess) {
825 ThrowPRException("TlsException",
826 "Failed SSL_ResetHandshake call");
827 }
828
829 // Set the peer address from the address passed. The DNS has already
830 // been done in Dart code, so just use that address. This relies on
831 // following about PRNetAddr: "The raw member of the union is
832 // equivalent to struct sockaddr", which is stated in the NSS
833 // documentation.
834 PRNetAddr peername;
835 memset(&peername, 0, sizeof(peername));
836 intptr_t len = SocketAddress::GetAddrLength(raw_addr);
837 ASSERT(static_cast<size_t>(len) <= sizeof(peername));
838 memmove(&peername, &raw_addr.addr, len);
839
840 // Adjust the address family field for BSD, whose sockaddr
841 // structure has a one-byte length and one-byte address family
842 // field at the beginning. PRNetAddr has a two-byte address
843 // family field at the beginning.
844 peername.raw.family = raw_addr.addr.sa_family;
845
846 memio_SetPeerName(filter_, &peername);
847 } 918 }
848 919
849 920
921 int printErrorCallback(const char *str, size_t len, void *ctx) {
922 Log::PrintErr("%.*s\n", static_cast<int>(len), str);
923 return 1;
924 }
925
850 void SSLFilter::Handshake() { 926 void SSLFilter::Handshake() {
851 SECStatus status = SSL_ForceHandshake(filter_); 927 // Try and push handshake along.
852 if (status == SECSuccess) { 928 int status;
929 int error;
930 status = SSL_do_handshake(ssl_);
931 if (callback_error != NULL) {
932 // The SSL_do_handshake will try performing a handshake and might call
933 // a CertificateCallback. If the certificate validation
934 // failed the 'callback_error" will be set by the certificateCallback
935 // logic and we propagate the error"
936 Dart_PropagateError(callback_error);
937 }
938 if (SSL_LOG_STATUS) Log::Print("SSL_handshake status: %d\n", status);
939 if (status != 1) {
940 error = SSL_get_error(ssl_, status);
941 if (SSL_LOG_STATUS) Log::Print("ERROR: %d\n", error);
942 ERR_print_errors_cb(printErrorCallback, NULL);
943 }
944 if (status == 1) {
853 if (in_handshake_) { 945 if (in_handshake_) {
946 // TODO(24071): Check return value of SSL_get_verify_result, this
947 // should give us the hostname check.
948 int result = SSL_get_verify_result(ssl_);
949 if (SSL_LOG_STATUS) {
950 Log::Print("Handshake verification status: %d\n", result);
951 X509* peer_certificate = SSL_get_peer_certificate(ssl_);
952 if (peer_certificate == NULL) {
953 Log::Print("No peer certificate received\n");
954 } else {
955 X509_NAME* s_name = X509_get_subject_name(peer_certificate);
956 printf("Peer certificate SN: ");
957 X509_NAME_print_ex_fp(stdout, s_name, 4, 0);
958 printf("\n");
959 }
960 }
854 ThrowIfError(Dart_InvokeClosure( 961 ThrowIfError(Dart_InvokeClosure(
855 Dart_HandleFromPersistent(handshake_complete_), 0, NULL)); 962 Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
856 in_handshake_ = false; 963 in_handshake_ = false;
857 } 964 }
858 } else { 965 } else if (status == 0) {
859 if (callback_error != NULL) { 966 if (is_server_) {
860 Dart_PropagateError(callback_error); 967 ThrowIOException("HandshakeException",
968 "Handshake error in server");
969 } else {
970 ThrowIOException("HandshakeException",
971 "Handshake error in client");
861 } 972 }
862 PRErrorCode error = PR_GetError(); 973 } else if (status < 0) {
863 if (error == PR_WOULD_BLOCK_ERROR) { 974 if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
864 if (!in_handshake_) { 975 if (!in_handshake_) {
865 in_handshake_ = true; 976 in_handshake_ = true;
866 } 977 }
867 } else { 978 } else {
868 if (is_server_) { 979 if (is_server_) {
869 ThrowPRException("HandshakeException", 980 ThrowIOException("HandshakeException",
870 "Handshake error in server"); 981 "Handshake error in server");
871 } else { 982 } else {
872 ThrowPRException("HandshakeException", 983 ThrowIOException("HandshakeException",
873 "Handshake error in client"); 984 "Handshake error in client");
874 } 985 }
875 } 986 }
876 } 987 }
877 } 988 }
878 989
879 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) { 990 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
880 // Space for the selected protocol. 991 const uint8_t* protocol;
881 const unsigned int kBufferSize = 256; 992 unsigned length;
882 unsigned char buffer[kBufferSize + 1]; 993 SSL_get0_alpn_selected(ssl_, &protocol, &length);
883 994 if (length == 0) {
884 unsigned int outLength = 0; 995 Dart_SetReturnValue(args, Dart_Null());
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 { 996 } else {
914 ThrowPRException("HandshakeException", 997 Dart_SetReturnValue(args, Dart_NewStringFromUTF8(protocol, length));
915 "Could not retrieve selected protocol via ALPN");
916 } 998 }
917 } 999 }
918 1000
919 1001
920 void SSLFilter::Renegotiate(bool use_session_cache, 1002 void SSLFilter::Renegotiate(bool use_session_cache,
921 bool request_client_certificate, 1003 bool request_client_certificate,
922 bool require_client_certificate) { 1004 bool require_client_certificate) {
923 SECStatus status;
924 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the 1005 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
925 // SSL_REQUEST_CERTIFICATE option is also set, so set it. 1006 // SSL_REQUEST_CERTIFICATE option is also set, so set it.
926 request_client_certificate = 1007 request_client_certificate =
927 request_client_certificate || require_client_certificate; 1008 request_client_certificate || require_client_certificate;
928 1009 // TODO(24070, 24069): Implement setting the client certificate parameters,
929 status = SSL_OptionSet(filter_, 1010 // and triggering rehandshake.
930 SSL_REQUEST_CERTIFICATE,
931 request_client_certificate);
932 if (status != SECSuccess) {
933 ThrowPRException("TlsException",
934 "Failure in (Raw)SecureSocket.renegotiate request_client_certificate");
935 }
936 status = SSL_OptionSet(filter_,
937 SSL_REQUIRE_CERTIFICATE,
938 require_client_certificate);
939 if (status != SECSuccess) {
940 ThrowPRException("TlsException",
941 "Failure in (Raw)SecureSocket.renegotiate require_client_certificate");
942 }
943 bool flush_cache = !use_session_cache;
944 status = SSL_ReHandshake(filter_, flush_cache);
945 if (status != SECSuccess) {
946 if (is_server_) {
947 ThrowPRException("HandshakeException",
948 "Failure in (Raw)SecureSocket.renegotiate in server");
949 } else {
950 ThrowPRException("HandshakeException",
951 "Failure in (Raw)SecureSocket.renegotiate in client");
952 }
953 }
954 } 1011 }
955 1012
956 1013
957 void SSLFilter::Destroy() { 1014 void SSLFilter::Destroy() {
1015 if (ssl_ != NULL) {
1016 SSL_free(ssl_);
1017 ssl_ = NULL;
1018 }
958 for (int i = 0; i < kNumBuffers; ++i) { 1019 for (int i = 0; i < kNumBuffers; ++i) {
959 Dart_DeletePersistentHandle(dart_buffer_objects_[i]); 1020 Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
960 delete[] buffers_[i]; 1021 delete[] buffers_[i];
961 } 1022 }
962 Dart_DeletePersistentHandle(string_start_); 1023 Dart_DeletePersistentHandle(string_start_);
963 Dart_DeletePersistentHandle(string_length_); 1024 Dart_DeletePersistentHandle(string_length_);
964 Dart_DeletePersistentHandle(handshake_complete_); 1025 Dart_DeletePersistentHandle(handshake_complete_);
965 Dart_DeletePersistentHandle(bad_certificate_callback_); 1026 Dart_DeletePersistentHandle(bad_certificate_callback_);
966 free(client_certificate_name_);
967
968 PR_Close(filter_);
969 } 1027 }
970 1028
971 1029
972 intptr_t SSLFilter::ProcessReadPlaintextBuffer(int start, int end) { 1030 /* Read decrypted data from the filter to the circular buffer */
1031 int SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
973 int length = end - start; 1032 int length = end - start;
974 int bytes_processed = 0; 1033 int bytes_processed = 0;
975 if (length > 0) { 1034 if (length > 0) {
976 bytes_processed = PR_Read(filter_, 1035 bytes_processed = SSL_read(
977 buffers_[kReadPlaintext] + start, 1036 ssl_,
978 length); 1037 reinterpret_cast<char*>((buffers_[kReadPlaintext] + start)),
1038 length);
979 if (bytes_processed < 0) { 1039 if (bytes_processed < 0) {
980 ASSERT(bytes_processed == -1); 1040 int error = SSL_get_error(ssl_, bytes_processed);
981 PRErrorCode pr_error = PR_GetError(); 1041 USE(error);
982 if (PR_WOULD_BLOCK_ERROR != pr_error) {
983 return -1;
984 }
985 bytes_processed = 0; 1042 bytes_processed = 0;
986 } 1043 }
987 } 1044 }
988 return bytes_processed; 1045 return bytes_processed;
989 } 1046 }
990 1047
991 1048
992 intptr_t SSLFilter::ProcessWritePlaintextBuffer(int start1, int end1, 1049 int SSLFilter::ProcessWritePlaintextBuffer(int start, int end) {
993 int start2, int end2) { 1050 int length = end - start;
994 PRIOVec ranges[2]; 1051 int bytes_processed = SSL_write(
995 uint8_t* buffer = buffers_[kWritePlaintext]; 1052 ssl_, buffers_[kWritePlaintext] + start, length);
996 ranges[0].iov_base = reinterpret_cast<char*>(buffer + start1);
997 ranges[0].iov_len = end1 - start1;
998 ranges[1].iov_base = reinterpret_cast<char*>(buffer + start2);
999 ranges[1].iov_len = end2 - start2;
1000 int bytes_processed = PR_Writev(filter_, ranges, 2, PR_INTERVAL_NO_TIMEOUT);
1001 if (bytes_processed < 0) { 1053 if (bytes_processed < 0) {
1002 ASSERT(bytes_processed == -1); 1054 if (SSL_LOG_DATA) {
1003 PRErrorCode pr_error = PR_GetError(); 1055 Log::Print("SSL_write returned error %d\n", bytes_processed);
1004 if (PR_WOULD_BLOCK_ERROR != pr_error) {
1005 return -1;
1006 } 1056 }
1007 bytes_processed = 0; 1057 return 0;
1008 } 1058 }
1009 return bytes_processed; 1059 return bytes_processed;
1010 } 1060 }
1011 1061
1012 1062
1013 intptr_t SSLFilter::ProcessReadEncryptedBuffer(int start, int end) { 1063 /* Read encrypted data from the circular buffer to the filter */
1064 int SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
1014 int length = end - start; 1065 int length = end - start;
1066 if (SSL_LOG_DATA) Log::Print(
1067 "Entering ProcessReadEncryptedBuffer with %d bytes\n", length);
1015 int bytes_processed = 0; 1068 int bytes_processed = 0;
1016 if (length > 0) { 1069 if (length > 0) {
1017 memio_Private* secret = memio_GetSecret(filter_); 1070 bytes_processed =
1018 uint8_t* filter_buf; 1071 BIO_write(socket_side_, buffers_[kReadEncrypted] + start, length);
1019 int free_bytes = memio_GetReadParams(secret, &filter_buf); 1072 if (bytes_processed <= 0) {
1020 bytes_processed = dart::Utils::Minimum(length, free_bytes); 1073 bool retry = BIO_should_retry(socket_side_);
1021 memmove(filter_buf, buffers_[kReadEncrypted] + start, bytes_processed); 1074 if (!retry) {
1022 memio_PutReadResult(secret, bytes_processed); 1075 if (SSL_LOG_DATA) Log::Print(
1076 "BIO_write failed in ReadEncryptedBuffer\n");
1077 }
1078 bytes_processed = 0;
1079 }
1023 } 1080 }
1081 if (SSL_LOG_DATA) Log::Print(
1082 "Leaving ProcessReadEncryptedBuffer wrote %d bytes\n", bytes_processed);
1024 return bytes_processed; 1083 return bytes_processed;
1025 } 1084 }
1026 1085
1027 1086
1028 intptr_t SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) { 1087 int SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
1029 int length = end - start; 1088 int length = end - start;
1030 int bytes_processed = 0; 1089 int bytes_processed = 0;
1031 if (length > 0) { 1090 if (length > 0) {
1032 uint8_t* buffer = buffers_[kWriteEncrypted]; 1091 bytes_processed = BIO_read(socket_side_,
1033 const uint8_t* buf1; 1092 buffers_[kWriteEncrypted] + start,
1034 const uint8_t* buf2; 1093 length);
1035 unsigned int len1; 1094 if (bytes_processed < 0) {
1036 unsigned int len2; 1095 if (SSL_LOG_DATA) Log::Print(
1037 memio_Private* secret = memio_GetSecret(filter_); 1096 "WriteEncrypted BIO_read returned error %d\n", bytes_processed);
1038 int status = memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2); 1097 return 0;
1039 if (status != 0) { 1098 } else {
1040 return -1; 1099 if (SSL_LOG_DATA) Log::Print(
1041 } 1100 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed);
1042 int bytes_to_send =
1043 dart::Utils::Minimum(len1, static_cast<unsigned>(length));
1044 if (bytes_to_send > 0) {
1045 memmove(buffer + start, buf1, bytes_to_send);
1046 bytes_processed = bytes_to_send;
1047 }
1048 bytes_to_send = dart::Utils::Minimum(len2,
1049 static_cast<unsigned>(length - bytes_processed));
1050 if (bytes_to_send > 0) {
1051 memmove(buffer + start + bytes_processed, buf2, bytes_to_send);
1052 bytes_processed += bytes_to_send;
1053 }
1054 if (bytes_processed > 0) {
1055 memio_PutWriteResult(secret, bytes_processed);
1056 } 1101 }
1057 } 1102 }
1058 return bytes_processed; 1103 return bytes_processed;
1059 } 1104 }
1060 1105
1061 } // namespace bin 1106 } // namespace bin
1062 } // namespace dart 1107 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/bin/secure_socket.h ('k') | runtime/bin/secure_socket_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698