Fix security issue.
[platform/framework/web/download-provider.git] / agent / download-agent-encoding.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 #include <string.h>
18 #include <stdlib.h>
19 #include "glib.h"
20 #include <curl/curl.h>
21
22 #include "download-agent-debug.h"
23 #include "download-agent-encoding.h"
24
25 da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str,
26         char **out_charset_type,
27         char *out_encoding_type,
28         char **out_raw_encoded_str);
29
30 da_bool_t is_base64_encoded_word(const char *in_str)
31 {
32         const char *haystack = DA_NULL;
33         char first_needle[8] = {0,};
34         char second_needle[8] = {0,};
35         char *found_str = DA_NULL;
36
37         if (!in_str) {
38                 DA_LOGE("input string is NULL");
39                 return DA_FALSE;
40         }
41
42         haystack = in_str;
43         if (haystack[0] == '"') {
44                 snprintf(first_needle, sizeof(first_needle), "%s", "\"=?");     // "=?
45                 snprintf(second_needle, sizeof(second_needle), "%s", "?=\"");   // ?="
46         } else {
47                 snprintf(first_needle, sizeof(first_needle), "%s", "=?");       // =?
48                 snprintf(second_needle, sizeof(second_needle), "%s", "?=");     // ?=
49         }
50
51         found_str = strstr(haystack, first_needle);
52         if (found_str) {
53                 if (found_str == haystack) {
54                         haystack = haystack + strlen(haystack) - strlen(second_needle);
55                         if(!strcmp(haystack, second_needle))
56                                 return DA_TRUE;
57                 }
58         }
59         return DA_FALSE;
60 }
61
62 da_ret_t decode_base64_encoded_str(const char *in_encoded_str,
63         char **out_decoded_ascii_str)
64 {
65         da_ret_t ret = DA_RESULT_OK;
66         const char *org_str = DA_NULL;
67         char *charset_type = NULL;
68         char encoding_type = '\0';
69         char *raw_encoded_str = NULL;
70         char *decoded_str = NULL;
71         const gchar *g_encoded_text = NULL;
72         guchar *g_decoded_text = NULL;
73         gsize g_decoded_text_len = 0;
74
75         DA_SECURE_LOGD("input str = [%s]", in_encoded_str);
76
77         org_str = in_encoded_str;
78         if(!org_str) {
79                 DA_LOGE("Input string is NULL");
80                 ret = DA_ERR_INVALID_ARGUMENT;
81                 goto ERR;
82         }
83
84         ret = _parsing_base64_encoded_str(org_str, &charset_type,
85                 &encoding_type, &raw_encoded_str);
86         if(ret != DA_RESULT_OK) {
87                 goto ERR;
88         }
89
90         if(encoding_type != 'B') {
91                 DA_LOGE("Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type);
92                 ret = DA_ERR_INVALID_ARGUMENT;
93                 goto ERR;
94         }
95
96         /*
97          * on glib/gtype.h
98          * typedef char   gchar;
99          * typedef unsigned char   guchar;
100          *
101          */
102         g_encoded_text = (const gchar*)raw_encoded_str;
103         g_decoded_text = g_base64_decode(g_encoded_text, &g_decoded_text_len);
104
105         if(g_decoded_text) {
106                 DA_SECURE_LOGD("g_decoded_text = [%s]", g_decoded_text);
107                 decoded_str = (char*)calloc(1, g_decoded_text_len+1);
108                 if(!decoded_str) {
109                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
110                         ret = DA_ERR_FAIL_TO_MEMALLOC;
111                         goto ERR;
112                 } else {
113                         memcpy(decoded_str, g_decoded_text, g_decoded_text_len);
114                 }
115         }
116         DA_SECURE_LOGD("decoded_str = [%s]", decoded_str);
117
118 ERR:
119         *out_decoded_ascii_str = decoded_str;
120         if(charset_type) {
121                 free(charset_type);
122                 charset_type = NULL;
123         }
124         if(raw_encoded_str) {
125                 free(raw_encoded_str);
126                 raw_encoded_str = NULL;
127         }
128         if(g_decoded_text) {
129                 g_free(g_decoded_text);
130         }
131         return ret;
132 }
133
134 da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str,
135         char **out_charset_type,
136         char *out_encoding_type,
137         char **out_raw_encoded_str)
138 {
139         da_ret_t ret = DA_RESULT_OK;
140         const char *org_str = DA_NULL;  // e.g. =?UTF-8?B?7Jew7JWE7JmA7IKs7J6QLmpwZw==?=
141         char *charset_type = NULL;              // e.g. UTF-8
142         char encoding_type = '\0';              // e.g. B (means Base64)
143         char *raw_encoded_str = NULL;   // e.g. 7Jew7JWE7JmA7IKs7J6QLmpwZw==
144         char *haystack = DA_NULL;
145         char needle[8] = {0,};
146         char *wanted_str = DA_NULL;
147         int wanted_str_len = 0;
148         char *wanted_str_start = DA_NULL;
149         char *wanted_str_end = DA_NULL;
150
151         org_str = in_encoded_str;
152         if (!org_str) {
153                 DA_LOGE("Input string is NULL");
154                 ret = DA_ERR_INVALID_ARGUMENT;
155                 goto ERR;
156         }
157
158         // strip "=?"
159         haystack = (char*)org_str;
160         snprintf(needle, sizeof(needle), "=?");
161         wanted_str_end = strstr(haystack, needle);
162         if (!wanted_str_end) {
163                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
164                 ret = DA_ERR_INVALID_ARGUMENT;
165                 goto ERR;
166         } else {
167                 wanted_str = wanted_str_end + strlen(needle);
168         }
169
170         // for charset
171         haystack = wanted_str_start = wanted_str;
172         needle[0] = '?';
173         wanted_str_end = strchr(haystack, needle[0]);
174         if (!wanted_str_end) {
175                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
176                 ret = DA_ERR_INVALID_ARGUMENT;
177                 goto ERR;
178         } else {
179                 wanted_str_len = wanted_str_end - wanted_str_start + 1;
180                 wanted_str = (char*)calloc(1, wanted_str_len+1);
181                 if (!wanted_str) {
182                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
183                         ret = DA_ERR_FAIL_TO_MEMALLOC;
184                         goto ERR;
185                 } else {
186                         snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
187                         charset_type = wanted_str;
188                         wanted_str = DA_NULL;
189                 }
190
191                 DA_LOGV("charset [%s]", charset_type);
192         }
193
194         // for encoding
195         encoding_type = *(++wanted_str_end);
196         DA_LOGV("encoding [%c]", encoding_type);
197
198         // for raw encoded str
199         haystack = wanted_str_start = wanted_str_end + 1;
200         snprintf(needle, sizeof(needle), "?=");
201         wanted_str_end = strstr(haystack, needle);
202         if (!wanted_str_end) {
203                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
204                 ret = DA_ERR_INVALID_ARGUMENT;
205                 goto ERR;
206         } else {
207                 wanted_str_len = wanted_str_end - wanted_str_start + 1;
208                 wanted_str = (char*)calloc(1, wanted_str_len+1);
209                 if (!wanted_str) {
210                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
211                         ret = DA_ERR_FAIL_TO_MEMALLOC;
212                         goto ERR;
213                 } else {
214                         snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
215                         raw_encoded_str = wanted_str;
216                         wanted_str = NULL;
217                 }
218
219                 DA_SECURE_LOGD("raw encoded str [%s]", raw_encoded_str);
220         }
221 ERR:
222         if (ret != DA_RESULT_OK) {
223                 if (charset_type) {
224                         free(charset_type);
225                         charset_type = NULL;
226                 }
227         }
228         *out_charset_type = charset_type;
229         *out_encoding_type = encoding_type;
230         *out_raw_encoded_str = raw_encoded_str;
231         return ret;
232 }
233
234 void decode_url_encoded_str(const char *in_encoded_str, char **out_str)
235 {
236         CURL* curl = curl_easy_init();
237
238         *out_str = curl_easy_unescape(curl, in_encoded_str, strlen(in_encoded_str), NULL);
239
240         if(!*out_str){
241                 DA_LOGE("CURLE_OUT_OF_MEMORY");
242                 return;
243         }
244
245         curl_easy_cleanup(curl);
246 }