Ticket #1136: web-ssl.patch
File web-ssl.patch, 10.9 KB (added by , 5 years ago) |
---|
-
xpra/net/websocket.py
30 30 server = AdHocStruct() 31 31 server.logger = log 32 32 server.run_once = True 33 server.verbose = os.environ.get("XPRA_WEBSOCKIFY_DEBUG", "0")=="1" 33 34 WebSocketRequestHandler.__init__(self, sock, addr, server) 34 35 35 36 def new_websocket_client(self): -
xpra/scripts/config.py
340 340 "speaker" : str, 341 341 "sound-source" : str, 342 342 "html" : str, 343 "ssl-cert" : str, 344 "ssl-key" : str, 343 345 "socket-permissions": str, 344 346 "exec-wrapper" : str, 345 347 "dbus-launch" : str, … … 523 525 "input-method" : "none", 524 526 "sound-source" : "", 525 527 "html" : "auto", 528 "ssl-cert" : "", 529 "ssl-key" : "", 526 530 "socket-permissions": "600", 527 531 "exec-wrapper" : "", 528 532 "dbus-launch" : "dbus-launch --close-stderr", -
xpra/scripts/main.py
310 310 dest="html", default=defaults.html, 311 311 metavar="on|off|[HOST:]PORT", 312 312 help="Enable the web server and the html5 client. Default: '%default'.") 313 group.add_option("--ssl-cert", action="store", 314 dest="ssl_cert", default=defaults.ssl_cert, 315 metavar="/path/to/cert.pem", 316 help="Certificate file to use for SSL traffic. Default: '%default'.") 317 group.add_option("--ssl-key", action="store", 318 dest="ssl_key", default=defaults.ssl_key, 319 metavar="/path/to/key.pem", 320 help="Key file to use for SSL traffic. Default: '%default'.") 313 321 else: 314 ignore({"tcp_proxy" : "", 315 "html" : ""}) 322 ignore({ 323 "tcp_proxy" : "", 324 "html" : "", 325 "ssl-cert" : "", 326 "ssl-key" : "", 327 }) 316 328 legacy_bool_parse("daemon") 317 329 if (supports_server or supports_shadow) and CAN_DAEMONIZE: 318 330 group.add_option("--daemon", action="store", metavar="yes|no", -
xpra/server/gtk_server_base.py
66 66 log("do_run() end of gtk.main()") 67 67 68 68 def add_listen_socket(self, socktype, sock): 69 sock.listen( 5)69 sock.listen(100) 70 70 glib.io_add_watch(sock, glib.IO_IN, self._new_connection, sock) 71 71 self.socket_types[sock] = socktype 72 72 -
xpra/server/server_core.py
149 149 self._tcp_proxy = "" 150 150 self._html = False 151 151 self._www_dir = None 152 self._ssl_cert = None 153 self._ssl_key = None 152 154 self._aliases = {} 153 155 self._reverse_aliases = {} 154 156 self.socket_types = {} … … 206 208 self.init_auth(opts) 207 209 208 210 def init_html_proxy(self, opts): 211 self._ssl_cert = opts.ssl_cert 212 self._ssl_key = opts.ssl_key or self._ssl_cert 213 209 214 self._tcp_proxy = opts.tcp_proxy 210 215 #opts.html can contain a boolean, "auto" or the path to the webroot 211 216 www_dir = None … … 509 514 netlog.error("too many connections (%s), ignoring new one", len(self._potential_protocols)) 510 515 sock.close() 511 516 return True 517 518 def threaded_accept(): 519 self.accept_socket(socktype, sock, address) 520 make_thread(threaded_accept, "%s-%s" % (socktype, address), daemon=True).start() 521 return True 522 523 def accept_socket(self, socktype, sock, address): 512 524 try: 513 525 peername = sock.getpeername() 514 526 except: … … 516 528 sockname = sock.getsockname() 517 529 target = peername or sockname 518 530 sock.settimeout(self._socket_timeout) 519 netlog(" new_connection(%s) sock=%s, timeout=%s, sockname=%s, address=%s, peername=%s", args, sock, self._socket_timeout, sockname, address, peername)531 netlog("accept_socket(%s) timeout=%s, sockname=%s, peername=%s", (socktype, sock, address), self._socket_timeout, sockname, peername) 520 532 conn = SocketConnection(sock, sockname, address, target, socktype) 521 533 netlog("socket connection: %s", conn) 522 534 if peername: … … 532 544 if socktype=="tcp" and self._html or self._tcp_proxy: 533 545 #see if the packet data is actually xpra or something else 534 546 #that we need to handle via a tcp proxy or the websockify adapter: 535 conn._socket.settimeout(25) 547 sock.settimeout(5) 548 #sock.setblocking(True) 536 549 v = conn.peek(128) 537 netlog("peek()=%s", nonl(v))550 netlog("peek()=%s", repr_ellipsized(v)) 538 551 if v and v[0] not in ("P", ord("P")): 552 netlog("peek() first character=%s / %s", nonl(v[0]), hex(ord(v[0]))) 553 #SSL? 554 ssl_sock = None 555 if v[0] in ("\x16", "\x80", 22, 128): 556 netlog("peek() SSL traffic, trying cert=%s, key=%s", self._ssl_cert, self._ssl_key) 557 if self._ssl_cert and self._ssl_key: 558 try: 559 import ssl 560 ssl_sock = ssl.wrap_socket(sock, server_side=True, certfile=self._ssl_cert, keyfile=self._ssl_key) 561 netlog("wrapped socket %s using SSL: %s", sock, ssl_sock) 562 conn._socket = ssl_sock 563 ssl_sock.settimeout(5) 564 ssl_sock.do_handshake(False) 565 v = conn.peek(128) 566 netlog("handshake complete, ssl peek: %s", repr_ellipsized(v)) 567 except Exception as e: 568 netlog.error("Error: cannot wrap SSL socket:") 569 netlog.error(" %s", e) 570 return 571 else: 572 log.warn("Warning: no SSL certificate configured, cannot parse this request") 573 539 574 if self._html: 540 line1 = v.splitlines()[0] 541 if line1.find("HTTP/")>0: 575 line1 = "" 576 if v: 577 line1 = v.splitlines()[0] 578 if line1.find("HTTP/")>0 or ssl_sock: 542 579 if line1.startswith("GET ") or line1.startswith("POST "): 543 580 parts = line1.split(" ") 544 netlog.info("New http %s request received from %s for '%s'", parts[0], frominfo, parts[1]) 545 tname = "%s-request" % parts[0] 581 netlog.info("New %s %s request received from %s for '%s'", ["http", "https"][ssl_sock is not None], parts[0], frominfo, parts[1]) 546 582 else: 547 netlog.info("New http connection received from %s", frominfo) 548 tname = "websockify-proxy" 549 def run_websockify(): 550 self.start_websockify(conn, frominfo) 551 make_thread(run_websockify, "%s-for-%s" % (tname, frominfo), daemon=True).start() 552 return True 583 netlog.info("New %s connection received from %s", ["http", "https"][ssl_sock is not None], frominfo) 584 self.start_websockify(conn, frominfo) 585 return 553 586 elif self._tcp_proxy: 554 587 netlog.info("New tcp proxy connection received from %s", frominfo) 555 588 def run_proxy(): 556 589 self.start_tcp_proxy(conn, frominfo) 557 590 make_thread(run_proxy, "tcp-proxy-for-%s" % frominfo, daemon=True).start() 558 return True591 return 559 592 else: 560 593 v = conn.peek(128) 561 594 netlog("%s.peek(128)=%s", conn, v) … … 570 603 conn.close() 571 604 except Exception as e: 572 605 netlog("error sending '%s': %s", nonl(msg), e) 573 return True606 return 574 607 netlog.info(info_msg) 575 returnself.make_protocol(socktype, conn, frominfo)608 self.make_protocol(socktype, conn, frominfo) 576 609 577 610 def make_protocol(self, socktype, conn, frominfo=""): 578 611 protocol = Protocol(self, conn, self.process_packet) … … 601 634 protocol.set_cipher_in(protocol.encryption, DEFAULT_IV, password, DEFAULT_SALT, DEFAULT_ITERATIONS, INITIAL_PADDING) 602 635 protocol.start() 603 636 self.timeout_add(SOCKET_TIMEOUT*1000, self.verify_connection_accepted, protocol) 604 return True605 637 606 638 def invalid_header(self, proto, data): 607 639 netlog("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s, html=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, self._html) … … 617 649 netlog("new_websocket_client(%s)", wsh) 618 650 wsc = WebSocketConnection(conn._socket, conn.local, conn.remote, conn.target, conn.info, wsh) 619 651 self.make_protocol("tcp", wsc, frominfo) 620 WSRequestHandler(conn._socket, frominfo, new_websocket_client, self._www_dir)621 return652 wsrh = WSRequestHandler(conn._socket, frominfo, new_websocket_client, self._www_dir) 653 netlog("WSRequestHandler=%s", wsrh) 622 654 except IOError as e: 623 655 netlog.error("Error: http failure responding to %s:", frominfo) 624 656 netlog.error(" %s", e) … … 626 658 except Exception as e: 627 659 netlog.error("Error: http failure responding to %s:", frominfo, exc_info=True) 628 660 try: 661 try: 662 conn._socket.shutdown(socket.SHUT_RDWR) 663 except Exception as ce: 664 netlog("error closing connection following error: %s", ce) 629 665 conn.close() 630 666 except Exception as ce: 631 667 netlog("error closing connection following error: %s", ce)