forked from hardcoresushi/DroidFS
Opening plaintext names volumes
This commit is contained in:
parent
4d47306b29
commit
e63981c788
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
@ -57,7 +58,7 @@ func err_to_bool(e error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func wipe(d []byte){
|
||||
func wipe(d []byte) {
|
||||
for i := range d {
|
||||
d[i] = 0
|
||||
}
|
||||
@ -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 ".".
|
||||
@ -291,7 +302,7 @@ func doRead(sessionID, handleID int, dst_buff []byte, offset uint64, length uint
|
||||
return out, true
|
||||
}
|
||||
|
||||
func doWrite(sessionID, handleID int, data []byte, offset uint64) (uint32, bool){
|
||||
func doWrite(sessionID, handleID int, data []byte, offset uint64) (uint32, bool) {
|
||||
fileWasEmpty := false
|
||||
f, ok := sessions[sessionID].file_handles[handleID]
|
||||
if !ok {
|
||||
@ -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
|
||||
@ -545,7 +559,7 @@ func gcf_init(root_cipher_dir string, password, givenScryptHash, returnedScryptH
|
||||
}
|
||||
|
||||
//export gcf_close
|
||||
func gcf_close(sessionID int){
|
||||
func gcf_close(sessionID int) {
|
||||
sessions[sessionID].cryptoCore.Wipe()
|
||||
for handleID, _ := range sessions[sessionID].file_handles {
|
||||
gcf_close_file(sessionID, handleID)
|
||||
@ -582,7 +596,7 @@ func gcf_change_password(root_cipher_dir string, old_password, givenScryptHash,
|
||||
masterkey := cf.GetMasterkey(old_password, givenScryptHash, nil)
|
||||
if masterkey != nil {
|
||||
logN := cf.ScryptObject.LogN()
|
||||
scryptHash := cf.EncryptKey(masterkey, new_password, logN, len(returnedScryptHashBuff)>0)
|
||||
scryptHash := cf.EncryptKey(masterkey, new_password, logN, len(returnedScryptHashBuff) > 0)
|
||||
wipe(masterkey)
|
||||
for i := range scryptHash {
|
||||
returnedScryptHashBuff[i] = scryptHash[i]
|
||||
@ -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
|
||||
@ -652,13 +673,13 @@ func gcf_list_dir(sessionID int, dirName string) (*C.char, *C.int, C.int) {
|
||||
// Override the ciphertext name with the plaintext name but reuse the rest
|
||||
// of the structure
|
||||
cipherEntries[i].Name = name
|
||||
plain.WriteString(cipherEntries[i].Name+"\x00")
|
||||
plain.WriteString(cipherEntries[i].Name + "\x00")
|
||||
modes = append(modes, cipherEntries[i].Mode)
|
||||
}
|
||||
p := C.malloc(C.ulong(C.sizeof_int*len(modes)))
|
||||
p := C.malloc(C.ulong(C.sizeof_int * len(modes)))
|
||||
for i := 0; i < len(modes); i++ {
|
||||
offset := C.sizeof_int*uintptr(i)
|
||||
*(*C.int)(unsafe.Pointer(uintptr(p)+offset)) = (C.int)(modes[i])
|
||||
offset := C.sizeof_int * uintptr(i)
|
||||
*(*C.int)(unsafe.Pointer(uintptr(p) + offset)) = (C.int)(modes[i])
|
||||
}
|
||||
return C.CString(plain.String()), (*C.int)(p), (C.int)(len(modes))
|
||||
}
|
||||
@ -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 {
|
||||
@ -835,7 +874,7 @@ func gcf_truncate(sessionID int, path string, offset uint64) bool {
|
||||
}
|
||||
|
||||
//export gcf_close_file
|
||||
func gcf_close_file(sessionID, handleID int){
|
||||
func gcf_close_file(sessionID, handleID int) {
|
||||
f, ok := sessions[sessionID].file_handles[handleID]
|
||||
if ok {
|
||||
f.fd.Close()
|
||||
@ -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,10 +994,10 @@ 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)
|
||||
}
|
||||
|
||||
func main(){}
|
||||
func main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user