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()
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)
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)
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