Blame src/config_parser.c

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
}