// Read a v5 archive, which is a proprietary binary format. bool readV5Config( const char *configFile, EncfsConfig &config, ConfigInfo *) { bool ok = false; // use Config to parse the file and query it.. ConfigReader cfgRdr; if(cfgRdr.load( configFile )) { try { config.set_revision(cfgRdr["subVersion"].readInt(0)); if(config.revision() > V5Latest) { /* config file specifies a version outside our supported range.. */ LOG(ERROR) << "Config subversion " << config.revision() << " found, but this version of encfs only supports up to version " << V5Latest; return false; } if( config.revision() < V5Latest ) { LOG(ERROR) << "This version of EncFS doesn't support " << "filesystems created with EncFS releases before 2004-08-13"; return false; } cfgRdr["creator"] >> (*config.mutable_creator()); cfgRdr["cipher"] >> (*config.mutable_cipher()); cfgRdr["naming"] >> (*config.mutable_naming()); int blockSize; cfgRdr["blockSize"] >> blockSize; config.set_block_size(blockSize); EncryptedKey *encryptedKey = config.mutable_key(); int keySize; cfgRdr["keySize"] >> keySize; encryptedKey->set_size(keySize / 8); cfgRdr["keyData"] >> (*encryptedKey->mutable_ciphertext()); config.set_unique_iv( cfgRdr["uniqueIV"].readBool( false ) ); config.set_chained_iv( cfgRdr["chainedIV"].readBool( false ) ); config.set_external_iv( cfgRdr["externalIV"].readBool( false ) ); config.set_block_mac_bytes( cfgRdr["blockMACBytes"].readInt(0) ); config.set_block_mac_rand_bytes( cfgRdr["blockMACRandBytes"].readInt(0) ); ok = true; } catch( Error &err) { LOG(WARNING) << "Error parsing data in config file " << configFile << "; " << err.what(); ok = false; } } return ok; }
/* Passing a copy to rootDir is on purpose here */ static int isValidEncFS(std::string rootDir) { if( !checkDir( rootDir )) return EXIT_FAILURE; #ifdef ENCFS_SVN EncfsConfig config; #else shared_ptr<EncFSConfig> config(new EncFSConfig); #endif ConfigType type = readConfig( rootDir, config ); #ifdef ENCFS_SVN std::string config_creator = config.creator(); int config_revision = config.revision(); #else std::string config_creator = config->creator; int config_revision = config->subVersion; #endif std::ostringstream info; // show information stored in config.. switch(type) { case Config_None: info << "Unable to load or parse config file in " << rootDir; LOGI(info.str().c_str()); return EXIT_FAILURE; case Config_Prehistoric: LOGI("A really old EncFS filesystem was found.\n" "It is not supported in this EncFS build."); return EXIT_FAILURE; case Config_V3: info << "Version 3 configuration; created by " << config_creator.c_str(); break; case Config_V4: info << "Version 4 configuration; created by " << config_creator.c_str(); break; case Config_V5: info << "Version 5 configuration; created by " << config_creator.c_str() << " (revision " << config_revision << ")"; break; case Config_V6: info << "Version 6 configuration; created by " << config_creator.c_str() << " (revision " << config_revision << ")"; break; #ifdef ENCFS_SVN case Config_V7: info << "Version 7 configuration; created by " << config_creator.c_str() << " (revision " << config_revision << ")"; break; #endif } LOGI(info.str().c_str()); showFSInfo( config ); return EXIT_SUCCESS; }
static int showInfo( int argc, char **argv ) { (void)argc; string rootDir = argv[1]; if( !checkDir( rootDir )) return EXIT_FAILURE; EncfsConfig config; 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: case Config_V6: case Config_V7: // xgroup(diag) cout << "\n" << autosprintf(_("Version %i configuration; " "created by %s (revision %i)\n"), type, config.creator().c_str(), config.revision()); break; } showFSInfo( config ); return EXIT_SUCCESS; }
// Read a boost::serialization config file using an Xml reader.. bool readV6Config( const char *configFile, EncfsConfig &cfg, ConfigInfo *info) { (void)info; XmlReader rdr; if (!rdr.load(configFile)) { LOG(ERROR) << "Failed to load config file " << configFile; return false; } XmlValuePtr serialization = rdr["boost_serialization"]; XmlValuePtr config = (*serialization)["cfg"]; if (!config) { config = (*serialization)["config"]; } if (!config) { LOG(ERROR) << "Unable to find XML configuration in file " << configFile; return false; } int version; if (!config->read("version", &version) && !config->read("@version", &version)) { LOG(ERROR) << "Unable to find version in config file"; return false; } // version numbering was complicated by boost::archive if (version == 20 || version >= 20100713) { VLOG(1) << "found new serialization format"; cfg.set_revision(version); } else if (version == 26800) { VLOG(1) << "found 20080816 version"; cfg.set_revision(20080816); } else if (version == 26797) { VLOG(1) << "found 20080813"; cfg.set_revision(20080813); } else if (version < V5Latest) { LOG(ERROR) << "Invalid version " << version << " - please fix config file"; } else { LOG(INFO) << "Boost <= 1.41 compatibility mode"; cfg.set_revision(version); } VLOG(1) << "subVersion = " << cfg.revision(); config->read("creator", cfg.mutable_creator()); config->read("cipherAlg", cfg.mutable_cipher()); config->read("nameAlg", cfg.mutable_naming()); //(*config)["keySize"] >> cfg.keySize; int blockSize, blockMacBytes, blockMacRandBytes; bool uniqueIv, chainedNameIv, externalIv, allowHoles; config->read("blockSize", &blockSize); config->read("uniqueIV", &uniqueIv); config->read("chainedNameIV", &chainedNameIv); config->read("externalIVChaining", &externalIv); config->read("blockMACBytes", &blockMacBytes); config->read("blockMACRandBytes", &blockMacRandBytes); config->read("allowHoles", &allowHoles); cfg.set_block_size(blockSize); cfg.set_unique_iv(uniqueIv); cfg.set_chained_iv(chainedNameIv); cfg.set_external_iv(externalIv); cfg.set_block_mac_bytes(blockMacBytes); cfg.set_block_mac_rand_bytes(blockMacRandBytes); cfg.set_allow_holes(allowHoles); EncryptedKey *encryptedKey = cfg.mutable_key(); int encodedSize; config->read("encodedKeySize", &encodedSize); unsigned char *key = new unsigned char[encodedSize]; config->readB64("encodedKeyData", key, encodedSize); encryptedKey->set_ciphertext(key, encodedSize); delete[] key; int keySize; config->read("keySize", &keySize); encryptedKey->set_size(keySize / 8); // save as size in bytes if(cfg.revision() >= 20080816) { int saltLen; config->read("saltLen", &saltLen); unsigned char *salt = new unsigned char[saltLen]; config->readB64("saltData", salt, saltLen); encryptedKey->set_salt(salt, saltLen); delete[] salt; int kdfIterations, desiredKDFDuration; config->read("kdfIterations", &kdfIterations); config->read("desiredKDFDuration", &desiredKDFDuration); encryptedKey->set_kdf_iterations(kdfIterations); encryptedKey->set_kdf_duration(desiredKDFDuration); } else { encryptedKey->clear_salt(); encryptedKey->set_kdf_iterations(16); encryptedKey->clear_kdf_duration(); } 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"; }