]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add existence and readablity checks for tls related files 88/1788/1
authorGeorge Joseph <george.joseph@fairview5.com>
Tue, 8 Dec 2015 23:49:20 +0000 (16:49 -0700)
committerGeorge Joseph <george.joseph@fairview5.com>
Tue, 8 Dec 2015 23:49:20 +0000 (16:49 -0700)
Both transport and endpoint now check for the existence and readability
of tls certificate and key files before passing them on to pjproject.
This will cause the object to not load rather than waiting for pjproject
to discover that there's a problem when a session is attempted.

NOTE: chan_sip also uses ast_rtp_dtls_cfg_parse but it's located
in build_peer which is gigantic and I didn't want to disturb it.
Error messages will emit but it won't interrupt chan_sip loading.

ASTERISK-25618 #close

Change-Id: Ie43f2c1d653ac1fda6a6f6faecb7c2ebadaf47c9
Reported-by: George Joseph
Tested-by: George Joseph
include/asterisk/utils.h
main/rtp_engine.c
main/utils.c
res/res_pjsip/config_transport.c
res/res_pjsip/pjsip_configuration.c

index 664e347cf2657284411be26b7a3916c6f9c216c1..832500c31e7bd423d3aa8526e3b0d87a4f49b4b2 100644 (file)
@@ -1089,4 +1089,14 @@ char *ast_crypt_encrypt(const char *key);
  */
 int ast_crypt_validate(const char *key, const char *expected);
 
+/*
+ * \brief Test that a file exists and is readable by the effective user.
+ * \since 13.7.0
+ *
+ * \param filename File to test.
+ * \return True (non-zero) if the file exists and is readable.
+ * \return False (zero) if the file either doesn't exists or is not readable.
+ */
+int ast_file_is_readable(const char *filename);
+
 #endif /* _ASTERISK_UTILS_H */
index 57a3ef354aac650bbc1948cb27bb1d482d62e530..beda8cd745651d0ae67531ca5935446853973211 100644 (file)
@@ -1634,18 +1634,34 @@ int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name,
                }
        } else if (!strcasecmp(name, "dtlscertfile")) {
                ast_free(dtls_cfg->certfile);
+               if (!ast_file_is_readable(value)) {
+                       ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
+                       return -1;
+               }
                dtls_cfg->certfile = ast_strdup(value);
        } else if (!strcasecmp(name, "dtlsprivatekey")) {
                ast_free(dtls_cfg->pvtfile);
+               if (!ast_file_is_readable(value)) {
+                       ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
+                       return -1;
+               }
                dtls_cfg->pvtfile = ast_strdup(value);
        } else if (!strcasecmp(name, "dtlscipher")) {
                ast_free(dtls_cfg->cipher);
                dtls_cfg->cipher = ast_strdup(value);
        } else if (!strcasecmp(name, "dtlscafile")) {
                ast_free(dtls_cfg->cafile);
+               if (!ast_file_is_readable(value)) {
+                       ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
+                       return -1;
+               }
                dtls_cfg->cafile = ast_strdup(value);
        } else if (!strcasecmp(name, "dtlscapath") || !strcasecmp(name, "dtlscadir")) {
                ast_free(dtls_cfg->capath);
+               if (!ast_file_is_readable(value)) {
+                       ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
+                       return -1;
+               }
                dtls_cfg->capath = ast_strdup(value);
        } else if (!strcasecmp(name, "dtlssetup")) {
                if (!strcasecmp(value, "active")) {
index ffef3ac976b2a9e7a207d92c96f64110ee8236a8..3eeafed4fb92ea8866f32e708115a92df5789fb2 100644 (file)
@@ -2932,3 +2932,20 @@ int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
 {
        return memcmp(eid1, eid2, sizeof(*eid1));
 }
+
+int ast_file_is_readable(const char *filename)
+{
+#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
+#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
+#define eaccess euidaccess
+#endif
+       return eaccess(filename, R_OK) == 0;
+#else
+       int fd = open(filename, O_RDONLY |  O_NONBLOCK);
+       if (fd < 0) {
+               return 0;
+       }
+       close(fd);
+       return 1;
+#endif
+}
index e2f0c7f4347cfac0db759005bf25017569904774..d8ece1509441e114a2fa97c8531d885bb6c4ba4c 100644 (file)
@@ -27,6 +27,7 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/sorcery.h"
 #include "asterisk/acl.h"
+#include "asterisk/utils.h"
 #include "include/res_pjsip_private.h"
 #include "asterisk/http_websocket.h"
 
@@ -224,8 +225,22 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
                                        ast_sorcery_object_get_id(obj));
                        return -1;
                }
+               if (!ast_strlen_zero(transport->ca_list_file)) {
+                       if (!ast_file_is_readable(transport->ca_list_file)) {
+                               ast_log(LOG_ERROR, "Transport: %s: ca_list_file %s is either missing or not readable\n",
+                                               ast_sorcery_object_get_id(obj), transport->ca_list_file);
+                               return -1;
+                       }
+               }
                transport->tls.ca_list_file = pj_str((char*)transport->ca_list_file);
 #ifdef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2
+               if (!ast_strlen_zero(transport->ca_list_path)) {
+                       if (!ast_file_is_readable(transport->ca_list_path)) {
+                               ast_log(LOG_ERROR, "Transport: %s: ca_list_path %s is either missing or not readable\n",
+                                               ast_sorcery_object_get_id(obj), transport->ca_list_path);
+                               return -1;
+                       }
+               }
                transport->tls.ca_list_path = pj_str((char*)transport->ca_list_path);
 #else
                if (!ast_strlen_zero(transport->ca_list_path)) {
@@ -233,7 +248,21 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
                                        "support the 'ca_list_path' option. Please upgrade to version 2.4 or later.\n");
                }
 #endif
+               if (!ast_strlen_zero(transport->cert_file)) {
+                       if (!ast_file_is_readable(transport->cert_file)) {
+                               ast_log(LOG_ERROR, "Transport: %s: cert_file %s is either missing or not readable\n",
+                                               ast_sorcery_object_get_id(obj), transport->cert_file);
+                               return -1;
+                       }
+               }
                transport->tls.cert_file = pj_str((char*)transport->cert_file);
+               if (!ast_strlen_zero(transport->privkey_file)) {
+                       if (!ast_file_is_readable(transport->privkey_file)) {
+                               ast_log(LOG_ERROR, "Transport: %s: privkey_file %s is either missing or not readable\n",
+                                               ast_sorcery_object_get_id(obj), transport->privkey_file);
+                               return -1;
+                       }
+               }
                transport->tls.privkey_file = pj_str((char*)transport->privkey_file);
                transport->tls.password = pj_str((char*)transport->password);
                set_qos(transport, &transport->tls.qos_params);
index 1b0d6e2e94e366dc4c4b24b6a9d790c4dd65750d..746a45742e84af95168be553f884c77e72eaf8ac 100644 (file)
@@ -683,7 +683,7 @@ static int media_encryption_handler(const struct aco_option *opt, struct ast_var
                endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_SDES;
        } else if (!strcasecmp("dtls", var->value)) {
                endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
-               ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, "dtlsenable", "yes");
+               return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, "dtlsenable", "yes");
        } else {
                return -1;
        }