certificate_viewer.mm 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #import "components/remote_cocoa/app_shim/certificate_viewer.h"
  5. #include <CoreFoundation/CFArray.h>
  6. #include <Security/Security.h>
  7. #import <SecurityInterface/SFCertificatePanel.h>
  8. #include "base/mac/foundation_util.h"
  9. #include "base/mac/scoped_cftyperef.h"
  10. #include "base/notreached.h"
  11. #include "net/cert/x509_util_apple.h"
  12. namespace remote_cocoa {
  13. void ShowCertificateViewerForWindow(NSWindow* owning_window,
  14. net::X509Certificate* certificate) {
  15. base::ScopedCFTypeRef<CFArrayRef> cert_chain(
  16. net::x509_util::CreateSecCertificateArrayForX509Certificate(certificate));
  17. if (!cert_chain)
  18. return;
  19. // Explicitly disable revocation checking, regardless of user preferences
  20. // or system settings. The behaviour of SFCertificatePanel is to call
  21. // SecTrustEvaluate on the certificate(s) supplied, effectively
  22. // duplicating the behaviour of net::X509Certificate::Verify(). However,
  23. // this call stalls the UI if revocation checking is enabled in the
  24. // Keychain preferences or if the cert may be an EV cert. By disabling
  25. // revocation checking, the stall is limited to the time taken for path
  26. // building and verification, which should be minimized due to the path
  27. // being provided in |certificates|. This does not affect normal
  28. // revocation checking from happening, which is controlled by
  29. // net::X509Certificate::Verify() and user preferences, but will prevent
  30. // the certificate viewer UI from displaying which certificate is revoked.
  31. // This is acceptable, as certificate revocation will still be shown in
  32. // the page info bubble if a certificate in the chain is actually revoked.
  33. base::ScopedCFTypeRef<CFMutableArrayRef> policies(
  34. CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
  35. if (!policies.get()) {
  36. NOTREACHED();
  37. return;
  38. }
  39. // Add a basic X.509 policy, in order to match the behaviour of
  40. // SFCertificatePanel when no policies are specified.
  41. base::ScopedCFTypeRef<SecPolicyRef> basic_policy(SecPolicyCreateBasicX509());
  42. if (!basic_policy) {
  43. NOTREACHED();
  44. return;
  45. }
  46. CFArrayAppendValue(policies, basic_policy.get());
  47. SFCertificatePanel* panel = [[SFCertificatePanel alloc] init];
  48. [panel setPolicies:base::mac::CFToNSCast(policies.get())];
  49. [panel beginSheetForWindow:owning_window
  50. modalDelegate:nil
  51. didEndSelector:nil
  52. contextInfo:nil
  53. certificates:base::mac::CFToNSCast(cert_chain.get())
  54. showGroup:YES];
  55. // beginSheetForWindow: internally retains an extra reference to |panel| and
  56. // releases it when the sheet closes. Release the original reference so the
  57. // sheet is destroyed.
  58. [panel autorelease];
  59. }
  60. } // namespace remote_cocoa