summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2015-10-06 00:29:08 +0200
committerJakob Unterwurzacher2015-10-06 00:31:18 +0200
commit022a6968ae0ede1259141e32b8e32553dad7d824 (patch)
treebc9aa404e3bf7d6778a81b168fc6c9743531ceab
parent552c32c5e9378b85e52c420c4dd2d7ccc827556f (diff)
Implement proper daemonization
The shell wrapper sends gocryptfs into the background and waits for SIGUSR1
-rwxr-xr-xall.bash2
-rw-r--r--cryptfs/cryptfs.go3
-rwxr-xr-xgocryptfs19
-rw-r--r--gocryptfs_main/main.go37
-rw-r--r--gocryptfs_main/sendsig.go42
5 files changed, 77 insertions, 26 deletions
diff --git a/all.bash b/all.bash
index 08bc7cf..ab55293 100755
--- a/all.bash
+++ b/all.bash
@@ -3,6 +3,4 @@
set -eu
cd gocryptfs_main
-echo -n "Compiling... "
go build
-echo "done."
diff --git a/cryptfs/cryptfs.go b/cryptfs/cryptfs.go
index c58481c..214ea10 100644
--- a/cryptfs/cryptfs.go
+++ b/cryptfs/cryptfs.go
@@ -9,10 +9,11 @@ import (
)
const (
+ DEFAULT_PLAINBS = 4096
KEY_LEN = 16
NONCE_LEN = 12
AUTH_TAG_LEN = 16
- DEFAULT_PLAINBS = 4096
+ FILEID_LEN = 16
)
type CryptFS struct {
diff --git a/gocryptfs b/gocryptfs
index ce15b97..73d7b42 100755
--- a/gocryptfs
+++ b/gocryptfs
@@ -1,9 +1,13 @@
#!/bin/bash
-# Simple wrapper that runs the gocryptfs process in the background
+# Shell wrapper that runs the gocryptfs process in the background
+# and exits on SIGUSR1
set -eu
+trap "exit 0" SIGUSR1
+shopt -u huponexit
+
dir=$(dirname "$0")
main="$dir/gocryptfs_main/gocryptfs_main"
@@ -12,11 +16,8 @@ if [ ! -x $main ]; then
exit 1
fi
-# This needs user input and cannot run in the background
-if [[ $* == *--init* ]]; then
- "$main" $*
-else
- "$main" $* &
- sleep 0.1
- disown
-fi
+# A backgrounded process gets /dev/null as stdin per default.
+# Explicitly set stdin to the current stdin so we can ask the user for input.
+"$main" $* < /proc/self/fd/0 & wait
+# The "& wait" is neccessary because bash only processes signals when
+# executing internal commands
diff --git a/gocryptfs_main/main.go b/gocryptfs_main/main.go
index ae3974e..3674eb2 100644
--- a/gocryptfs_main/main.go
+++ b/gocryptfs_main/main.go
@@ -128,11 +128,20 @@ func main() {
fmt.Println(err)
os.Exit(ERREXIT_LOADCONF)
}
- fmt.Printf("Success\n")
+ fmt.Printf("done.\n")
+ }
+
+ srv := pathfsFrontend(key, cipherdir, mountpoint, fusedebug)
+ fmt.Printf("Mounted.\n")
+
+ if zerokey == false {
printMasterKey(key)
}
- pathfsFrontend(key, cipherdir, mountpoint, fusedebug)
+ // Send notification to our parent
+ sendSig()
+ // Jump into server loop
+ srv.Serve()
}
// printMasterKey - remind the user that he should store the master key in
@@ -143,12 +152,13 @@ func printMasterKey(key []byte) {
h = h[0:8] + "-" + h[8:16] + "-" + h[16:24] + "-" + h[24:32]
fmt.Printf(`
-WARNING:
- If the gocryptfs config file becomes corrupted or you ever
- forget your password, there is only one hope for recovery:
- The master key. Print it to a piece of paper and store it in a drawer.
+ATTENTION:
+
+ Your master key is: %s
- Master key: %s
+If the gocryptfs.conf file becomes corrupted or you ever forget your password,
+there is only one hope for recovery: The master key. Print it to a piece of
+paper and store it in a drawer.
`, h)
}
@@ -171,7 +181,7 @@ func readPassword() string {
fd := int(os.Stdin.Fd())
p, err := terminal.ReadPassword(fd)
if err != nil {
- fmt.Printf("Error: Could not read password: %s\n")
+ fmt.Printf("Error: Could not read password: %v\n", err)
os.Exit(ERREXIT_PASSWORD)
}
return string(p)
@@ -189,7 +199,7 @@ func dirEmpty(dir string) bool {
return false
}
-func pathfsFrontend(key []byte, cipherdir string, mountpoint string, debug bool) {
+func pathfsFrontend(key []byte, cipherdir string, mountpoint string, debug bool) *fuse.Server {
finalFs := pathfs_frontend.NewFS(key, cipherdir, USE_OPENSSL)
pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}
@@ -210,13 +220,12 @@ func pathfsFrontend(key []byte, cipherdir string, mountpoint string, debug bool)
// Second column, "Type", will be shown as "fuse." + Name
mOpts.Name = "gocryptfs"
- state, err := fuse.NewServer(conn.RawFS(), mountpoint, &mOpts)
+ srv, err := fuse.NewServer(conn.RawFS(), mountpoint, &mOpts)
if err != nil {
- fmt.Printf("Mount fail: %v\n", err)
+ fmt.Printf("Mount failed: %v", err)
os.Exit(1)
}
- state.SetDebug(debug)
+ srv.SetDebug(debug)
- fmt.Println("Mounted.")
- state.Serve()
+ return srv
}
diff --git a/gocryptfs_main/sendsig.go b/gocryptfs_main/sendsig.go
new file mode 100644
index 0000000..98bd448
--- /dev/null
+++ b/gocryptfs_main/sendsig.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "syscall"
+ "bytes"
+ "fmt"
+ "os"
+ "io/ioutil"
+)
+
+// cmdline looks like this: /bin/bash \0 /path/to/gocryptfs \0 --zerokey \0 ...
+const (
+ WRAPPER_PREFIX = "/bin/bash\000"
+ WRAPPER_CONTAINS = "gocryptfs\000"
+)
+
+// Send USR1 to the "gocryptfs" wrapper shell script. This notifies it that the
+// mounting has completed sucessfully.
+//
+// Checks /proc/$PPID/cmdline to make sure we do not kill an unrelated process.
+func sendSig() {
+ ppid := os.Getppid()
+ fn := fmt.Sprintf("/proc/%d/cmdline", ppid)
+ cmdline, err := ioutil.ReadFile(fn)
+ if err != nil {
+ fmt.Printf("sendSig: ReadFile: %v\n", err)
+ return
+ }
+ if bytes.HasPrefix(cmdline, []byte(WRAPPER_PREFIX)) && bytes.Contains(cmdline, []byte(WRAPPER_CONTAINS)) {
+ p, err := os.FindProcess(ppid)
+ if err != nil {
+ fmt.Printf("sendSig: FindProcess: %v\n", err)
+ return
+ }
+ err = p.Signal(syscall.SIGUSR1)
+ if err != nil {
+ fmt.Printf("sendSig: Signal: %v\n", err)
+ }
+ } else {
+ fmt.Printf("Not running under the gocryptfs wrapper - will not daemonize\n")
+ }
+}