[2] | 1 | """Utilities to get a password and/or the current user name.
|
---|
| 2 |
|
---|
| 3 | getpass(prompt[, stream]) - Prompt for a password, with echo turned off.
|
---|
| 4 | getuser() - Get the user name from the environment or password database.
|
---|
| 5 |
|
---|
| 6 | GetPassWarning - This UserWarning is issued when getpass() cannot prevent
|
---|
| 7 | echoing of the password contents while reading.
|
---|
| 8 |
|
---|
| 9 | On Windows, the msvcrt module will be used.
|
---|
| 10 | On the Mac EasyDialogs.AskPassword is used, if available.
|
---|
| 11 |
|
---|
| 12 | """
|
---|
| 13 |
|
---|
| 14 | # Authors: Piers Lauder (original)
|
---|
| 15 | # Guido van Rossum (Windows support and cleanup)
|
---|
| 16 | # Gregory P. Smith (tty support & GetPassWarning)
|
---|
| 17 |
|
---|
| 18 | import os, sys, warnings
|
---|
| 19 |
|
---|
| 20 | __all__ = ["getpass","getuser","GetPassWarning"]
|
---|
| 21 |
|
---|
| 22 |
|
---|
| 23 | class GetPassWarning(UserWarning): pass
|
---|
| 24 |
|
---|
| 25 |
|
---|
| 26 | def unix_getpass(prompt='Password: ', stream=None):
|
---|
| 27 | """Prompt for a password, with echo turned off.
|
---|
| 28 |
|
---|
| 29 | Args:
|
---|
| 30 | prompt: Written on stream to ask for the input. Default: 'Password: '
|
---|
| 31 | stream: A writable file object to display the prompt. Defaults to
|
---|
| 32 | the tty. If no tty is available defaults to sys.stderr.
|
---|
| 33 | Returns:
|
---|
| 34 | The seKr3t input.
|
---|
| 35 | Raises:
|
---|
| 36 | EOFError: If our input tty or stdin was closed.
|
---|
| 37 | GetPassWarning: When we were unable to turn echo off on the input.
|
---|
| 38 |
|
---|
| 39 | Always restores terminal settings before returning.
|
---|
| 40 | """
|
---|
| 41 | fd = None
|
---|
| 42 | tty = None
|
---|
| 43 | try:
|
---|
| 44 | # Always try reading and writing directly on the tty first.
|
---|
| 45 | fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
|
---|
| 46 | tty = os.fdopen(fd, 'w+', 1)
|
---|
| 47 | input = tty
|
---|
| 48 | if not stream:
|
---|
| 49 | stream = tty
|
---|
| 50 | except EnvironmentError, e:
|
---|
| 51 | # If that fails, see if stdin can be controlled.
|
---|
| 52 | try:
|
---|
| 53 | fd = sys.stdin.fileno()
|
---|
[391] | 54 | except (AttributeError, ValueError):
|
---|
[2] | 55 | passwd = fallback_getpass(prompt, stream)
|
---|
| 56 | input = sys.stdin
|
---|
| 57 | if not stream:
|
---|
| 58 | stream = sys.stderr
|
---|
| 59 |
|
---|
| 60 | if fd is not None:
|
---|
| 61 | passwd = None
|
---|
| 62 | try:
|
---|
| 63 | old = termios.tcgetattr(fd) # a copy to save
|
---|
| 64 | new = old[:]
|
---|
[391] | 65 | new[3] &= ~termios.ECHO # 3 == 'lflags'
|
---|
[2] | 66 | tcsetattr_flags = termios.TCSAFLUSH
|
---|
| 67 | if hasattr(termios, 'TCSASOFT'):
|
---|
| 68 | tcsetattr_flags |= termios.TCSASOFT
|
---|
| 69 | try:
|
---|
| 70 | termios.tcsetattr(fd, tcsetattr_flags, new)
|
---|
| 71 | passwd = _raw_input(prompt, stream, input=input)
|
---|
| 72 | finally:
|
---|
| 73 | termios.tcsetattr(fd, tcsetattr_flags, old)
|
---|
| 74 | stream.flush() # issue7208
|
---|
| 75 | except termios.error, e:
|
---|
| 76 | if passwd is not None:
|
---|
| 77 | # _raw_input succeeded. The final tcsetattr failed. Reraise
|
---|
| 78 | # instead of leaving the terminal in an unknown state.
|
---|
| 79 | raise
|
---|
| 80 | # We can't control the tty or stdin. Give up and use normal IO.
|
---|
| 81 | # fallback_getpass() raises an appropriate warning.
|
---|
| 82 | del input, tty # clean up unused file objects before blocking
|
---|
| 83 | passwd = fallback_getpass(prompt, stream)
|
---|
| 84 |
|
---|
| 85 | stream.write('\n')
|
---|
| 86 | return passwd
|
---|
| 87 |
|
---|
| 88 |
|
---|
| 89 | def win_getpass(prompt='Password: ', stream=None):
|
---|
| 90 | """Prompt for password with echo off, using Windows getch()."""
|
---|
| 91 | if sys.stdin is not sys.__stdin__:
|
---|
| 92 | return fallback_getpass(prompt, stream)
|
---|
| 93 | import msvcrt
|
---|
| 94 | for c in prompt:
|
---|
| 95 | msvcrt.putch(c)
|
---|
| 96 | pw = ""
|
---|
| 97 | while 1:
|
---|
| 98 | c = msvcrt.getch()
|
---|
| 99 | if c == '\r' or c == '\n':
|
---|
| 100 | break
|
---|
| 101 | if c == '\003':
|
---|
| 102 | raise KeyboardInterrupt
|
---|
| 103 | if c == '\b':
|
---|
| 104 | pw = pw[:-1]
|
---|
| 105 | else:
|
---|
| 106 | pw = pw + c
|
---|
| 107 | msvcrt.putch('\r')
|
---|
| 108 | msvcrt.putch('\n')
|
---|
| 109 | return pw
|
---|
| 110 |
|
---|
| 111 |
|
---|
| 112 | def fallback_getpass(prompt='Password: ', stream=None):
|
---|
| 113 | warnings.warn("Can not control echo on the terminal.", GetPassWarning,
|
---|
| 114 | stacklevel=2)
|
---|
| 115 | if not stream:
|
---|
| 116 | stream = sys.stderr
|
---|
| 117 | print >>stream, "Warning: Password input may be echoed."
|
---|
| 118 | return _raw_input(prompt, stream)
|
---|
| 119 |
|
---|
| 120 |
|
---|
| 121 | def _raw_input(prompt="", stream=None, input=None):
|
---|
| 122 | # A raw_input() replacement that doesn't save the string in the
|
---|
| 123 | # GNU readline history.
|
---|
| 124 | if not stream:
|
---|
| 125 | stream = sys.stderr
|
---|
| 126 | if not input:
|
---|
| 127 | input = sys.stdin
|
---|
| 128 | prompt = str(prompt)
|
---|
| 129 | if prompt:
|
---|
| 130 | stream.write(prompt)
|
---|
| 131 | stream.flush()
|
---|
| 132 | # NOTE: The Python C API calls flockfile() (and unlock) during readline.
|
---|
| 133 | line = input.readline()
|
---|
| 134 | if not line:
|
---|
| 135 | raise EOFError
|
---|
| 136 | if line[-1] == '\n':
|
---|
| 137 | line = line[:-1]
|
---|
| 138 | return line
|
---|
| 139 |
|
---|
| 140 |
|
---|
| 141 | def getuser():
|
---|
| 142 | """Get the username from the environment or password database.
|
---|
| 143 |
|
---|
| 144 | First try various environment variables, then the password
|
---|
| 145 | database. This works on Windows as long as USERNAME is set.
|
---|
| 146 |
|
---|
| 147 | """
|
---|
| 148 |
|
---|
| 149 | import os
|
---|
| 150 |
|
---|
| 151 | for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
|
---|
| 152 | user = os.environ.get(name)
|
---|
| 153 | if user:
|
---|
| 154 | return user
|
---|
| 155 |
|
---|
| 156 | # If this fails, the exception will "explain" why
|
---|
| 157 | import pwd
|
---|
| 158 | return pwd.getpwuid(os.getuid())[0]
|
---|
| 159 |
|
---|
| 160 | # Bind the name getpass to the appropriate function
|
---|
| 161 | try:
|
---|
| 162 | import termios
|
---|
| 163 | # it's possible there is an incompatible termios from the
|
---|
| 164 | # McMillan Installer, make sure we have a UNIX-compatible termios
|
---|
| 165 | termios.tcgetattr, termios.tcsetattr
|
---|
| 166 | except (ImportError, AttributeError):
|
---|
| 167 | try:
|
---|
| 168 | import msvcrt
|
---|
| 169 | except ImportError:
|
---|
| 170 | try:
|
---|
| 171 | from EasyDialogs import AskPassword
|
---|
| 172 | except ImportError:
|
---|
| 173 | getpass = fallback_getpass
|
---|
| 174 | else:
|
---|
| 175 | getpass = AskPassword
|
---|
| 176 | else:
|
---|
| 177 | getpass = win_getpass
|
---|
| 178 | else:
|
---|
| 179 | getpass = unix_getpass
|
---|