Add file lock to key-manager server
[platform/core/security/key-manager.git] / src / listener / listener-daemon.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <syslog.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <systemd/sd-daemon.h>
11
12 #include <glib.h>
13 #include <package_manager.h>
14 #include <ckm/ckm-control.h>
15 #include <ckm/ckm-type.h>
16 #include <vconf/vconf.h>
17 #include <dlog.h>
18
19 #define CKM_LISTENER_TAG "CKM_LISTENER"
20
21 #ifndef VCONFKEY_SECURITY_MDPP_STATE
22 #define VCONFKEY_SECURITY_MDPP_STATE "file/security_mdpp/security_mdpp_state"
23 #endif
24
25 namespace {
26 const char* const CKM_LOCK = "/var/run/key-manager.pid";
27 };
28
29 void daemonize()
30 {
31     // Let's operate in background
32     int result = fork();
33     if (result < 0){
34         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Error in fork!");
35         exit(1);
36     }
37
38     if (result > 0)
39         exit(0);
40
41     // Let's disconnect from terminal
42     if (-1 == setsid()) {
43         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Error in fork!");
44         exit(1);
45     }
46
47     // Let's close all descriptors
48 //    for (result = getdtablesize(); result>=0; --result)
49 //    close(result);
50
51     close(0);
52     close(1);
53     close(2);
54
55     result = open("/dev/null", O_RDWR); // open stdin
56
57     int fd_stdout = 0;
58     int fd_stderr = 0;
59     fd_stdout = dup(result); // stdout
60     fd_stderr = dup(result); // stderr
61     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "%d : %s", fd_stdout, "stdout file descriptor");
62     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "%d : %s", fd_stderr, "stderr file descriptor");
63
64
65     umask(027);
66
67     // Let's change current directory
68     if (-1 == chdir("/")) {
69         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Error in chdir!");
70         exit(1);
71     }
72
73     // Let's create lock file
74     result = open("/tmp/ckm-listener.lock", O_RDWR | O_CREAT, 0640);
75     if (result < 0) {
76         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Error in opening lock file!");
77         exit(1);
78     }
79
80     if (lockf(result, F_TLOCK, 0) < 0) {
81         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Daemon already working!");
82         exit(0);
83     }
84
85     char str[100];
86     sprintf(str, "%d\n", getpid());
87     result = write(result, str, strlen(str));
88
89     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "%s", str);
90 }
91
92 bool isCkmRunning()
93 {
94     int lock = TEMP_FAILURE_RETRY(open(CKM_LOCK, O_RDWR));
95     if (lock == -1)
96         return false;
97
98     int ret = lockf(lock, F_TEST, 0);
99     close(lock);
100
101     // if lock test fails because of an error assume ckm is running
102     return (0 != ret);
103 }
104
105 void callUpdateCCMode()
106 {
107     if(!isCkmRunning())
108         return;
109
110     auto control = CKM::Control::create();
111     int ret = control->updateCCMode();
112
113     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "Callback caller process id : %d\n", getpid());
114
115     if ( ret != CKM_API_SUCCESS )
116         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "CKM::Control::updateCCMode error. ret : %d\n", ret);
117     else
118         SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "CKM::Control::updateCCMode success.\n");
119 }
120
121 void packageUninstalledEventCallback(
122     const char *type,
123     const char *package,
124     package_manager_event_type_e eventType,
125     package_manager_event_state_e eventState,
126     int progress,
127     package_manager_error_e error,
128     void *userData)
129 {
130     (void) type;
131     (void) progress;
132     (void) error;
133     (void) userData;
134
135     if (eventType != PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL ||
136             eventState != PACKAGE_MANAGER_EVENT_STATE_STARTED ||
137             package == NULL) {
138         SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "PackageUninstalled Callback error of Invalid Param");
139     }
140     else {
141         SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "PackageUninstalled Callback. Uninstalation of: %s", package);
142         auto control = CKM::Control::create();
143         int ret = 0;
144         if ( CKM_API_SUCCESS != (ret = control->removeApplicationData(std::string(package))) ) {
145             SLOG(LOG_ERROR, CKM_LISTENER_TAG, "CKM::Control::removeApplicationData error. ret : %d\n", ret);
146         }
147         else {
148             SLOG(LOG_DEBUG, CKM_LISTENER_TAG,
149                 "CKM::Control::removeApplicationData success. Uninstallation package : %s\n", package);
150         }
151     }
152 }
153
154 void ccModeChangedEventCallback(keynode_t*, void*)
155 {
156     callUpdateCCMode();
157 }
158
159 int main(void) {
160     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "%s", "Start!");
161
162     daemonize();
163
164     // Let's start to listen
165     GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
166
167     package_manager_h request;
168     package_manager_create(&request);
169
170     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "register uninstalledApp event callback start");
171     if (0 != package_manager_set_event_cb(request, packageUninstalledEventCallback, NULL)) {
172         SLOG(LOG_ERROR, CKM_LISTENER_TAG, "%s", "Error in package_manager_set_event_cb");
173         exit(-1);
174     }
175     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "register uninstalledApp event callback success");
176
177     int ret = 0;
178     char *mdpp_state = vconf_get_str(VCONFKEY_SECURITY_MDPP_STATE);
179     if ( mdpp_state ) { // Update cc mode and register event callback only when mdpp vconf key exists
180         callUpdateCCMode();
181
182         SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "register vconfCCModeChanged event callback start");
183         if ( 0 != (ret = vconf_notify_key_changed(VCONFKEY_SECURITY_MDPP_STATE, ccModeChangedEventCallback, NULL)) ) {
184             SLOG(LOG_ERROR, CKM_LISTENER_TAG, "Error in vconf_notify_key_changed. ret : %d", ret);
185             exit(-1);
186         }
187         SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "register vconfCCModeChanged event callback success");
188     }
189     else
190         SLOG(LOG_DEBUG, CKM_LISTENER_TAG,
191             "vconfCCModeChanged event callback is not registered. No vconf key exists : %s", VCONFKEY_SECURITY_MDPP_STATE);
192
193     SLOG(LOG_DEBUG, CKM_LISTENER_TAG, "%s", "Ready to listen!");
194     g_main_loop_run(main_loop);
195     return 0;
196 }
197