Source code for dispass.cli

'''Handling of password input and printing passphrases (using ncurses)'''

# Copyright (c) 2012-2016  Tom Willemse <tom@ryuslash.org>
# Copyright (c) 2011-2018  Benjamin Althues <benjamin@babab.nl>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import getpass

from dispass.algos import algoObject
from dispass.dispass import versionStr

try:
    import curses
    hasCurses = True
except ImportError:
    hasCurses = False


[docs]class CLI: '''Command Line Interface handling''' verifyPassword = False '''Boolean. Prompt for password twice and save label to labelfile''' scriptableIO = False '''Boolean. Optimize input/output for wrapping dispass''' passphrases = {} '''Dict of labels and generated passphrases''' def __init__(self, filehandler): '''Set `useCurses` to True or False. Depending on the availability of curses ''' self.filehandler = filehandler self.useCurses = hasCurses
[docs] def setCurses(self, useCurses): '''Optionally override `self.useCurses` Instead of setting the instance variable `self.useCurses` directly, a setter is used to ensure it can only be set to `True` if the curses library is supported. :Parameters: - `useCurses`: Boolean ''' if useCurses and not hasCurses: self.useCurses = False else: self.useCurses = useCurses
[docs] def passwordPrompt(self): '''Prompt for password Use the `getpass.getpass` function to ask the user for the password and ensure it is 8 characters. The password will be asked twice if `self.verifyPassword` == `True`. :Return: Password string. ''' while True: inp = getpass.getpass() if len(inp) < 8: print('Password must contain at least 8 characters.' 'Please try again.') continue if self.verifyPassword: inp2 = getpass.getpass("Password (again): ") if inp == inp2: break else: print('Passwords do not match. Please try again.') else: break return inp
[docs] def generate(self, password, labeltup): '''Generate passphrase and store result in `passphrases` :Parameters: - `password`: Password to use for passphrase generation - `labeltup`: A tuple `labeltup` with 5 values: * `label`: Label to use for passphrase generation * `length`: Length to use for passphrase generation * `algo`: Algorithm to use for passphrase generation * `seqno`: Sequence number to use for passphrase generation * `disabled`: Whether or not the label is disabled ''' label = labeltup[0] length = labeltup[1] algo = labeltup[2] seqno = labeltup[3] hasher = algoObject(algo) if hasher: self.passphrases.update({label: hasher.digest( label, password, length, seqno )})
[docs] def output(self): '''Output and flush passphrase(s)''' if not self.passphrases: return False divlen = len(max(self.passphrases.keys(), key=len)) + 2 if self.useCurses: stdscr = curses.initscr() curses.noecho() curses.cbreak() stdscr.addstr(0, 0, versionStr + " - press 'q' to quit", curses.A_BOLD) stdscr.addstr(1, 0, "Your passphrase(s)", curses.A_BOLD) j = 3 for label, passphrase in self.passphrases.items(): stdscr.addstr(j, 0, label, curses.A_BOLD) stdscr.addstr(j, divlen, passphrase) j += 1 stdscr.refresh() curses.curs_set(0) try: while True: c = stdscr.getch() if c == ord('q'): break finally: stdscr.erase() curses.nocbreak() curses.echo() curses.endwin() else: for label, passphrase in self.passphrases.items(): if self.scriptableIO: print('{:50} {}'.format(label[:50], passphrase)) else: print('{:{fill}} {}' .format(label, passphrase, fill=divlen)) self.passphrases = {} return True