]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_crypto: handle unsafe private key files
authorPhilip Prindeville <philipp@redfish-solutions.com>
Fri, 16 Sep 2022 18:45:55 +0000 (12:45 -0600)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Fri, 14 Oct 2022 15:00:53 +0000 (10:00 -0500)
ASTERISK-30213 #close

Change-Id: I4a77143d41615b7c4fc25bb1251c0a9cb87b417a

res/res_crypto.c
tests/test_crypto.c

index 8d6c536d1103d6ee61c829f44a4387d387453a43..2f7868cb625c9e92bc1fdfb38f94f96f3eb767ec 100644 (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");
index 1eec181b99fa7c9ec2186edaaa41912e5da7d2be..848a562b3676050b5a86ef8f2073a49fba995585 100644 (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;