diff --git a/res/res_crypto.c b/res/res_crypto.c index 8d6c536d11..2f7868cb62 100644 --- a/res/res_crypto.c +++ b/res/res_crypto.c @@ -34,6 +34,7 @@ #include "asterisk.h" #include /* for closedir, opendir, readdir, DIR */ +#include /* for fstat */ #include /* for ERR_print_errors_fp */ #include /* 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"); diff --git a/tests/test_crypto.c b/tests/test_crypto.c index 1eec181b99..848a562b36 100644 --- a/tests/test_crypto.c +++ b/tests/test_crypto.c @@ -40,6 +40,7 @@ #include "asterisk/file.h" #include +#include #include #include @@ -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;