summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2017-02-04 11:05:55 -0200
committerdrebs <drebs@leap.se>2017-04-04 18:27:35 +0200
commit47f95c81351a998150986f3551908167d0798d75 (patch)
tree6bfab445e406c9aae8b83569def909002bed7b46
parentd81690e48b5a91592c55c12d4aa1a5c4e4b2aad9 (diff)
[feature] add a tls-pinned, token-authenticated http agent
-rw-r--r--client/src/leap/soledad/client/_http.py60
1 files changed, 60 insertions, 0 deletions
diff --git a/client/src/leap/soledad/client/_http.py b/client/src/leap/soledad/client/_http.py
new file mode 100644
index 00000000..b5975772
--- /dev/null
+++ b/client/src/leap/soledad/client/_http.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+# _http.py
+# Copyright (C) 2017 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+A twisted-based, TLS-pinned, token-authenticated HTTP client.
+"""
+import base64
+
+from twisted.internet import reactor
+from twisted.web.iweb import IAgent
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+
+from zope.interface import implementer
+
+from leap.common.certs import get_compatible_ssl_context_factory
+
+
+@implementer(IAgent)
+class PinnedTokenAgent(Agent):
+
+ def __init__(self, uuid, token, cert_file):
+ self._uuid = uuid
+ self._token = None
+ self._creds = None
+ self.set_token(token)
+ # pin this agent with the platform TLS certificate
+ factory = get_compatible_ssl_context_factory(cert_file)
+ Agent.__init__(self, reactor, contextFactory=factory)
+
+ def set_token(self, token):
+ self._token = token
+ self._creds = self._encoded_creds()
+
+ def _encoded_creds(self):
+ creds = '%s:%s' % (self._uuid, self._token)
+ encoded = base64.b64encode(creds)
+ return 'Token %s' % encoded
+
+ def request(self, method, uri, headers=None, bodyProducer=None):
+ # authenticate the request
+ if not headers:
+ headers = Headers()
+ headers.addRawHeader('Authorization', self._creds)
+ # perform the authenticated request
+ return Agent.request(
+ self, method, uri, headers=headers, bodyProducer=bodyProducer)