After further investigation, I find that I didn't get relocation using
ssl/tls: the read/write to the pyOpenSSL socket.fileno() will communicate
without data encrypted.
I have add a wrapper to the read/write with the following patch.
This patch also makes pyOpenSSL an optional package.
Note on changing:
raise XendError("can't connect: %s" % err[1])
to:
raise XendError("can't connect: %s" % err)
in tools/python/xen/xend/XendDomain.py:
it will avoid the following error:
[2008-05-08 14:17:28 2678] ERROR (xmlrpclib2:178) Internal error handling
xend.domain.migrate
Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/xen/util/xmlrpclib2.py", line 131, in
_marshaled_dispatch
response = self._dispatch(method, params)
File "/usr/lib/python2.4/SimpleXMLRPCServer.py", line 406, in _dispatch
return func(*params)
File "/usr/lib/python2.4/site-packages/xen/xend/XendDomain.py", line 1335,
in domain_migrate
raise XendError("can't connect: %s" % err[1])
IndexError: tuple index out of range
Implement reference:
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py
Sorry for the careless.
thanks,
zhigang
Carb, Brian A wrote:
> This works on SLES10SP1 if we download a compatible python openssl rpm
> (python-openssl-0.6-17.x86_64.rpm) from opensuse.
>
> brian carb
> unisys corporation - malvern, pa
>
> -----Original Message-----
> From: Zhigang Wang [mailto:zhigang.x.wang@xxxxxxxxxx]
> Sent: Friday, May 02, 2008 2:11 PM
> To: Carb, Brian A
> Cc: xen-devel
> Subject: Re: [Xen-devel] [PATCH] add ssl/tls support to relocation
>
> Yes. I add a dependency.
>
> maybe we can separate SSLTCPListener to a new file like (tcp-ssl.py),
> and import it when needed, just like
> tools/python/xen/xend/server/SSLXMLRPCServer.py did.
>
> will try it later, or you can help.
>
> thanks,
>
> zhigang
>
> Carb, Brian A wrote:
>> With this patch included, xend start errors:
>>
>> # xend start
>> Traceback (most recent call last):
>> File "/usr/sbin/xend", line 44, in ?
>> from xen.xend.server import SrvDaemon
>> File
>> "/home/unisys/xen-unstable.hg/dist/install/usr/lib64/python/xen/xend/s
>> er
>> ver/SrvDaemon.py", line 26, in ?
>> import relocate
>> File
>> "/home/unisys/xen-unstable.hg/dist/install/usr/lib64/python/xen/xend/s
>> er
>> ver/relocate.py", line 23, in ?
>> from xen.web import protocol, tcp, unix
>> File
>>
> "/home/unisys/xen-unstable.hg/dist/install/usr/lib64/python/xen/web/tcp.
>> py", line 25, in ?
>> from OpenSSL import SSL
>> ImportError: No module named OpenSSL
>>
>> I guess this produces a dependency on python-openssl, but this rpm is
>> not included in the standard SLES10 distro.
>>
>> brian carb
>> unisys corporation - malvern, pa
>>
>>
>> -----Original Message-----
>> From: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
>> [mailto:xen-devel-bounces@xxxxxxxxxxxxxxxxxxx] On Behalf Of Zhigang
>> Wang
>> Sent: Sunday, April 27, 2008 10:50 PM
>> To: xen-devel
>> Subject: [Xen-devel] [PATCH] add ssl/tls support to relocation
>>
>> hi, this patch add ssl/tls support to relocation:
>>
>> * SSL/TLS support is disabled by default, as other server did.
>>
>> * If "xend-relocation-server-ssl-key-file" and
>> "xend-relocation-server-ssl-cert-file" exist, SSL/TLS is enabled
>> automatically.
>>
>> * "xend-relocation-tls" is used by relocation client only.
>>
>> Signed-off-by: Zhigang Wang <zhigang.x.wang@xxxxxxxxxx>
>>
>>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
Fix relocation ssl/tls support
* Make a wrapper of read/write sock.fileno().
* Makes pyOpenSSL an optional package.
* Implement reference:
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py
Signed-off-by: Zhigang Wang <zhigang.x.wang@xxxxxxxxxx>
diff -Nura xen-unstable.orig/tools/python/xen/web/connectionssl.py
xen-unstable/tools/python/xen/web/connectionssl.py
--- xen-unstable.orig/tools/python/xen/web/connectionssl.py 1970-01-01
08:00:00.000000000 +0800
+++ xen-unstable/tools/python/xen/web/connectionssl.py 2008-05-08
15:39:44.000000000 +0800
@@ -0,0 +1,188 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This library 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd.
+# Copyright (C) 2008 Oracle
+#============================================================================
+import os
+import socket
+
+from errno import EAGAIN, EINTR, EWOULDBLOCK
+from OpenSSL import SSL
+
+from connection import SocketServerConnection
+from xen.xend.XendLogging import log
+
+"""General classes to support server and client sockets, without
+specifying what kind of socket they are. There are subclasses
+for TCP and unix-domain sockets (see tcp.py and unix.py).
+
+As pyOpenSSL SSL.Connection fileno() method just retrieve the file descriptor
+number for the underlying socket, direct read/write to the file descriptor
+will result no data encrypted.
+
+recv2fd() and fd2send() are simple wrappers for functions who need direct
+read/write to a file descriptor rather than a socket like object.
+
+To use recv2fd(), you can create a pipe and start a thread to transfer all
+received data to one end of the pipe, then read from the other end:
+
+p2cread, p2cwrite = os.pipe()
+threading.Thread(target=connectionssl.recv2fd, args=(sock, p2cwrite)).start()
+os.read(p2cread, 1024)
+
+To use fd2send():
+
+p2cread, p2cwrite = os.pipe()
+threading.Thread(target=connectionssl.fd2send, args=(sock, p2cread)).start()
+os.write(p2cwrite, "data")
+
+"""
+
+BUFFER_SIZE = 1024
+
+
+class SSLSocketServerConnection(SocketServerConnection):
+ """An SSL aware accepted connection to a server.
+ """
+
+ def __init__(self, sock, protocol_class):
+ SocketServerConnection.__init__(self, sock, protocol_class)
+
+ def main(self):
+ try:
+ while True:
+ try:
+ data = self.sock.recv(BUFFER_SIZE)
+ if data == "":
+ break
+ if self.protocol.dataReceived(data):
+ break
+ except socket.error, ex:
+ if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+ break
+ except (SSL.WantReadError, SSL.WantWriteError, \
+ SSL.WantX509LookupError):
+ # The operation did not complete; the same I/O method
+ # should be called again.
+ continue
+ except SSL.ZeroReturnError:
+ # The SSL Connection has been closed.
+ break
+ except SSL.SysCallError, (retval, desc):
+ if ((retval == -1 and desc == "Unexpected EOF")
+ or retval > 0):
+ # The SSL Connection is lost.
+ break
+ log.debug("SSL SysCallError:%d:%s" % (retval, desc))
+ break
+ except SSL.Error, e:
+ # other SSL errors
+ log.debug("SSL Error:%s" % e)
+ break
+ finally:
+ try:
+ self.sock.close()
+ except:
+ pass
+
+def recv2fd(sock, fd):
+ try:
+ while True:
+ try:
+ data = sock.recv(BUFFER_SIZE)
+ if data == "":
+ break
+ count = 0
+ while count < len(data):
+ try:
+ nbytes = os.write(fd, data[count:])
+ count += nbytes
+ except os.error, ex:
+ if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+ raise
+ except socket.error, ex:
+ if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+ break
+ except (SSL.WantReadError, SSL.WantWriteError, \
+ SSL.WantX509LookupError):
+ # The operation did not complete; the same I/O method
+ # should be called again.
+ continue
+ except SSL.ZeroReturnError:
+ # The SSL Connection has been closed.
+ break
+ except SSL.SysCallError, (retval, desc):
+ if ((retval == -1 and desc == "Unexpected EOF")
+ or retval > 0):
+ # The SSL Connection is lost.
+ break
+ log.debug("SSL SysCallError:%d:%s" % (retval, desc))
+ break
+ except SSL.Error, e:
+ # other SSL errors
+ log.debug("SSL Error:%s" % e)
+ break
+ finally:
+ try:
+ sock.close()
+ os.close(fd)
+ except:
+ pass
+
+def fd2send(sock, fd):
+ try:
+ while True:
+ try:
+ data = os.read(fd, BUFFER_SIZE)
+ if data == "":
+ break
+ count = 0
+ while count < len(data):
+ try:
+ nbytes = sock.send(data[count:])
+ count += nbytes
+ except socket.error, ex:
+ if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+ raise
+ except (SSL.WantReadError, SSL.WantWriteError, \
+ SSL.WantX509LookupError):
+ # The operation did not complete; the same I/O method
+ # should be called again.
+ continue
+ except SSL.ZeroReturnError:
+ # The SSL Connection has been closed.
+ raise
+ except SSL.SysCallError, (retval, desc):
+ if not (e[0] == -1 and data == ""):
+ # errors when writing empty strings are expected
+ # and can be ignored
+ log.debug("SSL SysCallError:%d:%s" % (retval,
desc))
+ raise
+ except SSL.Error, e:
+ # other SSL errors
+ log.debug("SSL Error:%s" % e)
+ raise
+ except os.error, ex:
+ if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+ break
+ finally:
+ try:
+ sock.close()
+ os.close(fd)
+ except:
+ pass
+
diff -Nura xen-unstable.orig/tools/python/xen/web/tcp.py
xen-unstable/tools/python/xen/web/tcp.py
--- xen-unstable.orig/tools/python/xen/web/tcp.py 2008-05-05
14:17:45.000000000 +0800
+++ xen-unstable/tools/python/xen/web/tcp.py 2008-05-05 14:32:16.000000000
+0800
@@ -22,8 +22,6 @@
import socket
import time
-from OpenSSL import SSL
-
import connection
from xen.xend.XendLogging import log
@@ -67,41 +65,3 @@
except:
pass
-class SSLTCPListener(TCPListener):
-
- def __init__(self, protocol_class, port, interface, hosts_allow,
- ssl_key_file = None, ssl_cert_file = None):
- if not ssl_key_file or not ssl_cert_file:
- raise ValueError("SSLXMLRPCServer requires ssl_key_file "
- "and ssl_cert_file to be set.")
-
- self.ssl_key_file = ssl_key_file
- self.ssl_cert_file = ssl_cert_file
-
- TCPListener.__init__(self, protocol_class, port, interface,
hosts_allow)
-
-
- def createSocket(self):
- # make a SSL socket
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- ctx.set_options(SSL.OP_NO_SSLv2)
- ctx.use_privatekey_file (self.ssl_key_file)
- ctx.use_certificate_file(self.ssl_cert_file)
- sock = SSL.Connection(ctx,
- socket.socket(socket.AF_INET,
socket.SOCK_STREAM))
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- # SO_REUSEADDR does not always ensure that we do not get an address
- # in use error when restarted quickly
- # we implement a timeout to try and avoid failing unnecessarily
- timeout = time.time() + 30
- while True:
- try:
- sock.bind((self.interface, self.port))
- return sock
- except socket.error, (_errno, strerrno):
- if _errno == errno.EADDRINUSE and time.time() < timeout:
- time.sleep(0.5)
- else:
- raise
-
diff -Nura xen-unstable.orig/tools/python/xen/web/tcpssl.py
xen-unstable/tools/python/xen/web/tcpssl.py
--- xen-unstable.orig/tools/python/xen/web/tcpssl.py 1970-01-01
08:00:00.000000000 +0800
+++ xen-unstable/tools/python/xen/web/tcpssl.py 2008-05-08 15:38:54.000000000
+0800
@@ -0,0 +1,82 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd.
+# Copyright (C) 2008 Oracle
+#============================================================================
+
+
+import errno
+import socket
+import time
+
+import connection
+import connectionssl
+
+from OpenSSL import SSL
+from tcp import TCPListener
+from xen.xend.XendLogging import log
+
+
+class SSLTCPListener(TCPListener):
+
+ def __init__(self, protocol_class, port, interface, hosts_allow,
+ ssl_key_file = None, ssl_cert_file = None):
+ if not ssl_key_file or not ssl_cert_file:
+ raise ValueError("SSLXMLRPCServer requires ssl_key_file "
+ "and ssl_cert_file to be set.")
+
+ self.ssl_key_file = ssl_key_file
+ self.ssl_cert_file = ssl_cert_file
+
+ TCPListener.__init__(self, protocol_class, port, interface,
hosts_allow)
+
+
+ def createSocket(self):
+ # make a SSL socket
+ ctx = SSL.Context(SSL.SSLv23_METHOD)
+ ctx.set_options(SSL.OP_NO_SSLv2)
+ ctx.use_privatekey_file (self.ssl_key_file)
+ ctx.use_certificate_file(self.ssl_cert_file)
+ sock = SSL.Connection(ctx,
+ socket.socket(socket.AF_INET,
socket.SOCK_STREAM))
+ sock.set_accept_state()
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+
+ # SO_REUSEADDR does not always ensure that we do not get an address
+ # in use error when restarted quickly
+ # we implement a timeout to try and avoid failing unnecessarily
+ timeout = time.time() + 30
+ while True:
+ try:
+ sock.bind((self.interface, self.port))
+ return sock
+ except socket.error, (_errno, strerrno):
+ if _errno == errno.EADDRINUSE and time.time() < timeout:
+ time.sleep(0.5)
+ else:
+ raise
+
+
+ def acceptConnection(self, sock, addrport):
+ addr = addrport[0]
+ if connection.hostAllowed(addrport, self.hosts_allow):
+ connectionssl.SSLSocketServerConnection(sock, self.protocol_class)
+ else:
+ try:
+ sock.close()
+ except:
+ pass
+
diff -Nura xen-unstable.orig/tools/python/xen/xend/server/relocate.py
xen-unstable/tools/python/xen/xend/server/relocate.py
--- xen-unstable.orig/tools/python/xen/xend/server/relocate.py 2008-05-05
14:17:46.000000000 +0800
+++ xen-unstable/tools/python/xen/xend/server/relocate.py 2008-05-07
16:39:00.000000000 +0800
@@ -17,10 +17,18 @@
#============================================================================
import re
+import os
import sys
import StringIO
+import threading
from xen.web import protocol, tcp, unix
+try:
+ from xen.web import tcpssl
+ from xen.web import connectionssl
+ ssl_enabled = True
+except ImportError:
+ ssl_enabled = False
from xen.xend import sxp
from xen.xend import XendDomain
@@ -116,6 +124,27 @@
log.error(name + ": no transport")
raise XendError(name + ": no transport")
+ def op_sslreceive(self, name, _):
+ if self.transport:
+ self.send_reply(["ready", name])
+ p2cread, p2cwrite = os.pipe()
+ if not ssl_enabled:
+ raise ValueError("pyOpenSSL not installed. "
+ "Unable to start relocation with ssl")
+ threading.Thread(target=connectionssl.recv2fd,
+ args=(self.transport.sock, p2cwrite)).start()
+ try:
+ XendDomain.instance().domain_restore_fd(p2cread,
+ relocating=True)
+ except:
+ os.close(p2cread)
+ os.close(p2cwrite)
+ self.send_error()
+ self.close()
+ else:
+ log.error(name + ": no transport")
+ raise XendError(name + ": no transport")
+
def listenRelocation():
xoptions = XendOptions.instance()
@@ -136,10 +165,13 @@
ssl_cert_file = xoptions.get_xend_relocation_server_ssl_cert_file()
if ssl_key_file and ssl_cert_file:
- tcp.SSLTCPListener(RelocationProtocol, port, interface = interface,
- hosts_allow = hosts_allow,
- ssl_key_file = ssl_key_file,
- ssl_cert_file = ssl_cert_file)
+ if not ssl_enabled:
+ raise ValueError("pyOpenSSL not installed. "
+ "Unable to start relocation server with ssl")
+ tcpssl.SSLTCPListener(RelocationProtocol, port, interface =
interface,
+ hosts_allow = hosts_allow,
+ ssl_key_file = ssl_key_file,
+ ssl_cert_file = ssl_cert_file)
else:
tcp.TCPListener(RelocationProtocol, port, interface = interface,
hosts_allow = hosts_allow)
diff -Nura xen-unstable.orig/tools/python/xen/xend/XendDomain.py
xen-unstable/tools/python/xen/xend/XendDomain.py
--- xen-unstable.orig/tools/python/xen/xend/XendDomain.py 2008-05-05
14:17:45.000000000 +0800
+++ xen-unstable/tools/python/xen/xend/XendDomain.py 2008-05-08
14:56:54.000000000 +0800
@@ -1297,19 +1297,39 @@
tls = xoptions.get_xend_relocation_tls()
if tls:
from OpenSSL import SSL
+ from xen.web import connectionssl
ctx = SSL.Context(SSL.SSLv23_METHOD)
- sock = SSL.Connection(ctx, socket.socket(socket.AF_INET,
socket.SOCK_STREAM))
+ sock = SSL.Connection(ctx,
+ socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.set_connect_state()
+ sock.connect((dst, port))
+ sock.send("sslreceive\n")
+ sock.recv(80)
+ p2cread, p2cwrite = os.pipe()
+ threading.Thread(target=connectionssl.fd2send,
+ args=(sock, p2cread)).start()
+ XendCheckpoint.save(p2cwrite, dominfo, True, live, dst,
+ node=node)
+ os.close(p2cread)
+ os.close(p2cwrite)
+ sock.shutdown()
+ sock.close()
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect((dst, port))
+ # When connecting our ssl enabled relocation server using a
+ # plain socket, send will success but recv will block. Add a
+ # 30 seconds timeout to raise a socket.timeout exception to
+ # inform the client.
+ sock.settimeout(30.0)
+ sock.connect((dst, port))
+ sock.send("receive\n")
+ sock.recv(80)
+ sock.settimeout(None)
+ XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst,
+ node=node)
+ sock.close()
except socket.error, err:
- raise XendError("can't connect: %s" % err[1])
-
- sock.send("receive\n")
- sock.recv(80)
- XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst, node=node)
- sock.close()
+ raise XendError("can't connect: %s" % err)
def domain_save(self, domid, dst, checkpoint=False):
"""Start saving a domain to file.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|