Opening plaintext names volumes

This commit is contained in:
Matéo Duparc 2021-02-07 14:43:51 +01:00
parent 4d47306b29
commit e63981c788
Signed by: hardcoresushi
GPG Key ID: 007F84120107191E
2 changed files with 442 additions and 398 deletions

View File

@ -15,8 +15,8 @@ android {
applicationId "sushi.hardcore.droidfs"
minSdkVersion 21
targetSdkVersion 29
versionCode 9
versionName "1.4.1"
versionCode 10
versionName "1.4.2"
ndk {
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
@ -56,11 +56,11 @@ dependencies {
implementation "com.github.bumptech.glide:glide:4.11.0"
implementation "com.google.android.exoplayer:exoplayer-core:2.11.7"
implementation "com.google.android.exoplayer:exoplayer-ui:2.11.7"
implementation "androidx.biometric:biometric:1.0.1"
implementation "androidx.biometric:biometric:1.1.0"
def camerax_version = "1.0.0-rc01"
def camerax_version = "1.1.0-alpha01"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-view:1.0.0-alpha20"
implementation "androidx.camera:camera-extensions:1.0.0-alpha20"
implementation "androidx.camera:camera-view:1.0.0-alpha21"
implementation "androidx.camera:camera-extensions:1.0.0-alpha21"
}

View File

@ -2,25 +2,25 @@ package main
import (
"C"
"crypto/cipher"
"crypto/aes"
"syscall"
"strings"
"bytes"
"unsafe"
"os"
"io"
"crypto/aes"
"crypto/cipher"
"fmt"
"path/filepath"
"golang.org/x/sys/unix"
"io"
"os"
"path/filepath"
"strings"
"syscall"
"unsafe"
"./gocryptfs_internal/cryptocore"
"./gocryptfs_internal/stupidgcm"
"./gocryptfs_internal/eme"
"./gocryptfs_internal/nametransform"
"./rewrites/syscallcompat"
"./gocryptfs_internal/stupidgcm"
"./rewrites/configfile"
"./rewrites/contentenc"
"./rewrites/syscallcompat"
)
const (
@ -40,6 +40,7 @@ type File struct {
type SessionVars struct {
root_cipher_dir string
plainTextNames bool
nameTransform *nametransform.NameTransform
cryptoCore *cryptocore.CryptoCore
contentEnc *contentenc.ContentEnc
@ -72,6 +73,16 @@ func clear_dirCache(sessionID int) {
func openBackingDir(sessionID int, relPath string) (dirfd int, cName string, err error) {
dirRelPath := nametransform.Dir(relPath)
// With PlaintextNames, we don't need to read DirIVs. Easy.
if sessions[sessionID].plainTextNames {
dirfd, err = syscallcompat.OpenDirNofollow(sessions[sessionID].root_cipher_dir, dirRelPath)
if err != nil {
return -1, "", err
}
// If relPath is empty, cName is ".".
cName = filepath.Base(relPath)
return dirfd, cName, nil
}
dir, ok := sessions[sessionID].dirCache[dirRelPath]
if ok {
// If relPath is empty, cName is ".".
@ -487,6 +498,9 @@ func init_new_session(root_cipher_dir string, masterkey []byte, cf *configfile.C
}
if err == nil {
var new_session SessionVars
new_session.plainTextNames = cf.IsFeatureFlagSet(configfile.FlagPlaintextNames)
emeCipher = eme.New(emeBlockCipher)
new_session.nameTransform = nametransform.New(emeCipher, true, true)
@ -524,7 +538,7 @@ func init_new_session(root_cipher_dir string, masterkey []byte, cf *configfile.C
if sessions == nil {
sessions = make(map[int]SessionVars)
}
sessions[sessionID] = new_session;
sessions[sessionID] = new_session
return sessionID
}
return -1
@ -614,11 +628,13 @@ func gcf_list_dir(sessionID int, dirName string) (*C.char, *C.int, C.int) {
}
// Get DirIV (stays nil if PlaintextNames is used)
var cachedIV []byte
if !sessions[sessionID].plainTextNames {
// Read the DirIV from disk
cachedIV, err = nametransform.ReadDirIVAt(fd)
if err != nil {
return nil, nil, 0
}
}
// Decrypted directory entries
var plain strings.Builder
var modes []uint32
@ -629,6 +645,11 @@ func gcf_list_dir(sessionID int, dirName string) (*C.char, *C.int, C.int) {
// silently ignore "gocryptfs.conf" in the top level dir
continue
}
if sessions[sessionID].plainTextNames {
plain.WriteString(cipherEntries[i].Name + "\x00")
modes = append(modes, cipherEntries[i].Mode)
continue
}
if cName == nametransform.DirIVFilename {
// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled
continue
@ -670,6 +691,18 @@ func gcf_mkdir(sessionID int, newPath string) bool {
return false
}
defer syscall.Close(dirfd)
if sessions[sessionID].plainTextNames {
err = syscallcompat.Mkdirat(dirfd, cName, folder_mode)
if err != nil {
return false
}
var ust unix.Stat_t
err = syscallcompat.Fstatat(dirfd, cName, &ust, unix.AT_SYMLINK_NOFOLLOW)
if err != nil {
return false
}
} else {
// We need write and execute permissions to create gocryptfs.diriv.
// Also, we need read permissions to open the directory (to avoid
// race-conditions between getting and setting the mode).
@ -718,6 +751,7 @@ func gcf_mkdir(sessionID int, newPath string) bool {
return false
}
}
}
return true
}
@ -729,6 +763,11 @@ func gcf_rmdir(sessionID int, relPath string) bool {
return false
}
defer syscall.Close(parentDirFd)
if sessions[sessionID].plainTextNames {
// Unlinkat with AT_REMOVEDIR is equivalent to Rmdir
err = unix.Unlinkat(parentDirFd, cName, unix.AT_REMOVEDIR)
return err_to_bool(err)
}
dirfd, err := syscallcompat.Openat(parentDirFd, cName, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
if err != nil {
return false
@ -797,7 +836,7 @@ func gcf_open_write_mode(sessionID int, path string) int {
defer syscall.Close(dirfd)
fd := -1
// Handle long file name
if nametransform.IsLongContent(cName) {
if !sessions[sessionID].plainTextNames && nametransform.IsLongContent(cName) {
// Create ".name"
err = sessions[sessionID].nameTransform.WriteLongNameAt(dirfd, cName, path)
if err != nil {
@ -851,7 +890,7 @@ func gcf_close_file(sessionID, handleID int){
func gcf_read_file(sessionID, handleID int, offset uint64, dst_buff []byte) uint32 {
length := uint64(len(dst_buff))
if length > contentenc.MAX_KERNEL_WRITE {
return 0;
return 0
}
out, _ := doRead(sessionID, handleID, dst_buff[:0], offset, length)
@ -863,7 +902,7 @@ func gcf_read_file(sessionID, handleID int, offset uint64, dst_buff []byte) uint
func gcf_write_file(sessionID, handleID int, offset uint64, data []byte) uint32 {
length := uint64(len(data))
if length > contentenc.MAX_KERNEL_WRITE {
return 0;
return 0
}
written, _ := doWrite(sessionID, handleID, data, offset)
@ -899,6 +938,11 @@ func gcf_rename(sessionID int, oldPath string, newPath string) bool {
return false
}
defer syscall.Close(newDirfd)
// Easy case.
if sessions[sessionID].plainTextNames {
return err_to_bool(syscallcompat.Renameat(oldDirfd, oldCName, newDirfd, newCName))
}
// Long destination file name: create .name file
nameFileAlreadyThere := false
if nametransform.IsLongContent(newCName) {
@ -950,7 +994,7 @@ func gcf_remove_file(sessionID int, path string) bool {
return false
}
// Delete ".name" file
if nametransform.IsLongContent(cName) {
if !sessions[sessionID].plainTextNames && nametransform.IsLongContent(cName) {
err = nametransform.DeleteLongNameAt(dirfd, cName)
}
return err_to_bool(err)