config: Move common parser functions to config_parser.c

This will allow the moved functions to be used in the server side
configuration parser implementation.

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Anderson Toshiyuki Sasaki
2019-02-22 13:06:49 +01:00
committed by Andreas Schneider
parent 19e886d6b1
commit 79049981a5
4 changed files with 297 additions and 215 deletions

View File

@@ -33,6 +33,7 @@
#include <stdbool.h>
#include <limits.h>
#include "libssh/config_parser.h"
#include "libssh/config.h"
#include "libssh/priv.h"
#include "libssh/session.h"
@@ -193,102 +194,6 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
return SOC_UNKNOWN;
}
static char *ssh_config_get_cmd(char **str) {
register char *c;
char *r;
/* Ignore leading spaces */
for (c = *str; *c; c++) {
if (! isblank(*c)) {
break;
}
}
if (*c == '\"') {
for (r = ++c; *c; c++) {
if (*c == '\"') {
*c = '\0';
goto out;
}
}
}
for (r = c; *c; c++) {
if (*c == '\n') {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static char *ssh_config_get_token(char **str) {
register char *c;
char *r;
c = ssh_config_get_cmd(str);
for (r = c; *c; c++) {
if (isblank(*c) || *c == '=') {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static long ssh_config_get_long(char **str, long notfound) {
char *p, *endp;
long i;
p = ssh_config_get_token(str);
if (p && *p) {
i = strtol(p, &endp, 10);
if (p == endp) {
return notfound;
}
return i;
}
return notfound;
}
static const char *ssh_config_get_str_tok(char **str, const char *def) {
char *p;
p = ssh_config_get_token(str);
if (p && *p) {
return p;
}
return def;
}
static int ssh_config_get_yesno(char **str, int notfound) {
const char *p;
p = ssh_config_get_str_tok(str, NULL);
if (p == NULL) {
return notfound;
}
if (strncasecmp(p, "yes", 3) == 0) {
return 1;
} else if (strncasecmp(p, "no", 2) == 0) {
return 0;
}
return notfound;
}
static void
local_parse_file(ssh_session session,
const char *filename,
@@ -384,125 +289,6 @@ ssh_config_match(char *value, const char *pattern, bool negate)
return result;
}
/* @brief Parse SSH URI in format [user@]host[:port] from the given string
*
* @param[in] tok String to parse
* @param[out] username Pointer to the location, where the new username will
* be stored or NULL if we do not care about the result.
* @param[out] hostname Pointer to the location, where the new hostname will
* be stored or NULL if we do not care about the result.
* @param[out] port Pointer to the location, where the new port will
* be stored or NULL if we do not care about the result.
*
* @returns SSH_OK if the provided string is in format of SSH URI,
* SSH_ERROR on failure
*/
static int
ssh_config_parse_uri(const char *tok,
char **username,
char **hostname,
char **port)
{
char *endp = NULL;
long port_n;
/* Sanitize inputs */
if (username != NULL) {
*username = NULL;
}
if (hostname != NULL) {
*hostname = NULL;
}
if (port != NULL) {
*port = NULL;
}
/* Username part (optional) */
endp = strchr(tok, '@');
if (endp != NULL) {
/* Zero-length username is not valid */
if (tok == endp) {
goto error;
}
if (username != NULL) {
*username = strndup(tok, endp - tok);
if (*username == NULL) {
goto error;
}
}
tok = endp + 1;
/* If there is second @ character, this does not look like our URI */
endp = strchr(tok, '@');
if (endp != NULL) {
goto error;
}
}
/* Hostname */
if (*tok == '[') {
/* IPv6 address is enclosed with square brackets */
tok++;
endp = strchr(tok, ']');
if (endp == NULL) {
goto error;
}
} else {
/* Hostnames or aliases expand to the last colon or to the end */
endp = strrchr(tok, ':');
if (endp == NULL) {
endp = strchr(tok, '\0');
}
}
if (tok == endp) {
/* Zero-length hostnames are not valid */
goto error;
}
if (hostname != NULL) {
*hostname = strndup(tok, endp - tok);
if (*hostname == NULL) {
goto error;
}
}
/* Skip also the closing bracket */
if (*endp == ']') {
endp++;
}
/* Port (optional) */
if (*endp != '\0') {
char *port_end = NULL;
/* Verify the port is valid positive number */
port_n = strtol(endp + 1, &port_end, 10);
if (port_n < 1 || *port_end != '\0') {
SSH_LOG(SSH_LOG_WARN, "Failed to parse port number."
" The value '%ld' is invalid or there are some"
" trailing characters: '%s'", port_n, port_end);
goto error;
}
if (port != NULL) {
*port = strdup(endp + 1);
if (*port == NULL) {
goto error;
}
}
}
return SSH_OK;
error:
if (username != NULL) {
SAFE_FREE(*username);
}
if (hostname != NULL) {
SAFE_FREE(*hostname);
}
if (port != NULL) {
SAFE_FREE(*port);
}
return SSH_ERROR;
}
/* @brief: Parse the ProxyJump configuration line and if parsing,
* stores the result in the configuration option
*/