[IronPython] ssl server mode issue

Dino Viehland dinov at microsoft.com
Mon Apr 26 22:02:34 CEST 2010


That’s working for me as well.  I went ahead and added a do_GET implementation to the ProxyHandler class:

    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        stdout = sys.stdout
        self.wfile.write('<html><body>hi' + str(datetime.datetime.now()) + '</body></html>')

I generated the key by doing:

C:\OpenSSL\bin\openssl.exe req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem

And I’m able to successfully able to make requests to both CPython and IronPython from IE and FireFox.

So I guess the next possible questions would be what version of Windows you’re running on and did you create the certificate on Windows (maybe there’s some difference in OpenSSL between the two platforms?)   Also are you using the .NET 2 version or the .NET 4 version?  Also does my end-to-end repro demonstrate the problem for you or are you doing something different?


From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of qiuyingbo at sohu.com
Sent: Thursday, April 22, 2010 5:40 PM
To: Discussion of IronPython
Subject: Re: [IronPython] ssl server mode issue

I generated certificate as the instruction of http://docs.python.org/library/ssl.html:

openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem



----- 原文 -----

发件人: Dino Viehland
主 题: Re: [IronPython] ssl server mode issue
时 间: 2010年4月23日 6:46:11

Ok, took me a while to get back to this, but I haven’t forgotten.  So I’ve taken your code below and combined it with the code in test_ssl to have the full end to end test case.  I’ve included that here.  Let me know if there’s anything that’s significantly different.



First thing I tried w/ this was using the ‘keycert.pem’ which copes with the CPython test case and that seemed to behave similarly between IronPython and CPython.  There does seem to be one difference which is with CPython the connection from the browser stays open and w/ IronPython it closes.  This is after a GET request which we can’t respond to:



DINOV1.redmond.corp.microsoft.com - - [22/Apr/2010 15:38:16] code 501, message Unsupported method ('GET')

DINOV1.redmond.corp.microsoft.com - - [22/Apr/2010 15:38:16] "GET / HTTP/1.1" 501 –



That’s probably a bug but not the issue you’re running into but I’ve opened a bug here: http://ironpython.codeplex.com/WorkItem/View.aspx?WorkItemId=26852.



So then I generated a self-signed request as described here: http://sial.org/howto/openssl/self-signed/ with a .cnf file as described here: http://bugs.gentoo.org/show_bug.cgi?id=251047 but minus the x509_extensions line.  With that I get the same result as I get with keycert.pem.



So my guess is that I’m not generating the self signed certificate in the same way that you are and that there’s something about your cert which doesn’t work.  Does your generation differ from what I did?



import BaseHTTPServer

from BaseHTTPServer import HTTPServer

from SimpleHTTPServer import SimpleHTTPRequestHandler

import threading

import socket

import sys

import traceback

import ssl

CERTFILE = 'host.pem'

HOST='localhost'

import time



class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_CONNECT(self):

        print self.raw_requestline

        # "CONNECT twitter.com:443 HTTP/1.1"

        self.sslhost = self.raw_requestline.split()[1]

        self.wfile.write(self.protocol_version + " 200 Connection established\r\n")

        self.wfile.write("Proxy-agent: qiuyingbo\r\n\r\n")

        self.rfile = pseudofile(ssl.wrap_socket(self.connection, None, CERTFILE, True))

        self.wfile = self.rfile

        self.handle_one_request()





class SocketServerHTTPSServer(threading.Thread):

    class HTTPSServer(HTTPServer):

        def __init__(self, server_address, RequestHandlerClass, certfile):

            HTTPServer.__init__(self, server_address, RequestHandlerClass)

            # we assume the certfile contains both private key and certificate

            self.certfile = certfile

            self.active = False

            self.active_lock = threading.Lock()

            self.allow_reuse_address = True



        def __str__(self):

            return ('<%s %s:%s>' %

                    (self.__class__.__name__,

                     self.server_name,

                     self.server_port))



        def get_request (self):

            # override this to wrap socket with SSL

            sock, addr = self.socket.accept()

            sslconn = ssl.wrap_socket(sock, server_side=True,

                                      certfile=self.certfile)

            return sslconn, addr



        # The methods overridden below this are mainly so that we

        # can run it in a thread and be able to stop it from another

        # You probably wouldn't need them in other uses.



        def server_activate(self):

            # We want to run this in a thread for testing purposes,

            # so we override this to set timeout, so that we get

            # a chance to stop the server

            self.socket.settimeout(0.5)

            HTTPServer.server_activate(self)



        def serve_forever(self):

            # We want this to run in a thread, so we use a slightly

            # modified version of "forever".

            self.active = True

            while 1:

                try:

                    # We need to lock while handling the request.

                    # Another thread can close the socket after self.active

                    # has been checked and before the request is handled.

                    # This causes an exception when using the closed socket.

                    with self.active_lock:

                        if not self.active:

                            break

                        self.handle_request()

                except socket.timeout:

                    pass

                except KeyboardInterrupt:

                    self.server_close()

                    return

                except:

                    sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))

                    break

                time.sleep(0.1)



        def server_close(self):

            # Again, we want this to run in a thread, so we need to override

            # close to clear the "active" flag, so that serve_forever() will

            # terminate.

            with self.active_lock:

                HTTPServer.server_close(self)

                self.active = False



    def __init__(self, certfile):

        self.flag = None

        self.active = False

        self.port = 1234

        self.server = self.HTTPSServer(

            (HOST, self.port), ProxyHandler, certfile)

        threading.Thread.__init__(self)

        self.daemon = True



    def __str__(self):

        return "<%s %s>" % (self.__class__.__name__, self.server)



    def start (self, flag=None):

        self.flag = flag

        threading.Thread.start(self)



    def run (self):

        self.active = True

        if self.flag:

            self.flag.set()

        self.server.serve_forever()

        self.active = False



    def stop (self):

        self.active = False

        self.server.server_close()





class pseudofile():

    ''' SSL Pseudo File Object'''

    def __init__(self, sslobj):

        self.sslobj = sslobj

        self.closed = 0



    def read(self, size):

        chunks = []

        read = 0

        while read < size:

            data = self.sslobj.read(size-read)

            read += len(data)

            chunks.append(data)

        return ''.join(chunks)



    def readline(self):

        line = []

        while 1:

            char = self.sslobj.read(1)

            line.append(char)

            if char == "\n": return ''.join(line)



    def write(self, data):

        bytes = len(data)

        while bytes > 0:

            sent = self.sslobj.write(data)

            if sent == bytes:

                break    # avoid copy

            data = data[sent:]

            bytes = bytes - sent



    def flush(self):

        pass

    close = flush





server=SocketServerHTTPSServer(CERTFILE)

flag = threading.Event()

server.start(flag)

# wait for it to start

flag.wait()

print 'started'

time.sleep(100000)





From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of qiuyingbo at sohu.com
Sent: Wednesday, April 14, 2010 5:41 PM
To: Discussion of IronPython
Subject: Re: [IronPython] ssl server mode issue



I'm doing a web browser to ironpython connection. It is difficult to explain what I am doing,  I'm hacking a http proxy that inherit BaseHTTPServer.BaseHTTPRequestHandler. Next code snippets show how I support HTTPS proxy.. (Linux version run well)



class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_CONNECT(self):
        # print self.raw_requestline
        # "CONNECT twitter.com:443 HTTP/1.1"
        self.sslhost = self.raw_requestline.split()[1]
        self.wfile.write(self.protocol_version + " 200 Connection established\r\n")
        self.wfile.write("Proxy-agent: qiuyingbo\r\n\r\n")
        import ssl
        self.rfile = pseudofile(ssl.wrap_socket(self.connection, None, CERTFILE, True))
        self.wfile = self.rfile
        self.handle_one_request()



class pseudofile():
    ''' SSL Pseudo File Object'''
    def __init__(self, sslobj):
        self.sslobj = sslobj
        self.closed = 0



    def read(self, size):
        chunks = []
        read = 0
        while read < size:
            data = self.sslobj.read(size-read)
            read += len(data)
            chunks.append(data)
        return ''.join(chunks)



    def readline(self):
        line = []
        while 1:
            char = self.sslobj.read(1)
            line.append(char)
            if char == "\n": return ''.join(line)



    def write(self, data):
        bytes = len(data)
        while bytes > 0:
            sent = self.sslobj.write(data)
            if sent == bytes:
                break    # avoid copy
            data = data[sent:]
            bytes = bytes - sent

    def flush(self):
        pass

    close = flush

_______________________________________________
Users mailing list
Users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20100426/e2d5f970/attachment.html>


More information about the Ironpython-users mailing list