@@ 10,7 10,9 @@ mounting them painlessly (i.e. no passwo
automount solutions like *pam-encfs* and *pam-mount* which require to use the
same password for EncFS folders as for your local user account. This is bad
because local account passwords usually are weaker than those one should use
-for encrypting online stored data, e.g. in a [Dropbox][dbx].
+for encrypting online stored data, e.g. in a [Dropbox][dbx]. In this case, you
+can also move your EncFs config files (.encfs5 or .encfs6.xml) outside their
+EncFS folders to increase security so they are not stored online (See below).
[![Flattr this][flattr-img]][flattr-url]
@@ 50,6 52,25 @@ mounted to `~/Private`. Make it known to
This adds the EncFS path, its mount location and password to the GNOME keyring
and sets up a GNOME autostart entry to mount it at GNOME login (if enabled).
+### Add an EncFS folder with a custom location EncFs config file
+
+Suppose you have an EncFS folder at `~/.Private.encrypted` which should get
+mounted to `~/Private`.
+
+And suppose you move the EncFS config file (.encfs5 or .encfs6.xml), from
+`~/.Private.encrypted/.encfs6.xml` to `~/Private_encfs6.xml`.
+
+Make it known to *gnome-encfs*:
+
+ $ gnome-encfs -a ~/.Private.encrypted ~/Private
+ Custom EncFS config file path [**Default location**]: ~/Private_encfs6.xml
+ EncFS password: <enter encfs password>
+ Mount at login [Y/n]: <say 'y' or 'n'>
+
+This adds the EncFS path, its mount location, the location of its EncFS config
+file and password to the GNOME keyring and sets up a GNOME autostart entry to
+mount it at GNOME login (if enabled).
+
### Mount an EncFS folder
If you said *y* above to the login mount question, the EncFS folder gets
@@ 47,6 47,7 @@ class preset:
epath = None
mpoint = None
amount = None
+ encfs_config =None
# =============================================================================
# constants
@@ 113,6 114,8 @@ def _options():
help="Input for mount point edit")
og.add_option("", "--amount", default=None,
help="Input for auto mount question")
+ og.add_option("", "--encfs-config", default=None,
+ help="Input for custom EncFS config file path (Use 'default' to reset path to its default value during an edit)")
op.add_option_group(og)
opts, args = op.parse_args()
@@ 149,6 152,7 @@ def _options():
preset.epath = opts.epath
preset.mpoint = opts.mpoint
preset.amount = opts.amount
+ preset.encfs_config = opts.encfs_config
return opts
@@ 172,6 176,21 @@ def _pathify(path):
path = os.path.realpath(path)
return path
+def _setup_env(encfs_config):
+ """Set up a custom environnemnt for encfs process"""
+
+ custom_env = None
+ if encfs_config:
+ custom_env = os.environ.copy()
+ cmd = ["file", "-b", "--mime-type", encfs_config]
+ p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ mime_type = p.communicate()[0].strip()
+ if mime_type == 'application/xml':
+ custom_env["ENCFS6_CONFIG"] = encfs_config
+ else:
+ custom_env["ENCFS5_CONFIG"] = encfs_config
+ return custom_env
+
def _is_mounted(mpoint):
"""Check of something is mounted at given mount point."""
@@ 182,11 201,12 @@ def _is_mounted(mpoint):
points = [os.path.abspath(p) for p in points]
return os.path.abspath(mpoint) in points
-def _is_encfs(epath):
+def _is_encfs(epath, encfs_config=None):
"""Check if 'epath' points to an EncFS directory."""
+ encfs_env = _setup_env(encfs_config)
p = subprocess.Popen(["encfsctl", "info", epath], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ stderr=subprocess.PIPE, env=encfs_env)
p.communicate()
return p.returncode == 0
@@ 264,26 284,45 @@ def list_items(path=None):
epath = item.attributes["encfs-path"]
mpoint = item.attributes["mount-point"]
amount = item.attributes["auto-mount"]
+ encfs_config = item.attributes.get("encfs-config", None)
print("* encfs path : %s" % epath)
print(" mount point : %s" % mpoint)
print(" mount at login : %s" % (amount == "y" and "yes" or "no"))
+ if encfs_config:
+ print(" Custom EncFS config file path : %s" % encfs_config)
return True
def add_item(epath, mpoint):
"""Add new EncFS item to keyring."""
- if not _is_encfs(epath):
- _proceed("no EncFS at given path")
if not os.path.isdir(mpoint):
_proceed("mount point is not a directory")
if _get_items(mpoint=mpoint):
_proceed("mount point already in keyring")
+
+ encfs_config = None
+ if not _is_encfs(epath):
+ # Either epath is not an EncFS stash, or EncFS config file is elsewhere
+ encfs_config = preset.encfs_config or raw_input("Custom EncFS config file path [**Default location**]: ") or None
+ if ''.join(encfs_config).strip().lower() == "default":
+ encfs_config = None
+ if encfs_config:
+ encfs_config = _pathify(encfs_config)
+ if not os.path.isfile(encfs_config):
+ _proceed("Custom EncFS config file path is not a file")
+ if not _is_encfs(epath, encfs_config):
+ _proceed("no EncFS at given path")
secret = preset.password or getpass.getpass("EncFS password: ")
amount = preset.amount or raw_input("Mount at login [Y/n]: ") or "y"
amount = amount.strip()[0].lower() == "y" and "y" or "n"
- attr = {"encfs-path": epath, "mount-point": mpoint, "auto-mount": amount}
+ if encfs_config:
+ attr = {"encfs-path": epath, "mount-point": mpoint,
+ "auto-mount": amount, "encfs-config": encfs_config}
+ else:
+ attr = {"encfs-path": epath, "mount-point": mpoint,
+ "auto-mount": amount}
attr.update(GENCFS_ATTR)
name = "EncFS mount at %s" % mpoint
gk.item_create_sync(KEYRING, ITYPE, name, attr, secret, False)
@@ 309,20 348,33 @@ def edit_item(mpoint):
epath = item.attributes["encfs-path"]
mpoint = item.attributes["mount-point"]
amount = item.attributes["auto-mount"]
+ encfs_config = item.attributes.get("encfs-config", "default")
+
epath = preset.epath or raw_input("EncFS path [%s]: " % epath) or epath
mpoint = preset.mpoint or raw_input("Mount point [%s]: " % mpoint) or mpoint
+ hint = encfs_config if (encfs_config != "default") else "**Default location**"
+ encfs_config = preset.encfs_config \
+ or raw_input("Custom EncFS config file path - Type 'default' for the default " +
+ "location under EncFS path [%s]: " % hint) \
+ or encfs_config
+ if ''.join(encfs_config).strip().lower() == "default":
+ encfs_config = None
secret = preset.password or getpass.getpass("Password [**current**]: ") or item.secret
hint = amount == "y" and "Y/n" or "y/N"
amount = preset.amount or raw_input("Mount at login [%s]: " % hint) or amount
amount = amount.strip()[0].lower() == "y" and "y" or "n"
mpoint = _pathify(mpoint)
epath = _pathify(epath)
-
+ if encfs_config:
+ encfs_config = _pathify(encfs_config)
+
# check item data
for other in [i for i in items if i.item_id != item.item_id]:
if other.attributes["mount-point"] == mpoint:
_proceed("mount point already in use")
- if not _is_encfs(epath):
+ if encfs_config and not os.path.isfile(encfs_config):
+ _proceed("EncFS config file path is not a file")
+ if not _is_encfs(epath, encfs_config):
_proceed("no EncFS at given path")
if not os.path.isdir(mpoint):
_proceed("mount point is not a directory")
@@ 332,6 384,8 @@ def edit_item(mpoint):
attributes["encfs-path"] = epath
attributes["mount-point"] = mpoint
attributes["auto-mount"] = amount
+ if encfs_config:
+ attributes["encfs-config"] = encfs_config
gk.item_set_attributes_sync(KEYRING, item.item_id, attributes)
info = gk.item_get_info_sync(KEYRING, item.item_id)
info.set_secret(secret)
@@ 378,15 432,22 @@ def mount_items(path, autostart):
for item in items:
epath = item.attributes["encfs-path"]
mpoint = item.attributes["mount-point"]
- msg = "Mounting %s at %s: " % (epath, mpoint)
+ encfs_config = item.attributes.get("encfs-config", None)
+
+ if encfs_config:
+ msg = "Mounting %s at %s with custom EncFS config file %s: " % (epath, mpoint, encfs_config)
+ else:
+ msg = "Mounting %s at %s: " % (epath, mpoint)
+
if _is_mounted(mpoint):
msg += "mount point already in use"
elif not os.path.isdir(mpoint):
msg += "mount point does not exist or is not a directory"
rc = False
else:
+ encfs_env = _setup_env(encfs_config)
cmd = ["encfs", "-o", "nonempty", "-S", epath, mpoint]
- p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
+ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, env=encfs_env)
p.communicate(input="%s\n" % item.secret)
msg += p.returncode and "FAILED" or "OK"
rc &= not p.returncode
@@ 145,6 145,54 @@ Icon=folder
# EXPECT: 1 succeeding edits
# EXPECT: autostart off
autostart off
+# EXPECT: succeeding add with a custom EncFS5 config file (1)
+# EXPECT: 1 listed item (1)
+* encfs path : ./tenv/e1
+ mount point : ./tenv/m1
+ mount at login : no
+ Custom EncFS config file path : ./tenv/e1_encfs5
+# EXPECT: 1 succeeding mounts (1)
+Mounting ./tenv/e1_encfs5: OK
+# EXPECT: 1 mounted paths (1)
+encfs on ./tenv/m1 type fuse.encfs (rw,nosuid,nodev,default_permissions,)
+# EXPECT: no mounted paths - all unmounted
+# EXPECT: succeeding edit to set back EncFS5 config file to its default location (1)
+# EXPECT: 1 listed item (1)
+* encfs path : ./tenv/e1
+ mount point : ./tenv/m1
+ mount at login : no
+# EXPECT: succeeding edit with a custom EncFS5 config file (1)
+# EXPECT: 1 listed item (1)
+* encfs path : ./tenv/e1
+ mount point : ./tenv/m1
+ mount at login : no
+ Custom EncFS config file path : ./tenv/e1_encfs5
+# EXPECT: succeeding remove (1)
+# EXPECT: 0 items
+# EXPECT: succeeding add with a custom EncFS6 config file (1)
+# EXPECT: 1 listed item (2)
+* encfs path : ./tenv/e2
+ mount point : ./tenv/m2
+ mount at login : no
+ Custom EncFS config file path : ./tenv/e2_encfs6.xml
+# EXPECT: 1 succeeding mounts (2)
+Mounting ./tenv/e2_encfs6.xml: OK
+# EXPECT: 1 mounted paths (2)
+encfs on ./tenv/m2 type fuse.encfs (rw,nosuid,nodev,default_permissions,)
+# EXPECT: no mounted paths - all unmounted
+# EXPECT: succeeding edit to set back EncFS6 config file to its default location (2)
+# EXPECT: 1 listed item (2)
+* encfs path : ./tenv/e2
+ mount point : ./tenv/m2
+ mount at login : no
+# EXPECT: succeeding edit with a custom EncFS6 config file (2)
+# EXPECT: 1 listed item (2)
+* encfs path : ./tenv/e2
+ mount point : ./tenv/m2
+ mount at login : no
+ Custom EncFS config file path : ./tenv/e2_encfs6.xml
+# EXPECT: succeeding remove (2)
+# EXPECT: 0 items
# EXPECT: no listed items
# EXPECT: autostart off
autostart off
@@ 84,11 84,11 @@ mount | grep "/tenv/m[0-9]" | sed -e "s/
expect "3 items (1,2,3b)"
$GENCFS -l
-$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m3a --amount y
+$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m3a --amount y --encfs-config default
expect "3 items (1,2,3a)"
$GENCFS -l
-$GENCFS -e $TENV/m3a --password px --epath $TENV/e3 --mpoint $TENV/m3a --amount y
+$GENCFS -e $TENV/m3a --password px --epath $TENV/e3 --mpoint $TENV/m3a --amount y --encfs-config default
expect "3 items (1,2,3a)"
$GENCFS -l
@@ 97,7 97,7 @@ expect "1 failing mount (3a) - wrong pas
expect "no mounted paths"
mount | grep "/tenv/m[0-9]" | sed -e "s/user=\w\+//"
-$GENCFS -e $TENV/m3a --password p3 --epath $TENV/e3 --mpoint $TENV/m3b --amount y
+$GENCFS -e $TENV/m3a --password p3 --epath $TENV/e3 --mpoint $TENV/m3b --amount y --encfs-config default
expect "3 items (1,2,3b)"
$GENCFS -l
@@ 112,20 112,20 @@ expect "no mounted paths - all unmounted
mount | grep "/tenv/m[0-9]" | sed -e "s/user=\w\+//"
expect "failing edit (3b->2) - mount point in use"
-$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m2 --proceed n --amount y
+$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m2 --proceed n --amount y --encfs-config default
expect "3 items (1,2,3b)"
$GENCFS -l
expect "autostart on"
test -e autostart.desktop && echo "autostart on" || echo "autostart off"
expect "2 succeeding edits"
-$GENCFS -e $TENV/m1 --password p1 --epath $TENV/e1 --mpoint $TENV/m1 --proceed n --amount n
-$GENCFS -e $TENV/m2 --password p2 --epath $TENV/e2 --mpoint $TENV/m2 --proceed n --amount n
+$GENCFS -e $TENV/m1 --password p1 --epath $TENV/e1 --mpoint $TENV/m1 --proceed n --amount n --encfs-config default
+$GENCFS -e $TENV/m2 --password p2 --epath $TENV/e2 --mpoint $TENV/m2 --proceed n --amount n --encfs-config default
expect "autostart on"
test -e autostart.desktop && echo "autostart on" || echo "autostart off"
expect "autostart content"
cat autostart.desktop
expect "1 succeeding edits"
-$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m3b --proceed n --amount n
+$GENCFS -e $TENV/m3b --password p3 --epath $TENV/e3 --mpoint $TENV/m3b --proceed n --amount n --encfs-config default
expect "autostart off"
test -e autostart.desktop && echo "autostart on" || echo "autostart off"
@@ 133,6 133,82 @@ test -e autostart.desktop && echo "autos
$GENCFS -l | grep "mount point" | grep "/tenv/m[0-9]" | awk {'print $4'} | \
while read MP ; do $GENCFS -r $MP ; done
+# test EncFS config file custom location (encfs5)
+expect "succeeding add with a custom EncFS5 config file (1)"
+mv $TENV/e1/.encfs5 $TENV/e1_encfs5
+$GENCFS -a $TENV/e1 $TENV/m1 --password p1 --proceed n --amount n --encfs-config $TENV/e1_encfs5
+expect "1 listed item (1)"
+$GENCFS -l
+
+expect "1 succeeding mounts (1)"
+$GENCFS -m $TENV/e1
+expect "1 mounted paths (1)"
+mount | grep "/tenv/m[0-9]" | sed -e "s/user=\w\+//"
+
+for MPOINT in $TENV/m1* ; do
+ fusermount -u $MPOINT 2>&1
+done
+expect "no mounted paths - all unmounted"
+mount | grep "/tenv/m[0-9]"
+
+expect "succeeding edit to set back EncFS5 config file to its default location (1)"
+mv $TENV/e1_encfs5 $TENV/e1/.encfs5
+$GENCFS -e $TENV/m1 --password p1 --epath $TENV/e1 --mpoint $TENV/m1 --proceed n --amount n --encfs-config default
+expect "1 listed item (1)"
+$GENCFS -l
+
+expect "succeeding edit with a custom EncFS5 config file (1)"
+mv $TENV/e1/.encfs5 $TENV/e1_encfs5
+$GENCFS -e $TENV/m1 --password p1 --epath $TENV/e1 --mpoint $TENV/m1 --proceed n --amount n --encfs-config $TENV/e1_encfs5
+expect "1 listed item (1)"
+$GENCFS -l
+
+expect "succeeding remove (1)"
+$GENCFS -r $TENV/m1
+mv $TENV/e1_encfs5 $TENV/e1/.encfs5
+expect "0 items"
+$GENCFS -l
+
+# test EncFS config file custom location (encfs6.xml)
+expect "succeeding add with a custom EncFS6 config file (1)"
+mv $TENV/e2/.encfs6.xml $TENV/e2_encfs6.xml
+$GENCFS -a $TENV/e2 $TENV/m2 --password p2 --proceed n --amount n --encfs-config $TENV/e2_encfs6.xml
+expect "1 listed item (2)"
+$GENCFS -l
+
+expect "1 succeeding mounts (2)"
+$GENCFS -m $TENV/e2
+expect "1 mounted paths (2)"
+mount | grep "/tenv/m[0-9]" | sed -e "s/user=\w\+//"
+
+for MPOINT in $TENV/m2* ; do
+ fusermount -u $MPOINT 2>&1
+done
+expect "no mounted paths - all unmounted"
+mount | grep "/tenv/m[0-9]"
+
+expect "succeeding edit to set back EncFS6 config file to its default location (2)"
+mv $TENV/e2_encfs6.xml $TENV/e2/.encfs6.xml
+$GENCFS -e $TENV/m2 --password p2 --epath $TENV/e2 --mpoint $TENV/m2 --proceed n --amount n --encfs-config default
+expect "1 listed item (2)"
+$GENCFS -l
+
+expect "succeeding edit with a custom EncFS6 config file (2)"
+mv $TENV/e2/.encfs6.xml $TENV/e2_encfs6.xml
+$GENCFS -e $TENV/m2 --password p2 --epath $TENV/e2 --mpoint $TENV/m2 --proceed n --amount n --encfs-config $TENV/e2_encfs6.xml
+expect "1 listed item (2)"
+$GENCFS -l
+
+expect "succeeding remove (2)"
+$GENCFS -r $TENV/m2
+mv $TENV/e2_encfs6.xml $TENV/e2/.encfs6.xml
+expect "0 items"
+$GENCFS -l
+
+# clean up keyring
+$GENCFS -l | grep "mount point" | grep "/tenv/m[0-9]" | awk {'print $4'} | \
+ while read MP ; do $GENCFS -r $MP ; done
+
expect "no listed items"
$GENCFS -l
expect "autostart off"