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
luk3yx 2018-10-20 07:48:22 +13:00
parent 266b98356b
commit 5d7f3ed88e
2 changed files with 28 additions and 11 deletions

View File

@ -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`. |

34
miniirc.py Executable file → Normal file
View File

@ -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: