tizen 2.4 release
[framework/security/cert-svc-ui.git] / view / src / certificates / detail_info_cert.c
1 /**
2  * Copyright (c) 2012 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  * @file        detail_info_cert.c
18  * @author      Janusz Kozerski (j.kozerski@samsung.com)
19  * @version     1.0
20  * @brief
21  */
22 #include <cert-svc/ccert.h>
23 #include <cert-svc/cinstance.h>
24 #include <cert-svc/cpkcs12.h>
25 #include <cert-svc/cstring.h>
26
27 #include <vconf.h>
28 #include <vconf-keys.h>
29 #include <unicode/udat.h>
30 #include <unicode/ustring.h>
31 #include <unicode/uloc.h>
32 #include <unicode/ucal.h>
33 #include <unicode/udatpg.h>
34 #include <unicode/utmscale.h>
35 #include <system_settings.h>
36
37 #include "common-utils.h"
38 #include "certificates/certificate_util.h"
39
40 static char *format_key (char *key);
41 Eina_Bool _back(void *data, Elm_Object_Item *it);
42
43 #define UG_ICU_ARR_LENGTH  256
44 #define UG_DATE_FORMAT_12  "yMMMdEhhmms"
45 #define UG_DATE_FORMAT_24  "yMMMdEHHmms"
46
47 /* for language instance */
48 CertSvcCertificate certInstance;
49
50 #define NUMBER_OF_CERT_FIELDS 12
51 static const CertSvcCertificateField field_name[NUMBER_OF_CERT_FIELDS] = {
52         CERTSVC_SUBJECT_COMMON_NAME,
53         CERTSVC_SUBJECT_ORGANIZATION_NAME,
54         CERTSVC_ISSUER_COMMON_NAME,
55         CERTSVC_ISSUER_ORGANIZATION_NAME,
56         CERTSVC_VERSION,
57         CERTSVC_SUBJECT, /* Filler for CERTSVC_VALID_TO */
58         CERTSVC_SUBJECT, /* Filler for CERTSVC_VALID_FROM */
59         CERTSVC_SERIAL_NUMBER,
60         CERTSVC_SIGNATURE_ALGORITHM,
61         CERTSVC_KEY_USAGE,
62         CERTSVC_SUBJECT, /* Filler for "is CA certificate?" */
63         CERTSVC_KEY
64 };
65
66 typedef enum __cert_info_group {
67         OWNER = 0,
68         ISSUER,
69         DATA
70 } cert_info_group_e;
71
72 static char *_get_icu_time_string(const char *locale, const char *customSkeleton, const char *timezone, UDate date)
73 {
74         /*
75                 Copy a byte string encoded in the default codepage to a ustring.
76                 Copies at most n characters. The result will be null terminated if the length of src is less than n. Performs a host byte to UChar conversion
77         */
78         UChar ucustomSkeleton[UG_ICU_ARR_LENGTH] = {0,};
79
80         if (u_uastrncpy(ucustomSkeleton, customSkeleton, UG_ICU_ARR_LENGTH) == NULL) {
81                 LOGE("u_uastrncpy() error.");
82                 return NULL;
83         }
84
85         UChar utimezone[UG_ICU_ARR_LENGTH] = {0,};
86
87         if (u_uastrncpy(utimezone, timezone, UG_ICU_ARR_LENGTH) == NULL) {
88                 LOGE("u_uastrncpy() error.");
89                 return NULL;
90         }
91
92         UErrorCode status = U_ZERO_ERROR;
93         ucal_setDefaultTimeZone(utimezone, &status);
94
95         if (U_FAILURE(status)) {
96                 LOGE("ucal_setDefaultTimeZone() is failed");
97                 return NULL;
98         }
99
100         uloc_setDefault(secure_getenv("LC_TIME"), &status);
101
102         if (U_FAILURE(status)) {
103                 LOGE("ucal_setDefaultTimeZone() is failed");
104                 return NULL;
105         }
106
107         UDateTimePatternGenerator *generator = udatpg_open(locale, &status);
108         if (generator == NULL)
109                 return NULL;
110
111         UChar bestPattern[UG_ICU_ARR_LENGTH] = {0,};
112         int32_t bestPatternLength = udatpg_getBestPattern(generator, ucustomSkeleton, u_strlen(ucustomSkeleton), bestPattern, UG_ICU_ARR_LENGTH, &status);
113         if (bestPatternLength <= 0)
114                 return NULL;
115
116         UDateFormat *formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale, NULL, -1, bestPattern, -1, &status);
117         if (formatter == 0)
118                 return NULL;
119
120         UChar formatted[UG_ICU_ARR_LENGTH] = {0,};
121         int32_t formattedLength = udat_format(formatter, date, formatted, UG_ICU_ARR_LENGTH, NULL, &status);
122         if (formattedLength <= 0)
123                 return NULL;
124
125         char formattedString[UG_ICU_ARR_LENGTH] = {0,};
126         u_austrcpy(formattedString, formatted);
127         udatpg_close(generator);
128         udat_close(formatter);
129
130         if (strlen(formattedString) == 0)
131                 return NULL;
132
133         return strdup(formattedString);
134 }
135
136 static char *_get_icu_date(time_t mtime)
137 {
138         char *skeleton = NULL;
139         bool hours_24 = false;
140         int ret = -1;
141
142         ret = system_settings_get_value_bool(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, &hours_24);
143         if (ret != SYSTEM_SETTINGS_ERROR_NONE) {
144                 LOGE("Cannot get 24 hours format");
145                 /* default 12 */
146                 hours_24 = false;
147         }
148
149         if (hours_24 == true)
150                 skeleton = UG_DATE_FORMAT_24;
151         else
152                 skeleton = UG_DATE_FORMAT_12;
153
154         /* eg. en_US.UTF-8*/
155         char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
156         if (locale == NULL) {
157                 LOGE("Cannot get region format.");
158                 /* default value : en_US */
159                 locale = strdup("en_US");
160         }
161
162         char *timezone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
163         if (timezone == NULL) {
164                 /* TODO : How to get default time zone? */
165                 LOGE("Cannot get time zone");
166                 free(locale);
167
168                 return NULL;
169         }
170
171         LOGD("Locale:%s TimeZone:%s TimeFormat:%s", locale, skeleton, timezone);
172
173         char *datestr = _get_icu_time_string(locale, skeleton, timezone, (UDate)mtime * 1000);
174
175         free(timezone);
176         free(locale);
177
178         if (datestr == NULL) {
179                 LOGE("Cannot get time string");
180                 return NULL;
181         }
182
183         return datestr;
184 }
185
186 /*
187  * This function fill Cert_Data_Field with proper text.
188  * These texts are labels to certificate details
189  */
190 static char *_getCertFieldLabel(int index)
191 {
192         const char *cert_data_field = NULL;
193         switch (index) {
194         case 0:
195                 cert_data_field = "IDS_ST_BODY_COMMON_NAME_C";
196                 break;
197         case 1:
198                 cert_data_field = "IDS_ST_BODY_ORGANISATION_C";
199                 break;
200         case 2:
201                 cert_data_field = "IDS_ST_BODY_COMMON_NAME_C";
202                 break;
203         case 3:
204                 cert_data_field = "IDS_ST_BODY_ORGANISATION_C";
205                 break;
206         case 4:
207                 cert_data_field = "IDS_ST_BODY_VERSION_C";
208                 break;
209         case 5:
210                 cert_data_field = "IDS_ST_BODY_VALID_FROM_C";
211                 break;
212         case 6:
213                 cert_data_field = "IDS_ST_BODY_VALID_TO_C";
214                 break;
215         case 7:
216                 cert_data_field = "IDS_ST_BODY_SERIAL_NUMBER_COLON";
217                 break;
218         case 8:
219                 cert_data_field = "IDS_ST_BODY_SIGNATURE_ALGORITHM_C";
220                 break;
221         case 9:
222                 cert_data_field = "IDS_ST_BODY_KEY_USAGE_C";
223                 break;
224         case 10:
225                 cert_data_field = "IDS_ST_BODY_CERTIFICATION_AUTHORITY_C";
226                 break;
227         case 11:
228                 cert_data_field = "IDS_ST_BODY_PUBLIC_KEY_C";
229                 break;
230         default:
231                 LOGE("Invalid index of cert field");
232                 return NULL;
233         }
234
235         return strdup(dgettext(PACKAGE, cert_data_field));
236 }
237
238 static void put_no_data_text_if_empty(char **text)
239 {
240         if (text == NULL) {
241                 return;
242         } else if (*text == NULL) {
243                 *text = strdup(dgettext(PACKAGE, "IDS_ST_BODY_NO_DATA"));
244         } else if (strlen(*text) == 0) {
245                 free(*text);
246                 *text = strdup(dgettext(PACKAGE, "IDS_ST_BODY_NO_DATA"));
247         }
248 }
249
250 static char *getInfoFromCert(CertSvcCertificate cert, CertSvcCertificateField field, char **buffer)
251 {
252         CertSvcString certSvcString_buffer;
253         const char *certSvc_buffer;
254         int len;
255
256         certsvc_certificate_get_string_field(cert, field, &certSvcString_buffer);
257         certsvc_string_to_cstring(certSvcString_buffer, &certSvc_buffer, &len);
258         *buffer = strndup(certSvc_buffer, len);
259         certsvc_string_free(certSvcString_buffer);
260         LOGD("Cert string field: %s", *buffer);
261
262         return *buffer;
263 }
264
265 static char *_getCertFieldData(int index)
266 {
267         LOGD("fillCertData");
268         time_t time;
269         int status = -1;
270         CertSvcString buffer;
271         char *char_buffer = NULL;
272         char *cert_Data = NULL;
273
274         switch (index) {
275         case 5:
276                 certsvc_certificate_get_not_before(certInstance, &time);
277                 cert_Data = _get_icu_date(time);
278                 LOGD("Valid from: %s", cert_Data);
279                 break;
280
281         case 6:
282                 certsvc_certificate_get_not_after(certInstance, &time);
283                 cert_Data = _get_icu_date(time);
284                 LOGD("Valid to: %s", cert_Data);
285                 break;
286
287         case 10:
288                 certsvc_certificate_is_root_ca(certInstance, &status);
289                 if (status == CERTSVC_TRUE)
290                         cert_Data = strdup(dgettext(PACKAGE, "IDS_ST_BODY_TRUE"));
291                 else if (status == CERTSVC_FALSE)
292                         cert_Data = strdup(dgettext(PACKAGE, "IDS_ST_BODY_FALSE"));
293
294                 break;
295
296         case 11:
297                 certsvc_certificate_get_string_field(certInstance, CERTSVC_KEY, &buffer);
298                 char_buffer = strndup(buffer.privateHandler, buffer.privateLength);
299                 if (char_buffer != NULL) {
300                         LOGD("char_buffer : %s", char_buffer);
301                         cert_Data = format_key(char_buffer);
302
303                         certsvc_string_free(buffer);
304                         free(char_buffer);
305                         if (cert_Data == NULL)
306                                 SECURE_LOGD("Fail to get cert_Data");
307                         else
308                                 SECURE_LOGD("Public Key: %s", cert_Data);
309                 }
310
311                 break;
312
313         default:
314                 /*
315                  * ---- SUBJECT COMMON NAME ----
316                  * ---- SUBJECT ORGANIZATION NAME ----
317                  * ---- ISSUER COMMON NAME ----
318                  * ---- ISSUER ORGANIZATION NAME ----
319                  * ---- VERSION ----
320                  * ---- SERIAL NUMBER ----
321                  * ---- SIGNATURE ALGORITHM ----
322                  * ---- KEY USAGE ----
323                  */
324                 getInfoFromCert(certInstance, field_name[index], &cert_Data);
325                 break;
326         }
327
328         put_no_data_text_if_empty(&cert_Data);
329
330         return cert_Data;
331 }
332
333 static char *format_key(char *key)
334 {
335         LOGD("format_key");
336         int i = 0;
337         int j = 0;
338         int len = strlen(key);
339         const char *public_key_label = "Public-Key: ";
340         char *result;
341         char *formated_key = malloc(sizeof(char) * len);
342
343         if (formated_key == NULL)
344                 return NULL;
345
346         /* remove whitespaces at the beginning */
347         while ((i < len - 1) && (' ' == key[i]))
348                 i++;
349
350         /* remove the "Public-key: " string at the beginning */
351         if (strncmp(public_key_label, &(key[i]), strlen(public_key_label)) == 0)
352                 i += strlen(public_key_label);
353
354         while (i < len - 1) {
355                 if (key[i] == ':' && key[i + 1] == '\n') {
356                         formated_key[j] = key[i];
357                         i += 2;
358                         j += 1;
359                 } else if (key[i] == ' ' && key[i + 1] == ' ') {
360                         i += 2;
361                 } else {
362                         formated_key[j++] = key[i++];
363                 }
364
365                 if (key[i] == 'E' || key[i] == 'M') {
366                         formated_key[j++] = '<';
367                         formated_key[j++] = 'b';
368                         formated_key[j++] = 'r';
369                         formated_key[j++] = '>';
370                 }
371         }
372
373         if (i < len && key[i] != '\n') {
374                 formated_key[j++] = key[i++];
375         }
376
377         result = strndup(formated_key, j);
378         free(formated_key);
379         return result;
380 }
381
382 static void _gl_realized(void *data, Evas_Object *obj, void *ei)
383 {
384         int id = (int)elm_object_item_data_get(ei);
385
386         if (ei == NULL)
387                 return;
388         else if ((id == 0) || (id == 2) || (id == 4))
389                 elm_object_item_signal_emit(ei, "elm,state,top", "");
390         else if ((id == 1) || (id == 3) || (id == 11))
391                 elm_object_item_signal_emit(ei, "elm,state,bottom", "");
392         else
393                 elm_object_item_signal_emit(ei, "elm,state,center", "");
394 }
395
396 static char *_gl_get_text(void *data, Evas_Object *obj, const char *part)
397 {
398         int index = (int)data;
399         char *cert_data = NULL;
400
401         if (strcmp(part, "elm.text.main") == 0)
402                 cert_data = _getCertFieldLabel(index);
403         else if (strcmp(part, "elm.text.multiline") == 0)
404                 cert_data = _getCertFieldData(index);
405
406         LOGD("%s", cert_data);
407         return cert_data;
408 }
409
410 static char *_gl_get_text_group(void *data, Evas_Object *obj, const char *part)
411 {
412         cert_info_group_e group = (cert_info_group_e)data;
413         const char *text = NULL;
414
415         if (safeStrCmp(part, "elm.text.main") != 0)
416                 return NULL;
417
418         switch (group) {
419         case OWNER:
420                 text = "IDS_SCP_BODY_OWNER_ABB";
421                 break;
422
423         case ISSUER:
424                 text = "IDS_ST_BODY_ISSUER";
425                 break;
426
427         case DATA:
428                 text = "IDS_ST_BODY_CERTIFICATE_INFORMATION";
429                 break;
430
431         default:
432                 LOGE("Wrong *index - return NULL");
433                 return NULL;
434         }
435
436         return strdup(dgettext(PACKAGE, text));
437 }
438
439 static Elm_Genlist_Item_Class itc_group = {
440         .item_style       = "groupindex",
441         .func.text_get    = _gl_get_text_group,
442         .func.content_get = NULL,
443         .func.state_get   = NULL,
444         .func.del         = NULL
445 };
446
447 static Elm_Genlist_Item_Class itc_2text = {
448         .item_style       = "multiline_sub.main",
449         .func.text_get    = _gl_get_text,
450         .func.content_get = NULL,
451         .func.state_get   = NULL,
452         .func.del         = NULL
453 };
454
455 static Elm_Genlist_Item_Class separator = {
456         .item_style       = "dialogue/separator",
457         .func.del         = NULL
458 };
459
460 void show_detail_info(void)
461 {
462         int i = 0;
463         Elm_Object_Item *it;
464         Evas_Object *genlist;
465         struct ug_data *ad = get_ug_data();
466
467         if (!ad)
468                 return;
469
470         if (!ad->more_popup2)
471                 ad->more_popup2 = (Evas_Object *)(-1);
472
473         genlist = common_genlist(ad->win_main);
474         evas_object_smart_callback_add(genlist, "realized", _gl_realized, NULL);
475         evas_object_smart_callback_add(genlist, "selected", genlist_clicked_cb, NULL);
476
477         for (i = 0; i < NUMBER_OF_CERT_FIELDS; i++) {
478                 if (field_name[i] == CERTSVC_SUBJECT_COMMON_NAME) {
479                         it = elm_genlist_item_append(genlist, &separator, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
480                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
481
482                         it = elm_genlist_item_append(genlist, &itc_group, (void *)OWNER, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
483                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
484                 } else if (field_name[i] == CERTSVC_ISSUER_COMMON_NAME) {
485                         it = elm_genlist_item_append(genlist, &itc_group, (void *)ISSUER, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
486                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
487                 } else if (field_name[i] == CERTSVC_VERSION) {
488                         it = elm_genlist_item_append(genlist, &itc_group, (void *)DATA, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
489                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
490                 }
491
492                 LOGD("Try to append %d genlist item...", i);
493
494                 it = elm_genlist_item_append(genlist, &itc_2text, (void *)i, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
495                 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
496
497                 if (field_name[i] == CERTSVC_SUBJECT_ORGANIZATION_NAME
498                                 || field_name[i] == CERTSVC_ISSUER_ORGANIZATION_NAME
499                                 || field_name[i] == CERTSVC_KEY) {
500                         it = elm_genlist_item_append(genlist, &separator, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
501                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
502                 }
503
504                 elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
505                 LOGD("Succesful append %d genlist", i);
506         }
507
508         LOGD("Push genlist");
509         Elm_Object_Item *nf_it = elm_naviframe_item_push(ad->navi_bar, "IDS_ST_BODY_CERTIFICATE_DETAILS", common_back_btn(ad), NULL, genlist, NULL);
510         elm_object_item_domain_text_translatable_set(nf_it, PACKAGE, EINA_TRUE);
511         elm_naviframe_item_pop_cb_set(nf_it, _back, (struct Evas_Object *)ad);
512 }
513
514 #ifdef TIZEN_FEAT_STORE_CAPABILITY
515 void get_info_cert_from_file_cb(struct ug_data *ad, void *list)
516 {
517         LOGD("get_info_cert_from_file_cb()");
518         struct ListElement *current = (struct ListElement *)list;
519         if (certsvc_pkcs12_get_certificate_from_store(
520                         ad->instance,
521                         current->storeType,
522                         current->gname,
523                         &certInstance) != CERTSVC_SUCCESS) {
524                 LOGE("Unable to load certificate information into the certInstance.");
525                 return;
526         }
527         show_detail_info();
528
529         free(ad->data);
530         ad->data = NULL;
531 }
532 #else
533 void get_info_cert_from_file_cb(struct ug_data *ad)
534 {
535         LOGD("get_info_cert_from_file_cb()");
536         char *cert_path = NULL;
537
538         if (ad == NULL || ad->data == NULL) {
539                 LOGD("ad->data is NULL; return");
540                 return;
541         }
542
543         cert_path = (char *)ad->data;
544         SECURE_LOGD("cert_path = %s", cert_path);
545
546         LOGD("Get certificate data...");
547         if (CERTSVC_SUCCESS != certsvc_certificate_new_from_file(ad->instance, cert_path, &certInstance)) {
548                 SECURE_LOGD("Error in certsvc_certificate_new_from_file( %s )", cert_path);
549                 LOGD("EXIT");
550                 return;
551         }
552
553         show_detail_info();
554
555         free(ad->data);
556         ad->data = NULL;
557 }
558 #endif
559
560 void get_info_cert_from_certificate_cb(CertSvcCertificate cert)
561 {
562         LOGD("get_info_cert_from_certificate_cb()");
563
564         certInstance = cert;
565
566         show_detail_info();
567 }
568
569 Eina_Bool _back(void *data, Elm_Object_Item *it)
570 {
571         struct ug_data *ad = (struct ug_data *) data;
572         ad->more_popup2 = NULL;
573         certsvc_certificate_free(certInstance);
574         memset(&certInstance, 0, sizeof(certInstance));
575         return EINA_TRUE;
576 }