Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pluggable, more flexible, security policies. #429

Merged

Conversation

michaelkirk
Copy link
Contributor

@michaelkirk michaelkirk commented Jun 29, 2016

Motiviation

Extract @FredericJacobs' CertificateVerifier concept with @nlutsenko's
SRSecurityOptions into a pluggable SRSecurityPolicy protocol

This retains existing SSL configuration code paths, while allowing users
more flexibility to specify their own security policy. It's intended
that you're able to subclass an AFSecurityPolicy that conforms to the
<SRSecurityPolicy> protocol to share policy between websocket and
conventional requests.
This approach was changed. SRSecurityPolicy is now it's own class.

Inspired by original "Require TLS 1.2 & enable pinning" pull request by
Frederic Jacobs (@FredericJacobs) at: https://github.com/facebook/SocketRocket/pull/274/files

TODO

There are a couple things in particular that were kind of quick hacks, but wanted to get some feedback on the approach:

  • Testing
  • I added a synchronized block in didConnect. Maybe we can refactor so this isn't reached at so many different points
  • Should SecurityPolicyBuilder be public?
  • Are you OK with defaulting to TLS 1.2 only?
  • Implement no-encryption debug

@ghost
Copy link

ghost commented Jun 29, 2016

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at cla@fb.com. Thanks!

michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jun 29, 2016
Pluggable policies are currently only in our fork, not upsstream, but
pending PR: facebookincubator/SocketRocket#429

Also:
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy.m -> OWSTransportSecurityPolicy.m since
  it's being sued outside of AFNetworking
* Follow conventional singleton pattern with oneToken

// FREEBIE
@ghost
Copy link

ghost commented Jun 29, 2016

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

@ghost ghost added the CLA Signed label Jun 29, 2016
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jun 29, 2016
Pluggable policies are currently only in our fork, not upsstream, but
pending PR: facebookincubator/SocketRocket#429

Also:
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy.m -> OWSTransportSecurityPolicy.m since
  it's being sued outside of AFNetworking
* Follow conventional singleton pattern with oneToken

// FREEBIE
@nlutsenko
Copy link
Contributor

nlutsenko commented Jun 29, 2016

Love this PR, I think this is definitely the best of both worlds combined into one, with some polish required.

Putting few answers here the TODO questions you had:

Should SecurityPolicyBuilder be public?

Absolutely! I think we can structure it slightly differently, but creating different policies and using them should be public.

Are you OK with defaulting to TLS 1.2 only?

Yes, as long as we make sure we are no restricting only to it, meaning people can downgrade security to SSLv3 or TLS 1.1.

Implement no-encryption debug

I am less worried about this to be honest. When it comes to security - I think it's absolutely valid to test and develop with all security options turned on, otherwise - you are not testing the production flow.

@@ -0,0 +1,25 @@
//
// Copyright 2012 Square Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Since this is new code added and is not part of the original codebase - let's use the copyright statement from SRSecurityPolicyBuilder.

@nlutsenko
Copy link
Contributor

Few initial comments and nits. The most crucial one is around requestRequiresSSL and changes around it.

Also, around SRSecurityPolicyBuilder I think it's closer to Cocoa standards to use class cluster pattern here instead of Factory one. A good example is NSURLSessionConfiguration, where it has class constructors for creating different configurations or you can subclass it or you can create one and set it up.

So here, we would do SRSecurityPolicy as a class with the same methods as the protocol, as well as class constructors for other policy subclasses that are internal, but control the behavior.

@michaelkirk, let me know your thoughts about all of this, and whether it makes sense.

@michaelkirk
Copy link
Contributor Author

So here, we would do SRSecurityPolicy as a class with the same methods as the protocol, as well as class constructors for other policy subclasses that are internal, but control the behavior.

One concern we are trying to address is sharing a security policy from AFNetworking. It probably is more straight forward to implement a SRSecurityPolicy class like you've said, and then just delegate evaluateTrustForDomain:WithTrust to our AFSecurityPolicy.

michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jun 30, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jun 30, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jun 30, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
@michaelkirk
Copy link
Contributor Author

OK, I've refactored the Factory/Protocol into a couple of concrete classes. Take a peak and let me know what you think.

I'm leaving my commits separate for the sake of a PR dialogue, but would suggest smashing them when merging.

@michaelkirk
Copy link
Contributor Author

michaelkirk commented Jun 30, 2016

Here's an example of how we're using this to delegate domain verification to our existing AFNetworking security policy: https://github.com/WhisperSystems/SignalServiceKit/pull/15/files#diff-8aea6ac66bd50c6e854b63f64f7edeb9R1


@interface SRPinningSecurityPolicy ()

@property (nonatomic, readonly) NSArray *pinnedCertificates;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nonatomic, copy, readonly

@nlutsenko
Copy link
Contributor

This actually looks perfect now!
I am going to merge this in once Travis passes on it.

@nlutsenko
Copy link
Contributor

Thank you so much for making this happen!

@michaelkirk
Copy link
Contributor Author

michaelkirk commented Jun 30, 2016

Installing cocoapods-trunk 1.0.0
Using xcpretty 0.2.2
Installing activesupport 5.0.0
Gem::InstallError: activesupport requires Ruby version >= 2.2.2.
An error occurred while installing activesupport (5.0.0), and Bundler cannot
continue.

Ha. I wonder how many other people's CI failed due to today's Rails 5 release. :\

@michaelkirk
Copy link
Contributor Author

Can you restart the build after #430 (or something similar) is merged?

@nlutsenko
Copy link
Contributor

I believe this needs rebase actually, since it's going to test your specific branch and not the commit applied on top of master.

@nlutsenko
Copy link
Contributor

This indeed fails tests, I am investigating right now.

@nlutsenko
Copy link
Contributor

I bet it's due to the fact that we are still trying to validate the security policy, even though it's not required.


SRDebugLog(@"Allows connection any root cert: %d", _securityOptions.validatesCertificateChain);
SRDebugLog(@"Pinned cert count: %d", _securityOptions.pinnedCertificates.count);
[_securityPolicy updateSecurityOptionsInStream:_inputStream];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failing tests and probably is going to fail to connect to http hosts with this.
Please wrap 474-475 in a if (_requestRequiresSSL) check.

Extract @FredericJacobs' CertificateVerifier concept with @nlutsenko's
SRSecurityOptions into a pluggable SRSecurityPolicy model

This retains existing SSL configuration code paths, while allowing users
more flexibility to specify their own security policy.

If you are alread using AFNetworking and an `AFSecurityPolicy`, it's
intended that you can share domain trust logic by delegating
`SRSecurityPolicy evaluateTrust:ForDomain` to your AFSecurityPolicy
instance.

Inspired by original "Require TLS 1.2 & enable pinning" pull request by
Frederic Jacobs (@FredericJacobs) at:

https://github.com/facebook/SocketRocket/pull/274/files
@nlutsenko
Copy link
Contributor

Should be all good now, let's wait for Travis 😁

michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jul 1, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jul 1, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jul 1, 2016
Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken

// FREEBIE
@nlutsenko nlutsenko merged commit 8096fef into facebookincubator:master Jul 1, 2016
michaelkirk added a commit to signalapp/SignalServiceKit that referenced this pull request Jul 1, 2016
* Use SocketRocket pluggable policies

Pluggable policies are currently only in our fork, but pending upstream
PR: facebookincubator/SocketRocket#429

Also:
* rebased SocketRocket against latest upstream to incorporate bug fixes.
* adapt to new upstream API for error handling (vs previous exception throwing)
* renamed AFSecurityOWSPolicy -> OWSHTTPSecurityPolicy to differentiate
  it from OSWWebSocketSecurityPolicy
* Follow conventional singleton pattern with onceToken
* bump xcode version to play nice with SWIFT_NAME in SocketRocket

// FREEBIE
@michaelkirk
Copy link
Contributor Author

Great. Thanks for your prompt attention @nlutsenko! 🙏

@nlutsenko nlutsenko added this to the 0.6.0 milestone Oct 31, 2016
madlymad pushed a commit to madlymad/SocketRocket that referenced this pull request Jul 6, 2017
Extract @FredericJacobs' CertificateVerifier concept with @nlutsenko's
SRSecurityOptions into a pluggable SRSecurityPolicy model

This retains existing SSL configuration code paths, while allowing users
more flexibility to specify their own security policy.

If you are alread using AFNetworking and an `AFSecurityPolicy`, it's
intended that you can share domain trust logic by delegating
`SRSecurityPolicy evaluateTrust:ForDomain` to your AFSecurityPolicy
instance.

Inspired by original "Require TLS 1.2 & enable pinning" pull request by
Frederic Jacobs (@FredericJacobs) at:

https://github.com/facebook/SocketRocket/pull/274/files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants