config: Avoid infinite recursion when using Include

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2021-11-08 12:19:33 +01:00
parent 99c6eb305e
commit 227f416183
2 changed files with 46 additions and 22 deletions

View File

@@ -189,18 +189,29 @@ ssh_bind_config_parse_line(ssh_bind bind,
const char *line, const char *line,
unsigned int count, unsigned int count,
uint32_t *parser_flags, uint32_t *parser_flags,
uint8_t *seen); uint8_t *seen,
unsigned int depth);
static void local_parse_file(ssh_bind bind, #define LIBSSH_BIND_CONF_MAX_DEPTH 16
const char *filename, static void
uint32_t *parser_flags, local_parse_file(ssh_bind bind,
uint8_t *seen) const char *filename,
uint32_t *parser_flags,
uint8_t *seen,
unsigned int depth)
{ {
FILE *f; FILE *f;
char line[MAX_LINE_SIZE] = {0}; char line[MAX_LINE_SIZE] = {0};
unsigned int count = 0; unsigned int count = 0;
int rv; int rv;
if (depth > LIBSSH_BIND_CONF_MAX_DEPTH) {
ssh_set_error(bind, SSH_FATAL,
"ERROR - Too many levels of configuration includes "
"when processing file '%s'", filename);
return;
}
f = fopen(filename, "r"); f = fopen(filename, "r");
if (f == NULL) { if (f == NULL) {
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load", SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
@@ -213,7 +224,7 @@ static void local_parse_file(ssh_bind bind,
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
rv = ssh_bind_config_parse_line(bind, line, count, parser_flags, seen); rv = ssh_bind_config_parse_line(bind, line, count, parser_flags, seen, depth);
if (rv < 0) { if (rv < 0) {
fclose(f); fclose(f);
return; return;
@@ -228,7 +239,8 @@ static void local_parse_file(ssh_bind bind,
static void local_parse_glob(ssh_bind bind, static void local_parse_glob(ssh_bind bind,
const char *fileglob, const char *fileglob,
uint32_t *parser_flags, uint32_t *parser_flags,
uint8_t *seen) uint8_t *seen,
unsigned int depth)
{ {
glob_t globbuf = { glob_t globbuf = {
.gl_flags = 0, .gl_flags = 0,
@@ -248,7 +260,7 @@ static void local_parse_glob(ssh_bind bind,
} }
for (i = 0; i < globbuf.gl_pathc; i++) { for (i = 0; i < globbuf.gl_pathc; i++) {
local_parse_file(bind, globbuf.gl_pathv[i], parser_flags, seen); local_parse_file(bind, globbuf.gl_pathv[i], parser_flags, seen, depth);
} }
globfree(&globbuf); globfree(&globbuf);
@@ -274,7 +286,8 @@ ssh_bind_config_parse_line(ssh_bind bind,
const char *line, const char *line,
unsigned int count, unsigned int count,
uint32_t *parser_flags, uint32_t *parser_flags,
uint8_t *seen) uint8_t *seen,
unsigned int depth)
{ {
enum ssh_bind_config_opcode_e opcode; enum ssh_bind_config_opcode_e opcode;
const char *p = NULL; const char *p = NULL;
@@ -333,9 +346,9 @@ ssh_bind_config_parse_line(ssh_bind bind,
p = ssh_config_get_str_tok(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && (*parser_flags & PARSING)) { if (p && (*parser_flags & PARSING)) {
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
local_parse_glob(bind, p, parser_flags, seen); local_parse_glob(bind, p, parser_flags, seen, depth + 1);
#else #else
local_parse_file(bind, p, parser_flags, seen); local_parse_file(bind, p, parser_flags, seen, depth + 1);
#endif /* HAVE_GLOB */ #endif /* HAVE_GLOB */
} }
break; break;
@@ -628,7 +641,7 @@ int ssh_bind_config_parse_file(ssh_bind bind, const char *filename)
parser_flags = PARSING; parser_flags = PARSING;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
rv = ssh_bind_config_parse_line(bind, line, count, &parser_flags, seen); rv = ssh_bind_config_parse_line(bind, line, count, &parser_flags, seen, 0);
if (rv) { if (rv) {
fclose(f); fclose(f);
return -1; return -1;

View File

@@ -191,7 +191,7 @@ static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[]
}; };
static int ssh_config_parse_line(ssh_session session, const char *line, static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing); unsigned int count, int *parsing, unsigned int depth);
static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) { static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
int i; int i;
@@ -205,16 +205,25 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
return SOC_UNKNOWN; return SOC_UNKNOWN;
} }
#define LIBSSH_CONF_MAX_DEPTH 16
static void static void
local_parse_file(ssh_session session, local_parse_file(ssh_session session,
const char *filename, const char *filename,
int *parsing) int *parsing,
unsigned int depth)
{ {
FILE *f; FILE *f;
char line[MAX_LINE_SIZE] = {0}; char line[MAX_LINE_SIZE] = {0};
unsigned int count = 0; unsigned int count = 0;
int rv; int rv;
if (depth > LIBSSH_CONF_MAX_DEPTH) {
ssh_set_error(session, SSH_FATAL,
"ERROR - Too many levels of configuration includes "
"when processing file '%s'", filename);
return;
}
f = fopen(filename, "r"); f = fopen(filename, "r");
if (f == NULL) { if (f == NULL) {
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load", SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
@@ -225,7 +234,7 @@ local_parse_file(ssh_session session,
SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename); SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename);
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
rv = ssh_config_parse_line(session, line, count, parsing); rv = ssh_config_parse_line(session, line, count, parsing, depth);
if (rv < 0) { if (rv < 0) {
fclose(f); fclose(f);
return; return;
@@ -239,7 +248,8 @@ local_parse_file(ssh_session session,
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
static void local_parse_glob(ssh_session session, static void local_parse_glob(ssh_session session,
const char *fileglob, const char *fileglob,
int *parsing) int *parsing,
unsigned int depth)
{ {
glob_t globbuf = { glob_t globbuf = {
.gl_flags = 0, .gl_flags = 0,
@@ -259,7 +269,7 @@ static void local_parse_glob(ssh_session session,
} }
for (i = 0; i < globbuf.gl_pathc; i++) { for (i = 0; i < globbuf.gl_pathc; i++) {
local_parse_file(session, globbuf.gl_pathv[i], parsing); local_parse_file(session, globbuf.gl_pathv[i], parsing, depth);
} }
globfree(&globbuf); globfree(&globbuf);
@@ -513,7 +523,8 @@ static int
ssh_config_parse_line(ssh_session session, ssh_config_parse_line(ssh_session session,
const char *line, const char *line,
unsigned int count, unsigned int count,
int *parsing) int *parsing,
unsigned int depth)
{ {
enum ssh_config_opcode_e opcode; enum ssh_config_opcode_e opcode;
const char *p = NULL, *p2 = NULL; const char *p = NULL, *p2 = NULL;
@@ -573,9 +584,9 @@ ssh_config_parse_line(ssh_session session,
p = ssh_config_get_str_tok(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
local_parse_glob(session, p, parsing); local_parse_glob(session, p, parsing, depth + 1);
#else #else
local_parse_file(session, p, parsing); local_parse_file(session, p, parsing, depth + 1);
#endif /* HAVE_GLOB */ #endif /* HAVE_GLOB */
} }
break; break;
@@ -1163,7 +1174,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename)
parsing = 1; parsing = 1;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
rv = ssh_config_parse_line(session, line, count, &parsing); rv = ssh_config_parse_line(session, line, count, &parsing, 0);
if (rv < 0) { if (rv < 0) {
fclose(f); fclose(f);
return -1; return -1;
@@ -1215,7 +1226,7 @@ int ssh_config_parse_string(ssh_session session, const char *input)
memcpy(line, line_start, line_len); memcpy(line, line_start, line_len);
line[line_len] = '\0'; line[line_len] = '\0';
SSH_LOG(SSH_LOG_DEBUG, "Line %u: %s", line_num, line); SSH_LOG(SSH_LOG_DEBUG, "Line %u: %s", line_num, line);
rv = ssh_config_parse_line(session, line, line_num, &parsing); rv = ssh_config_parse_line(session, line, line_num, &parsing, 0);
if (rv < 0) { if (rv < 0) {
return SSH_ERROR; return SSH_ERROR;
} }