summaryrefslogtreecommitdiff
path: root/otp2289
diff options
context:
space:
mode:
Diffstat (limited to 'otp2289')
-rw-r--r--otp2289/__init__.py2
-rw-r--r--otp2289/__main__.py105
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
138def 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
138def get_rnd_seed() -> str: 180def 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))