All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhigang Wang <zhigang.x.wang@oracle.com>
To: xen-devel <xen-devel@lists.xensource.com>
Subject: Re: [PATCH] add ssl/tls support to relocation
Date: Tue, 13 May 2008 16:16:48 +0800	[thread overview]
Message-ID: <48294E70.40808@oracle.com> (raw)
In-Reply-To: <4829499B.3010704@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 1493 bytes --]

find some typos in comments after post. fix it and regenerate a patch.

use this one please.

thanks,

zhigang

Zhigang Wang wrote:
> Thanks Keir,
> 
> I reorganized the code and did a little more test, it just works.
> 
> But maybe the best way is to patch pyOpenSSL, or use python built-in
> SSL support after python 2.5 in the future.
> 
> And maybe someone (me ;-)) can rewrite the migration protocol based on
> a more robust framework.
> 
> Someone already uses it to make papers:
> http://www.eecs.umich.edu/techreports/cse/2007/CSE-TR-539-07.pdf
> 
> comments & testing are welcome.
> 
> thanks
> 
> zhigang
> 
> Keir Fraser wrote:
>> On 8/5/08 13:55, "Zhigang Wang" <zhigang.x.wang@oracle.com> wrote:
>>
>>> 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.
>> Need to be merged with current unstable tip (which is at least changeset
>> 17589). Note also that 17577 has already made OpenSSL optional, and with
>> less code movement than your approach.
>>
>>  -- Keir
>>
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xensource.com
>> http://lists.xensource.com/xen-devel
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xensource.com
>> http://lists.xensource.com/xen-devel

[-- Attachment #2: xen-unstable-ssl-relocation-errata.patch --]
[-- Type: text/x-patch, Size: 13293 bytes --]

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@oracle.com>

diff -Nura xen-unstable.orig/tools/python/xen/web/connection.py xen-unstable/tools/python/xen/web/connection.py
--- xen-unstable.orig/tools/python/xen/web/connection.py	2008-05-12 16:43:51.000000000 +0800
+++ xen-unstable/tools/python/xen/web/connection.py	2008-05-13 16:10:57.000000000 +0800
@@ -18,12 +18,18 @@
 #============================================================================
 
 import sys
+import os
 import threading
 import socket
 import fcntl
 
 from errno import EAGAIN, EINTR, EWOULDBLOCK
 
+try:
+    from OpenSSL import SSL
+except ImportError:
+    pass
+
 from xen.xend.XendLogging import log
 
 """General classes to support server and client sockets, without
@@ -115,6 +121,167 @@
             self.close()
 
 
+class SSLSocketServerConnection(SocketServerConnection):
+    """An SSL aware accepted connection to a server.
+
+    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=connection.SSLSocketServerConnection.recv2fd,
+                     args=(sock, p2cwrite)).start()
+    os.read(p2cread, 1024)
+    
+    To use fd2send():
+    
+    p2cread, p2cwrite = os.pipe()
+    threading.Thread(target=connection.SSLSocketServerConnection.fd2send,
+                     args=(sock, p2cread)).start()
+    os.write(p2cwrite, "data")
+    """
+
+    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
+
+    recv2fd = staticmethod(recv2fd)
+
+
+    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 (retval == -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
+
+    fd2send = staticmethod(fd2send)
+
+
 def hostAllowed(addrport, hosts_allowed):
     if hosts_allowed is None:
         return True
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-12 16:43:51.000000000 +0800
+++ xen-unstable/tools/python/xen/web/tcp.py	2008-05-12 17:03:49.000000000 +0800
@@ -88,6 +88,7 @@
         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
@@ -104,3 +105,14 @@
                 else:
                     raise
 
+
+    def acceptConnection(self, sock, addrport):
+        addr = addrport[0]
+        if connection.hostAllowed(addrport, self.hosts_allow):
+            connection.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-12 16:43:52.000000000 +0800
+++ xen-unstable/tools/python/xen/xend/server/relocate.py	2008-05-13 14:26:23.000000000 +0800
@@ -17,10 +17,12 @@
 #============================================================================
 
 import re
+import os
 import sys
 import StringIO
+import threading
 
-from xen.web import protocol, tcp, unix
+from xen.web import protocol, tcp, unix, connection
 
 from xen.xend import sxp
 from xen.xend import XendDomain
@@ -116,6 +118,24 @@
             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()
+            threading.Thread(target=connection.SSLSocketServerConnection.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()
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-12 16:43:52.000000000 +0800
+++ xen-unstable/tools/python/xen/xend/XendDomain.py	2008-05-13 11:18:34.000000000 +0800
@@ -1293,25 +1293,56 @@
         if port == 0:
             port = xoptions.get_xend_relocation_port()
 
-        try:
-            tls = xoptions.get_xend_relocation_tls()
-            if tls:
-                from OpenSSL import SSL
+        tls = xoptions.get_xend_relocation_tls()
+        if tls:
+            from OpenSSL import SSL
+            from xen.web import connection
+            try:
                 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()
-            else:
+                sock.connect((dst, port))
+                sock.send("sslreceive\n")
+                sock.recv(80)
+            except SSL.Error, err:
+                raise XendError("SSL error: %s" % err)
+            except socket.error, err:
+                raise XendError("can't connect: %s" % err)
+
+            p2cread, p2cwrite = os.pipe()
+            threading.Thread(target=connection.SSLSocketServerConnection.fd2send,
+                             args=(sock, p2cread)).start()
+
+            try:
+                XendCheckpoint.save(p2cwrite, dominfo, True, live, dst,
+                                    node=node)
+            finally:
+                sock.shutdown()
+                sock.close()
+
+            os.close(p2cread)
+            os.close(p2cwrite)
+        else:
+            try:
                 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            sock.connect((dst, port))
-        except socket.error, err:
-            raise XendError("can't connect: %s" % err[1])
-
-        sock.send("receive\n")
-        sock.recv(80)
-        try:
-            XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst, node=node)
-        finally:
-            sock.close()
+                # When connecting to 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)
+            except socket.error, err:
+                raise XendError("can't connect: %s" % err)
+
+            try:
+                XendCheckpoint.save(sock.fileno(), dominfo, True, live,
+                                    dst, node=node)
+            finally:
+                sock.close()
 
     def domain_save(self, domid, dst, checkpoint=False):
         """Start saving a domain to file.

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

      reply	other threads:[~2008-05-13  8:16 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-28  2:49 [PATCH] add ssl/tls support to relocation Zhigang Wang
2008-05-02 17:47 ` Carb, Brian A
2008-05-02 18:11   ` Zhigang Wang
2008-05-05 15:43     ` Carb, Brian A
2008-05-08 12:55       ` Zhigang Wang
2008-05-08 13:29         ` Keir Fraser
2008-05-13  7:56           ` Zhigang Wang
2008-05-13  8:16             ` Zhigang Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48294E70.40808@oracle.com \
    --to=zhigang.x.wang@oracle.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.