summaryrefslogtreecommitdiffstats
path: root/krebs/5pkgs/simple/ecrypt/default.nix
blob: f83f8cfe70971fe6a1bb6f5b04d52e448b3b2461 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
{ pkgs, lib }:

#usage: ecrypt mount /var/crypted /var/unencrypted
pkgs.writers.writeDashBin "ecrypt" ''
  set -euf

  PATH=${lib.makeBinPath (with pkgs; [
    coreutils
    ecryptfs
    gnused
    gnugrep
    jq
    mount
    keyutils
    umount
  ])}

  # turn echo back on if killed
  trap 'stty echo' INT

  case "$1" in
    init)
      shift
      mkdir -p "$1" "$2"

      # abort if src or dest are not empty
      if [ -e "$1"/.cfg.json ]; then
        echo 'source dir is already configured, aborting'
        exit 1
      elif ls -1qA "$2" | grep -q .; then
        echo 'destination dir is not empty, aborting'
        exit 1
      else
        # we start and exit ecryptfs-manager again to circumvent a bug where mounting the ecryptfs fails
        echo 4 | ecryptfs-manager
        stty -echo
        printf "passphrase: "
        read  passphrase
        stty echo
        sig=$(echo "$passphrase" | ecryptfs-add-passphrase | grep 'Inserted auth tok' | sed 's/.*\[\(.*\)\].*/\1/')
        mount -t ecryptfs \
          -o ecryptfs_unlink_sigs,ecryptfs_fnek_sig="$sig",ecryptfs_key_bytes=16,ecryptfs_cipher=aes,ecryptfs_sig="$sig" \
          "$1" "$2"

        # add sig to json state file
        jq -n --arg sig "$sig" '{ "sig": $sig }' > "$1"/.cfg.json
      fi
      ;;

    mount)
      shift
      if ! [ -e "$1"/.cfg.json ]; then
        echo '.cfg.json missing in src'
        exit 1
      fi
      old_sig=$(cat "$1"/.cfg.json | jq -r .sig)

      # check if key is already in keyring, otherwise add it
      
      if keyctl list @u | grep -q "$old_sig"; then
        echo 'pw already saved'
      else
        # we start and exit ecryptfs-manager again to circumvent a bug where mounting the ecryptfs fails
        echo 4 | ecryptfs-manager
        stty -echo
        printf "passphrase: "
        read  passphrase
        stty echo
        new_sig=$(echo "$passphrase" | ecryptfs-add-passphrase | grep 'Inserted auth tok' | sed 's/.*\[\(.*\)\].*/\1/')

        # check if passphrase matches sig
        if [ "$old_sig" != "$new_sig" ]; then
          echo 'passphrase does not match sig, bailing out'
          new_keyid=$(keyctl list @u | grep "$new_sig" | sed 's/\([0-9]*\).*/\1/')
          keyctl revoke "$new_keyid"
          keyctl unlink "$new_keyid"
          exit 1
        fi
      fi

      sig=$old_sig
      keyid=$(keyctl list @u | grep "$sig" | sed 's/\([0-9]*\).*/\1/')
      if (ls -1qA "$2" | grep -q .); then
        echo 'destination is not empty, bailing out'
        exit 1
      else
        mount -i -t ecryptfs \
          -o ecryptfs_passthrough=no,verbose=no,ecryptfs_unlink_sigs,ecryptfs_fnek_sig="$sig",ecryptfs_key_bytes=16,ecryptfs_cipher=aes,ecryptfs_sig="$sig" \
          "$1" "$2"
      fi
      ;;

    unmount)
      shift

      sig=$(cat "$1"/.cfg.json | jq -r .sig)
      keyid=$(keyctl list @u | grep "$sig" | sed 's/\s*\([0-9]*\).*/\1/')

      umount "$2" || :
      keyctl revoke "$keyid"
      keyctl unlink "$keyid"
      ;;

    *)
      echo 'usage:
        ecrypt init /tmp/src/ /tmp/dst/
        ecrypt mount /tmp/src/ /tmp/dst/
        ecrypt unmount /tmp/src/ /tmp/dst/
      '
  esac
''