From de4e2027a1e9e9eed0fbc5e1cc0b4b7bbc7c606e Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:24:31 +1100 Subject: [PATCH 01/17] Specify EditorConfig settings for this code base. --- .editorconfig | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2d32e1a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,34 @@ +# .editorconfig +# EditorConfig settings for this code base. +# See documentation at . + +# Is this the top-most EditorConfig config file in the code base? +root = true + +# Match all file names, unless more specific match later. +[*] + +# Text encoding name. +charset = utf-8 + +# Remove trailing whitespace on lines? +trim_trailing_whitespace = true + +# End-of-line style (“lf”, “cr”, “crlf”). +end_of_line = lf + +# Ensure file ends with a line break? +insert_final_newline = true + +# Character to use for indentation (“tab“ for U+0009, “space“ for U+0020). +indent_style = space + +# Number of columns for each indentation level. +indent_size = 4 + + +# Local variables: +# coding: utf-8 +# mode: conf +# End: +# vim: fileencoding=utf-8 filetype=dosini : From ebd066b17086ee0e66e4cd1622eceeca3c292807 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:24:40 +1100 Subject: [PATCH 02/17] Remove trailing whitespace. --- README.md | 2 +- auth-mastodon.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 739051a..b481d11 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a Python script designed to run as an [ejabberd external auth](https://d The code is derived from [ejabberd-auth-mysql](https://github.com/rankenstein/ejabberd-auth-mysql) and is licensed under the GNU GPLv3. -It is used on [Chinwag Social](https://social.chinwag.org) to provide XMPP messaging functionality to every account. +It is used on [Chinwag Social](https://social.chinwag.org) to provide XMPP messaging functionality to every account. Discussion, questions and/or just saying hi in the [Chinwag Social Beergarden](xmpp:beergarden@rooms.chinwag.org?join) MUC (beergarden@rooms.chinwag.org) is welcomed! diff --git a/auth-mastodon.py b/auth-mastodon.py index ad366dc..3cd73ee 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -25,7 +25,7 @@ logging.basicConfig(level=logging.INFO, filemode='a') try: - # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a + # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a # tendency to keep things "idle in transaction" and table locks eventually grind # Mastodon to a halt. We don't make any changes anyway. database=psycopg2.connect(host = db_host, user = db_user, password = db_pass, database = db_name, port = db_port) @@ -140,8 +140,8 @@ while True: op_result = False try: - # Only 'auth' and 'isuser' implemented, placeholders left to maybe - # expose other functions later but for now let's not even think about + # Only 'auth' and 'isuser' implemented, placeholders left to maybe + # expose other functions later but for now let's not even think about # modifying the Mastodon DB if ejab_request[0] == "auth": op_result = auth(ejab_request[1], ejab_request[2], ejab_request[3]) From c6c19a1bcfd1cc488186ca388c3e7080c18d286e Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:24:48 +1100 Subject: [PATCH 03/17] Convert indentation to use U+0020 SPACE characters. PEP 8 specifies: * Use 4 spaces per indentation level. * Spaces (U+0008) are the preferred indentation method. --- auth-mastodon.py | 174 +++++++++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 3cd73ee..e801f34 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -20,34 +20,34 @@ db_query_getpass="select users.encrypted_password as password from accounts inne sys.stderr = open('/var/log/ejabberd/extauth_err.log', 'a') logging.basicConfig(level=logging.INFO, - format='%(asctime)s %(levelname)s %(message)s', - filename='/var/log/ejabberd/extauth.log', - filemode='a') + format='%(asctime)s %(levelname)s %(message)s', + filename='/var/log/ejabberd/extauth.log', + filemode='a') try: - # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a - # tendency to keep things "idle in transaction" and table locks eventually grind - # Mastodon to a halt. We don't make any changes anyway. - database=psycopg2.connect(host = db_host, user = db_user, password = db_pass, database = db_name, port = db_port) - database.set_session(readonly=True, autocommit=True) - logging.debug(database.get_dsn_parameters()) + # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a + # tendency to keep things "idle in transaction" and table locks eventually grind + # Mastodon to a halt. We don't make any changes anyway. + database=psycopg2.connect(host = db_host, user = db_user, password = db_pass, database = db_name, port = db_port) + database.set_session(readonly=True, autocommit=True) + logging.debug(database.get_dsn_parameters()) except: - logging.error("Unable to initialize database, check settings!") - time.sleep(10) - sys.exit(1) + logging.error("Unable to initialize database, check settings!") + time.sleep(10) + sys.exit(1) @atexit.register def close_db(): - cursor.close() - database.close() + cursor.close() + database.close() logging.info('auth-mastodon script started, waiting for ejabberd requests') class EjabberdInputError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) ######################################################################## @@ -55,70 +55,70 @@ class EjabberdInputError(Exception): ######################################################################## def ejabberd_in(): - logging.debug("trying to read 2 bytes from ejabberd:") + logging.debug("trying to read 2 bytes from ejabberd:") - input_length = sys.stdin.buffer.read(2) + input_length = sys.stdin.buffer.read(2) - if len(input_length) is not 2: - logging.debug("ejabberd sent us wrong things!") - raise EjabberdInputError('Wrong input from ejabberd!') + if len(input_length) is not 2: + logging.debug("ejabberd sent us wrong things!") + raise EjabberdInputError('Wrong input from ejabberd!') - logging.debug('got 2 bytes via stdin: %s'%input_length) + logging.debug('got 2 bytes via stdin: %s'%input_length) - (size,) = struct.unpack('>h', input_length) - logging.debug('size of data: %i'%size) + (size,) = struct.unpack('>h', input_length) + logging.debug('size of data: %i'%size) - income=sys.stdin.read(size) - logging.debug("incoming data: %s"%income) + income=sys.stdin.read(size) + logging.debug("incoming data: %s"%income) - return income + return income def ejabberd_out(bool): - logging.debug("Ejabberd gets: %s" % bool) + logging.debug("Ejabberd gets: %s" % bool) - token = genanswer(bool) + token = genanswer(bool) - logging.debug("sent bytes: %#x %#x %#x %#x" % (token[0], token[1], token[2], token[3])) + logging.debug("sent bytes: %#x %#x %#x %#x" % (token[0], token[1], token[2], token[3])) - sys.stdout.buffer.write(token) - sys.stdout.buffer.flush() + sys.stdout.buffer.write(token) + sys.stdout.buffer.flush() def genanswer(bool): - answer = 0 - if bool: - answer = 1 - token = struct.pack('>hh', 2, answer) - return token + answer = 0 + if bool: + answer = 1 + token = struct.pack('>hh', 2, answer) + return token def get_password(user, host): - # Right now we ignore the host component, as Mastodon doesn't store it for local accounts. - # It may be required one day, so the code to handle passing it to the query is left in for now. - cursor = database.cursor() - cursor.execute(db_query_getpass, {"user": user.lower(), "host": host}) - data = cursor.fetchone() - cursor.close() - return data[0] if data != None else None + # Right now we ignore the host component, as Mastodon doesn't store it for local accounts. + # It may be required one day, so the code to handle passing it to the query is left in for now. + cursor = database.cursor() + cursor.execute(db_query_getpass, {"user": user.lower(), "host": host}) + data = cursor.fetchone() + cursor.close() + return data[0] if data != None else None def isuser(user, host): - return get_password(user, host) != None + return get_password(user, host) != None def auth(user, host, password): - db_password = get_password(user, host) - if db_password == None: - logging.debug("Wrong username: %s@%s" % (user, host)) - return False - else: - if bcrypt.checkpw(password.encode('utf8'), db_password.encode('utf8')): - logging.debug("Validated %s against hash %s" % (user, db_password)) - return True - else: - logging.debug("Wrong password for user: %s@%s" % (user, host)) - return False + db_password = get_password(user, host) + if db_password == None: + logging.debug("Wrong username: %s@%s" % (user, host)) + return False + else: + if bcrypt.checkpw(password.encode('utf8'), db_password.encode('utf8')): + logging.debug("Validated %s against hash %s" % (user, db_password)) + return True + else: + logging.debug("Wrong password for user: %s@%s" % (user, host)) + return False ######################################################################## @@ -128,38 +128,38 @@ def auth(user, host, password): exitcode=0 while True: - logging.debug("start of infinite loop") + logging.debug("start of infinite loop") - try: - ejab_request = ejabberd_in().split(':', 3) - except EOFError: - break - except Exception as e: - logging.exception("Exception occured while reading stdin") - raise + try: + ejab_request = ejabberd_in().split(':', 3) + except EOFError: + break + except Exception as e: + logging.exception("Exception occured while reading stdin") + raise - op_result = False - try: - # Only 'auth' and 'isuser' implemented, placeholders left to maybe - # expose other functions later but for now let's not even think about - # modifying the Mastodon DB - if ejab_request[0] == "auth": - op_result = auth(ejab_request[1], ejab_request[2], ejab_request[3]) - elif ejab_request[0] == "isuser": - op_result = isuser(ejab_request[1], ejab_request[2]) - elif ejab_request[0] == "setpass": - op_result = False - elif ejab_request[0] == "tryregister": - op_result = False - elif ejab_request[0] == "removeuser": - op_result = False - elif ejab_request[0] == "removeuser3": - op_result = False - except Exception: - logging.exception("Exception occured") + op_result = False + try: + # Only 'auth' and 'isuser' implemented, placeholders left to maybe + # expose other functions later but for now let's not even think about + # modifying the Mastodon DB + if ejab_request[0] == "auth": + op_result = auth(ejab_request[1], ejab_request[2], ejab_request[3]) + elif ejab_request[0] == "isuser": + op_result = isuser(ejab_request[1], ejab_request[2]) + elif ejab_request[0] == "setpass": + op_result = False + elif ejab_request[0] == "tryregister": + op_result = False + elif ejab_request[0] == "removeuser": + op_result = False + elif ejab_request[0] == "removeuser3": + op_result = False + except Exception: + logging.exception("Exception occured") - ejabberd_out(op_result) - logging.info("successful" if op_result else "unsuccessful") + ejabberd_out(op_result) + logging.info("successful" if op_result else "unsuccessful") logging.debug("end of infinite loop") logging.info('extauth script terminating') From dc09a6be928dd34b84ff764fc08846445181b2f1 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:24:54 +1100 Subject: [PATCH 04/17] Normalise indentation levels by wrapping at open parenthesis. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * Use 4 spaces per indentation level. * Continuation lines should align wrapped elements either vertically using Python’s implicit line joining inside parentheses, brackets and braces, or using a hanging indent. --- auth-mastodon.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index e801f34..c7b79aa 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -19,10 +19,12 @@ db_query_getpass="select users.encrypted_password as password from accounts inne ######################################################################## sys.stderr = open('/var/log/ejabberd/extauth_err.log', 'a') -logging.basicConfig(level=logging.INFO, - format='%(asctime)s %(levelname)s %(message)s', - filename='/var/log/ejabberd/extauth.log', - filemode='a') +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s %(levelname)s %(message)s', + filename='/var/log/ejabberd/extauth.log', + filemode='a', +) try: # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a From e30ab77cf4a34b357883ce26ff006fc5cc88b5b0 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:10 +1100 Subject: [PATCH 05/17] Use structural blank lines conformant with PEP 8. PEP 8 specifies: * Surround top-level function and class definitions with two blank lines. * Method definitions inside a class are surrounded by a single blank line. --- auth-mastodon.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/auth-mastodon.py b/auth-mastodon.py index c7b79aa..e7d9cdb 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 + import os, sys, logging, struct, psycopg2, bcrypt, random, atexit, time + # Database connection details. The credentials here need access to the Mastodon database, which "ejabberd" is unlikely # to have on your system by default. You shoud grant SELECT privileges to ejabberd on the "accounts" and "users" tables, # to play it safe, or include the Mastodon DB user credentials here (don't). @@ -38,16 +40,21 @@ except: time.sleep(10) sys.exit(1) + @atexit.register def close_db(): cursor.close() database.close() + logging.info('auth-mastodon script started, waiting for ejabberd requests') + class EjabberdInputError(Exception): + def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) From 3ef1d5daae7304e0cf22fccba09239601ef0a90e Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:24 +1100 Subject: [PATCH 06/17] =?UTF-8?q?Use=20a=20separate=20=E2=80=98import?= =?UTF-8?q?=E2=80=99=20statement=20for=20each=20module/package,=20grouped.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * Imports should usually be on separate lines. * Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants. * Imports should be grouped in the following order: * Standard library imports. * Related third party imports. * Local application/library specific imports. --- auth-mastodon.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index e7d9cdb..e7b36ae 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -1,6 +1,15 @@ #!/usr/bin/env python3 -import os, sys, logging, struct, psycopg2, bcrypt, random, atexit, time +import atexit +import logging +import os +import struct +import sys +import random +import time + +import bcrypt +import psycopg2 # Database connection details. The credentials here need access to the Mastodon database, which "ejabberd" is unlikely From 512114517c82d67292b65e1904582729e1b2d88a Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:35 +1100 Subject: [PATCH 07/17] Remove unused imports. --- auth-mastodon.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index e7b36ae..ee3b858 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -2,10 +2,8 @@ import atexit import logging -import os import struct import sys -import random import time import bcrypt From 9a2d05e51f6cd69ea926a94bae8ecb1cb3066dea Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:45 +1100 Subject: [PATCH 08/17] =?UTF-8?q?Use=20=E2=80=98#=20=E2=80=99=20comment=20?= =?UTF-8?q?leader=20for=20block=20comments.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment). --- auth-mastodon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index ee3b858..26890b6 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -24,7 +24,7 @@ db_name="mastodon" db_query_getpass="select users.encrypted_password as password from accounts inner join users on accounts.id=users.account_id where lower(accounts.username) = %(user)s and accounts.domain is null" ######################################################################## -#Setup +# Setup ######################################################################## sys.stderr = open('/var/log/ejabberd/extauth_err.log', 'a') @@ -67,7 +67,7 @@ class EjabberdInputError(Exception): ######################################################################## -#Declarations +# Declarations ######################################################################## def ejabberd_in(): @@ -138,7 +138,7 @@ def auth(user, host, password): ######################################################################## -#Main Loop +# Main Loop ######################################################################## exitcode=0 From 237abe539a4a0e5d3df2d5de8634a028ad8af505 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:54 +1100 Subject: [PATCH 09/17] Use whitespace around operators in conformance with PEP 8. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * A single space around binary operators (e.g. ‘=’ assignment, ‘%’ modulus). * No surrounding space around ‘=’ in keyword argument assignment for a function call. --- auth-mastodon.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 26890b6..0849a64 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -13,15 +13,15 @@ import psycopg2 # Database connection details. The credentials here need access to the Mastodon database, which "ejabberd" is unlikely # to have on your system by default. You shoud grant SELECT privileges to ejabberd on the "accounts" and "users" tables, # to play it safe, or include the Mastodon DB user credentials here (don't). -db_host="localhost" -db_port=5432 -db_user="ejabberd" -db_pass="" -db_name="mastodon" +db_host = "localhost" +db_port = 5432 +db_user = "ejabberd" +db_pass = "" +db_name = "mastodon" # This is the query that pulls the password hash for the given user. Mastodon doesn't store the domain for local accounts in # the database, so we ignore the host component and try to match username where the domain is NULL. -db_query_getpass="select users.encrypted_password as password from accounts inner join users on accounts.id=users.account_id where lower(accounts.username) = %(user)s and accounts.domain is null" +db_query_getpass = "select users.encrypted_password as password from accounts inner join users on accounts.id=users.account_id where lower(accounts.username) = %(user)s and accounts.domain is null" ######################################################################## # Setup @@ -39,7 +39,7 @@ try: # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a # tendency to keep things "idle in transaction" and table locks eventually grind # Mastodon to a halt. We don't make any changes anyway. - database=psycopg2.connect(host = db_host, user = db_user, password = db_pass, database = db_name, port = db_port) + database = psycopg2.connect(host=db_host, user=db_user, password=db_pass, database=db_name, port=db_port) database.set_session(readonly=True, autocommit=True) logging.debug(database.get_dsn_parameters()) except: @@ -79,13 +79,13 @@ def ejabberd_in(): logging.debug("ejabberd sent us wrong things!") raise EjabberdInputError('Wrong input from ejabberd!') - logging.debug('got 2 bytes via stdin: %s'%input_length) + logging.debug('got 2 bytes via stdin: %s' % input_length) (size,) = struct.unpack('>h', input_length) - logging.debug('size of data: %i'%size) + logging.debug('size of data: %i' % size) - income=sys.stdin.read(size) - logging.debug("incoming data: %s"%income) + income = sys.stdin.read(size) + logging.debug("incoming data: %s" % income) return income @@ -141,7 +141,7 @@ def auth(user, host, password): # Main Loop ######################################################################## -exitcode=0 +exitcode = 0 while True: logging.debug("start of infinite loop") From 34ab6489ba5255c8dd0a5368012d2e88e13018db Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:25:58 +1100 Subject: [PATCH 10/17] Reformat SQL statement for clarity and wrap the long line. --- auth-mastodon.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 0849a64..efc9714 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -21,7 +21,15 @@ db_name = "mastodon" # This is the query that pulls the password hash for the given user. Mastodon doesn't store the domain for local accounts in # the database, so we ignore the host component and try to match username where the domain is NULL. -db_query_getpass = "select users.encrypted_password as password from accounts inner join users on accounts.id=users.account_id where lower(accounts.username) = %(user)s and accounts.domain is null" +db_query_getpass = """ + SELECT users.encrypted_password AS password + FROM accounts + INNER JOIN users + ON accounts.id = users.account_id + WHERE + lower(accounts.username) = %(user)s + AND accounts.domain IS NULL + """ ######################################################################## # Setup From 9325300e391d086fad1173d5ab2aa1a70457b7c8 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:26:03 +1100 Subject: [PATCH 11/17] Wrap long statements across multiple lines. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * Limit all lines to a maximum of 79 characters. * The preferred way of wrapping long lines is by using Python’s implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation. --- auth-mastodon.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index efc9714..3084213 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -47,7 +47,13 @@ try: # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a # tendency to keep things "idle in transaction" and table locks eventually grind # Mastodon to a halt. We don't make any changes anyway. - database = psycopg2.connect(host=db_host, user=db_user, password=db_pass, database=db_name, port=db_port) + database = psycopg2.connect( + host=db_host, + user=db_user, + password=db_pass, + database=db_name, + port=db_port, + ) database.set_session(readonly=True, autocommit=True) logging.debug(database.get_dsn_parameters()) except: @@ -103,7 +109,9 @@ def ejabberd_out(bool): token = genanswer(bool) - logging.debug("sent bytes: %#x %#x %#x %#x" % (token[0], token[1], token[2], token[3])) + logging.debug( + "sent bytes: %#x %#x %#x %#x" + % (token[0], token[1], token[2], token[3])) sys.stdout.buffer.write(token) sys.stdout.buffer.flush() From a88f298e98af40260cfdc0e10566e744b1087f71 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:26:13 +1100 Subject: [PATCH 12/17] Wrap long block comment lines at 72 columns. --- auth-mastodon.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 3084213..798ba80 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -10,17 +10,21 @@ import bcrypt import psycopg2 -# Database connection details. The credentials here need access to the Mastodon database, which "ejabberd" is unlikely -# to have on your system by default. You shoud grant SELECT privileges to ejabberd on the "accounts" and "users" tables, -# to play it safe, or include the Mastodon DB user credentials here (don't). +# Database connection details. The credentials here need access to the +# Mastodon database, which "ejabberd" is unlikely to have on your system +# by default. You shoud grant SELECT privileges to ejabberd on the +# "accounts" and "users" tables, to play it safe, or include the +# Mastodon DB user credentials here (don't). db_host = "localhost" db_port = 5432 db_user = "ejabberd" db_pass = "" db_name = "mastodon" -# This is the query that pulls the password hash for the given user. Mastodon doesn't store the domain for local accounts in -# the database, so we ignore the host component and try to match username where the domain is NULL. +# This is the query that pulls the password hash for the given user. +# Mastodon doesn't store the domain for local accounts in the database, +# so we ignore the host component and try to match username where the +# domain is NULL. db_query_getpass = """ SELECT users.encrypted_password AS password FROM accounts @@ -44,9 +48,10 @@ logging.basicConfig( ) try: - # Connect to the DB, set autocommit and readonly otherwise postgresql seems to have a - # tendency to keep things "idle in transaction" and table locks eventually grind - # Mastodon to a halt. We don't make any changes anyway. + # Connect to the DB, set autocommit and readonly otherwise + # postgresql seems to have a tendency to keep things "idle in + # transaction" and table locks eventually grind Mastodon to a halt. + # We don't make any changes anyway. database = psycopg2.connect( host=db_host, user=db_user, @@ -126,8 +131,9 @@ def genanswer(bool): def get_password(user, host): - # Right now we ignore the host component, as Mastodon doesn't store it for local accounts. - # It may be required one day, so the code to handle passing it to the query is left in for now. + # Right now we ignore the host component, as Mastodon doesn't store + # it for local accounts. It may be required one day, so the code to + # handle passing it to the query is left in for now. cursor = database.cursor() cursor.execute(db_query_getpass, {"user": user.lower(), "host": host}) data = cursor.fetchone() @@ -172,9 +178,9 @@ while True: op_result = False try: - # Only 'auth' and 'isuser' implemented, placeholders left to maybe - # expose other functions later but for now let's not even think about - # modifying the Mastodon DB + # Only 'auth' and 'isuser' implemented, placeholders left to + # maybe expose other functions later but for now let's not even + # think about modifying the Mastodon DB if ejab_request[0] == "auth": op_result = auth(ejab_request[1], ejab_request[2], ejab_request[3]) elif ejab_request[0] == "isuser": From 4bed400c7df6a98a8695fa3f70119aff17815e90 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:48:10 +1100 Subject: [PATCH 13/17] Use equality operator for comparison to integer value. --- auth-mastodon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 798ba80..1e5a058 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -94,7 +94,7 @@ def ejabberd_in(): input_length = sys.stdin.buffer.read(2) - if len(input_length) is not 2: + if len(input_length) != 2: logging.debug("ejabberd sent us wrong things!") raise EjabberdInputError('Wrong input from ejabberd!') From 7118641d78a90c4f0cadbc4e63c80d203fdb625a Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:41:29 +1100 Subject: [PATCH 14/17] Use identity operators for comparison to None singleton. PEP 8 specifies: * Comparisons to singletons like None should always be done with `is` or `is not`, never the equality operators. --- auth-mastodon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 1e5a058..5c39435 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -138,16 +138,16 @@ def get_password(user, host): cursor.execute(db_query_getpass, {"user": user.lower(), "host": host}) data = cursor.fetchone() cursor.close() - return data[0] if data != None else None + return data[0] if data is not None else None def isuser(user, host): - return get_password(user, host) != None + return get_password(user, host) is not None def auth(user, host, password): db_password = get_password(user, host) - if db_password == None: + if db_password is None: logging.debug("Wrong username: %s@%s" % (user, host)) return False else: From 6a4de62467024bcc28d52d1f6743fbb9f0fad1d6 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:50:05 +1100 Subject: [PATCH 15/17] Remove an assignment to an unused name. --- auth-mastodon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 5c39435..1e0b377 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -172,7 +172,7 @@ while True: ejab_request = ejabberd_in().split(':', 3) except EOFError: break - except Exception as e: + except Exception: logging.exception("Exception occured while reading stdin") raise From 1ad357ba4a6c788b3f1992953013bbc5d51043ee Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:45:39 +1100 Subject: [PATCH 16/17] =?UTF-8?q?Specify=20the=20=E2=80=98Exception?= =?UTF-8?q?=E2=80=99=20catch-all=20exception=20class,=20not=20a=20bare=20?= =?UTF-8?q?=E2=80=98except=E2=80=99.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PEP 8 specifies: * When catching exceptions, mention specific exceptions whenever possible instead of using a bare `except:` clause […] A bare `except:` clause will catch `SystemExit` and `KeyboardInterrupt` exceptions, making it harder to interrupt a program with Control-C, and can disguise other problems. If you want to catch all exceptions that signal program errors, use `except Exception:` (bare except is equivalent to `except BaseException:`). --- auth-mastodon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 1e0b377..92d8c4a 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -61,7 +61,7 @@ try: ) database.set_session(readonly=True, autocommit=True) logging.debug(database.get_dsn_parameters()) -except: +except Exception: logging.error("Unable to initialize database, check settings!") time.sleep(10) sys.exit(1) From 2a7e4fcd6e2b3d739047bb46987cb3930e5b14f5 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 19 Dec 2022 09:52:20 +1100 Subject: [PATCH 17/17] Remove a statement using a name that is never defined in scope. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intention may have been to close the “current” database cursor; but there is no reference to that at this point in the code. --- auth-mastodon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/auth-mastodon.py b/auth-mastodon.py index 92d8c4a..fc0de5a 100644 --- a/auth-mastodon.py +++ b/auth-mastodon.py @@ -69,7 +69,6 @@ except Exception: @atexit.register def close_db(): - cursor.close() database.close()