PM/Password.pm

212 lines
4.5 KiB
Perl
Raw Normal View History

2014-04-27 03:46:32 +04:00
package Password;
use strict;
use warnings;
use utf8;
2014-04-27 23:11:52 +04:00
use Database;
2014-04-28 16:14:23 +04:00
use GPG;
2014-04-27 03:46:32 +04:00
2015-07-10 12:55:59 +03:00
use Digest::MD5;
use MIME::Base64;
2014-05-06 00:40:26 +04:00
# Debug
use Data::Dumper;
2014-04-27 03:46:32 +04:00
sub new {
2014-04-28 12:17:17 +04:00
my $class = shift;
2014-04-27 03:46:32 +04:00
2014-04-28 16:14:23 +04:00
my $db = Database->new();
my $gpg = GPG->new( $ENV{HOME} );
2014-04-28 12:04:17 +04:00
2014-04-28 12:17:17 +04:00
my $self = {
2014-04-29 15:45:31 +04:00
_db => $db,
_gpg => $gpg,
2014-04-27 03:46:32 +04:00
};
2014-04-28 12:17:17 +04:00
2014-04-27 03:46:32 +04:00
bless $self, $class;
return $self;
}
2014-04-28 16:14:23 +04:00
sub show {
2015-04-10 12:50:56 +03:00
my ( $self, $name, $username, $g ) = @_;
2014-04-28 16:14:23 +04:00
my $db_class = $self->{_db};
my $gpg = $self->{_gpg};
# Decrypt db
my $dec_db_file = $gpg->decrypt_db();
# Query
2014-05-06 15:18:34 +04:00
my $query_string;
2015-04-10 12:50:56 +03:00
if ( defined($username) and !($g)) {
2014-05-12 13:46:23 +04:00
$query_string = "select id, name, resource, password from passwords
2014-05-06 15:18:34 +04:00
where name='$name' and username='$username'";
}
2015-04-10 12:50:56 +03:00
# Fasthack
elsif ( defined($g)) {
$query_string = "select id, name, `group`, resource, username, comment from passwords where `group`='$g'";
}
2014-05-06 15:18:34 +04:00
else {
$query_string
2014-05-12 13:46:23 +04:00
= "select id, name, resource, password from passwords where name='$name'";
2014-05-06 15:18:34 +04:00
}
2014-04-28 16:14:23 +04:00
2015-04-10 12:50:56 +03:00
my $mdo_q;
$mdo_q = {
2014-04-28 16:14:23 +04:00
file => $dec_db_file,
query => $query_string,
name => $name,
type => 'select',
};
2015-04-10 12:50:56 +03:00
$mdo_q = {
file => $dec_db_file,
query => $query_string,
name => $name,
type => 'select',
group => $g,
} if $g;
2014-04-28 16:14:23 +04:00
my $q_hash = $db_class->mdo($mdo_q);
# Remove unencrypted file
2014-04-28 16:43:00 +04:00
my @rm_cmd = ( "rm", "-f", "$dec_db_file" );
2014-04-28 16:14:23 +04:00
system(@rm_cmd) == 0 or die "Cannot remove unencrypted database! $!\n";
return $q_hash;
}
2014-05-12 11:07:30 +04:00
# Remove password
sub remove {
my ( $self, $store ) = @_;
my $db_class = $self->{_db};
my $gpg = $self->{_gpg};
my $id = $store->{id};
# Decrypt database
my $dec_db_file = $gpg->decrypt_db();
2014-05-12 17:16:10 +04:00
my $q = "delete from passwords where id=$id";
my $mdo_q = {
2014-05-12 11:07:30 +04:00
file => $dec_db_file,
query => $q,
type => 'do',
};
$db_class->mdo($mdo_q);
$gpg->encrypt_db($dec_db_file);
return 0;
}
sub export {
my ( $self, $filename ) = @_;
my $gpg = $self->{_gpg};
my $dec_db_file = $gpg->decrypt_db();
my $export_enc = $gpg->export($dec_db_file);
my @mv_cmd = ( 'mv', "$export_enc", "$filename" );
system(@mv_cmd) == 0 or die "Cannot move $export_enc to $filename: $!\n";
return 0;
}
2014-04-29 11:37:41 +04:00
# Decrypt base and store new password
sub save {
my ( $self, $store ) = @_;
my $db_class = $self->{_db};
my $gpg = $self->{_gpg};
my $name = $store->{name};
my $resource = $store->{resource};
my $password = $store->{password};
2015-04-10 12:50:56 +03:00
my $group = $store->{group};
2014-05-13 17:57:14 +04:00
2014-05-12 17:16:10 +04:00
# Comment check
2014-05-13 17:57:14 +04:00
my $comment = '';
2014-05-12 17:16:10 +04:00
if ( defined( $store->{comment} ) ) {
$comment = $store->{comment};
}
2014-05-06 15:18:34 +04:00
# Username check
my $username = '';
2014-05-12 11:07:30 +04:00
if ( defined( $store->{username} ) ) {
$username = $store->{username};
2014-05-06 15:18:34 +04:00
}
2014-04-29 11:37:41 +04:00
# Decrypt database
my $dec_db_file = $gpg->decrypt_db();
2014-05-13 17:57:14 +04:00
my $q
2015-04-10 12:50:56 +03:00
= "insert into passwords(name, resource, password, username, comment, 'group')
values('$name', '$resource', '$password', '$username', '$comment', '$group')";
2014-04-29 11:37:41 +04:00
my $mdo_q = {
file => $dec_db_file,
name => $name,
2014-04-29 15:45:31 +04:00
query => $q,
2014-04-29 11:37:41 +04:00
type => 'do',
};
$db_class->mdo($mdo_q);
$gpg->encrypt_db($dec_db_file);
return 0;
}
# Generate password
sub generate {
2015-04-10 10:05:45 +03:00
my $value;
2015-07-10 12:55:59 +03:00
# Defaults
my $length = 16;
my $digest;
for (1..32) {
open my $rnd, "<", "/dev/urandom";
2016-02-08 19:11:37 +03:00
read $rnd, $value, 4096;
2015-07-10 12:55:59 +03:00
my $c = unpack( "H*", $value );
close $rnd;
# MORE ENTROPY
my $ctx = Digest::MD5->new();
$ctx->add($c);
# MORE
my $encoded = encode_base64( $ctx->hexdigest() );
$encoded =~ s/=//g;
$encoded =~ s/\n//g;
$digest .= $encoded;
}
2015-04-10 12:50:56 +03:00
2015-07-10 12:55:59 +03:00
my @chars = split( //, $digest );
my @r_special = ( '!', '@', '(', ')', '#', '$', '%', '^', '&' );
for (1..10) {
foreach my $special (@r_special) {
2015-07-10 14:04:04 +03:00
$chars[ rand(@chars) ] = $special;
2015-07-10 12:55:59 +03:00
}
}
2015-04-10 10:05:45 +03:00
2014-04-29 11:37:41 +04:00
my $string;
2015-07-10 12:55:59 +03:00
$string .= $chars[ rand @chars ] for 1 .. $length;
2014-04-29 11:37:41 +04:00
return $string;
}
2014-04-28 12:04:17 +04:00
# Check configuration. If it doesn't exist create it.
sub check_config {
2014-04-28 12:17:17 +04:00
my ($self) = @_;
2014-04-28 16:14:23 +04:00
if ( -e $ENV{HOME} . "/.PM/db.sqlite" ) {
2014-05-06 12:18:44 +04:00
return 1;
2014-04-28 12:17:17 +04:00
}
else {
my $db = $self->{_db};
$db->create_base();
2014-04-29 15:45:31 +04:00
2014-05-06 00:40:26 +04:00
print "Done!\n";
2014-04-29 15:45:31 +04:00
return 0;
2014-04-28 12:17:17 +04:00
}
2014-04-29 15:45:31 +04:00
return 1;
2014-04-28 12:04:17 +04:00
}
2014-04-28 12:17:17 +04:00
1;