libgocryptfs/init_dir.go
Jakob Unterwurzacher 61ef6b00a6 -devrandom: make flag a no-op
Commit f3c777d5ea added the `-devrandom` option:

    commit f3c777d5ea
    Author: @slackner
    Date:   Sun Nov 19 13:30:04 2017 +0100

    main: Add '-devrandom' commandline option

    Allows to use /dev/random for generating the master key instead of the
    default Go implementation. When the kernel random generator has been
    properly initialized both are considered equally secure, however:

    * Versions of Go prior to 1.9 just fall back to /dev/urandom if the
      getrandom() syscall would be blocking (Go Bug #19274)

    * Kernel versions prior to 3.17 do not support getrandom(), and there
      is no check if the random generator has been properly initialized
      before reading from /dev/urandom

    This is especially useful for embedded hardware with low-entroy. Please
    note that generation of the master key might block indefinitely if the
    kernel cannot harvest enough entropy.

We now require Go v1.13 and Kernel versions should have also moved on.
Make the flag a no-op.

https://github.com/rfjakob/gocryptfs/issues/596
2021-08-25 12:39:17 +02:00

144 lines
4.2 KiB
Go

package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"syscall"
"github.com/rfjakob/gocryptfs/v2/internal/configfile"
"github.com/rfjakob/gocryptfs/v2/internal/cryptocore"
"github.com/rfjakob/gocryptfs/v2/internal/exitcodes"
"github.com/rfjakob/gocryptfs/v2/internal/fido2"
"github.com/rfjakob/gocryptfs/v2/internal/nametransform"
"github.com/rfjakob/gocryptfs/v2/internal/readpassword"
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
"github.com/rfjakob/gocryptfs/v2/internal/tlog"
)
// isEmptyDir checks if "dir" exists and is an empty directory.
// Returns an *os.PathError if Stat() on the path fails.
func isEmptyDir(dir string) error {
err := isDir(dir)
if err != nil {
return err
}
entries, err := ioutil.ReadDir(dir)
if err != nil {
return err
}
if len(entries) == 0 {
return nil
}
return fmt.Errorf("directory %s not empty", dir)
}
// isDir checks if "dir" exists and is a directory.
func isDir(dir string) error {
fi, err := os.Stat(dir)
if err != nil {
return err
}
if !fi.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
return nil
}
// initDir handles "gocryptfs -init". It prepares a directory for use as a
// gocryptfs storage directory.
// In forward mode, this means creating the gocryptfs.conf and gocryptfs.diriv
// files in an empty directory.
// In reverse mode, we create .gocryptfs.reverse.conf and the directory does
// not need to be empty.
func initDir(args *argContainer) {
var err error
if args.reverse {
_, err = os.Stat(args.config)
if err == nil {
tlog.Fatal.Printf("Config file %q already exists", args.config)
os.Exit(exitcodes.Init)
}
} else {
err = isEmptyDir(args.cipherdir)
if err != nil {
tlog.Fatal.Printf("Invalid cipherdir: %v", err)
os.Exit(exitcodes.CipherDir)
}
}
// Choose password for config file
if len(args.extpass) == 0 && args.fido2 == "" {
tlog.Info.Printf("Choose a password for protecting your files.")
}
{
var password []byte
var fido2CredentialID, fido2HmacSalt []byte
if args.fido2 != "" {
fido2CredentialID = fido2.Register(args.fido2, filepath.Base(args.cipherdir))
fido2HmacSalt = cryptocore.RandBytes(32)
password = fido2.Secret(args.fido2, fido2CredentialID, fido2HmacSalt)
} else {
// normal password entry
password = readpassword.Twice([]string(args.extpass), []string(args.passfile))
fido2CredentialID = nil
fido2HmacSalt = nil
}
creator := tlog.ProgramName + " " + GitVersion
err = configfile.Create(&configfile.CreateArgs{
Filename: args.config,
Password: password,
PlaintextNames: args.plaintextnames,
LogN: args.scryptn,
Creator: creator,
AESSIV: args.aessiv,
Fido2CredentialID: fido2CredentialID,
Fido2HmacSalt: fido2HmacSalt,
DeterministicNames: args.deterministic_names,
XChaCha20Poly1305: args.xchacha})
if err != nil {
tlog.Fatal.Println(err)
os.Exit(exitcodes.WriteConf)
}
for i := range password {
password[i] = 0
}
// password runs out of scope here
}
// Forward mode with filename encryption enabled needs a gocryptfs.diriv file
// in the root dir
if !args.plaintextnames && !args.reverse && !args.deterministic_names {
// Open cipherdir (following symlinks)
dirfd, err := syscall.Open(args.cipherdir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
if err == nil {
err = nametransform.WriteDirIVAt(dirfd)
syscall.Close(dirfd)
}
if err != nil {
tlog.Fatal.Println(err)
os.Exit(exitcodes.Init)
}
}
mountArgs := ""
fsName := "gocryptfs"
if args.reverse {
mountArgs = " -reverse"
fsName = "gocryptfs-reverse"
}
tlog.Info.Printf(tlog.ColorGreen+"The %s filesystem has been created successfully."+tlog.ColorReset,
fsName)
wd, _ := os.Getwd()
friendlyPath, _ := filepath.Rel(wd, args.cipherdir)
if strings.HasPrefix(friendlyPath, "../") {
// A relative path that starts with "../" is pretty unfriendly, just
// keep the absolute path.
friendlyPath = args.cipherdir
}
if strings.Contains(friendlyPath, " ") {
friendlyPath = "\"" + friendlyPath + "\""
}
tlog.Info.Printf(tlog.ColorGrey+"You can now mount it using: %s%s %s MOUNTPOINT"+tlog.ColorReset,
tlog.ProgramName, mountArgs, friendlyPath)
}