How to fix files within archive having permission denied when downloaded from my endpoint?

206 Views Asked by At

I am implementing an endpoint using Actix Web and Tokio Tar to download an archive file.

The code for the archive generation is inspired from the code shown in the example here. It is reproduced below:

let mut ar = Builder::new(Cursor::new(vec![]));

for (path, file) in files {
    let mut header = Header::new_gnu();
    header.set_size(file.len() as u64);
    header.set_cksum();
    ar.append_data(&mut header, path, Cursor::new(file)).await?;
}
let ar_data = ar.into_inner().await?;

Ok(HttpResponse::Ok()
    .append_header(("Content-Disposition", "attachment; filename=\"archive.tar\""))
    .body(ar_data.into_inner()))

When I visit the endpoint I can download the archive and I can also unpack it. The problem now is, all the files within the archive seems to have the wrong permission. I cannot open it.

When I check the permissions this is what I get:

ls -l /Users/me/Downloads/archive
total 32
----------  1 me  staff    83 Jan  1  1970 one.md
----------  1 me  staff  2267 Jan  1  1970 two.png
----------  1 me  staff  4708 Jan  1  1970 three.svg
drwxr-xr-x@ 3 me  staff    96 Oct 21 19:37 src

When I manually update the permission to allow read/write I can open the file.

Question is, why is the archive being generated with this permission? And more importantly how do I make it such that the endpoint generates the archive with the correct permission to allow users to be able to read and write it?

1

There are 1 best solutions below

0
On

Your code isn't creating an archive from files on disk. It is instead reading files from disk, then using the std::io::Read reader of that file to provide the bytes for a file to be archived. In other words, the archiving library never sees the original file metadata (including permissions) so cannot possibly replicate the original permissions.

So you need to create the archive in such a way that the file permissions are what you want. I'm not an expert in tokio-tar, but a quick look at the docs suggests that you probably either want to use Builder::append_file or explicitly build the Header with the permissions you want (it has plenty of methods for setting file metadata).

In general, it's a good idea to get used to reading the docs for the crates you're using. See what functions and types are available, read around, and you'll likely find something that points you in the right direction.


In general, you should be pretty explicit about permissions with archives that's sending data over a network. File permissions can be an attack vector.

For example, there was a CVE fixed in Cargo relatively recently where Cargo unpacked crate archives without checking the permissions, which meant that a crate author could create a crate where all files were rwx for all users, which means that a malicious user could attack another user on the same machine by overwriting source code of cached downloaded crates. Be careful.