res_crypto: handle unsafe private key files

ASTERISK-30213 #close

Change-Id: I4a77143d41615b7c4fc25bb1251c0a9cb87b417a
This commit is contained in:
Philip Prindeville 2022-09-16 12:45:55 -06:00 committed by Friendly Automation
parent 14e1ba19ee
commit 95bb23ce4c
2 changed files with 31 additions and 1 deletions

View File

@ -34,6 +34,7 @@
#include "asterisk.h"
#include <dirent.h> /* for closedir, opendir, readdir, DIR */
#include <sys/stat.h> /* for fstat */
#include <openssl/err.h> /* for ERR_print_errors_fp */
#include <openssl/ssl.h> /* for NID_sha1, RSA */
@ -173,7 +174,7 @@ struct ast_key * AST_OPTIONAL_API_NAME(ast_key_get)(const char *kname, int ktype
*/
static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
{
int ktype = 0, found = 0;
int n, ktype = 0, found = 0;
const char *c = NULL;
char ffname[256];
unsigned char digest[MD5_DIGEST_LENGTH];
@ -182,6 +183,7 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd,
EVP_MD_CTX *ctx = NULL;
struct ast_key *key;
static int notice = 0;
struct stat st;
size_t fnamelen = strlen(fname);
/* Make sure its name is a public or private key */
@ -202,6 +204,27 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd,
return NULL;
}
n = fstat(fileno(f), &st);
if (n != 0) {
ast_log(LOG_ERROR, "Unable to stat key file: %s: %s\n", ffname, strerror(errno));
fclose(f);
return NULL;
}
if (!S_ISREG(st.st_mode)) {
ast_log(LOG_ERROR, "Key file is not a regular file: %s\n", ffname);
fclose(f);
return NULL;
}
/* only user read or read/write modes allowed */
if (ktype == AST_KEY_PRIVATE &&
((st.st_mode & ALLPERMS) & ~(S_IRUSR | S_IWUSR)) != 0) {
ast_log(LOG_ERROR, "Private key file has bad permissions: %s: %#4o\n", ffname, st.st_mode & ALLPERMS);
fclose(f);
return NULL;
}
ctx = EVP_MD_CTX_create();
if (ctx == NULL) {
ast_log(LOG_ERROR, "Out of memory\n");

View File

@ -40,6 +40,7 @@
#include "asterisk/file.h"
#include <assert.h>
#include <sys/stat.h>
#include <linux/limits.h>
#include <openssl/evp.h>
@ -117,6 +118,9 @@ AST_TEST_DEFINE(crypto_rsa_encrypt)
push_key_dir((const char *)key_dir);
snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
/* because git doesn't preserve permissions */
(void)chmod(priv, 0400);
if (ast_crypto_reload() != 1) {
ast_test_status_update(test, "Couldn't force crypto reload\n");
goto cleanup;
@ -414,6 +418,9 @@ AST_TEST_DEFINE(crypto_verify)
push_key_dir((const char *)key_dir);
snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
/* because git doesn't preserve permissions */
(void)chmod(priv, 0400);
if (ast_crypto_reload() != 1) {
ast_test_status_update(test, "Couldn't force crypto reload\n");
goto cleanup;