#!/usr/bin/python # author: nishiki # mail: nishiki@yaegashi.fr # date: 16/06/2013 # info: a simple script who manage your passwords import csv import re import os import sys import gnupg import getpass import StringIO import tempfile import time import datetime FILE_GPG = '/home/nishiki/.password-manager' KEY = 'nishiki@yaegashi.fr' FILE_PWD = '/tmp/.tmp_passwd' TIMEOUT_PWD = 300 class ManagePasswd: ID = 0 TYPE = 1 SERVER = 2 LOGIN = 3 PASSWD = 4 PORT = 5 COMMENT = 6 def __init__(self, key, file_gpg, file_pwd, timeout_pwd=300): self.KEY = key self.FILE_PWD = file_pwd self.FILE_GPG = file_gpg self.TIMEOUT_PWD = timeout_pwd if os.path.isfile(self.FILE_GPG): self.decrypt() else: self.data = '' def __del__(self): try: self.file_tmp_name except: self.file_tmp_name = '' if os.path.isfile(self.file_tmp_name): os.remove(self.file_tmp_name) # Decrypt a gpg file # @rtrn: true if data is decrypted def decrypt(self): gpg = gnupg.GPG(verbose=False) # Manage the passphrase if os.path.isfile(self.FILE_PWD): stat_file = os.stat(self.FILE_PWD) if stat_file.st_mtime + self.TIMEOUT_PWD < time.time(): open(self.FILE_PWD, 'w').close() else: open(self.FILE_PWD, 'w').close() file_pwd = open(self.FILE_PWD, 'r+') os.chmod(self.FILE_PWD, 0600) passwd = file_pwd.readline() if not passwd: passwd = getpass.getpass('Password GPG: ') file_pwd.write(passwd) file_pwd.close() file_gpg = open(self.FILE_GPG, 'rb') self.data = gpg.decrypt_file(file_gpg, passphrase=passwd) file_gpg.close() if not self.data.ok: print 'Error: Your passphrase is probably wrong!' os.remove(self.FILE_PWD) return False else: os.utime(self.FILE_PWD, None) return True # Encrypt a file def encrypt(self): if os.path.isfile(self.file_tmp_name): self.file_tmp.close() os.system('gpg -r ' + self.KEY + ' --yes --output ' + self.FILE_GPG + ' --encrypt ' + self.file_tmp_name) return True else: return False # Search in some csv data # @args: search -> the string to search # type -> the connection type (ssh, web, other) # @rtrn: a list with the resultat of the search def search(self, search, type=''): result = list() regex = re.compile('^.*' + search + '.*$') regex_type = re.compile('^' + type + '$') file_csv = StringIO.StringIO(self.data) reader = csv.reader(file_csv, delimiter=';', quotechar='|') for row in reader: if regex.match(row[self.SERVER]) or regex.match(row[self.COMMENT]): if type == '': result.append(row) else: if regex_type.match(row[self.TYPE]): result.append(row) file_csv.close() return result # Search an id in some csv data # @args: id -> the string to search # @rtrn: the resultat of the search or false def searchId(self, id): result = list() file_csv = StringIO.StringIO(self.data) reader = csv.reader(file_csv, delimiter=';', quotechar='|') for row in reader: if row[self.ID] == id: file_csv.close() return row file_csv.close() return False # Connect to ssh and display the password # @args: search -> def ssh(self, search): result = self.search(search, 'ssh') num = len(result) if num > 0: for i in range(num): server = result[i][self.SERVER] login = result[i][self.LOGIN] port = result[i][self.PORT] passwd = result[i][self.PASSWD] if passwd: os.system('sshpass -p ' + passwd + ' ssh ' + login + '@' + server + ' -p ' + str(port)) else: os.system('ssh ' + login + '@' + server + ' -p ' + str(port)) else: print 'No result!' # Display the connections informations for a server def display(self, search, type=''): result = self.search(search, type) num = len(result) if num > 0: for i in range(num): print '# --------------------' print '# Id: ' + result[i][self.ID] print '# Server: ' + result[i][self.SERVER] print '# Type: ' + result[i][self.TYPE] print '# Login: ' + result[i][self.LOGIN] print '# Password: ' + result[i][self.PASSWD] print '# Port: ' + result[i][self.PORT] print '# Comment: ' + result[i][self.COMMENT] else: print 'No result!' # Display help def help(self): print '# HELP' print '# --------------------' print 'Add a new item: -a' print 'Remove an item: -r ID' print 'Show a item: -d search [type]' print 'Connect ssh: -s search' # Add a new item def add(self): print '# Add a new password' print '# --------------------' id = hex(int(time.time())) server = raw_input('Enter the server name or ip: ') type = raw_input('Enter the type of connection (ssh, web, other): ') login = raw_input('Enter the login connection: ') passwd = raw_input('Enter the the password: ') port = raw_input('Enter the connection port (optinal): ') comment = raw_input('Enter a comment (optinal): ') self.generateTmpFile() writer = csv.writer(self.file_tmp, delimiter=';', quotechar='|') file_csv = StringIO.StringIO(self.data) reader = csv.reader(file_csv, delimiter=';', quotechar='|') for row in reader: writer.writerow(row) file_csv.close() writer.writerow([id, type, server, login, passwd, port, comment]) print 'Item has been added!' # Remove an item # @args: id -> the unique identifiant def remove(self, id): self.generateTmpFile() writer = csv.writer(self.file_tmp, delimiter=';', quotechar='|') file_csv = StringIO.StringIO(self.data) reader = csv.reader(file_csv, delimiter=';', quotechar='|') for row in reader: if row[self.ID] != id: writer.writerow(row) else: print 'The item has been removed!' file_csv.close() # Update an item # @args: id -> the item identifiant def update(self, id): result = self.searchId(id) print '# Add a new password' print '# --------------------' id = result[self.ID] server = raw_input('Enter the server name or ip [' + result[self.SERVER] + ']: ') type = raw_input('Enter the type of connection [' + result[self.TYPE] + ']: ') login = raw_input('Enter the login connection [' + result[self.LOGIN] + ']: ') passwd = raw_input('Enter the the password: ') port = raw_input('Enter the connection port [' + result[self.PORT] + ']: ') comment = raw_input('Enter a comment [' + result[self.COMMENT]+ ']: ') if not server: server = result[self.SERVER] if not login: login = result[self.LOGIN] if not type: type = result[self.TYPE] if not passwd: passwd = result[self.PASSWD] if not port: port = result[self.PORT] if not comment: comment = result[self.COMMENT] self.generateTmpFile() writer = csv.writer(self.file_tmp, delimiter=';', quotechar='|') file_csv = StringIO.StringIO(self.data) reader = csv.reader(file_csv, delimiter=';', quotechar='|') for row in reader: if row[self.ID] != id: writer.writerow(row) writer.writerow([id, type, server, login, passwd, port, comment]) file_csv.close() print 'Item has been updated!' # Generate a temporary file def generateTmpFile(self): try: self.file_tmp_name except: self.file_tmp_name = '' if not os.path.isfile(self.file_tmp_name): (file_tmp_fd, self.file_tmp_name) = tempfile.mkstemp() self.file_tmp = os.fdopen(file_tmp_fd, 'r+') return True else: try: self.file_tmp = open(file_tmp_name, 'r+') return True except: return False ################ # BEGIN SCRIPT # ################ num_argv = len(sys.argv) manage = ManagePasswd(KEY, FILE_GPG, FILE_PWD, TIMEOUT_PWD) # Display the item's informations if num_argv >= 3 and sys.argv[1] == '-d': if num_argv == 4: manage.display(sys.argv[2], sys.argv[3]) else: manage.display(sys.argv[2]) # Remove an item elif num_argv == 3 and sys.argv[1] == '-r': manage.remove(sys.argv[2]) manage.encrypt() # Update an item elif num_argv == 3 and sys.argv[1] == '-u': manage.update(sys.argv[2]) manage.encrypt() # Connect to ssh elif num_argv == 3 and sys.argv[1] == '-s': manage.ssh(sys.argv[2]) # Add a new item elif num_argv == 2 and sys.argv[1] == '-a': manage.add() manage.encrypt() # Display help else: manage.help()