| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2020, Sangoma Technologies Corporation | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Ben Ford <bford@sangoma.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/logger.h"
 | 
					
						
							| 
									
										
										
										
											2021-12-16 19:41:56 +00:00
										 |  |  | #include "asterisk/file.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | #include "asterisk/acl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | #include "curl.h"
 | 
					
						
							|  |  |  | #include "general.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | #include "stir_shaken.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | #include "profile.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <curl/curl.h>
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | #include <sys/stat.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Used to check CURL headers */ | 
					
						
							|  |  |  | #define MAX_HEADER_LENGTH 1023
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | /* Used to limit download size */ | 
					
						
							|  |  |  | #define MAX_DOWNLOAD_SIZE 8192
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Used to limit how many bytes we get from CURL per write */ | 
					
						
							|  |  |  | #define MAX_BUF_SIZE_PER_WRITE 1024
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Certificates should begin with this */ | 
					
						
							|  |  |  | #define BEGIN_CERTIFICATE_STR "-----BEGIN CERTIFICATE-----"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | /* CURL callback data to avoid storing useless info in AstDB */ | 
					
						
							|  |  |  | struct curl_cb_data { | 
					
						
							|  |  |  | 	char *cache_control; | 
					
						
							|  |  |  | 	char *expires; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | struct curl_cb_write_buf { | 
					
						
							|  |  |  | 	char buf[MAX_DOWNLOAD_SIZE + 1]; | 
					
						
							|  |  |  | 	size_t size; | 
					
						
							|  |  |  | 	const char *url; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | struct curl_cb_open_socket { | 
					
						
							|  |  |  | 	const struct ast_acl_list *acl; | 
					
						
							|  |  |  | 	curl_socket_t *sockfd; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | struct curl_cb_data *curl_cb_data_create(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct curl_cb_data *data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 13:05:43 -05:00
										 |  |  | 	data = ast_calloc(1, sizeof(*data)); | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void curl_cb_data_free(struct curl_cb_data *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_free(data->cache_control); | 
					
						
							|  |  |  | 	ast_free(data->expires); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_free(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | static void curl_cb_open_socket_free(struct curl_cb_open_socket *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	close(*data->sockfd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* We don't need to free the ACL since we just use a reference */ | 
					
						
							|  |  |  | 	ast_free(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | char *curl_cb_data_get_cache_control(const struct curl_cb_data *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data->cache_control; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *curl_cb_data_get_expires(const struct curl_cb_data *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data->expires; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Called when a CURL request completes | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-11-19 09:54:42 +01:00
										 |  |  |  * \param buffer, size, nitems | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  |  * \param data The curl_cb_data structure to store expiration info | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static size_t curl_header_callback(char *buffer, size_t size, size_t nitems, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct curl_cb_data *cb_data = data; | 
					
						
							|  |  |  | 	size_t realsize; | 
					
						
							|  |  |  | 	char *header; | 
					
						
							|  |  |  | 	char *value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	realsize = size * nitems; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (realsize > MAX_HEADER_LENGTH) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "CURL header length is too large (size: '%zu' | max: '%d')\n", | 
					
						
							|  |  |  | 			realsize, MAX_HEADER_LENGTH); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	header = ast_alloca(realsize + 1); | 
					
						
							|  |  |  | 	memcpy(header, buffer, realsize); | 
					
						
							|  |  |  | 	header[realsize] = '\0'; | 
					
						
							|  |  |  | 	value = strchr(header, ':'); | 
					
						
							|  |  |  | 	if (!value) { | 
					
						
							|  |  |  | 		return realsize; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*value++ = '\0'; | 
					
						
							|  |  |  | 	value = ast_trim_blanks(ast_skip_blanks(value)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!strcasecmp(header, "Cache-Control")) { | 
					
						
							|  |  |  | 		cb_data->cache_control = ast_strdup(value); | 
					
						
							|  |  |  | 	} else if (!strcasecmp(header, "Expires")) { | 
					
						
							|  |  |  | 		cb_data->expires = ast_strdup(value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return realsize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Prepare a CURL instance to use | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param data The CURL callback data | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \retval NULL on failure | 
					
						
							| 
									
										
										
										
											2021-11-19 09:54:42 +01:00
										 |  |  |  * \return CURL instance on success | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  |  */ | 
					
						
							|  |  |  | static CURL *get_curl_instance(struct curl_cb_data *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CURL *curl; | 
					
						
							|  |  |  | 	struct stir_shaken_general *cfg; | 
					
						
							|  |  |  | 	unsigned int curl_timeout; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg = stir_shaken_general_get(); | 
					
						
							|  |  |  | 	curl_timeout = ast_stir_shaken_curl_timeout(cfg); | 
					
						
							|  |  |  | 	ao2_cleanup(cfg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl = curl_easy_init(); | 
					
						
							|  |  |  | 	if (!curl) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_TIMEOUT, curl_timeout); | 
					
						
							| 
									
										
										
										
											2022-01-13 14:37:16 +00:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_USERAGENT, AST_CURL_USER_AGENT); | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_header_callback); | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_HEADERDATA, data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return curl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Write callback passed to libcurl | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note If this function returns anything other than the size of the data | 
					
						
							|  |  |  |  * libcurl expected us to process, the request will cancel. That's why we return | 
					
						
							|  |  |  |  * 0 on error, otherwise the amount of data we were given | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param curl_data The data from libcurl | 
					
						
							|  |  |  |  * \param size Always 1 according to libcurl | 
					
						
							|  |  |  |  * \param actual_size The actual size of the data | 
					
						
							|  |  |  |  * \param our_data The data we passed to libcurl | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \retval The size of the data we processed | 
					
						
							|  |  |  |  * \retval 0 if there was an error | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static size_t curl_write_cb(void *curl_data, size_t size, size_t actual_size, void *our_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Just in case size is NOT always 1 or if it's changed in the future, let's go ahead
 | 
					
						
							|  |  |  | 	 * and do the math for the actual size */ | 
					
						
							|  |  |  | 	size_t real_size = size * actual_size; | 
					
						
							|  |  |  | 	struct curl_cb_write_buf *buf = our_data; | 
					
						
							|  |  |  | 	size_t new_size = buf->size + real_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (new_size > MAX_DOWNLOAD_SIZE) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Attempted to retrieve certificate from %s failed " | 
					
						
							|  |  |  | 			"because it's size exceeds the maximum %d bytes\n", buf->url, MAX_DOWNLOAD_SIZE); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(&(buf->buf[buf->size]), curl_data, real_size); | 
					
						
							|  |  |  | 	buf->size += real_size; | 
					
						
							|  |  |  | 	buf->buf[buf->size] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return real_size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | static curl_socket_t stir_shaken_curl_open_socket_callback(void *our_data, curlsocktype purpose, struct curl_sockaddr *address) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct curl_cb_open_socket *data = our_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_acl_list_is_empty((struct ast_acl_list *)data->acl)) { | 
					
						
							|  |  |  | 		struct ast_sockaddr ast_address = { {0,} }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_sockaddr_copy_sockaddr(&ast_address, &address->addr, address->addrlen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (ast_apply_acl((struct ast_acl_list *)data->acl, &ast_address, NULL) != AST_SENSE_ALLOW) { | 
					
						
							|  |  |  | 			return CURLE_COULDNT_CONNECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*data->sockfd = socket(address->family, address->socktype, address->protocol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return *data->sockfd; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *curl_public_key(const char *public_cert_url, const char *path, struct curl_cb_data *data, const struct ast_acl_list *acl) | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *public_key_file; | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 	char *filename; | 
					
						
							|  |  |  | 	char *serial; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	long http_code; | 
					
						
							|  |  |  | 	CURL *curl; | 
					
						
							|  |  |  | 	char curl_errbuf[CURL_ERROR_SIZE + 1]; | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	struct curl_cb_write_buf *buf; | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 	struct curl_cb_open_socket *open_socket_data; | 
					
						
							|  |  |  | 	curl_socket_t sockfd; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 	curl_errbuf[CURL_ERROR_SIZE] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  	buf = ast_calloc(1, sizeof(*buf)); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	if (!buf) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to allocate memory for CURL write buffer for %s\n", public_cert_url); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 	open_socket_data = ast_calloc(1, sizeof(*open_socket_data)); | 
					
						
							|  |  |  | 	if (!open_socket_data) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to allocate memory for open socket callback\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	open_socket_data->acl = acl; | 
					
						
							|  |  |  | 	open_socket_data->sockfd = &sockfd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	buf->url = public_cert_url; | 
					
						
							|  |  |  | 	curl_errbuf[CURL_ERROR_SIZE] = '\0'; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	curl = get_curl_instance(data); | 
					
						
							|  |  |  | 	if (!curl) { | 
					
						
							| 
									
										
										
										
											2021-10-30 21:04:36 -04:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to set up CURL instance for '%s'\n", public_cert_url); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_URL, public_cert_url); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb); | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf); | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, MAX_BUF_SIZE_PER_WRITE); | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 	curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, stir_shaken_curl_open_socket_callback); | 
					
						
							|  |  |  | 	curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, open_socket_data); | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (curl_easy_perform(curl)) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "%s\n", curl_errbuf); | 
					
						
							|  |  |  | 		curl_easy_cleanup(curl); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 		curl_cb_open_socket_free(open_socket_data); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 11:19:54 -06:00
										 |  |  | 	curl_cb_open_socket_free(open_socket_data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl_easy_cleanup(curl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (http_code / 100 != 2) { | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to retrieve URL '%s': code %ld\n", public_cert_url, http_code); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_free(buf); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_begins_with(buf->buf, BEGIN_CERTIFICATE_STR)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Certificate from %s does not begin with what we expect\n", public_cert_url); | 
					
						
							|  |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	serial = stir_shaken_get_serial_number_x509(buf->buf, buf->size); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 	if (!serial) { | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to get serial from CURL buffer from %s\n", public_cert_url); | 
					
						
							|  |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_asprintf(&filename, "%s/%s.pem", path, serial) < 0) { | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to allocate memory for filename after CURL from %s\n", public_cert_url); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		ast_free(serial); | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_free(serial); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	public_key_file = fopen(filename, "w"); | 
					
						
							|  |  |  | 	if (!public_key_file) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to open file '%s' to write public key from '%s': %s (%d)\n", | 
					
						
							|  |  |  | 			filename, public_cert_url, strerror(errno), errno); | 
					
						
							|  |  |  | 		ast_free(buf); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 		ast_free(filename); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 08:50:18 -06:00
										 |  |  | 	if (fputs(buf->buf, public_key_file) == EOF) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to write string to file from URL %s\n", public_cert_url); | 
					
						
							|  |  |  | 		fclose(public_key_file); | 
					
						
							|  |  |  | 		ast_free(buf); | 
					
						
							|  |  |  | 		ast_free(filename); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fclose(public_key_file); | 
					
						
							|  |  |  | 	ast_free(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:12:55 -05:00
										 |  |  | 	return filename; | 
					
						
							| 
									
										
										
										
											2020-04-15 13:15:21 -05:00
										 |  |  | } |