* @brief This file contains test of CAPI for Privacy Privilege Manager
*/
-#include <iostream>
#include <map>
#include <set>
#include <stdio.h>
struct ClientRequest {
RequestId m_id;
Privilege m_privilege;
+ GMainLoop *m_mainLoop;
+ bool m_stopAppAfterDeny;
};
struct Connection
GIOCondition maskToGIOCondition(int mask)
{
- int ret = (mask & FdMask::READ ? G_IO_IN : 0) |
- (mask & FdMask::WRITE ? G_IO_OUT : 0);
+ int ret = ((mask & FdMask::READ) ? G_IO_IN : 0) |
+ ((mask & FdMask::WRITE) ? G_IO_OUT : 0);
return static_cast<GIOCondition>(ret);
}
return !!(GIO_ERROR_CONDITION & condition);
}
-void print_prompt(Mode mode)
+void printPrompt(Mode mode)
{
switch (mode) {
case Mode::CLIENT:
fflush(stdout);
}
+const char *popupResultToString(ppm_popup_result_e result)
+{
+ switch (result) {
+ case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_ALLOW_FOREVER:
+ return "ALLOW_FOREVER";
+ case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER:
+ return "DENY_FOREVER";
+ case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE:
+ return "DENY_ONCE";
+ }
+
+ return "UNKNOWN";
+}
+
+void printClientHelp()
+{
+ printf("c <privilege> check privilege status\n");
+ printf("r <privilege> send popup request\n");
+ printf("s <privilege> send popup request, additionally after receiving DENY it finishes this app\n");
+ printf("h print help\n");
+ printf("q quit\n");
+ printPrompt(Mode::CLIENT);
+}
+
+void printClientError(ppm_error_e error)
+{
+ switch (error) {
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE:
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR:
+ printf("I/O error\n");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER:
+ printf("Invalid parameters\n");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY:
+ printf("Out of memory\n");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN:
+ printf("Unknown error\n");
+ break;
+ }
+}
+
+void printClientCheckResult(ppm_check_result_e result)
+{
+ printf("res: ");
+
+ switch (result) {
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
+ printf("ALLOW\n");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY:
+ printf("DENY\n");
+ break;
+ case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
+ printf("ASK\n");
+ break;
+ }
+
+ printPrompt(Mode::CLIENT);
+}
+
+void printAppHelp(const char *programName)
+{
+ printf("Usage: %s [OPTIONS]\n", programName);
+ printf("Allows to test CAPI for Privacy Privilege Manager.\n");
+ printf("This program can run in two modes: as a client and as a server.\n");
+ printf("You can use it in two scenarios:\n");
+ printf("1. Run as a client (%s -c) to trigger popups in the askuser-notification daemon.\n", programName);
+ printf("2. Run one part as a client (%s -c) and other one as a server (%s -s).\n",
+ programName, programName);
+ printf("If you want to run this program as a root you need to create /var/run/user_ext/0 folder.\n");
+ printf("To run this program in context of some Tizen's application, type in the console:\n");
+ printf("#echo <SMACK label of the application> > /proc/self/attr/current\n");
+ printf("#su - <user name>\n\n");
+ printf("Options:\n");
+ printf("-s run as a server\n");
+ printf("-c run as a client (uses CAPI)\n");
+ printf("-h display this help end exit\n");
+}
+
+void printServerHelp()
+{
+ printf("l list all connections\n");
+ printf("s list all requests\n");
+ printf("ra <fd> <request id> send ALLOW FOREVER response\n");
+ printf("rd <fd> <request id> send DENY FOREVER response\n");
+ printf("ro <fd> <request id> send DENY ONCE response\n");
+ printf("c <fd> close connection\n");
+ printf("h print help\n");
+ printf("q quit\n");
+ printPrompt(Mode::SERVER);
+}
+
struct ServerSimulator : public IServerCallbacks {
ServerSimulator()
: m_channel(nullptr)
- {
- }
+ {}
virtual void newConnection(ConnectionFd fd, const Credentials &creds) {
printf("\nnew connection fd: %d credentials = { label: \"%s\" uid: %s }",
fd, creds.label.c_str(), creds.uid.c_str());
}
- static gboolean server_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data)
- {
+ static gboolean serverGIOCallback(GIOChannel *src, GIOCondition cond, gpointer data) {
ServerSimulator *handle = static_cast<ServerSimulator *>(data);
int fd = g_io_channel_unix_get_fd(src);
- int events = (cond & G_IO_IN ? FdMask::READ : 0) |
- (cond & G_IO_OUT ? FdMask::WRITE : 0);
+ int events = ((cond & G_IO_IN) ? FdMask::READ : 0) |
+ ((cond & G_IO_OUT) ? FdMask::WRITE : 0);
handle->m_channel->process(fd, isErrorCondition(cond) ? 0 : events);
m_requests.erase(fd);
printf("Connection for fd: %d has been closed\n", fd);
- print_prompt(Mode::SERVER);
+ printPrompt(Mode::SERVER);
return;
}
guint watch_id = g_io_add_watch(gio_channel,
makeCondition(gio_condition),
- server_gio_cb,
+ serverGIOCallback,
this);
m_connections.insert({ fd, Connection{gio_channel, gio_condition, watch_id }});
g_source_remove(connection.watch_id);
connection.watch_id = g_io_add_watch(connection.gio_channel,
makeCondition(connection.condition),
- server_gio_cb,
+ serverGIOCallback,
this);
}
}
virtual void popup(ConnectionFd fd, RequestId id, Privilege &&privilege) {
printf("\npopup request fd: %d requestId: %d privilege: \"%s\"\n", fd, id, privilege.c_str());
addRequest(fd, id, privilege);
- print_prompt(Mode::SERVER);
+ printPrompt(Mode::SERVER);
}
void addRequest(ConnectionFd fd, RequestId id, const Privilege &privilege) {
- auto fdIt = m_requests.find(fd);
- if (fdIt == m_requests.end()) {
- m_requests.insert({ fd, PrivilegeRequestSet() });
- }
-
auto &s = m_requests[fd];
auto reqIt = s.find(id);
auto it = m_connections.find(fd);
if (it == m_connections.end()) {
printf("ERROR: Connection fd: %d not found\n", fd);
- print_prompt(Mode::SERVER);
+ printPrompt(Mode::SERVER);
return;
}
std::map<ConnectionFd, PrivilegeRequestSet> m_requests;
};
-struct AppContext {
+class AppContext {
+public:
AppContext()
- : m_serverSimulator(nullptr)
+ : m_mainloop(g_main_loop_new(nullptr, FALSE))
+ , m_serverSimulator(nullptr)
, m_channel(nullptr)
, m_mode(Mode::UNKNOWN)
{}
~AppContext() {
+ g_main_loop_unref(m_mainloop);
+
if (m_channel != nullptr) {
delete m_channel;
}
}
- void initialize() {
- if (m_mode == Mode::SERVER) {
- m_serverSimulator = new ServerSimulator();
- m_channel = new ServerChannel(ServerCallbacksPtr(m_serverSimulator));
- m_serverSimulator->setServerChannel(m_channel);
+ void initialize(int argc, char **argv) {
+ if (argc < 1) {
+ throw std::logic_error("AppContext::initialize called with argc < 1");
}
- }
-
- ServerSimulator *m_serverSimulator;
- ServerChannel *m_channel;
- Mode m_mode;
-};
-
-const char *popup_result_to_str(ppm_popup_result_e result)
-{
- switch (result) {
- case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_ALLOW_FOREVER:
- return "ALLOW_FOREVER";
- case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER:
- return "DENY_FOREVER";
- case PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE:
- return "DENY_ONCE";
- }
- return "UNKNOWN";
-}
-
-void popup_response_cb(ppm_call_cause_e cause, ppm_popup_result_e result, void *user_data)
-{
- ClientRequest *request = static_cast<ClientRequest *>(user_data);
- if (request == nullptr) {
- printf("ERROR: User data is nullptr\n");
- return;
- }
+ int c;
+ opterr = 0;
+ while ((c = getopt (argc, argv, "sch")) != -1) {
+ switch (c) {
+ case 's':
+ m_mode = Mode::SERVER;
+ break;
+ case 'c':
+ m_mode = Mode::CLIENT;
+ break;
+ case 'h':
+ default:
+ break;
+ }
+ }
- printf("localId: %d privilege: \"%s\" ", request->m_id, request->m_privilege.c_str());
+ switch (m_mode) {
+ case Mode::SERVER:
+ m_serverSimulator = new ServerSimulator();
+ m_channel = new ServerChannel(ServerCallbacksPtr(m_serverSimulator));
+ m_serverSimulator->setServerChannel(m_channel);
+ printServerHelp();
+ break;
+ case Mode::CLIENT:
+ printClientHelp();
+ break;
+ case Mode::UNKNOWN:
+ default:
+ printAppHelp(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
- switch (cause) {
- case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER:
- printf("popup response ANSWER: %s\n", popup_result_to_str(result));
- break;
- case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR:
- printf("popup response ERROR cause: PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR\n");
- break;
+ GIOChannel *gio_channel = g_io_channel_unix_new(0);
+ g_io_add_watch(gio_channel, static_cast<GIOCondition>(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+ &AppContext::mainLoopCallback, this);
}
- delete request;
-
- print_prompt(Mode::CLIENT);
-}
-
-void print_client_help()
-{
- printf("c <privilege> check privilege status\n");
- printf("r <privilege> send popup request\n");
- printf("h print help\n");
- printf("q quit\n");
- print_prompt(Mode::CLIENT);
-}
+ void run() {
+ if (m_mode == Mode::UNKNOWN) {
+ throw std::logic_error("AppContext is not initialized");
+ }
-void print_client_error(ppm_error_e error)
-{
- switch (error) {
- case PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE:
- break;
- case PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR:
- printf("I/O error\n");
- break;
- case PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER:
- printf("Invalid parameters\n");
- break;
- case PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY:
- printf("Out of memory\n");
- break;
- case PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN:
- printf("Unknown error\n");
- break;
+ g_main_loop_run(m_mainloop);
}
-}
-static void print_client_check_result(ppm_check_result_e result)
-{
- printf("res: ");
+private:
- switch (result) {
- case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
- printf("ALLOW\n");
- break;
- case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY:
- printf("DENY\n");
- break;
- case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
- printf("ASK\n");
- break;
- }
+ static void popupResponseCallback(ppm_call_cause_e cause, ppm_popup_result_e result, void *user_data) {
+ ClientRequest *request = static_cast<ClientRequest *>(user_data);
+ if (request == nullptr) {
+ printf("ERROR: User data is nullptr\n");
+ return;
+ }
- print_prompt(Mode::CLIENT);
-}
+ printf("localId: %d privilege: \"%s\" ", request->m_id, request->m_privilege.c_str());
-void handle_client(char *buffer)
-{
- ppm_check_result_e result;
- ppm_error_e err = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
- ClientRequest *request = nullptr;
- char *privilege = nullptr;
- static RequestId clientRequestId;
-
- switch (buffer[0]) {
- case 'c':
- if (strlen(buffer) < 3) {
- print_client_help();
+ switch (cause) {
+ case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER:
+ printf("popup response ANSWER: %s\n", popupResultToString(result));
break;
- }
- err = static_cast<ppm_error_e>(ppm_check_privilege(&buffer[2], &result));
- if (err == PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
- print_client_check_result(result);
- }
- break;
- case 'r':
- if (strlen(buffer) < 3) {
- print_client_help();
+ case PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR:
+ printf("popup response ERROR cause: PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR\n");
break;
- }
-
- buffer[strlen(buffer)] = '\0'; // erase new line
- privilege = &buffer[2];
+ }
- printf("sending localId: %d privilege: \"%s\"\n", clientRequestId, privilege);
+ if (result == PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER && request->m_stopAppAfterDeny) {
+ g_main_loop_quit(request->m_mainLoop);
+ }
- request = new ClientRequest{ clientRequestId++, privilege };
- err = static_cast<ppm_error_e>(ppm_popup_request(privilege, popup_response_cb, request));
- if (err != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
- delete request;
- }
+ delete request;
- break;
- case 'q':
- exit(EXIT_SUCCESS);
- case 'h':
- default:
- print_client_help();
- return;
+ printPrompt(Mode::CLIENT);
}
- print_client_error(err);
- print_prompt(Mode::CLIENT);
-}
+ void handleClient(char *buffer) {
+ ppm_check_result_e result;
+ ppm_error_e err = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
+ ClientRequest *request = nullptr;
+ char *privilege = nullptr;
+ static RequestId clientRequestId;
+ bool stopAppAfterDeny = false;
-void print_server_help()
-{
- printf("l list all connections\n");
- printf("s list all requests\n");
- printf("ra <fd> <request id> send ALLOW FOREVER response\n");
- printf("rd <fd> <request id> send DENY FOREVER response\n");
- printf("ro <fd> <request id> send DENY ONCE response\n");
- printf("c <fd> close connection\n");
- printf("h print help\n");
- printf("q quit\n");
- print_prompt(Mode::SERVER);
-}
+ switch (buffer[0]) {
+ case 'c':
+ if (strlen(buffer) < 3) {
+ printClientHelp();
+ break;
+ }
+ err = static_cast<ppm_error_e>(ppm_check_privilege(&buffer[2], &result));
+ if (err == PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
+ printClientCheckResult(result);
+ }
+ break;
+ case 's':
+ stopAppAfterDeny = true;
+ case 'r':
+ if (strlen(buffer) < 3) {
+ printClientHelp();
+ break;
+ }
-void handle_server(const char *buffer, ServerSimulator *serverSimulator)
-{
- int res;
- ConnectionFd fd;
- RequestId requestId;
+ buffer[strlen(buffer)] = '\0'; // erase new line
+ privilege = &buffer[2];
- switch (buffer[0]) {
- case 'l':
- serverSimulator->showConnections();
- break;
- case 's':
- serverSimulator->showPrivilegeRequests();
- break;
- case 'r':
- res = sscanf(&buffer[2], "%d %d", &fd, &requestId);
- if (res != 2) {
- print_server_help();
+ printf("sending localId: %d privilege: \"%s\"\n", clientRequestId, privilege);
+
+ request = new ClientRequest{ clientRequestId++, privilege, m_mainloop, stopAppAfterDeny };
+ err = static_cast<ppm_error_e>(ppm_popup_request(privilege, &AppContext::popupResponseCallback, request));
+ if (err != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
+ delete request;
+ }
+
+ break;
+ case 'q':
+ g_main_loop_quit(m_mainloop);
return;
- }
- switch (buffer[1]) {
- case 'a':
- serverSimulator->sendResponse(fd, requestId, ASKUSER_ALLOW_FOREVER);
- break;
- case 'd':
- serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_FOREVER);
- break;
- case 'o':
- serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_ONCE);
- break;
- default:
- print_server_help();
- return;
- }
- break;
- case 'c':
- res = sscanf(&buffer[1], "%d", &fd);
- if (res != 1) {
- print_server_help();
+ case 'h':
+ default:
+ printClientHelp();
return;
- }
- serverSimulator->closeConnection(fd);
- return;
- case 'h':
- print_server_help();
- return;
- case 'q':
- exit(EXIT_SUCCESS);
+ }
+
+ printClientError(err);
+ printPrompt(Mode::CLIENT);
}
- print_prompt(Mode::SERVER);
-}
+ void handleServer(const char *buffer) {
+ int res;
+ ConnectionFd fd;
+ RequestId requestId;
-gboolean main_loop_cb(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, gpointer user_data)
-{
- char buffer[4096];
+ switch (buffer[0]) {
+ case 'l':
+ m_serverSimulator->showConnections();
+ break;
+ case 's':
+ m_serverSimulator->showPrivilegeRequests();
+ break;
+ case 'r':
+ res = sscanf(&buffer[2], "%d %d", &fd, &requestId);
+ if (res != 2) {
+ printServerHelp();
+ return;
+ }
+ switch (buffer[1]) {
+ case 'a':
+ m_serverSimulator->sendResponse(fd, requestId, ASKUSER_ALLOW_FOREVER);
+ break;
+ case 'd':
+ m_serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_FOREVER);
+ break;
+ case 'o':
+ m_serverSimulator->sendResponse(fd, requestId, ASKUSER_DENY_ONCE);
+ break;
+ default:
+ printServerHelp();
+ return;
+ }
+ break;
+ case 'c':
+ res = sscanf(&buffer[1], "%d", &fd);
+ if (res != 1) {
+ printServerHelp();
+ return;
+ }
+ m_serverSimulator->closeConnection(fd);
+ return;
+ case 'h':
+ printServerHelp();
+ return;
+ case 'q':
+ g_main_loop_quit(m_mainloop);
+ return;
+ }
- int ret = read(0, buffer, sizeof(buffer));
- if (ret <= 0) {
- printf("read from stdin failed\n");
- exit(EXIT_FAILURE);
+ printPrompt(Mode::SERVER);
}
- buffer[ret - 1] = '\0';
+ static gboolean mainLoopCallback(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, gpointer user_data) {
+ char buffer[4096];
- AppContext *ctx = static_cast<AppContext *>(user_data);
- switch (ctx->m_mode) {
- case Mode::CLIENT:
- handle_client(buffer);
- break;
- case Mode::SERVER:
- handle_server(buffer, ctx->m_serverSimulator);
- break;
- case Mode::UNKNOWN:
- default:
- printf("Mode not set, exiting.\n");
+ int ret = read(0, buffer, sizeof(buffer));
+ if (ret <= 0) {
+ printf("read from stdin failed\n");
exit(EXIT_FAILURE);
- }
-
- return TRUE;
-}
-
-void print_help(const char *programName)
-{
- printf("Usage: %s [OPTIONS]\n", programName);
- printf("Allows to test CAPI for Privacy Privilege Manager.\n");
- printf("This program can run in two modes: as a client and as a server.\n");
- printf("You can use it in two scenarios:\n");
- printf("1. Run as a client (%s -c) to trigger popups in the askuser-notification daemon.\n", programName);
- printf("2. Run one part as a client (%s -c) and other one as a server (%s -s).\n",
- programName, programName);
- printf("If you want to run this program as a root you need to create /var/run/user_ext/0 folder.\n");
- printf("To run this program in context of some Tizen's application, type in the console:\n");
- printf("#echo <SMACK label of the application> > /proc/self/attr/current\n");
- printf("#su - <user name>\n\n");
- printf("Options:\n");
- printf("-s run as a server\n");
- printf("-c run as a client (uses CAPI)\n");
- printf("-h display this help end exit\n");
-}
+ }
-int main(int argc, char **argv)
-{
- AppContext ctx;
- int c;
+ buffer[ret - 1] = '\0';
- opterr = 0;
- while ((c = getopt (argc, argv, "sch")) != -1) {
- switch (c) {
- case 's':
- ctx.m_mode = Mode::SERVER;
+ AppContext *ctx = static_cast<AppContext *>(user_data);
+ switch (ctx->m_mode) {
+ case Mode::CLIENT:
+ ctx->handleClient(buffer);
break;
- case 'c':
- ctx.m_mode = Mode::CLIENT;
+ case Mode::SERVER:
+ ctx->handleServer(buffer);
break;
- case 'h':
+ case Mode::UNKNOWN:
default:
- break;
+ printf("Mode not set, exiting.\n");
+ exit(EXIT_FAILURE);
}
- }
- if (ctx.m_mode == Mode::UNKNOWN) {
- print_help(argv[0]);
- exit(EXIT_SUCCESS);
+ return TRUE;
}
+ GMainLoop *m_mainloop;
+ ServerSimulator *m_serverSimulator;
+ ServerChannel *m_channel;
+ Mode m_mode;
+};
+
+int main(int argc, char **argv)
+{
+ AppContext appCtx;
+
try {
- ctx.initialize();
+ appCtx.initialize(argc, argv);
+ appCtx.run();
}
catch (const ConnectionException &e) {
printf("Connection exception occured during initialization: %s, exiting.\n", e.what());
exit(EXIT_FAILURE);
}
- switch (ctx.m_mode) {
- case Mode::SERVER:
- print_server_help();
- break;
- case Mode::CLIENT:
- print_client_help();
- break;
- case Mode::UNKNOWN:
- default:
- printf("Unknown mode\n");
- exit(EXIT_FAILURE);
- }
-
- GMainLoop *mainloop = g_main_loop_new(nullptr, FALSE);
-
- GIOChannel *gio_channel = g_io_channel_unix_new(0);
- g_io_add_watch(gio_channel, static_cast<GIOCondition>(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
- main_loop_cb, &ctx);
-
- g_main_loop_run(mainloop);
-
return 0;
}