diff options
Diffstat (limited to 'doc/core/howto/ssl.html')
-rw-r--r-- | doc/core/howto/ssl.html | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/doc/core/howto/ssl.html b/doc/core/howto/ssl.html new file mode 100644 index 0000000..6744ad3 --- /dev/null +++ b/doc/core/howto/ssl.html @@ -0,0 +1,550 @@ +<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + <head> +<title>Twisted Documentation: Using SSL in Twisted</title> +<link href="stylesheet.css" rel="stylesheet" type="text/css"/> + </head> + + <body bgcolor="white"> + <h1 class="title">Using SSL in Twisted</h1> + <div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">SSL echo server and client without client authentication</a></li><ul><li><a href="#auto2">SSL echo server</a></li><li><a href="#auto3">SSL echo client</a></li></ul><li><a href="#auto4">Using startTLS</a></li><ul><li><a href="#auto5">startTLS server</a></li><li><a href="#auto6">startTLS client</a></li></ul><li><a href="#auto7">Client authentication</a></li><ul><li><a href="#auto8">Client-authenticating server</a></li><li><a href="#auto9">Client with certificates</a></li></ul><li><a href="#auto10">Other facilities</a></li><li><a href="#auto11">Conclusion</a></li></ol></div> + <div class="content"> + <span/> + + <h2>Overview<a name="auto0"/></h2> + + <p>This document describes how to use SSL in Twisted servers and clients. It + assumes that you know what SSL is, what some of the major reasons to use it + are, and how to generate your own SSL certificates, in particular self-signed + certificates. It also assumes that you are comfortable with creating TCP + servers and clients as described in the <a href="servers.html" shape="rect">server howto + </a> and <a href="clients.html" shape="rect">client howto</a>. After reading this + document you should be able to create servers and clients that can use SSL to + encrypt their connections, switch from using an unencrypted channel to an + encrypted one mid-connection, and require client authentication.</p> + + <p>Using SSL in Twisted requires that you have + <a href="http://pyopenssl.sf.net" shape="rect">pyOpenSSL</a> installed. A quick test to + verify that you do is to run <code>from OpenSSL import SSL</code> at a + python prompt and not get an error.</p> + + <p>SSL connections require SSL contexts. These contexts are generated by a + <code>ContextFactory</code> that maintains state like the SSL method, private + key file name, and certificate file name.</p> + + <p>Instead of using listenTCP and connectTCP to create a connection, use + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorSSL.listenSSL.html" title="twisted.internet.interfaces.IReactorSSL.listenSSL">listenSSL</a></code> and + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorSSL.connectSSL.html" title="twisted.internet.interfaces.IReactorSSL.connectSSL">connectSSL</a></code> for a + server and client respectively. These methods take a contextFactory as an + additional argument.</p> + + <p>The basic server context factory is + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.ssl.ContextFactory.html" title="twisted.internet.ssl.ContextFactory">twisted.internet.ssl.ContextFactory</a></code>, and the basic + client context factory is + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.ssl.ClientContextFactory.html" title="twisted.internet.ssl.ClientContextFactory">twisted.internet.ssl.ClientContextFactory</a></code>. They can + be used as-is or subclassed. + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.ssl.DefaultOpenSSLContextFactory.html" title="twisted.internet.ssl.DefaultOpenSSLContextFactory">twisted.internet.ssl.DefaultOpenSSLContextFactory</a></code> + is a convenience server class that subclasses <code>ContextFactory</code> + and adds default parameters to the SSL handshake and connection. Another + useful class is + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.ssl.CertificateOptions.html" title="twisted.internet.ssl.CertificateOptions">twisted.internet.ssl.CertificateOptions</a></code>; it is a + factory for SSL context objects that lets you specify many of the common + verification and session options so it can do the proper pyOpenSSL + initialization for you.</p> + + <p>Those are the big immediate differences between TCP and SSL connections, + so let's look at an example. In it and all subsequent examples it is assumed + that keys and certificates for the server, certificate authority, and client + should they exist live in a <i>keys/</i> subdirectory of the directory + containing the example code, and that the certificates are self-signed.</p> + + <h2>SSL echo server and client without client authentication<a name="auto1"/></h2> + + <p>Authentication and encryption are two separate parts of the SSL protocol. + The server almost always needs a key and certificate to authenticate itself + to the client but is usually configured to allow encrypted connections with + unauthenticated clients who don't have certificates. This common case is + demonstrated first by adding SSL support to the echo client and server in + the <a href="../examples/index.html" shape="rect">core examples</a>.</p> + + <h3>SSL echo server<a name="auto2"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ssl</span>, <span class="py-src-variable">reactor</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Factory</span>, <span class="py-src-variable">Protocol</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>): + <span class="py-src-string">"""As soon as any data is received, write it back."""</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">data</span>) + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">Factory</span>() + <span class="py-src-variable">factory</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">Echo</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenSSL</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>, + <span class="py-src-variable">ssl</span>.<span class="py-src-variable">DefaultOpenSSLContextFactory</span>( + <span class="py-src-string">'keys/server.key'</span>, <span class="py-src-string">'keys/server.crt'</span>)) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <h3>SSL echo client<a name="auto3"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ssl</span>, <span class="py-src-variable">reactor</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span>, <span class="py-src-variable">Protocol</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClient</span>(<span class="py-src-parameter">Protocol</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"hello, world"</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">"hello, world!"</span>) + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Server said:"</span>, <span class="py-src-variable">data</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>() + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span>(<span class="py-src-parameter">ClientFactory</span>): + <span class="py-src-variable">protocol</span> = <span class="py-src-variable">EchoClient</span> + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Connection failed - goodbye!"</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Connection lost - goodbye!"</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">EchoClientFactory</span>() + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectSSL</span>(<span class="py-src-string">'localhost'</span>, <span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>, <span class="py-src-variable">ssl</span>.<span class="py-src-variable">ClientContextFactory</span>()) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <p>Contexts are created according to a specified method. + <code>SSLv3_METHOD</code>, <code>SSLv23_METHOD</code>, and + <code>TLSv1_METHOD</code> are the valid constants that represent SSL methods + to use when creating a context object. <code>DefaultOpenSSLContextFactory</code> and + <code>ClientContextFactory</code> default to using <code>SSL.SSLv23_METHOD</code> as their + method, and it is compatible for communication with all the other methods + listed above. An older method constant, <code>SSLv2_METHOD</code>, exists but + is explicitly disallowed in both <code>DefaultOpenSSLContextFactory</code> and + <code>ClientContextFactory</code> for being insecure by calling + <code>set_options(SSL.OP_NO_SSLv2)</code> on their contexts. See + <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.ssl.html" title="twisted.internet.ssl">twisted.internet.ssl</a></code> for additional comments.</p> + + <h2>Using startTLS<a name="auto4"/></h2> + + <p>If you want to switch from unencrypted to encrypted traffic + mid-connection, you'll need to turn on SSL with <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.ITLSTransport.startTLS.html" title="twisted.internet.interfaces.ITLSTransport.startTLS">startTLS</a></code> on both + ends of the connection at the same time via some agreed-upon signal like the + reception of a particular message. You can readily verify the switch to an + encrypted channel by examining the packet payloads with a tool like + <a href="http://www.wireshark.org/" shape="rect">Wireshark</a>.</p> + + <h3>startTLS server<a name="auto5"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">OpenSSL</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SSL</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>, <span class="py-src-variable">ssl</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ServerFactory</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span>.<span class="py-src-variable">basic</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">LineReceiver</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">TLSServer</span>(<span class="py-src-parameter">LineReceiver</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">line</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"received: "</span> + <span class="py-src-variable">line</span> + + <span class="py-src-keyword">if</span> <span class="py-src-variable">line</span> == <span class="py-src-string">"STARTTLS"</span>: + <span class="py-src-keyword">print</span> <span class="py-src-string">"-- Switching to TLS"</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">sendLine</span>(<span class="py-src-string">'READY'</span>) + <span class="py-src-variable">ctx</span> = <span class="py-src-variable">ServerTLSContext</span>( + <span class="py-src-variable">privateKeyFileName</span>=<span class="py-src-string">'keys/server.key'</span>, + <span class="py-src-variable">certificateFileName</span>=<span class="py-src-string">'keys/server.crt'</span>, + ) + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">startTLS</span>(<span class="py-src-variable">ctx</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>) + + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">ServerTLSContext</span>(<span class="py-src-parameter">ssl</span>.<span class="py-src-parameter">DefaultOpenSSLContextFactory</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, *<span class="py-src-parameter">args</span>, **<span class="py-src-parameter">kw</span>): + <span class="py-src-variable">kw</span>[<span class="py-src-string">'sslmethod'</span>] = <span class="py-src-variable">SSL</span>.<span class="py-src-variable">TLSv1_METHOD</span> + <span class="py-src-variable">ssl</span>.<span class="py-src-variable">DefaultOpenSSLContextFactory</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>, *<span class="py-src-variable">args</span>, **<span class="py-src-variable">kw</span>) + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">ServerFactory</span>() + <span class="py-src-variable">factory</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">TLSServer</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenTCP</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <h3>startTLS client<a name="auto6"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">OpenSSL</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SSL</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>, <span class="py-src-variable">ssl</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span>.<span class="py-src-variable">basic</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">LineReceiver</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">ClientTLSContext</span>(<span class="py-src-parameter">ssl</span>.<span class="py-src-parameter">ClientContextFactory</span>): + <span class="py-src-variable">isClient</span> = <span class="py-src-number">1</span> + <span class="py-src-keyword">def</span> <span class="py-src-identifier">getContext</span>(<span class="py-src-parameter">self</span>): + <span class="py-src-keyword">return</span> <span class="py-src-variable">SSL</span>.<span class="py-src-variable">Context</span>(<span class="py-src-variable">SSL</span>.<span class="py-src-variable">TLSv1_METHOD</span>) + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">TLSClient</span>(<span class="py-src-parameter">LineReceiver</span>): + <span class="py-src-variable">pretext</span> = [ + <span class="py-src-string">"first line"</span>, + <span class="py-src-string">"last thing before TLS starts"</span>, + <span class="py-src-string">"STARTTLS"</span>] + + <span class="py-src-variable">posttext</span> = [ + <span class="py-src-string">"first thing after TLS started"</span>, + <span class="py-src-string">"last thing ever"</span>] + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>): + <span class="py-src-keyword">for</span> <span class="py-src-variable">l</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">pretext</span>: + <span class="py-src-variable">self</span>.<span class="py-src-variable">sendLine</span>(<span class="py-src-variable">l</span>) + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">line</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"received: "</span> + <span class="py-src-variable">line</span> + <span class="py-src-keyword">if</span> <span class="py-src-variable">line</span> == <span class="py-src-string">"READY"</span>: + <span class="py-src-variable">ctx</span> = <span class="py-src-variable">ClientTLSContext</span>() + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">startTLS</span>(<span class="py-src-variable">ctx</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>) + <span class="py-src-keyword">for</span> <span class="py-src-variable">l</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">posttext</span>: + <span class="py-src-variable">self</span>.<span class="py-src-variable">sendLine</span>(<span class="py-src-variable">l</span>) + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>() + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">TLSClientFactory</span>(<span class="py-src-parameter">ClientFactory</span>): + <span class="py-src-variable">protocol</span> = <span class="py-src-variable">TLSClient</span> + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"connection failed: "</span>, <span class="py-src-variable">reason</span>.<span class="py-src-variable">getErrorMessage</span>() + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"connection lost: "</span>, <span class="py-src-variable">reason</span>.<span class="py-src-variable">getErrorMessage</span>() + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">"__main__"</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">TLSClientFactory</span>() + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectTCP</span>(<span class="py-src-string">'localhost'</span>, <span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <p><code>startTLS</code> is a transport method that gets passed a context. + It is invoked at an agreed-upon time in the data reception method of the + client and server protocols. The <code>ServerTLSContext</code> and + <code>ClientTLSContext</code> classes used above inherit from the basic + server and client context factories used in the earlier echo examples and + illustrate two more ways of setting an SSL method.</p> + + <h2>Client authentication<a name="auto7"/></h2> + + <p>Server and client-side changes to require client authentication fall + largely under the dominion of pyOpenSSL, but few examples seem to exist on + the web so for completeness a sample server and client are provided here.</p> + + <h3>Client-authenticating server<a name="auto8"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">OpenSSL</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SSL</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ssl</span>, <span class="py-src-variable">reactor</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Factory</span>, <span class="py-src-variable">Protocol</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>): + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">data</span>) + +<span class="py-src-keyword">def</span> <span class="py-src-identifier">verifyCallback</span>(<span class="py-src-parameter">connection</span>, <span class="py-src-parameter">x509</span>, <span class="py-src-parameter">errnum</span>, <span class="py-src-parameter">errdepth</span>, <span class="py-src-parameter">ok</span>): + <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">ok</span>: + <span class="py-src-keyword">print</span> <span class="py-src-string">'invalid cert from subject:'</span>, <span class="py-src-variable">x509</span>.<span class="py-src-variable">get_subject</span>() + <span class="py-src-keyword">return</span> <span class="py-src-variable">False</span> + <span class="py-src-keyword">else</span>: + <span class="py-src-keyword">print</span> <span class="py-src-string">"Certs are fine"</span> + <span class="py-src-keyword">return</span> <span class="py-src-variable">True</span> + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">Factory</span>() + <span class="py-src-variable">factory</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">Echo</span> + + <span class="py-src-variable">myContextFactory</span> = <span class="py-src-variable">ssl</span>.<span class="py-src-variable">DefaultOpenSSLContextFactory</span>( + <span class="py-src-string">'keys/server.key'</span>, <span class="py-src-string">'keys/server.crt'</span> + ) + + <span class="py-src-variable">ctx</span> = <span class="py-src-variable">myContextFactory</span>.<span class="py-src-variable">getContext</span>() + + <span class="py-src-variable">ctx</span>.<span class="py-src-variable">set_verify</span>( + <span class="py-src-variable">SSL</span>.<span class="py-src-variable">VERIFY_PEER</span> | <span class="py-src-variable">SSL</span>.<span class="py-src-variable">VERIFY_FAIL_IF_NO_PEER_CERT</span>, + <span class="py-src-variable">verifyCallback</span> + ) + + <span class="py-src-comment"># Since we have self-signed certs we have to explicitly</span> + <span class="py-src-comment"># tell the server to trust them.</span> + <span class="py-src-variable">ctx</span>.<span class="py-src-variable">load_verify_locations</span>(<span class="py-src-string">"keys/ca.pem"</span>) + + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenSSL</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>, <span class="py-src-variable">myContextFactory</span>) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <p>Use the <code>set_verify</code> method to set the verification mode for a + context object and the verification callback. The mode is either + <code>VERIFY_NONE</code> or <code>VERIFY_PEER</code>. If + <code>VERIFY_PEER</code> is set, the mode can be augmented by + <code>VERIFY_FAIL_IF_NO_PEER_CERT</code> and/or + <code>VERIFY_CLIENT_ONCE</code>.</p> + + <p>The callback takes as its arguments a connection object, X509 object, + error number, error depth, and return code. The purpose of the callback is + to allow you to enforce additional restrictions on the verification. Thus, + if the return code is False, you should return False; if the return code is + True <i>and</i> further verification passes, return True.</p> + + + <h3>Client with certificates<a name="auto9"/></h3> + + <pre class="python"><p class="py-linenumber"> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +</p><span class="py-src-keyword">from</span> <span class="py-src-variable">OpenSSL</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SSL</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ssl</span>, <span class="py-src-variable">reactor</span> +<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span>, <span class="py-src-variable">Protocol</span> + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClient</span>(<span class="py-src-parameter">Protocol</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"hello, world"</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">"hello, world!"</span>) + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Server said:"</span>, <span class="py-src-variable">data</span> + <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>() + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span>(<span class="py-src-parameter">ClientFactory</span>): + <span class="py-src-variable">protocol</span> = <span class="py-src-variable">EchoClient</span> + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Connection failed - goodbye!"</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + + <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>): + <span class="py-src-keyword">print</span> <span class="py-src-string">"Connection lost - goodbye!"</span> + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>() + +<span class="py-src-keyword">class</span> <span class="py-src-identifier">CtxFactory</span>(<span class="py-src-parameter">ssl</span>.<span class="py-src-parameter">ClientContextFactory</span>): + <span class="py-src-keyword">def</span> <span class="py-src-identifier">getContext</span>(<span class="py-src-parameter">self</span>): + <span class="py-src-variable">self</span>.<span class="py-src-variable">method</span> = <span class="py-src-variable">SSL</span>.<span class="py-src-variable">SSLv23_METHOD</span> + <span class="py-src-variable">ctx</span> = <span class="py-src-variable">ssl</span>.<span class="py-src-variable">ClientContextFactory</span>.<span class="py-src-variable">getContext</span>(<span class="py-src-variable">self</span>) + <span class="py-src-variable">ctx</span>.<span class="py-src-variable">use_certificate_file</span>(<span class="py-src-string">'keys/client.crt'</span>) + <span class="py-src-variable">ctx</span>.<span class="py-src-variable">use_privatekey_file</span>(<span class="py-src-string">'keys/client.key'</span>) + + <span class="py-src-keyword">return</span> <span class="py-src-variable">ctx</span> + +<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>: + <span class="py-src-variable">factory</span> = <span class="py-src-variable">EchoClientFactory</span>() + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectSSL</span>(<span class="py-src-string">'localhost'</span>, <span class="py-src-number">8000</span>, <span class="py-src-variable">factory</span>, <span class="py-src-variable">CtxFactory</span>()) + <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>() +</pre> + + <h2>Other facilities<a name="auto10"/></h2> + + <p><code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.protocols.amp.html" title="twisted.protocols.amp">twisted.protocols.amp</a></code> supports encrypted + connections and exposes a <code>startTLS</code> method one can use or + subclass. <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.web.html" title="twisted.web">twisted.web</a></code> has built-in SSL support in + its <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.web.client.html" title="twisted.web.client">client</a></code>, <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.web.http.html" title="twisted.web.http">http</a></code>, and <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.web.xmlrpc.html" title="twisted.web.xmlrpc">xmlrpc</a></code> modules.</p> + + <h2>Conclusion<a name="auto11"/></h2> + + <p>After reading through this tutorial, you should be able to: </p> + <ul> + <li>Use <code>listenSSL</code> and <code>connectSSL</code> to create servers and clients that use + SSL</li> + <li>Use <code>startTLS</code> to switch a channel from being unencrypted to using SSL + mid-connection</li> + <li>Add server and client support for client authentication</li> + </ul> + + </div> + + <p><a href="index.html">Index</a></p> + <span class="version">Version: 12.1.0</span> + </body> +</html>
\ No newline at end of file |