Merge lp:~denys.duchier/bzr/bzr.ssl into lp:~bzr/bzr/trunk-old
- bzr.ssl
- Merge into trunk-old
Status: | Superseded |
---|---|
Proposed branch: | lp:~denys.duchier/bzr/bzr.ssl |
Merge into: | lp:~bzr/bzr/trunk-old |
Diff against target: | 460 lines |
To merge this branch: | bzr merge lp:~denys.duchier/bzr/bzr.ssl |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Bennetts | Pending | ||
Review via email: mp+10175@code.launchpad.net |
This proposal supersedes a proposal from 2009-08-14.
This proposal has been superseded by a proposal from 2009-08-14.
Commit message
Description of the change
Denys Duchier (denys.duchier) wrote : Posted in a previous version of this proposal | # |
Martin Pool (mbp) wrote : Posted in a previous version of this proposal | # |
Thanks, that's an interesting feature to add!
Does this do authentication at all, or do you plan to add it?
--
Martin <http://
Denys Duchier (denys.duchier) wrote : Posted in a previous version of this proposal | # |
Martin Pool <email address hidden> writes:
> Does this do authentication at all, or do you plan to add it?
I wanted to use python's built-in SSL support. Verification of
certificates is only supported starting with python 2.6. Thus
certificate-based authentication is very easy to add, but can only be
activated for recent python distros. If there is interest, I can add
support for, it of course.
I am also interested in supporting client authentication and
authorization, but that's a more complex proposition and should be
attempted in a separate branch.
Cheers,
--Denys
Vincent Ladeuil (vila) wrote : Posted in a previous version of this proposal | # |
>>>>> "Denys" == Denys Duchier <email address hidden> writes:
Denys> Martin Pool <email address hidden> writes:
>> Does this do authentication at all, or do you plan to add it?
Denys> I wanted to use python's built-in SSL support.
Denys> Verification of certificates is only supported
Denys> starting with python 2.6.
That's the plan for the http client anyway.
Denys> Thus certificate-based authentication is very easy to
Denys> add, but can only be activated for recent python
Denys> distros. If there is interest, I can add support for,
Denys> it of course.
Preliminary work on the test infrastructure is in
bzrlib/
It would be nice to reuse/stay compatible with that.
It's already possible to create the key and cert files and
version the results instead of embedding opaque versions like you
did in creds.py.
Denys> I am also interested in supporting client
Denys> authentication and authorization, but that's a more
Denys> complex proposition and should be attempted in a
Denys> separate branch.
Indeed.
Denys Duchier (denys.duchier) wrote : Posted in a previous version of this proposal | # |
Vincent Ladeuil <email address hidden> writes:
> Preliminary work on the test infrastructure is in
> bzrlib/
>
> It would be nice to reuse/stay compatible with that.
>
> It's already possible to create the key and cert files and
> version the results instead of embedding opaque versions like you
> did in creds.py.
Ah yes! I had not noticed ssl_certs. This is perfect; I'll use it
instead of my hack. Did you have more than this reuse in mind?
Cheers,
--Denys
Vincent Ladeuil (vila) wrote : Posted in a previous version of this proposal | # |
>>>>> "Denys" == Denys Duchier <email address hidden> writes:
Denys> Ah yes! I had not noticed ssl_certs. This is
Denys> perfect; I'll use it instead of my hack. Did you have
Denys> more than this reuse in mind?
_ssl_wrap_socket in bzrlib/
looks very much like your wrap_socket :-)
I'm pretty sure the expand* should go somewhere else, closer to
the CLI UI... i.e. higher in the stack.
Then, since this is now needed in two different places, that may
need to be moved to osutils.py instead.
Other than that, the way you reuse the tests in
blackbox/
You want to move these tests in their own class and make them
parameterized instead.
So I'm voting resubmit (the points above are worth doing a new
submission with them fixed but the overall patch sounds good) and
with that sorted out, I'd leave it to Andrew to review the smart
server part of it.
review: resubmit
reviewer: spiv
- 4610. By Denys Duchier
-
load_tests to multiply bzr tests bare and over SSL
- 4611. By Denys Duchier
-
reinstate useful comments on ssl_wrap_socket.
- 4612. By Denys Duchier
-
improved refactoring. added doc comments.
- 4613. By Denys Duchier
-
renamed: bare->tcp ssl->ssl/tcp.
- 4614. By Denys Duchier
-
prune doc string for RemoteSSLTransport.
- 4615. By Denys Duchier
-
document bzr server over SSL.
- 4616. By Denys Duchier
-
sanity check for --keyfile and --certfile options
- 4617. By Denys Duchier
-
tests for options --keyfile and --certfile
Unmerged revisions
- 4617. By Denys Duchier
-
tests for options --keyfile and --certfile
- 4616. By Denys Duchier
-
sanity check for --keyfile and --certfile options
- 4615. By Denys Duchier
-
document bzr server over SSL.
- 4614. By Denys Duchier
-
prune doc string for RemoteSSLTransport.
- 4613. By Denys Duchier
-
renamed: bare->tcp ssl->ssl/tcp.
- 4612. By Denys Duchier
-
improved refactoring. added doc comments.
- 4611. By Denys Duchier
-
reinstate useful comments on ssl_wrap_socket.
- 4610. By Denys Duchier
-
load_tests to multiply bzr tests bare and over SSL
- 4609. By Denys Duchier
-
cleaned up ssl tests
- 4608. By Denys Duchier
-
moved ssl_wrap_socket to osutils as suggested by Vincent Ladeuil
Preview Diff
1 | === modified file 'bzrlib/builtins.py' |
2 | --- bzrlib/builtins.py 2009-08-10 08:25:53 +0000 |
3 | +++ bzrlib/builtins.py 2009-08-14 20:35:20 +0000 |
4 | @@ -4701,6 +4701,12 @@ |
5 | '--allow-writes enables write access to the contents of ' |
6 | 'the served directory and below.' |
7 | ), |
8 | + Option('keyfile', |
9 | + help="Path to server's private key (for SSL).", |
10 | + type=str), |
11 | + Option('certfile', |
12 | + help="Path to server's certificate (for SSL).", |
13 | + type=str), |
14 | ] |
15 | |
16 | def get_host_and_port(self, port): |
17 | @@ -4723,10 +4729,14 @@ |
18 | return host, port |
19 | |
20 | def run(self, port=None, inet=False, directory=None, allow_writes=False, |
21 | - protocol=None): |
22 | + protocol=None, keyfile=None, certfile=None): |
23 | from bzrlib.transport import get_transport, transport_server_registry |
24 | if directory is None: |
25 | directory = os.getcwd() |
26 | + if keyfile: |
27 | + keyfile = os.path.expanduser(keyfile) |
28 | + if certfile: |
29 | + certfile = os.path.expanduser(certfile) |
30 | if protocol is None: |
31 | protocol = transport_server_registry.get() |
32 | host, port = self.get_host_and_port(port) |
33 | @@ -4734,7 +4744,7 @@ |
34 | if not allow_writes: |
35 | url = 'readonly+' + url |
36 | transport = get_transport(url) |
37 | - protocol(transport, host, port, inet) |
38 | + protocol(transport, host, port, inet, keyfile=keyfile, certfile=certfile) |
39 | |
40 | |
41 | class cmd_join(Command): |
42 | |
43 | === modified file 'bzrlib/osutils.py' |
44 | --- bzrlib/osutils.py 2009-07-23 16:01:17 +0000 |
45 | +++ bzrlib/osutils.py 2009-08-14 20:35:20 +0000 |
46 | @@ -1900,3 +1900,26 @@ |
47 | if use_cache: |
48 | _cached_concurrency = concurrency |
49 | return concurrency |
50 | + |
51 | +_ssl_wrap_socket = None |
52 | + |
53 | +def ssl_wrap_socket(sock, keyfile=None, certfile=None, server_side=False): |
54 | + """Wrap SSL around a socket and return a SSLSocket object. |
55 | + |
56 | + :param sock: the original socket object. |
57 | + :param keyfile: path to the server's private key (only for a server). |
58 | + :param certfile: path to the server's certificate (only for a server). |
59 | + :param server_side: boolean (default False. Pass True for a server). |
60 | + """ |
61 | + global _ssl_wrap_socket |
62 | + if _ssl_wrap_socket is None: |
63 | + try: |
64 | + import ssl |
65 | + _ssl_wrap_socket = ssl.wrap_socket |
66 | + except ImportError: |
67 | + from httplib import FakeSocket |
68 | + def _ssl_wrap_socket(sock, keyfile=None, certfile=None, |
69 | + server_side=False): |
70 | + return FakeSocket(sock, socket.ssl(sock, keyfile, certfile)) |
71 | + return _ssl_wrap_socket(sock, keyfile=keyfile, certfile=certfile, |
72 | + server_side=server_side) |
73 | |
74 | === modified file 'bzrlib/smart/medium.py' |
75 | --- bzrlib/smart/medium.py 2009-08-07 05:56:29 +0000 |
76 | +++ bzrlib/smart/medium.py 2009-08-14 20:35:21 +0000 |
77 | @@ -211,6 +211,7 @@ |
78 | # None during interpreter shutdown. |
79 | from sys import stderr |
80 | try: |
81 | + self._before_serve() |
82 | while not self.finished: |
83 | server_protocol = self._build_protocol() |
84 | self._serve_one_request(server_protocol) |
85 | @@ -218,6 +219,11 @@ |
86 | stderr.write("%s terminating on exception %s\n" % (self, e)) |
87 | raise |
88 | |
89 | + def _before_serve(self): |
90 | + """Executed before the serve loop. Maybe used to setup e.g. ssl. |
91 | + """ |
92 | + pass |
93 | + |
94 | def _build_protocol(self): |
95 | """Identifies the version of the incoming request, and returns an |
96 | a protocol object that can interpret it. |
97 | @@ -260,7 +266,8 @@ |
98 | |
99 | class SmartServerSocketStreamMedium(SmartServerStreamMedium): |
100 | |
101 | - def __init__(self, sock, backing_transport, root_client_path='/'): |
102 | + def __init__(self, sock, backing_transport, root_client_path='/', |
103 | + keyfile=None, certfile=None): |
104 | """Constructor. |
105 | |
106 | :param sock: the socket the server will read from. It will be put |
107 | @@ -269,8 +276,17 @@ |
108 | SmartServerStreamMedium.__init__( |
109 | self, backing_transport, root_client_path=root_client_path) |
110 | sock.setblocking(True) |
111 | + self._keyfile = keyfile |
112 | + self._certfile = certfile |
113 | self.socket = sock |
114 | |
115 | + def _before_serve(self): |
116 | + """Setup ssl if a certificate was provided.""" |
117 | + if self._certfile: |
118 | + self.socket = osutils.ssl_wrap_socket( |
119 | + self.socket, keyfile=self._keyfile, certfile=self._certfile, |
120 | + server_side=True) |
121 | + |
122 | def _serve_one_request_unguarded(self, protocol): |
123 | while protocol.next_read_size(): |
124 | # We can safely try to read large chunks. If there is less data |
125 | @@ -815,13 +831,14 @@ |
126 | class SmartTCPClientMedium(SmartClientStreamMedium): |
127 | """A client medium using TCP.""" |
128 | |
129 | - def __init__(self, host, port, base): |
130 | + def __init__(self, host, port, base, use_ssl=False): |
131 | """Creates a client that will connect on the first use.""" |
132 | SmartClientStreamMedium.__init__(self, base) |
133 | self._connected = False |
134 | self._host = host |
135 | self._port = port |
136 | self._socket = None |
137 | + self._use_ssl = use_ssl |
138 | |
139 | def _accept_bytes(self, bytes): |
140 | """See SmartClientMedium.accept_bytes.""" |
141 | @@ -873,6 +890,9 @@ |
142 | err_msg = err.args[1] |
143 | raise errors.ConnectionError("failed to connect to %s:%d: %s" % |
144 | (self._host, port, err_msg)) |
145 | + if self._use_ssl: |
146 | + self._socket = osutils.ssl_wrap_socket(self._socket, |
147 | + server_side=False) |
148 | self._connected = True |
149 | |
150 | def _flush(self): |
151 | |
152 | === modified file 'bzrlib/smart/server.py' |
153 | --- bzrlib/smart/server.py 2009-07-20 11:27:05 +0000 |
154 | +++ bzrlib/smart/server.py 2009-08-14 20:35:21 +0000 |
155 | @@ -43,7 +43,7 @@ |
156 | """ |
157 | |
158 | def __init__(self, backing_transport, host='127.0.0.1', port=0, |
159 | - root_client_path='/'): |
160 | + root_client_path='/', keyfile=None, certfile=None): |
161 | """Construct a new server. |
162 | |
163 | To actually start it running, call either start_background_thread or |
164 | @@ -54,6 +54,8 @@ |
165 | :param port: TCP port to listen on, or 0 to allocate a transient port. |
166 | :param root_client_path: The client path that will correspond to root |
167 | of backing_transport. |
168 | + :param keyfile: Path to server's private key (for SSL). |
169 | + :param certfile: Path to server's certificate (for SSL). |
170 | """ |
171 | # let connections timeout so that we get a chance to terminate |
172 | # Keep a reference to the exceptions we want to catch because the socket |
173 | @@ -84,6 +86,8 @@ |
174 | self._started = threading.Event() |
175 | self._stopped = threading.Event() |
176 | self.root_client_path = root_client_path |
177 | + self._keyfile = keyfile |
178 | + self._certfile = certfile |
179 | |
180 | def serve(self, thread_name_suffix=''): |
181 | self._should_terminate = False |
182 | @@ -150,7 +154,10 @@ |
183 | |
184 | def get_url(self): |
185 | """Return the url of the server""" |
186 | - return "bzr://%s:%d/" % self._sockname |
187 | + if self._certfile: |
188 | + return "bzrs://%s:%d/" % self._sockname |
189 | + else: |
190 | + return "bzr://%s:%d/" % self._sockname |
191 | |
192 | def serve_conn(self, conn, thread_name_suffix): |
193 | # For WIN32, where the timeout value from the listening socket |
194 | @@ -158,7 +165,8 @@ |
195 | conn.setblocking(True) |
196 | conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) |
197 | handler = medium.SmartServerSocketStreamMedium( |
198 | - conn, self.backing_transport, self.root_client_path) |
199 | + conn, self.backing_transport, self.root_client_path, |
200 | + keyfile=self._keyfile, certfile=self._certfile) |
201 | thread_name = 'smart-server-child' + thread_name_suffix |
202 | connection_thread = threading.Thread( |
203 | None, handler.serve, name=thread_name) |
204 | @@ -313,7 +321,8 @@ |
205 | return transport.get_transport(url) |
206 | |
207 | |
208 | -def serve_bzr(transport, host=None, port=None, inet=False): |
209 | +def serve_bzr(transport, host=None, port=None, inet=False, |
210 | + keyfile=None, certfile=None): |
211 | from bzrlib import lockdir, ui |
212 | from bzrlib.transport import get_transport |
213 | from bzrlib.transport.chroot import ChrootServer |
214 | @@ -328,7 +337,8 @@ |
215 | host = medium.BZR_DEFAULT_INTERFACE |
216 | if port is None: |
217 | port = medium.BZR_DEFAULT_PORT |
218 | - smart_server = SmartTCPServer(transport, host=host, port=port) |
219 | + smart_server = SmartTCPServer(transport, host=host, port=port, |
220 | + keyfile=keyfile, certfile=certfile) |
221 | trace.note('listening on port: %s' % smart_server.port) |
222 | # For the duration of this server, no UI output is permitted. note |
223 | # that this may cause problems with blackbox tests. This should be |
224 | |
225 | === modified file 'bzrlib/tests/blackbox/test_serve.py' |
226 | --- bzrlib/tests/blackbox/test_serve.py 2009-07-20 11:27:05 +0000 |
227 | +++ bzrlib/tests/blackbox/test_serve.py 2009-08-14 20:35:21 +0000 |
228 | @@ -40,7 +40,7 @@ |
229 | from bzrlib.transport import get_transport, remote |
230 | |
231 | |
232 | -class TestBzrServe(TestCaseWithTransport): |
233 | +class TestBzrServeCommon(TestCaseWithTransport): |
234 | |
235 | def assertInetServerShutsdownCleanly(self, process): |
236 | """Shutdown the server process looking for errors.""" |
237 | @@ -71,6 +71,8 @@ |
238 | finally: |
239 | branch.unlock() |
240 | |
241 | +class TestBzrServeInet(TestBzrServeCommon): |
242 | + |
243 | def start_server_inet(self, extra_options=()): |
244 | """Start a bzr server subprocess using the --inet option. |
245 | |
246 | @@ -90,23 +92,6 @@ |
247 | transport = remote.RemoteTransport(url, medium=client_medium) |
248 | return process, transport |
249 | |
250 | - def start_server_port(self, extra_options=()): |
251 | - """Start a bzr server subprocess. |
252 | - |
253 | - :param extra_options: extra options to give the server. |
254 | - :return: a tuple with the bzr process handle for passing to |
255 | - finish_bzr_subprocess, and the base url for the server. |
256 | - """ |
257 | - # Serve from the current directory |
258 | - args = ['serve', '--port', 'localhost:0'] |
259 | - args.extend(extra_options) |
260 | - process = self.start_bzr_subprocess(args, skip_if_plan_to_signal=True) |
261 | - port_line = process.stderr.readline() |
262 | - prefix = 'listening on port: ' |
263 | - self.assertStartsWith(port_line, prefix) |
264 | - port = int(port_line[len(prefix):]) |
265 | - return process,'bzr://localhost:%d/' % port |
266 | - |
267 | def test_bzr_serve_inet_readonly(self): |
268 | """bzr server should provide a read only filesystem by default.""" |
269 | process, transport = self.start_server_inet() |
270 | @@ -124,35 +109,7 @@ |
271 | self.make_read_requests(branch) |
272 | self.assertInetServerShutsdownCleanly(process) |
273 | |
274 | - def test_bzr_serve_port_readonly(self): |
275 | - """bzr server should provide a read only filesystem by default.""" |
276 | - process, url = self.start_server_port() |
277 | - transport = get_transport(url) |
278 | - self.assertRaises(errors.TransportNotPossible, transport.mkdir, 'adir') |
279 | - self.assertServerFinishesCleanly(process) |
280 | - |
281 | - def test_bzr_serve_port_readwrite(self): |
282 | - # Make a branch |
283 | - self.make_branch('.') |
284 | - |
285 | - process, url = self.start_server_port(['--allow-writes']) |
286 | - |
287 | - # Connect to the server |
288 | - branch = Branch.open(url) |
289 | - self.make_read_requests(branch) |
290 | - self.assertServerFinishesCleanly(process) |
291 | - |
292 | - def test_bzr_serve_supports_protocol(self): |
293 | - # Make a branch |
294 | - self.make_branch('.') |
295 | - |
296 | - process, url = self.start_server_port(['--allow-writes', |
297 | - '--protocol=bzr']) |
298 | - |
299 | - # Connect to the server |
300 | - branch = Branch.open(url) |
301 | - self.make_read_requests(branch) |
302 | - self.assertServerFinishesCleanly(process) |
303 | +class TestBzrServeSSH(TestBzrServeCommon): |
304 | |
305 | def test_bzr_connect_to_bzr_ssh(self): |
306 | """User acceptance that get_transport of a bzr+ssh:// behaves correctly. |
307 | @@ -244,6 +201,76 @@ |
308 | self.command_executed) |
309 | |
310 | |
311 | +class TestBzrServePort(TestBzrServeCommon): |
312 | + |
313 | + def start_server_port(self, extra_options=()): |
314 | + """Start a bzr server subprocess. |
315 | + |
316 | + :param extra_options: extra options to give the server. |
317 | + :return: a tuple with the bzr process handle for passing to |
318 | + finish_bzr_subprocess, and the base url for the server. |
319 | + """ |
320 | + # Serve from the current directory |
321 | + args = ['serve', '--port', 'localhost:0'] |
322 | + args.extend(extra_options) |
323 | + urlfmt = 'bzr://localhost:%d/' |
324 | + if self.use_ssl: |
325 | + from bzrlib.tests.ssl_certs import build_path |
326 | + keyfile = build_path('server_without_pass.key') |
327 | + certfile = build_path('server.crt') |
328 | + args.extend(("--keyfile", keyfile, |
329 | + "--certfile", certfile)) |
330 | + urlfmt = 'bzrs://localhost:%d/' |
331 | + process = self.start_bzr_subprocess(args, skip_if_plan_to_signal=True) |
332 | + port_line = process.stderr.readline() |
333 | + prefix = 'listening on port: ' |
334 | + self.assertStartsWith(port_line, prefix) |
335 | + port = int(port_line[len(prefix):]) |
336 | + return process, urlfmt % port |
337 | + |
338 | + def test_bzr_serve_port_readonly(self): |
339 | + """bzr server should provide a read only filesystem by default.""" |
340 | + process, url = self.start_server_port() |
341 | + transport = get_transport(url) |
342 | + self.assertRaises(errors.TransportNotPossible, transport.mkdir, 'adir') |
343 | + self.assertServerFinishesCleanly(process) |
344 | + |
345 | + def test_bzr_serve_port_readwrite(self): |
346 | + # Make a branch |
347 | + self.make_branch('.') |
348 | + |
349 | + process, url = self.start_server_port(['--allow-writes']) |
350 | + |
351 | + # Connect to the server |
352 | + branch = Branch.open(url) |
353 | + self.make_read_requests(branch) |
354 | + self.assertServerFinishesCleanly(process) |
355 | + |
356 | + def test_bzr_serve_supports_protocol(self): |
357 | + # Make a branch |
358 | + self.make_branch('.') |
359 | + |
360 | + process, url = self.start_server_port(['--allow-writes', |
361 | + '--protocol=bzr']) |
362 | + |
363 | + # Connect to the server |
364 | + branch = Branch.open(url) |
365 | + self.make_read_requests(branch) |
366 | + self.assertServerFinishesCleanly(process) |
367 | + |
368 | +def serve_port_scenarios(): |
369 | + return (('bare', dict(use_ssl=False)), |
370 | + ('ssl' , dict(use_ssl=True))) |
371 | + |
372 | +def load_tests(basic_tests, module, loader): |
373 | + from bzrlib import tests |
374 | + suite = loader.suiteClass() |
375 | + serve_port_tests, remaining_tests = tests.split_suite_by_condition( |
376 | + basic_tests, tests.condition_isinstance(TestBzrServePort)) |
377 | + tests.multiply_tests(serve_port_tests, serve_port_scenarios(), suite) |
378 | + suite.addTest(remaining_tests) |
379 | + return suite |
380 | + |
381 | class TestCmdServeChrooting(TestCaseWithTransport): |
382 | |
383 | def test_serve_tcp(self): |
384 | |
385 | === modified file 'bzrlib/transport/__init__.py' |
386 | --- bzrlib/transport/__init__.py 2009-08-04 11:40:59 +0000 |
387 | +++ bzrlib/transport/__init__.py 2009-08-14 20:35:21 +0000 |
388 | @@ -1826,9 +1826,14 @@ |
389 | register_transport_proto('bzr://', |
390 | help="Fast access using the Bazaar smart server.", |
391 | register_netloc=True) |
392 | +register_transport_proto('bzrs://', |
393 | + help="Fast access using the Bazaar smart server over SSL.", |
394 | + register_netloc=True) |
395 | |
396 | register_lazy_transport('bzr://', 'bzrlib.transport.remote', |
397 | 'RemoteTCPTransport') |
398 | +register_lazy_transport('bzrs://', 'bzrlib.transport.remote', |
399 | + 'RemoteSSLTransport') |
400 | register_transport_proto('bzr-v2://', register_netloc=True) |
401 | |
402 | register_lazy_transport('bzr-v2://', 'bzrlib.transport.remote', |
403 | |
404 | === modified file 'bzrlib/transport/http/_urllib2_wrappers.py' |
405 | --- bzrlib/transport/http/_urllib2_wrappers.py 2009-05-04 15:21:26 +0000 |
406 | +++ bzrlib/transport/http/_urllib2_wrappers.py 2009-08-14 20:35:21 +0000 |
407 | @@ -280,19 +280,6 @@ |
408 | self._wrap_socket_for_reporting(self.sock) |
409 | |
410 | |
411 | -# Build the appropriate socket wrapper for ssl |
412 | -try: |
413 | - # python 2.6 introduced a better ssl package |
414 | - import ssl |
415 | - _ssl_wrap_socket = ssl.wrap_socket |
416 | -except ImportError: |
417 | - # python versions prior to 2.6 don't have ssl and ssl.wrap_socket instead |
418 | - # they use httplib.FakeSocket |
419 | - def _ssl_wrap_socket(sock, key_file, cert_file): |
420 | - ssl_sock = socket.ssl(sock, key_file, cert_file) |
421 | - return httplib.FakeSocket(sock, ssl_sock) |
422 | - |
423 | - |
424 | class HTTPSConnection(AbstractHTTPConnection, httplib.HTTPSConnection): |
425 | |
426 | def __init__(self, host, port=None, key_file=None, cert_file=None, |
427 | @@ -313,7 +300,8 @@ |
428 | self.connect_to_origin() |
429 | |
430 | def connect_to_origin(self): |
431 | - ssl_sock = _ssl_wrap_socket(self.sock, self.key_file, self.cert_file) |
432 | + ssl_sock = osutils.ssl_wrap_socket( |
433 | + self.sock, self.key_file, self.cert_file) |
434 | # Wrap the ssl socket before anybody use it |
435 | self._wrap_socket_for_reporting(ssl_sock) |
436 | |
437 | |
438 | === modified file 'bzrlib/transport/remote.py' |
439 | --- bzrlib/transport/remote.py 2009-03-24 01:53:42 +0000 |
440 | +++ bzrlib/transport/remote.py 2009-08-14 20:35:21 +0000 |
441 | @@ -485,6 +485,19 @@ |
442 | return client_medium, None |
443 | |
444 | |
445 | +class RemoteSSLTransport(RemoteTransport): |
446 | + """Connection to smart server over ssl. |
447 | + |
448 | + This is essentially just a factory to get 'RemoteTransport(url, |
449 | + SmartTCPClientMedium). |
450 | + """ |
451 | + |
452 | + def _build_medium(self): |
453 | + client_medium = medium.SmartTCPClientMedium( |
454 | + self._host, self._port, self.base, use_ssl=True) |
455 | + return client_medium, None |
456 | + |
457 | + |
458 | class RemoteTCPTransportV2Only(RemoteTransport): |
459 | """Connection to smart server over plain tcp with the client hard-coded to |
460 | assume protocol v2 and remote server version <= 1.6. |
This branch introduces support for the bzr protocol over SSL.
Server Side
---------------
The smart server can be started with options --keyfile and --certfile to
request that client connections be SSL encrypted:
bzr serve --keyfile FILE --certfile FILE ...
Client Side
--------------
a bzrs:// url causes the client to open an SSL connection to a bzr smart server.