1
1
Amends f818e63f8, which introduced the constants and matching of this
configuration option, but did not implement the handling of the values
which was causing the configuration parser failing for certain
configurations.

This commit exposes match_pattern_list() from match.c

Red Hat Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=1624425

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
Jakub Jelen 2018-09-04 13:46:37 +02:00 коммит произвёл Andreas Schneider
родитель 9f5f10552b
Коммит e9b44d26b1
3 изменённых файлов: 167 добавлений и 2 удалений

Просмотреть файл

@ -262,6 +262,8 @@ int compress_buffer(ssh_session session,ssh_buffer buf);
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
/* match.c */
int match_pattern_list(const char *string, const char *pattern,
unsigned int len, int dolower);
int match_hostname(const char *host, const char *pattern, unsigned int len);
/* connector.c */

Просмотреть файл

@ -30,6 +30,7 @@
#ifdef HAVE_GLOB_H
# include <glob.h>
#endif
#include <stdbool.h>
#include "libssh/priv.h"
#include "libssh/session.h"
@ -185,6 +186,32 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ NULL, SOC_UNKNOWN }
};
enum ssh_config_match_e {
MATCH_UNKNOWN = -1,
MATCH_ALL,
MATCH_CANONICAL,
MATCH_EXEC,
MATCH_HOST,
MATCH_ORIGINALHOST,
MATCH_USER,
MATCH_LOCALUSER
};
struct ssh_config_match_keyword_table_s {
const char *name;
enum ssh_config_match_e opcode;
};
static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[] = {
{ "all", MATCH_ALL },
{ "canonical", MATCH_CANONICAL },
{ "exec", MATCH_EXEC },
{ "host", MATCH_HOST },
{ "originalhost", MATCH_ORIGINALHOST },
{ "user", MATCH_USER },
{ "localuser", MATCH_LOCALUSER },
};
static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing, int seen[]);
@ -351,6 +378,40 @@ static void local_parse_glob(ssh_session session,
}
#endif /* HAVE_GLOB */
static enum ssh_config_match_e
ssh_config_get_match_opcode(const char *keyword)
{
size_t i;
for (i = 0; ssh_config_match_keyword_table[i].name != NULL; i++) {
if (strcasecmp(keyword, ssh_config_match_keyword_table[i].name) == 0) {
return ssh_config_match_keyword_table[i].opcode;
}
}
return MATCH_UNKNOWN;
}
static int
ssh_config_match(char *value, const char *pattern, bool negate)
{
int ok, result = 0;
char *lowervalue;
lowervalue = (value) ? ssh_lowercase(value) : NULL;
ok = match_pattern_list(lowervalue, pattern, strlen(pattern), 0);
if (ok <= 0 && negate == true) {
result = 1;
} else if (ok > 0 && negate == false) {
result = 1;
}
SSH_LOG(SSH_LOG_TRACE, "%s '%s' against pattern '%s'%s (ok=%d)",
result == 1 ? "Matched" : "Not matched", value, pattern,
negate == true ? " (negated)" : "", ok);
SAFE_FREE(lowervalue);
return result;
}
static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing, int seen[]) {
enum ssh_config_opcode_e opcode;
@ -384,7 +445,10 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
}
opcode = ssh_config_get_opcode(keyword);
if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_INCLUDE &&
if (*parsing == 1 &&
opcode != SOC_HOST &&
opcode != SOC_MATCH &&
opcode != SOC_INCLUDE &&
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
if (seen[opcode] != 0) {
SAFE_FREE(x);
@ -405,6 +469,105 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
#endif /* HAVE_GLOB */
}
break;
case SOC_MATCH: {
bool negate;
int result = 1, args = 0;
enum ssh_config_match_e opt;
*parsing = 0;
do {
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
break;
}
args++;
SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'",
count, p);
/* If the option is prefixed with ! the result should be negated */
negate = false;
if (p[0] == '!') {
negate = true;
p++;
}
opt = ssh_config_get_match_opcode(p);
switch (opt) {
case MATCH_ALL:
p = ssh_config_get_str_tok(&s, NULL);
if (args == 1 && (p == NULL || p[0] == '\0')) {
/* The first argument and end of line */
if (negate == true) {
result = 0;
}
break;
}
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match all can not be combined with "
"other Match attributes", count);
SAFE_FREE(x);
return -1;
case MATCH_EXEC:
case MATCH_ORIGINALHOST:
case MATCH_LOCALUSER:
/* Skip one argument */
p = ssh_config_get_str_tok(&s, NULL);
args++;
FALL_THROUGH;
case MATCH_CANONICAL:
SSH_LOG(SSH_LOG_WARN, "line: %d: Unsupported Match keyword "
"'%s', Ignoring\n", count, p);
result = 0;
break;
case MATCH_HOST:
/* Here we match only one argument */
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match host keyword "
"requires argument", count);
SAFE_FREE(x);
return -1;
}
result &= ssh_config_match(session->opts.host, p, negate);
args++;
break;
case MATCH_USER:
/* Here we match only one argument */
p = ssh_config_get_str_tok(&s, NULL);
if (p == NULL || p[0] == '\0') {
ssh_set_error(session, SSH_FATAL,
"line %d: ERROR - Match user keyword "
"requires argument", count);
SAFE_FREE(x);
return -1;
}
result &= ssh_config_match(session->opts.username, p, negate);
args++;
break;
case MATCH_UNKNOWN:
default:
ssh_set_error(session, SSH_FATAL,
"ERROR - Unknown argument '%s' for Match keyword", p);
SAFE_FREE(x);
return -1;
}
} while (p != NULL && p[0] != '\0');
if (args < 1) {
ssh_set_error(session, SSH_FATAL,
"ERROR - Match keyword requires an argument");
SAFE_FREE(x);
return -1;
}
*parsing = result;
break;
}
case SOC_HOST: {
int ok = 0, result = -1;

Просмотреть файл

@ -119,7 +119,7 @@ static int match_pattern(const char *s, const char *pattern) {
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there is
* no match at all.
*/
static int match_pattern_list(const char *string, const char *pattern,
int match_pattern_list(const char *string, const char *pattern,
unsigned int len, int dolower) {
char sub[1024];
int negated;