|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* config_parser.c - Common configuration file parser functions
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This file is part of the SSH Library
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is free software; you can redistribute it and/or modify
|
|
Packit Service |
31306d |
* it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
31306d |
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
|
Packit Service |
31306d |
* option) any later version.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is distributed in the hope that it will be useful, but
|
|
Packit Service |
31306d |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit Service |
31306d |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
Packit Service |
31306d |
* License for more details.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
31306d |
* along with the SSH Library; see the file COPYING. If not, write to
|
|
Packit Service |
31306d |
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
Packit Service |
31306d |
* MA 02111-1307, USA.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "config.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include <ctype.h>
|
|
Packit Service |
31306d |
#include <stdio.h>
|
|
Packit Service |
31306d |
#include <string.h>
|
|
Packit Service |
31306d |
#include <stdlib.h>
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "libssh/config_parser.h"
|
|
Packit Service |
31306d |
#include "libssh/priv.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
char *ssh_config_get_cmd(char **str)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
register char *c;
|
|
Packit Service |
31306d |
char *r;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Ignore leading spaces */
|
|
Packit Service |
31306d |
for (c = *str; *c; c++) {
|
|
Packit Service |
31306d |
if (! isblank(*c)) {
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (*c == '\"') {
|
|
Packit Service |
31306d |
for (r = ++c; *c; c++) {
|
|
Packit Service |
31306d |
if (*c == '\"') {
|
|
Packit Service |
31306d |
*c = '\0';
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (r = c; *c; c++) {
|
|
Packit Service |
31306d |
if (*c == '\n') {
|
|
Packit Service |
31306d |
*c = '\0';
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
*str = c + 1;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return r;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
char *ssh_config_get_token(char **str)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
register char *c;
|
|
Packit Service |
31306d |
char *r;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
c = ssh_config_get_cmd(str);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (r = c; *c; c++) {
|
|
Packit Service |
31306d |
if (isblank(*c) || *c == '=') {
|
|
Packit Service |
31306d |
*c = '\0';
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
*str = c + 1;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return r;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
long ssh_config_get_long(char **str, long notfound)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char *p, *endp;
|
|
Packit Service |
31306d |
long i;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
p = ssh_config_get_token(str);
|
|
Packit Service |
31306d |
if (p && *p) {
|
|
Packit Service |
31306d |
i = strtol(p, &endp, 10);
|
|
Packit Service |
31306d |
if (p == endp) {
|
|
Packit Service |
31306d |
return notfound;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return i;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return notfound;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_config_get_str_tok(char **str, const char *def)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char *p;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
p = ssh_config_get_token(str);
|
|
Packit Service |
31306d |
if (p && *p) {
|
|
Packit Service |
31306d |
return p;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return def;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_config_get_yesno(char **str, int notfound)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
const char *p;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
p = ssh_config_get_str_tok(str, NULL);
|
|
Packit Service |
31306d |
if (p == NULL) {
|
|
Packit Service |
31306d |
return notfound;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (strncasecmp(p, "yes", 3) == 0) {
|
|
Packit Service |
31306d |
return 1;
|
|
Packit Service |
31306d |
} else if (strncasecmp(p, "no", 2) == 0) {
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return notfound;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_config_parse_uri(const char *tok,
|
|
Packit Service |
31306d |
char **username,
|
|
Packit Service |
31306d |
char **hostname,
|
|
Packit Service |
31306d |
char **port)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char *endp = NULL;
|
|
Packit Service |
31306d |
long port_n;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Sanitize inputs */
|
|
Packit Service |
31306d |
if (username != NULL) {
|
|
Packit Service |
31306d |
*username = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (hostname != NULL) {
|
|
Packit Service |
31306d |
*hostname = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (port != NULL) {
|
|
Packit Service |
31306d |
*port = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Username part (optional) */
|
|
Packit Service |
31306d |
endp = strchr(tok, '@');
|
|
Packit Service |
31306d |
if (endp != NULL) {
|
|
Packit Service |
31306d |
/* Zero-length username is not valid */
|
|
Packit Service |
31306d |
if (tok == endp) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (username != NULL) {
|
|
Packit Service |
31306d |
*username = strndup(tok, endp - tok);
|
|
Packit Service |
31306d |
if (*username == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
tok = endp + 1;
|
|
Packit Service |
31306d |
/* If there is second @ character, this does not look like our URI */
|
|
Packit Service |
31306d |
endp = strchr(tok, '@');
|
|
Packit Service |
31306d |
if (endp != NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Hostname */
|
|
Packit Service |
31306d |
if (*tok == '[') {
|
|
Packit Service |
31306d |
/* IPv6 address is enclosed with square brackets */
|
|
Packit Service |
31306d |
tok++;
|
|
Packit Service |
31306d |
endp = strchr(tok, ']');
|
|
Packit Service |
31306d |
if (endp == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
/* Hostnames or aliases expand to the last colon or to the end */
|
|
Packit Service |
31306d |
endp = strrchr(tok, ':');
|
|
Packit Service |
31306d |
if (endp == NULL) {
|
|
Packit Service |
31306d |
endp = strchr(tok, '\0');
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (tok == endp) {
|
|
Packit Service |
31306d |
/* Zero-length hostnames are not valid */
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (hostname != NULL) {
|
|
Packit Service |
31306d |
*hostname = strndup(tok, endp - tok);
|
|
Packit Service |
31306d |
if (*hostname == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
/* Skip also the closing bracket */
|
|
Packit Service |
31306d |
if (*endp == ']') {
|
|
Packit Service |
31306d |
endp++;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Port (optional) */
|
|
Packit Service |
31306d |
if (*endp != '\0') {
|
|
Packit Service |
31306d |
char *port_end = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Verify the port is valid positive number */
|
|
Packit Service |
31306d |
port_n = strtol(endp + 1, &port_end, 10);
|
|
Packit Service |
31306d |
if (port_n < 1 || *port_end != '\0') {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_WARN, "Failed to parse port number."
|
|
Packit Service |
31306d |
" The value '%ld' is invalid or there are some"
|
|
Packit Service |
31306d |
" trailing characters: '%s'", port_n, port_end);
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (port != NULL) {
|
|
Packit Service |
31306d |
*port = strdup(endp + 1);
|
|
Packit Service |
31306d |
if (*port == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
if (username != NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(*username);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (hostname != NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(*hostname);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (port != NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(*port);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|