Bug Summary

File:test/../gcs.c
Warning:line 204, column 4
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name test_gcs.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -D HAVE_CONFIG_H -I . -I ../../../../src/include -I ../../../../libs/esl/src/include -I ../../../../libs/xmlrpc-c -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -I /usr/include/uuid -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -D HAVE_OPENSSL -I . -D SWITCH_TEST_BASE_DIR_FOR_CONF="/drone/src/src/mod/applications/mod_http_cache/test" -D SWITCH_TEST_BASE_DIR_OVERRIDE="/drone/src/src/mod/applications/mod_http_cache/test" -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wno-misleading-indentation -std=c99 -fdebug-compilation-dir /drone/src/src/mod/applications/mod_http_cache -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /drone/src/scan-build/2022-06-23-052828-407-1 -x c test/test_gcs.c -faddrsig
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
68switch_size_t file_size_to_alloc(switch_size_t in) {
69 switch_size_t last = 4096;
70 for (int i = 0; i < 20; i++) {
71 if (! (in & last)) {
72 return last;
73 }
74 last *= 2;
75 }
76 return last;
77}
78
79void signtoken(char *token, int tokenlen,char *pkey, char *out) {
80 unsigned char *sig = NULL((void*)0);
81 BIO *b = NULL((void*)0);
82 RSA *r = NULL((void*)0);
83 unsigned int sig_len;
84 unsigned char *md = malloc(SHA256_DIGEST_LENGTH32 * sizeof(unsigned char));
85 unsigned char *digest = SHA256((const unsigned char *) token, tokenlen, md);
86 b = BIO_new_mem_buf(pkey, -1);
87 r = PEM_read_bio_RSAPrivateKey(b, NULL((void*)0), NULL((void*)0), NULL((void*)0));
88 BIO_set_close(b, BIO_CLOSE)(int)BIO_ctrl(b,9,(0x01),((void*)0));
89 BIO_free(b);
90 sig = malloc(RSA_size(r));
91 RSA_sign(NID_sha256672, digest, sizeof(char) * SHA256_DIGEST_LENGTH32, sig, &sig_len, r);
92 switch_b64_encode(sig,(switch_size_t) sizeof(char) * sig_len,(unsigned char *) out, 343 * sizeof(char));
93 free(sig);
94 free(md);
95 RSA_free(r);
96}
97
98char *gcs_auth_request(char *content, char *url);
99switch_status_t gcs_refresh_authorization (http_profile_t *profile)
100{
101 int token_length;
102 char *token = NULL((void*)0);
103 char *encoded = NULL((void*)0);
104 char *assertion = NULL((void*)0);
105 char *auth = NULL((void*)0);
106 char content[GCS_SIGNATURE_LENGTH_MAX1024];
107 char *signature_url_encoded = NULL((void*)0);
108 time_t exp;
109 time_t now = time(NULL((void*)0));
110 token = encoded_token(profile->region, profile->gcs_email, profile->aws_s3_access_key_id, &token_length, now);
111 encoded = malloc(sizeof(char) * 343);
112 signtoken(token, token_length, profile->secret_access_key, encoded);
113 assertion = malloc(sizeof(char) * (1 + token_length + 343));
114 sprintf(assertion, "%s.%s", token, encoded);
115 free(token);
116 free(encoded);
117 signature_url_encoded = switch_string_replace(assertion, "+", "%2B");
118 sprintf(content,"%s%s", "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=", signature_url_encoded);
119 free(signature_url_encoded);
120 auth = gcs_auth_request(content, profile->region);
121 profile->gcs_credentials = auth;
122 free(auth);
123 exp = now + 3540;
124 profile->expires = exp;
125 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "test/../gcs.c", (const char *)__func__
, 125, ((void*)0)
, SWITCH_LOG_DEBUG, "Credentials Expries Unix Time: %ld", exp);
126 switch_safe_free(assertion)if (assertion) {free(assertion);assertion=((void*)0);};
127 return SWITCH_STATUS_SUCCESS;
128}
129#endif
130
131/**
132 * Append the specific GCS Blob Service headers
133 * @param http_profile_t the provile
134 * @param headers the list of headers to append to
135 */
136
137switch_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)
138{
139 char header[1024];
140#if defined(HAVE_OPENSSL1)
141 switch_time_t now = time(NULL((void*)0));
142 if (profile->expires < now) {
143 gcs_refresh_authorization(profile);
144 }
145 switch_snprintf(header, sizeof(header), "Authorization: Bearer %s", profile->gcs_credentials);
146 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Credecials Token: %s", profile->gcs_credentials);
147 headers = switch_curl_slist_append(headers, header);
148#endif
149 return headers;
150}
151
152/**
153 * Read the GCS Blob Service profile
154 * @param name the name of the profile
155 * @param xml the portion of the XML document containing the profile
156 * @param access_key_id returned value of access_key_id in the configuration
157 * @param secret_access_key returned value of secret_access_key in the configuration
158 * @param base_domain returned value of base_domain in the configuration
159 * @param bytes_per_block returned value of bytes_per_block in the configuration
160 * @return SWITCH_STATUS_SUCCESS on success
161 */
162switch_status_t gcs_config_profile(switch_xml_t xml, http_profile_t *profile,switch_memory_pool_t *pool)
163{
164 switch_status_t status = SWITCH_STATUS_SUCCESS;
165#if defined(HAVE_OPENSSL1)
166 char *file = NULL((void*)0);
167 char *envfile = getenv("GOOGLE_APPLICATION_CREDENTIALS");
168 switch_xml_t base_domain_xml = switch_xml_child(xml, "base-domain");
169 profile->append_headers_ptr = gcs_append_headers;
170
171 /* check if environment variables set the keys */
172 if (!zstr(envfile)_zstr(envfile)) {
173 file = strdup(envfile);
174 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
175 // "Using GOOGLE_APPLICATION_CREDENTIALS environment variables for GCS access on profile \"%s\"\n", profile->name);
176 } else {
177 /* use configuration for keys */
178 switch_xml_t creds = switch_xml_child(xml, "credential_file");
179 if (creds) {
180 file = switch_strip_whitespace(switch_xml_txt(creds)((creds) ? creds->txt : ""));
181 }
182 }
183 if (switch_file_exists(file, pool) == SWITCH_STATUS_SUCCESS) {
184 char *contents = NULL((void*)0);
185 char *jsonstr = NULL((void*)0);
186 switch_file_t *fd;
187 switch_status_t status;
188 switch_size_t size;
189 cJSON *json = {0};
190
191 status = switch_file_open(&fd, file, SWITCH_FOPEN_READ0x00001, SWITCH_FPROT_UREAD0x0400, pool);
192 if (status != SWITCH_STATUS_SUCCESS) {
193 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not open credencial file\n", profile->bytes_per_block);
194 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
195 return status;
196 }
197
198 size = switch_file_get_size(fd);
199 if (size) {
200 contents = malloc(file_size_to_alloc(size * 2) * sizeof(char));
201 switch_file_read(fd, (void *) contents, &size);
202 } else {
203 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
204 status = switch_file_close(fd);
Value stored to 'status' is never read
205 return SWITCH_STATUS_FALSE;
206 }
207 status = switch_file_close(fd);
208 if (status != SWITCH_STATUS_SUCCESS) {
209 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not close credencial file\n", profile->bytes_per_block);
210 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
211 free(contents);
212 return status;
213 }
214 json = cJSON_Parse(contents);
215 if (cJSON_GetObjectItem(json,"private_key_id") != NULL((void*)0)) {
216 jsonstr = cJSON_GetObjectItem(json,"private_key_id")->valuestring;
217 profile->aws_s3_access_key_id = malloc(sizeof(char) * (1+ strlen(jsonstr)));
218 strcpy(profile->aws_s3_access_key_id, jsonstr);
219 }
220 if (cJSON_GetObjectItem(json,"private_key") != NULL((void*)0)) {
221 jsonstr = cJSON_GetObjectItem(json,"private_key")->valuestring;
222 profile->secret_access_key = malloc(sizeof(char) * (1+ strlen(jsonstr)));
223 strcpy(profile->secret_access_key, jsonstr);
224 }
225 if (cJSON_GetObjectItem(json,"client_email") != NULL((void*)0)) {
226 jsonstr = cJSON_GetObjectItem(json,"client_email")->valuestring;
227 profile->gcs_email = malloc(sizeof(char) * (1+ strlen(jsonstr)));
228 strcpy(profile->gcs_email, jsonstr);
229 }
230 if (cJSON_GetObjectItem(json,"token_uri") != NULL((void*)0)) {
231 jsonstr = cJSON_GetObjectItem(json,"token_uri")->valuestring;
232 profile->region = malloc(sizeof(char) * (1+ strlen(jsonstr)));
233 strcpy(profile->region, jsonstr);
234 }
235 cJSON_Delete(json);
236 switch_safe_free(contents)if (contents) {free(contents);contents=((void*)0);};
237 } else {
238 switch_xml_t private_key = switch_xml_child(xml, "private_key");
239 switch_xml_t private_key_id = switch_xml_child(xml, "private_key_id");
240 switch_xml_t client_email = switch_xml_child(xml, "client_email");
241 switch_xml_t token_uri = switch_xml_child(xml, "token_uri");
242 if (private_key_id) {
243 profile->aws_s3_access_key_id = switch_strip_whitespace(switch_xml_txt(private_key_id)((private_key_id) ? private_key_id->txt : ""));
244 } else {
245 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key_id\n");
246 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
247 return SWITCH_STATUS_FALSE;
248 }
249 if (private_key) {
250 profile->secret_access_key = switch_xml_txt(private_key)((private_key) ? private_key->txt : "");
251 } else {
252 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key\n");
253 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
254 return SWITCH_STATUS_FALSE;
255 }
256 if (client_email) {
257 profile->gcs_email = switch_strip_whitespace(switch_xml_txt(client_email)((client_email) ? client_email->txt : ""));
258 } else {
259 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key client_email\n");
260 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
261 return SWITCH_STATUS_FALSE;
262 }
263 if (token_uri) {
264 profile->region = switch_strip_whitespace(switch_xml_txt(token_uri)((token_uri) ? token_uri->txt : ""));
265 } else {
266 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key token_uri\n");
267 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
268 return SWITCH_STATUS_FALSE;
269 }
270 }
271 switch_safe_free(file)if (file) {free(file);file=((void*)0);};
272 profile->bytes_per_block = 4e6;
273 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set number of bytes per block to %zu\n", profile->bytes_per_block);
274 status = gcs_refresh_authorization(profile);
275 if (status != SWITCH_STATUS_SUCCESS){
276 return status;
277 }
278 if (base_domain_xml) {
279 profile->base_domain = switch_strip_whitespace(switch_xml_txt(base_domain_xml)((base_domain_xml) ? base_domain_xml->txt : ""));
280 if (zstr(profile->base_domain)_zstr(profile->base_domain)) {
281 switch_safe_free(profile->base_domain)if (profile->base_domain) {free(profile->base_domain);profile
->base_domain=((void*)0);}
;
282 }
283 }
284#endif
285 return status;
286}
287
288#if defined(HAVE_OPENSSL1)
289static size_t gcs_auth_callback(void *ptr, size_t size, size_t nmemb, void *data)
290{
291 register unsigned int realsize = (unsigned int) (size * nmemb);
292 struct http_data *http_data = data;
293
294 http_data->bytes += realsize;
295
296 if (http_data->bytes > http_data->max_bytes) {
297 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "test/../gcs.c", (const char *)__func__
, 297, ((void*)0)
, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) http_data->bytes);
298 http_data->err = 1;
299 return 0;
300 }
301
302 http_data->stream.write_function(&http_data->stream, "%.*s", realsize, ptr);
303 return realsize;
304}
305
306char *gcs_auth_request(char *content, char *url) {
307 switch_CURL *curl_handle = NULL((void*)0);
308 long httpRes = 0;
309 char *response = NULL((void*)0);
310 switch_curl_slist_t *headers = NULL((void*)0);
311 char *ct = "Content-Type: application/x-www-form-urlencoded";
312 struct http_data http_data;
313 CURLcode res;
314 memset(&http_data, 0, sizeof(http_data));
315 http_data.max_bytes = 10240;
316 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"
, 316, __extension__ __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
;
317
318 curl_handle = switch_curl_easy_init();
319 switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url)curl_easy_setopt(curl_handle,CURLOPT_URL,url);
320 switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, content)curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,content);
321 switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 5)curl_easy_setopt(curl_handle,CURLOPT_CONNECTTIMEOUT,5);
322 switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10)curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,10);
323
324 headers = switch_curl_slist_append(headers, ct);
325 switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0")curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"freeswitch-curl/1.0"
)
;
326 switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
327 switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers)curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER,headers);
328 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, gcs_auth_callback)curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,gcs_auth_callback
)
;
329 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&http_data)curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&http_data
)
;
330
331 res = switch_curl_easy_perform(curl_handle);
332 switch_curl_easy_cleanup(curl_handle);
333
334 if(res != CURLE_OK)
335 fprintf(stderrstderr, "curl_easy_perform() failed: %s\n",
336 switch_curl_easy_strerror(res));
337
338 if (http_data.stream.data && !zstr((char *) http_data.stream.data)_zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) {
339 cJSON *json = {0};
340 json = cJSON_Parse(http_data.stream.data);
341
342 if (cJSON_GetObjectItem(json,"access_token") != NULL((void*)0)) {
343 char *jsonstr;
344 jsonstr = cJSON_GetObjectItem(json,"access_token")->valuestring;
345 response = malloc(sizeof(char) * (1+strlen(jsonstr)));
346 strcpy(response, jsonstr);
347 }
348 cJSON_Delete(json);
349 }
350 switch_safe_free(http_data.stream.data)if (http_data.stream.data) {free(http_data.stream.data);http_data
.stream.data=((void*)0);}
;
351 if (headers) {
352 switch_curl_slist_free_all(headers);
353 }
354 return response;
355}
356#endif
357
358
359/* For Emacs:
360 * Local Variables:
361 * mode:c
362 * indent-tabs-mode:t
363 * tab-width:4
364 * c-basic-offset:4
365 * End:
366 * For VIM:
367 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
368 */