b077abe0a40dfaf6d1f8524d325e61b750345362
[platform/core/account/fido-client.git] / server / fido_uaf_policy_checker.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 <string.h>
19 #include <stdio.h>
20
21 #include "fido_keys.h"
22 #include "fido_logs.h"
23 #include "fido_uaf_policy_checker.h"
24 #include "fido_json_handler.h"
25
26 //static _fido_asm_proxy_t*
27 //__dup_asm_proxy(const _fido_asm_proxy_t *src)
28 //{
29 //    _fido_asm_proxy_t *dest = calloc(1, sizeof(_fido_asm_proxy_t));
30 //    dest->bin_path = strdup(src->bin_path);
31 //    dest->dbus_info = strdup(src->dbus_info);
32 //    dest->dbus_interface_name = strdup(src->dbus_interface_name);
33 //    dest->dbus_method_name = strdup(src->dbus_method_name);
34 //    dest->dbus_obj_path = strdup(src->dbus_obj_path);
35 //    dest->vendor = strdup(src->vendor);
36
37 //    dest->dbus_proxy = src->dbus_proxy;
38
39 //    return dest;
40 //}
41
42 static gint
43 _int_cmp(gconstpointer a, gconstpointer b)
44 {
45     int int1 = GPOINTER_TO_INT(a);
46     int int2 = GPOINTER_TO_INT(b);
47     return (int1 - int2);
48 }
49
50 bool
51 _policy_checker_is_matched(_match_criteria_t *match_criteria, fido_authenticator_s *auth_info)
52 {
53     _INFO("_policy_checker_is_matched");
54
55     /* -1 means the int value is not present, so we should ignore that. */
56
57     /* 1. If any AAID is mentioned in match_criteria, then atleast one AAID should match */
58     GList *aaid_list = match_criteria->aaid_list;
59
60     if (aaid_list &&
61             (g_list_length(aaid_list)) &&
62             (auth_info->aaid) &&
63             (strlen(auth_info->aaid) > 0)) {
64         aaid_list = g_list_first(aaid_list);
65         if (g_list_find_custom(aaid_list, auth_info->aaid, (GCompareFunc)strcmp) == NULL) {
66             _ERR("AAID match failed");
67             return false;
68         }
69     }
70
71
72     /* 2. If any Vendor ID is mentioned in match_criteria, then atleast one Vendor ID should match */
73     GList *vendor_list = match_criteria->vendor_list;
74
75     if (vendor_list && auth_info->aaid) {
76         char *auth_aaid = strdup(auth_info->aaid);
77         char *auth_vendor = strtok(auth_aaid, "#");
78
79         if (vendor_list &&
80                 (g_list_length(vendor_list)) &&
81                 auth_vendor &&
82                 (strlen(auth_vendor) > 0)) {
83             vendor_list = g_list_first(vendor_list);
84             if (g_list_find_custom(vendor_list, auth_vendor, (GCompareFunc)strcmp) == NULL) {
85                 _ERR("Vendor ID match failed");
86
87                 SAFE_DELETE(auth_aaid);
88                 return false;
89             }
90         }
91         SAFE_DELETE(auth_aaid);
92     }
93
94     _INFO("keyid matching");
95
96     /* 3. If any Key ID is mentioned in match_criteria, then atleast one Key ID should match */
97     GList *key_id_list = match_criteria->key_id_list;
98
99     if (key_id_list != NULL) {
100
101         if (auth_info->key_ids == NULL) {
102             _ERR("keyID match failed");
103             return false;
104         }
105
106         GList *auth_key_ids = auth_info->key_ids;
107
108         GList *common_key_id_list = NULL;
109
110         key_id_list = g_list_first(key_id_list);
111         auth_key_ids = g_list_first(auth_key_ids);
112
113         _INFO("match_criteria keyid count = [%d]", g_list_length(key_id_list));
114         _INFO("auth info keyid count = [%d]", g_list_length(auth_key_ids));
115
116         GList *key_id_iter = g_list_first(key_id_list);
117         while (key_id_iter != NULL) {
118             char *key_id = (char*) (key_id_iter->data);
119             if (key_id) {
120                 if (g_list_find_custom(auth_key_ids, key_id, (GCompareFunc)strcmp) != NULL) {
121                     _INFO("keyid matched [%s]", key_id);
122                     common_key_id_list = g_list_append(common_key_id_list, strdup(key_id));
123                 }
124             }
125             key_id_iter = key_id_iter->next;
126         }
127
128         if (common_key_id_list == NULL) {
129             _ERR("keyID match failed");
130             return false;
131         }
132
133         common_key_id_list = g_list_first(common_key_id_list);
134
135         /*Set common keyIds in match*/
136         g_list_free_full(match_criteria->key_id_list, free);
137         match_criteria->key_id_list = common_key_id_list;
138
139         _INFO("keyID matched count [%d]", g_list_length(match_criteria->key_id_list));
140
141     }
142
143     _INFO("User verification matching");
144
145     /* 4. User verification match */
146     if (match_criteria->user_verification != -1) {
147         if ((match_criteria->user_verification == auth_info->user_verification)
148                 ||
149                 (
150                         ((auth_info->user_verification & _USER_VER_METHOD_ALL) == 0)
151                         &&
152                         ((match_criteria->user_verification & _USER_VER_METHOD_ALL) == 0)
153                         &&
154                         ((auth_info->user_verification & match_criteria->user_verification) != 0)
155                 )
156         )
157             _INFO("User verification match passed");
158         else {
159             _ERR("User verification match failed");
160             return false;
161         }
162     }
163
164     /* 5. Key protection field bit matching */
165     if ((match_criteria->key_protection != -1) && auth_info->key_protection) {
166         if (((match_criteria->key_protection) && (auth_info->key_protection)) == 0) {
167             _ERR("Key protection match failed");
168             return false;
169         }
170     }
171
172     /* 6. Matcher Protection field bit matching */
173     if ((match_criteria->matcher_protection != -1) && auth_info->matcher_protection) {
174         if (((match_criteria->matcher_protection) && (auth_info->matcher_protection)) == 0) {
175             _ERR("Matcher protection match failed");
176             return false;
177         }
178     }
179
180     /* 7. Attachment hint field bit matching */
181     if ((match_criteria->attachement_hint != -1) && auth_info->attachment_hint) {
182         if (((match_criteria->attachement_hint) && (auth_info->attachment_hint)) == 0) {
183             _ERR("Attachment hint match failed");
184             return false;
185         }
186     }
187
188     /* 8. TC Display field bit matching */
189     if ((match_criteria->tc_display != -1) && auth_info->tc_display) {
190         if (((match_criteria->tc_display) && (auth_info->tc_display)) == 0) {
191             _ERR("Attachment hint match failed");
192             return false;
193         }
194     }
195
196     /* 9. If any algo is mentioned in match_criteria, then atleast one algo should match */
197     GList *match_algo_list = match_criteria->auth_algo_list;
198     if (match_algo_list && (g_list_length(match_algo_list))
199             && (auth_info->authentication_algorithm)) {
200         match_algo_list = g_list_first(match_algo_list);
201         if (g_list_find_custom(match_algo_list, GINT_TO_POINTER(auth_info->authentication_algorithm), (GCompareFunc)_int_cmp) == NULL) {
202             _ERR("Algorithm match failed");
203             return false;
204         }
205     }
206
207     /* 10. If any assertion scheme is mentioned in match_criteria, then atleast one assertion scheme should match */
208     GList *assertion_list = match_criteria->assertion_scheme_list;
209     if (assertion_list && (g_list_length(assertion_list))
210             && (auth_info->assertion_scheme) && (strlen(auth_info->assertion_scheme) > 0)) {
211         assertion_list = g_list_first(assertion_list);
212         if (g_list_find_custom(assertion_list, auth_info->assertion_scheme, (GCompareFunc)strcmp) == NULL)
213         {
214             _ERR("Assertion scheme match failed");
215             return false;
216         }
217     }
218
219     /* 11. If any attestation type is mentioned in match_criteria, then atleast one attestation type should match */
220     GList *attestation_type_list = match_criteria->attestation_type_list;
221     if (attestation_type_list && (g_list_length(attestation_type_list))
222             && (auth_info->attestation_types)) {
223         attestation_type_list = g_list_first(attestation_type_list);
224         if (g_list_find_custom(attestation_type_list, GINT_TO_POINTER(auth_info->attestation_types), (GCompareFunc)_int_cmp) == NULL) {
225             _ERR("Attestation type match failed");
226             return false;
227         }
228     }
229
230     /* TODO : 12. Auth version */
231
232     /* TODO : 13. Extension */
233
234     _INFO("_policy_checker_is_matched true");
235
236     return true;
237 }
238
239 int
240 _get_attestation_type(_match_criteria_t *match_criteria, fido_authenticator_s *auth_info)
241 {
242      _INFO("_get_attestation_type");
243
244     if (match_criteria && match_criteria->attestation_type_list) {
245
246         GList *match_att_list_iter = g_list_first(match_criteria->attestation_type_list);
247         while (match_att_list_iter != NULL) {
248
249             int match_att_type = GPOINTER_TO_INT(match_att_list_iter->data);
250
251             if (auth_info && auth_info->attestation_types) {
252
253                 GList *auth_att_list_iter = g_list_first(auth_info->attestation_types);
254                 while (auth_att_list_iter != NULL) {
255
256                     int auth_att_type = GPOINTER_TO_INT(auth_att_list_iter->data);
257
258                     if (match_att_type == auth_att_type) {
259                         _INFO("_get_attestation_type end [%d]", match_att_type);
260                         return match_att_type;
261                     }
262                 }
263             }
264             match_att_list_iter = match_att_list_iter->data;
265         }
266     }
267     else {
268         if (auth_info->attestation_types != NULL) {
269             GList *att_type_iter = g_list_first(auth_info->attestation_types);
270
271             /*Returning first attestation type in case policy does not mandate any*/
272             while (att_type_iter != NULL) {
273                 int auth_att_type = GPOINTER_TO_INT(att_type_iter->data);
274                 _INFO("Returning first attestation type in case policy does not mandate any [%d]", auth_att_type);
275                 return auth_att_type;
276             }
277         }
278     }
279
280     _ERR("_get_attestation_type end");
281     return -1;
282 }
283
284 static char *
285 __get_verification_method_string(unsigned long int ver_method)
286 {
287     char *ver_str = calloc(1, 128);
288
289     switch (ver_method) {
290
291     case _USER_VER_METHOD_PRESENCE:
292         snprintf(ver_str, 127, "%s", "Presence Authenticator");
293         break;
294
295     case _USER_VER_METHOD_FINGERPRINT:
296         snprintf(ver_str, 127, "%s", "Fingerprint Authenticator");
297         break;
298
299     case _USER_VER_METHOD_PASSCODE:
300         snprintf(ver_str, 127, "%s", "Passcode Authenticator");
301         break;
302
303     case _USER_VER_METHOD_VOICE_PRINT:
304         snprintf(ver_str, 127, "%s", "Voice Print Authenticator");
305         break;
306
307     case _USER_VER_METHOD_FACE_PRINT:
308         snprintf(ver_str, 127, "%s", "Face Print Authenticator");
309         break;
310
311     case _USER_VER_METHOD_LOCATION:
312         snprintf(ver_str, 127, "%s", "Location Authenticator");
313         break;
314
315     case _USER_VER_METHOD_EYE_PRINT:
316         snprintf(ver_str, 127, "%s", "Eye Print Authenticator");
317         break;
318
319     case _USER_VER_METHOD_PATTERN:
320         snprintf(ver_str, 127, "%s", "Pattern Authenticator");
321         break;
322
323     case _USER_VER_METHOD_HAND_PRINT:
324         snprintf(ver_str, 127, "%s", "Hand Print Authenticator");
325         break;
326
327 //    case _USER_VER_METHOD_NONE:
328 //        snprintf(ver_str, "%s", "");
329 //        break;
330
331     case _USER_VER_METHOD_ALL:
332         snprintf(ver_str, 127, "%s", "All Authenticator");
333         break;
334
335     default:
336         snprintf(ver_str, 127, "%s", "Other Type");
337         break;
338     }
339
340     return ver_str;
341 }
342
343 static GList*
344 __copy_string_list(GList *src)
345 {
346     RET_IF_FAIL(src != NULL, NULL);
347
348     GList *dest = NULL;
349
350     GList *iter = g_list_first(src);
351     while (iter != NULL) {
352         char *str = (char*)(iter->data);
353         dest = g_list_append(dest, strdup(str));
354
355         iter = iter->next;
356     }
357
358     return dest;
359 }
360
361 /* Returns _matched_auth_data_t list*/
362 GList *
363 _policy_checker_get_matched_auth_list(_policy_t *policy, GList *auth_list)
364 {
365     _INFO("_policy_checker_get_matched_auth_list");
366
367     if (policy == NULL)
368         _INFO("policy is NULL");
369
370     if (auth_list == NULL)
371         _INFO("auth_list is NULL");
372
373     RET_IF_FAIL(policy != NULL, NULL);
374     RET_IF_FAIL(auth_list != NULL, NULL);
375
376     //    _match_criteria_t *match_criteria_or = NULL;
377     GList *allowed_list = NULL;
378     GList *disallowed_list = policy->disallowed_list;
379     GList *accepted_list = policy->accepted_list;
380
381     if (accepted_list != NULL)
382         _INFO("accepted_list count = [%d]", g_list_length(accepted_list));
383
384     if (disallowed_list != NULL)
385         _INFO("allowed_list count = [%d]", g_list_length(disallowed_list));
386
387     GList *accepted_list_iter = g_list_first(accepted_list);
388     while (accepted_list_iter != NULL) {
389
390         GList *accepted_list_internal = (GList *) accepted_list_iter->data;
391         GList *accepted_list_internal_iter = g_list_first(accepted_list_internal);
392         while (accepted_list_internal_iter != NULL) {
393             _match_criteria_t *match_info = (_match_criteria_t *) accepted_list_internal_iter->data;
394
395             GList *auth_list_iter = g_list_first(auth_list);
396             while (auth_list_iter != NULL) {
397                 fido_authenticator_s *authenticator = (fido_authenticator_s*) (auth_list_iter->data);
398
399                 if (_policy_checker_is_matched(match_info, authenticator)) {
400                     _INFO("[%s] is matched from allowed list", authenticator->aaid);
401
402                     /*Disallowed list can be NULL, which means put all which are matching with accepted list*/
403
404                     if (disallowed_list != NULL) {
405
406                         GList *disallowed_list_iter = g_list_first(disallowed_list);
407                         while (disallowed_list_iter != NULL) {
408                             _match_criteria_t *disallowed_match_info = (_match_criteria_t *) disallowed_list_iter->data;
409
410                             if (!_policy_checker_is_matched(disallowed_match_info, authenticator)) {
411                                 _INFO("[%s] is not in disallowed list", authenticator->aaid);
412                                 _matched_auth_data_t *matched_auth_data = (_matched_auth_data_t*) calloc(1, sizeof(_matched_auth_data_t));
413                                 RET_IF_FAIL(matched_auth_data, NULL);
414
415                                 /*TODO : ASM must send auth index*/
416                                 if (authenticator->auth_index != NULL)
417                                     matched_auth_data->auth_index = strdup(authenticator->auth_index);
418                                 else
419                                     _ERR("auth index missing");
420
421                                 matched_auth_data->att_type = _get_attestation_type(match_info, authenticator);
422
423                                 if (authenticator->title != NULL)
424                                     matched_auth_data->label = strdup(authenticator->title);
425                                 else {
426                                     _ERR("title missing, putting ver method");
427                                     /*If label is null, set verification method name instead*/
428                                     matched_auth_data->label = __get_verification_method_string(authenticator->user_verification);
429                                 }
430
431
432                                 if (authenticator->asm_id != NULL)
433                                     matched_auth_data->asm_id = strdup(authenticator->asm_id);
434                                 else
435                                     _ERR("Authenticator does not have any ASM ID!!");
436
437                                 matched_auth_data->key_ids = __copy_string_list(match_info->key_id_list);
438
439                                 allowed_list = g_list_append(allowed_list, matched_auth_data);
440                             }
441                             disallowed_list_iter = disallowed_list_iter->next;
442                         }
443                     }
444                     else {
445                         _INFO("[%s] adding since no disallowed list", authenticator->aaid);
446                         _matched_auth_data_t *matched_auth_data = (_matched_auth_data_t*) calloc(1, sizeof(_matched_auth_data_t));
447                         RET_IF_FAIL(matched_auth_data, NULL);
448
449                         matched_auth_data->auth_index = strdup(authenticator->auth_index);
450                         matched_auth_data->att_type = _get_attestation_type(match_info, authenticator);
451                         if (authenticator->title != NULL)
452                             matched_auth_data->label = strdup(authenticator->title);
453                         else {
454                             _ERR("title missing, putting ver method");
455                             /*If label is null, set verification method name instead*/
456                             matched_auth_data->label = __get_verification_method_string(authenticator->user_verification);
457                         }
458
459                         if (authenticator->asm_id != NULL)
460                             matched_auth_data->asm_id = strdup(authenticator->asm_id);
461                         else
462                             _ERR("Authenticator does not have any ASM ID!!");
463
464                         matched_auth_data->key_ids = __copy_string_list(match_info->key_id_list);
465
466                         allowed_list = g_list_append(allowed_list, matched_auth_data);
467                     }
468                 }
469                 auth_list_iter = auth_list_iter->next;
470             }
471             accepted_list_internal_iter = accepted_list_internal_iter->next;
472         }
473         accepted_list_iter = accepted_list_iter->next;
474     }
475
476     if (allowed_list != NULL)
477         allowed_list = g_list_first(allowed_list);
478
479     return allowed_list;
480 }
481
482 /* Returns _matched_auth_dereg_t list */
483 GList*
484 _policy_checker_get_matched_auth_list_dereg(const char *app_id, GList *input_auth_list, GList *available_auth_list)
485 {
486         _INFO("");
487
488         RET_IF_FAIL(app_id, NULL);
489     RET_IF_FAIL(input_auth_list, NULL);
490     RET_IF_FAIL(available_auth_list, NULL);
491
492         _INFO("");
493
494     GList *matched_auth_dereg_list = NULL;
495
496     GList *input_auth_list_iter = g_list_first(input_auth_list);
497     while (input_auth_list_iter != NULL) {
498         _dereg_auth_info_t *dereg_auth_info = (_dereg_auth_info_t*) (input_auth_list_iter->data);
499
500         GList *available_auth_list_iter = g_list_first(available_auth_list);
501         while (available_auth_list_iter != NULL) {
502             fido_authenticator_s *authenticator = (fido_authenticator_s*) (available_auth_list_iter->data);
503
504                         if (dereg_auth_info->aaid != NULL)
505                                 _INFO("Input AAID = [%s]", dereg_auth_info->aaid);
506
507                         if (authenticator->aaid != NULL)
508                                 _INFO("Authenticator AAID = [%s]", authenticator->aaid);
509                         
510             if (dereg_auth_info->aaid && authenticator->aaid && !strcmp(dereg_auth_info->aaid, authenticator->aaid)) {
511                 _matched_auth_dereg_t *matched_auth_dereg = (_matched_auth_dereg_t*) calloc(1, sizeof(_matched_auth_dereg_t));
512                 RET_IF_FAIL(matched_auth_dereg, NULL);
513
514                 matched_auth_dereg->auth_index = strdup(authenticator->auth_index);
515                 matched_auth_dereg->app_id = strdup(app_id);
516                 matched_auth_dereg->key_id = strdup(dereg_auth_info->key_id);
517                 if (authenticator->asm_id != NULL)
518                     matched_auth_dereg->asm_id = strdup(authenticator->asm_id);
519                 else
520                     _ERR("Authenticator does not have any ASM ID!!");
521
522                                 _INFO("");
523                 matched_auth_dereg_list = g_list_append(matched_auth_dereg_list, matched_auth_dereg);
524             }
525             available_auth_list_iter = available_auth_list_iter->next;
526         }
527         input_auth_list_iter = input_auth_list_iter->next;
528     }
529
530     return matched_auth_dereg_list;
531 }