diff options
| author | Simeon Simeonov | 2022-03-29 20:44:03 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2022-03-29 20:44:03 +0200 |
| commit | f19fde48c6b3f65c164c931286e72a0d254c1fb3 (patch) | |
| tree | 5b6c1bf6cef51c852c49abff3a0e4626e8a33146 /otp2289 | |
| parent | 12c5e38691b24d12a8fc9605e3b93fac86d461ae (diff) | |
Add the -P param and improve tests
Diffstat (limited to 'otp2289')
| -rw-r--r-- | otp2289/__init__.py | 2 | ||||
| -rw-r--r-- | otp2289/__main__.py | 105 |
2 files changed, 74 insertions, 33 deletions
diff --git a/otp2289/__init__.py b/otp2289/__init__.py index 608595b..59694a7 100644 --- a/otp2289/__init__.py +++ b/otp2289/__init__.py | |||
| @@ -40,7 +40,7 @@ from .server import ( | |||
| 40 | ) | 40 | ) |
| 41 | 41 | ||
| 42 | __author__ = 'Simeon Simeonov' | 42 | __author__ = 'Simeon Simeonov' |
| 43 | __version__ = '1.1.0-beta1' | 43 | __version__ = '1.1.0' |
| 44 | __license__ = 'BSD 2-Clause' | 44 | __license__ = 'BSD 2-Clause' |
| 45 | 45 | ||
| 46 | 46 | ||
diff --git a/otp2289/__main__.py b/otp2289/__main__.py index 471ae24..78e60e8 100644 --- a/otp2289/__main__.py +++ b/otp2289/__main__.py | |||
| @@ -135,6 +135,48 @@ def generate_otp_range(args: argparse.Namespace) -> str: | |||
| 135 | ) | 135 | ) |
| 136 | 136 | ||
| 137 | 137 | ||
| 138 | def get_password(args: argparse.Namespace) -> str: | ||
| 139 | """ | ||
| 140 | Extract the provided password using the defined argparse arguments | ||
| 141 | |||
| 142 | :param args: The arguments assigned from argparse | ||
| 143 | :type args: argparse.Namespace | ||
| 144 | |||
| 145 | :raises KeyboardInterrupt: If the password prompt is interrupted | ||
| 146 | |||
| 147 | :return: The extrated password string | ||
| 148 | :rtype: str | ||
| 149 | """ | ||
| 150 | if args.force_password_prompt: | ||
| 151 | while True: | ||
| 152 | password = getpass.getpass() | ||
| 153 | if not args.initiate_new_sequence or password == getpass.getpass( | ||
| 154 | 'Repeat password: ' | ||
| 155 | ): | ||
| 156 | break | ||
| 157 | eprint('The passwords do not match') | ||
| 158 | return password | ||
| 159 | |||
| 160 | if not args.password: | ||
| 161 | password = os.environ.get('OTP2289_PASSWORD') | ||
| 162 | if password is not None: | ||
| 163 | return password | ||
| 164 | while True: | ||
| 165 | password = getpass.getpass() | ||
| 166 | if not args.initiate_new_sequence or password == getpass.getpass( | ||
| 167 | 'Repeat password: ' | ||
| 168 | ): | ||
| 169 | break | ||
| 170 | eprint('The passwords do not match') | ||
| 171 | return password | ||
| 172 | |||
| 173 | if os.path.isfile(args.password): | ||
| 174 | with io.open(args.password, 'r', encoding='utf-8') as fp: | ||
| 175 | return fp.readline().strip() | ||
| 176 | |||
| 177 | return args.password | ||
| 178 | |||
| 179 | |||
| 138 | def get_rnd_seed() -> str: | 180 | def get_rnd_seed() -> str: |
| 139 | """ | 181 | """ |
| 140 | Returns a random seed in the format: | 182 | Returns a random seed in the format: |
| @@ -192,6 +234,7 @@ def main(args=None): | |||
| 192 | description='The following options are available', | 234 | description='The following options are available', |
| 193 | ) | 235 | ) |
| 194 | group = parser.add_mutually_exclusive_group(required=True) | 236 | group = parser.add_mutually_exclusive_group(required=True) |
| 237 | password_group = parser.add_mutually_exclusive_group() | ||
| 195 | group.add_argument( | 238 | group.add_argument( |
| 196 | '--generate-otp-range', | 239 | '--generate-otp-range', |
| 197 | action='store_true', | 240 | action='store_true', |
| @@ -217,6 +260,28 @@ def main(args=None): | |||
| 217 | 'and always outputs hex (ignores -f).' | 260 | 'and always outputs hex (ignores -f).' |
| 218 | ), | 261 | ), |
| 219 | ) | 262 | ) |
| 263 | password_group.add_argument( | ||
| 264 | '-P', | ||
| 265 | '--force-password-prompt', | ||
| 266 | dest='force_password_prompt', | ||
| 267 | action='store_true', | ||
| 268 | help=( | ||
| 269 | 'Force password prompt even if the env. variable ' | ||
| 270 | '"OTP2289_PASSWORD" is set' | ||
| 271 | ), | ||
| 272 | ) | ||
| 273 | password_group.add_argument( | ||
| 274 | '-p', | ||
| 275 | '--password', | ||
| 276 | metavar='<PASSWORD[FILE]>', | ||
| 277 | type=str, | ||
| 278 | dest='password', | ||
| 279 | default='', | ||
| 280 | help=( | ||
| 281 | 'The password or path to password file ' | ||
| 282 | '(default & recommended: prompt for passwd)' | ||
| 283 | ), | ||
| 284 | ) | ||
| 220 | parser.add_argument( | 285 | parser.add_argument( |
| 221 | '-a', | 286 | '-a', |
| 222 | '--hash-algorithm', | 287 | '--hash-algorithm', |
| @@ -254,18 +319,6 @@ def main(args=None): | |||
| 254 | help='The step. Default for initiating a new sequence is: 500', | 319 | help='The step. Default for initiating a new sequence is: 500', |
| 255 | ) | 320 | ) |
| 256 | parser.add_argument( | 321 | parser.add_argument( |
| 257 | '-p', | ||
| 258 | '--password', | ||
| 259 | metavar='<PASSWORD[FILE]>', | ||
| 260 | type=str, | ||
| 261 | dest='password', | ||
| 262 | default='', | ||
| 263 | help=( | ||
| 264 | 'The password or path to password file ' | ||
| 265 | '(default & recommended: prompt for passwd)' | ||
| 266 | ), | ||
| 267 | ) | ||
| 268 | parser.add_argument( | ||
| 269 | '-q', | 322 | '-q', |
| 270 | '--quiet', | 323 | '--quiet', |
| 271 | action='store_true', | 324 | action='store_true', |
| @@ -303,26 +356,14 @@ def main(args=None): | |||
| 303 | ) | 356 | ) |
| 304 | args = parser.parse_args(args) | 357 | args = parser.parse_args(args) |
| 305 | # handle the password before everything else | 358 | # handle the password before everything else |
| 306 | if not args.password: | 359 | try: |
| 307 | try: | 360 | args.password = get_password(args) |
| 308 | while True: | 361 | except KeyboardInterrupt: |
| 309 | args.password = getpass.getpass() | 362 | eprint(os.linesep + 'Prompt terminated') |
| 310 | if ( | 363 | sys.exit(errno.EACCES) |
| 311 | not args.initiate_new_sequence | 364 | except Exception as exp: |
| 312 | or args.password == getpass.getpass('Repeat password: ') | 365 | eprint(f'Unable to fetch password: {exp}') |
| 313 | ): | 366 | sys.exit(1) |
| 314 | break | ||
| 315 | eprint('The passwords do not match') | ||
| 316 | except KeyboardInterrupt: | ||
| 317 | eprint(os.linesep + 'Prompt terminated') | ||
| 318 | sys.exit(errno.EACCES) | ||
| 319 | elif os.path.isfile(args.password): | ||
| 320 | try: | ||
| 321 | with io.open(args.password, 'r', encoding='utf-8') as fp: | ||
| 322 | args.password = fp.readline().strip() | ||
| 323 | except Exception as exp: | ||
| 324 | eprint(f'Unable to open password file: {exp}') | ||
| 325 | sys.exit(1) | ||
| 326 | try: | 367 | try: |
| 327 | if args.initiate_new_sequence: | 368 | if args.initiate_new_sequence: |
| 328 | print(initiate_new_sequence(args)) | 369 | print(initiate_new_sequence(args)) |
