Chromium Code Reviews| 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)); | |
|
Mads Ager (google)
2012/12/05 13:08:03
We need to get rid of the last persistent handle s
Bill Hesse
2012/12/05 14:31:06
Done - It is freed in the destructor, if it exists
| |
| 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 if (PR_WOULD_BLOCK_ERROR != pr_error) { | 602 if (PR_WOULD_BLOCK_ERROR != pr_error) { |
| 510 ThrowPRException("Error reading plaintext from SSLFilter"); | 603 ThrowPRException("Error reading plaintext from SSLFilter"); |
| 511 } | 604 } |
| 512 bytes_processed = 0; | 605 bytes_processed = 0; |
| 513 } | 606 } |
| 514 break; | 607 break; |
| 515 } | 608 } |
| 516 } | 609 } |
| 517 return bytes_processed; | 610 return bytes_processed; |
| 518 } | 611 } |
| OLD | NEW |