Chromium Code Reviews| Index: runtime/bin/secure_socket.cc |
| diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc |
| index 671b1a9bafc1a64da61893a5d536e5f8a2f3ed9f..c1953d5df56def2090d6b9386415b84449bde9bb 100644 |
| --- a/runtime/bin/secure_socket.cc |
| +++ b/runtime/bin/secure_socket.cc |
| @@ -143,6 +143,20 @@ void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)( |
| } |
| +void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)( |
| + Dart_NativeArguments args) { |
| + Dart_EnterScope(); |
| + Dart_Handle callback = |
| + ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| + if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) { |
| + Dart_ThrowException(DartUtils::NewDartArgumentError( |
| + "Illegal argument to RegisterBadCertificateCallback")); |
| + } |
| + GetFilter(args)->RegisterBadCertificateCallback(callback); |
| + Dart_ExitScope(); |
| +} |
| + |
| + |
| void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) { |
| Dart_EnterScope(); |
| Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| @@ -205,6 +219,44 @@ void FUNCTION_NAME(SecureSocket_InitializeLibrary) |
| } |
| +static bool CallBadCertificateCallback(Dart_Handle callback, |
| + const char* subject_name, |
| + const char* issuer_name, |
| + int64_t start_validity, |
| + int64_t end_validity) { |
| + if (callback == NULL || Dart_IsNull(callback)) return false; |
| + Dart_EnterScope(); |
| + Dart_Handle subject_name_object = DartUtils::NewString(subject_name); |
| + Dart_Handle issuer_name_object = DartUtils::NewString(issuer_name); |
| + Dart_Handle start_validity_int = Dart_NewInteger(start_validity); |
| + Dart_Handle end_validity_int = Dart_NewInteger(end_validity); |
| + |
| + Dart_Handle date_class = |
| + DartUtils::GetDartClass(DartUtils::kCoreLibURL, "Date"); |
| + Dart_Handle from_milliseconds = |
| + DartUtils::NewString("fromMillisecondsSinceEpoch"); |
| + |
| + Dart_Handle start_validity_date = |
| + Dart_New(date_class, from_milliseconds, 1, &start_validity_int); |
| + Dart_Handle end_validity_date = |
| + Dart_New(date_class, from_milliseconds, 1, &end_validity_int); |
| + |
| + Dart_Handle x509_class = |
| + DartUtils::GetDartClass(DartUtils::kIOLibURL, "X509Certificate"); |
| + Dart_Handle arguments[] = { subject_name_object, |
| + issuer_name_object, |
| + start_validity_date, |
| + end_validity_date }; |
| + Dart_Handle certificate = Dart_New(x509_class, Dart_Null(), 4, arguments); |
| + |
| + Dart_Handle result = |
| + ThrowIfError(Dart_InvokeClosure(callback, 1, &certificate)); |
| + bool c_result = Dart_IsBoolean(result) && DartUtils::GetBooleanValue(result); |
| + Dart_ExitScope(); |
| + return c_result; |
| +} |
| + |
| + |
| void SSLFilter::Init(Dart_Handle dart_this) { |
| string_start_ = ThrowIfError( |
| Dart_NewPersistentHandle(DartUtils::NewString("start"))); |
| @@ -252,6 +304,14 @@ void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) { |
| } |
| +void SSLFilter::RegisterBadCertificateCallback(Dart_Handle complete) { |
| + if (NULL != bad_certificate_callback_) { |
| + Dart_DeletePersistentHandle(bad_certificate_callback_); |
| + } |
| + 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
|
| +} |
| + |
| + |
| void SSLFilter::InitializeLibrary(const char* certificate_database, |
| const char* password, |
| bool use_builtin_root_certificates) { |
| @@ -301,6 +361,7 @@ void SSLFilter::InitializeLibrary(const char* certificate_database, |
| } |
| } |
| + |
| char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) { |
| if (!retry) { |
| return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals. |
| @@ -308,6 +369,33 @@ char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) { |
| return NULL; |
| } |
| + |
| +SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) { |
| + return static_cast<SSLFilter*>(filter)->HandleBadCertificate(fd); |
| +} |
| + |
| + |
| +SECStatus SSLFilter::HandleBadCertificate(PRFileDesc* fd) { |
| + ASSERT(fd == filter_); |
| + CERTCertificate* certificate = SSL_PeerCertificate(fd); |
| + PRTime start_validity; |
| + PRTime end_validity; |
| + SECStatus status = |
| + CERT_GetCertTimes(certificate, &start_validity, &end_validity); |
| + if (status != SECSuccess) { |
| + ThrowPRException("Cannot get validity times from certificate"); |
| + } |
| + int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC; |
| + int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC; |
| + bool accept = CallBadCertificateCallback(bad_certificate_callback_, |
| + certificate->subjectName, |
| + certificate->issuerName, |
| + start_epoch_ms, |
| + end_epoch_ms); |
| + return accept ? SECSuccess : SECFailure; |
| +} |
| + |
| + |
| void SSLFilter::Connect(const char* host_name, |
| int port, |
| bool is_server, |
| @@ -358,7 +446,12 @@ void SSLFilter::Connect(const char* host_name, |
| } |
| } |
| - PRBool as_server = is_server ? PR_TRUE : PR_FALSE; // Convert bool to PRBool. |
| + // Install bad certificate callback, and pass 'this' to it if it is called. |
| + status = SSL_BadCertHook(filter_, |
| + BadCertificateCallback, |
| + static_cast<void*>(this)); |
| + |
| + PRBool as_server = is_server ? PR_TRUE : PR_FALSE; |
| status = SSL_ResetHandshake(filter_, as_server); |
| if (status != SECSuccess) { |
| ThrowPRException("Unsuccessful SSL_ResetHandshake call"); |