mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-09-25 02:33:51 +08:00
Add MOSQUITTO_UNSAFE_ALLOW_SYMLINKS env var
Setting this environment variable allows sensitive files to be read through symlinks. Closes #3461. Thanks to Jeff Cutsinger
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
|
||||
# Broker
|
||||
- Fix PUID/PGID checking for docker
|
||||
- Add MOSQUITTO_UNSAFE_ALLOW_SYMLINKS environment variable to allow the
|
||||
restrictions on reading files through symlinks to be lifted in safe
|
||||
environments like kubernetes. Closes #3461.
|
||||
|
||||
|
||||
2.1.0 - 2026-01-29
|
||||
|
||||
@@ -166,7 +166,10 @@ FILE *mosquitto_fopen(const char *path, const char *mode, bool restrict_read)
|
||||
|
||||
old_mask = umask(0077);
|
||||
|
||||
int open_flags = O_NOFOLLOW;
|
||||
int open_flags = 0;
|
||||
if(!getenv("MOSQUITTO_UNSAFE_ALLOW_SYMLINKS")){
|
||||
open_flags |= O_NOFOLLOW;
|
||||
}
|
||||
for(size_t i = 0; i<strlen(mode); i++){
|
||||
if(mode[i] == 'r'){
|
||||
open_flags |= O_RDONLY;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<varlistentry>
|
||||
<term><envar>MOSQUITTO_UNSAFE_ALLOW_SYMLINKS</envar></term>
|
||||
<listitem>
|
||||
<para>
|
||||
By default, sensitive file with a path including a
|
||||
symbolic link will be refused to be loaded. Set this
|
||||
environment variable to any value to allow load files
|
||||
through symbolic links. Note that making use of this
|
||||
variable could expose you to symlink attacks and so it
|
||||
should only be used in cases where you are absolutely
|
||||
sure this is not a risk.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -974,6 +974,13 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Environment Variables</title>
|
||||
<variablelist>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/env-var-mosquitto-unsafe-allow-symlinks.xml" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Files</title>
|
||||
<variablelist>
|
||||
|
||||
@@ -267,6 +267,14 @@
|
||||
</refsect1>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/section-exit-status.xml" />
|
||||
|
||||
<refsect1>
|
||||
<title>Environment Variables</title>
|
||||
<variablelist>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/env-var-mosquitto-unsafe-allow-symlinks.xml" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/section-bugs.xml" />
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -179,6 +179,13 @@
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Environment Variables</title>
|
||||
<variablelist>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/env-var-mosquitto-unsafe-allow-symlinks.xml" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="common/section-bugs.xml" />
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -327,6 +327,9 @@ static void report_features(void)
|
||||
#else
|
||||
log__printf(NULL, MOSQ_LOG_INFO, "Websockets support NOT available.");
|
||||
#endif
|
||||
if(getenv("MOSQUITTO_UNSAFE_ALLOW_SYMLINKS")){
|
||||
log__printf(NULL, MOSQ_LOG_NOTICE, "MOSQUITTO_UNSAFE_ALLOW_SYMLINKS is set, loading of sensitive files through symbolic links is allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_executable(libcommon-test
|
||||
base64_test.c
|
||||
file_test.c
|
||||
property_add.c
|
||||
property_value.c
|
||||
strings_test.c
|
||||
|
||||
@@ -14,6 +14,7 @@ endif
|
||||
|
||||
TEST_OBJS = \
|
||||
base64_test.o \
|
||||
file_test.o \
|
||||
property_add.o \
|
||||
property_value.o \
|
||||
strings_test.o \
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <CUnit/Basic.h>
|
||||
#ifndef WIN32
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mosquitto.h"
|
||||
|
||||
#define ALLOW_SYMLINKS "MOSQUITTO_UNSAFE_ALLOW_SYMLINKS"
|
||||
|
||||
#ifndef WIN32
|
||||
static bool symlink_create(void)
|
||||
{
|
||||
FILE *fptr = mosquitto_fopen("libcommon_test", "rb", false);
|
||||
|
||||
/* Verify we are in the right path */
|
||||
CU_ASSERT_PTR_NOT_NULL(fptr);
|
||||
if(!fptr){
|
||||
return false;
|
||||
}
|
||||
fclose(fptr);
|
||||
|
||||
int rc = symlink("libcommon_test", "libcommon_symlink");
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
return rc == 0?true:false;
|
||||
}
|
||||
|
||||
|
||||
static void symlink_remove(void)
|
||||
{
|
||||
unlink("libcommon_symlink");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
static void TEST_restrict_read_default(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
|
||||
if(!symlink_create()){
|
||||
return;
|
||||
}
|
||||
unsetenv(ALLOW_SYMLINKS);
|
||||
|
||||
/* No restrict read, so symlink ok */
|
||||
fptr = mosquitto_fopen("libcommon_symlink", "rb", false);
|
||||
CU_ASSERT_PTR_NOT_NULL(fptr);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* Restricted read, so symlink not allowed */
|
||||
fptr = mosquitto_fopen("libcommon_symlink", "rb", true);
|
||||
CU_ASSERT_PTR_NULL(fptr);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
symlink_remove();
|
||||
}
|
||||
|
||||
|
||||
static void TEST_restrict_read_with_symlinks(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
|
||||
if(!symlink_create()){
|
||||
return;
|
||||
}
|
||||
|
||||
int rc = setenv(ALLOW_SYMLINKS, "1", true);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
/* No restrict read, so symlink ok */
|
||||
fptr = mosquitto_fopen("libcommon_symlink", "rb", false);
|
||||
CU_ASSERT_PTR_NOT_NULL(fptr);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* Restricted read but with override so symlink ok */
|
||||
fptr = mosquitto_fopen("libcommon_symlink", "rb", true);
|
||||
CU_ASSERT_PTR_NOT_NULL(fptr);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
symlink_remove();
|
||||
unsetenv(ALLOW_SYMLINKS);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* TEST SUITE SETUP
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
int init_file_tests(void)
|
||||
{
|
||||
CU_pSuite test_suite = NULL;
|
||||
|
||||
test_suite = CU_add_suite("file", NULL, NULL);
|
||||
if(!test_suite){
|
||||
printf("Error adding CUnit file test suite.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(0
|
||||
#ifndef WIN32
|
||||
|| !CU_add_test(test_suite, "Restrict read default", TEST_restrict_read_default)
|
||||
|| !CU_add_test(test_suite, "Restrict read with symlinks", TEST_restrict_read_with_symlinks)
|
||||
#endif
|
||||
){
|
||||
|
||||
printf("Error adding file CUnit tests.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
int init_base64_tests(void);
|
||||
int init_file_tests(void);
|
||||
int init_property_add_tests(void);
|
||||
int init_property_value_tests(void);
|
||||
int init_strings_tests(void);
|
||||
@@ -27,6 +28,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(0
|
||||
|| init_base64_tests()
|
||||
|| init_file_tests()
|
||||
|| init_property_add_tests()
|
||||
|| init_property_value_tests()
|
||||
|| init_strings_tests()
|
||||
|
||||
Reference in New Issue
Block a user