mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-12 11:10:28 +09:00
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:
committed by
Andreas Schneider
parent
19e886d6b1
commit
79049981a5
57
include/libssh/config_parser.h
Normal file
57
include/libssh/config_parser.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* config_parser.h - Common configuration file parser functions
|
||||||
|
*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 by Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||||
|
*
|
||||||
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
* MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_PARSER_H_
|
||||||
|
#define CONFIG_PARSER_H_
|
||||||
|
|
||||||
|
char *ssh_config_get_cmd(char **str);
|
||||||
|
|
||||||
|
char *ssh_config_get_token(char **str);
|
||||||
|
|
||||||
|
long ssh_config_get_long(char **str, long notfound);
|
||||||
|
|
||||||
|
const char *ssh_config_get_str_tok(char **str, const char *def);
|
||||||
|
|
||||||
|
int ssh_config_get_yesno(char **str, int notfound);
|
||||||
|
|
||||||
|
/* @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
|
||||||
|
*/
|
||||||
|
int ssh_config_parse_uri(const char *tok,
|
||||||
|
char **username,
|
||||||
|
char **hostname,
|
||||||
|
char **port);
|
||||||
|
|
||||||
|
#endif /* LIBSSH_CONFIG_H_ */
|
||||||
@@ -163,6 +163,7 @@ set(libssh_SRCS
|
|||||||
external/poly1305.c
|
external/poly1305.c
|
||||||
external/sc25519.c
|
external/sc25519.c
|
||||||
chachapoly.c
|
chachapoly.c
|
||||||
|
config_parser.c
|
||||||
)
|
)
|
||||||
|
|
||||||
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
|
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
|
||||||
|
|||||||
216
src/config.c
216
src/config.c
@@ -33,6 +33,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "libssh/config_parser.h"
|
||||||
#include "libssh/config.h"
|
#include "libssh/config.h"
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
@@ -193,102 +194,6 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
|
|||||||
return SOC_UNKNOWN;
|
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
|
static void
|
||||||
local_parse_file(ssh_session session,
|
local_parse_file(ssh_session session,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
@@ -384,125 +289,6 @@ ssh_config_match(char *value, const char *pattern, bool negate)
|
|||||||
return result;
|
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,
|
/* @brief: Parse the ProxyJump configuration line and if parsing,
|
||||||
* stores the result in the configuration option
|
* stores the result in the configuration option
|
||||||
*/
|
*/
|
||||||
|
|||||||
238
src/config_parser.c
Normal file
238
src/config_parser.c
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* config_parser.c - Common configuration file parser functions
|
||||||
|
*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||||
|
*
|
||||||
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
* MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "libssh/config_parser.h"
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user