2 * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include "fido_logs.h"
26 #include "fido_uaf_types.h"
27 #include "fido_internal_types.h"
28 #include "fido_json_handler.h"
29 #include "fido_internal_types.h"
31 #include "fido_asm_plugin_manager.h"
33 #define _ASM_CONF_DIR_PATH "/usr/lib/fido/asm/"
34 #define _ASM_CONF_DIR_PATH_64 "/usr/lib64/fido/asm/"
36 typedef struct _asm_ipc_cb_data {
37 _asm_ipc_response_cb cb;
41 typedef struct _asm_ipc_discover_cb_data {
42 _asm_plugin_discover_response_cb cb;
43 GList *asm_proxy_list_iter;
46 } _asm_ipc_discover_cb_data_t;
48 static GHashTable *asm_proxy_table = NULL;
49 static GFileMonitor *__monitor = NULL;
51 static GDBusConnection *
52 __get_dbus_connection(void)
56 GDBusConnection *dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
58 if (dbus_conn == NULL) {
59 _ERR("Unable to connect to dbus: %s", error->message);
60 g_clear_error(&error);
67 __get_dbus_proxy(const char *dbus_name, const char *obj_path,
68 const char *intf_name)
70 GDBusConnection *conn = __get_dbus_connection();
76 GDBusProxy *dbus_proxy = g_dbus_proxy_new_sync(conn,
77 G_DBUS_PROXY_FLAGS_NONE,
86 _ERR("g_dbus_proxy_new_sync failed [%d][%s]", err->code, err->message);
92 __free_asm_proxy_data(gpointer data)
95 _fido_asm_proxy_t *proxy = data;
97 SAFE_DELETE(proxy->bin_path);
98 SAFE_DELETE(proxy->dbus_info);
99 SAFE_DELETE(proxy->dbus_interface_name);
100 SAFE_DELETE(proxy->dbus_method_name);
101 SAFE_DELETE(proxy->dbus_obj_path);
102 SAFE_DELETE(proxy->vendor);
111 __load_plugins(char **plugin_path)
113 if (asm_proxy_table != NULL) {
114 g_hash_table_destroy(asm_proxy_table);
115 asm_proxy_table = NULL;
118 asm_proxy_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, _free_fido_asm_proxy);
121 struct dirent *entry;
124 dir = opendir(_ASM_CONF_DIR_PATH_64);
127 dir = opendir(_ASM_CONF_DIR_PATH);
130 _ERR("Could not open [%s] and [%s] path = [%s]", _ASM_CONF_DIR_PATH_64, _ASM_CONF_DIR_PATH, strerror(errno));
131 return FIDO_ERROR_PERMISSION_DENIED;
136 *plugin_path = calloc(1, 128);
138 snprintf(*plugin_path, 127, _ASM_CONF_DIR_PATH_64);
140 snprintf(*plugin_path, 127, _ASM_CONF_DIR_PATH);
142 bool is_asm_found = false;
144 _INFO("Loading ASM conf files from [%s]", *plugin_path);
146 while ((entry = readdir(dir)) != NULL) {
147 if (entry->d_type == DT_REG) {
148 char *conf_file_name = entry->d_name;
149 if (conf_file_name != NULL) {
150 char conf_file_name_full[128] = {0, };
151 /*TODO make safe size*/
152 snprintf(conf_file_name_full, 127, "%s%s", *plugin_path, conf_file_name);
153 _INFO("Processing [%s]", conf_file_name_full);
154 _fido_asm_proxy_t *asm_proxy = _parse_asm_conf_file(conf_file_name_full);
155 if (asm_proxy != NULL) {
156 asm_proxy->dbus_proxy = __get_dbus_proxy(asm_proxy->dbus_info, asm_proxy->dbus_obj_path,
157 asm_proxy->dbus_interface_name);
158 if (asm_proxy->dbus_proxy != NULL) {
161 asm_proxy->asm_id = strdup(conf_file_name);
162 g_hash_table_insert(asm_proxy_table, strdup(conf_file_name), asm_proxy);
165 _ERR("Failed to get dbus proxy for the ASM");
166 __free_asm_proxy_data((gpointer)asm_proxy);
176 if (is_asm_found == false)
177 return FIDO_ERROR_NOT_SUPPORTED;
179 return FIDO_ERROR_NONE;
183 __plugin_changed_cb(GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type,
186 char *plugin_path = NULL;
187 int ret = __load_plugins(&plugin_path);
188 _INFO("__load_plugins=[%d]", ret);
190 SAFE_DELETE(plugin_path);
194 __set_up_watcher(const char *watch_path)
196 if ((watch_path == NULL)
197 || (strlen(watch_path) == 0))
200 GFile* file = g_file_new_for_path(watch_path);
202 if (__monitor != NULL)
203 g_object_unref(__monitor);
205 __monitor = g_file_monitor(file, G_FILE_MONITOR_NONE, NULL, NULL);
206 g_object_unref(file);
208 if (__monitor == NULL)
211 g_signal_connect(__monitor, "changed", G_CALLBACK(__plugin_changed_cb), NULL);
215 _asm_plugin_mgr_init(void)
218 _INFO("_asm_plugin_mgr_init start");
220 char *plugin_path = NULL;
221 int ret = __load_plugins(&plugin_path);
222 _INFO("__load_plugins=[%d]", ret);
224 __set_up_watcher(plugin_path);
226 SAFE_DELETE(plugin_path);
228 /*Ignored load_plugins error, since ASM might get installed later*/
229 return FIDO_ERROR_NONE;
233 _asm_plugin_mgr_destroy(void)
235 if (asm_proxy_table != NULL) {
236 g_hash_table_destroy(asm_proxy_table);
237 asm_proxy_table = NULL;
239 if (__monitor != NULL)
240 g_object_unref(__monitor);
244 __discover_cb_internal(int error_code, const char *asm_response_json, void *user_data)
246 _asm_ipc_discover_cb_data_t *cb_data = user_data;
248 _asm_discover_response_t *response_info = calloc(1, sizeof(_asm_discover_response_t));
249 response_info->error_code = error_code;
250 if (asm_response_json != NULL)
251 response_info->asm_response_json = strdup(asm_response_json);
253 _fido_asm_proxy_t *asm_proxy = (_fido_asm_proxy_t*)(cb_data->asm_proxy_list_iter->data);
254 response_info->asm_id = strdup(asm_proxy->asm_id);
256 cb_data->asm_resp_list = g_list_append(cb_data->asm_resp_list, response_info);
258 cb_data->asm_proxy_list_iter = g_list_next(cb_data->asm_proxy_list_iter);
259 if (cb_data->asm_proxy_list_iter == NULL) {
260 _INFO("All ASM processing finished");
262 cb_data->asm_resp_list = g_list_first(cb_data->asm_resp_list);
263 (cb_data->cb)(cb_data->asm_resp_list, cb_data->user_data);
265 cb_data->asm_proxy_list_iter = g_list_first(cb_data->asm_proxy_list_iter);
266 g_list_free(cb_data->asm_proxy_list_iter);
268 SAFE_DELETE(cb_data);
272 _fido_asm_proxy_t *asm_proxy = (_fido_asm_proxy_t*)(cb_data->asm_proxy_list_iter->data);
273 int ret = _asm_ipc_send(asm_proxy->asm_id, _GET_INFO_ASM_REQUEST_JSON, __discover_cb_internal, cb_data);
274 if (ret != FIDO_ERROR_NONE)
275 __discover_cb_internal(ret, NULL, user_data);
281 _asm_plugin_mgr_discover_all(_asm_plugin_discover_response_cb cb, void *user_data)
283 if (asm_proxy_table == NULL
284 || g_hash_table_size(asm_proxy_table) <= 0) {
285 _ERR("No ASM found");
286 return FIDO_ERROR_NOT_SUPPORTED;
289 _asm_ipc_discover_cb_data_t *cb_data = calloc(1, sizeof(_asm_ipc_discover_cb_data_t));
294 cb_data->asm_proxy_list_iter = g_hash_table_get_values(asm_proxy_table);
296 cb_data->user_data = user_data;
298 _fido_asm_proxy_t *asm_proxy = (_fido_asm_proxy_t*)(cb_data->asm_proxy_list_iter->data);
300 return _asm_ipc_send(asm_proxy->asm_id, _GET_INFO_ASM_REQUEST_JSON, __discover_cb_internal, cb_data);
304 _on_asm_dbus_reply(GObject *proxy, GAsyncResult *res, gpointer user_data)
306 _INFO("_on_asm_dbus_reply");
308 GError *dbus_err = NULL;
310 if (user_data == NULL) {
311 _ERR("Can not proceed since callback data is NULL");
315 _asm_ipc_cb_data_t *cb_data = (_asm_ipc_cb_data_t *)user_data;
316 if (cb_data == NULL) {
317 _ERR("Can not proceed since callback data is NULL");
321 if (cb_data->cb == NULL) {
322 _ERR("Can not proceed since callback data's cb part is NULL");
326 int tizen_err = FIDO_ERROR_NONE;
327 char *asm_response_json = NULL;
329 GError *error = NULL;
331 /*For dereg request, ASM does not send any reponse, so this is not error for dereg*/
332 GVariant *dbus_resp = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error);
333 if (dbus_resp == NULL) {
334 _ERR("g_dbus_proxy_call_finish failed with [%d][%s]", error->code, error->message);
335 (cb_data->cb)(FIDO_ERROR_PERMISSION_DENIED, NULL, cb_data->user_data);
337 SAFE_DELETE(cb_data);
342 g_variant_get(dbus_resp, "(is)",
347 g_clear_error(&dbus_err);
349 if (asm_response_json != NULL)
350 _INFO("asm_response_json=[%s]", asm_response_json);
352 (cb_data->cb)(tizen_err, asm_response_json, cb_data->user_data);
354 if (dbus_resp != NULL)
355 g_variant_unref(dbus_resp);
357 SAFE_DELETE(cb_data);
361 __get_asm_req_dbus_method_name(const char *intf_name, const char *dbus_method_name)
363 char *method_name = (char *)calloc(1, 128);
364 if (method_name == NULL)
367 snprintf(method_name, 127, "%s.%s", intf_name, dbus_method_name);
373 _asm_ipc_send(const char *asm_id, const char *asm_request, _asm_ipc_response_cb cb, void *user_data)
375 _INFO("asm_request=[%s]", asm_request);
377 if (asm_id == NULL) {
378 _ERR("dbus proxy failed");
379 return FIDO_ERROR_NOT_SUPPORTED;
382 _fido_asm_proxy_t *asm_proxy = g_hash_table_lookup(asm_proxy_table, asm_id);
383 if (asm_proxy == NULL) {
384 _ERR("dbus proxy failed");
385 return FIDO_ERROR_NOT_SUPPORTED;
388 _INFO("For=[%s]", asm_id);
390 if (asm_proxy->dbus_info != NULL)
391 _INFO("For DBUS = [%s]", asm_proxy->dbus_info);
393 _asm_ipc_cb_data_t *cb_data = (_asm_ipc_cb_data_t*)calloc(1, sizeof(_asm_ipc_cb_data_t));
398 cb_data->user_data = user_data;
400 char *method_name = __get_asm_req_dbus_method_name(asm_proxy->dbus_interface_name,
401 asm_proxy->dbus_method_name);
402 if (method_name == NULL) {
404 SAFE_DELETE(cb_data);
405 return FIDO_ERROR_OUT_OF_MEMORY;
408 g_dbus_proxy_call(asm_proxy->dbus_proxy,
410 g_variant_new ("(s)",
412 G_DBUS_CALL_FLAGS_NONE,
413 _DBUS_TIMEOUT_INFINITE,
418 SAFE_DELETE(method_name);
424 _asm_ipc_send_sync(const char *asm_id, const char *asm_req)
426 _INFO("_asm_ipc_send_sync");
428 if (asm_id == NULL) {
429 _ERR("dbus proxy failed");
433 _INFO("For=[%s]", asm_id);
435 _fido_asm_proxy_t *asm_proxy = g_hash_table_lookup(asm_proxy_table, asm_id);
436 if (asm_proxy == NULL) {
437 _ERR("dbus proxy failed");
441 if (asm_proxy->dbus_info != NULL)
442 _INFO("For DBUS = [%s]", asm_proxy->dbus_info);
444 int tz_err = FIDO_ERROR_NONE;
445 char *asm_res_json = NULL;
447 GError *error = NULL;
450 char *method_name = __get_asm_req_dbus_method_name(asm_proxy->dbus_interface_name,
451 asm_proxy->dbus_method_name);
453 if (method_name == NULL)
456 _ret = g_dbus_proxy_call_sync(asm_proxy->dbus_proxy,
458 g_variant_new ("(s)",
460 G_DBUS_CALL_FLAGS_NONE,
461 _DBUS_TIMEOUT_USE_DEFAULT,
466 _ERR("g_dbus_proxy_call_sync failed [%s]", error->message);
468 _INFO("g_dbus_proxy_call_sync success");
473 g_variant_get (_ret, "(is)", &tz_err, &asm_res_json);
474 if (asm_res_json != NULL)
475 _INFO("ASM returned = %s", asm_res_json);
477 //g_variant_unref (_ret);