コード例 #1
0
    def _init_server(self, peer_address):
        if self._sock.type != socket.SOCK_DGRAM:
            raise InvalidSocketError("sock must be of type SOCK_DGRAM")

        self._wbio = _BIO(BIO_new_dgram(self._sock.fileno(), BIO_NOCLOSE))
        if peer_address:
            # Connect directly to this client peer, bypassing the demux
            rsock = self._sock
            BIO_dgram_set_connected(self._wbio.value, peer_address)
        else:
            from demux import UDPDemux
            self._udp_demux = UDPDemux(self._sock)
            rsock = self._udp_demux.get_connection(None)
        if rsock is self._sock:
            self._rbio = self._wbio
        else:
            self._rsock = rsock
            self._rbio = _BIO(BIO_new_dgram(self._rsock.fileno(), BIO_NOCLOSE))
        server_method = DTLS_server_method
        if self._ssl_version == PROTOCOL_DTLSv1_2:
            server_method = DTLSv1_2_server_method
        elif self._ssl_version == PROTOCOL_DTLSv1:
            server_method = DTLSv1_server_method
        self._ctx = _CTX(SSL_CTX_new(server_method()))
        self._intf_ssl_ctx = SSLContext(self._ctx.value)
        SSL_CTX_set_session_cache_mode(self._ctx.value, SSL_SESS_CACHE_OFF)
        if self._cert_reqs == CERT_NONE:
            verify_mode = SSL_VERIFY_NONE
        elif self._cert_reqs == CERT_OPTIONAL:
            verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE
        else:
            verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | \
              SSL_VERIFY_FAIL_IF_NO_PEER_CERT
        self._config_ssl_ctx(verify_mode)
        if not peer_address:
            # Configure UDP listening socket
            self._listening = False
            self._listening_peer_address = None
            self._pending_peer_address = None
            self._cb_keepalive = SSL_CTX_set_cookie_cb(
                self._ctx.value,
                _CallbackProxy(self._generate_cookie_cb),
                _CallbackProxy(self._verify_cookie_cb))
        self._ssl = _SSL(SSL_new(self._ctx.value))
        self._intf_ssl = SSL(self._ssl.value)
        SSL_set_accept_state(self._ssl.value)
        if peer_address and self._do_handshake_on_connect:
            return lambda: self.do_handshake()
コード例 #2
0
    def _init_client(self, peer_address):
        if self._sock.type != socket.SOCK_DGRAM:
            raise InvalidSocketError("sock must be of type SOCK_DGRAM")

        self._wbio = _BIO(BIO_new_dgram(self._sock.fileno(), BIO_NOCLOSE))
        self._rbio = self._wbio
        self._ctx = _CTX(SSL_CTX_new(DTLSv1_client_method()))
        if self._cert_reqs == CERT_NONE:
            verify_mode = SSL_VERIFY_NONE
        else:
            verify_mode = SSL_VERIFY_PEER
        self._config_ssl_ctx(verify_mode)
        self._ssl = _SSL(SSL_new(self._ctx.value))
        SSL_set_connect_state(self._ssl.value)
        if peer_address:
            return lambda: self.connect(peer_address)
コード例 #3
0
    def _init_client(self, peer_address):
        if self._sock.type != socket.SOCK_DGRAM:
            raise InvalidSocketError("sock must be of type SOCK_DGRAM")

        self._wbio = _BIO(BIO_new_dgram(self._sock.fileno(), BIO_NOCLOSE))
        self._rbio = self._wbio
        client_method = DTLSv1_2_client_method  # no "any" exists, therefore use v1_2 (highest possible)
        if self._ssl_version == PROTOCOL_DTLSv1_2:
            client_method = DTLSv1_2_client_method
        elif self._ssl_version == PROTOCOL_DTLSv1:
            client_method = DTLSv1_client_method
        self._ctx = _CTX(SSL_CTX_new(client_method()))
        self._intf_ssl_ctx = SSLContext(self._ctx.value)
        if self._cert_reqs == CERT_NONE:
            verify_mode = SSL_VERIFY_NONE
        else:
            verify_mode = SSL_VERIFY_PEER
        self._config_ssl_ctx(verify_mode)
        self._ssl = _SSL(SSL_new(self._ctx.value))
        self._intf_ssl = SSL(self._ssl.value)
        SSL_set_connect_state(self._ssl.value)
        if peer_address:
            return lambda: self.connect(peer_address)
コード例 #4
0
    def listen(self):
        """Server-side cookie exchange

        This method reads datagrams from the socket and initiates cookie
        exchange, upon whose successful conclusion one can then proceed to
        the accept method. Alternatively, accept can be called directly, in
        which case it will call this method. In order to prevent denial-of-
        service attacks, only a small, constant set of computing resources
        are used during the listen phase.

        On some platforms, listen must be called so that packets will be
        forwarded to accepted connections. Doing so is therefore recommened
        in all cases for portable code.

        Return value: a peer address if a datagram from a new peer was
        encountered, None if a datagram for a known peer was forwarded
        """

        if not hasattr(self, "_listening"):
            raise InvalidSocketError("listen called on non-listening socket")

        self._pending_peer_address = None
        try:
            peer_address = self._udp_demux.service()
        except socket.timeout:
            peer_address = None
        except socket.error as sock_err:
            if sock_err.errno != errno.EWOULDBLOCK:
                _logger.exception("Unexpected socket error in listen")
                raise
            peer_address = None

        if not peer_address:
            _logger.debug("Listen returning without peer")
            return

        # The demux advises that a datagram from a new peer may have arrived
        if type(peer_address) is tuple:
            # For this type of demux, the write BIO must be pointed at the peer
            BIO_dgram_set_peer(self._wbio.value, peer_address)
            self._udp_demux.forward()
            self._listening_peer_address = peer_address

        self._check_nbio()
        self._listening = True
        try:
            _logger.debug("Invoking DTLSv1_listen for ssl: %d", self._ssl.raw)
            dtls_peer_address = DTLSv1_listen(self._ssl.value)
        except openssl_error() as err:
            if err.ssl_error == SSL_ERROR_WANT_READ:
                # This method must be called again to forward the next datagram
                _logger.debug("DTLSv1_listen must be resumed")
                return
            elif err.errqueue and err.errqueue[0][
                    0] == ERR_WRONG_VERSION_NUMBER:
                _logger.debug("Wrong version number; aborting handshake")
                raise
            elif err.errqueue and err.errqueue[0][0] == ERR_COOKIE_MISMATCH:
                _logger.debug(
                    "Mismatching cookie received; aborting handshake")
                raise
            elif err.errqueue and err.errqueue[0][0] == ERR_NO_SHARED_CIPHER:
                _logger.debug("No shared cipher; aborting handshake")
                raise
            _logger.exception("Unexpected error in DTLSv1_listen")
            raise
        finally:
            self._listening = False
            self._listening_peer_address = None
        if type(peer_address) is tuple:
            _logger.debug("New local peer: %s", dtls_peer_address)
            self._pending_peer_address = peer_address
        else:
            self._pending_peer_address = dtls_peer_address
        _logger.debug("New peer: %s", self._pending_peer_address)
        return self._pending_peer_address