#include <vector>
#include <iostream>
#include <condition_variable>
+#include <stdexcept>
#include <ode/secure-erase.h>
#include <ode/internal-encryption.h>
std::cout << "Usage: " << name << " [Option]" << std::endl
<< std::endl
<< "Options :" << std::endl
- << " -m, --mount=internal|external mount" << std::endl
- << " -u, --umount=internal|external umount" << std::endl
- << " -e, --encrypt=internal|external encrypt" << std::endl
- << " -d, --decrypt=internal|external decrypt" << std::endl
- << " -l --luks=format|open|close|wait perform LUKS operation or wait for completion. May also require -D and/or -M option." << std::endl
- << " -D --device=<device> device path required for LUKS format and LUKS open operations" << std::endl
- << " -M --mapping=<mapping> mapping name required for LUKS open and LUKS close operations" << std::endl
- << " -p, --changepw=internal|external change password" << std::endl
- << " -s, --state=internal|external get state" << std::endl
- << " -w, --waitmnt=internal|external wait for mount"<< std::endl
- << " -c, --clean=DIRECTORY secure-clean" << std::endl
- << " -h, --help show this" << std::endl
+ << " -m, --mount=internal|external mount" << std::endl
+ << " -u, --umount=internal|external umount" << std::endl
+ << " -e, --encrypt=internal|external encrypt" << std::endl
+ << " -d, --decrypt=internal|external decrypt" << std::endl
+ << " -l --luks=format|open|close|wait perform LUKS operation using asynchronous" << std::endl
+ << " API or wait for completion. May also" << std::endl
+ << " require -D and/or -M option." << std::endl
+ << " -L --luks_sync=format|open|close perform LUKS operation using synchronous" << std::endl
+ << " API. May also require -D and/or -M option." << std::endl
+ << " -D --device=<device> device path required for LUKS format and" << std::endl
+ << " LUKS open operations" << std::endl
+ << " -M --mapping=<mapping> mapping name required for LUKS open and" << std::endl
+ << " LUKS close operations" << std::endl
+ << " -p, --changepw=internal|external change password" << std::endl
+ << " -s, --state=internal|external get state" << std::endl
+ << " -w, --waitmnt=internal|external wait for mount"<< std::endl
+ << " -c, --clean=DIRECTORY secure-clean" << std::endl
+ << " -h, --help show this" << std::endl
<< std::endl;
return -1;
return ret;
}
-class LuksListener {
+class LuksWrapper {
public:
+ explicit LuksWrapper(bool sync) : synchronous(sync) {
+ if (synchronous)
+ return;
+
+ int ret = ode_luks_set_event_cb(&LuksWrapper::StaticCallback, this);
+ if (ret != ODE_ERROR_NONE)
+ throw std::runtime_error("Callback setting failed " + ret);
+ }
+
+ int format(const std::string& device)
+ {
+ std::cout << "New ";
+ std::string password = getPassword();
+
+ std::cout << "Confirm ";
+ std::string password2 = getPassword();
+ if (password != password2) {
+ std::cerr << "Confirm password doesn't match" << std::endl;
+ return -1;
+ }
+
+ int ret;
+ if (synchronous)
+ ret = ode_luks_format_sync(device.c_str(), password.c_str());
+ else
+ ret = ode_luks_format(device.c_str(), password.c_str());
+
+ if (ret != ODE_ERROR_NONE) {
+ std::cerr << "ode_luks_format() failed " << ret << std::endl;
+ return ret;
+ }
+ if (synchronous)
+ return ret;
+
+ return WaitForCallback(ODE_LUKS_FORMAT);
+ }
+
+ int open(const std::string& device, const std::string& mapping)
+ {
+ std::string password = getPassword();
+ int ret;
+ if (synchronous)
+ ret = ode_luks_open_sync(device.c_str(), password.c_str(), mapping.c_str());
+ else
+ ret = ode_luks_open(device.c_str(), password.c_str(), mapping.c_str());
+
+ if (ret != ODE_ERROR_NONE) {
+ std::cerr << "ode_luks_open() failed " << ret << std::endl;
+ return ret;
+ }
+ if (synchronous)
+ return ret;
+
+ return WaitForCallback(ODE_LUKS_OPEN);
+ }
+
+ int close(const std::string& mapping)
+ {
+ int ret;
+ if (synchronous)
+ ret = ode_luks_close_sync(mapping.c_str());
+ else
+ ret = ode_luks_close(mapping.c_str());
+
+ if (ret != ODE_ERROR_NONE) {
+ std::cerr << "ode_luks_close() failed " << ret << std::endl;
+ return ret;
+ }
+ if (synchronous)
+ return ret;
+
+ return WaitForCallback(ODE_LUKS_CLOSE);
+ }
+
+ int wait()
+ {
+ return WaitForCallbackInternal([](ode_luks_operation_e) { return true; });
+ }
+
+ ~LuksWrapper() {
+ if (synchronous)
+ ode_luks_unset_event_cb();
+ }
+
+private:
static void StaticCallback(ode_luks_operation_e op, int ret, void* user_data)
{
- auto self = static_cast<LuksListener*>(user_data);
+ auto self = static_cast<LuksWrapper*>(user_data);
self->Callback(op, ret);
}
cond.notify_one();
}
- int WaitForCallback()
- {
- return WaitForCallbackInternal([](ode_luks_operation_e) { return true; });
- }
-
int WaitForCallback(ode_luks_operation_e expected)
{
return WaitForCallbackInternal([=](ode_luks_operation_e op) {
});
}
- ~LuksListener() {
- ode_luks_unset_event_cb();
- }
-
-private:
int WaitForCallbackInternal(const std::function<bool(ode_luks_operation_e)>& opCheck)
{
std::unique_lock<std::mutex> lock(mutex);
};
std::vector<result> results;
+ bool synchronous;
};
-static inline int luks(const std::string& name,
+static inline int luks(bool sync,
+ const std::string& name,
const std::string& device,
const std::string& mapping)
{
- int ret;
-
- if (name == "format") {
- if (device.empty())
- return usage(name);
+ try {
+ if (name == "format") {
+ if (device.empty())
+ return usage(name);
- LuksListener listener;
- ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "Callback setting failed " << ret << std::endl;
- return ret;
+ LuksWrapper wrapper(sync);
+ return wrapper.format(device);
}
- std::cout << "New ";
- std::string password = getPassword();
-
- std::cout << "Confirm ";
- std::string password2 = getPassword();
- if (password != password2) {
- std::cerr << "Confirm password doesn't match" << std::endl;
- return -1;
- }
+ if (name == "open") {
+ if (device.empty() || mapping.empty())
+ return usage(name);
- ret = ode_luks_format(device.c_str(), password.c_str());
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "ode_luks_format() failed " << ret << std::endl;
- return ret;
+ LuksWrapper wrapper(sync);
+ return wrapper.open(device, mapping);
}
- return listener.WaitForCallback(ODE_LUKS_FORMAT);
- }
- if (name == "open") {
- if (device.empty() || mapping.empty())
- return usage(name);
+ if (name == "close") {
+ if (mapping.empty())
+ return usage(name);
- LuksListener listener;
- ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "Callback setting failed " << ret << std::endl;
- return ret;
+ LuksWrapper wrapper(sync);
+ return wrapper.close(mapping);
}
- std::string password = getPassword();
- ret = ode_luks_open(device.c_str(), password.c_str(), mapping.c_str());
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "ode_luks_open() failed " << ret << std::endl;
- return ret;
+ if (name == "wait" && !sync) {
+ LuksWrapper wrapper(sync);
+ return wrapper.wait();
}
- return listener.WaitForCallback(ODE_LUKS_OPEN);
- }
-
- if (name == "close") {
- if (mapping.empty())
- return usage(name);
- LuksListener listener;
- ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "Callback setting failed " << ret << std::endl;
- return ret;
- }
-
- ret = ode_luks_close(mapping.c_str());
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "ode_luks_open() failed " << ret << std::endl;
- return ret;
- }
- return listener.WaitForCallback(ODE_LUKS_CLOSE);
- }
-
- if (name == "wait") {
- LuksListener listener;
- ret = ode_luks_set_event_cb(&LuksListener::StaticCallback, &listener);
- if (ret != ODE_ERROR_NONE) {
- std::cerr << "Callback setting failed " << ret << std::endl;
- return ret;
- }
-
- return listener.WaitForCallback();
+ if (sync)
+ std::cerr << "Wrong arguments (format|open|close)" << std::endl;
+ else
+ std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl;
+ return -1;
+ } catch (const std::runtime_error& e) {
+ std::cerr << e.what() << std::endl;
+ return -1;
}
-
- std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl;
- return -1;
}
static inline int change_password(const std::string name)
{"encrypt", required_argument, 0, 'e'},
{"decrypt", required_argument, 0, 'd'},
{"luks" , required_argument, 0, 'l'},
+ {"luks_sync" , required_argument, 0, 'L'},
{"state", required_argument, 0, 's'},
{"waitmnt", required_argument, 0, 'w'},
{"clean", required_argument, 0, 'c'},
struct option luks_options[] = {
{"device", required_argument, 0, 'D'},
{"mapping", required_argument, 0, 'M'},
+ {"synchronous", no_argument, 0, 'S'},
{0, 0, 0, 0}
};
}
std::string mapping, device, op;
+ bool sync = true;
- while ((opt = getopt_long(argc, argv, "m:u:e:d:l:p:s:w:c:h", options, &index)) != -1) {
+ while ((opt = getopt_long(argc, argv, "m:u:e:d:l:L:p:s:w:c:h", options, &index)) != -1) {
switch (opt) {
case 'm':
ret = mount(optarg);
ret = decrypt_storage(optarg);
break;
case 'l':
+ sync = false;
+ // No break on purpose. Logic is the same just the flag is different.
+ case 'L':
op = optarg;
while ((luks_opt = getopt_long(argc, argv, "D:M:", luks_options, &index)) != -1) {
switch (luks_opt) {
}
}
if (ret == 0)
- ret = luks(op, device, mapping);
+ ret = luks(sync, op, device, mapping);
break;
case 'p':
ret = change_password(optarg);