[PATCH] verify certificate of https server

Dimitris Glynos dimitris at census-labs.com
Tue Apr 7 10:11:15 CDT 2009


Hello all,

this is sort of a followup to the certificate-based authentication 
mechanism we were discussing back in January [1],[2],[3]

I'm attaching a patch that enables clients to verify the certificate of
an https server against a local "database" containing digests of trusted
certificates. To do this I've introduced two new sections in .hgrc:

[https]
requiresigs = True

[certs]
ACB59587AB3EC6429B0FFA841536937938FC1FAD = a.srv1.org, a.srv1.org:774
BF24012841294129491249294929429491249FF0 = other.host.org

The "https" section refers to https-related configuration options for
clients. Specifically, the "requiresigs" option when enabled, disallows
communication with https servers that are not described in the "certs"
section. By default "requiresigs" is False, allowing connection to
any web server. This follows the logic suggested by Matt Mackall in [3].

The "certs" section contains key-value pairs describing trusted certificates.
Each hash may be bound to multiple sites as shown above. Where port
number is not specified, the default port for https (443) is assumed.

On a sidenote, I'm trying to keep the certificate specification as 
generic as possible so that the same format may be used in the future
for certificate-based authentication on the server.
For example:

[certs]
BF24012841294129491249294929429491212345 = joe
ACB59587AB3EC6429B0FFA841536937938543210 = mary

Now, as far as the patch itself is concerned:

* To do proper validation of the server certificate I had to rely on
  pyopenssl. The openSSL wrappers provided by python 2.5, 2.6 and 3.0 
  are "ok" for simple high-level SSL communication, but they're not
  sufficient for the functionality we're after here 
  (see mercurial/url.py).

* Subclassed httplib.SSLFile and httplib.FakeSocket in order
  to have httplib/urllib/KeepAliveHandler play transparently with the
  pyopenssl sockets. The 2 new classes are called pyopensslfile and 
  pyopensslfakesocket respectively (see mercurial/url.py).

* A few new exit points were introduced. The client aborts if:
	- a malformed certificate entry is found in the config file
	- a duplicate certificate entry is found
	- an openssl error occurs during certificate verification
	- if requiresigs is enabled and an unknown certificate is
	  presented to the client

* Being presented with a self-signed certificate is not considered
  an error

* Fixed a tiny SSL-related bug in mercurial/hgweb/server.py:
  Apparently handle_one_request didn't handle correctly the Error 
  exception thrown by pyOpenSSL.

* Added 4 test cases (tests/test-requiresigs)
  - requiresigs enabled, known cert
  - requiresigs disabled, known cert
  - requiresigs enabled, unknown cert
  - requiresigs enabled, local cert digest points to unrelated provider

* Updated the manpage for hgrc (sections [certs] and [https])

If you find that the client-side is ok, I can send in a separate patch
for the server-side as well (i.e. authenticated clients based on certs).

best regards,

dimitris

[1] http://selenic.com/pipermail/mercurial-devel/2009-January/009649.html
[2] http://selenic.com/pipermail/mercurial-devel/2009-January/009651.html
[3] http://selenic.com/pipermail/mercurial-devel/2009-January/009662.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: crew.patch
Type: text/x-patch
Size: 14932 bytes
Desc: not available
Url : http://selenic.com/pipermail/mercurial-devel/attachments/20090407/d266f39b/attachment.bin 


More information about the Mercurial-devel mailing list