callback=self._set_krb5_ccache)
self.creds = Credentials()
+ def _ensure_secure_proctitle(self, opt_str, secret_data, data_type="password"):
+ """ Make sure no sensitive data (e.g. password) resides in proctitle. """
+ import re
+ try:
+ import setproctitle
+ except ModuleNotFoundError:
+ msg = ("WARNING: Using %s on command line is insecure. "
+ "Please install the setproctitle python module.\n"
+ % data_type)
+ sys.stderr.write(msg)
+ sys.stderr.flush()
+ return False
+ # Regex to search and replace secret data + option with.
+ # .*[ ]+ -> Before the option must be one or more spaces.
+ # [= ] -> The option and the secret data might be separated by space
+ # or equal sign.
+ # [ ]*.* -> After the secret data might be one, many or no space.
+ pass_opt_re_str = "(.*[ ]+)(%s[= ]%s)([ ]*.*)" % (opt_str, secret_data)
+ pass_opt_re = re.compile(pass_opt_re_str)
+ # Get current proctitle.
+ cur_proctitle = setproctitle.getproctitle()
+ # Make sure we build the correct regex.
+ if not pass_opt_re.match(cur_proctitle):
+ msg = ("Unable to hide %s in proctitle. This is most likely "
+ "a bug!\n" % data_type)
+ sys.stderr.write(msg)
+ sys.stderr.flush()
+ return False
+ # String to replace secret data with.
+ secret_data_replacer = "xxx"
+ # Build string to replace secret data and option with. And as we dont
+ # want to change anything else than the secret data within the proctitle
+ # we have to check if the option was passed with space or equal sign as
+ # separator.
+ opt_pass_with_eq = "%s=%s" % (opt_str, secret_data)
+ opt_pass_part = re.sub(pass_opt_re_str, r'\2', cur_proctitle)
+ if opt_pass_part == opt_pass_with_eq:
+ replace_str = "%s=%s" % (opt_str, secret_data_replacer)
+ else:
+ replace_str = "%s %s" % (opt_str, secret_data_replacer)
+ # Build new proctitle:
+ new_proctitle = re.sub(pass_opt_re_str,
+ r'\1' + replace_str + r'\3',
+ cur_proctitle)
+ # Set new proctitle.
+ setproctitle.setproctitle(new_proctitle)
+
def _add_option(self, *args1, **kwargs):
if self.special_name is None:
return self.add_option(*args1, **kwargs)
self.creds.set_domain(arg)
def _set_password(self, option, opt_str, arg, parser):
+ self._ensure_secure_proctitle(opt_str, arg, "password")
self.creds.set_password(arg)
self.ask_for_password = False
self.machine_pass = False