aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/config_parser.h57
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/config.c216
-rw-r--r--src/config_parser.c238
4 files changed, 297 insertions, 215 deletions
diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h
new file mode 100644
index 00000000..e974917c
--- /dev/null
+++ b/include/libssh/config_parser.h
@@ -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_ */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fdb53baf..de66f056 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -163,6 +163,7 @@ set(libssh_SRCS
external/poly1305.c
external/sc25519.c
chachapoly.c
+ config_parser.c
)
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
diff --git a/src/config.c b/src/config.c
index 85ecd96a..4268545d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -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
*/
diff --git a/src/config_parser.c b/src/config_parser.c
new file mode 100644
index 00000000..ae2aa2c8
--- /dev/null
+++ b/src/config_parser.c
@@ -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;
+}