opennel-pymanager/pymanager/password.py
2018-02-05 23:08:24 +01:00

136 lines
4.8 KiB
Python
Executable file

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# script to manipulate password file
#
# Copyright (C) 2017 AleaJactaEst
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import bcrypt
import argparse
import sys
import os
import getpass
__VERSION__ = '1.0'
class PasswordFile:
def __init__(self, passwordfile, createfile, password_comand_line, username, password):
self.passwordfile = passwordfile
self.users = {}
if not password_comand_line:
if password is not None:
raise Exception("password in command line (but option disable to read this password).")
else:
self.password = None
elif password is None:
raise Exception("Missing password.")
else:
self.password = password
self.username = username
if not os.path.exists(self.passwordfile):
if createfile:
with open(self.passwordfile, 'wt', encoding='utf-8') as fp:
fp.write('\n')
else:
raise Exception("%s does not exist." % self.passwordfile)
else:
self.__load__()
def __load__(self):
with open(self.passwordfile, 'rt') as fp:
for line in fp:
line = line.strip()
if not line:
continue
username, password = line.split(':', maxsplit=1)
self.users.setdefault(username, password)
def save(self):
with open(self.passwordfile, 'wt', encoding='utf-8') as fp:
for user in sorted(self.users):
fp.write('%s:%s\n' % (user, self.users[user]))
def update(self):
if self.password is None:
self.password = getpass.getpass('New password:')
check = getpass.getpass('Re-type new password:')
if self.password != check:
raise Exception("password verification error")
hashed_password = bcrypt.hashpw(self.password.encode('utf-8'), bcrypt.gensalt()).decode('utf8')
self.users[self.username] = hashed_password
print("Adding password for user %s" % self.username)
def verify(self):
if self.password is None:
self.password = getpass.getpass('Enter password:')
if bcrypt.checkpw(self.password.encode('utf-8'), self.users[self.username].encode('utf-8')):
print("Password for user %s correct." % self.username)
else:
raise Exception("password verification failed.")
def delete(self):
if self.username in self.users:
del self.users[self.username]
def root(passwordfile, create, password_comand_line, username, password, delete, verify):
pf = PasswordFile(passwordfile, create, password_comand_line, username, password)
if delete:
pf.delete()
pf.save()
elif verify:
pf.verify()
else:
pf.update()
pf.save()
def main(args=sys.argv[1:]):
""" Main function
:param list args: root password
"""
parser = argparse.ArgumentParser(description='password manager')
parser.add_argument('--version', action='version', version='%(prog)s ' + __VERSION__)
parser.add_argument('-c', '--create', action='store_true',
help='create a new file', default=False)
parser.add_argument('-D', '--delete', action='store_true',
help='delete username', default=False)
parser.add_argument('-v', '--verify', action='store_true',
help='Verify password for the specified user.', default=False)
parser.add_argument('-b', '--password-comand-line', action='store_true',
help='Use the password from the command line rather than prompting for it.',
default=False)
parser.add_argument('passwordfile', type=str, help='file contains all password')
parser.add_argument('username', type=str)
parser.add_argument('password', type=str, nargs='?')
param = parser.parse_args(args)
root(param.passwordfile,
param.create,
param.password_comand_line,
param.username,
param.password,
param.delete, param.verify)
if __name__ == '__main__':
main()