From: Frank Brehm Date: Fri, 11 Nov 2022 15:38:27 +0000 (+0100) Subject: Adding bin/mkldappasswd and its application module pp_admintools.app.mk_ldap_passwd X-Git-Tag: 0.7.2^2^2~9 X-Git-Url: https://git.uhu-banane.net/?a=commitdiff_plain;h=8531832f7964abeb69599d1ca69e43b02f49f859;p=pixelpark%2Fpp-admin-tools.git Adding bin/mkldappasswd and its application module pp_admintools.app.mk_ldap_passwd --- diff --git a/bin/mkldappasswd b/bin/mkldappasswd new file mode 100755 index 0000000..255a54b --- /dev/null +++ b/bin/mkldappasswd @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +from __future__ import print_function + +# Standard modules +import sys + +__exp_py_version_major__ = 3 +__min_py_version_minor__ = 6 + +if sys.version_info[0] != __exp_py_version_major__: + print("This script is intended to use with Python {}.".format( + __exp_py_version_major__), file=sys.stderr) + print("You are using Python: {0}.{1}.{2}-{3}-{4}.".format( + *sys.version_info) + "\n", file=sys.stderr) + sys.exit(1) + +if sys.version_info[1] < __min_py_version_minor__: + print("A minimal Python version of {maj}.{min} is necessary to execute this script.".format( + maj=__exp_py_version_major__, min=__min_py_version_minor__), file=sys.stderr) + print("You are using Python: {0}.{1}.{2}-{3}-{4}.".format( + *sys.version_info) + "\n", file=sys.stderr) + sys.exit(1) + +# Standard modules +import os +import locale + +try: + from pathlib import Path +except ImportError: + from pathlib2 import Path + +__author__ = 'Frank Brehm ' +__copyright__ = '(C) 2022 by Frank Brehm, Digitas Pixelpark GmbH, Berlin' + +# own modules: + +my_path = Path(__file__) +my_real_path = my_path.resolve() +bin_path = my_real_path.parent +base_dir = bin_path.parent +lib_dir = base_dir.joinpath('lib') +module_dir = lib_dir.joinpath('pp_admintools') + +if module_dir.exists(): + sys.path.insert(0, str(lib_dir)) + +from pp_admintools.app.mk_ldap_passwd import MkLdapPasswdApplication + +appname = os.path.basename(sys.argv[0]) + +locale.setlocale(locale.LC_ALL, '') + +app = MkLdapPasswdApplication(appname=appname, base_dir=base_dir) +app.initialized = True + +if app.verbose > 2: + print("{c}-Object:\n{a}".format(c=app.__class__.__name__, a=app)) + +app() + +sys.exit(0) + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/lib/pp_admintools/app/mk_ldap_passwd.py b/lib/pp_admintools/app/mk_ldap_passwd.py new file mode 100644 index 0000000..bf34fa7 --- /dev/null +++ b/lib/pp_admintools/app/mk_ldap_passwd.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- +""" +@summary: An application module for the mkldappasswd application + +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 2022 by Frank Brehm, Berlin +""" +from __future__ import absolute_import + +# Standard modules +import logging +import os +import getpass +import sys + +# Own modules +# from fb_tools.common import to_bool, is_sequence, pp +from fb_tools.common import is_sequence +from fb_tools.app import BaseApplication + +from .. import pp + +from ..xlate import XLATOR + +from ..errors import PpAppError + +from .ldap import PasswordFileOptionAction + +from ..handler.ldap_password import WrongPwdSchemaError +from ..handler.ldap_password import LdapPasswordHandler +from ..handler.ldap_password import HAS_CRACKLIB +from ..handler.ldap_password import WrongSaltError, WrongRoundsError + +__version__ = '0.1.1' +LOG = logging.getLogger(__name__) + +_ = XLATOR.gettext +ngettext = XLATOR.ngettext + + +# ============================================================================= +class MkLdapPasswdError(PpAppError): + """Special exception class for exceptions inside this module.""" + + pass + + +# ============================================================================= +class MkLdapPasswdApplication(BaseApplication): + """Application class for the mkldappasswd application.""" + + show_simulate_option = False + + # ------------------------------------------------------------------------- + def __init__(self, appname=None, base_dir=None): + + LdapPasswordHandler.init_pass_schemes() + + self.password = None + self.no_cracklib = False + + self.pwd_handler = LdapPasswordHandler( + appname=appname, base_dir=base_dir, initialized=False) + + desc = _("Encrypting the password with a defined password schema.") + + super(MkLdapPasswdApplication, self).__init__( + appname=appname, description=desc, base_dir=base_dir, initialized=False) + + self.initialized = True + + # ------------------------------------------------------------------------- + def as_dict(self, short=True): + """ + Transforms the elements of the object into a dict + + @param short: don't include local properties in resulting dict. + @type short: bool + + @return: structure as dict + @rtype: dict + """ + + res = super(MkLdapPasswdApplication, self).as_dict(short=short) + + if self.password and self.verbose < 5: + res['password'] = '******' + + return res + + # ------------------------------------------------------------------------- + def init_arg_parser(self): + + app_group = self.arg_parser.add_argument_group(_("Options for {}").format( + self.appname)) + + schema_list = [] + def_schema = '' + for method in LdapPasswordHandler.available_schemes: + schema_id = LdapPasswordHandler.schema_ids[method] + schema_list.append(schema_id) + if method == LdapPasswordHandler.default_schema: + def_schema = schema_id + schema_list.append('list') + schema_list.append('help') + + help_txt = _( + "The schema (hashing method) to use to hash the new password. " + "Default: {default!r}.").format(default=def_schema) + + app_group.add_argument( + '-m', '--method', metavar=_("TYPE"), dest="method", choices=schema_list, help=help_txt) + + pwd_group = app_group.add_mutually_exclusive_group() + + pwd_group.add_argument( + '--stdin', action="store_true", dest="stdin", + help=_("Like {}").format('--password-fd=0') + ) + + app_group.add_argument( + '-S', '--salt', metavar='SALT', dest="salt", + help=_( + "A possible salt to use on hashing the password. Caution: " + "not all hashing schemes are supporting a salt.") + ) + + app_group.add_argument( + '-R', '--rounds', metavar=_('NUMBER'), dest="rounds", type=int, + help=_( + "The number of calculation rounds to use on hashing the password. Caution: " + "not all hashing schemes are supporting calculation rounds.") + ) + + pwd_help = _( + "The password to hash. If not given and no file desriptor was given, " + "then the password will be requested on TTY.") + pwd_group.add_argument( + 'password', metavar=_('PASSWORD'), nargs='?', help=pwd_help) + + super(MkLdapPasswdApplication, self).init_arg_parser() + + # ------------------------------------------------------------------------- + def post_init(self): + """ + Method to execute before calling run(). + """ + + super(MkLdapPasswdApplication, self).post_init() + + if self.verbose > 1: + msg = "Given args:\n" + pp(self.args.__dict__) + LOG.debug(msg) + + self.pwd_handler.verbose = self.verbose + self.pwd_handler.simulate = self.simulate + self.pwd_handler.force = self.force + self.pwd_handler.terminal_has_colors = self.terminal_has_colors + self.pwd_handler.initialized = True + + given_schema = getattr(self.args, 'method', None) + if given_schema: + if given_schema in ('list', 'help'): + self.pwd_handler.show_hashing_schemes() + self.exit(0) + return + try: + self.pwd_handler.set_schema_by_id(given_schema) + except WrongPwdSchemaError as e: + self.exit(5, str(e)) + + if self.args.password: + self.password = self.args.password + + # ------------------------------------------------------------------------- + def pre_run(self): + + if not self.password: + + if self.args.stdin: + pwd = sys.stdin.read() + pwd = pwd.rstrip('\r\n') + if pwd: + self.password = pwd + else: + msg = _("Got no password by {}.").format('STDIN') + self.exit(1, msg) + else: + first_prompt = _("Password:") + ' ' + second_prompt = _('Repeat password:') + ' ' + self.password = self.get_password( + first_prompt, second_prompt, may_empty=False, repeat=False) + + super(MkLdapPasswdApplication, self).pre_run() + + # ------------------------------------------------------------------------- + def _run(self): + + self.show_password() + + # ------------------------------------------------------------------------- + def show_password(self): + + msg = _("Encrypting password with hashing schema '{schema}' ...").format( + schema=self.colored(self.pwd_handler.schema_id, 'CYAN')) + LOG.debug(msg) + + salt = getattr(self.args, 'salt', None) + rounds = getattr(self.args, 'rounds', None) + + LOG.debug(_("Used schema: {!r}.").format(self.pwd_handler.schema)) + try: + hashed_passwd = self.pwd_handler.get_hash( + self.password, self.pwd_handler.schema, salt=salt, rounds=rounds) + except (WrongSaltError, WrongRoundsError) as e: + self.exit(1, str(e)) + print(hashed_passwd) + + +# ============================================================================= +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list