def starttls (self): """Modify the current socket to make it a TLS socket. Use the tlsdata as currently setup (see class-level documentation). Afterwards, call handle_secure() to start from scratch with a secure connection. Also see the man page on the underlying C library call, tlspool_starttls(3). Some protocols start TLS immediately, for instance HTTPS; for such protocols, the handle() method would immediately call starttls() and the actual handler code would move into secure_handle(). Other protocols, such as XMPP and IMAP, start in plaintext and exchange pleasantries until they agree on running TLS. This is the point where starttls() can be invoked. The methods startssh() and startgss() are place holders for future alternatives to start other security wrappers than TLS, after negotiating them in a manner similar to STARTTLS. """ if type (self.request) == tuple: sox = self.request [1] else: sox = self.request assert (type (sox) == socket._socketobject) try: af = sox.family except: af = socket.AF_INET try: if sox.proto in [socket.IPPROTO_UDP]: socktp = socket.SOCK_DGRAM elif sox.proto in [socket.IPPROTO_SCTP]: socktp = socket.SOCK_SEQPACKET else: socktp = socket.SOCK_STREAM except: socktp = socket.SOCK_STREAM plainsockptr = socket_data () plainsockptr.unix_socket = -1 unix_sox = os.dup (sox.fileno ()) if unix_sox < 0: _tlspool.raise_errno () sox.close () rv = _starttls (unix_sox, self.tlsdata, plainsockptr, None) if rv < 0: _tlspool.raise_errno () assert (plainsockptr.unix_socket >= 0) sox2 = socket.fromfd (plainsockptr.unix_socket, af, socktp) # Now, since socket.fromfd() used os.dup(), we close the original os.close (plainsockptr.unix_socket) plainsockptr.unix_socket = -1 if type (self.request) == tuple: #TODO# This is not permitted, editing a tuple self.request [1] = sox2 else: self.request = sox2 self.handle_secure ()
def starttls (self): """Initiate a TLS connection with the current settings, as provided during instantiation or through getter/setter access afterwards. The variables that are required at this point are service and, already obliged when making a new instance, cryptfd. Quoting the library documentation on file handles and who should close them: The cryptfd handle supplies the TLS connection that is assumed to have been setup. When the function ends, either in success or failure, this handle will no longer be available to the caller; the responsibility of closing it is passed on to the function and/or the TLS Pool. And on plainfd: The file handle returned [in privdata], if it is >= 0, should be closed by the caller, both in case of success and failure. """ assert (self.cryptsk is not None) assert (self.cryptfd >= 0) assert (self.tlsdata.service != '') try: af = self.cryptsk.family except: af = socket.AF_INET try: if self.cryptsk.proto in [socket.IPPROTO_UDP]: socktp = socket.SOCK_DGRAM elif self.cryptsk.proto in [socket.IPPROTO_SCTP]: socktp = socket.SOCK_SEQPACKET else: socktp = socket.SOCK_STREAM except: socktp = socket.SOCK_STREAM plainsockptr = socket_data () plainsockptr.unix_socket = self.plainfd # Clone cryptfd so _starttls() and Python can each close it unix_cryptfd = os.dup (self.cryptfd) if unix_cryptfd < 0: _tlspool.raise_errno () # We close cryptsk now and it will not repeat during garbage collection self.cryptsk.close () self.cryptsk = None self.cryptfd = -1 # Provide None for the callback function, SWIG won't support it # We might at some point desire a library of C routine options? rv = _starttls (unix_cryptfd, self.tlsdata, plainsockptr, None) self.plainfd = -1 if rv < 0: _tlspool.raise_errno () if self.plainsk is None: self.plainfd = plainsockptr.unix_socket self.plainsk = socket.fromfd (self.plainfd, af, socktp) return self.plainsk
def pid (pidfile=None): """This function returns the process identity of the TLS Pool. When no pidfile is provided, the default path as configured in the TLS Pool libary will be used. An Exception is thrown when there is no TLS Pool. """ process_id = _pid (pidfile) if process_id < 0: _tlspool.raise_errno () else: return process_id
def open_poolhandle (path=None): """This function returns the OS-specific socket handle value for the TLS Pool. It is already connected, and shared with the internal management of this module, so it must not be closed by the caller. When no path is provided, the default path is used instead. This function blocks until a connection to the TLS Pool succeeds. The path is only used in the first call, and only when no prior contact to the TLS Pool has been made; if that has happened, then this function returns the previously found socket handle. """ fd = _open_poolhandle (path) if fd < 0: _tlspool.raise_errno () else: return fd
def ping (YYYYMMDD_producer=_tlspool.TLSPOOL_IDENTITY_V2, facilities=_tlspool.PIOF_FACILITY_ALL_CURRENT): """This function takes in a string with a date in YYYYMMDD format, followed by a user@domain producer identifier. It takes in an integer value that is the logical or of PIOF_FACILITY_xxx values. This is sent to the TLS Pool through tlspool_ping() and the response is returned as a similar tuple (YYYYMMDD_producer, facilities) as returned by the TLS Pool. This function blocks until a connection to the TLS Pool has been found. It is a good first command to send to the TLS Pool. """ pp = ping_data () pp.YYYYMMDD_producer = YYYYMMDD_producer pp.facilities = facilities if _ping (pp) < 0: _tlspool.raise_errno () else: return (pp.YYYYMMDD_producer, pp.facilities)
def prng (self, length, label, ctxvalue=None): """Produce length bytes of randomness from the master key, after mixing it with the label and optional context value in ctxvalue. The procedure has been described in RFC 5705. #TODO# Find a way to return the random bytes, and use the length """ assert (length > 0) assert (1 <= len (label) <= 254) assert (1 <= len (ctxvalue or 'X') <= 254) buf = prng_data () # buf.in1_len = len (label) # buf.in2_len = len (ctxvalue) if ctxvalue is not None else 255 # buf.prng_len = length rv = _prng (label, ctxvalue, length, buf.buffer, self.tlsdata.ctlkey) if rv < 0: _tlspool.raise_errno () else: return buf.buffer [:length]
def starttls (self): """Initiate a TLS connection with the current settings, as provided during instantiation or through getter/setter access afterwards. The variables that are required at this point are service and, already obliged when making a new instance, cryptfd. """ assert (self.cryptsk is not None) assert (self.cryptfd >= 0) assert (self.tlsdata.service != '') try: af = self.cryptsk.family except: af = socket.AF_INET try: if self.cryptsk.proto in [socket.IPPROTO_UDP]: socktp = socket.SOCK_DGRAM elif self.cryptsk.proto in [socket.IPPROTO_SCTP]: socktp = socket.SOCK_SEQPACKET else: socktp = socket.SOCK_STREAM except: socktp = socket.SOCK_STREAM plainsockptr = socket_data () plainsockptr.unix_socket = self.plainfd # Provide None for the callback function, SWIG won't support it # We might at some point desire a library of C routine options? rv = _starttls (self.cryptfd, self.tlsdata, plainsockptr, None) self.plainfd = -1 self.cryptfd = -1 self.cryptsk = None if rv < 0: _tlspool.raise_errno () if self.plainsk is None: self.plainfd = plainsockptr.unix_socket self.plainsk = socket.fromfd (self.plainfd, af, socktp) return self.plainsk
def raise_errno(): return _tlspool.raise_errno()