From: Krzysztof Jackiewicz Date: Fri, 6 Oct 2017 12:16:27 +0000 (+0200) Subject: Support for luks API in ode-admin-cli X-Git-Tag: submit/tizen_4.0/20171018.042033~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=da77d6974ac655a718ac8aaceb71df548bae980c;p=platform%2Fcore%2Fsecurity%2Fode.git Support for luks API in ode-admin-cli Allows synchronous formatting, opening and closing of LUKS device. It also allows waiting for completion notification in a separate process. Change-Id: I28b4c543bc2a3135bd8cde53fbf6e13181684ffd --- diff --git a/tools/cli/ode-admin-cli.cpp b/tools/cli/ode-admin-cli.cpp index 4bce8ad..83b01cf 100644 --- a/tools/cli/ode-admin-cli.cpp +++ b/tools/cli/ode-admin-cli.cpp @@ -27,11 +27,13 @@ #include #include #include +#include #include #include #include #include +#include extern char** environ; @@ -45,6 +47,9 @@ static inline int usage(const std::string name) << " -e, --encrypt=internal|external encrypt" << std::endl << " -d, --decrypt=internal|external decrypt" << std::endl << " -f, --format=extension format and setup encryption" << 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 path required for LUKS format and LUKS open operations" << std::endl + << " -M --mapping= mapping name required for LUKS open and LUKS close operations" << std::endl << " -p, --changepw=internal|external|extension change password" << std::endl << " -s, --state=internal|external|extension get state" << std::endl << " -w, --waitmnt=internal|external|extension wait for mount"<< std::endl @@ -319,6 +324,154 @@ static inline int format_storage(const std::string name) return ret; } +class LuksListener { +public: + static void StaticCallback(ode_luks_operation_e op, int ret, void* user_data) + { + auto self = static_cast(user_data); + self->Callback(op, ret); + } + + void Callback(ode_luks_operation_e op, int ret) + { + { + std::lock_guard guard(mutex); + results.push_back({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) { + return expected == op; + }); + } + + ~LuksListener() { + ode_luks_unset_event_cb(); + } + +private: + int WaitForCallbackInternal(const std::function& opCheck) + { + std::unique_lock lock(mutex); + cond.wait(lock, [this]{ + return !results.empty(); + }); + + auto& res = results.front(); + int ret = res.ret; + + std::cout << "Luks callback received. Operation: " << static_cast(res.op) + << " result: " << res.ret << std::endl; + if (!opCheck(res.op)) { + std::cerr << "Unexpected operation finished " << res.op << std::endl; + ret = -1; + } + + results.erase(results.begin()); + lock.unlock(); + + return ret; + } + + std::condition_variable cond; + std::mutex mutex; + + struct result { + ode_luks_operation_e op; + int ret; + }; + + std::vector results; +}; + +static inline int luks(const std::string& name, + const std::string& device, + const std::string& mapping) +{ + int ret; + + 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; + } + + std::string password = getPassword(); + 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; + } + return listener.WaitForCallback(ODE_LUKS_FORMAT); + } + + if (name == "open") { + if (device.empty() || 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; + } + + 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; + } + 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(); + } + + std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl; + return -1; +} + static inline int change_password(const std::string name) { int ret; @@ -433,7 +586,7 @@ static inline int clean(const std::string name) int main(int argc, char* argv[]) { - int opt = 0, index, ret = 0; + int opt = 0, luks_opt = 0, index, ret = 0; struct option options[] = { {"help", no_argument, 0, 'h'}, @@ -442,18 +595,27 @@ int main(int argc, char* argv[]) {"encrypt", required_argument, 0, 'e'}, {"decrypt", required_argument, 0, 'd'}, {"format", required_argument, 0, 'f'}, + {"luks" , required_argument, 0, 'l'}, {"state", required_argument, 0, 's'}, {"waitmnt", required_argument, 0, 'w'}, {"clean", required_argument, 0, 'c'}, {0, 0, 0, 0} }; + struct option luks_options[] = { + {"device", required_argument, 0, 'D'}, + {"mapping", required_argument, 0, 'M'}, + {0, 0, 0, 0} + }; + if (argc <= 1) { usage(argv[0]); return EXIT_SUCCESS; } - while ((opt = getopt_long(argc, argv, "m:u:e:d:f:p:s:w:c:h", options, &index)) != -1) { + std::string mapping, device, op; + + while ((opt = getopt_long(argc, argv, "m:u:e:d:f:l:p:s:w:c:h", options, &index)) != -1) { switch (opt) { case 'm': ret = mount(optarg); @@ -470,6 +632,23 @@ int main(int argc, char* argv[]) case 'f': ret = format_storage(optarg); break; + case 'l': + op = optarg; + while ((luks_opt = getopt_long(argc, argv, "D:M:", luks_options, &index)) != -1) { + switch (luks_opt) { + case 'D': + device = optarg; + break; + case 'M': + mapping = optarg; + break; + default: + ret = usage(argv[0]); + } + } + if (ret == 0) + ret = luks(op, device, mapping); + break; case 'p': ret = change_password(optarg); break; @@ -482,6 +661,12 @@ int main(int argc, char* argv[]) case 'c': ret = clean(optarg); break; + case 'D': + device = optarg; + break; + case 'M': + mapping = optarg; + break; case 'h': default: ret = usage(argv[0]);