aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron LI <aly@aaronly.me>2018-03-06 16:00:47 +0800
committerAaron LI <aly@aaronly.me>2018-03-14 11:35:08 +0800
commitfb5e49943bb467d4d47243b48bfc7587994e36d9 (patch)
treeaf08134ea9011a44fad3f1e59b567bb00803b6eb
parent35fba2ec5aa5a4f61ed4e8d805fab294549daa13 (diff)
downloadansible-dfly-vps-fb5e49943bb467d4d47243b48bfc7587994e36d9.tar.bz2
add hash-passdb.py tool to help build passdb for dovecot's passwd
-rwxr-xr-xprivate/dovecot/hash-passdb.py73
1 files changed, 73 insertions, 0 deletions
diff --git a/private/dovecot/hash-passdb.py b/private/dovecot/hash-passdb.py
new file mode 100755
index 0000000..abb05a9
--- /dev/null
+++ b/private/dovecot/hash-passdb.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2018 Aaron LI
+# MIT License
+#
+
+"""
+Find and hash the plain passwords in "passdb.yml" used to generate
+the "passwd" auth database for Dovecot.
+
+The given infile will be updated in place, and the already hashed
+passwords are also kept.
+
+NOTE: The "SHA512-CRYPT" scheme is used.
+"""
+
+import argparse
+import crypt
+
+from ruamel.yaml import YAML
+
+SCHEME = "SHA512-CRYPT"
+METHOD = crypt.METHOD_SHA512
+yaml = YAML()
+
+
+def hashpass(word):
+ """
+ Check the given word, and hash it if it's not hashed.
+ """
+ if word.startswith("{%s}" % SCHEME):
+ # Already hashed
+ return word
+
+ salt = crypt.mksalt(METHOD)
+ return "{%s}%s" % (SCHEME, crypt.crypt(word, salt))
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Find and hash the plain passwords in a YAML file"
+ )
+ parser.add_argument("infile", help="input passdb.yml")
+ args = parser.parse_args()
+
+ data = yaml.load(open(args.infile))
+ print("Loaded passdb from file: %s" % args.infile)
+
+ for name, user in data["passdb"].items():
+ if "pass" in user:
+ oldword = user["pass"]
+ user["pass"] = hashpass(oldword)
+ if user["pass"] == oldword:
+ status = "ok"
+ else:
+ status = "hashed"
+ print("* %s ... [%s]" % (name, status))
+ if "devices" in user:
+ devices = user["devices"]
+ for dev, oldword in devices.items():
+ devices[dev] = hashpass(oldword)
+ if devices[dev] == oldword:
+ status = "ok"
+ else:
+ status = "hashed"
+ print("* %s @ %s ... [%s]" % (name, dev, status))
+
+ yaml.dump(data, open(args.infile, "w"))
+ print("Dumped hashed passdb to file: %s" % args.infile)
+
+
+if __name__ == "__main__":
+ main()