Fix SSL certificate verification
• Bump version number to 0.2. • Force-verify SSL certificates (at least on Linux). • Make miniirc more RFC-complaint. · Add '\r\n' to the end of messages instead of '\n'. · Cut messages off if they are longer than 512 bytes.master
parent
266b98356b
commit
5d7f3ed88e
|
@ -9,7 +9,7 @@ A simple IRC client framework.
|
|||
## Parameters
|
||||
|
||||
~~~py
|
||||
irc = miniirc.IRC(ip, port, nick, channels = None, *, ssl = None, ident = None, realname = None, persist = False, debug = False, ns_identity = None, auto_connect = True, ircv3_caps = set())
|
||||
irc = miniirc.IRC(ip, port, nick, channels = None, *, ssl = None, ident = None, realname = None, persist = False, debug = False, ns_identity = None, auto_connect = True, ircv3_caps = set(), verify_ssl = True)
|
||||
~~~
|
||||
|
||||
| Parameter | Description |
|
||||
|
@ -26,6 +26,7 @@ irc = miniirc.IRC(ip, port, nick, channels = None, *, ssl = None, ident = None,
|
|||
| `ns_identity` | The NickServ account to use (`<user> <password>`). |
|
||||
| `auto_connect`| Runs `.connect()` straight away. |
|
||||
| `ircv3_caps` | A set() of IRCv3 capabilities to request. SASL is auto-added if `ns_identity` is specified. |
|
||||
| `verify_ssl` | Verifies SSL certificates. Disabling this is not recommended. |
|
||||
|
||||
## Functions
|
||||
|
||||
|
@ -34,7 +35,7 @@ irc = miniirc.IRC(ip, port, nick, channels = None, *, ssl = None, ident = None,
|
|||
| `connect()` | Connects to the IRC server if not already connected. |
|
||||
| `ctcp(target, *msg, reply=False)` | Sends a `CTCP` request or reply to `target`. |
|
||||
| `debug(...)` | Debug, calls `print(...)` if debug mode is on. |
|
||||
| `disconnect()`| Disconnects from the IRC server. |
|
||||
| `disconnect(msg = ..., *, auto_reconnect = False)`| Disconnects from the IRC server. `auto_reconnect` will be overriden by `self.persist` if set to `True`. |
|
||||
| `Hander(...)` | An event handler, see [Handlers](#handlers) for more info.|
|
||||
| `main()` | Starts the main loop in a thread if not already running. |
|
||||
| `me(target, *msg)` | Sends a `/me` (`CTCP ACTION`) to `target`. |
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
import atexit, copy, threading, socket, ssl, sys
|
||||
from time import sleep
|
||||
__all__ = ['Handler', 'IRC']
|
||||
version = 'miniirc IRC framework v0.1'
|
||||
version = 'miniirc IRC framework v0.2'
|
||||
|
||||
# Get the certificate list.
|
||||
try:
|
||||
from certifi import where as get_ca_certs
|
||||
except ImportError:
|
||||
get_ca_certs = lambda : None
|
||||
|
||||
# Create global handlers
|
||||
_global_handlers = {}
|
||||
|
@ -47,7 +53,7 @@ class IRC:
|
|||
self.sendq = None
|
||||
for i in sendq:
|
||||
self.quote(*i)
|
||||
msg = '{}\n'.format(' '.join(msg)).encode('utf-8')
|
||||
msg = '{}\r\n'.format(' '.join(msg)).encode('utf-8')[:512]
|
||||
self.sock.send(msg)
|
||||
else:
|
||||
self.debug('>Q>', *msg)
|
||||
|
@ -84,8 +90,15 @@ class IRC:
|
|||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
if self.ssl:
|
||||
self.debug('SSL handshake')
|
||||
self.sock = ssl.wrap_socket(self.sock)
|
||||
if self.verify_ssl:
|
||||
self.sock = ssl.wrap_socket(self.sock,
|
||||
cert_reqs=ssl.CERT_REQUIRED, ca_certs = get_ca_certs(),
|
||||
do_handshake_on_connect = True)
|
||||
else:
|
||||
self.sock = ssl.wrap_socket(self.sock,
|
||||
do_handshake_on_connect = True)
|
||||
self.sock.connect((self.ip, self.port))
|
||||
self.verify_ssl and ssl.match_hostname(self.sock.getpeercert(), self.ip)
|
||||
# Iterate over the caps list to make it easier to pick up ACKs and NAKs.
|
||||
for cap in self.ircv3_caps:
|
||||
self.debug('Requesting IRCv3 capability', cap)
|
||||
|
@ -98,8 +111,9 @@ class IRC:
|
|||
self.main()
|
||||
|
||||
# An easier way to disconnect
|
||||
def disconnect(self, msg = 'I grew sick and died.'):
|
||||
self.persist = False
|
||||
def disconnect(self, msg = 'I grew sick and died.', *,
|
||||
auto_reconnect = False):
|
||||
self.persist = auto_reconnect and self.persist
|
||||
self.connected = False
|
||||
atexit.unregister(self.disconnect)
|
||||
try:
|
||||
|
@ -120,10 +134,10 @@ class IRC:
|
|||
raw += self.sock.recv(4096)
|
||||
if c > 100:
|
||||
self.debug('Waited 100 times on the socket!')
|
||||
raise NotImplementedError('Spam detected')
|
||||
raise Exception('Spam detected')
|
||||
except Exception as e:
|
||||
self.debug('Lost connection! ', repr(e))
|
||||
self.disconnect()
|
||||
self.disconnect(auto_reconnect = True)
|
||||
if self.persist:
|
||||
sleep(5)
|
||||
self.debug('Reconnecting...')
|
||||
|
@ -190,11 +204,12 @@ class IRC:
|
|||
ssl = None, # None: Auto
|
||||
ident = None,
|
||||
realname = None,
|
||||
persist = False,
|
||||
persist = True,
|
||||
debug = False,
|
||||
ns_identity = None,
|
||||
auto_connect = True,
|
||||
ircv3_caps = set()
|
||||
ircv3_caps = set(),
|
||||
verify_ssl = True,
|
||||
):
|
||||
# Set basic variables
|
||||
self.ip = ip
|
||||
|
@ -208,6 +223,7 @@ class IRC:
|
|||
self._debug = debug
|
||||
self.ns_identity = ns_identity
|
||||
self.ircv3_caps = set(ircv3_caps or [])
|
||||
self.verify_ssl = verify_ssl
|
||||
|
||||
# Add SASL
|
||||
if self.ns_identity:
|
||||
|
|
Loading…
Reference in New Issue