mirror of
				https://github.com/mail-in-a-box/mailinabox.git
				synced 2025-10-31 19:00:54 +00:00 
			
		
		
		
	replace Dovecot authentication (formerly an sql query) with a call to our management daemon
This commit is contained in:
		
							parent
							
								
									7e05d7478f
								
							
						
					
					
						commit
						1f0345fe0e
					
				
							
								
								
									
										53
									
								
								conf/dovecot-checkpassword.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								conf/dovecot-checkpassword.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| #!/usr/bin/python3 | ||||
| # | ||||
| # This script implement's Dovecot's checkpassword authentication mechanism: | ||||
| # http://wiki2.dovecot.org/AuthDatabase/CheckPassword?action=show&redirect=PasswordDatabase%2FCheckPassword | ||||
| # | ||||
| # This allows us to perform our own password validation, such as for two-factor authentication, | ||||
| # which Dovecot does not have any native support for. | ||||
| # | ||||
| # We will issue an HTTP request to our management server to perform authentication. | ||||
| 
 | ||||
| import sys, os, urllib.request, base64, json, traceback | ||||
| 
 | ||||
| try: | ||||
| 	# Read fd 3 which provides the username and password separated | ||||
| 	# by NULLs and two other undocumented/empty fields. | ||||
| 	creds = b'' | ||||
| 	while True: | ||||
| 		b = os.read(3, 1024) | ||||
| 		if len(b) == 0: break | ||||
| 		creds += b | ||||
| 	email, pw, dummy, dummy = creds.split(b'\x00') | ||||
| 
 | ||||
| 	# Call the management server's "/me" method with the | ||||
| 	# provided credentials | ||||
| 	req = urllib.request.Request('http://127.0.0.1:10222/me') | ||||
| 	req.add_header(b'Authorization', b'Basic ' + base64.b64encode(email + b':' + pw)) | ||||
| 	response = urllib.request.urlopen(req) | ||||
| 
 | ||||
| 	# The response is always success and always a JSON object | ||||
| 	# indicating the authentication result. | ||||
| 	resp = response.read().decode('utf8') | ||||
| 	resp = json.loads(resp) | ||||
| 	if not isinstance(resp, dict): raise ValueError("Response is not a JSON object.") | ||||
| 
 | ||||
| except: | ||||
| 	# Handle all exceptions. Print what happens (ends up in syslog, thanks | ||||
| 	# to dovecot) and return an exit status that indicates temporary failure, | ||||
| 	# which is passed on to the authenticating client. | ||||
| 	traceback.print_exc() | ||||
| 	print(json.dumps(dict(os.environ), indent=2), file=sys.stderr) | ||||
| 	sys.exit(111) | ||||
| 
 | ||||
| if resp.get('status') != 'authorized': | ||||
| 	# Indicates login failure. | ||||
| 	# (sys.exit should not be inside the try block.) | ||||
| 	sys.exit(1) | ||||
| 
 | ||||
| # Signal ok by executing the indicated process, per the Dovecot | ||||
| # protocol. (Note that the second parameter is the 0th argument | ||||
| # to the called process, which is required and is typically the | ||||
| # file itself.) | ||||
| os.execl(sys.argv[1], sys.argv[1]) | ||||
| 
 | ||||
| @ -26,31 +26,55 @@ fi | ||||
| 
 | ||||
| # ### User Authentication | ||||
| 
 | ||||
| # Have Dovecot query our database, and not system users, for authentication. | ||||
| sed -i "s/#*\(\!include auth-system.conf.ext\)/#\1/"  /etc/dovecot/conf.d/10-auth.conf | ||||
| sed -i "s/#\(\!include auth-sql.conf.ext\)/\1/"  /etc/dovecot/conf.d/10-auth.conf | ||||
| # Disable all of the built-in authentication mechanisms. (We formerly uncommented | ||||
| # a line to include auth-sql.conf.ext but we no longer use that.) | ||||
| sed -i "s/#*\(\!include auth-.*.conf.ext\)/#\1/"  /etc/dovecot/conf.d/10-auth.conf | ||||
| 
 | ||||
| # Specify how the database is to be queried for user authentication (passdb) | ||||
| # and where user mailboxes are stored (userdb). | ||||
| cat > /etc/dovecot/conf.d/auth-sql.conf.ext << EOF; | ||||
| # Legacy: Delete our old sql conf files. | ||||
| rm -f /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext | ||||
| 
 | ||||
| # Specify how Dovecot should perform user authentication (passdb) and how it knows | ||||
| # where user mailboxes are stored (userdb). | ||||
| # | ||||
| # For passwords, we would normally have Dovecot query our mail user database | ||||
| # directly. The way to do that is commented out below. Instead, in order to | ||||
| # provide our own authentication framework so we can handle two-factor auth, | ||||
| # we will use a custom system that hooks into the Mail-in-a-Box management daemon. | ||||
| # | ||||
| # The user part of this is standard. The mailbox path and Unix system user are the | ||||
| # same for all mail users, modulo string substitution for the mailbox path that | ||||
| # Dovecot handles. | ||||
| cat > /etc/dovecot/conf.d/10-auth-mailinabox.conf << EOF; | ||||
| passdb { | ||||
|   driver = sql | ||||
|   args = /etc/dovecot/dovecot-sql.conf.ext | ||||
|   driver = checkpassword | ||||
|   args = /usr/local/bin/dovecot-checkpassword | ||||
| } | ||||
| userdb { | ||||
|   driver = static | ||||
|   args = uid=mail gid=mail home=$STORAGE_ROOT/mail/mailboxes/%d/%n | ||||
| } | ||||
| EOF | ||||
| chmod 0600 /etc/dovecot/conf.d/10-auth-mailinabox.conf | ||||
| 
 | ||||
| # Configure the SQL to query for a user's password. | ||||
| cat > /etc/dovecot/dovecot-sql.conf.ext << EOF; | ||||
| driver = sqlite | ||||
| connect = $db_path | ||||
| default_pass_scheme = SHA512-CRYPT | ||||
| password_query = SELECT email as user, password FROM users WHERE email='%u'; | ||||
| EOF | ||||
| chmod 0600 /etc/dovecot/dovecot-sql.conf.ext # per Dovecot instructions | ||||
| # Copy dovecot-checkpassword into place. | ||||
| cp conf/dovecot-checkpassword.py /usr/local/bin/dovecot-checkpassword | ||||
| chown dovecot.dovecot /usr/local/bin/dovecot-checkpassword | ||||
| chmod 700 /usr/local/bin/dovecot-checkpassword | ||||
| 
 | ||||
| # If we were having Dovecot query our database directly, which we did | ||||
| # originally, `/etc/dovecot/conf.d/10-auth-mailinabox.conf` would say: | ||||
| # | ||||
| #     passdb { | ||||
| #       driver = sql | ||||
| #       args = /etc/dovecot/dovecot-sql.conf.ext | ||||
| #     } | ||||
| # | ||||
| # and then `/etc/dovecot/dovecot-sql.conf.ext` (chmod 0600) would contain: | ||||
| # | ||||
| #    driver = sqlite | ||||
| #    connect = $db_path | ||||
| #    default_pass_scheme = SHA512-CRYPT | ||||
| #    password_query = SELECT email as user, password FROM users WHERE email='%u'; | ||||
| 
 | ||||
| # Have Dovecot provide an authorization service that Postfix can access & use. | ||||
| cat > /etc/dovecot/conf.d/99-local-auth.conf << EOF; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user