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

braintree calls raise NoCertificate when setdefaulttimeout() has been used. #10

Closed
foresto opened this issue Aug 25, 2010 · 9 comments
Closed

Comments

@foresto
Copy link

foresto commented Aug 25, 2010

I'm currently seeing this problem with Customer.create(), but it probably applies to all braintree API calls which contact the server. These calls are failing, raising a spurious NoCertificate exception with this message: "peer did not return certificate"

This appears to be caused by a known bug in m2crypto:
https://bugzilla.osafoundation.org/show_bug.cgi?id=2341
http://bytes.com/topic/python/answers/586302-wierd-m2crypto-bug-phony-peer-did-not-return-certificate-error

Our application calls socket.setdefaulttimeout() to make it gracefully handle cases when third-party libraries contact unresponsive servers. This is still pretty common in the python world, since per-connection timeout support was only recently added to urllib2 and many libraries have not yet started using that feature. That means we can't reasonably stop using socket.setdefaulttimeout(). Unfortunately, it causes braintree calls to fail.

So, as long as the braintree library depends on m2crypto for its https support, it seems we are stuck with either an incompatibility or (if we were to disable socket timeouts to work around the bug) a reliability problem.

Perhaps it would make sense for the braintree python library to use pycurl instead of m2crypto, or better yet, expose a pluggable http/https fetcher API? (The latter would be especially nice when we migrate to App Engine. Of course, such a plugin API should support caller-specified timeouts. :)

@braintreeps
Copy link
Contributor

Thanks for the detailed description of what is going wrong. We're looking into reproducing this, and I'll get back to you when I have more information.

In the meantime, does turning off SSL verification by setting braintree.Configuration.use_unsafe_ssl = True stop the error from occurring?

@foresto
Copy link
Author

foresto commented Sep 4, 2010

Yes, use_unsafe_ssl stops the error, though it does of course introduce a pretty awful security hole.

@braintreeps
Copy link
Contributor

I've successfully reproduced the issue locally.

It looks like pycurl might be able to work for us. I'll look into supporting swapping it in for M2Crypto in the Python client library and keep you posted.

@foresto
Copy link
Author

foresto commented Sep 7, 2010

Thank you.

A heads-up regarding pycurl: It is not a pure-python library, which means we won't be able to use it when we migrate to Google App Engine. When that time comes (probably in about 4 months) we will need another option. We are preparing our own code for this in two ways:

  • We have a generic http/https fetcher interface which currently calls pycurl but could easily call python's standard urllib2 or App Engine's urlfetch service instead, without affecting the rest of our application.
  • For third-party libraries that expose a pluggable http fetcher system (e.g. openid) we implement our own fetcher plugin for the library to use.

@braintreeps
Copy link
Contributor

Hi foresto,

Just wanted to give you an update on my progress so far. I've completed the switch from M2Crypto to PycURL in our code base, and so the change should be included in our next release.

Regarding your Google App Engine migration, do you know of a way to verify SSL certificates on that platform? My initial research seems to show that they don't support it [1], but perhaps you know of a workaround?

I'll update this issue again once we've released the new version,

Paul

[1] http://code.google.com/appengine/docs/python/urlfetch/overview.html#Secure_Connections_and_HTTPS

@foresto
Copy link
Author

foresto commented Sep 9, 2010

Thanks for the good news, Paul. By the way, you'll probably want to pay attention to the NOSIGNAL option when using pycurl, to keep your API safe for use with threaded code. In my own pycurl wrapper, I use setopt( pycurl.NOSIGNAL, 1) when instantiating a Curl object.

App Engine's urlfetch service does not yet verify SSL certificates. It's an open issue in their bug tracker for now, but I don't expect that to last for long. They have been filling in missing pieces every couple of months, paying particular attention to features that enable common classes of application. For example, https on custom domain names was an open issue until recently, and is now on their roadmap for an end-of-year release. App Engine for Business is driving some of this work forward.

In the mean time, we're preparing our application so we can make the switch in production as soon as possible. As long as Braintree's API continues to work on App Engine (it currently does so with use_unsafe_ssl) we can continue using it in our new code. Certificate verification isn't really needed while we're still porting and testing.

@braintreeps
Copy link
Contributor

Thanks for the additional information, foresto. Version 2.6.0 of the client library is now available, which uses PycURL for SSL verification, and should take care of this issue. Let us know if you run into any troubles with SSL verification in the new version.

@foresto
Copy link
Author

foresto commented Mar 15, 2011

Update: It looks like App Engine release 1.4.2 added server certificate validation. References:

http://code.google.com/p/googleappengine/issues/detail?id=3400#c5

http://code.google.com/appengine/docs/python/urlfetch/overview.html#Secure_Connections_and_HTTPS

@braintreeps
Copy link
Contributor

Thanks for the heads up. We'll take a look and see if we can use an SSL verification strategy that will work with GAE.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants