Blame src/options.c

Packit Service 31306d
/*
Packit Service 31306d
 * options.c - handle pre-connection options
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2003-2008 by Aris Adamantiadis
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
#include <stdio.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#ifndef _WIN32
Packit Service 31306d
#include <pwd.h>
Packit Service 31306d
#else
Packit Service 31306d
#include <winsock2.h>
Packit Service 31306d
#endif
Packit Service 31306d
#include <sys/types.h>
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
#include "libssh/session.h"
Packit Service 31306d
#include "libssh/misc.h"
Packit Service 31306d
#include "libssh/options.h"
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
#include "libssh/server.h"
Packit Service 31306d
#include "libssh/bind.h"
Packit Service 31306d
#include "libssh/bind_config.h"
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @addtogroup libssh_session
Packit Service 31306d
 * @{
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Duplicate the options of a session structure.
Packit Service 31306d
 *
Packit Service 31306d
 * If you make several sessions with the same options this is useful. You
Packit Service 31306d
 * cannot use twice the same option structure in ssh_session_connect.
Packit Service 31306d
 *
Packit Service 31306d
 * @param src           The session to use to copy the options.
Packit Service 31306d
 *
Packit Service 31306d
 * @param dest          A pointer to store the allocated session with duplicated
Packit Service 31306d
 *                      options. You have to free the memory.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             0 on sucess, -1 on error with errno set.
Packit Service 31306d
 *
Packit Service 31306d
 * @see ssh_session_connect()
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_copy(ssh_session src, ssh_session *dest)
Packit Service 31306d
{
Packit Service 31306d
    ssh_session new;
Packit Service 31306d
    struct ssh_iterator *it = NULL;
Packit Service 31306d
    char *id = NULL;
Packit Service 31306d
    int i;
Packit Service 31306d
Packit Service 31306d
    if (src == NULL || dest == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    new = ssh_new();
Packit Service 31306d
    if (new == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.username != NULL) {
Packit Service 31306d
        new->opts.username = strdup(src->opts.username);
Packit Service 31306d
        if (new->opts.username == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.host != NULL) {
Packit Service 31306d
        new->opts.host = strdup(src->opts.host);
Packit Service 31306d
        if (new->opts.host == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.bindaddr != NULL) {
Packit Service 31306d
        new->opts.bindaddr = strdup(src->opts.bindaddr);
Packit Service 31306d
        if (new->opts.bindaddr == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Remove the default identities */
Packit Service 31306d
    for (id = ssh_list_pop_head(char *, new->opts.identity);
Packit Service 31306d
         id != NULL;
Packit Service 31306d
         id = ssh_list_pop_head(char *, new->opts.identity)) {
Packit Service 31306d
        SAFE_FREE(id);
Packit Service 31306d
    }
Packit Service 31306d
    /* Copy the new identities from the source list */
Packit Service 31306d
    if (src->opts.identity != NULL) {
Packit Service 31306d
        it = ssh_list_get_iterator(src->opts.identity);
Packit Service 31306d
        while (it) {
Packit Service 31306d
            int rc;
Packit Service 31306d
Packit Service 31306d
            id = strdup((char *) it->data);
Packit Service 31306d
            if (id == NULL) {
Packit Service 31306d
                ssh_free(new);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_list_append(new->opts.identity, id);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                free(id);
Packit Service 31306d
                ssh_free(new);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            it = it->next;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.sshdir != NULL) {
Packit Service 31306d
        new->opts.sshdir = strdup(src->opts.sshdir);
Packit Service 31306d
        if (new->opts.sshdir == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.knownhosts != NULL) {
Packit Service 31306d
        new->opts.knownhosts = strdup(src->opts.knownhosts);
Packit Service 31306d
        if (new->opts.knownhosts == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.global_knownhosts != NULL) {
Packit Service 31306d
        new->opts.global_knownhosts = strdup(src->opts.global_knownhosts);
Packit Service 31306d
        if (new->opts.global_knownhosts == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    for (i = 0; i < SSH_KEX_METHODS; i++) {
Packit Service 31306d
        if (src->opts.wanted_methods[i] != NULL) {
Packit Service 31306d
            new->opts.wanted_methods[i] = strdup(src->opts.wanted_methods[i]);
Packit Service 31306d
            if (new->opts.wanted_methods[i] == NULL) {
Packit Service 31306d
                ssh_free(new);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.ProxyCommand != NULL) {
Packit Service 31306d
        new->opts.ProxyCommand = strdup(src->opts.ProxyCommand);
Packit Service 31306d
        if (new->opts.ProxyCommand == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.pubkey_accepted_types != NULL) {
Packit Service 31306d
        new->opts.pubkey_accepted_types = strdup(src->opts.pubkey_accepted_types);
Packit Service 31306d
        if (new->opts.pubkey_accepted_types == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.gss_server_identity != NULL) {
Packit Service 31306d
        new->opts.gss_server_identity = strdup(src->opts.gss_server_identity);
Packit Service 31306d
        if (new->opts.gss_server_identity == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (src->opts.gss_client_identity != NULL) {
Packit Service 31306d
        new->opts.gss_client_identity = strdup(src->opts.gss_client_identity);
Packit Service 31306d
        if (new->opts.gss_client_identity == NULL) {
Packit Service 31306d
            ssh_free(new);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    memcpy(new->opts.options_seen, src->opts.options_seen,
Packit Service 31306d
           sizeof(new->opts.options_seen));
Packit Service 31306d
Packit Service 31306d
    new->opts.fd                    = src->opts.fd;
Packit Service 31306d
    new->opts.port                  = src->opts.port;
Packit Service 31306d
    new->opts.timeout               = src->opts.timeout;
Packit Service 31306d
    new->opts.timeout_usec          = src->opts.timeout_usec;
Packit Service 31306d
    new->opts.compressionlevel      = src->opts.compressionlevel;
Packit Service 31306d
    new->opts.StrictHostKeyChecking = src->opts.StrictHostKeyChecking;
Packit Service 31306d
    new->opts.gss_delegate_creds    = src->opts.gss_delegate_creds;
Packit Service 31306d
    new->opts.flags                 = src->opts.flags;
Packit Service 31306d
    new->opts.nodelay               = src->opts.nodelay;
Packit Service 31306d
    new->opts.config_processed      = src->opts.config_processed;
Packit Service 31306d
    new->common.log_verbosity       = src->common.log_verbosity;
Packit Service 31306d
    new->common.callbacks           = src->common.callbacks;
Packit Service 31306d
Packit Service 31306d
    *dest = new;
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int ssh_options_set_algo(ssh_session session,
Packit Service 31306d
                         enum ssh_kex_types_e algo,
Packit Service 31306d
                         const char *list)
Packit Service 31306d
{
Packit Service 31306d
    char *p = NULL;
Packit Service 31306d
Packit Service 31306d
    if (ssh_fips_mode()) {
Packit Service 31306d
        p = ssh_keep_fips_algos(algo, list);
Packit Service 31306d
    } else {
Packit Service 31306d
        p = ssh_keep_known_algos(algo, list);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (p == NULL) {
Packit Service 31306d
        ssh_set_error(session, SSH_REQUEST_DENIED,
Packit Service 31306d
                "Setting method: no allowed algorithm for method \"%s\" (%s)",
Packit Service 31306d
                ssh_kex_get_description(algo), list);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SAFE_FREE(session->opts.wanted_methods[algo]);
Packit Service 31306d
    session->opts.wanted_methods[algo] = p;
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief This function can set all possible ssh options.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  session An allocated SSH session structure.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  type The option type to set. This could be one of the
Packit Service 31306d
 *              following:
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_HOST:
Packit Service 31306d
 *                The hostname or ip address to connect to (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PORT:
Packit Service 31306d
 *                The port to connect to (unsigned int *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PORT_STR:
Packit Service 31306d
 *                The port to connect to (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_FD:
Packit Service 31306d
 *                The file descriptor to use (socket_t).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                If you wish to open the socket yourself for a reason
Packit Service 31306d
 *                or another, set the file descriptor. Don't forget to
Packit Service 31306d
 *                set the hostname as the hostname is used as a key in
Packit Service 31306d
 *                the known_host mechanism.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_BINDADDR:
Packit Service 31306d
 *                The address to bind the client to (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_USER:
Packit Service 31306d
 *                The username for authentication (const char *).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                If the value is NULL, the username is set to the
Packit Service 31306d
 *                default username.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_SSH_DIR:
Packit Service 31306d
 *                Set the ssh directory (const char *,format string).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                If the value is NULL, the directory is set to the
Packit Service 31306d
 *                default ssh directory.\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                The ssh directory is used for files like known_hosts
Packit Service 31306d
 *                and identity (private and public key). It may include
Packit Service 31306d
 *                "%s" which will be replaced by the user home
Packit Service 31306d
 *                directory.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_KNOWNHOSTS:
Packit Service 31306d
 *                Set the known hosts file name (const char *,format string).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                If the value is NULL, the directory is set to the
Packit Service 31306d
 *                default known hosts file, normally
Packit Service 31306d
 *                ~/.ssh/known_hosts.\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                The known hosts file is used to certify remote hosts
Packit Service 31306d
 *                are genuine. It may include "%d" which will be
Packit Service 31306d
 *                replaced by the user home directory.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GLOBAL_KNOWNHOSTS:
Packit Service 31306d
 *                Set the global known hosts file name (const char *,format string).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                If the value is NULL, the directory is set to the
Packit Service 31306d
 *                default global known hosts file, normally
Packit Service 31306d
 *                /etc/ssh/ssh_known_hosts.\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                The known hosts file is used to certify remote hosts
Packit Service 31306d
 *                are genuine.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_ADD_IDENTITY (or SSH_OPTIONS_IDENTITY):
Packit Service 31306d
 *                Add a new identity file (const char *, format string) to
Packit Service 31306d
 *                the identity list.\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                By default identity, id_dsa and id_rsa are checked.\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                The identity used to authenticate with public key will be
Packit Service 31306d
 *                prepended to the list.
Packit Service 31306d
 *                It may include "%s" which will be replaced by the
Packit Service 31306d
 *                user home directory.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_TIMEOUT:
Packit Service 31306d
 *                Set a timeout for the connection in seconds (long).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_TIMEOUT_USEC:
Packit Service 31306d
 *                Set a timeout for the connection in micro seconds
Packit Service 31306d
 *                        (long).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_SSH1:
Packit Service 31306d
 *                Deprecated
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_SSH2:
Packit Service 31306d
 *                Unused
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_LOG_VERBOSITY:
Packit Service 31306d
 *                Set the session logging verbosity (int).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                The verbosity of the messages. Every log smaller or
Packit Service 31306d
 *                equal to verbosity will be shown.
Packit Service 31306d
 *                - SSH_LOG_NOLOG: No logging
Packit Service 31306d
 *                - SSH_LOG_WARNING: Only warnings
Packit Service 31306d
 *                - SSH_LOG_PROTOCOL: High level protocol information
Packit Service 31306d
 *                - SSH_LOG_PACKET: Lower level protocol infomations, packet level
Packit Service 31306d
 *                - SSH_LOG_FUNCTIONS: Every function path
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_LOG_VERBOSITY_STR:
Packit Service 31306d
 *                Set the session logging verbosity via a
Packit Service 31306d
 *                string that will be converted to a numerical
Packit Service 31306d
 *                value (e.g. "3") and interpreted according
Packit Service 31306d
 *                to the values of
Packit Service 31306d
 *                SSH_OPTIONS_LOG_VERBOSITY above (const
Packit Service 31306d
 *                char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_CIPHERS_C_S:
Packit Service 31306d
 *                Set the symmetric cipher client to server (const char *,
Packit Service 31306d
 *                comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_CIPHERS_S_C:
Packit Service 31306d
 *                Set the symmetric cipher server to client (const char *,
Packit Service 31306d
 *                comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_KEY_EXCHANGE:
Packit Service 31306d
 *                Set the key exchange method to be used (const char *,
Packit Service 31306d
 *                comma-separated list). ex:
Packit Service 31306d
 *                "ecdh-sha2-nistp256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_HMAC_C_S:
Packit Service 31306d
 *                Set the Message Authentication Code algorithm client to server
Packit Service 31306d
 *                (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_HMAC_S_C:
Packit Service 31306d
 *                Set the Message Authentication Code algorithm server to client
Packit Service 31306d
 *                (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_HOSTKEYS:
Packit Service 31306d
 *                Set the preferred server host key types (const char *,
Packit Service 31306d
 *                comma-separated list). ex:
Packit Service 31306d
 *                "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
Packit Service 31306d
 *                Set the preferred public key algorithms to be used for
Packit Service 31306d
 *                authentication (const char *, comma-separated list). ex:
Packit Service 31306d
 *                "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256"
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_COMPRESSION_C_S:
Packit Service 31306d
 *                Set the compression to use for client to server
Packit Service 31306d
 *                communication (const char *, "yes", "no" or a specific
Packit Service 31306d
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_COMPRESSION_S_C:
Packit Service 31306d
 *                Set the compression to use for server to client
Packit Service 31306d
 *                communication (const char *, "yes", "no" or a specific
Packit Service 31306d
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_COMPRESSION:
Packit Service 31306d
 *                Set the compression to use for both directions
Packit Service 31306d
 *                communication (const char *, "yes", "no" or a specific
Packit Service 31306d
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_COMPRESSION_LEVEL:
Packit Service 31306d
 *                Set the compression level to use for zlib functions. (int,
Packit Service 31306d
 *                value from 1 to 9, 9 being the most efficient but slower).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_STRICTHOSTKEYCHECK:
Packit Service 31306d
 *                Set the parameter StrictHostKeyChecking to avoid
Packit Service 31306d
 *                asking about a fingerprint (int, 0 = false).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PROXYCOMMAND:
Packit Service 31306d
 *                Set the command to be executed in order to connect to
Packit Service 31306d
 *                server (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GSSAPI_SERVER_IDENTITY
Packit Service 31306d
 *                Set it to specify the GSSAPI server identity that libssh
Packit Service 31306d
 *                should expect when connecting to the server (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY
Packit Service 31306d
 *                Set it to specify the GSSAPI client identity that libssh
Packit Service 31306d
 *                should expect when connecting to the server (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS
Packit Service 31306d
 *                Set it to specify that GSSAPI should delegate credentials
Packit Service 31306d
 *                to the server (int, 0 = false).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PASSWORD_AUTH
Packit Service 31306d
 *                Set it if password authentication should be used
Packit Service 31306d
 *                in ssh_userauth_auto_pubkey(). (int, 0=false).
Packit Service 31306d
 *                Currently without effect (ssh_userauth_auto_pubkey doesn't use
Packit Service 31306d
 *                password authentication).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PUBKEY_AUTH
Packit Service 31306d
 *                Set it if pubkey authentication should be used
Packit Service 31306d
 *                in ssh_userauth_auto_pubkey(). (int, 0=false).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_KBDINT_AUTH
Packit Service 31306d
 *                Set it if keyboard-interactive authentication should be used
Packit Service 31306d
 *                in ssh_userauth_auto_pubkey(). (int, 0=false).
Packit Service 31306d
 *                Currently without effect (ssh_userauth_auto_pubkey doesn't use
Packit Service 31306d
 *                keyboard-interactive authentication).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GSSAPI_AUTH
Packit Service 31306d
 *                Set it if gssapi authentication should be used
Packit Service 31306d
 *                in ssh_userauth_auto_pubkey(). (int, 0=false).
Packit Service 31306d
 *                Currently without effect (ssh_userauth_auto_pubkey doesn't use
Packit Service 31306d
 *                gssapi authentication).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_NODELAY
Packit Service 31306d
 *                Set it to disable Nagle's Algorithm (TCP_NODELAY) on the
Packit Service 31306d
 *                session socket. (int, 0=false)
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PROCESS_CONFIG
Packit Service 31306d
 *                Set it to false to disable automatic processing of per-user
Packit Service 31306d
 *                and system-wide OpenSSH configuration files. LibSSH
Packit Service 31306d
 *                automatically uses these configuration files unless
Packit Service 31306d
 *                you provide it with this option or with different file (bool).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_REKEY_DATA
Packit Service 31306d
 *                Set the data limit that can be transferred with a single
Packit Service 31306d
 *                key in bytes. RFC 4253 Section 9 recommends 1GB of data, while
Packit Service 31306d
 *                RFC 4344 provides more specific restrictions, that are applied
Packit Service 31306d
 *                automatically. When specified, the lower value will be used.
Packit Service 31306d
 *                (uint64_t, 0=default)
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_REKEY_TIME
Packit Service 31306d
 *                Set the time limit for a session before intializing a rekey
Packit Service 31306d
 *                in seconds. RFC 4253 Section 9 recommends one hour.
Packit Service 31306d
 *                (uint32_t, 0=off)
Packit Service 31306d
 *
Packit Service 31306d
 * @param  value The value to set. This is a generic pointer and the
Packit Service 31306d
 *               datatype which is used should be set according to the
Packit Service 31306d
 *               type set.
Packit Service 31306d
 *
Packit Service 31306d
 * @return       0 on success, < 0 on error.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_set(ssh_session session, enum ssh_options_e type,
Packit Service 31306d
    const void *value) {
Packit Service 31306d
    const char *v;
Packit Service 31306d
    char *p, *q;
Packit Service 31306d
    long int i;
Packit Service 31306d
    unsigned int u;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (session == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (type) {
Packit Service 31306d
        case SSH_OPTIONS_HOST:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                q = strdup(value);
Packit Service 31306d
                if (q == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                p = strchr(q, '@');
Packit Service 31306d
Packit Service 31306d
                SAFE_FREE(session->opts.host);
Packit Service 31306d
Packit Service 31306d
                if (p) {
Packit Service 31306d
                    *p = '\0';
Packit Service 31306d
                    session->opts.host = strdup(p + 1);
Packit Service 31306d
                    if (session->opts.host == NULL) {
Packit Service 31306d
                        SAFE_FREE(q);
Packit Service 31306d
                        ssh_set_error_oom(session);
Packit Service 31306d
                        return -1;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    SAFE_FREE(session->opts.username);
Packit Service 31306d
                    session->opts.username = strdup(q);
Packit Service 31306d
                    SAFE_FREE(q);
Packit Service 31306d
                    if (session->opts.username == NULL) {
Packit Service 31306d
                        ssh_set_error_oom(session);
Packit Service 31306d
                        return -1;
Packit Service 31306d
                    }
Packit Service 31306d
                } else {
Packit Service 31306d
                    session->opts.host = q;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PORT:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int *x = (int *) value;
Packit Service 31306d
                if (*x <= 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->opts.port = *x & 0xffffU;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PORT_STR:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                q = strdup(v);
Packit Service 31306d
                if (q == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                i = strtol(q, &p, 10);
Packit Service 31306d
                if (q == p) {
Packit Service 31306d
                    SAFE_FREE(q);
Packit Service 31306d
                }
Packit Service 31306d
                SAFE_FREE(q);
Packit Service 31306d
                if (i <= 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->opts.port = i & 0xffffU;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_FD:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                session->opts.fd = SSH_INVALID_SOCKET;
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                socket_t *x = (socket_t *) value;
Packit Service 31306d
                if (*x < 0) {
Packit Service 31306d
                    session->opts.fd = SSH_INVALID_SOCKET;
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->opts.fd = *x & 0xffff;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_BINDADDR:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            q = strdup(v);
Packit Service 31306d
            if (q == NULL) {
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            SAFE_FREE(session->opts.bindaddr);
Packit Service 31306d
            session->opts.bindaddr = q;
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_USER:
Packit Service 31306d
            v = value;
Packit Service 31306d
            SAFE_FREE(session->opts.username);
Packit Service 31306d
            if (v == NULL) {
Packit Service 31306d
                q = ssh_get_local_username();
Packit Service 31306d
                if (q == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                session->opts.username = q;
Packit Service 31306d
            } else if (v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else { /* username provided */
Packit Service 31306d
                session->opts.username = strdup(value);
Packit Service 31306d
                if (session->opts.username == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_SSH_DIR:
Packit Service 31306d
            v = value;
Packit Service 31306d
            SAFE_FREE(session->opts.sshdir);
Packit Service 31306d
            if (v == NULL) {
Packit Service 31306d
                session->opts.sshdir = ssh_path_expand_tilde("~/.ssh");
Packit Service 31306d
                if (session->opts.sshdir == NULL) {
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            } else if (v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                session->opts.sshdir = ssh_path_expand_tilde(v);
Packit Service 31306d
                if (session->opts.sshdir == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_IDENTITY:
Packit Service 31306d
        case SSH_OPTIONS_ADD_IDENTITY:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            q = strdup(v);
Packit Service 31306d
            if (q == NULL) {
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            rc = ssh_list_prepend(session->opts.identity, q);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                free(q);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_KNOWNHOSTS:
Packit Service 31306d
            v = value;
Packit Service 31306d
            SAFE_FREE(session->opts.knownhosts);
Packit Service 31306d
            if (v == NULL) {
Packit Service 31306d
                /* The default value will be set by the ssh_options_apply() */
Packit Service 31306d
            } else if (v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                session->opts.knownhosts = strdup(v);
Packit Service 31306d
                if (session->opts.knownhosts == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_GLOBAL_KNOWNHOSTS:
Packit Service 31306d
            v = value;
Packit Service 31306d
            SAFE_FREE(session->opts.global_knownhosts);
Packit Service 31306d
            if (v == NULL) {
Packit Service 31306d
                session->opts.global_knownhosts =
Packit Service 31306d
                    strdup("/etc/ssh/ssh_known_hosts");
Packit Service 31306d
                if (session->opts.global_knownhosts == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            } else if (v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                session->opts.global_knownhosts = strdup(v);
Packit Service 31306d
                if (session->opts.global_knownhosts == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_TIMEOUT:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                long *x = (long *) value;
Packit Service 31306d
                if (*x < 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->opts.timeout = *x & 0xffffffffU;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_TIMEOUT_USEC:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                long *x = (long *) value;
Packit Service 31306d
                if (*x < 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->opts.timeout_usec = *x & 0xffffffffU;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_SSH1:
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_SSH2:
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_LOG_VERBOSITY:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int *x = (int *) value;
Packit Service 31306d
                if (*x < 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->common.log_verbosity = *x & 0xffffU;
Packit Service 31306d
                ssh_set_log_level(*x & 0xffffU);
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_LOG_VERBOSITY_STR:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                session->common.log_verbosity = 0;
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                q = strdup(v);
Packit Service 31306d
                if (q == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                i = strtol(q, &p, 10);
Packit Service 31306d
                if (q == p) {
Packit Service 31306d
                    SAFE_FREE(q);
Packit Service 31306d
                }
Packit Service 31306d
                SAFE_FREE(q);
Packit Service 31306d
                if (i < 0) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                session->common.log_verbosity = i & 0xffffU;
Packit Service 31306d
                ssh_set_log_level(i & 0xffffU);
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_CIPHERS_C_S:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_CRYPT_C_S, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_CIPHERS_S_C:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_CRYPT_S_C, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_KEY_EXCHANGE:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_KEX, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_HOSTKEYS:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_HOSTKEYS, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_fips_mode()) {
Packit Service 31306d
                    p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
Packit Service 31306d
                } else {
Packit Service 31306d
                    p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
Packit Service 31306d
                }
Packit Service 31306d
                if (p == NULL) {
Packit Service 31306d
                    ssh_set_error(session, SSH_REQUEST_DENIED,
Packit Service 31306d
                        "Setting method: no known public key algorithm (%s)",
Packit Service 31306d
                         v);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                SAFE_FREE(session->opts.pubkey_accepted_types);
Packit Service 31306d
                session->opts.pubkey_accepted_types = p;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_HMAC_C_S:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_MAC_C_S, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
         case SSH_OPTIONS_HMAC_S_C:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (ssh_options_set_algo(session, SSH_MAC_S_C, v) < 0)
Packit Service 31306d
                    return -1;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_COMPRESSION_C_S:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (strcasecmp(value,"yes")==0){
Packit Service 31306d
                    if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,zlib") < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                } else if (strcasecmp(value,"no")==0){
Packit Service 31306d
                    if(ssh_options_set_algo(session,SSH_COMP_C_S,"none") < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                } else {
Packit Service 31306d
                    if (ssh_options_set_algo(session, SSH_COMP_C_S, v) < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_COMPRESSION_S_C:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                if (strcasecmp(value,"yes")==0){
Packit Service 31306d
                    if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,zlib") < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                } else if (strcasecmp(value,"no")==0){
Packit Service 31306d
                    if(ssh_options_set_algo(session,SSH_COMP_S_C,"none") < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                } else {
Packit Service 31306d
                    if (ssh_options_set_algo(session, SSH_COMP_S_C, v) < 0)
Packit Service 31306d
                        return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_COMPRESSION:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
            if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_C_S, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
            if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_S_C, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_COMPRESSION_LEVEL:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int *x = (int *)value;
Packit Service 31306d
                if (*x < 1 || *x > 9) {
Packit Service 31306d
                    ssh_set_error_invalid(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                session->opts.compressionlevel = *x & 0xff;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_STRICTHOSTKEYCHECK:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int *x = (int *) value;
Packit Service 31306d
Packit Service 31306d
                session->opts.StrictHostKeyChecking = (*x & 0xff) > 0 ? 1 : 0;
Packit Service 31306d
            }
Packit Service 31306d
            session->opts.StrictHostKeyChecking = *(int*)value;
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PROXYCOMMAND:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                SAFE_FREE(session->opts.ProxyCommand);
Packit Service 31306d
                /* Setting the command to 'none' disables this option. */
Packit Service 31306d
                rc = strcasecmp(v, "none");
Packit Service 31306d
                if (rc != 0) {
Packit Service 31306d
                    q = strdup(v);
Packit Service 31306d
                    if (q == NULL) {
Packit Service 31306d
                        return -1;
Packit Service 31306d
                    }
Packit Service 31306d
                    session->opts.ProxyCommand = q;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_GSSAPI_SERVER_IDENTITY:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                SAFE_FREE(session->opts.gss_server_identity);
Packit Service 31306d
                session->opts.gss_server_identity = strdup(v);
Packit Service 31306d
                if (session->opts.gss_server_identity == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY:
Packit Service 31306d
            v = value;
Packit Service 31306d
            if (v == NULL || v[0] == '\0') {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                SAFE_FREE(session->opts.gss_client_identity);
Packit Service 31306d
                session->opts.gss_client_identity = strdup(v);
Packit Service 31306d
                if (session->opts.gss_client_identity == NULL) {
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int x = *(int *)value;
Packit Service 31306d
Packit Service 31306d
                session->opts.gss_delegate_creds = (x & 0xff);
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PASSWORD_AUTH:
Packit Service 31306d
        case SSH_OPTIONS_PUBKEY_AUTH:
Packit Service 31306d
        case SSH_OPTIONS_KBDINT_AUTH:
Packit Service 31306d
        case SSH_OPTIONS_GSSAPI_AUTH:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int x = *(int *)value;
Packit Service 31306d
                u = type == SSH_OPTIONS_PASSWORD_AUTH ?
Packit Service 31306d
                    SSH_OPT_FLAG_PASSWORD_AUTH:
Packit Service 31306d
                    type == SSH_OPTIONS_PUBKEY_AUTH ?
Packit Service 31306d
                        SSH_OPT_FLAG_PUBKEY_AUTH:
Packit Service 31306d
                        type == SSH_OPTIONS_KBDINT_AUTH ?
Packit Service 31306d
                            SSH_OPT_FLAG_KBDINT_AUTH:
Packit Service 31306d
                            SSH_OPT_FLAG_GSSAPI_AUTH;
Packit Service 31306d
                if (x != 0){
Packit Service 31306d
                    session->opts.flags |= u;
Packit Service 31306d
                } else {
Packit Service 31306d
                    session->opts.flags &= ~u;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_NODELAY:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                int *x = (int *) value;
Packit Service 31306d
                session->opts.nodelay = (*x & 0xff) > 0 ? 1 : 0;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_PROCESS_CONFIG:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                bool *x = (bool *)value;
Packit Service 31306d
                session->opts.config_processed = !(*x);
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_REKEY_DATA:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                uint64_t *x = (uint64_t *)value;
Packit Service 31306d
                session->opts.rekey_data = *x;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_OPTIONS_REKEY_TIME:
Packit Service 31306d
            if (value == NULL) {
Packit Service 31306d
                ssh_set_error_invalid(session);
Packit Service 31306d
                return -1;
Packit Service 31306d
            } else {
Packit Service 31306d
                uint32_t *x = (uint32_t *)value;
Packit Service 31306d
                if ((*x * 1000) < *x) {
Packit Service 31306d
                    ssh_set_error(session, SSH_REQUEST_DENIED,
Packit Service 31306d
                                  "The provided value (%" PRIu32 ") for rekey"
Packit Service 31306d
                                  " time is too large", *x);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                session->opts.rekey_time = (*x) * 1000;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
Packit Service 31306d
            return -1;
Packit Service 31306d
            break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief This function can get ssh the ssh port. It must only be used on
Packit Service 31306d
 *        a valid ssh session. This function is useful when the session
Packit Service 31306d
 *        options have been automatically inferred from the environment
Packit Service 31306d
 *        or configuration files and one
Packit Service 31306d
 *
Packit Service 31306d
 * @param  session An allocated SSH session structure.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  port_target An unsigned integer into which the
Packit Service 31306d
 *         port will be set from the ssh session.
Packit Service 31306d
 *
Packit Service 31306d
 * @return       0 on success, < 0 on error.
Packit Service 31306d
 *
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_get_port(ssh_session session, unsigned int* port_target) {
Packit Service 31306d
    if (session == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->opts.port == 0) {
Packit Service 31306d
        *port_target = 22;
Packit Service 31306d
        return 0;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    *port_target = session->opts.port;
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief This function can get ssh options, it does not support all options provided for
Packit Service 31306d
 *        ssh options set, but mostly those which a user-space program may care about having
Packit Service 31306d
 *        trusted the ssh driver to infer these values from underlaying configuration files.
Packit Service 31306d
 *        It operates only on those SSH_OPTIONS_* which return char*. If you wish to receive
Packit Service 31306d
 *        the port then please use ssh_options_get_port() which returns an unsigned int.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  session An allocated SSH session structure.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  type The option type to get. This could be one of the
Packit Service 31306d
 *              following:
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_HOST:
Packit Service 31306d
 *                The hostname or ip address to connect to (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_USER:
Packit Service 31306d
 *                The username for authentication (const char *).\n
Packit Service 31306d
 *                \n when not explicitly set this will be inferred from the
Packit Service 31306d
 *                ~/.ssh/config file.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_IDENTITY:
Packit Service 31306d
 *                Get the first identity file name (const char *).\n
Packit Service 31306d
 *                \n
Packit Service 31306d
 *                By default identity, id_dsa and id_rsa are checked.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_PROXYCOMMAND:
Packit Service 31306d
 *                Get the proxycommand necessary to log into the
Packit Service 31306d
 *                remote host. When not explicitly set, it will be read
Packit Service 31306d
 *                from the ~/.ssh/config file.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_GLOBAL_KNOWNHOSTS:
Packit Service 31306d
 *                Get the path to the global known_hosts file being used.
Packit Service 31306d
 *
Packit Service 31306d
 *              - SSH_OPTIONS_KNOWNHOSTS:
Packit Service 31306d
 *                Get the path to the known_hosts file being used.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  value The value to get into. As a char**, space will be
Packit Service 31306d
 *               allocated by the function for the value, it is
Packit Service 31306d
 *               your responsibility to free the memory using
Packit Service 31306d
 *               ssh_string_free_char().
Packit Service 31306d
 *
Packit Service 31306d
 * @return       SSH_OK on success, SSH_ERROR on error.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
Packit Service 31306d
{
Packit Service 31306d
    char* src = NULL;
Packit Service 31306d
Packit Service 31306d
    if (session == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch(type)
Packit Service 31306d
    {
Packit Service 31306d
        case SSH_OPTIONS_HOST: {
Packit Service 31306d
            src = session->opts.host;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_OPTIONS_USER: {
Packit Service 31306d
            src = session->opts.username;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_OPTIONS_IDENTITY: {
Packit Service 31306d
            struct ssh_iterator *it = ssh_list_get_iterator(session->opts.identity);
Packit Service 31306d
            if (it == NULL) {
Packit Service 31306d
                return SSH_ERROR;
Packit Service 31306d
            }
Packit Service 31306d
            src = ssh_iterator_value(char *, it);
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_OPTIONS_PROXYCOMMAND: {
Packit Service 31306d
            src = session->opts.ProxyCommand;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_OPTIONS_KNOWNHOSTS: {
Packit Service 31306d
            src = session->opts.knownhosts;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: {
Packit Service 31306d
            src = session->opts.global_knownhosts;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        default:
Packit Service 31306d
            ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
Packit Service 31306d
            return SSH_ERROR;
Packit Service 31306d
        break;
Packit Service 31306d
    }
Packit Service 31306d
    if (src == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    *value = strdup(src);
Packit Service 31306d
    if (*value == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Parse command line arguments.
Packit Service 31306d
 *
Packit Service 31306d
 * This is a helper for your application to generate the appropriate
Packit Service 31306d
 * options from the command line arguments.\n
Packit Service 31306d
 * The argv array and argc value are changed so that the parsed
Packit Service 31306d
 * arguments wont appear anymore in them.\n
Packit Service 31306d
 * The single arguments (without switches) are not parsed. thus,
Packit Service 31306d
 * myssh -l user localhost\n
Packit Service 31306d
 * The command wont set the hostname value of options to localhost.
Packit Service 31306d
 *
Packit Service 31306d
 * @param session       The session to configure.
Packit Service 31306d
 *
Packit Service 31306d
 * @param argcptr       The pointer to the argument count.
Packit Service 31306d
 *
Packit Service 31306d
 * @param argv          The arguments list pointer.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns 0 on success, < 0 on error.
Packit Service 31306d
 *
Packit Service 31306d
 * @see ssh_session_new()
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
Packit Service 31306d
{
Packit Service 31306d
#ifdef _MSC_VER
Packit Service 31306d
    (void)session;
Packit Service 31306d
    (void)argcptr;
Packit Service 31306d
    (void)argv;
Packit Service 31306d
    /* Not supported with a Microsoft compiler */
Packit Service 31306d
    return -1;
Packit Service 31306d
#else
Packit Service 31306d
    char *user = NULL;
Packit Service 31306d
    char *cipher = NULL;
Packit Service 31306d
    char *identity = NULL;
Packit Service 31306d
    char *port = NULL;
Packit Service 31306d
    char **save = NULL;
Packit Service 31306d
    char **tmp = NULL;
Packit Service 31306d
    size_t i = 0;
Packit Service 31306d
    int argc = *argcptr;
Packit Service 31306d
    int debuglevel = 0;
Packit Service 31306d
    int usersa = 0;
Packit Service 31306d
    int usedss = 0;
Packit Service 31306d
    int compress = 0;
Packit Service 31306d
    int cont = 1;
Packit Service 31306d
    size_t current = 0;
Packit Service 31306d
    int saveoptind = optind; /* need to save 'em */
Packit Service 31306d
    int saveopterr = opterr;
Packit Service 31306d
    int opt;
Packit Service 31306d
Packit Service 31306d
    opterr = 0; /* shut up getopt */
Packit Service 31306d
    while((opt = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1) {
Packit Service 31306d
        switch(opt) {
Packit Service 31306d
        case 'l':
Packit Service 31306d
            user = optarg;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'p':
Packit Service 31306d
            port = optarg;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'v':
Packit Service 31306d
            debuglevel++;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'r':
Packit Service 31306d
            usersa++;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'd':
Packit Service 31306d
            usedss++;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'c':
Packit Service 31306d
            cipher = optarg;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'i':
Packit Service 31306d
            identity = optarg;
Packit Service 31306d
            break;
Packit Service 31306d
        case 'C':
Packit Service 31306d
            compress++;
Packit Service 31306d
            break;
Packit Service 31306d
        case '2':
Packit Service 31306d
            break;
Packit Service 31306d
        case '1':
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            {
Packit Service 31306d
                char optv[3] = "- ";
Packit Service 31306d
                optv[1] = optopt;
Packit Service 31306d
                tmp = realloc(save, (current + 1) * sizeof(char*));
Packit Service 31306d
                if (tmp == NULL) {
Packit Service 31306d
                    SAFE_FREE(save);
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                save = tmp;
Packit Service 31306d
                save[current] = strdup(optv);
Packit Service 31306d
                if (save[current] == NULL) {
Packit Service 31306d
                    SAFE_FREE(save);
Packit Service 31306d
                    ssh_set_error_oom(session);
Packit Service 31306d
                    return -1;
Packit Service 31306d
                }
Packit Service 31306d
                current++;
Packit Service 31306d
                if (optarg) {
Packit Service 31306d
                    save[current++] = argv[optind + 1];
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
        } /* switch */
Packit Service 31306d
    } /* while */
Packit Service 31306d
    opterr = saveopterr;
Packit Service 31306d
    tmp = realloc(save, (current + (argc - optind)) * sizeof(char*));
Packit Service 31306d
    if (tmp == NULL) {
Packit Service 31306d
        SAFE_FREE(save);
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
    save = tmp;
Packit Service 31306d
    while (optind < argc) {
Packit Service 31306d
        tmp = realloc(save, (current + 1) * sizeof(char*));
Packit Service 31306d
        if (tmp == NULL) {
Packit Service 31306d
            SAFE_FREE(save);
Packit Service 31306d
            ssh_set_error_oom(session);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        save = tmp;
Packit Service 31306d
        save[current] = argv[optind];
Packit Service 31306d
        current++;
Packit Service 31306d
        optind++;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (usersa && usedss) {
Packit Service 31306d
        ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
Packit Service 31306d
        cont = 0;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_set_log_level(debuglevel);
Packit Service 31306d
Packit Service 31306d
    optind = saveoptind;
Packit Service 31306d
Packit Service 31306d
    if(!cont) {
Packit Service 31306d
        SAFE_FREE(save);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* first recopy the save vector into the original's */
Packit Service 31306d
    for (i = 0; i < current; i++) {
Packit Service 31306d
        /* don't erase argv[0] */
Packit Service 31306d
        argv[ i + 1] = save[i];
Packit Service 31306d
    }
Packit Service 31306d
    argv[current + 1] = NULL;
Packit Service 31306d
    *argcptr = current + 1;
Packit Service 31306d
    SAFE_FREE(save);
Packit Service 31306d
Packit Service 31306d
    /* set a new option struct */
Packit Service 31306d
    if (compress) {
Packit Service 31306d
        if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
Packit Service 31306d
            cont = 0;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (cont && cipher) {
Packit Service 31306d
        if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) {
Packit Service 31306d
            cont = 0;
Packit Service 31306d
        }
Packit Service 31306d
        if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) {
Packit Service 31306d
            cont = 0;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (cont && user) {
Packit Service 31306d
        if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
Packit Service 31306d
            cont = 0;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (cont && identity) {
Packit Service 31306d
        if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) {
Packit Service 31306d
            cont = 0;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (port != NULL) {
Packit Service 31306d
        ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (!cont) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
#endif
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Parse the ssh config file.
Packit Service 31306d
 *
Packit Service 31306d
 * This should be the last call of all options, it may overwrite options which
Packit Service 31306d
 * are already set. It requires that the host name is already set with
Packit Service 31306d
 * ssh_options_set_host().
Packit Service 31306d
 *
Packit Service 31306d
 * @param  session      SSH session handle
Packit Service 31306d
 *
Packit Service 31306d
 * @param  filename     The options file to use, if NULL the default
Packit Service 31306d
 *                      ~/.ssh/config will be used.
Packit Service 31306d
 *
Packit Service 31306d
 * @return 0 on success, < 0 on error.
Packit Service 31306d
 *
Packit Service 31306d
 * @see ssh_options_set_host()
Packit Service 31306d
 */
Packit Service 31306d
int ssh_options_parse_config(ssh_session session, const char *filename) {
Packit Service 31306d
  char *expanded_filename;
Packit Service 31306d
  int r;
Packit Service 31306d
Packit Service 31306d
  if (session == NULL) {
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
  if (session->opts.host == NULL) {
Packit Service 31306d
    ssh_set_error_invalid(session);
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (session->opts.sshdir == NULL) {
Packit Service 31306d
      r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
Packit Service 31306d
      if (r < 0) {
Packit Service 31306d
          ssh_set_error_oom(session);
Packit Service 31306d
          return -1;
Packit Service 31306d
      }
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  /* set default filename */
Packit Service 31306d
  if (filename == NULL) {
Packit Service 31306d
    expanded_filename = ssh_path_expand_escape(session, "%d/config");
Packit Service 31306d
  } else {
Packit Service 31306d
    expanded_filename = ssh_path_expand_escape(session, filename);
Packit Service 31306d
  }
Packit Service 31306d
  if (expanded_filename == NULL) {
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  r = ssh_config_parse_file(session, expanded_filename);
Packit Service 31306d
  if (r < 0) {
Packit Service 31306d
      goto out;
Packit Service 31306d
  }
Packit Service 31306d
  if (filename == NULL) {
Packit Service 31306d
      r = ssh_config_parse_file(session, GLOBAL_CLIENT_CONFIG);
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  /* Do not process the default configuration as part of connection again */
Packit Service 31306d
  session->opts.config_processed = true;
Packit Service 31306d
out:
Packit Service 31306d
  free(expanded_filename);
Packit Service 31306d
  return r;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int ssh_options_apply(ssh_session session) {
Packit Service 31306d
    struct ssh_iterator *it;
Packit Service 31306d
    char *tmp;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (session->opts.sshdir == NULL) {
Packit Service 31306d
        rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->opts.username == NULL) {
Packit Service 31306d
        rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->opts.knownhosts == NULL) {
Packit Service 31306d
        tmp = ssh_path_expand_escape(session, "%d/known_hosts");
Packit Service 31306d
    } else {
Packit Service 31306d
        tmp = ssh_path_expand_escape(session, session->opts.knownhosts);
Packit Service 31306d
    }
Packit Service 31306d
    if (tmp == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
    free(session->opts.knownhosts);
Packit Service 31306d
    session->opts.knownhosts = tmp;
Packit Service 31306d
Packit Service 31306d
    if (session->opts.global_knownhosts == NULL) {
Packit Service 31306d
        tmp = strdup("/etc/ssh/ssh_known_hosts");
Packit Service 31306d
    } else {
Packit Service 31306d
        tmp = ssh_path_expand_escape(session, session->opts.global_knownhosts);
Packit Service 31306d
    }
Packit Service 31306d
    if (tmp == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
    free(session->opts.global_knownhosts);
Packit Service 31306d
    session->opts.global_knownhosts = tmp;
Packit Service 31306d
Packit Service 31306d
    if (session->opts.ProxyCommand != NULL) {
Packit Service 31306d
        tmp = ssh_path_expand_escape(session, session->opts.ProxyCommand);
Packit Service 31306d
        if (tmp == NULL) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        free(session->opts.ProxyCommand);
Packit Service 31306d
        session->opts.ProxyCommand = tmp;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    for (it = ssh_list_get_iterator(session->opts.identity);
Packit Service 31306d
         it != NULL;
Packit Service 31306d
         it = it->next) {
Packit Service 31306d
        char *id = (char *) it->data;
Packit Service 31306d
        if (strncmp(id, "pkcs11:", 6) == 0) {
Packit Service 31306d
            /* PKCS#11 URIs are using percent-encoding so we can not mix
Packit Service 31306d
             * it with ssh expansion of ssh escape characters.
Packit Service 31306d
             * Skip these identities now, before we will have PKCS#11 support
Packit Service 31306d
             */
Packit Service 31306d
             continue;
Packit Service 31306d
        }
Packit Service 31306d
        tmp = ssh_path_expand_escape(session, id);
Packit Service 31306d
        if (tmp == NULL) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        free(id);
Packit Service 31306d
        it->data = tmp;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @} */
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
/**
Packit Service 31306d
 * @addtogroup libssh_server
Packit Service 31306d
 * @{
Packit Service 31306d
 */
Packit Service 31306d
static int ssh_bind_set_key(ssh_bind sshbind, char **key_loc,
Packit Service 31306d
                            const void *value) {
Packit Service 31306d
    if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
    } else {
Packit Service 31306d
        SAFE_FREE(*key_loc);
Packit Service 31306d
        *key_loc = strdup(value);
Packit Service 31306d
        if (*key_loc == NULL) {
Packit Service 31306d
            ssh_set_error_oom(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int ssh_bind_set_algo(ssh_bind sshbind,
Packit Service 31306d
                             enum ssh_kex_types_e algo,
Packit Service 31306d
                             const char *list)
Packit Service 31306d
{
Packit Service 31306d
    char *p = NULL;
Packit Service 31306d
Packit Service 31306d
    if (ssh_fips_mode()) {
Packit Service 31306d
        p = ssh_keep_fips_algos(algo, list);
Packit Service 31306d
    } else {
Packit Service 31306d
        p = ssh_keep_known_algos(algo, list);
Packit Service 31306d
    }
Packit Service 31306d
    if (p == NULL) {
Packit Service 31306d
        ssh_set_error(sshbind, SSH_REQUEST_DENIED,
Packit Service 31306d
                      "Setting method: no algorithm for method \"%s\" (%s)",
Packit Service 31306d
                      ssh_kex_get_description(algo), list);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SAFE_FREE(sshbind->wanted_methods[algo]);
Packit Service 31306d
    sshbind->wanted_methods[algo] = p;
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Set options for an SSH server bind.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  sshbind      The ssh server bind to configure.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  type         The option type to set. This should be one of the
Packit Service 31306d
 *                      following:
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_HOSTKEY:
Packit Service 31306d
 *                        Set the path to an ssh host key, regardless
Packit Service 31306d
 *                        of type.  Only one key from per key type
Packit Service 31306d
 *                        (RSA, DSA, ECDSA) is allowed in an ssh_bind
Packit Service 31306d
 *                        at a time, and later calls to this function
Packit Service 31306d
 *                        with this option for the same key type will
Packit Service 31306d
 *                        override prior calls (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_BINDADDR:
Packit Service 31306d
 *                        Set the IP address to bind (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_BINDPORT:
Packit Service 31306d
 *                        Set the port to bind (unsigned int *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_BINDPORT_STR:
Packit Service 31306d
 *                        Set the port to bind (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_LOG_VERBOSITY:
Packit Service 31306d
 *                        Set the session logging verbosity (int *).
Packit Service 31306d
 *                        The logging verbosity should have one of the
Packit Service 31306d
 *                        following values, which are listed in order
Packit Service 31306d
 *                        of increasing verbosity.  Every log message
Packit Service 31306d
 *                        with verbosity less than or equal to the
Packit Service 31306d
 *                        logging verbosity will be shown.
Packit Service 31306d
 *                        - SSH_LOG_NOLOG: No logging
Packit Service 31306d
 *                        - SSH_LOG_WARNING: Only warnings
Packit Service 31306d
 *                        - SSH_LOG_PROTOCOL: High level protocol information
Packit Service 31306d
 *                        - SSH_LOG_PACKET: Lower level protocol infomations, packet level
Packit Service 31306d
 *                        - SSH_LOG_FUNCTIONS: Every function path
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
Packit Service 31306d
 *                        Set the session logging verbosity via a
Packit Service 31306d
 *                        string that will be converted to a numerical
Packit Service 31306d
 *                        value (e.g. "3") and interpreted according
Packit Service 31306d
 *                        to the values of
Packit Service 31306d
 *                        SSH_BIND_OPTIONS_LOG_VERBOSITY above (const
Packit Service 31306d
 *                        char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_DSAKEY:
Packit Service 31306d
 *                        Set the path to the ssh host dsa key, SSHv2
Packit Service 31306d
 *                        only (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_RSAKEY:
Packit Service 31306d
 *                        Set the path to the ssh host rsa key, SSHv2
Packit Service 31306d
 *                        only (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_ECDSAKEY:
Packit Service 31306d
 *                        Set the path to the ssh host ecdsa key,
Packit Service 31306d
 *                        SSHv2 only (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_BANNER:
Packit Service 31306d
 *                        Set the server banner sent to clients (const char *).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_IMPORT_KEY:
Packit Service 31306d
 *                        Set the Private Key for the server directly (ssh_key)
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_CIPHERS_C_S:
Packit Service 31306d
 *                        Set the symmetric cipher client to server (const char *,
Packit Service 31306d
 *                        comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_CIPHERS_S_C:
Packit Service 31306d
 *                        Set the symmetric cipher server to client (const char *,
Packit Service 31306d
 *                        comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_KEY_EXCHANGE:
Packit Service 31306d
 *                        Set the key exchange method to be used (const char *,
Packit Service 31306d
 *                        comma-separated list). ex:
Packit Service 31306d
 *                        "ecdh-sha2-nistp256,diffie-hellman-group14-sha1"
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_HMAC_C_S:
Packit Service 31306d
 *                        Set the Message Authentication Code algorithm client
Packit Service 31306d
 *                        to server (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_HMAC_S_C:
Packit Service 31306d
 *                        Set the Message Authentication Code algorithm server
Packit Service 31306d
 *                        to client (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_CONFIG_DIR:
Packit Service 31306d
 *                        Set the directory (const char *, format string)
Packit Service 31306d
 *                        to be used when the "%d" scape is used when providing
Packit Service 31306d
 *                        paths of configuration files to
Packit Service 31306d
 *                        ssh_bind_options_parse_config().
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_PROCESS_CONFIG
Packit Service 31306d
 *                        Set it to false to disable automatic processing of
Packit Service 31306d
 *                        system-wide configuration files. LibSSH automatically
Packit Service 31306d
 *                        uses these configuration files otherwise. This
Packit Service 31306d
 *                        option will only have effect if set before any call
Packit Service 31306d
 *                        to ssh_bind_options_parse_config() (bool).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES:
Packit Service 31306d
 *                        Set the public key algorithm accepted by the server
Packit Service 31306d
 *                        (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 *                      - SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS:
Packit Service 31306d
 *                        Set the list of allowed hostkey signatures algorithms
Packit Service 31306d
 *                        to offer to the client, ordered by preference. This
Packit Service 31306d
 *                        list is used as a filter when creating the list of
Packit Service 31306d
 *                        algorithms to offer to the client: first the list of
Packit Service 31306d
 *                        possible algorithms is created from the list of keys
Packit Service 31306d
 *                        set and then filtered against this list.
Packit Service 31306d
 *                        (const char *, comma-separated list).
Packit Service 31306d
 *
Packit Service 31306d
 * @param  value        The value to set. This is a generic pointer and the
Packit Service 31306d
 *                      datatype which should be used is described at the
Packit Service 31306d
 *                      corresponding value of type above.
Packit Service 31306d
 *
Packit Service 31306d
 * @return              0 on success, < 0 on error, invalid option, or parameter.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
Packit Service 31306d
    const void *value)
Packit Service 31306d
{
Packit Service 31306d
  char *p, *q;
Packit Service 31306d
  const char *v;
Packit Service 31306d
  int i, rc;
Packit Service 31306d
Packit Service 31306d
  if (sshbind == NULL) {
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  switch (type) {
Packit Service 31306d
    case SSH_BIND_OPTIONS_HOSTKEY:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
      } else {
Packit Service 31306d
          int key_type;
Packit Service 31306d
          ssh_key key;
Packit Service 31306d
          ssh_key *bind_key_loc = NULL;
Packit Service 31306d
          char **bind_key_path_loc;
Packit Service 31306d
Packit Service 31306d
          rc = ssh_pki_import_privkey_file(value, NULL, NULL, NULL, &key);
Packit Service 31306d
          if (rc != SSH_OK) {
Packit Service 31306d
              return -1;
Packit Service 31306d
          }
Packit Service 31306d
          key_type = ssh_key_type(key);
Packit Service 31306d
          switch (key_type) {
Packit Service 31306d
          case SSH_KEYTYPE_DSS:
Packit Service 31306d
#ifdef HAVE_DSA
Packit Service 31306d
              bind_key_loc = &sshbind->dsa;
Packit Service 31306d
              bind_key_path_loc = &sshbind->dsakey;
Packit Service 31306d
#else
Packit Service 31306d
              ssh_set_error(sshbind,
Packit Service 31306d
                      SSH_FATAL,
Packit Service 31306d
                      "DSS key used and libssh compiled "
Packit Service 31306d
                      "without DSA support");
Packit Service 31306d
#endif
Packit Service 31306d
              break;
Packit Service 31306d
          case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
          case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
          case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_ECC
Packit Service 31306d
              bind_key_loc = &sshbind->ecdsa;
Packit Service 31306d
              bind_key_path_loc = &sshbind->ecdsakey;
Packit Service 31306d
#else
Packit Service 31306d
              ssh_set_error(sshbind,
Packit Service 31306d
                            SSH_FATAL,
Packit Service 31306d
                            "ECDSA key used and libssh compiled "
Packit Service 31306d
                            "without ECDSA support");
Packit Service 31306d
#endif
Packit Service 31306d
              break;
Packit Service 31306d
          case SSH_KEYTYPE_RSA:
Packit Service 31306d
              bind_key_loc = &sshbind->rsa;
Packit Service 31306d
              bind_key_path_loc = &sshbind->rsakey;
Packit Service 31306d
              break;
Packit Service 31306d
          case SSH_KEYTYPE_ED25519:
Packit Service 31306d
		  bind_key_loc = &sshbind->ed25519;
Packit Service 31306d
		  bind_key_path_loc = &sshbind->ed25519key;
Packit Service 31306d
		  break;
Packit Service 31306d
          default:
Packit Service 31306d
              ssh_set_error(sshbind,
Packit Service 31306d
                            SSH_FATAL,
Packit Service 31306d
                            "Unsupported key type %d", key_type);
Packit Service 31306d
          }
Packit Service 31306d
Packit Service 31306d
          if (bind_key_loc == NULL) {
Packit Service 31306d
              ssh_key_free(key);
Packit Service 31306d
              return -1;
Packit Service 31306d
          }
Packit Service 31306d
Packit Service 31306d
          /* Set the location of the key on disk even though we don't
Packit Service 31306d
             need it in case some other function wants it */
Packit Service 31306d
          rc = ssh_bind_set_key(sshbind, bind_key_path_loc, value);
Packit Service 31306d
          if (rc < 0) {
Packit Service 31306d
              ssh_key_free(key);
Packit Service 31306d
              return -1;
Packit Service 31306d
          }
Packit Service 31306d
          ssh_key_free(*bind_key_loc);
Packit Service 31306d
          *bind_key_loc = key;
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_IMPORT_KEY:
Packit Service 31306d
        if (value == NULL) {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            int key_type;
Packit Service 31306d
            ssh_key *bind_key_loc = NULL;
Packit Service 31306d
            ssh_key key = (ssh_key)value;
Packit Service 31306d
Packit Service 31306d
            key_type = ssh_key_type(key);
Packit Service 31306d
            switch (key_type) {
Packit Service 31306d
                case SSH_KEYTYPE_DSS:
Packit Service 31306d
#ifdef HAVE_DSA
Packit Service 31306d
                    bind_key_loc = &sshbind->dsa;
Packit Service 31306d
#else
Packit Service 31306d
                    ssh_set_error(sshbind,
Packit Service 31306d
                                  SSH_FATAL,
Packit Service 31306d
                                  "DSA key used and libssh compiled "
Packit Service 31306d
                                  "without DSA support");
Packit Service 31306d
#endif
Packit Service 31306d
                    break;
Packit Service 31306d
                case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
                case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
                case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_ECC
Packit Service 31306d
                    bind_key_loc = &sshbind->ecdsa;
Packit Service 31306d
#else
Packit Service 31306d
                    ssh_set_error(sshbind,
Packit Service 31306d
                                  SSH_FATAL,
Packit Service 31306d
                                  "ECDSA key used and libssh compiled "
Packit Service 31306d
                                  "without ECDSA support");
Packit Service 31306d
#endif
Packit Service 31306d
                    break;
Packit Service 31306d
                case SSH_KEYTYPE_RSA:
Packit Service 31306d
                    bind_key_loc = &sshbind->rsa;
Packit Service 31306d
                    break;
Packit Service 31306d
                case SSH_KEYTYPE_ED25519:
Packit Service 31306d
                    bind_key_loc = &sshbind->ed25519;
Packit Service 31306d
                    break;
Packit Service 31306d
                default:
Packit Service 31306d
                    ssh_set_error(sshbind,
Packit Service 31306d
                                  SSH_FATAL,
Packit Service 31306d
                                  "Unsupported key type %d", key_type);
Packit Service 31306d
            }
Packit Service 31306d
            if (bind_key_loc == NULL)
Packit Service 31306d
                return -1;
Packit Service 31306d
            ssh_key_free(*bind_key_loc);
Packit Service 31306d
            *bind_key_loc = key;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_BINDADDR:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
      } else {
Packit Service 31306d
        SAFE_FREE(sshbind->bindaddr);
Packit Service 31306d
        sshbind->bindaddr = strdup(value);
Packit Service 31306d
        if (sshbind->bindaddr == NULL) {
Packit Service 31306d
          ssh_set_error_oom(sshbind);
Packit Service 31306d
          return -1;
Packit Service 31306d
        }
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_BINDPORT:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
      } else {
Packit Service 31306d
        int *x = (int *) value;
Packit Service 31306d
        sshbind->bindport = *x & 0xffffU;
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_BINDPORT_STR:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        sshbind->bindport = 22 & 0xffffU;
Packit Service 31306d
      } else {
Packit Service 31306d
        q = strdup(value);
Packit Service 31306d
        if (q == NULL) {
Packit Service 31306d
          ssh_set_error_oom(sshbind);
Packit Service 31306d
          return -1;
Packit Service 31306d
        }
Packit Service 31306d
        i = strtol(q, &p, 10);
Packit Service 31306d
        if (q == p) {
Packit Service 31306d
          SAFE_FREE(q);
Packit Service 31306d
        }
Packit Service 31306d
        SAFE_FREE(q);
Packit Service 31306d
Packit Service 31306d
        sshbind->bindport = i & 0xffffU;
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_LOG_VERBOSITY:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
      } else {
Packit Service 31306d
        int *x = (int *) value;
Packit Service 31306d
        ssh_set_log_level(*x & 0xffffU);
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
      	ssh_set_log_level(0);
Packit Service 31306d
      } else {
Packit Service 31306d
        q = strdup(value);
Packit Service 31306d
        if (q == NULL) {
Packit Service 31306d
          ssh_set_error_oom(sshbind);
Packit Service 31306d
          return -1;
Packit Service 31306d
        }
Packit Service 31306d
        i = strtol(q, &p, 10);
Packit Service 31306d
        if (q == p) {
Packit Service 31306d
          SAFE_FREE(q);
Packit Service 31306d
        }
Packit Service 31306d
        SAFE_FREE(q);
Packit Service 31306d
Packit Service 31306d
        ssh_set_log_level(i & 0xffffU);
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_DSAKEY:
Packit Service 31306d
        rc = ssh_bind_set_key(sshbind, &sshbind->dsakey, value);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_RSAKEY:
Packit Service 31306d
        rc = ssh_bind_set_key(sshbind, &sshbind->rsakey, value);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_ECDSAKEY:
Packit Service 31306d
        rc = ssh_bind_set_key(sshbind, &sshbind->ecdsakey, value);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_BANNER:
Packit Service 31306d
      if (value == NULL) {
Packit Service 31306d
        ssh_set_error_invalid(sshbind);
Packit Service 31306d
        return -1;
Packit Service 31306d
      } else {
Packit Service 31306d
        SAFE_FREE(sshbind->banner);
Packit Service 31306d
        sshbind->banner = strdup(value);
Packit Service 31306d
        if (sshbind->banner == NULL) {
Packit Service 31306d
          ssh_set_error_oom(sshbind);
Packit Service 31306d
          return -1;
Packit Service 31306d
        }
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_CIPHERS_C_S:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            if (ssh_bind_set_algo(sshbind, SSH_CRYPT_C_S, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_CIPHERS_S_C:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            if (ssh_bind_set_algo(sshbind, SSH_CRYPT_S_C, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_KEY_EXCHANGE:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            rc = ssh_bind_set_algo(sshbind, SSH_KEX, v);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_HMAC_C_S:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            if (ssh_bind_set_algo(sshbind, SSH_MAC_C_S, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
     case SSH_BIND_OPTIONS_HMAC_S_C:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            if (ssh_bind_set_algo(sshbind, SSH_MAC_S_C, v) < 0)
Packit Service 31306d
                return -1;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_CONFIG_DIR:
Packit Service 31306d
        v = value;
Packit Service 31306d
        SAFE_FREE(sshbind->config_dir);
Packit Service 31306d
        if (v == NULL) {
Packit Service 31306d
            break;
Packit Service 31306d
        } else if (v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            sshbind->config_dir = ssh_path_expand_tilde(v);
Packit Service 31306d
            if (sshbind->config_dir == NULL) {
Packit Service 31306d
                ssh_set_error_oom(sshbind);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            if (ssh_fips_mode()) {
Packit Service 31306d
                p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
Packit Service 31306d
            } else {
Packit Service 31306d
                p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
Packit Service 31306d
            }
Packit Service 31306d
            if (p == NULL) {
Packit Service 31306d
                ssh_set_error(sshbind, SSH_REQUEST_DENIED,
Packit Service 31306d
                    "Setting method: no known public key algorithm (%s)",
Packit Service 31306d
                     v);
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            SAFE_FREE(sshbind->pubkey_accepted_key_types);
Packit Service 31306d
            sshbind->pubkey_accepted_key_types = p;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS:
Packit Service 31306d
        v = value;
Packit Service 31306d
        if (v == NULL || v[0] == '\0') {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            rc = ssh_bind_set_algo(sshbind, SSH_HOSTKEYS, v);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                return -1;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_BIND_OPTIONS_PROCESS_CONFIG:
Packit Service 31306d
        if (value == NULL) {
Packit Service 31306d
            ssh_set_error_invalid(sshbind);
Packit Service 31306d
            return -1;
Packit Service 31306d
        } else {
Packit Service 31306d
            bool *x = (bool *)value;
Packit Service 31306d
            sshbind->config_processed = !(*x);
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    default:
Packit Service 31306d
      ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
Packit Service 31306d
      return -1;
Packit Service 31306d
    break;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static char *ssh_bind_options_expand_escape(ssh_bind sshbind, const char *s)
Packit Service 31306d
{
Packit Service 31306d
    char buf[MAX_BUF_SIZE];
Packit Service 31306d
    char *r, *x = NULL;
Packit Service 31306d
    const char *p;
Packit Service 31306d
    size_t i, l;
Packit Service 31306d
Packit Service 31306d
    r = ssh_path_expand_tilde(s);
Packit Service 31306d
    if (r == NULL) {
Packit Service 31306d
        ssh_set_error_oom(sshbind);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (strlen(r) > MAX_BUF_SIZE) {
Packit Service 31306d
        ssh_set_error(sshbind, SSH_FATAL, "string to expand too long");
Packit Service 31306d
        free(r);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    p = r;
Packit Service 31306d
    buf[0] = '\0';
Packit Service 31306d
Packit Service 31306d
    for (i = 0; *p != '\0'; p++) {
Packit Service 31306d
        if (*p != '%') {
Packit Service 31306d
            buf[i] = *p;
Packit Service 31306d
            i++;
Packit Service 31306d
            if (i >= MAX_BUF_SIZE) {
Packit Service 31306d
                free(r);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
            buf[i] = '\0';
Packit Service 31306d
            continue;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        p++;
Packit Service 31306d
        if (*p == '\0') {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        switch (*p) {
Packit Service 31306d
            case 'd':
Packit Service 31306d
                x = strdup(sshbind->config_dir);
Packit Service 31306d
                break;
Packit Service 31306d
            default:
Packit Service 31306d
                ssh_set_error(sshbind, SSH_FATAL,
Packit Service 31306d
                        "Wrong escape sequence detected");
Packit Service 31306d
                free(r);
Packit Service 31306d
                return NULL;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        if (x == NULL) {
Packit Service 31306d
            ssh_set_error_oom(sshbind);
Packit Service 31306d
            free(r);
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        i += strlen(x);
Packit Service 31306d
        if (i >= MAX_BUF_SIZE) {
Packit Service 31306d
            ssh_set_error(sshbind, SSH_FATAL,
Packit Service 31306d
                    "String too long");
Packit Service 31306d
            free(x);
Packit Service 31306d
            free(r);
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
        l = strlen(buf);
Packit Service 31306d
        strncpy(buf + l, x, sizeof(buf) - l - 1);
Packit Service 31306d
        buf[i] = '\0';
Packit Service 31306d
        SAFE_FREE(x);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    free(r);
Packit Service 31306d
    return strdup(buf);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Parse a ssh bind options configuration file.
Packit Service 31306d
 *
Packit Service 31306d
 * This parses the options file and set them to the ssh_bind handle provided. If
Packit Service 31306d
 * an option was previously set, it is overridden. If the global configuration
Packit Service 31306d
 * hasn't been processed yet, it is processed prior to the provided file.
Packit Service 31306d
 *
Packit Service 31306d
 * @param  sshbind      SSH bind handle
Packit Service 31306d
 *
Packit Service 31306d
 * @param  filename     The options file to use; if NULL only the global
Packit Service 31306d
 *                      configuration is parsed and applied (if it haven't been
Packit Service 31306d
 *                      processed before).
Packit Service 31306d
 *
Packit Service 31306d
 * @return 0 on success, < 0 on error.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_bind_options_parse_config(ssh_bind sshbind, const char *filename)
Packit Service 31306d
{
Packit Service 31306d
    int rc = 0;
Packit Service 31306d
    char *expanded_filename;
Packit Service 31306d
Packit Service 31306d
    if (sshbind == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* If the global default configuration hasn't been processed yet, process it
Packit Service 31306d
     * before the provided configuration. */
Packit Service 31306d
    if (!(sshbind->config_processed)) {
Packit Service 31306d
        rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG);
Packit Service 31306d
        if (rc != 0) {
Packit Service 31306d
            return rc;
Packit Service 31306d
        }
Packit Service 31306d
        sshbind->config_processed = true;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (filename != NULL) {
Packit Service 31306d
        expanded_filename = ssh_bind_options_expand_escape(sshbind, filename);
Packit Service 31306d
        if (expanded_filename == NULL) {
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* Apply the user provided configuration */
Packit Service 31306d
        rc = ssh_bind_config_parse_file(sshbind, expanded_filename);
Packit Service 31306d
        free(expanded_filename);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
/** @} */