diff options
-rwxr-xr-x | cli/icevault | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/cli/icevault b/cli/icevault index 73136d1..992ee6a 100755 --- a/cli/icevault +++ b/cli/icevault @@ -80,6 +80,11 @@ sub usage($) { exit $rv; } +sub mysystem(@) { + system {$_[0]} @_; + error "C<%s> exited with value %d", $_[0], ($? >> 8) if $? and $? != -1; +} + # grepIdx BLOCK LIST # Evaluates the BLOCK for each element of LIST (locally setting $_ to # each element) and returns the list value consisting of the index of @@ -134,7 +139,7 @@ sub loadConfig($) { chomp; s/#.*//; # ignore comments next if /^\s*$/; # ignore empty and blank lines - /^([-\@\w.]+)(?:\s*=\s*)(\p{print}+)/ or error "Can't parse config line: C<%s>", $_; + /^([-\@a-zA-Z0-9.]+)(?:\s*=\s*)(\p{Print}+)/ or error "Can't parse config line: C<%s>", $_; $CONFIG{$1} //= $2; } close $CONFIG; @@ -162,10 +167,11 @@ sub connect($) { } closedir $dh; error "No Firefox profile found under C<%s>", $ffdir unless defined $profile; - "$ffdir/$profile" =~ /\A(\p{Print}+)\z/ or error "Insecure C<%s>", "$ffdir/$profile"; # untaint $ffdir/$profile - $sockname = "$1/$sockname"; - myprintf \*STDERR, "Using socket C<%s>", $sockname if $CONFIG{debug}; + $sockname = "$$ffdir/$profile/$sockname"; } + myprintf \*STDERR, "Using socket C<%s>", $sockname if $CONFIG{debug}; + $sockname =~ /\A(\/\p{Print}+)\z/ or error "Insecure C<%s>", $sockname; # untaint $sockname + $sockname = $1; require 'IO/Socket/UNIX.pm'; $SOCKET = IO::Socket::UNIX->new( Type => IO::Socket::UNIX::SOCK_STREAM(), Peer => $sockname ) @@ -224,13 +230,31 @@ sub sendCommand(@) { getResponse(); } + +# Glob over all form templates. Note that the output needs to be +# $LOCALE-decode'ed. +sub myglob(;$$$) { + my ($s, $h, $i) = @_; + my $glob = $LOCALE->encode($CONFIG{store}); + require 'File/Glob.pm'; + + $glob =~ s/([\\\[\]\{\}\*\?\~])/\\$1/g; + $glob =~ s{\%(.)}{ $1 eq '%' ? '%' : + $1 eq 's' ? $s // '*' : + $1 eq 'h' ? $h // '*' : + $1 eq 'i' ? $i // '*' : + die "Invalid placeholder %$1" }ge; + + myprintf \*STDERR, "Using glob pattern C<%s>", $glob if $CONFIG{debug}; + return File::Glob::bsd_glob($glob); +} + # Get all identities with the given $prefix. If there are multiple # matches and $all is false, limit the output to one depth more than the # longuest common prefix. sub complete($;$) { my $prefix = shift // ''; my $all = shift; - require 'File/Glob.pm'; my $pat = $CONFIG{store}; my ($s, $h, $i); # extract URI components from the prefix @@ -253,14 +277,6 @@ sub complete($;$) { $gh .= '*' if defined $gh and !defined $gi; $gi .= '*' if defined $gi; - my $glob = $pat; - $glob =~ s/([\\\[\]\{\}\*\?\~])/\\$1/g; - $glob =~ s{\%(.)}{ $1 eq '%' ? '%' : - $1 eq 's' ? $gs // '*' : - $1 eq 'h' ? $gh // '*' : - $1 eq 'i' ? $gi // '*' : - die "Invalid placeholder %$1" }ge; - # construct regexp to extract the URI compontents of the matching URIs my ($ps, $ph, $pi) = ($s, $h, $i); $ps = defined $h ? qr/(?<s>\Q$s\E)/ : (defined $s and $s ne '') ? qr/(?<s>\Q$s\E[A-Za-z0-9-]*)/ : qr/(?<s>[A-Za-z0-9-]+)/; @@ -275,11 +291,11 @@ sub complete($;$) { die "Invalid placeholder %$1"}ge; $pat = qr/\A$pat\z/; - myprintf \*STDERR, "Using glob pattern C<%s>", $glob if $CONFIG{debug}; - myprintf \*STDERR, "Using regexp C<%s>", "$pat" if $CONFIG{debug}; + myprintf \*STDERR, "Using regexp C<%s>", "$pat" if $CONFIG{debug}; my @matches; - foreach my $filename (File::Glob::bsd_glob($glob)) { + foreach my $filename (myglob($gs, $gh, $gi)) { + next unless -f $filename; $LOCALE->decode($filename) =~ $pat or die "$filename doesn't match $pat"; push @matches, "$+{s}://$+{h}/$+{i}"; } @@ -339,8 +355,7 @@ sub getIdentityFile($) { $1 eq 'h' ? $h : $1 eq 'i' ? $i : die "Invalid placeholder %$1" }ge; - $filename =~ /\A(\p{Print}+)\z/ or error "Insecure C<%s>", $filename; # untaint $filename - return $1; + return $filename; } # Decrypt the given identity file. In scalar context, return the @@ -846,8 +861,9 @@ elsif ($command eq 'edit') { require 'File/Temp.pm'; error "C<%s> is not set", '$EDITOR' unless defined $ENV{EDITOR}; - $ENV{EDITOR} =~ /\A(\p{Print}+)\z/ or error "Insecure C<%s>", "\$EDITOR"; - my $EDITOR = $1; # untaint $EDITOR + my $EDITOR = $ENV{EDITOR} // 'editor'; + $EDITOR =~ /\A(\p{Print}+)\z/ or error "Insecure C<%s>", "\$EDITOR"; + $EDITOR = $1; # untaint $EDITOR my $fh = File::Temp->new(SUFFIX => '.yaml', UNLINK => 0, TMPDIR => 1) or die; END { unlink $fh->filename if defined $fh; } # never leave cleartext lying around @@ -855,7 +871,7 @@ elsif ($command eq 'edit') { my $h = sha256_file $fh->filename; while (1) { - system $EDITOR, $fh->filename; + mysystem $EDITOR, $fh->filename; error "C<%s> exited with value %d", $EDITOR, ($? >> 8) if $? and $? != -1; my $h2 = sha256_file $fh->filename; |