mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 15:33:16 +01:00
Add -c & -u cmdline options (#474)
This commit is contained in:
parent
dcf8435d4c
commit
11aec8f28d
@ -35,6 +35,10 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
@ -222,10 +226,19 @@ ConfigType readConfig_load(ConfigInfo *nm, const char *path,
|
||||
* Try to locate the config file
|
||||
* Tries the most recent format first, then looks for older versions
|
||||
*/
|
||||
ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
|
||||
ConfigType readConfig(const string &rootDir, EncFSConfig *config, const string &cmdConfig) {
|
||||
ConfigInfo *nm = ConfigFileMapping;
|
||||
while (nm->fileName != nullptr) {
|
||||
// allow environment variable to override default config path
|
||||
// allow command line argument to override default config path
|
||||
if (!cmdConfig.empty()) {
|
||||
if (!fileExists(cmdConfig.c_str())) {
|
||||
RLOG(ERROR)
|
||||
<< "fatal: config file specified on command line does not exist: "
|
||||
<< cmdConfig;
|
||||
exit(1);
|
||||
}
|
||||
return readConfig_load(nm, cmdConfig.c_str(), config);
|
||||
} // allow environment variable to override default config path
|
||||
if (nm->environmentOverride != nullptr) {
|
||||
char *envFile = getenv(nm->environmentOverride);
|
||||
if (envFile != nullptr) {
|
||||
@ -433,14 +446,18 @@ bool readV4Config(const char *configFile, EncFSConfig *config,
|
||||
}
|
||||
|
||||
bool saveConfig(ConfigType type, const string &rootDir,
|
||||
const EncFSConfig *config) {
|
||||
const EncFSConfig *config, const string &cmdConfig) {
|
||||
bool ok = false;
|
||||
|
||||
ConfigInfo *nm = ConfigFileMapping;
|
||||
while (nm->fileName != nullptr) {
|
||||
if (nm->type == type && (nm->saveFunc != nullptr)) {
|
||||
string path = rootDir + nm->fileName;
|
||||
if (nm->environmentOverride != nullptr) {
|
||||
if (!cmdConfig.empty()) {
|
||||
// use command line argument if specified
|
||||
path.assign(cmdConfig);
|
||||
}
|
||||
else if (nm->environmentOverride != nullptr) {
|
||||
// use environment file if specified..
|
||||
const char *envFile = getenv(nm->environmentOverride);
|
||||
if (envFile != nullptr) {
|
||||
@ -1199,7 +1216,7 @@ RootPtr createV6Config(EncFS_Context *ctx,
|
||||
return rootInfo;
|
||||
}
|
||||
|
||||
if (!saveConfig(Config_V6, rootDir, config.get())) {
|
||||
if (!saveConfig(Config_V6, rootDir, config.get(), opts->config)) {
|
||||
return rootInfo;
|
||||
}
|
||||
|
||||
@ -1559,7 +1576,7 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
|
||||
RootPtr rootInfo;
|
||||
std::shared_ptr<EncFSConfig> config(new EncFSConfig);
|
||||
|
||||
if (readConfig(opts->rootDir, config.get()) != Config_None) {
|
||||
if (readConfig(opts->rootDir, config.get(), opts->config) != Config_None) {
|
||||
if (config->blockMACBytes == 0 && opts->requireMac) {
|
||||
cout << _(
|
||||
"The configuration disabled MAC, but you passed --require-macs\n");
|
||||
@ -1669,6 +1686,15 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
|
||||
return rootInfo;
|
||||
}
|
||||
|
||||
void unmountFS(const char *mountPoint) {
|
||||
// fuse_unmount succeeds and returns void
|
||||
fuse_unmount(mountPoint, nullptr);
|
||||
#ifdef __APPLE__
|
||||
// fuse_unmount does not work on Mac OS, see #428
|
||||
unmount(mountPoint, MNT_FORCE);
|
||||
#endif
|
||||
}
|
||||
|
||||
int remountFS(EncFS_Context *ctx) {
|
||||
VLOG(1) << "Attempting to reinitialize filesystem";
|
||||
|
||||
@ -1689,13 +1715,8 @@ bool unmountFS(EncFS_Context *ctx) {
|
||||
ctx->setRoot(std::shared_ptr<DirNode>());
|
||||
return false;
|
||||
}
|
||||
// Time to unmount!
|
||||
#if FUSE_USE_VERSION < 30
|
||||
fuse_unmount(ctx->opts->mountPoint.c_str(), nullptr);
|
||||
#else
|
||||
fuse_unmount(fuse_get_context()->fuse);
|
||||
#endif
|
||||
// fuse_unmount succeeds and returns void
|
||||
// Time to unmount!
|
||||
unmountFS(ctx->opts->mountPoint.c_str());
|
||||
RLOG(INFO) << "Filesystem inactive, unmounted: " << ctx->opts->mountPoint;
|
||||
return true;
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ struct EncFS_Opts {
|
||||
bool idleTracking; // turn on idle monitoring of filesystem
|
||||
bool mountOnDemand; // mounting on-demand
|
||||
bool delayMount; // delay initial mount
|
||||
bool unmount; // unmount
|
||||
|
||||
bool checkKey; // check crypto key decoding
|
||||
bool forceDecode; // force decode on MAC block failures
|
||||
@ -98,12 +99,14 @@ struct EncFS_Opts {
|
||||
bool requireMac; // Throw an error if MAC is disabled
|
||||
|
||||
ConfigMode configMode;
|
||||
std::string config; // path to configuration file (or empty)
|
||||
|
||||
EncFS_Opts() {
|
||||
createIfNotFound = true;
|
||||
idleTracking = false;
|
||||
mountOnDemand = false;
|
||||
delayMount = false;
|
||||
unmount = false;
|
||||
checkKey = true;
|
||||
forceDecode = false;
|
||||
useStdin = false;
|
||||
@ -120,19 +123,21 @@ struct EncFS_Opts {
|
||||
/*
|
||||
Read existing config file. Looks for any supported configuration version.
|
||||
*/
|
||||
ConfigType readConfig(const std::string &rootDir, EncFSConfig *config);
|
||||
ConfigType readConfig(const std::string &rootDir, EncFSConfig *config, const std::string &cmdConfig);
|
||||
|
||||
/*
|
||||
Save the configuration. Saves back as the same configuration type as was
|
||||
read from.
|
||||
*/
|
||||
bool saveConfig(ConfigType type, const std::string &rootdir,
|
||||
const EncFSConfig *config);
|
||||
const EncFSConfig *config, const std::string &cmdConfig);
|
||||
|
||||
class EncFS_Context;
|
||||
|
||||
RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts);
|
||||
|
||||
void unmountFS(const char *mountPoint);
|
||||
|
||||
RootPtr createV6Config(EncFS_Context *ctx,
|
||||
const std::shared_ptr<EncFS_Opts> &opts);
|
||||
|
||||
|
@ -16,11 +16,11 @@ encfs - mounts or creates an encrypted virtual filesystem
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<encfs> [B<--version>] [B<-v>|B<--verbose>] [B<-t>|B<--syslogtag>]
|
||||
B<encfs> [B<--version>] [B<-v>|B<--verbose>] [B<-c>|B<--config>] [B<-t>|B<--syslogtag>]
|
||||
[B<-s>] [B<-f>] [B<--annotate>] [B<--standard>] [B<--paranoia>]
|
||||
[B<--reverse>] [B<--reversewrite>] [B<--extpass=program>] [B<-S>|B<--stdinpass>]
|
||||
[B<--anykey>] [B<--forcedecode>] [B<-require-macs>]
|
||||
[B<-i MINUTES>|B<--idle=MINUTES>] [B<-m>|B<--ondemand>] [B<--delaymount>]
|
||||
[B<-i MINUTES>|B<--idle=MINUTES>] [B<-m>|B<--ondemand>] [B<--delaymount>] [B<-u>|B<--unmount>]
|
||||
[B<--public>] [B<--nocache>] [B<--no-default-flags>]
|
||||
[B<-o FUSE_OPTION>] [B<-d>|B<--fuse-debug>] [B<-H>|B<--fuse-help>]
|
||||
I<rootdir> I<mountPoint>
|
||||
@ -48,6 +48,10 @@ may be an increasing number of choices.
|
||||
Shows B<EncFS> version. Using B<--verbose> before B<--version> may display
|
||||
additional information.
|
||||
|
||||
=item B<-c>, B<--config>
|
||||
|
||||
Causes B<EncFS> to use the supplied file as the configuration file.
|
||||
|
||||
=item B<-v>, B<--verbose>
|
||||
|
||||
Causes B<EncFS> to enable logging of various debug channels within B<EncFS>.
|
||||
@ -204,6 +208,10 @@ password. If this succeeds, then the filesystem becomes available again.
|
||||
Do not mount the filesystem when encfs starts; instead, delay mounting until
|
||||
first use. This option only makes sense with B<--ondemand>.
|
||||
|
||||
=item B<-u>, B<--unmount>
|
||||
|
||||
Unmounts the specified I<mountPoint>.
|
||||
|
||||
=item B<--public>
|
||||
|
||||
Attempt to make encfs behave as a typical multi-user filesystem. By default,
|
||||
|
@ -165,7 +165,7 @@ static int showInfo(int argc, char **argv) {
|
||||
if (!checkDir(rootDir)) return EXIT_FAILURE;
|
||||
|
||||
std::shared_ptr<EncFSConfig> config(new EncFSConfig);
|
||||
ConfigType type = readConfig(rootDir, config.get());
|
||||
ConfigType type = readConfig(rootDir, config.get(), "");
|
||||
|
||||
// show information stored in config..
|
||||
switch (type) {
|
||||
@ -637,7 +637,7 @@ static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc,
|
||||
if (!checkDir(rootDir)) return EXIT_FAILURE;
|
||||
|
||||
EncFSConfig *config = new EncFSConfig;
|
||||
ConfigType cfgType = readConfig(rootDir, config);
|
||||
ConfigType cfgType = readConfig(rootDir, config, "");
|
||||
|
||||
if (cfgType == Config_None) {
|
||||
cout << _("Unable to load or parse config file\n");
|
||||
@ -698,7 +698,7 @@ static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc,
|
||||
config->assignKeyData(keyBuf, encodedKeySize);
|
||||
delete[] keyBuf;
|
||||
|
||||
if (saveConfig(cfgType, rootDir, config)) {
|
||||
if (saveConfig(cfgType, rootDir, config, "")) {
|
||||
// password modified -- changes volume key of filesystem..
|
||||
cout << _("Volume Key successfully updated.\n");
|
||||
result = EXIT_SUCCESS;
|
||||
|
@ -162,6 +162,10 @@ static void usage(const char *name) {
|
||||
"reverse encryption\n")
|
||||
<< _(" --reversewrite\t\t"
|
||||
"reverse encryption with writes enabled\n")
|
||||
<< _(" -c, --config=path\t\t"
|
||||
"specifies config file (overrides ENV variable)\n")
|
||||
<< _(" -u, --unmount\t\t"
|
||||
"unmounts specified mountPoint\n")
|
||||
|
||||
// xgroup(usage)
|
||||
<< _(" --extpass=program\tUse external program for password prompt\n"
|
||||
@ -217,6 +221,7 @@ static bool processArgs(int argc, char *argv[],
|
||||
out->opts->annotate = false;
|
||||
out->opts->reverseEncryption = false;
|
||||
out->opts->requireMac = false;
|
||||
out->opts->unmount = false;
|
||||
|
||||
bool useDefaultFlags = true;
|
||||
|
||||
@ -255,6 +260,8 @@ static bool processArgs(int argc, char *argv[],
|
||||
{"standard", 0, nullptr, '1'}, // standard configuration
|
||||
{"paranoia", 0, nullptr, '2'}, // standard configuration
|
||||
{"require-macs", 0, nullptr, LONG_OPT_REQUIRE_MAC}, // require MACs
|
||||
{"config", 1, nullptr, 'c'}, // command-line-supplied config location
|
||||
{"unmount", 1, nullptr, 'u'}, // unmount
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
while (true) {
|
||||
@ -269,8 +276,10 @@ static bool processArgs(int argc, char *argv[],
|
||||
// 'S' : password from stdin
|
||||
// 'o' : arguments meant for fuse
|
||||
// 't' : syslog tag
|
||||
// 'c' : configuration file
|
||||
// 'u' : unmount
|
||||
int res =
|
||||
getopt_long(argc, argv, "HsSfvdmi:o:t:", long_options, &option_index);
|
||||
getopt_long(argc, argv, "HsSfvdmi:o:t:c:u", long_options, &option_index);
|
||||
|
||||
if (res == -1) {
|
||||
break;
|
||||
@ -298,6 +307,14 @@ static bool processArgs(int argc, char *argv[],
|
||||
case LONG_OPT_REQUIRE_MAC:
|
||||
out->opts->requireMac = true;
|
||||
break;
|
||||
case 'c':
|
||||
/* Take config file path from command
|
||||
* line instead of ENV variable */
|
||||
out->opts->config.assign(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
out->opts->unmount = true;
|
||||
break;
|
||||
case 'f':
|
||||
out->isDaemon = false;
|
||||
// this option was added in fuse 2.x
|
||||
@ -376,7 +393,7 @@ static bool processArgs(int argc, char *argv[],
|
||||
break;
|
||||
case 'P':
|
||||
if (geteuid() != 0) {
|
||||
RLOG(WARNING) << "option '--public' ignored for non-root user";
|
||||
cerr << "option '--public' ignored for non-root user";
|
||||
} else {
|
||||
out->opts->ownerCreate = true;
|
||||
// add 'allow_other' option
|
||||
@ -407,7 +424,7 @@ static bool processArgs(int argc, char *argv[],
|
||||
// missing parameter for option..
|
||||
break;
|
||||
default:
|
||||
RLOG(WARNING) << "getopt error: " << res;
|
||||
cerr << "getopt error: " << res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -416,6 +433,17 @@ static bool processArgs(int argc, char *argv[],
|
||||
PUSHARG("-s");
|
||||
}
|
||||
|
||||
// for --unmount, we should have exactly 1 argument - the mount point
|
||||
if (out->opts->unmount) {
|
||||
if (optind + 1 == argc) {
|
||||
out->opts->mountPoint = slashTerminate(argv[optind++]);
|
||||
return true;
|
||||
}
|
||||
// no mount point specified
|
||||
cerr << _("Expecting one argument, aborting.") << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// we should have at least 2 arguments left over - the source directory and
|
||||
// the mount point.
|
||||
if (optind + 2 <= argc) {
|
||||
@ -425,7 +453,7 @@ static bool processArgs(int argc, char *argv[],
|
||||
out->opts->mountPoint = slashTerminate(argv[optind++]);
|
||||
} else {
|
||||
// no mount point specified
|
||||
cerr << _("Missing one or more arguments, aborting.");
|
||||
cerr << _("Missing one or more arguments, aborting.") << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -575,6 +603,13 @@ int main(int argc, char *argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Let's unmount if requested
|
||||
if (encfsArgs->opts->unmount) {
|
||||
unmountFS(encfsArgs->opts->mountPoint.c_str());
|
||||
cout << "Filesystem unmounting: " << encfsArgs->opts->mountPoint << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
encfs::initLogging(encfsArgs->isVerbose, encfsArgs->isDaemon);
|
||||
ELPP_INITIALIZE_SYSLOG(encfsArgs->syslogTag.c_str(), LOG_PID, LOG_USER);
|
||||
|
||||
|
@ -2,13 +2,7 @@
|
||||
# works on Linux AND OSX
|
||||
sub portable_unmount {
|
||||
my $crypt = shift;
|
||||
my $fusermount = qx(which fusermount);
|
||||
chomp($fusermount);
|
||||
if(-f $fusermount) {
|
||||
qx($fusermount -u "$crypt");
|
||||
} else {
|
||||
qx(umount "$crypt");
|
||||
}
|
||||
qx(./build/encfs -u "$crypt" >/dev/null);
|
||||
}
|
||||
|
||||
# Helper function
|
||||
|
@ -441,8 +441,9 @@ sub create_unmount_remount
|
||||
# Unmount
|
||||
portable_unmount($mnt);
|
||||
|
||||
# Mount again
|
||||
system("./build/encfs --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||
# Mount again, testing -c as the same time
|
||||
rename("$crypt/.encfs6.xml", "$crypt/.encfs6_moved.xml");
|
||||
system("./build/encfs -c $crypt/.encfs6_moved.xml --extpass=\"echo test\" $crypt $mnt 2>&1");
|
||||
ok( $? == 0, "encfs command returns 0") || return;
|
||||
|
||||
# Check if content is still there
|
||||
|
Loading…
Reference in New Issue
Block a user