| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/secure_socket.h" | 5 #include "bin/secure_socket.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 ThrowIfError(Dart_GetNativeArgument(args, 1)); | 136 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 137 if (!Dart_IsClosure(handshake_complete)) { | 137 if (!Dart_IsClosure(handshake_complete)) { |
| 138 Dart_ThrowException(DartUtils::NewDartArgumentError( | 138 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 139 "Illegal argument to RegisterHandshakeCompleteCallback")); | 139 "Illegal argument to RegisterHandshakeCompleteCallback")); |
| 140 } | 140 } |
| 141 GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete); | 141 GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete); |
| 142 Dart_ExitScope(); | 142 Dart_ExitScope(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 | 145 |
| 146 void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)( |
| 147 Dart_NativeArguments args) { |
| 148 Dart_EnterScope(); |
| 149 Dart_Handle callback = |
| 150 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 151 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) { |
| 152 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 153 "Illegal argument to RegisterBadCertificateCallback")); |
| 154 } |
| 155 GetFilter(args)->RegisterBadCertificateCallback(callback); |
| 156 Dart_ExitScope(); |
| 157 } |
| 158 |
| 159 |
| 146 void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) { | 160 void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) { |
| 147 Dart_EnterScope(); | 161 Dart_EnterScope(); |
| 148 Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); | 162 Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 149 int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object); | 163 int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object); |
| 150 if (buffer_id < 0 || buffer_id >= SSLFilter::kNumBuffers) { | 164 if (buffer_id < 0 || buffer_id >= SSLFilter::kNumBuffers) { |
| 151 Dart_ThrowException(DartUtils::NewDartArgumentError( | 165 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 152 "Illegal argument to ProcessBuffer")); | 166 "Illegal argument to ProcessBuffer")); |
| 153 } | 167 } |
| 154 | 168 |
| 155 intptr_t bytes_read = | 169 intptr_t bytes_read = |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } else { | 212 } else { |
| 199 Dart_ThrowException(DartUtils::NewDartArgumentError( | 213 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 200 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); | 214 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); |
| 201 } | 215 } |
| 202 | 216 |
| 203 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); | 217 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); |
| 204 Dart_ExitScope(); | 218 Dart_ExitScope(); |
| 205 } | 219 } |
| 206 | 220 |
| 207 | 221 |
| 222 static bool CallBadCertificateCallback(Dart_Handle callback, |
| 223 const char* subject_name, |
| 224 const char* issuer_name, |
| 225 int64_t start_validity, |
| 226 int64_t end_validity) { |
| 227 if (callback == NULL || Dart_IsNull(callback)) return false; |
| 228 Dart_EnterScope(); |
| 229 Dart_Handle subject_name_object = DartUtils::NewString(subject_name); |
| 230 Dart_Handle issuer_name_object = DartUtils::NewString(issuer_name); |
| 231 Dart_Handle start_validity_int = Dart_NewInteger(start_validity); |
| 232 Dart_Handle end_validity_int = Dart_NewInteger(end_validity); |
| 233 |
| 234 Dart_Handle date_class = |
| 235 DartUtils::GetDartClass(DartUtils::kCoreLibURL, "Date"); |
| 236 Dart_Handle from_milliseconds = |
| 237 DartUtils::NewString("fromMillisecondsSinceEpoch"); |
| 238 |
| 239 Dart_Handle start_validity_date = |
| 240 Dart_New(date_class, from_milliseconds, 1, &start_validity_int); |
| 241 Dart_Handle end_validity_date = |
| 242 Dart_New(date_class, from_milliseconds, 1, &end_validity_int); |
| 243 |
| 244 Dart_Handle x509_class = |
| 245 DartUtils::GetDartClass(DartUtils::kIOLibURL, "X509Certificate"); |
| 246 Dart_Handle arguments[] = { subject_name_object, |
| 247 issuer_name_object, |
| 248 start_validity_date, |
| 249 end_validity_date }; |
| 250 Dart_Handle certificate = Dart_New(x509_class, Dart_Null(), 4, arguments); |
| 251 |
| 252 Dart_Handle result = |
| 253 ThrowIfError(Dart_InvokeClosure(callback, 1, &certificate)); |
| 254 bool c_result = Dart_IsBoolean(result) && DartUtils::GetBooleanValue(result); |
| 255 Dart_ExitScope(); |
| 256 return c_result; |
| 257 } |
| 258 |
| 259 |
| 208 void SSLFilter::Init(Dart_Handle dart_this) { | 260 void SSLFilter::Init(Dart_Handle dart_this) { |
| 209 string_start_ = ThrowIfError( | 261 string_start_ = ThrowIfError( |
| 210 Dart_NewPersistentHandle(DartUtils::NewString("start"))); | 262 Dart_NewPersistentHandle(DartUtils::NewString("start"))); |
| 211 string_length_ = ThrowIfError( | 263 string_length_ = ThrowIfError( |
| 212 Dart_NewPersistentHandle(DartUtils::NewString("length"))); | 264 Dart_NewPersistentHandle(DartUtils::NewString("length"))); |
| 213 | 265 |
| 214 InitializeBuffers(dart_this); | 266 InitializeBuffers(dart_this); |
| 215 filter_ = memio_CreateIOLayer(kMemioBufferSize); | 267 filter_ = memio_CreateIOLayer(kMemioBufferSize); |
| 216 } | 268 } |
| 217 | 269 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 245 } | 297 } |
| 246 } | 298 } |
| 247 | 299 |
| 248 | 300 |
| 249 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) { | 301 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) { |
| 250 ASSERT(NULL == handshake_complete_); | 302 ASSERT(NULL == handshake_complete_); |
| 251 handshake_complete_ = ThrowIfError(Dart_NewPersistentHandle(complete)); | 303 handshake_complete_ = ThrowIfError(Dart_NewPersistentHandle(complete)); |
| 252 } | 304 } |
| 253 | 305 |
| 254 | 306 |
| 307 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle complete) { |
| 308 if (NULL != bad_certificate_callback_) { |
| 309 Dart_DeletePersistentHandle(bad_certificate_callback_); |
| 310 } |
| 311 bad_certificate_callback_ = ThrowIfError(Dart_NewPersistentHandle(complete)); |
| 312 } |
| 313 |
| 314 |
| 255 void SSLFilter::InitializeLibrary(const char* certificate_database, | 315 void SSLFilter::InitializeLibrary(const char* certificate_database, |
| 256 const char* password, | 316 const char* password, |
| 257 bool use_builtin_root_certificates) { | 317 bool use_builtin_root_certificates) { |
| 258 MutexLocker locker(&mutex_); | 318 MutexLocker locker(&mutex_); |
| 259 if (!library_initialized_) { | 319 if (!library_initialized_) { |
| 260 library_initialized_ = true; | 320 library_initialized_ = true; |
| 261 password_ = strdup(password); // This one copy persists until Dart exits. | 321 password_ = strdup(password); // This one copy persists until Dart exits. |
| 262 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); | 322 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
| 263 // TODO(whesse): Verify there are no UTF-8 issues here. | 323 // TODO(whesse): Verify there are no UTF-8 issues here. |
| 264 PRUint32 init_flags = NSS_INIT_READONLY; | 324 PRUint32 init_flags = NSS_INIT_READONLY; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 294 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); | 354 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); |
| 295 if (status != SECSuccess) { | 355 if (status != SECSuccess) { |
| 296 ThrowPRException("Unsuccessful SSL_ConfigServerSessionIDCache call."); | 356 ThrowPRException("Unsuccessful SSL_ConfigServerSessionIDCache call."); |
| 297 } | 357 } |
| 298 | 358 |
| 299 } else { | 359 } else { |
| 300 ThrowException("Called SSLFilter::InitializeLibrary more than once"); | 360 ThrowException("Called SSLFilter::InitializeLibrary more than once"); |
| 301 } | 361 } |
| 302 } | 362 } |
| 303 | 363 |
| 364 |
| 304 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) { | 365 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) { |
| 305 if (!retry) { | 366 if (!retry) { |
| 306 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals. | 367 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals. |
| 307 } | 368 } |
| 308 return NULL; | 369 return NULL; |
| 309 } | 370 } |
| 310 | 371 |
| 372 |
| 373 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) { |
| 374 return static_cast<SSLFilter*>(filter)->HandleBadCertificate(fd); |
| 375 } |
| 376 |
| 377 |
| 378 SECStatus SSLFilter::HandleBadCertificate(PRFileDesc* fd) { |
| 379 ASSERT(fd == filter_); |
| 380 CERTCertificate* certificate = SSL_PeerCertificate(fd); |
| 381 PRTime start_validity; |
| 382 PRTime end_validity; |
| 383 SECStatus status = |
| 384 CERT_GetCertTimes(certificate, &start_validity, &end_validity); |
| 385 if (status != SECSuccess) { |
| 386 ThrowPRException("Cannot get validity times from certificate"); |
| 387 } |
| 388 int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC; |
| 389 int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC; |
| 390 bool accept = CallBadCertificateCallback(bad_certificate_callback_, |
| 391 certificate->subjectName, |
| 392 certificate->issuerName, |
| 393 start_epoch_ms, |
| 394 end_epoch_ms); |
| 395 return accept ? SECSuccess : SECFailure; |
| 396 } |
| 397 |
| 398 |
| 311 void SSLFilter::Connect(const char* host_name, | 399 void SSLFilter::Connect(const char* host_name, |
| 312 int port, | 400 int port, |
| 313 bool is_server, | 401 bool is_server, |
| 314 const char* certificate_name) { | 402 const char* certificate_name) { |
| 315 is_server_ = is_server; | 403 is_server_ = is_server; |
| 316 if (in_handshake_) { | 404 if (in_handshake_) { |
| 317 ThrowException("Connect called while already in handshake state."); | 405 ThrowException("Connect called while already in handshake state."); |
| 318 } | 406 } |
| 319 | 407 |
| 320 filter_ = SSL_ImportFD(NULL, filter_); | 408 filter_ = SSL_ImportFD(NULL, filter_); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 351 status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa); | 439 status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa); |
| 352 if (status != SECSuccess) { | 440 if (status != SECSuccess) { |
| 353 ThrowPRException("Unsuccessful SSL_ConfigSecureServer call"); | 441 ThrowPRException("Unsuccessful SSL_ConfigSecureServer call"); |
| 354 } | 442 } |
| 355 } else { // Client. | 443 } else { // Client. |
| 356 if (SSL_SetURL(filter_, host_name) == -1) { | 444 if (SSL_SetURL(filter_, host_name) == -1) { |
| 357 ThrowPRException("Unsuccessful SetURL call"); | 445 ThrowPRException("Unsuccessful SetURL call"); |
| 358 } | 446 } |
| 359 } | 447 } |
| 360 | 448 |
| 361 PRBool as_server = is_server ? PR_TRUE : PR_FALSE; // Convert bool to PRBool. | 449 // Install bad certificate callback, and pass 'this' to it if it is called. |
| 450 status = SSL_BadCertHook(filter_, |
| 451 BadCertificateCallback, |
| 452 static_cast<void*>(this)); |
| 453 |
| 454 PRBool as_server = is_server ? PR_TRUE : PR_FALSE; |
| 362 status = SSL_ResetHandshake(filter_, as_server); | 455 status = SSL_ResetHandshake(filter_, as_server); |
| 363 if (status != SECSuccess) { | 456 if (status != SECSuccess) { |
| 364 ThrowPRException("Unsuccessful SSL_ResetHandshake call"); | 457 ThrowPRException("Unsuccessful SSL_ResetHandshake call"); |
| 365 } | 458 } |
| 366 | 459 |
| 367 // SetPeerAddress | 460 // SetPeerAddress |
| 368 PRNetAddr host_address; | 461 PRNetAddr host_address; |
| 369 char host_entry_buffer[PR_NETDB_BUF_SIZE]; | 462 char host_entry_buffer[PR_NETDB_BUF_SIZE]; |
| 370 PRHostEnt host_entry; | 463 PRHostEnt host_entry; |
| 371 PRStatus rv = PR_GetHostByName(host_name, host_entry_buffer, | 464 PRStatus rv = PR_GetHostByName(host_name, host_entry_buffer, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 | 500 |
| 408 | 501 |
| 409 void SSLFilter::Destroy() { | 502 void SSLFilter::Destroy() { |
| 410 for (int i = 0; i < kNumBuffers; ++i) { | 503 for (int i = 0; i < kNumBuffers; ++i) { |
| 411 Dart_DeletePersistentHandle(dart_buffer_objects_[i]); | 504 Dart_DeletePersistentHandle(dart_buffer_objects_[i]); |
| 412 delete[] buffers_[i]; | 505 delete[] buffers_[i]; |
| 413 } | 506 } |
| 414 Dart_DeletePersistentHandle(string_start_); | 507 Dart_DeletePersistentHandle(string_start_); |
| 415 Dart_DeletePersistentHandle(string_length_); | 508 Dart_DeletePersistentHandle(string_length_); |
| 416 Dart_DeletePersistentHandle(handshake_complete_); | 509 Dart_DeletePersistentHandle(handshake_complete_); |
| 510 if (bad_certificate_callback_ != NULL) { |
| 511 Dart_DeletePersistentHandle(bad_certificate_callback_); |
| 512 } |
| 417 // TODO(whesse): Free NSS objects here. | 513 // TODO(whesse): Free NSS objects here. |
| 418 } | 514 } |
| 419 | 515 |
| 420 | 516 |
| 421 intptr_t SSLFilter::ProcessBuffer(int buffer_index) { | 517 intptr_t SSLFilter::ProcessBuffer(int buffer_index) { |
| 422 Dart_Handle buffer_object = dart_buffer_objects_[buffer_index]; | 518 Dart_Handle buffer_object = dart_buffer_objects_[buffer_index]; |
| 423 Dart_Handle start_object = ThrowIfError( | 519 Dart_Handle start_object = ThrowIfError( |
| 424 Dart_GetField(buffer_object, string_start_)); | 520 Dart_GetField(buffer_object, string_start_)); |
| 425 Dart_Handle length_object = ThrowIfError( | 521 Dart_Handle length_object = ThrowIfError( |
| 426 Dart_GetField(buffer_object, string_length_)); | 522 Dart_GetField(buffer_object, string_length_)); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 if (PR_WOULD_BLOCK_ERROR != pr_error) { | 605 if (PR_WOULD_BLOCK_ERROR != pr_error) { |
| 510 ThrowPRException("Error reading plaintext from SSLFilter"); | 606 ThrowPRException("Error reading plaintext from SSLFilter"); |
| 511 } | 607 } |
| 512 bytes_processed = 0; | 608 bytes_processed = 0; |
| 513 } | 609 } |
| 514 break; | 610 break; |
| 515 } | 611 } |
| 516 } | 612 } |
| 517 return bytes_processed; | 613 return bytes_processed; |
| 518 } | 614 } |
| OLD | NEW |