void Drive::Umount(HWND) { // check mounted CheckMounted(); // if (GetDriveType(mnt) == DRIVE_NO_ROOT_DIR) // mounted = false; if (!mounted) throw truntime_error(_T("Cannot unmount a not mounted drive")); // unmount fuse_unmount(wchar_to_utf8_cstr(mnt).c_str(), NULL); if (subProcess) { // attach console to allow sending ctrl-c AttachConsole(subProcess->pid); // disable ctrl-c to not exit this process SetConsoleCtrlHandler(HandlerRoutine, TRUE); if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, subProcess->pid) && !GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, subProcess->pid)) TerminateProcess(subProcess->hProcess, 0); // force exit if (WaitForSingleObject(subProcess->hProcess, 2000) == WAIT_TIMEOUT) TerminateProcess(subProcess->hProcess, 0); // close the console FreeConsole(); SetConsoleCtrlHandler(HandlerRoutine, FALSE); } CheckMounted(); }
void Drive::Mount(HWND hwnd) { // check drive empty or require a new drive while (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) { char drive = SelectFreeDrive(hwnd); if (!drive) return; _stprintf(mnt, _T("%c:\\"), drive); Save(); } // check directory existence if (!isDirectory(wchar_to_utf8_cstr(dir.c_str()).c_str())) { if (YesNo(hwnd, _T("Directory does not exists. Remove from list?"))) Drives::Delete(shared_from_this()); return; } // TODO check configuration still exists ?? ... no can cause recursion problem // search if executable is present TCHAR executable[MAX_PATH]; if (!SearchPath(NULL, _T("encfs.exe"), NULL, LENGTH(executable), executable, NULL)) throw truntime_error(_T("Unable to find encfs.exe file")); // ask a password to mount TCHAR pass[128+2]; if (!GetPassword(hwnd, pass, LENGTH(pass)-2)) return; _tcscat(pass, _T("\r\n")); // mount using a sort of popen TCHAR cmd[2048]; _sntprintf(cmd, LENGTH(cmd), _T("\"%s\" -S \"%s\" %c:"), executable, dir.c_str(), mnt[0]); boost::shared_ptr<SubProcessInformations> proc(new SubProcessInformations); proc->creationFlags = CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW; if (!CreateSubProcess(cmd, proc.get())) { DWORD err = GetLastError(); memset(pass, 0, sizeof(pass)); _sntprintf(cmd, LENGTH(cmd), _T("Error: %s (%u)"), proc->errorPart, (unsigned) err); throw truntime_error(cmd); } subProcess = proc; // send the password std::string pwd = wchar_to_utf8_cstr(pass); DWORD written; WriteFile(proc->hIn, pwd.c_str(), pwd.length(), &written, NULL); CloseHandle(proc->hIn); // close input so sub process does not any more proc->hIn = NULL; memset(pass, 0, sizeof(pass)); memset((char*) pwd.c_str(), 0, pwd.length()); mounted = false; // wait for mount, read error and give feedback for (unsigned n = 0; n < 5*10; ++n) { // drive appeared if (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) { if (Drives::autoShow) Show(hwnd); break; } // process terminated DWORD readed; char output[2048]; switch (WaitForSingleObject(subProcess->hProcess, 200)) { case WAIT_OBJECT_0: case WAIT_ABANDONED: if (ReadFile(proc->hOut, output, sizeof(output)-1, &readed, NULL)) { output[readed] = 0; utf8_to_wchar_buf(output, cmd, LENGTH(cmd)); } else { _stprintf(cmd, _T("Unknown error mounting drive %c:"), mnt[0]); } subProcess.reset(); throw truntime_error(cmd); } } if (subProcess) mounted = true; Save(); // save for resume }
static void createConfig(const std::string& rootDir, bool paranoid, const char* password) { bool reverseEncryption = false; ConfigMode configMode = paranoid ? Config_Paranoia : Config_Standard; int keySize = 0; int blockSize = 0; Cipher::CipherAlgorithm alg; rel::Interface nameIOIface; int blockMACBytes = 0; int blockMACRandBytes = 0; bool uniqueIV = false; bool chainedIV = false; bool externalIV = false; bool allowHoles = true; long desiredKDFDuration = NormalKDFDuration; if (reverseEncryption) { uniqueIV = false; chainedIV = false; externalIV = false; blockMACBytes = 0; blockMACRandBytes = 0; } if(configMode == Config_Paranoia) { // look for AES with 256 bit key.. // Use block filename encryption mode. // Enable per-block HMAC headers at substantial performance penalty.. // Enable per-file initialization vector headers. // Enable filename initialization vector chaning keySize = 256; blockSize = DefaultBlockSize; alg = findCipherAlgorithm("AES", keySize); nameIOIface = BlockNameIO::CurrentInterface(); blockMACBytes = 8; blockMACRandBytes = 0; // using uniqueIV, so this isn't necessary uniqueIV = true; chainedIV = true; externalIV = true; desiredKDFDuration = ParanoiaKDFDuration; } else { // xgroup(setup) // AES w/ 192 bit key, block name encoding, per-file initialization // vectors are all standard. keySize = 192; blockSize = DefaultBlockSize; alg = findCipherAlgorithm("AES", keySize); blockMACBytes = 0; externalIV = false; nameIOIface = BlockNameIO::CurrentInterface(); if (!reverseEncryption) { uniqueIV = true; chainedIV = true; } } boost::shared_ptr<Cipher> cipher = Cipher::New( alg.name, keySize ); if(!cipher) { TCHAR buf[256]; _sntprintf(buf, LENGTH(buf), _T("Unable to instanciate cipher %s, key size %i, block size %i"), alg.name.c_str(), keySize, blockSize); throw truntime_error(buf); } boost::shared_ptr<EncFSConfig> config( new EncFSConfig ); config->cfgType = Config_V6; config->cipherIface = cipher->Interface(); config->keySize = keySize; config->blockSize = blockSize; config->nameIface = nameIOIface; config->creator = "EncFS " VERSION; config->subVersion = V6SubVersion; config->blockMACBytes = blockMACBytes; config->blockMACRandBytes = blockMACRandBytes; config->uniqueIV = uniqueIV; config->chainedNameIV = chainedIV; config->externalIVChaining = externalIV; config->allowHoles = allowHoles; config->salt.clear(); config->kdfIterations = 0; // filled in by keying function config->desiredKDFDuration = desiredKDFDuration; int encodedKeySize = cipher->encodedKeySize(); unsigned char *encodedKey = new unsigned char[ encodedKeySize ]; CipherKey volumeKey = cipher->newRandomKey(); // get user key and use it to encode volume key CipherKey userKey; userKey = config->makeKey(password, strlen(password)); cipher->writeKey( volumeKey, encodedKey, userKey ); userKey.reset(); config->assignKeyData(encodedKey, encodedKeySize); delete[] encodedKey; if(!volumeKey) throw truntime_error(_T("Failure generating new volume key! ") _T("Please report this error.")); if (!saveConfig( Config_V6, rootDir, config )) throw truntime_error(_T("Error saving configuration file")); }