Bug Summary

File:test/../gcs.c
Warning:line 73, column 22
Result of 'malloc' is converted to a pointer of type 'unsigned char', which is incompatible with sizeof operand type 'char'

Annotated Source Code

1/*
2 * gcs.c for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2020
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is gcs.c for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * gcs.c -- Some GCS Blob Service helper functions
20 *
21 */
22#include "gcs.h"
23#include <switch.h>
24#include <switch_curl.h>
25
26#if defined(HAVE_OPENSSL1)
27#include <stdio.h>
28#include <string.h>
29#include <time.h>
30#include <stdlib.h>
31#include <openssl/sha.h>
32#include <openssl/bio.h>
33#include <openssl/rsa.h>
34#include <openssl/pem.h>
35#endif
36
37struct http_data {
38 switch_stream_handle_t stream;
39 switch_size_t bytes;
40 switch_size_t max_bytes;
41 int err;
42};
43
44#if defined(HAVE_OPENSSL1)
45char *encoded_token(const char *token_uri, const char *client_email, const char *private_key_id, int *token_length, time_t now) {
46 time_t then = now + 3600;
47 int tlength = 1 + snprintf(NULL((void*)0), 0, "{\"typ\":\"JWT\",\"alg\":\"RS256\",\"kid\":\"%s\"}", private_key_id);
48 int payload_length = 1 + snprintf(NULL((void*)0), 0, "{\"iat\":\"%ld\",\"exp\":\"%ld\",\"iss\":\"%s\",\"aud\":\"%s\",\"scope\":\"https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/devstorage.read_write\"}", now, then, client_email,token_uri);
49 char token[tlength];
50 char payload[payload_length];
51 int encoded_tlength = tlength * 4 / 3 + (tlength % 3 ? 1 : 0);
52 int encoded_playload_length = payload_length * 4 / 3 + (payload_length % 3 ? 1 : 0);
53 char *tokenb64 = malloc(encoded_tlength * sizeof(char));
54 char *payloadb64 = malloc(encoded_playload_length* sizeof(char));
55 int signee_length = encoded_tlength + encoded_playload_length;
56 char *signee = malloc((signee_length) * sizeof(char));
57 sprintf(token,"{\"typ\":\"JWT\",\"alg\":\"RS256\",\"kid\":\"%s\"}", private_key_id);
58 sprintf(payload, "{\"iat\":\"%ld\",\"exp\":\"%ld\",\"iss\":\"%s\",\"aud\":\"%s\",\"scope\":\"https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/devstorage.read_write\"}", now, then, client_email,token_uri);
59 *token_length = signee_length - 1;
60 switch_b64_encode((unsigned char *) token,sizeof(token), (unsigned char *) tokenb64, encoded_tlength);
61 switch_b64_encode((unsigned char *) payload,sizeof(payload), (unsigned char *) payloadb64, encoded_playload_length);
62 sprintf(signee, "%s.%s", tokenb64, payloadb64);
63 free(tokenb64);
64 free(payloadb64);
65 return signee;
66}
67
68void signtoken(char *token, int tokenlen,char *pkey, char *out) {
69 unsigned char *sig = NULL((void*)0);
70 BIO *b = NULL((void*)0);
71 RSA *r = NULL((void*)0);
72 unsigned int sig_len;
73 unsigned char *md = malloc(SHA256_DIGEST_LENGTH32 * sizeof(char));
Result of 'malloc' is converted to a pointer of type 'unsigned char', which is incompatible with sizeof operand type 'char'
74 unsigned char *digest = SHA256((const unsigned char *) token, tokenlen, md);
75 b = BIO_new_mem_buf(pkey, -1);
76 r = PEM_read_bio_RSAPrivateKey(b, NULL((void*)0), NULL((void*)0), NULL((void*)0));
77 BIO_set_close(b, BIO_CLOSE)(int)BIO_ctrl(b,9,(0x01),((void*)0));
78 BIO_free(b);
79 sig = malloc(RSA_size(r));
80 RSA_sign(NID_sha256672, digest, sizeof(char) * SHA256_DIGEST_LENGTH32, sig, &sig_len, r);
81 switch_b64_encode(sig,(switch_size_t) sizeof(char) * sig_len,(unsigned char *) out, 343 * sizeof(char));
82 free(sig);
83 free(md);
84 RSA_free(r);
85}
86
87char *gcs_auth_request(char *content, char *url);
88switch_status_t gcs_refresh_authorization (http_profile_t *profile)
89{
90 int token_length;
91 char *token = NULL((void*)0);
92 char *encoded = NULL((void*)0);
93 char *assertion = NULL((void*)0);
94 char *auth = NULL((void*)0);
95 char content[GCS_SIGNATURE_LENGTH_MAX1024];
96 char *signature_url_encoded = NULL((void*)0);
97 time_t exp;
98 time_t now = time(NULL((void*)0));
99 token = encoded_token(profile->region, profile->gcs_email, profile->aws_s3_access_key_id, &token_length, now);
100 encoded = malloc(sizeof(char) * 343);
101 signtoken(token, token_length, profile->secret_access_key, encoded);
102 assertion = malloc(sizeof(char) * (1 + token_length + 343));
103 sprintf(assertion, "%s.%s", token, encoded);
104 free(token);
105 signature_url_encoded = switch_string_replace(assertion, "+", "%2B");
106 sprintf(content,"%s%s", "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=", signature_url_encoded);
107 auth = gcs_auth_request(content, profile->region);
108 profile->gcs_credentials = auth;
109 exp = now + 3540;
110 profile->expires = exp;
111 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "test/../gcs.c", (const char *)__func__
, 111, ((void*)0)
, SWITCH_LOG_DEBUG, "Credentials Expries Unix Time: %ld", exp);
112 switch_safe_free(assertion)if (assertion) {free(assertion);assertion=((void*)0);};
113 return SWITCH_STATUS_SUCCESS;
114}
115#endif
116
117/**
118 * Append the specific GCS Blob Service headers
119 * @param http_profile_t the provile
120 * @param headers the list of headers to append to
121 */
122
123switch_curl_slist_t *gcs_append_headers(http_profile_t *profile, switch_curl_slist_t *headers, const char *verb,unsigned int content_length, const char *content_type, const char *url, const unsigned int block_num, char **query_string)
124{
125 char header[1024];
126#if defined(HAVE_OPENSSL1)
127 switch_time_t now = time(NULL((void*)0));
128 if (profile->expires < now) {
129 gcs_refresh_authorization(profile);
130 }
131 switch_snprintf(header, sizeof(header), "Authorization: Bearer %s", profile->gcs_credentials);
132 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Credecials Token: %s", profile->gcs_credentials);
133 headers = switch_curl_slist_append(headers, header);
134#endif
135 return headers;
136}
137
138/**
139 * Read the GCS Blob Service profile
140 * @param name the name of the profile
141 * @param xml the portion of the XML document containing the profile
142 * @param access_key_id returned value of access_key_id in the configuration
143 * @param secret_access_key returned value of secret_access_key in the configuration
144 * @param base_domain returned value of base_domain in the configuration
145 * @param bytes_per_block returned value of bytes_per_block in the configuration
146 * @return SWITCH_STATUS_SUCCESS on success
147 */
148switch_status_t gcs_config_profile(switch_xml_t xml, http_profile_t *profile,switch_memory_pool_t *pool)
149{
150 switch_status_t status = SWITCH_STATUS_SUCCESS;
151#if defined(HAVE_OPENSSL1)
152 char *file = NULL((void*)0);
153 char *envfile = getenv("GOOGLE_APPLICATION_CREDENTIALS");
154 switch_xml_t base_domain_xml = switch_xml_child(xml, "base-domain");
155 profile->append_headers_ptr = gcs_append_headers;
156
157 /* check if environment variables set the keys */
158 if (!zstr(envfile)_zstr(envfile)) {
159 file = switch_core_strdup(pool, envfile)switch_core_perform_strdup(pool, envfile, "test/../gcs.c", (const
char *)__func__, 159)
;
160 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
161 // "Using GOOGLE_APPLICATION_CREDENTIALS environment variables for GCS access on profile \"%s\"\n", profile->name);
162 } else {
163 /* use configuration for keys */
164 switch_xml_t creds = switch_xml_child(xml, "credential_file");
165 if (creds) {
166 file = switch_strip_whitespace(switch_xml_txt(creds)((creds) ? creds->txt : ""));
167 }
168 }
169 if (switch_file_exists(file, pool) == SWITCH_STATUS_SUCCESS) {
170 char *contents = NULL((void*)0);
171 char *jsonstr = NULL((void*)0);
172 switch_file_t *fd;
173 switch_status_t status;
174 switch_size_t size;
175 cJSON *json = {0};
176
177 status = switch_file_open(&fd, file, SWITCH_FOPEN_READ0x00001, SWITCH_FPROT_UREAD0x0400, pool);
178 if (status != SWITCH_STATUS_SUCCESS) {
179 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not open credencial file\n", profile->bytes_per_block);
180 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
181 return status;
182 }
183
184 size = switch_file_get_size(fd);
185 if (size) {
186 contents = malloc(size);
187 switch_file_read(fd, (void *) contents, &size);
188 } else {
189 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
190 return SWITCH_STATUS_FALSE;
191 }
192
193 status = switch_file_close(fd);
194 if (status != SWITCH_STATUS_SUCCESS) {
195 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not close credencial file\n", profile->bytes_per_block);
196 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
197 return status;
198 }
199 json = cJSON_Parse(contents);
200 if (cJSON_GetObjectItem(json,"private_key_id") != NULL((void*)0)) {
201 jsonstr = cJSON_GetObjectItem(json,"private_key_id")->valuestring;
202 profile->aws_s3_access_key_id = malloc(sizeof(char) * (1+ strlen(jsonstr)));
203 strcpy(profile->aws_s3_access_key_id, jsonstr);
204 }
205 if (cJSON_GetObjectItem(json,"private_key") != NULL((void*)0)) {
206 jsonstr = cJSON_GetObjectItem(json,"private_key")->valuestring;
207 profile->secret_access_key = malloc(sizeof(char) * (1+ strlen(jsonstr)));
208 strcpy(profile->secret_access_key, jsonstr);
209 }
210 if (cJSON_GetObjectItem(json,"client_email") != NULL((void*)0)) {
211 jsonstr = cJSON_GetObjectItem(json,"client_email")->valuestring;
212 profile->gcs_email = malloc(sizeof(char) * (1+ strlen(jsonstr)));
213 strcpy(profile->gcs_email, jsonstr);
214 }
215 if (cJSON_GetObjectItem(json,"token_uri") != NULL((void*)0)) {
216 jsonstr = cJSON_GetObjectItem(json,"token_uri")->valuestring;
217 profile->region = malloc(sizeof(char) * (1+ strlen(jsonstr)));
218 strcpy(profile->region, jsonstr);
219 }
220 cJSON_Delete(json);
221 free(contents);
222 } else {
223 switch_xml_t private_key = switch_xml_child(xml, "private_key");
224 switch_xml_t private_key_id = switch_xml_child(xml, "private_key_id");
225 switch_xml_t client_email = switch_xml_child(xml, "client_email");
226 switch_xml_t token_uri = switch_xml_child(xml, "token_uri");
227 if (private_key_id) {
228 profile->aws_s3_access_key_id = switch_strip_whitespace(switch_xml_txt(private_key_id)((private_key_id) ? private_key_id->txt : ""));
229 } else {
230 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key_id\n");
231 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
232 return SWITCH_STATUS_FALSE;
233 }
234 if (private_key) {
235 profile->secret_access_key = switch_xml_txt(private_key)((private_key) ? private_key->txt : "");
236 } else {
237 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key\n");
238 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
239 return SWITCH_STATUS_FALSE;
240 }
241 if (client_email) {
242 profile->gcs_email = switch_strip_whitespace(switch_xml_txt(client_email)((client_email) ? client_email->txt : ""));
243 } else {
244 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key client_email\n");
245 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
246 return SWITCH_STATUS_FALSE;
247 }
248 if (token_uri) {
249 profile->region = switch_strip_whitespace(switch_xml_txt(token_uri)((token_uri) ? token_uri->txt : ""));
250 } else {
251 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key token_uri\n");
252 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
253 return SWITCH_STATUS_FALSE;
254 }
255 }
256 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
257 profile->bytes_per_block = 4e6;
258 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set number of bytes per block to %zu\n", profile->bytes_per_block);
259 status = gcs_refresh_authorization(profile);
260 if (status != SWITCH_STATUS_SUCCESS){
261 return status;
262 }
263
264 if (base_domain_xml) {
265 profile->base_domain = switch_strip_whitespace(switch_xml_txt(base_domain_xml)((base_domain_xml) ? base_domain_xml->txt : ""));
266 if (zstr(profile->base_domain)_zstr(profile->base_domain)) {
267 switch_safe_free(profile->base_domain)if (profile->base_domain) {free(profile->base_domain);profile
->base_domain=((void*)0);}
;
268 }
269 }
270#endif
271 return status;
272}
273
274#if defined(HAVE_OPENSSL1)
275static size_t gcs_auth_callback(void *ptr, size_t size, size_t nmemb, void *data)
276{
277 register unsigned int realsize = (unsigned int) (size * nmemb);
278 struct http_data *http_data = data;
279
280 http_data->bytes += realsize;
281
282 if (http_data->bytes > http_data->max_bytes) {
283 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "test/../gcs.c", (const char *)__func__
, 283, ((void*)0)
, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) http_data->bytes);
284 http_data->err = 1;
285 return 0;
286 }
287
288 http_data->stream.write_function(&http_data->stream, "%.*s", realsize, ptr);
289 return realsize;
290}
291
292char *gcs_auth_request(char *content, char *url) {
293 switch_CURL *curl_handle = NULL((void*)0);
294 long httpRes = 0;
295 char *response = NULL((void*)0);
296 switch_curl_slist_t *headers = NULL((void*)0);
297 char *ct = "Content-Type: application/x-www-form-urlencoded";
298 struct http_data http_data;
299 CURLcode res;
300
301 memset(&http_data, 0, sizeof(http_data));
302 http_data.max_bytes = 10240;
303 SWITCH_STANDARD_STREAM(http_data.stream)memset(&http_data.stream, 0, sizeof(http_data.stream)); http_data
.stream.data = malloc(1024); ((http_data.stream.data) ? (void
) (0) : __assert_fail ("http_data.stream.data", "test/../gcs.c"
, 303, __PRETTY_FUNCTION__)); memset(http_data.stream.data, 0
, 1024); http_data.stream.end = http_data.stream.data; http_data
.stream.data_size = 1024; http_data.stream.write_function = switch_console_stream_write
; http_data.stream.raw_write_function = switch_console_stream_raw_write
; http_data.stream.alloc_len = 1024; http_data.stream.alloc_chunk
= 1024
;
304
305 curl_handle = switch_curl_easy_init();
306 switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url)curl_easy_setopt(curl_handle,CURLOPT_URL,url);
307 switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, content)curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,content);
308 switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 5)curl_easy_setopt(curl_handle,CURLOPT_CONNECTTIMEOUT,5);
309 switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10)curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,10);
310
311 headers = switch_curl_slist_append(headers, ct);
312 switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0")curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"freeswitch-curl/1.0"
)
;
313 switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
314 switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers)curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER,headers);
315 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, gcs_auth_callback)curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,gcs_auth_callback
)
;
316 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&http_data)curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&http_data
)
;
317
318 res = switch_curl_easy_perform(curl_handle);
319 switch_curl_easy_cleanup(curl_handle);
320
321 if(res != CURLE_OK)
322 fprintf(stderrstderr, "curl_easy_perform() failed: %s\n",
323 switch_curl_easy_strerror(res));
324
325 if (http_data.stream.data && !zstr((char *) http_data.stream.data)_zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(" ") && __builtin_constant_p (http_data.stream.data
) && (__s1_len = __builtin_strlen (" "), __s2_len = __builtin_strlen
(http_data.stream.data), (!((size_t)(const void *)((" ") + 1
) - (size_t)(const void *)(" ") == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((http_data.stream.data) + 1) - (size_t
)(const void *)(http_data.stream.data) == 1) || __s2_len >=
4)) ? __builtin_strcmp (" ", http_data.stream.data) : (__builtin_constant_p
(" ") && ((size_t)(const void *)((" ") + 1) - (size_t
)(const void *)(" ") == 1) && (__s1_len = __builtin_strlen
(" "), __s1_len < 4) ? (__builtin_constant_p (http_data.stream
.data) && ((size_t)(const void *)((http_data.stream.data
) + 1) - (size_t)(const void *)(http_data.stream.data) == 1) ?
__builtin_strcmp (" ", http_data.stream.data) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (http_data.stream.data); int __result = (((const unsigned
char *) (const char *) (" "))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (" "))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (" "))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (" "))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(http_data.stream.data) && ((size_t)(const void *)((
http_data.stream.data) + 1) - (size_t)(const void *)(http_data
.stream.data) == 1) && (__s2_len = __builtin_strlen (
http_data.stream.data), __s2_len < 4) ? (__builtin_constant_p
(" ") && ((size_t)(const void *)((" ") + 1) - (size_t
)(const void *)(" ") == 1) ? __builtin_strcmp (" ", http_data
.stream.data) : -(__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (" "); int __result =
(((const unsigned char *) (const char *) (http_data.stream.data
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (http_data
.stream.data))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
http_data.stream.data))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (http_data.stream.data))[3] - __s2[3]); } } __result; }))
) : __builtin_strcmp (" ", http_data.stream.data)))); })
) {
326 cJSON *json = {0};
327 json = cJSON_Parse(http_data.stream.data);
328
329 if (cJSON_GetObjectItem(json,"access_token") != NULL((void*)0)) {
330 char *jsonstr;
331 jsonstr = cJSON_GetObjectItem(json,"access_token")->valuestring;
332 response = malloc(sizeof(char) * (1+strlen(jsonstr)));
333 strcpy(response, jsonstr);
334 }
335 cJSON_Delete(json);
336 }
337 return response;
338}
339#endif
340
341
342/* For Emacs:
343 * Local Variables:
344 * mode:c
345 * indent-tabs-mode:t
346 * tab-width:4
347 * c-basic-offset:4
348 * End:
349 * For VIM:
350 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
351 */