increase code quality(static analysis)
[platform/core/account/fido-client.git] / server / fido_server.c
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 <stdio.h>
19 #include <stdlib.h>
20 #include <signal.h>
21 #include <glib.h>
22 #if !GLIB_CHECK_VERSION(2, 31, 0)
23 #include <glib/gmacros.h>
24 #endif
25
26 #include "fido_privilege_checker.h"
27 #include "fido_asm_plugin_manager.h"
28 #include "fido_internal_types.h"
29 #include "fido_json_handler.h"
30 #include "fido_keys.h"
31 #include "fido_app_id_handler.h"
32 #include "fido_uaf_policy_checker.h"
33 #include "fido_selection_ui_adaptor.h"
34 #include "fido_logs.h"
35 #include "fido_uaf_types.h"
36 #include "fido-stub.h"
37
38 #define _FIDO_SERVICE_DBUS_PATH       "/org/tizen/fido"
39
40 /* timeout for terminating on-demand service */
41 #define _FIDO_SERVICE_MIN_TIMEOUT       1       /* seconds */
42 #define _FIDO_SERVICE_BOOTUP_TIMEOUT    30      /* seconds */
43 #define _FIDO_SERVICE_PROCESS_TIMEOUT   90      /* seconds */
44
45 static guint owner_id = 0;
46 //GDBusObjectManagerServer *fido_dbus_mgr = NULL;
47 static Fido* fido_dbus_obj = NULL;
48 static GMainLoop *mainloop = NULL;
49 static guint timeout_handle;
50
51 //TODO : current assumption is, ASM will handle multiple request queueing
52
53 typedef struct _dbus_info {
54         Fido *dbus_obj;
55         GDBusMethodInvocation *invocation;
56 } _dbus_info_t;
57
58 typedef struct _discover_cb {
59         //fido_authenticator_cb cb;
60         void *user_data;
61         _dbus_info_t *dbus_info;
62 } discover_cb_t;
63
64 typedef struct _fido_discover_asm_cb_data {
65         _fido_discover_asm_cb cb;
66         void *user_data;
67 } _fido_discover_asm_cb_data_t;
68
69 typedef enum {
70         _PROCESS_TYPE_MIN = 0,
71         _PROCESS_TYPE_AUTH,
72         _PROCESS_TYPE_REG,
73         _PROCESS_TYPE_DEREG,
74         _PROCESS_TYPE_CHECK_POLICY,
75         _PROCESS_TYPE_MAX
76 } _process_type_t;
77
78 typedef struct _process_cb_data {
79         _process_type_t type;
80         _message_t *uaf_req;
81         void *asm_in;/* ASM input data, type varies depending on operation name */
82         _dbus_info_t *dbus_info;
83 } _process_cb_data_t;
84
85 static void __process_dereg_queue(_dereg_q_t *dereg_q);
86 static void __set_timeout(int seconds);
87
88 static char**
89 __create_empty_json_2d_array(void)
90 {
91         char **asm_resp_json_arr = calloc(1, sizeof(int));
92
93         char *empty_asm_resp = calloc(1, 128);
94         snprintf(empty_asm_resp, 127, "%s", _EMPTY_JSON_STRING);
95         asm_resp_json_arr[0] = empty_asm_resp;
96
97         return asm_resp_json_arr;
98 }
99
100 static void
101 __free_2d_string_array(char **arr, int row_count)
102 {
103         RET_IF_FAIL_VOID(arr != NULL);
104
105         int i = 0;
106         for (; i < row_count; i++)
107                 SAFE_DELETE(arr[i]);
108
109         SAFE_DELETE(arr);
110 }
111
112 static char*
113 __dup_string(const char *source)
114 {
115         if (source != NULL)
116                 return strdup(source);
117
118         return NULL;
119 }
120
121 static void
122 __free_asm_discover_response_list_item(gpointer data)
123 {
124         RET_IF_FAIL_VOID(data != NULL);
125
126         _free_asm_discover_response((_asm_discover_response_t*)data);
127 }
128
129 static void
130 __send_discover_response(Fido *object, GDBusMethodInvocation *invocation, int err, char **asm_resp_2d_arr, int asm_resp_len)
131 {
132         if (asm_resp_2d_arr == NULL
133                         || asm_resp_len <= 0) {
134
135                 char **empty_arr = __create_empty_json_2d_array();
136                 fido_complete_fido_uaf_discover(object, invocation, err,
137                         (const gchar * const *)empty_arr, 0);
138
139                 __free_2d_string_array(empty_arr, 1);
140                 return;
141         }
142
143         fido_complete_fido_uaf_discover(object, invocation, err,
144                 (const gchar * const *)asm_resp_2d_arr, asm_resp_len);
145
146         __free_2d_string_array(asm_resp_2d_arr, asm_resp_len);
147 }
148
149 void
150 _asm_get_info_cb(GList *asm_resp_list, void *user_data)
151 {
152         _INFO("_asm_get_info_cb");
153
154         _dbus_info_t *dbus_info = (_dbus_info_t *)user_data;
155         if (dbus_info != NULL) {
156
157                 if (asm_resp_list != NULL) {
158
159                         int str_list_len = g_list_length(asm_resp_list);
160                         char **asm_resp_json_arr = calloc(str_list_len, sizeof(int));
161                         int data_len = 0;
162                         int i = 0;
163
164                         GList *asm_resp_list_iter = g_list_first(asm_resp_list);
165                         while (asm_resp_list_iter != NULL) {
166                                 _asm_discover_response_t *disc_resp = (_asm_discover_response_t*)(asm_resp_list_iter->data);
167
168                                 if (disc_resp->asm_response_json != NULL) {
169                                         asm_resp_json_arr[i++] = strdup(disc_resp->asm_response_json);
170                                         data_len++;
171                                 }
172                                 asm_resp_list_iter = g_list_next(asm_resp_list_iter);
173                         }
174
175                    __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NONE,
176                                                                                    asm_resp_json_arr, data_len);
177                 } else
178                    __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NOT_SUPPORTED,
179                                                                                    NULL, 0);
180         }
181
182         if (asm_resp_list != NULL)
183                 g_list_free_full(asm_resp_list, __free_asm_discover_response_list_item);
184 }
185
186 static void
187 _send_process_response(_process_cb_data_t *cb_data, int tz_err_code, char *uaf_response_json)
188 {
189         _INFO("_send_process_response");
190
191         if (cb_data == NULL) {
192                 SAFE_DELETE(uaf_response_json);
193                 return;
194         }
195
196         /*TODO*/
197         _dbus_info_t *dbus_info = (_dbus_info_t *)(cb_data->dbus_info);
198         if (dbus_info != NULL) {
199                 if (cb_data->type == _PROCESS_TYPE_CHECK_POLICY) {
200                         _INFO("before fido_complete_fido_uaf_check_policy");
201                         fido_complete_fido_uaf_check_policy(dbus_info->dbus_obj, dbus_info->invocation, tz_err_code);
202                         goto CATCH;
203                 }
204
205                 _INFO("before fido_complete_fido_uaf_process_operation");
206
207                 if (uaf_response_json != NULL)
208                         fido_complete_fido_uaf_process_operation(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NONE,
209                                                                                            uaf_response_json);
210                 else
211                         fido_complete_fido_uaf_process_operation(dbus_info->dbus_obj, dbus_info->invocation, tz_err_code, _EMPTY_JSON_STRING);
212         }
213
214 CATCH:
215         SAFE_DELETE(uaf_response_json);
216         _free_message(cb_data->uaf_req);
217
218         SAFE_DELETE(cb_data->dbus_info);
219
220         if (cb_data->type == _PROCESS_TYPE_AUTH)
221                 _free_fido_asm_auth_in((_fido_asm_auth_in_t*)(cb_data->asm_in));
222         else if (cb_data->type == _PROCESS_TYPE_REG)
223                 _free_fido_asm_reg_in((_fido_asm_reg_in_t*)(cb_data->asm_in));
224         else if (cb_data->type == _PROCESS_TYPE_DEREG)
225                 _free_fido_asm_dereg_in((_fido_asm_dereg_in_t*)(cb_data->asm_in));
226         else
227                 SAFE_DELETE(cb_data->asm_in);
228
229         SAFE_DELETE(cb_data);
230 }
231
232 void
233 _discover_response_intermediate_cb(GList *asm_response_list, void *user_data)
234 {
235         _INFO("_discover_response_intermediate_cb");
236
237         _fido_discover_asm_cb_data_t *cb_data = (_fido_discover_asm_cb_data_t *)user_data;
238
239         int error = FIDO_ERROR_NONE;
240         GList *asm_auth_list = NULL;
241
242         if (asm_response_list == NULL)
243                 _ERR("Discover response failed");
244         else
245                 asm_auth_list = _uaf_parser_parse_asm_response_discover(asm_response_list, &error);
246
247         (cb_data->cb)(error, 0, asm_auth_list, cb_data->user_data);
248
249         if (asm_response_list != NULL)
250                 g_list_free_full(asm_response_list, __free_asm_discover_response_list_item);
251
252         SAFE_DELETE(cb_data);
253 }
254
255 static int
256 __fido_uaf_discover_internal(_fido_discover_asm_cb callback, void *user_data)
257 {
258         _INFO("__fido_uaf_discover_internal");
259
260         _fido_discover_asm_cb_data_t *cb_data_inter_mediate = (_fido_discover_asm_cb_data_t *) calloc(1, sizeof(_fido_discover_asm_cb_data_t));
261         cb_data_inter_mediate->cb = callback;
262         cb_data_inter_mediate->user_data = user_data;
263
264         return _asm_plugin_mgr_discover_all(_discover_response_intermediate_cb, cb_data_inter_mediate);
265 }
266
267 static void
268 _asm_response_auth_process(int error_code, const char *asm_response_json, void *user_data)
269 {
270         _INFO("_asm_response_auth_process");
271
272         if (user_data == NULL)
273                 _ERR("user_data is NULL");
274
275         _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
276         if (cb_data == NULL) {
277                 _ERR("_process_cb_data_t not found");
278                 return;
279         }
280
281         _INFO("error_code = [%d]", error_code);
282
283         if (error_code != 0) {
284                 _ERR("ASM response contains error code [%d]", error_code);
285                 _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
286                 return;
287         }
288
289         _asm_out_t *asm_out = NULL;
290
291         _INFO("before _uaf_parser_parse_asm_response_auth");
292
293         int parser_err = 0;
294         asm_out = _uaf_parser_parse_asm_response_auth(asm_response_json, &parser_err);
295         if (parser_err != 0 || asm_out == NULL) {
296                 _ERR("_uaf_parser_parse_asm_response_auth failed");
297
298                 int uaf_err_code = _convert_asm_status_code_to_uaf_error(parser_err);
299                 if (uaf_err_code == FIDO_ERROR_NONE)
300                         _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
301                 else
302                         _send_process_response(cb_data, uaf_err_code, NULL);
303
304                 _free_asm_out(asm_out);
305                 asm_out = NULL;
306
307                 return;
308         }
309
310         _asm_auth_out_t *asm_auth_out = (_asm_auth_out_t*)(asm_out->response_data);
311
312         _fido_asm_auth_in_t *asm_auth_in = (_fido_asm_auth_in_t *) cb_data->asm_in;
313
314         _message_t *uaf_message = cb_data->uaf_req;
315
316         _op_header_t *header = uaf_message->header;
317
318         char *uaf_response_json = NULL;
319
320
321         /* TODO : Add logic to accumulate multiple auth response and form the assertion_list*/
322         GList *assertion_list = NULL;
323
324         _auth_reg_assertion_t *asst_data = (_auth_reg_assertion_t*)calloc(1, sizeof(_auth_reg_assertion_t));
325
326         _INFO("before assertion");
327         asst_data->assertion = strdup(asm_auth_out->assertion);
328
329         _INFO("before assertion_schm");
330         asst_data->assertion_schm = strdup(asm_auth_out->assertion_scheme);
331
332         assertion_list = g_list_append(assertion_list, asst_data);
333
334         assertion_list = g_list_first(assertion_list);
335
336
337         _INFO("before _uaf_composer_compose_uaf_process_response_auth");
338         parser_err = _uaf_composer_compose_uaf_process_response_auth(header, asm_auth_in->final_challenge,
339                                                                                                    assertion_list, &uaf_response_json);
340
341         g_list_free_full(assertion_list, _free_auth_reg_assertion_list_item);
342
343         _free_asm_out(asm_out);
344         asm_out = NULL;
345
346         if (parser_err != 0) {
347                 _ERR("_uaf_composer_compose_uaf_process_response_auth failed");
348                 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
349                 return;
350         }
351
352         _send_process_response(cb_data, FIDO_ERROR_NONE, uaf_response_json);
353 }
354
355 static void
356 _asm_response_reg_process(int error_code, const char *asm_response_json, void *user_data)
357 {
358         _INFO("_asm_response_reg_process");
359
360         _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
361         if (cb_data == NULL)
362                 return;
363
364         if (error_code != 0) {
365                 _ERR("ASM response contains error code [%d]", error_code);
366
367                 _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
368
369                 return;
370         }
371
372         _asm_out_t *asm_out = NULL;
373         int parser_err = 0;
374         asm_out = _uaf_parser_parse_asm_response_reg(asm_response_json, &parser_err);
375         if (parser_err != 0 || asm_out == NULL) {
376                 _ERR("_uaf_parser_parse_asm_response_reg failed");
377
378                 int uaf_err_code = _convert_asm_status_code_to_uaf_error(parser_err);
379                 if (uaf_err_code == FIDO_ERROR_NONE)
380                         _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
381                 else
382                         _send_process_response((_process_cb_data_t *)user_data, uaf_err_code, NULL);
383
384                 _free_asm_out(asm_out);
385
386                 return;
387         }
388
389         _asm_reg_out_t *asm_reg_out = (_asm_reg_out_t*)(asm_out->response_data);
390
391         _fido_asm_reg_in_t *asm_reg_in = (_fido_asm_reg_in_t *)(cb_data->asm_in);
392
393         _message_t *uaf_req = cb_data->uaf_req;
394         _reg_request_t *uaf_reg_req = (_reg_request_t*)(uaf_req->data);
395         _op_header_t *header = uaf_req->header;
396
397         char *uaf_response_json = NULL;
398
399         /* TODO : Add logic to accumulate multiple auth response and form the assertion_list*/
400         _auth_reg_assertion_t *ass_data = (_auth_reg_assertion_t*) calloc(1, sizeof(_auth_reg_assertion_t));
401         ass_data->assertion = __dup_string(asm_reg_out->assertion);
402         ass_data->assertion_schm = __dup_string(asm_reg_out->assertion_schm);
403         ass_data->tc_disp_char_list = uaf_reg_req->png_list;
404
405
406         _free_asm_out(asm_out);
407         asm_out = NULL;
408
409         GList *ass_list = NULL;
410         ass_list = g_list_append(ass_list, ass_data);
411
412         parser_err = _uaf_composer_compose_uaf_process_response_reg(header, asm_reg_in->final_challenge,
413                                                                                                    ass_list, &uaf_response_json);
414
415         g_list_free_full(ass_list, _free_auth_reg_assertion_list_item);
416
417         if (parser_err != 0) {
418                 _ERR("_uaf_composer_compose_uaf_process_response_reg failed");
419                 _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
420                 return;
421         }
422
423         _send_process_response((_process_cb_data_t *)user_data, FIDO_ERROR_NONE, uaf_response_json);
424 }
425
426 static void
427 __handle_reg(_process_cb_data_t *cb_data, _matched_auth_data_t *matched_auth)
428 {
429         _message_t *uaf_req = (_message_t *)(cb_data->uaf_req);
430
431         _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
432
433         uaf_reg_req->png_list = matched_auth->tc_display_png_characteristics;
434
435         _fido_asm_reg_in_t *reg_in = (_fido_asm_reg_in_t*) calloc(1, sizeof(_fido_asm_reg_in_t));
436
437         /*If no app-id mentioned in UAF request*/
438         if (cb_data->uaf_req->header->app_id == NULL) {
439                 if (cb_data->uaf_req->facet_id == NULL) {
440                         _ERR("Failed to get app id");
441                         _send_process_response(cb_data, FIDO_ERROR_UNTRUSTED_FACET_ID, NULL);
442                         _free_fido_asm_reg_in(reg_in);
443                         return;
444                 }
445                 /* app id*/
446                 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
447                 reg_in->app_id = strdup(cb_data->uaf_req->header->app_id);
448         } else {
449                 /* app id*/
450                 reg_in->app_id = strdup(cb_data->uaf_req->header->app_id);
451         }
452
453         /* user name */
454         if (uaf_reg_req->user_name != NULL)
455                 reg_in->user_name = strdup(uaf_reg_req->user_name);
456
457         char *fc_json = _uaf_composer_compose_final_challenge(reg_in->app_id, uaf_reg_req->challenge,
458                                                                                                                   uaf_req->facet_id, cb_data->uaf_req->channel_binding);
459
460         if (fc_json == NULL) {
461                 _ERR("Failed to compose final challenge");
462                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
463                 _free_fido_asm_reg_in(reg_in);
464                 return;
465         }
466
467         /* Final challenge */
468         reg_in->final_challenge = fc_json;
469
470         int auth_idx_int = -1;
471         char *end;
472         long sl;
473
474         sl = strtol(matched_auth->auth_index, &end, 10);
475         if (end == matched_auth->auth_index) {
476                 _ERR("Failed to compose final challenge");
477                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
478                 _free_fido_asm_reg_in(reg_in);
479                 return;
480         } else if ('\0' != *end) {
481                 _ERR("Failed to compose final challenge");
482                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
483                 _free_fido_asm_reg_in(reg_in);
484                 return;
485         } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
486                 _ERR("Failed to compose final challenge");
487                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
488                 _free_fido_asm_reg_in(reg_in);
489                 return;
490         } else if (sl > INT_MAX) {
491                 _ERR("Failed to compose final challenge");
492                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
493                 _free_fido_asm_reg_in(reg_in);
494                 return;
495         } else if (sl < INT_MIN) {
496                 _ERR("Failed to compose final challenge");
497                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
498                 _free_fido_asm_reg_in(reg_in);
499                 return;
500         } else {
501                 auth_idx_int = (int)sl;
502         }
503
504         reg_in->attestation_type = matched_auth->att_type;
505
506         _version_t *version = (_version_t *)calloc(1, sizeof(_version_t));
507         version->major = _VERSION_MAJOR;
508         version->minor = _VERSION_MINOR;
509
510         char *asm_req_json = NULL;
511
512         cb_data->asm_in = reg_in;
513
514         int ret = _uaf_composer_compose_asm_reg_request(version, auth_idx_int, reg_in, &asm_req_json);
515         if (ret == 0 && asm_req_json != NULL)
516                 _asm_ipc_send(matched_auth->asm_id,
517                                           asm_req_json, _asm_response_reg_process, cb_data);
518         else
519                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
520
521         SAFE_DELETE(asm_req_json);
522         SAFE_DELETE(version);
523
524 }
525
526 static GList *
527 __copy_convert_uaf_trans_list(GList *uaf_tr_list)
528 {
529         RET_IF_FAIL(uaf_tr_list != NULL, NULL);
530
531         GList *asm_tr_list = NULL;
532
533         GList *uaf_tr_list_iter = g_list_first(uaf_tr_list);
534         while (uaf_tr_list_iter != NULL) {
535
536                 _auth_transaction_t *uaf_tr = (_auth_transaction_t*)(uaf_tr_list_iter->data);
537
538                 _fido_asm_transaction_t *asm_tr = calloc(1, sizeof(_fido_asm_transaction_t));
539
540                 asm_tr->content = __dup_string(uaf_tr->content);
541                 asm_tr->content_type = __dup_string(uaf_tr->content_type);
542                 if (uaf_tr->display_charac != NULL) {
543                         asm_tr->display_charac = calloc(1, sizeof(_fido_asm_display_png_characteristics_descriptor_t));
544
545                         asm_tr->display_charac->bit_depth = uaf_tr->display_charac->bit_depth;
546                         asm_tr->display_charac->color_type = uaf_tr->display_charac->color_type;
547                         asm_tr->display_charac->compression = uaf_tr->display_charac->compression;
548                         asm_tr->display_charac->filter = uaf_tr->display_charac->filter;
549                         asm_tr->display_charac->height = uaf_tr->display_charac->height;
550                         asm_tr->display_charac->interlace = uaf_tr->display_charac->interlace;
551                         asm_tr->display_charac->width = uaf_tr->display_charac->width;
552
553                         if (uaf_tr->display_charac->plte != NULL) {
554
555                                 GList *uaf_plte_iter = g_list_first(uaf_tr->display_charac->plte);
556                                 while (uaf_plte_iter != NULL) {
557                                         fido_rgb_pallette_entry_s *uaf_plte_entry = (fido_rgb_pallette_entry_s*)(uaf_plte_iter->data);
558
559                                         fido_rgb_pallette_entry_s *asm_plte_entry = calloc(1, sizeof(fido_rgb_pallette_entry_s));
560                                         asm_plte_entry->r = uaf_plte_entry->r;
561                                         asm_plte_entry->g = uaf_plte_entry->g;
562                                         asm_plte_entry->b = uaf_plte_entry->b;
563
564                                         asm_tr->display_charac->plte = g_list_append(asm_tr->display_charac->plte, asm_plte_entry);
565
566                                         uaf_plte_iter = uaf_plte_iter->next;
567                                 }
568                         }
569                 }
570
571                 asm_tr_list = g_list_append(asm_tr_list, asm_tr);
572
573                 uaf_tr_list_iter = uaf_tr_list_iter->next;
574         }
575
576         if (asm_tr_list != NULL) {
577                 asm_tr_list = g_list_first(asm_tr_list);
578                 _INFO("Trans list = [%d]", g_list_length(asm_tr_list));
579         }
580         return asm_tr_list;
581 }
582
583 static GList*
584 __copy_string_list(GList *src)
585 {
586         RET_IF_FAIL(src != NULL, NULL);
587
588         GList *dest = NULL;
589
590         GList *iter = g_list_first(src);
591         while (iter != NULL) {
592                 char *str = (char*)(iter->data);
593                 dest = g_list_append(dest, strdup(str));
594
595                 iter = iter->next;
596         }
597
598         return dest;
599 }
600
601 static void
602 __handle_auth(_process_cb_data_t *cb_data, _matched_auth_data_t *matched_auth)
603 {
604         _INFO("__handle_auth");
605
606         _auth_request_t *uaf_auth_req = (_auth_request_t*)(cb_data->uaf_req->data);
607
608         _fido_asm_auth_in_t *auth_asm_in = (_fido_asm_auth_in_t*)calloc(1, sizeof(_fido_asm_auth_in_t));
609
610         if (cb_data->uaf_req->header->app_id == NULL) {
611
612                 if (cb_data->uaf_req->facet_id == NULL) {
613                         _ERR("Failed to get app id");
614                         _send_process_response(cb_data, FIDO_ERROR_PERMISSION_DENIED, NULL);
615                         _free_fido_asm_auth_in(auth_asm_in);
616                         return;
617                 }
618                 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
619                 auth_asm_in->app_id = strdup(cb_data->uaf_req->facet_id);
620         } else {
621                 auth_asm_in->app_id = strdup(cb_data->uaf_req->header->app_id);
622         }
623
624         char *fc_json = _uaf_composer_compose_final_challenge(cb_data->uaf_req->header->app_id,
625                                                                                                                   uaf_auth_req->challenge, cb_data->uaf_req->facet_id,
626                                                                                                                   cb_data->uaf_req->channel_binding);
627         if (fc_json == NULL) {
628                 _ERR("Failed to compose final challenge");
629                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
630
631                 _free_fido_asm_auth_in(auth_asm_in);
632                 return;
633         }
634
635         /*keyIDs*/
636         auth_asm_in->key_ids = __copy_string_list(matched_auth->key_ids);
637
638         /* Final challenge */
639         auth_asm_in->final_challenge = fc_json;
640
641         /*Transaction*/
642         auth_asm_in->trans_list = __copy_convert_uaf_trans_list(uaf_auth_req->transaction_list);
643
644
645         cb_data->asm_in = auth_asm_in;
646
647         char *asm_req_json = NULL;
648         _version_t *version = (_version_t *)calloc(1, sizeof(_version_t));
649         version->major = _VERSION_MAJOR;
650         version->minor = _VERSION_MINOR;
651
652         int auth_idx_int = -1;
653         char *end;
654         long sl;
655
656         sl = strtol(matched_auth->auth_index, &end, 10);
657         if (end == matched_auth->auth_index) {
658                 _ERR("Failed to compose final challenge");
659                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
660                 SAFE_DELETE(version);
661                 return;
662         } else if ('\0' != *end) {
663                 _ERR("Failed to compose final challenge");
664                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
665                 SAFE_DELETE(version);
666                 return;
667         } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
668                 _ERR("Failed to compose final challenge");
669                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
670                 SAFE_DELETE(version);
671                 return;
672         } else if (sl > INT_MAX) {
673                 _ERR("Failed to compose final challenge");
674                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
675                 SAFE_DELETE(version);
676                 return;
677         } else if (sl < INT_MIN) {
678                 _ERR("Failed to compose final challenge");
679                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
680                 SAFE_DELETE(version);
681                 return;
682         } else {
683                 auth_idx_int = (int)sl;
684         }
685
686         if (auth_idx_int == -1) {
687                 _ERR("ASM in data missing");
688                 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
689                 SAFE_DELETE(version);
690                 return;
691         }
692
693         int ret = _uaf_composer_compose_asm_auth_request(version, auth_idx_int, auth_asm_in, &asm_req_json);
694         if (ret == 0 && asm_req_json != NULL) {
695                 _asm_ipc_send(matched_auth->asm_id,
696                                           asm_req_json, _asm_response_auth_process, cb_data);
697         } else {
698                 _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
699         }
700
701         SAFE_DELETE(version);
702         SAFE_DELETE(asm_req_json);
703 }
704
705 static void
706 _ui_response_callback(int error_code, _ui_auth_data_t *selected_auth_data, void *user_data)
707 {
708         if (selected_auth_data == NULL) {
709                         _ERR("User did not select any Authenticator");
710                         _send_process_response((_process_cb_data_t *)user_data, error_code, NULL);
711                         free(selected_auth_data);
712                         return;
713         }
714
715         _INFO("User selected [%s] authenticator index", selected_auth_data->auth_index);
716
717         _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
718
719
720         _matched_auth_data_t *match_data = (_matched_auth_data_t*)calloc(1, sizeof(_matched_auth_data_t));
721         match_data->att_type = selected_auth_data->att_type;
722         match_data->auth_index = selected_auth_data->auth_index;
723         match_data->asm_id = strdup(selected_auth_data->asm_id);
724
725         if (cb_data->type == _PROCESS_TYPE_REG)
726                 __handle_reg(cb_data, match_data);
727         else if (cb_data->type == _PROCESS_TYPE_AUTH)
728                 __handle_auth(cb_data, match_data);
729         else {
730                 _send_process_response(cb_data, FIDO_ERROR_UNKNOWN, NULL);
731                 _free_matched_auth_data(match_data);
732                 return;
733         }
734         _free_matched_auth_data(match_data);
735
736 }
737
738 static void
739 _asm_response_dereg_process(int error_code, const char *asm_response_json, void *user_data)
740 {
741         _dereg_q_t *dereg_q = (_dereg_q_t*)(user_data);
742         _process_cb_data_t *cb_data = (_process_cb_data_t*)(dereg_q->cb_data);
743
744         if (cb_data == NULL) {
745                 SAFE_DELETE(dereg_q);
746                 return;
747         }
748
749         /*Process next dereg*/
750         GQueue *q = (GQueue*) (dereg_q->dereg_asm_in_q);
751         if (g_queue_is_empty(q) == FALSE)
752                 __process_dereg_queue(user_data);
753         else {
754                 /*ASM does not return success/faliure for dereg*/
755                 _INFO("Ignoring ASM's response for dereg");
756                 _send_process_response((_process_cb_data_t *)cb_data, FIDO_ERROR_NONE, NULL);
757
758                 _INFO("Deleting dereg_asm_in_q");
759                 /*Elements were deleted during pop*/
760                 g_queue_free(dereg_q->dereg_asm_in_q);
761                 dereg_q->dereg_asm_in_q = NULL;
762                 _INFO("After Deleting dereg_asm_in_q");
763
764                 SAFE_DELETE(dereg_q);
765         }
766
767 }
768
769 static void
770 __process_dereg_queue(_dereg_q_t *dereg_q)
771 {
772         _INFO("__process_dereg_queue");
773
774         GQueue *q = dereg_q->dereg_asm_in_q;
775         if (q == NULL) {
776                 SAFE_DELETE(dereg_q);
777                 return;
778         }
779
780         if (g_queue_is_empty(q) == true) {
781                 _INFO("Deleting dereg_asm_in_q");
782                 g_queue_free(dereg_q->dereg_asm_in_q);
783                 dereg_q->dereg_asm_in_q = NULL;
784                 _INFO("After Deleting dereg_asm_in_q");
785                 SAFE_DELETE(dereg_q);
786                 return;
787         }
788
789         _process_cb_data_t *cb_data = (_process_cb_data_t*)(dereg_q->cb_data);
790         _message_t *uaf_message = cb_data->uaf_req;
791
792         _matched_auth_dereg_t *dereg_data = (_matched_auth_dereg_t*)(g_queue_pop_head(q));
793
794         char *asm_req_json = NULL;
795
796         int auth_index_int = _INVALID_INT;
797         char *end;
798         long sl;
799
800         sl = strtol(dereg_data->auth_index, &end, 10);
801         if (end == dereg_data->auth_index) {
802                 _ERR("Failed to compose final challenge");
803                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
804                 return;
805         } else if ('\0' != *end) {
806                 _ERR("Failed to compose final challenge");
807                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
808                 return;
809         } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
810                 _ERR("Failed to compose final challenge");
811                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
812                 return;
813         } else if (sl > INT_MAX) {
814                 _ERR("Failed to compose final challenge");
815                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
816                 return;
817         } else if (sl < INT_MIN) {
818                 _ERR("Failed to compose final challenge");
819                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
820                 return;
821         } else {
822                 auth_index_int = (int)sl;
823         }
824
825         _INFO("Auth index for dereg req = [%d]", auth_index_int);
826
827         int ret = _uaf_composer_compose_asm_dereg_request(uaf_message->header->version, auth_index_int,
828                                                                                                           dereg_data, &asm_req_json);
829
830         /*TODO : ASM does not return anything for dereg, so do not wait for response, send back
831         * success always.
832         */
833         if (ret == 0 && asm_req_json != NULL) {
834                 _asm_ipc_send(dereg_data->asm_id,
835                                           asm_req_json, _asm_response_dereg_process, dereg_q);
836         } else {
837                 _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
838                 SAFE_DELETE(dereg_q);
839         }
840
841         _free_matched_auth_dereg(dereg_data);
842         SAFE_DELETE(asm_req_json);
843
844 }
845
846 static GList*
847 __get_keyid_list_from_app_reg(GList *app_reg_list)
848 {
849         _INFO("__get_keyid_list_from_app_reg");
850
851         RET_IF_FAIL(app_reg_list != NULL, NULL);
852
853         GList *key_id_list = NULL;
854
855         GList *app_reg_list_iter = g_list_first(app_reg_list);
856         while (app_reg_list_iter != NULL) {
857
858                 _asm_app_reg_t *app_reg = (_asm_app_reg_t*)(app_reg_list_iter->data);
859                 if (app_reg != NULL) {
860
861                         if (app_reg->key_id_list != NULL) {
862                                 GList *key_id_list_iter = g_list_first(app_reg->key_id_list);
863                                 while (key_id_list_iter != NULL) {
864                                         char *key_id = (char*)(key_id_list_iter->data);
865                                         if (key_id != NULL) {
866                                                 key_id_list = g_list_append(key_id_list, strdup(key_id));
867                                                 _INFO("[%s]", key_id);
868                                         }
869
870                                         key_id_list_iter = key_id_list_iter->next;
871                                 }
872                         }
873                 }
874
875                 app_reg_list_iter = app_reg_list_iter->next;
876         }
877
878         return key_id_list;
879 }
880
881 static GList *
882 __get_auth_list_with_keyids(_policy_t *policy, GList *available_authenticators)
883 {
884         _INFO("keyID retrieval start");
885
886         GList *available_authenticators_full = NULL;
887
888         GList *avl_auth_iter = g_list_first(available_authenticators);
889         for (; avl_auth_iter != NULL; avl_auth_iter = avl_auth_iter->next) {
890
891                 fido_authenticator_s *asm_auth = (fido_authenticator_s*)(avl_auth_iter->data);
892                 if (asm_auth != NULL) {
893                         if (asm_auth->is_roaming == true) {
894                                 /*For RA, keyID = keyHandle*/
895                                 _INFO("For Roaming");
896                                 GList *accepted_list = policy->accepted_list;
897
898                                 if (accepted_list != NULL)
899                                         _INFO("accepted_list count = [%d]", g_list_length(accepted_list));
900
901                                 GList *accepted_list_iter = g_list_first(accepted_list);
902                                 for (; accepted_list_iter != NULL; accepted_list_iter = accepted_list_iter->next) {
903
904                                         GList *accepted_list_internal = (GList *) accepted_list_iter->data;
905                                         GList *accepted_list_internal_iter = g_list_first(accepted_list_internal);
906                                         for (; accepted_list_internal_iter != NULL;
907                                                  accepted_list_internal_iter = accepted_list_internal_iter->next) {
908                                                 _match_criteria_t *match_info = (_match_criteria_t *) accepted_list_internal_iter->data;
909
910                                                 if (match_info->aaid_list != NULL) {
911
912                                                         GList *aaid_iter = g_list_first(match_info->aaid_list);
913                                                         for (; aaid_iter != NULL; aaid_iter = aaid_iter->next) {
914
915                                                                 char *aaid = (char*)aaid_iter->data;
916                                                                 if ((aaid != NULL) && (strcmp(aaid, asm_auth->aaid) == 0)) {
917                                                                         _INFO("Adding keyid as keyhandle");
918
919                                                                         if (match_info->key_id_list != NULL) {
920                                                                                 GList *key_list_iter = g_list_first(match_info->key_id_list);
921                                                                                 for (; key_list_iter != NULL; key_list_iter = key_list_iter->next) {
922
923                                                                                         char *key_id = (char*)key_list_iter->data;
924                                                                                         if (key_id != NULL) {
925                                                                                                 asm_auth->key_ids = g_list_append(asm_auth->key_ids, _SAFE_DUP(key_id));
926                                                                                                 _INFO("Added keyid as keyhandle");
927                                                                                                 _INFO("%s", key_id);
928                                                                                         }
929                                                                                 }
930                                                                         }
931                                                                 }
932                                                         }
933                                                 }
934                                         }
935                                 }
936
937                                 if (asm_auth->key_ids != NULL) {
938                                         asm_auth->key_ids = g_list_first(asm_auth->key_ids);
939                                         available_authenticators_full = g_list_append(available_authenticators_full, asm_auth);
940                                         _INFO("Added keyid as keyhandle [%p][%s][%d]", asm_auth,
941                                                   asm_auth->aaid, g_list_length(asm_auth->key_ids));
942                                 }
943
944                         } else {
945
946                                 _INFO("For Bound");
947                                 char *get_reg_json = _uaf_composer_compose_get_registrations_request(asm_auth->auth_index);
948                                 char *get_reg_resp = _asm_ipc_send_sync(asm_auth->asm_id, get_reg_json);
949
950                                 if (get_reg_resp != NULL)
951                                         _INFO("_asm_ipc_send_sync = [%s]", get_reg_resp);
952
953                                 _asm_get_reg_out_t *get_reg_out = _uaf_parser_parser_asm_get_reg_response(get_reg_resp);
954                                 if (get_reg_out != NULL) {
955                                         asm_auth->key_ids = __get_keyid_list_from_app_reg(get_reg_out->app_reg_list);
956                                         asm_auth->key_ids = g_list_first(asm_auth->key_ids);
957                                         _INFO(" asm_auth->key_ids count = [%d]",  g_list_length(asm_auth->key_ids));
958                                 }
959                                 available_authenticators_full = g_list_append(available_authenticators_full, asm_auth);
960
961                                 SAFE_DELETE(get_reg_json);
962                                 SAFE_DELETE(get_reg_resp);
963                                 _free_asm_get_reg_out(get_reg_out);
964
965                         }
966                 }
967         }
968
969         _INFO("keyID retrieval end");
970         return available_authenticators_full;
971 }
972
973 static void
974 __free_matched_dereg_auth_data_list_item(gpointer data)
975 {
976         RET_IF_FAIL_VOID(data != NULL);
977
978         _free_matched_auth_dereg((_matched_auth_dereg_t*)data);
979 }
980
981 static void
982 _discover_response_cb_for_process(int tz_error_code, int error_code, GList *available_authenticators, void *user_data)
983 {
984         _INFO("_discover_response_cb_for_process [%p]", user_data);
985
986         _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
987
988         if (available_authenticators == NULL) {
989                 _ERR("No supported authenticators found");
990
991                 if (tz_error_code == FIDO_ERROR_NONE)
992                         _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
993                 else
994                         _send_process_response(cb_data, tz_error_code, NULL);
995                 return;
996         }
997
998         if (cb_data->uaf_req->header->operation == NULL) {
999                 _ERR("op field missing in uaf json message");
1000
1001                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
1002
1003                 return;
1004         }
1005
1006         _INFO("cb_data->type = [%d]", cb_data->type);
1007
1008         GList *available_authenticators_full = g_list_first(available_authenticators);
1009
1010         if (cb_data->type == _PROCESS_TYPE_CHECK_POLICY) {
1011
1012                 _INFO("_PROCESS_TYPE_CHECK_POLICY");
1013
1014                 _INFO("operation = [%s]", cb_data->uaf_req->header->operation);
1015
1016                 if ((strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0)
1017                                          || ((strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0))) {
1018
1019                         _policy_t *policy = NULL;
1020
1021                         if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0) {
1022                                 _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
1023                                 policy = uaf_reg_req->policy;
1024                                  _INFO("_PROCESS_TYPE_CHECK_POLICY for reg");
1025                         } else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0) {
1026                                 _auth_request_t *uaf_auth_req = (_auth_request_t *)(cb_data->uaf_req->data);
1027                                 policy = uaf_auth_req->policy;
1028                                 _INFO("_PROCESS_TYPE_CHECK_POLICY for auth");
1029                         }
1030
1031                         if (policy != NULL) {
1032                                 if (policy->is_keyid_present == true) {
1033                                         /*Available authenticators' keyIDs can be fetched via GetRegistrations ASM op*/
1034                                         _INFO("Need to call GetRegistrations to match policy");
1035                                         GList *avl_auth_list_full_temp = __get_auth_list_with_keyids(policy, available_authenticators);
1036                                         if (avl_auth_list_full_temp != NULL) {
1037                                                 g_list_free(available_authenticators_full);
1038
1039                                                 available_authenticators_full = g_list_first(avl_auth_list_full_temp);
1040                                         }
1041
1042                                 }
1043                                 GList *allowed_auth_list = _policy_checker_get_matched_auth_list(policy, available_authenticators_full);
1044                                 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
1045
1046                                 if ((allowed_auth_list != NULL) && g_list_length(allowed_auth_list) > 0)
1047                                         _send_process_response(cb_data, FIDO_ERROR_NONE, NULL);
1048                                 else
1049                                         _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
1050
1051                                 if (allowed_auth_list != NULL)
1052                                         g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1053                         }
1054                 } else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_DE_REG) == 0) {
1055
1056                         _dereg_request_t *dereg_req = (_dereg_request_t*)(cb_data->uaf_req->data);
1057
1058                         /* _matched_auth_dereg_t list*/
1059                         if (cb_data->uaf_req->header->app_id == NULL)
1060                                 cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
1061
1062                         GList *matched_auth_list = _policy_checker_get_matched_auth_list_dereg(cb_data->uaf_req->header->app_id, dereg_req->auth_info_list,
1063                                                                                                                                                                    available_authenticators_full);
1064                         g_list_free_full(available_authenticators_full, _free_asm_auth_list);
1065
1066                         if ((matched_auth_list != NULL) && g_list_length(matched_auth_list) > 0)
1067                                 _send_process_response(cb_data, FIDO_ERROR_NONE, NULL);
1068                         else
1069                                 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
1070
1071                         if (matched_auth_list != NULL)
1072                                 g_list_free_full(matched_auth_list, __free_matched_dereg_auth_data_list_item);
1073
1074                 }
1075
1076                 return;
1077         }
1078         if (cb_data->type == _PROCESS_TYPE_DEREG) {
1079
1080
1081                 _dereg_request_t *dereg_req = (_dereg_request_t*)(cb_data->uaf_req->data);
1082
1083                 if (cb_data->uaf_req->header->app_id == NULL)
1084                         cb_data->uaf_req->header->app_id = strdup(cb_data->uaf_req->facet_id);
1085
1086                 /* _matched_auth_dereg_t list*/
1087                 GList *matched_auth_list = _policy_checker_get_matched_auth_list_dereg(cb_data->uaf_req->header->app_id, dereg_req->auth_info_list,
1088                                                                                                                                                            available_authenticators_full);
1089
1090                 g_list_free_full(available_authenticators_full, _free_asm_auth_list);
1091
1092                 if (matched_auth_list == NULL) {
1093                         _ERR("No supported authenticators found");
1094                         _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
1095                         return;
1096                 }
1097
1098                 _dereg_q_t *dereg_q = (_dereg_q_t*) calloc(1, sizeof(_dereg_q_t));
1099
1100                 GList *matched_auth_list_iter = g_list_first(matched_auth_list);
1101                 while (matched_auth_list_iter != NULL) {
1102                         _matched_auth_dereg_t *dereg_auth_matched = (_matched_auth_dereg_t*) (matched_auth_list_iter->data);
1103
1104                         if (dereg_auth_matched != NULL) {
1105                                 GQueue *q = dereg_q->dereg_asm_in_q;
1106
1107                                 if (q == NULL)
1108                                         dereg_q->dereg_asm_in_q = g_queue_new();
1109
1110                                 g_queue_push_head(dereg_q->dereg_asm_in_q, dereg_auth_matched);
1111                         }
1112                         matched_auth_list_iter = matched_auth_list_iter->next;
1113                 }
1114
1115                 /*The elements will be deleted while freeing dereg_q->dereg_asm_in_q*/
1116                 g_list_free(matched_auth_list);
1117
1118                 dereg_q->cb_data = cb_data;
1119
1120                 __process_dereg_queue(dereg_q);
1121
1122                 return;
1123         }
1124
1125         _policy_t *policy = NULL;
1126
1127         if (cb_data->type == _PROCESS_TYPE_REG) {
1128                 _reg_request_t *uaf_reg_req = (_reg_request_t *)(cb_data->uaf_req->data);
1129                 policy = uaf_reg_req->policy;
1130         } else if (cb_data->type == _PROCESS_TYPE_AUTH) {
1131                 _auth_request_t *uaf_auth_req = (_auth_request_t *)(cb_data->uaf_req->data);
1132                 policy = uaf_auth_req->policy;
1133         } else {
1134                 _send_process_response(cb_data, FIDO_ERROR_UNKNOWN, NULL);
1135                 return;
1136         }
1137
1138         if (policy->is_keyid_present == true) {
1139                 /*Available authenticators' keyIDs can be fetched via GetRegistrations ASM op*/
1140                 _INFO("Need to call GetRegistrations to match policy");
1141                 GList *avl_auth_list_full_temp = __get_auth_list_with_keyids(policy, available_authenticators);
1142                 if (avl_auth_list_full_temp != NULL) {
1143                         g_list_free(available_authenticators_full);
1144                         available_authenticators_full = g_list_first(avl_auth_list_full_temp);
1145                 }
1146
1147         }
1148
1149         GList *allowed_auth_list = _policy_checker_get_matched_auth_list(policy, available_authenticators_full);
1150         g_list_free_full(available_authenticators_full, _free_asm_auth_list);
1151
1152         if (allowed_auth_list == NULL) {
1153                 _ERR("No supported authenticators found");
1154                 _send_process_response(cb_data, FIDO_ERROR_NO_SUITABLE_AUTHENTICATOR, NULL);
1155
1156                 return;
1157         }
1158
1159         allowed_auth_list = g_list_first(allowed_auth_list);
1160
1161         if (g_list_length(allowed_auth_list) > 1) {
1162
1163                 GList *ui_data_list = NULL;
1164
1165                 GList *allowed_auth_list_iter = allowed_auth_list;
1166                 while (allowed_auth_list_iter != NULL) {
1167                         _matched_auth_data_t *match_data = (_matched_auth_data_t *)(allowed_auth_list_iter->data);
1168
1169                         if (match_data != NULL) {
1170
1171                                 _ui_auth_data_t *ui_data = (_ui_auth_data_t*) calloc(1, sizeof(_ui_auth_data_t));
1172                                 if (match_data->asm_id != NULL)
1173                                         ui_data->asm_id = strdup(match_data->asm_id);
1174                                 else
1175                                         _ERR("No ASM id found to send to UI!!");
1176
1177                                 ui_data->auth_index = strdup(match_data->auth_index);
1178                                 ui_data->att_type = match_data->att_type;
1179
1180                                 ui_data->label = strdup(match_data->label);
1181
1182                                 ui_data_list = g_list_append(ui_data_list, ui_data);
1183
1184                                 allowed_auth_list_iter = allowed_auth_list_iter->next;
1185                         }
1186                 }
1187
1188                 int ret = _auth_ui_selector_send(ui_data_list, _ui_response_callback, cb_data);
1189                 if (ret != 0) {
1190                         _ERR("Failed to invoke selector UI");
1191                         _send_process_response(cb_data, FIDO_ERROR_NOT_SUPPORTED, NULL);
1192                         if (allowed_auth_list != NULL)
1193                                 g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1194                         return;
1195                 }
1196         } else {
1197                 GList *allowed_auth_list_iter = allowed_auth_list;
1198                 if (allowed_auth_list_iter != NULL) {
1199                         _matched_auth_data_t *match_data = (_matched_auth_data_t *)(allowed_auth_list_iter->data);
1200
1201                         if (cb_data->type == _PROCESS_TYPE_REG)
1202                                 __handle_reg(cb_data, match_data);
1203                         else if (cb_data->type == _PROCESS_TYPE_AUTH)
1204                                 __handle_auth(cb_data, match_data);
1205                         else {
1206                                 _send_process_response(cb_data, FIDO_ERROR_UNKNOWN, NULL);
1207                                 if (allowed_auth_list != NULL)
1208                                         g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1209                                 return;
1210                         }
1211                 }
1212         }
1213         if (allowed_auth_list != NULL)
1214                 g_list_free_full(allowed_auth_list, _free_matched_auth_data);
1215
1216 }
1217
1218 static int
1219 _handle_process_message(_process_cb_data_t *cb_data)
1220 {
1221         return __fido_uaf_discover_internal(_discover_response_cb_for_process, cb_data);
1222 }
1223
1224 static void
1225 __facet_id_cb(int err, const char *facet_id, void *user_data)
1226 {
1227         _INFO("__facet_id_cb");
1228         if (facet_id != NULL)
1229                 _INFO("[%s]", facet_id);
1230
1231         _process_cb_data_t *cb_data = (_process_cb_data_t*)user_data;
1232
1233         if (err != FIDO_ERROR_NONE || facet_id == NULL) {
1234                 _send_process_response(cb_data, err, NULL);
1235                 return;
1236         }
1237
1238         cb_data->uaf_req->facet_id = strdup(facet_id);
1239
1240         int error_code = FIDO_ERROR_NONE;
1241
1242         if (cb_data->type != _PROCESS_TYPE_CHECK_POLICY) {
1243
1244                 /**
1245                  * 1. Extract embedded policy to find the suitable authenticator(s)
1246                  * 2. Show UI to let user select one, if (1) gives multiple result.
1247                  * 3. Compose ASMRequest in json format
1248                  * 4. Send the same to asm
1249                  * 5. Send the ASMResponse to application.
1250                  */
1251
1252                 if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_REG) == 0)
1253                         cb_data->type = _PROCESS_TYPE_REG;
1254
1255                 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_AUTH) == 0)
1256                         cb_data->type = _PROCESS_TYPE_AUTH;
1257
1258                 else if (strcmp(cb_data->uaf_req->header->operation, _UAF_OPERATION_NAME_KEY_DE_REG) == 0)
1259                         cb_data->type = _PROCESS_TYPE_DEREG;
1260
1261                 else {
1262                          _send_process_response(cb_data, FIDO_ERROR_INVALID_PARAMETER, NULL);
1263                          return;
1264                 }
1265         }
1266
1267         error_code = _handle_process_message(cb_data);
1268
1269         if (error_code != FIDO_ERROR_NONE)
1270                 _send_process_response(cb_data, error_code, NULL);
1271 }
1272
1273 gboolean
1274 _dbus_on_fido_init(Fido *object, GDBusMethodInvocation *invocation)
1275 {
1276         _INFO("_dbus_on_fido_init");
1277         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1278
1279         fido_complete_fido_uaf_init(object, invocation, FIDO_ERROR_NONE);
1280
1281         return true;
1282 }
1283
1284 gboolean
1285 _dbus_on_fido_deinit(Fido *object, GDBusMethodInvocation *invocation)
1286 {
1287         _INFO("_dbus_on_fido_deinit");
1288         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1289
1290         if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1291                 fido_complete_fido_uaf_deinit(object, invocation, FIDO_ERROR_PERMISSION_DENIED);
1292         } else {
1293                 //_auth_ui_selector_deinit();
1294                 fido_complete_fido_uaf_deinit(object, invocation, FIDO_ERROR_NONE);
1295         }
1296
1297         return true;
1298 }
1299
1300 gboolean
1301 _dbus_on_fido_discover(Fido *object, GDBusMethodInvocation *invocation)
1302 {
1303         _INFO("_dbus_on_fido_discover");
1304
1305         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1306         if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1307
1308                 __send_discover_response(object, invocation, FIDO_ERROR_PERMISSION_DENIED,
1309                                                                                 NULL, 0);
1310                 return true;
1311         }
1312
1313         _dbus_info_t *dbus_info = (_dbus_info_t *)calloc(1, sizeof(_dbus_info_t));
1314         dbus_info->dbus_obj = object;
1315         dbus_info->invocation = invocation;
1316
1317         int ret = _asm_plugin_mgr_discover_all(_asm_get_info_cb, dbus_info);
1318         if (ret != FIDO_ERROR_NONE) {
1319
1320                 _ERR("_asm_ipc_send failed = [%d]", ret);
1321                 __send_discover_response(dbus_info->dbus_obj, dbus_info->invocation, FIDO_ERROR_NOT_SUPPORTED,
1322                                                                                 NULL, 0);
1323
1324                 SAFE_DELETE(dbus_info);
1325
1326         }
1327
1328         return true;
1329 }
1330
1331 gboolean
1332 _dbus_handle_process_or_check_policy(Fido *object, GDBusMethodInvocation *invocation,
1333                                                                         const gchar *uaf_request_json, const gchar *channel_binding,
1334                                                                          _process_type_t type)
1335 {
1336
1337         _INFO("_dbus_handle_process_or_check_policy");
1338
1339         _process_cb_data_t *cb_data = (_process_cb_data_t*) calloc(1, sizeof(_process_cb_data_t));
1340         _dbus_info_t *dbus_info = (_dbus_info_t *)calloc(1, sizeof(_dbus_info_t));
1341         dbus_info->dbus_obj = object;
1342         dbus_info->invocation = invocation;
1343         cb_data->dbus_info = dbus_info;
1344         cb_data->type = type;
1345
1346         if (is_allowed_to_call(invocation, _FIDO_CLIENT_PRIVILEGE) == false) {
1347                 _send_process_response(cb_data, FIDO_ERROR_PERMISSION_DENIED, NULL);
1348                 return true;
1349         }
1350
1351         if (uaf_request_json == NULL) {
1352                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
1353                 return true;
1354         }
1355
1356         _INFO("%s", uaf_request_json);
1357
1358         _message_t *uaf_message = _uaf_parser_parse_message(uaf_request_json, channel_binding);
1359         if (uaf_message == NULL) {
1360                 _send_process_response(cb_data, FIDO_ERROR_PROTOCOL_ERROR, NULL);
1361                 return true;
1362         }
1363
1364
1365         cb_data->uaf_req = uaf_message;
1366
1367
1368         int ret = _verify_and_get_facet_id(uaf_message->header->app_id, invocation, __facet_id_cb, cb_data);
1369         if (ret != FIDO_ERROR_NONE) {
1370                 _send_process_response(cb_data, FIDO_ERROR_UNTRUSTED_FACET_ID, NULL);
1371                 return true;
1372         }
1373
1374         return true;
1375 }
1376
1377 gboolean
1378 _dbus_on_fido_uaf_is_supported(Fido *object, GDBusMethodInvocation *invocation,
1379                                                            const gchar *uaf_request_json)
1380 {
1381         _INFO("_dbus_on_fido_uaf_is_supported");
1382
1383         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1384         return _dbus_handle_process_or_check_policy(object, invocation, uaf_request_json, NULL,
1385                                                                                                 _PROCESS_TYPE_CHECK_POLICY);
1386 }
1387
1388 gboolean
1389 _dbus_on_fido_process_operation(Fido *object, GDBusMethodInvocation *invocation,
1390                                                                         const gchar *uaf_request_json, const gchar* channel_binding_json)
1391 {
1392         _INFO("_dbus_on_fido_process_operation");
1393
1394         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1395         return _dbus_handle_process_or_check_policy(object, invocation, uaf_request_json,
1396                                                                                                 channel_binding_json, _PROCESS_TYPE_MIN);
1397 }
1398
1399 /*gboolean
1400 _dbus_on_fido_uaf_notify_result(Fido *object, GDBusMethodInvocation *invocation, const gchar *arg_cookie, gint arg_respose_code,
1401                                                                 const gchar *uaf_response_json)
1402 {
1403         __set_timeout(_FIDO_SERVICE_PROCESS_TIMEOUT);
1404         fido_complete_fido_uaf_notify_result(object, invocation, 0, 0);
1405         return true;
1406 }*/
1407
1408 static void
1409 on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
1410 {
1411                 dlog_print(DLOG_INFO, "FIDO", "on_bus_acquired");
1412
1413                 _INFO("on_bus_acquired [%s]", name);
1414
1415                 GDBusInterfaceSkeleton* interface = NULL;
1416                 fido_dbus_obj = fido_skeleton_new();
1417                 if (fido_dbus_obj == NULL) {
1418                         _ERR("fido_dbus_obj NULL!!");
1419                         return;
1420                 }
1421
1422                 dlog_print(DLOG_INFO, "FIDO", "G_DBUS_INTERFACE_SKELETON");
1423
1424                 interface = G_DBUS_INTERFACE_SKELETON(fido_dbus_obj);
1425                 if (!g_dbus_interface_skeleton_export(interface, connection, _FIDO_SERVICE_DBUS_PATH, NULL)) {
1426                         _ERR("export failed!!");
1427                         return;
1428                 }
1429
1430                 dlog_print(DLOG_INFO, "FIDO", "g_signal_connect");
1431
1432                 _INFO("connecting fido signals start");
1433
1434                 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_init",
1435                                                 G_CALLBACK(_dbus_on_fido_init), NULL);
1436
1437                 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_deinit",
1438                                                 G_CALLBACK(_dbus_on_fido_deinit), NULL);
1439
1440                 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_discover",
1441                                                 G_CALLBACK(_dbus_on_fido_discover), NULL);
1442
1443                 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_check_policy",
1444                                                 G_CALLBACK(_dbus_on_fido_uaf_is_supported), NULL);
1445
1446                 g_signal_connect(fido_dbus_obj, "handle_fido_uaf_process_operation",
1447                                                 G_CALLBACK(_dbus_on_fido_process_operation), NULL);
1448
1449 //        g_signal_connect(fido_dbus_obj, "handle_fido_uaf_notify_result",
1450 //                        G_CALLBACK(_dbus_on_fido_uaf_notify_result), NULL);
1451
1452                 g_signal_connect(fido_dbus_obj, "handle_ui_response",
1453                                                 G_CALLBACK(_auth_ui_selector_on_ui_response), NULL);
1454
1455                 if (_asm_plugin_mgr_init() != FIDO_ERROR_NONE) {
1456                         _ERR("Falied to init ASM plugin manager");
1457                         dlog_print(DLOG_INFO, "FIDO", "_asm_plugin_mgr_init failed");
1458                         exit(1);
1459                 }
1460
1461
1462 }
1463
1464 static void
1465 on_name_acquired(GDBusConnection *connection,
1466                                                 const gchar     *name,
1467                                                 gpointer         user_data)
1468 {
1469                 _INFO("on_name_acquired");
1470
1471 }
1472
1473 static void
1474 on_name_lost(GDBusConnection *connection,
1475                                                 const gchar     *name,
1476                                                 gpointer         user_data)
1477 {
1478                 _INFO("on_name_lost");
1479                 _asm_plugin_mgr_destroy();
1480                 exit(1);
1481 }
1482
1483
1484 static gboolean
1485 __timeout_cb(gpointer user_data)
1486 {
1487         _INFO("__timeout_cb Enter");
1488         g_main_loop_quit(mainloop);
1489         mainloop = NULL;
1490         return false;
1491 }
1492
1493 static void
1494 __set_timeout(int seconds)
1495 {
1496         if (seconds < _FIDO_SERVICE_MIN_TIMEOUT) {
1497                 _ERR("timeout value is wrong");
1498                 return;
1499         }
1500
1501         if (timeout_handle)
1502                 g_source_remove(timeout_handle);
1503
1504         timeout_handle = g_timeout_add_seconds(seconds, __timeout_cb, NULL);
1505         _INFO("__set_timeout handle=%d", timeout_handle);
1506 }
1507
1508 static bool
1509 __initialize_dbus(void)
1510 {
1511         _INFO("__initialize_dbus Enter");
1512
1513         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1514                                 _FIDO_DBUS_NAME,
1515                                 G_BUS_NAME_OWNER_FLAGS_NONE,
1516                                 on_bus_acquired,
1517                                 on_name_acquired,
1518                                 on_name_lost,
1519                                 NULL,
1520                                 NULL);
1521
1522         _INFO("owner_id=[%d]", owner_id);
1523
1524         if (owner_id == 0) {
1525                         _INFO("gdbus own failed!!");
1526                         return false;
1527         }
1528
1529         _INFO("g_bus_own_name SUCCESS");
1530         return true;
1531 }
1532
1533 static void
1534 __initialize(void)
1535 {
1536 #if !GLIB_CHECK_VERSION(2, 35, 0)
1537         g_type_init();
1538 #endif
1539
1540         if (__initialize_dbus() == false) {
1541                 _ERR("DBUS Initialization Failed");
1542                 exit(1);
1543         }
1544 }
1545
1546 int
1547 main(void)
1548 {
1549         dlog_print(DLOG_INFO, "FIDO", "start");
1550
1551         _INFO("Starting FIDO SVC");
1552
1553         mainloop = g_main_loop_new(NULL, FALSE);
1554
1555         __initialize();
1556         __set_timeout(_FIDO_SERVICE_BOOTUP_TIMEOUT);
1557
1558         g_main_loop_run(mainloop);
1559         g_main_loop_unref(mainloop);
1560
1561         _INFO("Ending FIDO SVC");
1562         return 0;
1563 }