static int selectBlockSize(const CipherV1::CipherAlgorithm &alg) { if (alg.blockSize.min() == alg.blockSize.max()) { cout << autosprintf( // xgroup(setup) _("Using filesystem block size of %i bytes"), alg.blockSize.min()) << "\n"; return alg.blockSize.min(); } cout << autosprintf( // xgroup(setup) _("Select a block size in bytes. The cipher you have chosen\n" "supports sizes from %i to %i bytes in increments of %i.\n" "Or just hit enter for the default (%i bytes)\n"), alg.blockSize.min(), alg.blockSize.max(), alg.blockSize.inc(), DefaultBlockSize); // xgroup(setup) cout << "\n" << _("filesystem block size: "); int blockSize = DefaultBlockSize; char answer[10]; char *res = fgets(answer, sizeof(answer), stdin); cout << "\n"; if (res != 0 && atoi(answer) >= alg.blockSize.min()) blockSize = atoi(answer); blockSize = alg.blockSize.closest(blockSize); // xgroup(setup) cout << autosprintf(_("Using filesystem block size of %i bytes"), blockSize) << "\n\n"; return blockSize; }
int main(int argc, char **argv) { encfs::init_mpool_mutex(); START_EASYLOGGINGPP(argc, argv); encfs::initLogging(); #if defined(ENABLE_NLS) && defined(LOCALEDIR) setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif SSL_load_error_strings(); SSL_library_init(); if (argc < 2) { usage(argv[0]); return EXIT_FAILURE; } // Skip over uninteresting args. while (argc > 2 && *argv[1] == '-') { VLOG(1) << "skipping arg " << argv[1]; argc--; argv[1] = argv[0]; argv++; } if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) { // default command when only 1 argument given -- treat the argument as // a directory.. return showInfo(argc, argv); } else { // find the specified command int offset = 0; while (commands[offset].name != 0) { if (!strcmp(argv[1], commands[offset].name)) break; ++offset; } if (commands[offset].name == 0) { cerr << autosprintf(_("invalid command: \"%s\""), argv[1]) << "\n"; } else { if ((argc - 2 < commands[offset].minOptions) || (argc - 2 > commands[offset].maxOptions)) { cerr << autosprintf( _("Incorrect number of arguments for command \"%s\""), argv[1]) << "\n"; } else return (*commands[offset].func)(argc - 1, argv + 1); } } return EXIT_FAILURE; }
static int selectKeySize( const CipherV1::CipherAlgorithm &alg ) { if(alg.keyLength.min() == alg.keyLength.max()) { cout << autosprintf(_("Using key size of %i bits"), alg.keyLength.min()) << "\n"; return alg.keyLength.min(); } cout << autosprintf( // xgroup(setup) _("Please select a key size in bits. The cipher you have chosen\n" "supports sizes from %i to %i bits in increments of %i bits.\n" "For example: "), alg.keyLength.min(), alg.keyLength.max(), alg.keyLength.inc()) << "\n"; int numAvail = (alg.keyLength.max() - alg.keyLength.min()) / alg.keyLength.inc(); if(numAvail < 5) { // show them all for(int i=0; i<=numAvail; ++i) { if(i) cout << ", "; cout << alg.keyLength.min() + i * alg.keyLength.inc(); } } else { // partial for(int i=0; i<3; ++i) { if(i) cout << ", "; cout << alg.keyLength.min() + i * alg.keyLength.inc(); } cout << " ... " << alg.keyLength.max() - alg.keyLength.inc(); cout << ", " << alg.keyLength.max(); } // xgroup(setup) cout << "\n" << _("Selected key size: "); char answer[10]; char *res = fgets( answer, sizeof(answer), stdin ); int keySize = (res == 0 ? 0 : atoi( answer )); cout << "\n"; keySize = alg.keyLength.closest( keySize ); // xgroup(setup) cout << autosprintf(_("Using key size of %i bits"), keySize) << "\n\n"; return keySize; }
static int showInfo(int argc, char **argv) { (void)argc; string rootDir = argv[1]; if (!checkDir(rootDir)) return EXIT_FAILURE; shared_ptr<EncFSConfig> config(new EncFSConfig); ConfigType type = readConfig(rootDir, config); // show information stored in config.. switch (type) { case Config_None: // xgroup(diag) cout << _("Unable to load or parse config file\n"); return EXIT_FAILURE; case Config_Prehistoric: // xgroup(diag) cout << _( "A really old EncFS filesystem was found. \n" "It is not supported in this EncFS build.\n"); return EXIT_FAILURE; case Config_V3: // xgroup(diag) cout << "\n" << autosprintf(_("Version 3 configuration; " "created by %s\n"), config->creator.c_str()); break; case Config_V4: // xgroup(diag) cout << "\n" << autosprintf(_("Version 4 configuration; " "created by %s\n"), config->creator.c_str()); break; case Config_V5: // xgroup(diag) cout << "\n" << autosprintf(_("Version 5 configuration; " "created by %s (revision %i)\n"), config->creator.c_str(), config->subVersion); break; case Config_V6: // xgroup(diag) cout << "\n" << autosprintf(_("Version 6 configuration; " "created by %s (revision %i)\n"), config->creator.c_str(), config->subVersion); break; } showFSInfo(config); return EXIT_SUCCESS; }
int main(int argc, char **argv) { RLogInit(argc, argv); #if defined(ENABLE_NLS) && defined(LOCALEDIR) setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif SSL_load_error_strings(); SSL_library_init(); StdioNode *slog = new StdioNode(STDERR_FILENO); slog->subscribeTo(GetGlobalChannel("error")); slog->subscribeTo(GetGlobalChannel("warning")); if (argc < 2) { usage(argv[0]); return EXIT_FAILURE; } if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) { // default command when only 1 argument given -- treat the argument as // a directory.. return showInfo(argc, argv); } else { // find the specified command int offset = 0; while (commands[offset].name != 0) { if (!strcmp(argv[1], commands[offset].name)) break; ++offset; } if (commands[offset].name == 0) { cerr << autosprintf(_("invalid command: \"%s\""), argv[1]) << "\n"; } else { if ((argc - 2 < commands[offset].minOptions) || (argc - 2 > commands[offset].maxOptions)) { cerr << autosprintf( _("Incorrect number of arguments for command \"%s\""), argv[1]) << "\n"; } else return (*commands[offset].func)(argc - 1, argv + 1); } } return EXIT_FAILURE; }
bool userAllowMkdir(int promptno, const char *path, mode_t mode) { // TODO: can we internationalize the y/n names? Seems strange to prompt in // their own language but then have to respond 'y' or 'n'. // xgroup(setup) cerr << autosprintf(_("The directory \"%s\" does not exist. " "Should it be created? (y,n) "), path); char answer[10]; char *res; switch (promptno) { case 1: cerr << endl << "$PROMPT$ create_root_dir" << endl; break; case 2: cerr << endl << "$PROMPT$ create_mount_point" << endl; break; default: break; } res = fgets(answer, sizeof(answer), stdin); if (res != 0 && toupper(answer[0]) == 'Y') { int result = mkdir(path, mode); if (result < 0) { perror(_("Unable to create directory: ")); return false; } else return true; } else { // Directory not created, by user request cerr << _("Directory not created.") << "\n"; return false; } }
static int showVersion(int argc, char **argv) { (void)argc; (void)argv; // xgroup(usage) cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n"; return EXIT_SUCCESS; }
static bool checkDir(string &rootDir) { if (!isDirectory(rootDir.c_str())) { cerr << autosprintf(_("directory %s does not exist.\n"), rootDir.c_str()); return false; } if (rootDir[rootDir.length() - 1] != '/') rootDir.append("/"); return true; }
static void usage(const char *name) { // xgroup(usage) cerr << autosprintf(_("Build: encfs version %s"), VERSION) << "\n\n" // xgroup(usage) << autosprintf( _("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount " "Options]]"), name) << "\n\n" // xgroup(usage) << _("Common Options:\n" " -H\t\t\t" "show optional FUSE Mount Options\n" " -s\t\t\t" "disable multithreaded operation\n" " -f\t\t\t" "run in foreground (don't spawn daemon).\n" "\t\t\tError messages will be sent to stderr\n" "\t\t\tinstead of syslog.\n") // xgroup(usage) << _(" -v, --verbose\t\t" "verbose: output encfs debug messages\n" " -i, --idle=MINUTES\t" "Auto unmount after period of inactivity\n" " --anykey\t\t" "Do not verify correct key is being used\n" " --forcedecode\t\t" "decode data even if an error is detected\n" "\t\t\t(for filesystems using MAC block headers)\n") << _(" --public\t\t" "act as a typical multi-user filesystem\n" "\t\t\t(encfs must be run as root)\n") << _(" --reverse\t\t" "reverse encryption\n") // xgroup(usage) << _(" --extpass=program\tUse external program for password prompt\n" "\n" "Example, to mount at ~/crypt with raw storage in ~/.crypt :\n" " encfs ~/.crypt ~/crypt\n" "\n") // xgroup(usage) << _("For more information, see the man page encfs(1)") << "\n" << endl; }
static int selectKDFDuration() { cout << autosprintf(_("Select desired KDF duration in milliseconds.\n" "The default is 500 (half a second): ")); char answer[10]; char *res = fgets( answer, sizeof(answer), stdin ); int duration = (res == 0 ? 0 : atoi( answer )); cout << "\n"; return duration; }
static void usage(const char *name) { cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n" << _("Usage:\n") // displays usage commands, eg "./encfs (root dir) ..." // xgroup(usage) << autosprintf( _("%s (root dir)\n" " -- displays information about the filesystem, or \n"), name); int offset = 0; while (commands[offset].name != 0) { if (commands[offset].argStr != 0) { cerr << "encfsctl " << commands[offset].name << " " << commands[offset].argStr << "\n" << gettext(commands[offset].usageStr) << "\n"; } ++offset; } cerr << "\n" // xgroup(usage) << autosprintf(_("Example: \n%s info ~/.crypt\n"), name) << "\n"; }
/* iterate recursively through the filesystem and print out names of files which have filenames which cannot be decoded with the given key.. */ static int cmd_showcruft(int argc, char **argv) { (void)argc; RootPtr rootInfo = initRootInfo(argv[1]); if (!rootInfo) return EXIT_FAILURE; int filesFound = showcruft(rootInfo, "/"); // TODO: the singular version should say "Found an invalid file", but all the // translations // depend upon this broken singular form, so it isn't easy to change. cerr << autosprintf(ngettext("Found %i invalid file.", "Found %i invalid files.", filesFound), filesFound) << "\n"; return EXIT_SUCCESS; }
static Interface selectNameCoding(const CipherV1::CipherAlgorithm &alg) { for(;;) { // figure out what cipher they want to use.. // xgroup(setup) cout << _("The following filename encoding algorithms are available:") << "\n"; NameIO::AlgorithmList algorithms = NameIO::GetAlgorithmList(); NameIO::AlgorithmList::const_iterator it; int optNum = 1; map<int, NameIO::AlgorithmList::const_iterator> algMap; for(it = algorithms.begin(); it != algorithms.end(); ++it) { cout << optNum << ". " << it->name << " : " << gettext(it->description.c_str()) << "\n"; algMap[optNum++] = it; } // xgroup(setup) cout << "\n" << _("Enter the number corresponding to your choice: "); char answer[10]; char *res = fgets( answer, sizeof(answer), stdin ); int algNum = (res == 0 ? 0 : atoi( answer )); cout << "\n"; if( algNum < 1 || algNum >= optNum ) { cerr << _("Invalid selection.") << "\n"; continue; } it = algMap[algNum]; // xgroup(setup) cout << autosprintf(_("Selected algorithm \"%s\""), it->name.c_str()) << "\"\n\n"; return it->iface; } }
int showcruft(const std::shared_ptr<EncFS_Root> &rootInfo, const char *dirName) { int found = 0; DirTraverse dt = rootInfo->root->openDir(dirName); if (dt.valid()) { bool showedDir = false; for (string name = dt.nextInvalid(); !name.empty(); name = dt.nextInvalid()) { string cpath = rootInfo->root->cipherPath(dirName); cpath += '/'; cpath += name; if (!showedDir) { // just before showing a list of files in a directory cout << autosprintf(_("In directory %s: \n"), dirName); showedDir = true; } ++found; cout << cpath << "\n"; } // now go back and look for directories to recurse into.. dt = rootInfo->root->openDir(dirName); if (dt.valid()) { for (string name = dt.nextPlaintextName(); !name.empty(); name = dt.nextPlaintextName()) { if (name == "." || name == "..") continue; string plainPath = dirName; plainPath += '/'; plainPath += name; string cpath = rootInfo->root->cipherPath(plainPath.c_str()); if (isDirectory(cpath.c_str())) found += showcruft(rootInfo, plainPath.c_str()); } } } return found; }
static int do_chpasswd(bool useStdin, bool annotate, int argc, char **argv) { (void)argc; string rootDir = argv[1]; if (!checkDir(rootDir)) return EXIT_FAILURE; shared_ptr<EncFSConfig> config(new EncFSConfig); ConfigType cfgType = readConfig(rootDir, config); if (cfgType == Config_None) { cout << _("Unable to load or parse config file\n"); return EXIT_FAILURE; } // instanciate proper cipher shared_ptr<Cipher> cipher = Cipher::New(config->cipherIface, config->keySize); if (!cipher) { cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"), config->cipherIface.name().c_str()); return EXIT_FAILURE; } // ask for existing password cout << _("Enter current Encfs password\n"); if (annotate) cerr << "$PROMPT$ passwd" << endl; CipherKey userKey = config->getUserKey(useStdin); if (!userKey) return EXIT_FAILURE; // decode volume key using user key -- at this point we detect an incorrect // password if the key checksum does not match (causing readKey to fail). CipherKey volumeKey = cipher->readKey(config->getKeyData(), userKey); if (!volumeKey) { cout << _("Invalid password\n"); return EXIT_FAILURE; } // Now, get New user key.. userKey.reset(); cout << _("Enter new Encfs password\n"); // reinitialize salt and iteration count config->kdfIterations = 0; // generate new if (useStdin) { if (annotate) cerr << "$PROMPT$ new_passwd" << endl; userKey = config->getUserKey(true); } else userKey = config->getNewUserKey(); // re-encode the volume key using the new user key and write it out.. int result = EXIT_FAILURE; if (userKey) { int encodedKeySize = cipher->encodedKeySize(); unsigned char *keyBuf = new unsigned char[encodedKeySize]; // encode volume key with new user key cipher->writeKey(volumeKey, keyBuf, userKey); userKey.reset(); config->assignKeyData(keyBuf, encodedKeySize); delete[] keyBuf; if (saveConfig(cfgType, rootDir, config)) { // password modified -- changes volume key of filesystem.. cout << _("Volume Key successfully updated.\n"); result = EXIT_SUCCESS; } else { cout << _("Error saving modified config file.\n"); } } else { cout << _("Error creating key\n"); } volumeKey.reset(); return result; }
static bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out) { // set defaults out->isDaemon = true; out->isThreaded = true; out->isVerbose = false; out->idleTimeout = 0; out->fuseArgc = 0; out->opts->idleTracking = false; out->opts->checkKey = true; out->opts->forceDecode = false; out->opts->ownerCreate = false; out->opts->useStdin = false; out->opts->annotate = false; out->opts->reverseEncryption = false; bool useDefaultFlags = true; // pass executable name through out->fuseArgv[0] = lastPathElement(argv[0]); ++out->fuseArgc; // leave a space for mount point, as FUSE expects the mount point before // any flags out->fuseArgv[1] = NULL; ++out->fuseArgc; // TODO: can flags be internationalized? static struct option long_options[] = { {"fuse-debug", 0, 0, 'd'}, // Fuse debug mode {"forcedecode", 0, 0, 'D'}, // force decode // {"foreground", 0, 0, 'f'}, // foreground mode (no daemon) {"fuse-help", 0, 0, 'H'}, // fuse_mount usage {"idle", 1, 0, 'i'}, // idle timeout {"anykey", 0, 0, 'k'}, // skip key checks {"no-default-flags", 0, 0, 'N'}, // don't use default fuse flags {"ondemand", 0, 0, 'm'}, // mount on-demand {"public", 0, 0, 'P'}, // public mode {"extpass", 1, 0, 'p'}, // external password program // {"single-thread", 0, 0, 's'}, // single-threaded mode {"stdinpass", 0, 0, 'S'}, // read password from stdin {"annotate", 0, 0, 513}, // Print annotation lines to stderr {"verbose", 0, 0, 'v'}, // verbose mode {"version", 0, 0, 'V'}, //version {"reverse", 0, 0, 'r'}, // reverse encryption {"standard", 0, 0, '1'}, // standard configuration {"paranoia", 0, 0, '2'}, // standard configuration {0,0,0,0} }; while (1) { int option_index = 0; // 's' : single-threaded mode // 'f' : foreground mode // 'v' : verbose mode (same as --verbose) // 'd' : fuse debug mode (same as --fusedebug) // 'i' : idle-timeout, takes argument // 'm' : mount-on-demand // 'S' : password from stdin // 'o' : arguments meant for fuse int res = getopt_long( argc, argv, "HsSfvVdmi:o:", long_options, &option_index); if(res == -1) break; switch( res ) { case '1': out->opts->configMode = Config_Standard; break; case '2': out->opts->configMode = Config_Paranoia; break; case 's': out->isThreaded = false; break; case 'S': out->opts->useStdin = true; break; case 513: out->opts->annotate = true; break; case 'f': out->isDaemon = false; // this option was added in fuse 2.x PUSHARG("-f"); break; case 'v': out->isVerbose = true; break; case 'd': PUSHARG("-d"); break; case 'i': out->idleTimeout = strtol( optarg, (char**)NULL, 10); out->opts->idleTracking = true; break; case 'k': out->opts->checkKey = false; break; case 'D': out->opts->forceDecode = true; break; case 'r': out->opts->reverseEncryption = true; break; case 'm': out->opts->mountOnDemand = true; break; case 'N': useDefaultFlags = false; break; case 'o': PUSHARG("-o"); PUSHARG( optarg ); break; case 'p': out->opts->passwordProgram.assign( optarg ); break; case 'P': if(geteuid() != 0) LOG(WARNING) << "option '--public' ignored for non-root user"; else { out->opts->ownerCreate = true; // add 'allow_other' option // add 'default_permissions' option (default) PUSHARG("-o"); PUSHARG("allow_other"); } break; case 'V': // xgroup(usage) cerr << autosprintf(_("encfs version %s"), VERSION) << endl; exit(EXIT_SUCCESS); break; case 'H': FuseUsage(); exit(EXIT_SUCCESS); break; case '?': // invalid options.. break; case ':': // missing parameter for option.. break; default: LOG(WARNING) << "getopt error: " << res; break; } } if(!out->isThreaded) PUSHARG("-s"); if(useDefaultFlags) { PUSHARG("-o"); PUSHARG("use_ino"); PUSHARG("-o"); PUSHARG("default_permissions"); } // we should have at least 2 arguments left over - the source directory and // the mount point. if(optind+2 <= argc) { out->opts->rootDir = slashTerminate( argv[optind++] ); out->mountPoint = argv[optind++]; } else { // no mount point specified LOG(ERROR) << "Missing one or more arguments, aborting."; return false; } // If there are still extra unparsed arguments, pass them onto FUSE.. if(optind < argc) { rAssert(out->fuseArgc < MaxFuseArgs); while(optind < argc) { rAssert(out->fuseArgc < MaxFuseArgs); out->fuseArgv[out->fuseArgc++] = argv[optind]; ++optind; } } // sanity check if(out->isDaemon && (!isAbsolutePath( out->mountPoint.c_str() ) || !isAbsolutePath( out->opts->rootDir.c_str() ) ) ) { cerr << // xgroup(usage) _("When specifying daemon mode, you must use absolute paths " "(beginning with '/')") << endl; return false; } // the raw directory may not be a subdirectory of the mount point. { string testMountPoint = slashTerminate( out->mountPoint ); string testRootDir = out->opts->rootDir.substr(0, testMountPoint.length()); if( testMountPoint == testRootDir ) { cerr << // xgroup(usage) _("The raw directory may not be a subdirectory of the " "mount point.") << endl; return false; } } if(out->opts->mountOnDemand && out->opts->passwordProgram.empty()) { cerr << // xgroup(usage) _("Must set password program when using mount-on-demand") << endl; return false; } // check that the directories exist, or that we can create them.. if(!isDirectory( out->opts->rootDir.c_str() ) && !userAllowMkdir( out->opts->annotate? 1:0, out->opts->rootDir.c_str() ,0700)) { LOG(WARNING) << "Unable to locate root directory, aborting."; return false; } if(!isDirectory( out->mountPoint.c_str() ) && !userAllowMkdir( out->opts->annotate? 2:0, out->mountPoint.c_str(),0700)) { LOG(WARNING) << "Unable to locate mount point, aborting."; return false; } // fill in mount path for fuse out->fuseArgv[1] = out->mountPoint.c_str(); return true; }
void showFSInfo( const EncfsConfig &config ) { shared_ptr<CipherV1> cipher = CipherV1::New( config.cipher(), config.key().size() ); { cout << autosprintf( // xgroup(diag) _("Filesystem cipher: \"%s\", version %i:%i:%i"), config.cipher().name().c_str(), config.cipher().major(), config.cipher().minor(), config.cipher().age()); // check if we support this interface.. if(!cipher) cout << _(" (NOT supported)\n"); else { // if we're using a newer interface, show the version number if( config.cipher() != cipher->interface() ) { Interface iface = cipher->interface(); // xgroup(diag) cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.major(), iface.minor(), iface.age()); } else cout << "\n"; } } // xgroup(diag) cout << autosprintf(_("Filename encoding: \"%s\", version %i:%i:%i"), config.naming().name().c_str(), config.naming().major(), config.naming().minor(), config.naming().age()); if (!cipher) { cout << "\n"; } else { // check if we support the filename encoding interface.. shared_ptr<NameIO> nameCoder = NameIO::New( config.naming(), cipher ); if(!nameCoder) { // xgroup(diag) cout << _(" (NOT supported)\n"); } else { // if we're using a newer interface, show the version number if( config.naming() != nameCoder->interface() ) { Interface iface = nameCoder->interface(); cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.major(), iface.minor(), iface.age()); } else cout << "\n"; } } const EncryptedKey &key = config.key(); { cout << autosprintf(_("Key Size: %i bits"), 8 * key.size()); cipher = getCipher(config); if(!cipher) { // xgroup(diag) cout << _(" (NOT supported)\n"); } else cout << "\n"; } if(key.kdf_iterations() > 0 && key.salt().size() > 0) { cout << autosprintf(_("Using PBKDF2, with %i iterations"), key.kdf_iterations()) << "\n"; cout << autosprintf(_("Salt Size: %i bits"), 8*(int)key.salt().size()) << "\n"; } if(config.block_mac_bytes() || config.block_mac_rand_bytes()) { if(config.revision() < V5Latest) { cout << autosprintf( // xgroup(diag) _("Block Size: %i bytes + %i byte MAC header"), config.block_size(), config.block_mac_bytes() + config.block_mac_rand_bytes()) << endl; } else { // new version stores the header as part of that block size.. cout << autosprintf( // xgroup(diag) _("Block Size: %i bytes, including %i byte MAC header"), config.block_size(), config.block_mac_bytes() + config.block_mac_rand_bytes()) << endl; } } else { // xgroup(diag) cout << autosprintf(_("Block Size: %i bytes"), config.block_size()); cout << "\n"; } if(config.unique_iv()) { // xgroup(diag) cout << _("Each file contains 8 byte header with unique IV data.\n"); } if(config.chained_iv()) { // xgroup(diag) cout << _("Filenames encoded using IV chaining mode.\n"); } if(config.external_iv()) { // xgroup(diag) cout << _("File data IV is chained to filename IV.\n"); } if(config.allow_holes()) { // xgroup(diag) cout << _("File holes passed through to ciphertext.\n"); } cout << "\n"; }
static CipherV1::CipherAlgorithm selectCipherAlgorithm() { for(;;) { // figure out what cipher they want to use.. // xgroup(setup) cout << _("The following cipher algorithms are available:") << "\n"; int optNum = 0; auto algorithms = CipherV1::GetAlgorithmList(); for (auto &it : algorithms) { cout << ++optNum << ". " << it.name << " : " << gettext(it.description.c_str()) << "\n"; if(it.keyLength.min() == it.keyLength.max()) { // shown after algorithm name and description. // xgroup(setup) cout << autosprintf(_(" -- key length %i bits") , it.keyLength.min()) << "\n"; } else { cout << autosprintf( // shown after algorithm name and description. // xgroup(setup) _(" -- Supports key lengths of %i to %i bits"), it.keyLength.min(), it.keyLength.max()) << "\n"; } if(it.blockSize.min() == it.blockSize.max()) { cout << autosprintf( // shown after algorithm name and description. // xgroup(setup) _(" -- block size %i bytes"), it.blockSize.min()) << "\n"; } else { cout << autosprintf( // shown after algorithm name and description. // xgroup(setup) _(" -- Supports block sizes of %i to %i bytes"), it.blockSize.min(), it.blockSize.max()) << "\n"; } } // xgroup(setup) cout << "\n" << _("Enter the number corresponding to your choice: "); char answer[10]; char *res = fgets( answer, sizeof(answer), stdin ); int cipherNum = (res == 0 ? 0 : atoi( answer )); cout << "\n"; if( cipherNum < 1 || cipherNum > (int)algorithms.size() ) { cerr << _("Invalid selection.") << "\n"; continue; } CipherV1::CipherAlgorithm alg; for (auto &it : algorithms) { if (!--cipherNum) { alg = it; break; } } // xgroup(setup) cout << autosprintf(_("Selected algorithm \"%s\""), alg.name.c_str()) << "\n\n"; return alg; } }
static bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out) { // set defaults out->isDaemon = true; out->isThreaded = true; out->isVerbose = false; out->idleTimeout = 0; out->fuseArgc = 0; out->opts->idleTracking = false; out->opts->checkKey = true; out->opts->forceDecode = false; out->opts->ownerCreate = false; out->opts->useStdin = false; out->opts->annotate = false; out->opts->reverseEncryption = false; bool useDefaultFlags = true; // pass executable name through out->fuseArgv[0] = lastPathElement(argv[0]); ++out->fuseArgc; // leave a space for mount point, as FUSE expects the mount point before // any flags out->fuseArgv[1] = NULL; ++out->fuseArgc; // TODO: can flags be internationalized? static struct option long_options[] = { {"fuse-debug", 0, 0, 'd'}, // Fuse debug mode {"forcedecode", 0, 0, 'D'}, // force decode // {"foreground", 0, 0, 'f'}, // foreground mode (no daemon) {"fuse-help", 0, 0, 'H'}, // fuse_mount usage {"idle", 1, 0, 'i'}, // idle timeout {"anykey", 0, 0, 'k'}, // skip key checks {"no-default-flags", 0, 0, 'N'}, // don't use default fuse flags {"ondemand", 0, 0, 'm'}, // mount on-demand {"delaymount", 0, 0, 'M'}, // delay initial mount until use {"public", 0, 0, 'P'}, // public mode {"extpass", 1, 0, 'p'}, // external password program // {"single-thread", 0, 0, 's'}, // single-threaded mode {"stdinpass", 0, 0, 'S'}, // read password from stdin {"annotate", 0, 0, 513}, // Print annotation lines to stderr {"nocache", 0, 0, 514}, // disable caching {"verbose", 0, 0, 'v'}, // verbose mode {"version", 0, 0, 'V'}, // version {"reverse", 0, 0, 'r'}, // reverse encryption {"standard", 0, 0, '1'}, // standard configuration {"paranoia", 0, 0, '2'}, // standard configuration {0, 0, 0, 0}}; while (1) { int option_index = 0; // 's' : single-threaded mode // 'f' : foreground mode // 'v' : verbose mode (same as --verbose) // 'd' : fuse debug mode (same as --fusedebug) // 'i' : idle-timeout, takes argument // 'm' : mount-on-demand // 'S' : password from stdin // 'o' : arguments meant for fuse int res = getopt_long(argc, argv, "HsSfvdmi:o:", long_options, &option_index); if (res == -1) break; switch (res) { case '1': out->opts->configMode = Config_Standard; break; case '2': out->opts->configMode = Config_Paranoia; break; case 's': out->isThreaded = false; break; case 'S': out->opts->useStdin = true; break; case 513: out->opts->annotate = true; break; case 'f': out->isDaemon = false; // this option was added in fuse 2.x PUSHARG("-f"); break; case 'v': out->isVerbose = true; break; case 'd': PUSHARG("-d"); break; case 'i': out->idleTimeout = strtol(optarg, (char **)NULL, 10); out->opts->idleTracking = true; break; case 'k': out->opts->checkKey = false; break; case 'D': out->opts->forceDecode = true; break; case 'r': out->opts->reverseEncryption = true; /* Reverse encryption does not support writing unless uniqueIV * is disabled (expert mode) */ out->opts->readOnly = true; /* By default, the kernel caches file metadata for one second. * This is fine for EncFS' normal mode, but for --reverse, this * means that the encrypted view will be up to one second out of * date. * Quoting Goswin von Brederlow: * "Caching only works correctly if you implement a disk based * filesystem, one where only the fuse process can alter * metadata and all access goes only through fuse. Any overlay * filesystem where something can change the underlying * filesystem without going through fuse can run into * inconsistencies." * Enabling reverse automatically enables noCache */ case 514: /* Disable EncFS block cache * Causes reverse grow tests to fail because short reads * are returned */ out->opts->noCache = true; /* Disable kernel stat() cache * Causes reverse grow tests to fail because stale stat() data * is returned */ PUSHARG("-oattr_timeout=0"); /* Disable kernel dentry cache * Fallout unknown, disabling for safety */ PUSHARG("-oentry_timeout=0"); break; case 'm': out->opts->mountOnDemand = true; break; case 'M': out->opts->delayMount = true; break; case 'N': useDefaultFlags = false; break; case 'o': PUSHARG("-o"); PUSHARG(optarg); break; case 'p': out->opts->passwordProgram.assign(optarg); break; case 'P': if (geteuid() != 0) rWarning(_("option '--public' ignored for non-root user")); else { out->opts->ownerCreate = true; // add 'allow_other' option // add 'default_permissions' option (default) PUSHARG("-o"); PUSHARG("allow_other"); } break; case 'V': // xgroup(usage) cerr << autosprintf(_("encfs version %s"), VERSION) << endl; exit(EXIT_SUCCESS); break; case 'H': FuseUsage(); exit(EXIT_SUCCESS); break; case '?': // invalid options.. break; case ':': // missing parameter for option.. break; default: rWarning(_("getopt error: %i"), res); break; } } if (!out->isThreaded) PUSHARG("-s"); if (useDefaultFlags) { PUSHARG("-o"); PUSHARG("use_ino"); PUSHARG("-o"); PUSHARG("default_permissions"); } // we should have at least 2 arguments left over - the source directory and // the mount point. if (optind + 2 <= argc) { out->opts->rootDir = slashTerminate(argv[optind++]); out->mountPoint = argv[optind++]; } else { // no mount point specified rWarning(_("Missing one or more arguments, aborting.")); return false; } // If there are still extra unparsed arguments, pass them onto FUSE.. if (optind < argc) { rAssert(out->fuseArgc < MaxFuseArgs); while (optind < argc) { rAssert(out->fuseArgc < MaxFuseArgs); out->fuseArgv[out->fuseArgc++] = argv[optind]; ++optind; } } // sanity check if (out->isDaemon && (!isAbsolutePath(out->mountPoint.c_str()) || !isAbsolutePath(out->opts->rootDir.c_str()))) { cerr << // xgroup(usage) _("When specifying daemon mode, you must use absolute paths " "(beginning with '/')") << endl; return false; } // the raw directory may not be a subdirectory of the mount point. { string testMountPoint = slashTerminate(out->mountPoint); string testRootDir = out->opts->rootDir.substr(0, testMountPoint.length()); if (testMountPoint == testRootDir) { cerr << // xgroup(usage) _("The raw directory may not be a subdirectory of the " "mount point.") << endl; return false; } } if (out->opts->delayMount && !out->opts->mountOnDemand) { cerr << // xgroup(usage) _("You must use mount-on-demand with delay-mount") << endl; return false; } if (out->opts->mountOnDemand && out->opts->passwordProgram.empty()) { cerr << // xgroup(usage) _("Must set password program when using mount-on-demand") << endl; return false; } // check that the directories exist, or that we can create them.. if (!isDirectory(out->opts->rootDir.c_str()) && !userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(), 0700)) { rWarning(_("Unable to locate root directory, aborting.")); return false; } if (!isDirectory(out->mountPoint.c_str()) && !userAllowMkdir(out->opts->annotate ? 2 : 0, out->mountPoint.c_str(), 0700)) { rWarning(_("Unable to locate mount point, aborting.")); return false; } // fill in mount path for fuse out->fuseArgv[1] = out->mountPoint.c_str(); return true; }