summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Joseph <george.joseph@fairview5.com>2015-12-08 16:49:20 -0700
committerGeorge Joseph <george.joseph@fairview5.com>2015-12-08 18:04:33 -0600
commita9874345648dbcf66eefecc8fc2ccaba93fa216e (patch)
treebf31fa3ebc0c77116c6fafce1e3ddca1f836c175
parent4cf470c70a7d6038355ce627918069f42a64fc22 (diff)
res_pjsip: Add existence and readablity checks for tls related files
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
-rw-r--r--include/asterisk/utils.h10
-rw-r--r--main/rtp_engine.c16
-rw-r--r--main/utils.c17
-rw-r--r--res/res_pjsip/config_transport.c29
-rw-r--r--res/res_pjsip/pjsip_configuration.c2
5 files changed, 73 insertions, 1 deletions
diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h
index 664e347cf..832500c31 100644
--- a/include/asterisk/utils.h
+++ b/include/asterisk/utils.h
@@ -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 */
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 32909090f..24e56b49f 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -2118,18 +2118,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")) {
diff --git a/main/utils.c b/main/utils.c
index ba1a07ca2..74932b8c2 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -2927,3 +2927,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
+}
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index e2f0c7f43..d8ece1509 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -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);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 3bb086945..72f896ad0 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -680,7 +680,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;
}