1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """helper classes for creating a twisted server
23 """
24
25 import os
26
27 from twisted.internet import reactor
28 from zope.interface import Interface
29
30 from flumotion.common import log
31
32 __version__ = "$Rev$"
33
34
35 -class _ServerContextFactory(log.Loggable):
36
37 logCategory = "SSLServer"
38
39 - def __init__(self, pemFile):
40 self._pemFile = pemFile
41
42 - def getContext(self):
43 """
44 Create an SSL context.
45 """
46 from OpenSSL import SSL
47 ctx = SSL.Context(SSL.SSLv23_METHOD)
48 try:
49 ctx.use_certificate_file(self._pemFile)
50 ctx.use_privatekey_file(self._pemFile)
51 except SSL.Error, e:
52 self.warning('SSL error: %r' % e.args)
53 self.error('Could not open certificate %s' % self._pemFile)
54 return ctx
55
56
58 """
59 I am an interface for objects that want to be servable through a
60 L{Server}.
61 """
62
64 """
65 @rtype: L{twisted.spread.pb.PBServerFactory}
66 """
67
69 """
70 @param host: the host to listen as
71 @type host: str
72 @param port: the port to listen on
73 @type port: int
74 @param useSSL: whether this connection uses SSL
75 @type useSSL: bool
76 """
77
78
80 logCategory = "server"
81
83 """
84 I expose a servable to the network using TCP or SSL.
85
86 @type servable: an implemtor of L{IServable}
87 """
88 self._servable = servable
89
90 - def startSSL(self, host, port, pemFile, configDir):
91 """
92 Listen as the given host and on the given port using SSL.
93 Use the given .pem file, or look for it in the config directory.
94
95 @param pemFile: File containing the SSL certificate.
96 If it's a full path, respects the full path.
97 If not, looks in configDir for this file.
98 @param configDir: directory where .pem file is stored
99 @returns: {twisted.internet.interfaces.IListeningPort} on which
100 we are listening; call .stopListening() to stop.
101 """
102 from flumotion.common import common
103 common.assertSSLAvailable()
104
105
106 if not os.path.split(pemFile)[0]:
107 pemFile = os.path.join(configDir, pemFile)
108 if not os.path.exists(pemFile):
109 self.error(".pem file %s does not exist.\n" \
110 "For more information, see \n" \
111 "http://www.flumotion.net/doc/flumotion/manual/html/" \
112 "chapter-security.html" % pemFile)
113 log.debug('manager', 'Using PEM certificate file %s' % pemFile)
114 ctxFactory = _ServerContextFactory(pemFile)
115
116 self.info('Starting on port %d using SSL' % port)
117 if not host == "":
118 self.info('Listening as host %s' % host)
119 self._servable.setConnectionInfo(host, port, True)
120 return reactor.listenSSL(port, self._servable.getFactory(),
121 ctxFactory, interface=host)
122
124 """
125 Listen as the given host and on the given port using normal TCP.
126
127 @returns: {twisted.internet.interfaces.IListeningPort} on which
128 we are listening; call .stopListening() to stop.
129 """
130 self.info('Starting on port %d using TCP' % port)
131 if not host == "":
132 self.info('Listening as host %s' % host)
133 self._servable.setConnectionInfo(host, port, False)
134 return reactor.listenTCP(port, self._servable.getFactory(),
135 interface=host)
136