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