| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -6,6 +6,9 @@ try:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				except ImportError:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    import pickle
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import dns
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import dns.resolver
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import hmac
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import secrets
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import time
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -25,7 +28,6 @@ from itsdangerous.encoding import want_bytes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from werkzeug.datastructures import CallbackDict
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				from werkzeug.contrib import fixers
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				# Login configuration
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				login = flask_login.LoginManager()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				login.login_view = "ui.login"
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -37,6 +39,26 @@ def handle_needs_login():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        flask.url_for('ui.login', next=flask.request.endpoint)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				# DNS stub configured to do DNSSEC enabled queries
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				resolver = dns.resolver.Resolver()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				resolver.use_edns(0, 0, 1500)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				resolver.flags = dns.flags.AD | dns.flags.RD
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def has_dane_record(domain, timeout=5):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    try:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result = resolver.query(f'_25._tcp.{domain}', dns.rdatatype.TLSA,dns.rdataclass.IN, lifetime=timeout)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (result.response.flags & dns.flags.AD) == dns.flags.AD:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            for record in result:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if isinstance(record, dns.rdtypes.ANY.TLSA.TLSA):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    record.validate()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if record.usage in [2,3]: # postfix wants DANE-only
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        return True
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    except dns.resolver.NoNameservers:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        # this could be an attack / a failed DNSSEC lookup
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return True
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    except:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pass
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				# Rate limiter
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				limiter = limiter.LimitWraperFactory()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |