diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains.in b/install/oddjob/com.redhat.idm.trust-fetch-domains.in index 45c1f1463..b86be0212 100644 --- a/install/oddjob/com.redhat.idm.trust-fetch-domains.in +++ b/install/oddjob/com.redhat.idm.trust-fetch-domains.in @@ -15,6 +15,7 @@ import six import gssapi from ipalib.install.kinit import kinit_keytab, kinit_password +from ipapython.admintool import admin_cleanup_global_argv if six.PY3: unicode = str @@ -52,11 +53,13 @@ def parse_options(): "--password", action="store", dest="password", - help="Display debugging information", + help="Password for Active Directory administrator", + sensitive=True ) options, args = parser.parse_args() safe_options = parser.get_safe_opts(options) + admin_cleanup_global_argv(parser, options, sys.argv) # We only use first argument of the passed args but as D-BUS interface # in oddjobd cannot expose optional, we fill in empty slots from IPA side diff --git a/install/tools/ipa-adtrust-install.in b/install/tools/ipa-adtrust-install.in index e7b0e3692..1efccdb67 100644 --- a/install/tools/ipa-adtrust-install.in +++ b/install/tools/ipa-adtrust-install.in @@ -35,7 +35,7 @@ from ipaserver.install.installutils import ( read_password, check_server_configuration, run_script) -from ipapython.admintool import ScriptError +from ipapython.admintool import ScriptError, admin_cleanup_global_argv from ipapython import version from ipapython import ipautil from ipalib import api, errors, krb_utils @@ -93,6 +93,7 @@ def parse_options(): options, _args = parser.parse_args() safe_options = parser.get_safe_opts(options) + admin_cleanup_global_argv(parser, options, sys.argv) return safe_options, options diff --git a/install/tools/ipa-ca-install.in b/install/tools/ipa-ca-install.in index 9f3d16669..b437e761f 100644 --- a/install/tools/ipa-ca-install.in +++ b/install/tools/ipa-ca-install.in @@ -42,6 +42,7 @@ from ipalib.constants import DOMAIN_LEVEL_1 from ipapython.config import IPAOptionParser from ipapython.ipa_log_manager import standard_logging_setup from ipaplatform.paths import paths +from ipapython.admintool import admin_cleanup_global_argv logger = logging.getLogger(os.path.basename(__file__)) @@ -132,6 +133,7 @@ def parse_options(): options, args = parser.parse_args() safe_options = parser.get_safe_opts(options) + admin_cleanup_global_argv(parser, options, sys.argv) if args: parser.error("Too many arguments provided") diff --git a/install/tools/ipa-compat-manage.in b/install/tools/ipa-compat-manage.in index 459f39fc8..9650abd6f 100644 --- a/install/tools/ipa-compat-manage.in +++ b/install/tools/ipa-compat-manage.in @@ -24,13 +24,13 @@ from __future__ import print_function import sys from ipaplatform.paths import paths try: - from optparse import OptionParser # pylint: disable=deprecated-module from ipapython import ipautil, config from ipaserver.install import installutils from ipaserver.install.ldapupdate import LDAPUpdate from ipalib import api, errors from ipapython.ipa_log_manager import standard_logging_setup from ipapython.dn import DN + from ipapython.admintool import admin_cleanup_global_argv except ImportError as e: print("""\ There was a problem importing one of the required Python modules. The @@ -46,7 +46,8 @@ nis_config_dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config')) def parse_options(): usage = "%prog [options] \n" usage += "%prog [options]\n" - parser = OptionParser(usage=usage, formatter=config.IPAFormatter()) + parser = config.IPAOptionParser(usage=usage, + formatter=config.IPAFormatter()) parser.add_option("-d", "--debug", action="store_true", dest="debug", help="Display debugging information about the update(s)") @@ -55,6 +56,7 @@ def parse_options(): config.add_standard_options(parser) options, args = parser.parse_args() + admin_cleanup_global_argv(parser, options, sys.argv) return options, args diff --git a/install/tools/ipa-csreplica-manage.in b/install/tools/ipa-csreplica-manage.in index 6f248cc50..2fab27a94 100644 --- a/install/tools/ipa-csreplica-manage.in +++ b/install/tools/ipa-csreplica-manage.in @@ -32,8 +32,8 @@ from ipaserver.install import (replication, installutils, bindinstance, from ipalib import api, errors from ipalib.constants import FQDN from ipalib.util import has_managed_topology, print_replication_status -from ipapython import ipautil, ipaldap, version -from ipapython.admintool import ScriptError +from ipapython import ipautil, ipaldap, version, config +from ipapython.admintool import admin_cleanup_global_argv, ScriptError from ipapython.dn import DN logger = logging.getLogger(os.path.basename(__file__)) @@ -54,11 +54,10 @@ commands = { def parse_options(): - from optparse import OptionParser # pylint: disable=deprecated-module - - parser = OptionParser(version=version.VERSION) + parser = config.IPAOptionParser(version=version.VERSION) parser.add_option("-H", "--host", dest="host", help="starting host") - parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password") + parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True, + help="Directory Manager password") parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="provide additional information") parser.add_option("-f", "--force", dest="force", action="store_true", default=False, @@ -66,6 +65,7 @@ def parse_options(): parser.add_option("--from", dest="fromhost", help="Host to get data from") options, args = parser.parse_args() + admin_cleanup_global_argv(parser, options, sys.argv) valid_syntax = False diff --git a/install/tools/ipa-managed-entries.in b/install/tools/ipa-managed-entries.in index e3f121943..ff2fd6a58 100644 --- a/install/tools/ipa-managed-entries.in +++ b/install/tools/ipa-managed-entries.in @@ -24,7 +24,6 @@ import logging import os import re import sys -from optparse import OptionParser # pylint: disable=deprecated-module from ipaplatform.paths import paths from ipapython import config @@ -32,6 +31,7 @@ from ipaserver.install import installutils from ipalib import api, errors from ipapython.ipa_log_manager import standard_logging_setup from ipapython.dn import DN +from ipapython.admintool import admin_cleanup_global_argv logger = logging.getLogger(os.path.basename(__file__)) @@ -51,9 +51,10 @@ def parse_options(): action="store_true", help="List available Managed Entries") parser.add_option("-p", "--password", dest="dirman_password", - help="Directory Manager password") + sensitive=True, help="Directory Manager password") options, args = parser.parse_args() + admin_cleanup_global_argv(parser, options, sys.argv) return options, args diff --git a/install/tools/ipa-replica-conncheck.in b/install/tools/ipa-replica-conncheck.in index 8eee82483..81b7d13ac 100644 --- a/install/tools/ipa-replica-conncheck.in +++ b/install/tools/ipa-replica-conncheck.in @@ -23,15 +23,15 @@ from __future__ import print_function import logging from ipapython import ipachangeconf -from ipapython.config import IPAOptionParser +from ipapython.config import (IPAOptionParser, OptionGroup, + OptionValueError) +from ipapython.admintool import admin_cleanup_global_argv from ipapython.dn import DN from ipapython import version from ipapython import ipautil, certdb from ipalib import api, errors, x509 from ipalib.constants import FQDN from ipaserver.install import installutils -# pylint: disable=deprecated-module -from optparse import OptionGroup, OptionValueError # pylint: enable=deprecated-module from ipapython.ipa_log_manager import standard_logging_setup import copy @@ -189,6 +189,7 @@ def parse_options(): options, _args = parser.parse_args() safe_options = parser.get_safe_opts(options) + admin_cleanup_global_argv(parser, options, sys.argv) if options.master and options.replica: parser.error("on-master and on-replica options are mutually exclusive!") diff --git a/install/tools/ipa-replica-manage.in b/install/tools/ipa-replica-manage.in index d6e6ef57c..7e5b31a59 100644 --- a/install/tools/ipa-replica-manage.in +++ b/install/tools/ipa-replica-manage.in @@ -43,6 +43,7 @@ from ipalib.util import ( print_replication_status, verify_host_resolvable, ) +from ipapython.admintool import admin_cleanup_global_argv from ipapython.ipa_log_manager import standard_logging_setup from ipapython.dn import DN from ipapython.config import IPAOptionParser @@ -84,7 +85,8 @@ class NoRUVsFound(Exception): def parse_options(): parser = IPAOptionParser(version=version.VERSION) parser.add_option("-H", "--host", dest="host", help="starting host") - parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password") + parser.add_option("-p", "--password", dest="dirman_passwd", sensitive=True, + help="Directory Manager password") parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="provide additional information") parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, @@ -95,7 +97,7 @@ def parse_options(): help="DANGER: clean up references to a ghost master") parser.add_option("--binddn", dest="binddn", default=None, type="dn", help="Bind DN to use with remote server") - parser.add_option("--bindpw", dest="bindpw", default=None, + parser.add_option("--bindpw", dest="bindpw", default=None, sensitive=True, help="Password for Bind DN to use with remote server") parser.add_option("--winsync", dest="winsync", action="store_true", default=False, help="This is a Windows Sync Agreement") @@ -103,13 +105,15 @@ def parse_options(): help="Full path and filename of CA certificate to use with TLS/SSL to the remote server") parser.add_option("--win-subtree", dest="win_subtree", default=None, help="DN of Windows subtree containing the users you want to sync (default cn=Users, ...', add two args + _argc = len(argv) + 2 + all_options = [] + if '_get_all_options' in dir(option_parser): + # OptParse parser + all_options = option_parser._get_all_options() + elif '_actions' in dir(option_parser): + # ArgParse parser + all_options = option_parser._actions + + for opt in all_options: + if getattr(opt, 'sensitive', False): + v = getattr(options, opt.dest) + for i in range(0, _argc): + vi = ctypes.cast(_argv[i], + ctypes.c_char_p + ).value.decode('utf-8') + if vi == v: + ctypes.memset(_argv[i], ord('X'), len(v)) + except Exception: + pass + + class ScriptError(Exception): """An exception that records an error message and a return value """ @@ -148,6 +187,7 @@ class AdminTool: cls._option_parsers[cls] = cls.option_parser options, args = cls.option_parser.parse_args(argv[1:]) + admin_cleanup_global_argv(cls.option_parser, options, argv) command_class = cls.get_command_class(options, args) command = command_class(options, args) diff --git a/ipaserver/install/ipa_migrate.py b/ipaserver/install/ipa_migrate.py index e21937401..1d1342788 100644 --- a/ipaserver/install/ipa_migrate.py +++ b/ipaserver/install/ipa_migrate.py @@ -28,6 +28,7 @@ from ipaplatform.paths import paths from ipapython.dn import DN from ipapython.ipaldap import LDAPClient, LDAPEntry, realm_to_ldapi_uri from ipapython.ipa_log_manager import standard_logging_setup +from ipapython.admintool import admin_cleanup_global_argv from ipaserver.install.ipa_migrate_constants import ( DS_CONFIG, DB_OBJECTS, DS_INDEXES, BIND_DN, LOG_FILE_NAME, STRIP_OP_ATTRS, STRIP_ATTRS, STRIP_OC, PROD_ATTRS, @@ -284,6 +285,18 @@ class LDIFParser(ldif.LDIFParser): self.mc.process_db_entry(entry_dn=dn, entry_attrs=entry_attrs) +class SensitiveStoreAction(argparse._StoreAction): + def __init__(self, *, sensitive, **options): + super(SensitiveStoreAction, self).__init__(**options) + self.sensitive = sensitive + + def _get_kwargs(self): + names = super(SensitiveStoreAction, self)._get_kwargs() + sensitive_name = 'sensitive' + names.extend((sensitive_name, getattr(self, sensitive_name))) + return names + + # # Migrate IPA to IPA Class # @@ -344,7 +357,8 @@ class IPAMigrate(): help='Password for the Bind DN. If a password ' 'is not provided then the user will be ' 'prompted to enter it', - default=None) + default=None, sensitive=True, + action=SensitiveStoreAction) parser.add_argument('-j', '--bind-pw-file', help='A text file containing the clear text ' 'password for the Bind DN', default=None) @@ -2023,6 +2037,7 @@ class IPAMigrate(): parser = argparse.ArgumentParser(description=desc, allow_abbrev=True) self.add_options(parser) self.validate_options() + admin_cleanup_global_argv(parser, self.args, sys.argv) # Check for dryrun mode if self.args.dryrun or self.args.dryrun_record is not None: diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py index 8d75a0e6b..539501ab4 100644 --- a/ipaserver/install/ipa_restore.py +++ b/ipaserver/install/ipa_restore.py @@ -185,7 +185,7 @@ class Restore(admintool.AdminTool): super(Restore, cls).add_options(parser, debug_option=True) parser.add_option( - "-p", "--password", dest="password", + "-p", "--password", dest="password", sensitive=True, help="Directory Manager password") parser.add_option( "--gpg-keyring", dest="gpg_keyring", diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py index e9f680b1d..76ad37ca7 100644 --- a/ipaserver/install/ipa_server_certinstall.py +++ b/ipaserver/install/ipa_server_certinstall.py @@ -72,7 +72,7 @@ class ServerCertInstall(admintool.AdminTool): help="Name of the certificate to install") parser.add_option( "-p", "--dirman-password", - dest="dirman_password", + dest="dirman_password", sensitive=True, help="Directory Manager password") def validate_options(self):