mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
STIR/SHAKEN: Fix certificate type and storage.
During OpenSIPit, we found out that the public certificates must be of type X.509. When reading in public keys, we use the corresponding X.509 functions now. We also discovered that we needed a better naming scheme for the certificates since certificates with the same name would cause issues (overwriting certs, etc.). Now when we download a public certificate, we get the serial number from it and use that as the name of the cached certificate. The configuration option public_key_url in stir_shaken.conf has also been renamed to public_cert_url, which better describes what the option is for. https://wiki.asterisk.org/wiki/display/AST/OpenSIPit+2021 Change-Id: Ia00b20835f5f976e3603797f2f2fb19672d8114d
This commit is contained in:
@@ -22,8 +22,10 @@
|
||||
#include "asterisk/logger.h"
|
||||
#include "curl.h"
|
||||
#include "general.h"
|
||||
#include "stir_shaken.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Used to check CURL headers */
|
||||
#define MAX_HEADER_LENGTH 1023
|
||||
@@ -148,33 +150,80 @@ static CURL *get_curl_instance(struct curl_cb_data *data)
|
||||
return curl;
|
||||
}
|
||||
|
||||
int curl_public_key(const char *public_key_url, const char *path, struct curl_cb_data *data)
|
||||
/*!
|
||||
* \brief Create a temporary file located at path
|
||||
*
|
||||
* \note This function assumes path does not end with a '/'
|
||||
*
|
||||
* \param path The directory path to create the file in
|
||||
* \param filename Function allocates memory and stores full filename (including path) here
|
||||
*
|
||||
* \retval -1 on failure
|
||||
* \retval file descriptor on success
|
||||
*/
|
||||
static int create_temp_file(const char *path, char **filename)
|
||||
{
|
||||
const char *template_name = "certXXXXXX";
|
||||
int fd;
|
||||
|
||||
if (ast_asprintf(filename, "%s/%s", path, template_name) < 0) {
|
||||
ast_log(LOG_ERROR, "Failed to set up temporary file path for CURL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_mkdir(path, 0644);
|
||||
|
||||
if ((fd = mkstemp(*filename)) < 0) {
|
||||
ast_log(LOG_NOTICE, "Failed to create temporary file for CURL\n");
|
||||
ast_free(*filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
char *curl_public_key(const char *public_cert_url, const char *path, struct curl_cb_data *data)
|
||||
{
|
||||
FILE *public_key_file;
|
||||
RAII_VAR(char *, tmp_filename, NULL, ast_free);
|
||||
char *filename;
|
||||
char *serial;
|
||||
int fd;
|
||||
long http_code;
|
||||
CURL *curl;
|
||||
char curl_errbuf[CURL_ERROR_SIZE + 1];
|
||||
char hash[41];
|
||||
|
||||
ast_sha1_hash(hash, public_key_url);
|
||||
|
||||
curl_errbuf[CURL_ERROR_SIZE] = '\0';
|
||||
|
||||
public_key_file = fopen(path, "wb");
|
||||
/* For now, it's fine to pass in path as is - it shouldn't end with a '/'. However,
|
||||
* if we decide to change how certificates are stored in the future (configurable paths),
|
||||
* then we will need to check to see if path ends with '/', copy everything up to the '/',
|
||||
* and use this new variable for create_temp_file as well as for ast_asprintf below.
|
||||
*/
|
||||
fd = create_temp_file(path, &tmp_filename);
|
||||
if (fd == -1) {
|
||||
ast_log(LOG_ERROR, "Failed to get temporary file descriptor for CURL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public_key_file = fdopen(fd, "wb");
|
||||
if (!public_key_file) {
|
||||
ast_log(LOG_ERROR, "Failed to open file '%s' to write public key from '%s': %s (%d)\n",
|
||||
path, public_key_url, strerror(errno), errno);
|
||||
return -1;
|
||||
tmp_filename, public_cert_url, strerror(errno), errno);
|
||||
close(fd);
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curl = get_curl_instance(data);
|
||||
if (!curl) {
|
||||
ast_log(LOG_ERROR, "Failed to set up CURL isntance for '%s'\n", public_key_url);
|
||||
ast_log(LOG_ERROR, "Failed to set up CURL isntance for '%s'\n", public_cert_url);
|
||||
fclose(public_key_file);
|
||||
return -1;
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, public_key_url);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, public_cert_url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, public_key_file);
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf);
|
||||
|
||||
@@ -182,7 +231,8 @@ int curl_public_key(const char *public_key_url, const char *path, struct curl_cb
|
||||
ast_log(LOG_ERROR, "%s\n", curl_errbuf);
|
||||
curl_easy_cleanup(curl);
|
||||
fclose(public_key_file);
|
||||
return -1;
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
@@ -191,9 +241,34 @@ int curl_public_key(const char *public_key_url, const char *path, struct curl_cb
|
||||
fclose(public_key_file);
|
||||
|
||||
if (http_code / 100 != 2) {
|
||||
ast_log(LOG_ERROR, "Failed to retrieve URL '%s': code %ld\n", public_key_url, http_code);
|
||||
return -1;
|
||||
ast_log(LOG_ERROR, "Failed to retrieve URL '%s': code %ld\n", public_cert_url, http_code);
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
serial = stir_shaken_get_serial_number_x509(tmp_filename);
|
||||
if (!serial) {
|
||||
ast_log(LOG_ERROR, "Failed to get serial from cert %s\n", tmp_filename);
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ast_asprintf(&filename, "%s/%s.pem", path, serial) < 0) {
|
||||
ast_log(LOG_ERROR, "Failed to allocate memory for new filename for temporary "
|
||||
"file %s after CURL\n", tmp_filename);
|
||||
ast_free(serial);
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ast_free(serial);
|
||||
|
||||
if (rename(tmp_filename, filename)) {
|
||||
ast_log(LOG_ERROR, "Failed to rename temporary file %s to %s after CURL\n", tmp_filename, filename);
|
||||
ast_free(filename);
|
||||
remove(tmp_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
Reference in New Issue
Block a user