=================================================================== RCS file: /cvs/palm/Palm-Keyring/lib/Palm/Keyring.pm,v retrieving revision 1.50 retrieving revision 1.56 diff -u -r1.50 -r1.56 --- palm/Palm-Keyring/lib/Palm/Keyring.pm 2007/09/13 01:02:52 1.50 +++ palm/Palm-Keyring/lib/Palm/Keyring.pm 2008/09/18 07:04:55 1.56 @@ -1,5 +1,5 @@ package Palm::Keyring; -# $RedRiver: Keyring.pm,v 1.49 2007/09/12 03:39:22 andrew Exp $ +# $RedRiver: Keyring.pm,v 1.55 2008/09/17 14:47:47 andrew Exp $ ######################################################################## # Keyring.pm *** Perl class for Keyring for Palm OS databases. # @@ -15,6 +15,8 @@ use strict; use warnings; +require 5.006_001; + use Carp; use base qw/ Palm::StdAppInfo /; @@ -83,7 +85,7 @@ ); -our $VERSION = '0.96_04'; +our $VERSION = '0.96_07'; sub new { @@ -108,6 +110,7 @@ else { $options->{password} = shift; $options->{version} = shift; + $options->{cipher} = shift; } } @@ -139,6 +142,10 @@ $self->{appinfo}->{iter} ||= $self->{options}->{iterations}; }; + if ( defined $options->{file} ) { + $self->Load($options->{file}); + } + if ( defined $options->{password} ) { $self->Password($options->{password}); } @@ -217,13 +224,13 @@ } } - my $rc = $self->SUPER::Write(@_); + my @rc = $self->SUPER::Write(@_); if ($self->{version} == 4) { shift @{ $self->{records} }; } - return $rc; + return @rc; } # ParseRecord @@ -233,7 +240,7 @@ my $self = shift; my $rec = $self->SUPER::ParseRecord(@_); - return $rec if ! exists $rec->{data}; + return $rec if !(defined $rec->{data} && length $rec->{data} ); if ($self->{version} == 4) { # skip the first record because it contains the password. @@ -241,7 +248,7 @@ $self->{encpassword} = $rec->{data}; return '__DELETE_ME__'; } - + if ($self->{records}->[0] eq '__DELETE_ME__') { shift @{ $self->{records} }; } @@ -270,8 +277,9 @@ $rec->{encrypted} = substr $extra, $blocksize; } else { + # XXX Can never get here to test, ParseAppInfoBlock is always run + # XXX first by Load(). croak "Unsupported Version $self->{version}"; - return; } return $rec; @@ -284,15 +292,19 @@ my $self = shift; my $rec = shift; + # XXX This probably shouldn't croak, just make something up + croak "No encrypted content to pack" if !defined $rec->{encrypted}; + if ($self->{version} == 4) { if ($rec->{encrypted}) { my $name = $rec->{plaintext}->{0}->{data} || $EMPTY; $rec->{data} = join $NULL, $name, $rec->{encrypted}; - delete $rec->{plaintext}; - delete $rec->{encrypted}; } } elsif ($self->{version} == 5) { + # XXX This probably shouldn't croak, just make something up + croak "No ivec" if !$rec->{ivec}; + my $field; if ($rec->{plaintext}->{0}) { $field = $rec->{plaintext}->{0}; @@ -311,6 +323,9 @@ } else { croak "Unsupported Version $self->{version}"; } + # XXX Should I? + delete $rec->{plaintext}; + delete $rec->{encrypted}; return $self->SUPER::PackRecord($rec, @_); } @@ -631,8 +646,10 @@ my $plaintext; foreach my $k (keys %{ $new }) { + next if $new->{$k}->{label_id} == 0; $plaintext .= _pack_field($new->{$k}); } + $plaintext .= chr(0xff) x 2; my $encrypted; if ($c->{name} eq 'None') { @@ -1176,7 +1193,7 @@ my ($len) = unpack "n", $field; if ($len + 4 > length $field) { - return undef, $field; + return (undef, $field); } my $unpackstr = "x2 C1 C1 A$len"; my $offset = 2 +1 +1 +$len; @@ -1285,6 +1302,8 @@ my $maxlines = shift; # Max # of lines to dump my $offset; # Offset of current chunk + my @lines; + for ($offset = 0; $offset < length($data); $offset += 16) { my $hex; # Hex values of the data @@ -1299,8 +1318,9 @@ ($ascii = $chunk) =~ y/\040-\176/./c; - printf "%s %-48s|%-16s|\n", $prefix, $hex, $ascii; + push @lines, sprintf "%s %-48s|%-16s|\n", $prefix, $hex, $ascii; } + return wantarray ? @lines : \@lines; } sub _bindump @@ -1310,6 +1330,8 @@ my $maxlines = shift; # Max # of lines to dump my $offset; # Offset of current chunk + my @lines; + for ($offset = 0; $offset < length($data); $offset += 8) { my $bin; # binary values of the data @@ -1324,8 +1346,9 @@ ($ascii = $chunk) =~ y/\040-\176/./c; - printf "%s %-72s|%-8s|\n", $prefix, $bin, $ascii; + push @lines, sprintf "%s %-72s|%-8s|\n", $prefix, $bin, $ascii; } + return wantarray ? @lines : \@lines; } # Thanks to Jochen Hoenicke @@ -1337,7 +1360,7 @@ # keylen is length of generated key in bytes # prf is the pseudo random function (e.g. hmac_sha1) # returns the key. -sub _pbkdf2($$$$$) +sub _pbkdf2 { my ($password, $salt, $iter, $keylen, $prf) = @_; my ($k, $t, $u, $ui, $i); @@ -1353,7 +1376,7 @@ return substr($t, 0, $keylen); } -sub _DES_odd_parity($) { +sub _DES_odd_parity { my $key = $_[0]; my ($r, $i); my @odd_parity = ( @@ -1418,7 +1441,7 @@ =head2 new - $pdb = new Palm::Keyring([$password[, $version]]); + $pdb = new Palm::Keyring([$password[, $version[, $cipher]]]); Create a new PDB, initialized with the various Palm::Keyring fields and an empty record list. @@ -1460,6 +1483,10 @@ =item iterations The number of iterations to encrypt with. Only used by somy crypts in v5 databases. + +=item file + +The name of a file to Load(). This will override many of the other options. =back