mirror of
				https://github.com/jlu5/PyLink.git
				synced 2025-11-04 00:47:21 +01:00 
			
		
		
		
	Irc: optionally validate SSL cert fingerprints (#80)
This commit is contained in:
		
							parent
							
								
									fe7adb716b
								
							
						
					
					
						commit
						d9f5cdfeaf
					
				@ -56,9 +56,14 @@ servers:
 | 
			
		||||
        # Toggles SSL for this network. Defaults to false if not specified, and requires the
 | 
			
		||||
        # ssl_certfile and ssl_keyfile options to work.
 | 
			
		||||
        # ssl: true
 | 
			
		||||
 | 
			
		||||
        # ssl_certfile: pylink-cert.pem
 | 
			
		||||
        # ssl_keyfile: pylink-key.pem
 | 
			
		||||
 | 
			
		||||
        # Optionally, you can set this option to verify the SSL certificate
 | 
			
		||||
        # fingerprint (SHA1) of your uplink.
 | 
			
		||||
        # ssl_fingerprint: "e0fee1adf795c84eec4735f039503eb18d9c35cc"
 | 
			
		||||
 | 
			
		||||
    ts6net:
 | 
			
		||||
        ip: 127.0.0.1
 | 
			
		||||
        port: 7000
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								main.py
									
									
									
									
									
								
							@ -8,6 +8,7 @@ import sys
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
import threading
 | 
			
		||||
import ssl
 | 
			
		||||
import hashlib
 | 
			
		||||
 | 
			
		||||
from log import log
 | 
			
		||||
import conf
 | 
			
		||||
@ -75,31 +76,62 @@ class Irc():
 | 
			
		||||
        port = self.serverdata["port"]
 | 
			
		||||
        while True:
 | 
			
		||||
            self.initVars()
 | 
			
		||||
            checks_ok = True
 | 
			
		||||
            try:
 | 
			
		||||
                self.socket = socket.socket()
 | 
			
		||||
                self.socket.setblocking(0)
 | 
			
		||||
                # Initial connection timeout is a lot smaller than the timeout after
 | 
			
		||||
                # we've connected; this is intentional.
 | 
			
		||||
                self.socket.settimeout(self.pingfreq)
 | 
			
		||||
 | 
			
		||||
                if self.serverdata.get('ssl'):
 | 
			
		||||
                self.ssl = self.serverdata.get('ssl')
 | 
			
		||||
                if self.ssl:
 | 
			
		||||
                    log.info('(%s) Attempting SSL for this connection...', self.name)
 | 
			
		||||
                    certfile = self.serverdata.get('ssl_certfile')
 | 
			
		||||
                    keyfile = self.serverdata.get('ssl_keyfile')
 | 
			
		||||
                    if certfile and keyfile:
 | 
			
		||||
                        self.socket = ssl.wrap_socket(self.socket, certfile=certfile, keyfile=keyfile)
 | 
			
		||||
                    else:
 | 
			
		||||
                        log.warning('(%s) SSL certfile/keyfile was not set correctly. '
 | 
			
		||||
                                    'SSL will be disabled for this connection.', self.name)
 | 
			
		||||
                        log.error('(%s) SSL certfile/keyfile was not set '
 | 
			
		||||
                                  'correctly, aborting... ', self.name)
 | 
			
		||||
                        checks_ok = False
 | 
			
		||||
                log.info("Connecting to network %r on %s:%s", self.name, ip, port)
 | 
			
		||||
                self.socket.connect((ip, port))
 | 
			
		||||
                self.socket.settimeout(self.pingtimeout)
 | 
			
		||||
                self.proto.connect(self)
 | 
			
		||||
                self.spawnMain()
 | 
			
		||||
                log.info('(%s) Starting ping schedulers....', self.name)
 | 
			
		||||
                self.schedulePing()
 | 
			
		||||
                log.info('(%s) Server ready; listening for data.', self.name)
 | 
			
		||||
                self.run()
 | 
			
		||||
 | 
			
		||||
                if self.ssl and checks_ok:
 | 
			
		||||
                    peercert = self.socket.getpeercert(binary_form=True)
 | 
			
		||||
                    sha1fp = hashlib.sha1(peercert).hexdigest()
 | 
			
		||||
                    expected_fp = self.serverdata.get('ssl_fingerprint')
 | 
			
		||||
                    if expected_fp:
 | 
			
		||||
                        if sha1fp != expected_fp:
 | 
			
		||||
                            log.error('(%s) Uplink\'s SSL certificate '
 | 
			
		||||
                                      'fingerprint (SHA1) does not match the '
 | 
			
		||||
                                      'one configured: expected %r, got %r; '
 | 
			
		||||
                                      'disconnecting...', self.name,
 | 
			
		||||
                                      expected_fp, sha1fp)
 | 
			
		||||
                            checks_ok = False
 | 
			
		||||
                        else:
 | 
			
		||||
                            log.info('(%s) Uplink SSL certificate fingerprint '
 | 
			
		||||
                                     '(SHA1) verified: %r', self.name, sha1fp)
 | 
			
		||||
                    else:
 | 
			
		||||
                        log.info('(%s) Uplink\'s SSL certificate fingerprint '
 | 
			
		||||
                                 'is %r. You can enhance the security of your '
 | 
			
		||||
                                 'link by specifying this in a "ssl_fingerprint"'
 | 
			
		||||
                                 ' option in your server block.', self.name,
 | 
			
		||||
                                 sha1fp)
 | 
			
		||||
 | 
			
		||||
                if checks_ok:
 | 
			
		||||
                    self.proto.connect(self)
 | 
			
		||||
                    self.spawnMain()
 | 
			
		||||
                    log.info('(%s) Starting ping schedulers....', self.name)
 | 
			
		||||
                    self.schedulePing()
 | 
			
		||||
                    log.info('(%s) Server ready; listening for data.', self.name)
 | 
			
		||||
                    self.run()
 | 
			
		||||
                else:
 | 
			
		||||
                    log.error('(%s) A configuration error was encountered '
 | 
			
		||||
                              'trying to set up this connection. Please check'
 | 
			
		||||
                              ' your configuration file and try again.',
 | 
			
		||||
                              self.name)
 | 
			
		||||
            except (socket.error, classes.ProtocolError, ConnectionError) as e:
 | 
			
		||||
                log.warning('(%s) Disconnected from IRC: %s: %s',
 | 
			
		||||
                            self.name, type(e).__name__, str(e))
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user