x509_crt: handle properly broken links when looking for certificates

On non-windows environments, when loading certificates from a given
path through mbedtls_x509_crt_parse_path() function, if a symbolic
link is found and is broken (meaning the target file don't exists),
the function is returning MBEDTLS_ERR_X509_FILE_IO_ERROR which is
not honoring the default behavior of just skip the bad certificate file
and increase the counter of wrong files.

The problem have been raised many times in our open source project
called Fluent Bit which depends on MbedTLS:

https://github.com/fluent/fluent-bit/issues/843#issuecomment-486388209

The expected behavior is that if a simple certificate cannot be processed,
it should just be skipped.

This patch implements a workaround with lstat(2) and stat(2) to determinate
first if the entry found in the directory is a symbolic link or not, if is
a simbolic link, do a proper stat(2) for the target file, otherwise process
normally. Upon find a broken symbolic link it will increase the counter of
not processed certificates.

Signed-off-by: Eduardo Silva <eduardo@treaure-data.com>
This commit is contained in:
Eduardo Silva 2019-04-25 10:43:26 -06:00 committed by Dave Rodgman
parent d5b1eb51db
commit e1bfffc4f6

View file

@ -81,6 +81,7 @@
#else
#include <dirent.h>
#endif /* __MBED__ */
#include <errno.h>
#endif /* !_WIN32 || EFIX64 || EFI32 */
#endif
@ -1655,10 +1656,39 @@ cleanup:
ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
goto cleanup;
}
else if( stat( entry_name, &sb ) == -1 )
else
{
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
goto cleanup;
/* determinate if the file entry could be a link, using lstat(2)
* is safer than just stat(2), otherwise a broken link will
* give us a false positive. */
if( lstat( entry_name, &sb ) == -1 )
{
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
goto cleanup;
}
/* if the file is a symbolic link, we need to validate the real
* information using stat(2). */
if( S_ISLNK( sb.st_mode ) )
{
/* if stat(2) fails it could be a broken link or a generic
* error, if the link is broken, just report it as a
* certificate that could not be processed, otherwise
* just set a MBEDTLS_ERR_X509_FILE_IO_ERROR. */
if( stat( entry_name, &sb ) == -1 )
{
if( errno == ENOENT )
{
/* Broken link */
ret++;
}
else
{
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
goto cleanup;
}
}
}
}
if( !S_ISREG( sb.st_mode ) )