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