f20fb256b9aec4d1be9592c6c70043798d56010c
[platform/core/account/fido-asm.git] / server / src / ClientListener.cpp
1 /*
2  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include "ClientListener.h"
19 #include <app_manager.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <tizen.h>
24 #include <gio/gio.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <aul.h>
29 #include "JsonUtil.h"
30 #include "AsmOp.h"
31 #include "AsmOpFactory.h"
32 #include "AsmHelper.h"
33 #include "TCUiAdaptor.h"
34 #include "AcUiAdaptor.h"
35 #include "AuthUiFactory.h"
36 #include "RoamingUtil.h"
37
38 //#define ASM_UI_TEST
39
40 #define ASM_DBUS_PATH "/org/tizen/fidoasm"
41 #define ASM_DBUS_NAME "org.tizen.fidoasm"
42
43 #define _FREEDESKTOP_SERVICE    "org.freedesktop.DBus"
44 #define _FREEDESKTOP_PATH       "/org/freedesktop/DBus"
45 #define _FREEDESKTOP_INTERFACE  "org.freedesktop.DBus"
46
47 #define FIDO_CLIENT_SVC_PATH "/usr/bin/fido-service"
48 #define FIDO_RAGENT_SVC_PATH "/usr/bin/fido-roaming-agent-service"
49 #define FIDO_BLE_RAGENT_SVC_PATH "/usr/bin/fido-ble-ragent-service"
50 #define FIDO_BT_RAGENT_SVC_PATH "/usr/bin/fido-bt-ragent-service"
51
52 guint ClientListner::__ownerId = 0;
53 Fidoasm* ClientListner::__dbusObj = NULL;
54
55 ClientListner* ClientListner::__this = NULL;
56
57 #define RESP_NEG "{\"statusCode\":1}"
58
59 ClientListner::ClientListner(void) {}
60
61 ClientListner::~ClientListner(void) {}
62
63 ClientListner*
64 ClientListner::getInstance(void)
65 {
66         if (__this != NULL)
67                 return __this;
68
69         /*TODO: thread-safe singleton*/
70         ClientListner *thisTemp = new ClientListner();
71         if (thisTemp == NULL)
72                 return NULL;
73
74         __this = thisTemp;
75
76         return __this;
77 }
78
79 int
80 ClientListner::readProc(const char *path, char *buf, int size)
81 {
82         int fd = 0;
83         int ret = 0;
84
85         if (buf == NULL || path == NULL) {
86                 _ERR("path and buffer is mandatory\n");
87                 return -1;
88         }
89
90         fd = open(path, O_RDONLY);
91         if (fd < 0) {
92                 _ERR("fd open error(%d)\n", fd);
93                 return -1;
94         }
95
96         ret = read(fd, buf, size - 1);
97         if (ret <= 0) {
98                 _ERR("fd read error(%d)\n", fd);
99                 close(fd);
100                 return -1;
101         } else {
102                 buf[ret] = 0;
103         }
104
105         close(fd);
106
107         return ret;
108 }
109
110 std::string
111 ClientListner::getCallerId(GDBusMethodInvocation *invocation)
112 {
113         pid_t remote_pid = 0;
114         GError *error = NULL;
115         GDBusConnection *connection = NULL;
116         GVariant *response = NULL;
117         guint32 upid;
118         const gchar *sender = NULL;
119
120         sender = g_dbus_method_invocation_get_sender(invocation);
121         if (!sender) {
122                 _ERR("Failed to get sender");
123                 return "";
124         }
125
126         connection = g_dbus_method_invocation_get_connection(invocation);
127         if (connection == NULL) {
128                 _ERR("Failed to open connection for the invocation");
129                 return "";
130         }
131
132         error = NULL;
133         response = g_dbus_connection_call_sync(connection,
134                         _FREEDESKTOP_SERVICE, _FREEDESKTOP_PATH,
135                         _FREEDESKTOP_INTERFACE, "GetConnectionUnixProcessID",
136                         g_variant_new("(s)", sender), ((const GVariantType *) "(u)"),
137                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
138
139
140         if (response == NULL) {
141                 _ERR("Failed to get caller id [%s]", error->message);
142                 g_error_free(error);
143                 return "";
144         }
145
146         g_variant_get(response, "(u)", &upid);
147         _INFO("Remote msg-bus peer service=%s pid=%u", sender, upid);
148         remote_pid = (pid_t) upid;
149
150         g_variant_unref(response);
151
152         char *app_id = NULL;
153         int ret = app_manager_get_app_id(remote_pid, &app_id);
154
155         if (app_id == NULL) {
156                 _ERR("app_manager_get_app_id for %d failed = %d", remote_pid, ret);
157
158                 /* Exception case : Daemons will not have app-ids, for them path will be set : /usr/bin/sample-service */
159                 char buf[128];
160                 int ret = 0;
161
162                 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", upid);
163                 ret = readProc(buf, buf, sizeof(buf));
164                 if (ret <= 0) {
165                         _ERR("No proc directory (%d)\n", upid);
166                         return "";
167                 }
168
169                 _INFO("Caller=[%s]", buf);
170
171                 app_id = strdup(buf);
172         }
173
174
175         std::string appIdStr(app_id, strlen(app_id));
176         SAFE_DELETE(app_id);
177         return appIdStr;
178 }
179
180 #define ASM_RESP_ACCESS_DENIED "{\"statusCode\":2}"
181 #define ASM_RESP_DEREG "{\"statusCode\":0}"
182
183 gboolean
184 ClientListner::onClientRequest(Fidoasm *object, GDBusMethodInvocation *invocation,
185                                                                         const gchar *asmReqJson)
186 {
187         _BEGIN;
188
189         /*TODO: Caller Id check*/
190
191         AsmRequest *req = NULL;
192
193         std::string callerId = FIDO_CLIENT_SVC_PATH;
194
195         _INFO("FIDO client request");
196         req = JsonUtil::parseAsmRequestJson(asmReqJson);
197         _INFO("");
198         if (req == NULL) {
199                 fidoasm_complete_asm_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
200                 return true;
201         }
202         req->setCallerId(callerId);
203
204         AsmOp *operation = AsmOpFactory::createOperation(req);
205         if (operation == NULL) {
206                 _ERR("AsmOp creation failed");
207                 fidoasm_complete_asm_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
208                 return true;
209         }
210
211         _INFO("Before operation exec ");
212         char *asmResp = operation->execute();
213         /*For Dereg request coming from Client, there should not be any indication about success/failure*/
214         if ((req->getRequesttype() == "Deregister")) {
215                 _INFO("");
216                 fidoasm_complete_asm_request(__dbusObj, invocation, -1, ASM_RESP_DEREG);
217                 return true;
218         }
219         if (asmResp == NULL) {
220                 _ERR("");
221                 fidoasm_complete_asm_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
222                 return true;
223         }
224
225         _INFO("After operation exec ");
226         _INFO("%s", asmResp);
227         fidoasm_complete_asm_request(__dbusObj, invocation, 0, asmResp);
228         _END;
229
230         return true;
231 }
232
233 gboolean
234 ClientListner::onAgentRequest(Fidoasm *object, GDBusMethodInvocation *invocation,
235                                                                         const gchar *tlvReqB64)
236 {
237         _BEGIN;
238
239         /*TODO: Caller Id check*/
240
241         AsmRequest *req = NULL;
242
243         std::string callerId = FIDO_BT_RAGENT_SVC_PATH;
244
245         _INFO("Roaming Agent request");
246         if (RoamingUtil::isRASupported() == false) {
247                 _ERR("RA feature not supported");
248
249                 fidoasm_complete_ra_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
250                 return true;
251         }
252
253         req = RoamingUtil::createAuthReq(tlvReqB64);
254         if (req == NULL) {
255                 _ERR("");
256                 fidoasm_complete_ra_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
257                 return true;
258         }
259         req->setCallerId(callerId);
260
261
262         AsmOp *operation = AsmOpFactory::createOperation(req);
263         if (operation == NULL) {
264                 _ERR("AsmOp creation failed");
265                 fidoasm_complete_ra_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
266                 return true;
267         }
268
269         _INFO("Before operation exec ");
270         char *asmResp = operation->execute();
271         if (asmResp == NULL) {
272                 _ERR("");
273                 fidoasm_complete_ra_request(__dbusObj, invocation, -1, ASM_RESP_ACCESS_DENIED);
274                 return true;
275         }
276
277         _INFO("After operation exec ");
278         _INFO("%s", asmResp);
279         fidoasm_complete_asm_request(__dbusObj, invocation, 0, asmResp);
280         _END;
281
282         return true;
283 }
284
285 gboolean
286 ClientListner::onTCUiResponse(Fidoasm *object, GDBusMethodInvocation *invocation,
287                                            const gchar *nonce, int result)
288 {
289         /*TODO: Allow only from org.tizen.asmui*/
290         TcUiAdaptor::OnTcResponseFromUi(nonce, result);
291
292         return true;
293 }
294
295 gboolean
296 ClientListner::onAccountUiResponse(Fidoasm *object, GDBusMethodInvocation *invocation,
297                                            const gchar *nonce, int result, const gchar *account)
298 {
299         /*TODO: Allow only from org.tizen.asmui*/
300         AcUiAdaptor::OnAccountResponseFromUi(nonce, result, account);
301
302         return true;
303 }
304
305 gboolean
306 ClientListner::onAuthUiResponse(Fidoasm *object, GDBusMethodInvocation *invocation,
307                                            int uiType, const gchar *nonce, int error,
308                                                                 const gchar *token)
309 {
310         /*TODO: Allow only from org.tizen.asmui*/
311         IAuthUiAdaptor *uiAd = AuthUiFactory::getAuthUiAdaptor((auth_ui_type_e)uiType);
312         RET_IF_FAIL(uiAd != NULL, false);
313
314         if (nonce == NULL)
315                 _INFO("Nonce received from to UI=[NULL]");
316         else
317                 _INFO("Nonce received from to UI=[%s]", nonce);
318
319         uiAd->OnAuthResponseFromUi(nonce, token, error);
320
321         return true;
322 }
323
324 void
325 ClientListner::onBusAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
326 {
327         _BEGIN;
328
329         GDBusInterfaceSkeleton* interface = NULL;
330         __dbusObj = fidoasm_skeleton_new();
331         if (__dbusObj == NULL) {
332                 return;
333         }
334
335         interface = G_DBUS_INTERFACE_SKELETON(__dbusObj);
336         if (!g_dbus_interface_skeleton_export(interface, connection, ASM_DBUS_PATH, NULL)) {
337                 return;
338         }
339
340         g_signal_connect(__dbusObj, "handle_asm_request",
341                                         G_CALLBACK(ClientListner::onClientRequest), NULL);
342
343         g_signal_connect(__dbusObj, "handle_ra_request",
344                                         G_CALLBACK(ClientListner::onAgentRequest), NULL);
345
346         g_signal_connect(__dbusObj, "handle_asm_ui_confirm_tc",
347                                         G_CALLBACK(ClientListner::onTCUiResponse), NULL);
348
349         g_signal_connect(__dbusObj, "handle_asm_ui_confirm_acc",
350                                         G_CALLBACK(ClientListner::onAccountUiResponse), NULL);
351
352         g_signal_connect(__dbusObj, "handle_auth_ui_result",
353                                         G_CALLBACK(ClientListner::onAuthUiResponse), NULL);
354
355         _END;
356 }
357
358 void
359 ClientListner::onNameAcquired(GDBusConnection *connection,
360                                                 const gchar *name,
361                                                 gpointer user_data)
362 {
363 }
364
365 void
366 ClientListner::onNameLost(GDBusConnection *connection,
367                                                 const gchar *name,
368                                                 gpointer user_data)
369 {
370                 exit(1);
371 }
372
373 bool
374 ClientListner::initDbus(void)
375 {
376         _BEGIN;
377
378         __ownerId = g_bus_own_name(G_BUS_TYPE_SYSTEM,
379                                                          ASM_DBUS_NAME,
380                                                          G_BUS_NAME_OWNER_FLAGS_NONE,
381                                                          ClientListner::onBusAcquired,
382                                                          ClientListner::onNameAcquired,
383                                                          ClientListner::onNameAcquired,
384                                                          NULL,
385                                                          NULL);
386
387
388         if (__ownerId == 0) {
389                         return false;
390         }
391
392         _END;
393
394         return true;
395 }
396
397 void
398 ClientListner::initialize(void)
399 {
400 #if !GLIB_CHECK_VERSION(2, 35, 0)
401         g_type_init();
402 #endif
403
404         if (initDbus() == false) {
405                 exit(1);
406         }
407 }
408
409 int
410 ClientListner::start(void)
411 {
412         if (__this == NULL)
413                 return -1;
414
415         _BEGIN;
416
417         GMainLoop *mainloop = NULL;
418
419         mainloop = g_main_loop_new(NULL, FALSE);
420
421         initialize();
422
423         g_main_loop_run(mainloop);
424
425         _END;
426
427         return 0;
428 }