Skip to content

Commit f29539d

Browse files
committed
[RT#69439] Secure temp files handling in bin/dave
1 parent dc42293 commit f29539d

File tree

7 files changed

+87
-13
lines changed

7 files changed

+87
-13
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pm_to_blib
33
Makefile
44
Makefile.old
5+
MANIFEST.bak
56
blib
67
pod2htm*
78

MANIFEST

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
bin/dave
22
bin/dist
33
Changes
4-
lib/HTTP/DAV.pm
5-
lib/HTTP/DAV/Comms.pm
6-
lib/HTTP/DAV/Lock.pm
7-
lib/HTTP/DAV/Resource.pm
8-
lib/HTTP/DAV/ResourceList.pm
9-
lib/HTTP/DAV/Response.pm
10-
lib/HTTP/DAV/Utils.pm
114
doc/Changes.pod
125
doc/html/Changes.html
136
doc/html/dave.html
@@ -16,8 +9,17 @@ doc/html/index.html
169
doc/html/TODO.html
1710
doc/README.pod
1811
doc/TODO.pod
12+
lib/HTTP/DAV.pm
13+
lib/HTTP/DAV/Changes.pod
14+
lib/HTTP/DAV/Comms.pm
15+
lib/HTTP/DAV/Lock.pm
16+
lib/HTTP/DAV/Resource.pm
17+
lib/HTTP/DAV/ResourceList.pm
18+
lib/HTTP/DAV/Response.pm
19+
lib/HTTP/DAV/Utils.pm
1920
Makefile.PL
2021
MANIFEST
22+
MANIFEST.SKIP
2123
META.yml Module meta-data (added by MakeMaker)
2224
README
2325
t/1_loadme.t
@@ -42,6 +44,7 @@ t/9_RT_52665.t
4244
t/9_RT_59674.t
4345
t/9_RT_60457.t
4446
t/9_RT_68936.t
47+
t/9_RT_69439.t
4548
t/multistatus.xml
4649
t/test_data/file1
4750
t/test_data/file2

MANIFEST.SKIP

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
patches/.*
2+
pod2htm.*
3+
pm_to_blib$
4+
blib.*
5+
\.git.*
6+
Makefile$
7+
\.bak$
8+
\.old$

Makefile.PL

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ WriteMakefile(
1515
'EXE_FILES' => [ map {"bin/$_"} @programs_to_install ],
1616
'PREREQ_PM' => {
1717
'Cwd' => 0,
18+
'File::Temp' => 0,
1819
'LWP' => 5.48,
1920
'Scalar::Util' => 0,
2021
'Time::Local' => 0,
@@ -23,7 +24,6 @@ WriteMakefile(
2324
'XML::DOM' => 0,
2425

2526
# bin/dave specific dependencies
26-
'File::Temp' => 0,
2727
'Getopt::Long' => 0,
2828
'Term::ReadLine' => 0,
2929
'Text::ParseWords' => 0,

bin/dave

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ GetOptions(
5555
'u|username=s' => \$user,
5656
'p|password=s' => \$pass,
5757
'tmpdir:s' => \$TMP_DIR,
58-
) or pod2usage(2);
58+
) or Pod::Usage::pod2usage(2);
5959

6060
# Basic sanity check for /tmp dir
61-
if (! -d $TMP_DIR or ! -w $TMP_DIR) {
61+
if (! $TMP_DIR or ! -d $TMP_DIR or ! -w $TMP_DIR) {
6262
die "Can't write into temp dir '$TMP_DIR': $!\n";
6363
}
6464

@@ -238,9 +238,9 @@ sub command_cat {
238238

239239
sub command_edit {
240240
my $remote_file = shift;
241-
$TMP_DIR||="/tmp";
242-
my $EDITOR= $ENV{DAV_EDITOR} || $ENV{EDITOR} || "vi";
243-
my $local_file = "$TMP_DIR/dave.perldav." . $$ . time;
241+
242+
my $EDITOR= $ENV{DAV_EDITOR} || $ENV{EDITOR} || 'vi';
243+
my $local_file = HTTP::DAV::_tempfile('dave', $TMP_DIR);
244244

245245
my $resource = $gdc->propfind($remote_file);
246246
if ( $resource && $resource->is_collection() ) {

lib/HTTP/DAV.pm

+21
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use URI::file;
2525
use URI::Escape;
2626
use FileHandle;
2727
use File::Glob;
28+
use File::Temp ();
2829

2930
sub new {
3031
my $class = shift;
@@ -71,6 +72,26 @@ sub DebugLevel {
7172
$DEBUG = $level;
7273
}
7374

75+
sub _tempfile {
76+
my ($prefix, $tempdir) = @_;
77+
78+
$prefix ||= 'dav';
79+
$tempdir ||= '/tmp';
80+
81+
my $template = $prefix . 'XXXXXXXXXXXXX';
82+
83+
my $old_umask = umask 0077;
84+
my ($fh, $filename) = File::Temp::tempfile($template,
85+
DIR => $tempdir,
86+
SUFFIX => '.tmp'
87+
);
88+
umask $old_umask;
89+
90+
return wantarray
91+
? ($fh, $filename)
92+
: $filename;
93+
}
94+
7495
######################################################################
7596
# new_resource acts as a resource factory.
7697
# It will create a new one for you each time you ask.

t/9_RT_69439.t

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env perl
2+
#
3+
# RT #69439, insecure /tmp file handling
4+
#
5+
6+
use strict;
7+
use warnings;
8+
use Test::More tests => 11;
9+
10+
use File::Path ();
11+
use HTTP::DAV;
12+
13+
# Dave uses HTTP::DAV::_tempfile() every time
14+
# it has to open a new temporary file
15+
16+
my $tmpdir = ".http-dav-test-tmpdir.$$";
17+
18+
ok(File::Path::mkpath($tmpdir), "Created temp dir");
19+
20+
# Generate two temp files one immediately after the other
21+
my ($fh1, $filename1) = HTTP::DAV::_tempfile('dave', $tmpdir);
22+
my ($fh2, $filename2) = HTTP::DAV::_tempfile('dave', $tmpdir);
23+
24+
ok($fh1);
25+
ok($fh2);
26+
ok($filename1);
27+
ok($filename2);
28+
29+
# They have to have different filenames
30+
isnt($filename1, $filename2, "Different filenames should be generated");
31+
isnt($fh1, $fh2, "They should be different filehandles too, just in case");
32+
33+
#diag("Generated temp file: $filename1");
34+
#diag("Generated temp file: $filename2");
35+
36+
ok(index($filename1, "$tmpdir/dave") > -1);
37+
ok(index($filename2, "$tmpdir/dave") > -1);
38+
39+
is(unlink($filename1, $filename2), 2, "Removed temp files");
40+
41+
ok(File::Path::rmtree($tmpdir), "Cleaned up temp dir");

0 commit comments

Comments
 (0)