diff options
author | Andreas Schneider <asn@cynapses.org> | 2010-09-06 14:28:38 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cynapses.org> | 2010-09-06 14:28:38 +0200 |
commit | f7842e3a4b9acea2126ff725f993c299aef0e6db (patch) | |
tree | 18239f819a5edbcfc7f2961c48f3f9297314ef22 /src/options.c | |
parent | 38421403d2dc45636e597f2a909daa6ae31976de (diff) | |
download | libssh-f7842e3a4b9acea2126ff725f993c299aef0e6db.tar.gz libssh-f7842e3a4b9acea2126ff725f993c299aef0e6db.tar.xz libssh-f7842e3a4b9acea2126ff725f993c299aef0e6db.zip |
misc: Rename libssh/ to src/
Diffstat (limited to 'src/options.c')
-rw-r--r-- | src/options.c | 1138 |
1 files changed, 1138 insertions, 0 deletions
diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..9cbaf6f --- /dev/null +++ b/src/options.c @@ -0,0 +1,1138 @@ +/* + * options.c - handle pre-connection options + * + * This file is part of the SSH Library + * + * Copyright (c) 2003-2008 by Aris Adamantiadis + * Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org> + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef _WIN32 +#include <pwd.h> +#else +#include <winsock2.h> +#endif +#include <sys/types.h> +#include "libssh/priv.h" +#include "libssh/session.h" +#include "libssh/misc.h" +#ifdef WITH_SERVER +#include "libssh/server.h" +#endif + +/** + * @addtogroup libssh_session + * @{ + */ + +/** + * @brief Duplicate the options of a session structure. + * + * If you make several sessions with the same options this is useful. You + * cannot use twice the same option structure in ssh_session_connect. + * + * @param src The session to use to copy the options. + * + * @param dest The session to copy the options to. + * + * @returns 0 on sucess, -1 on error with errno set. + * + * @see ssh_session_connect() + */ +int ssh_options_copy(ssh_session src, ssh_session *dest) { + ssh_session new; + int i; + + if (src == NULL || dest == NULL || *dest == NULL) { + return -1; + } + + new = *dest; + + if (src->username) { + new->username = strdup(src->username); + if (new->username == NULL) { + return -1; + } + } + + if (src->host) { + new->host = strdup(src->host); + if (new->host == NULL) { + return -1; + } + } + + if (src->identity) { + struct ssh_iterator *it; + + new->identity = ssh_list_new(); + if (new->identity == NULL) { + return -1; + } + + it = ssh_list_get_iterator(src->identity); + while (it) { + char *id; + int rc; + + id = strdup((char *) it->data); + if (id == NULL) { + return -1; + } + + rc = ssh_list_append(new->identity, id); + if (rc < 0) { + return -1; + } + it = it->next; + } + } + + if (src->sshdir) { + new->sshdir = strdup(src->sshdir); + if (new->sshdir == NULL) { + return -1; + } + } + + if (src->knownhosts) { + new->knownhosts = strdup(src->knownhosts); + if (new->knownhosts == NULL) { + return -1; + } + } + + for (i = 0; i < 10; ++i) { + if (src->wanted_methods[i]) { + new->wanted_methods[i] = strdup(src->wanted_methods[i]); + if (new->wanted_methods[i] == NULL) { + return -1; + } + } + } + + if(src->ProxyCommand) { + new->ProxyCommand = strdup(src->ProxyCommand); + if(new->ProxyCommand == NULL) + return -1; + } + new->fd = src->fd; + new->port = src->port; + new->callbacks = src->callbacks; + new->timeout = src->timeout; + new->timeout_usec = src->timeout_usec; + new->ssh2 = src->ssh2; + new->ssh1 = src->ssh1; + new->log_verbosity = src->log_verbosity; + + return 0; +} + +int ssh_options_set_algo(ssh_session session, int algo, + const char *list) { + if (!verify_existing_algo(algo, list)) { + ssh_set_error(session, SSH_REQUEST_DENIED, + "Setting method: no algorithm for method \"%s\" (%s)\n", + ssh_kex_nums[algo], list); + return -1; + } + + SAFE_FREE(session->wanted_methods[algo]); + session->wanted_methods[algo] = strdup(list); + if (session->wanted_methods[algo] == NULL) { + ssh_set_error_oom(session); + return -1; + } + + return 0; +} + +/** + * @brief This function can set all possible ssh options. + * + * @param session An allocated ssh option structure. + * + * @param type The option type to set. This could be one of the + * following: + * + * - SSH_OPTIONS_HOST: + * The hostname or ip address to connect to (string). + * + * - SSH_OPTIONS_PORT: + * The port to connect to (integer). + * + * - SSH_OPTIONS_PORT_STR: + * The port to connect to (string). + * + * - SSH_OPTIONS_FD: + * The file descriptor to use (socket_t).\n + * \n + * If you wish to open the socket yourself for a reason + * or another, set the file descriptor. Don't forget to + * set the hostname as the hostname is used as a key in + * the known_host mechanism. + * + * - SSH_OPTIONS_BINDADDR: + * The address to bind the client to (string). + * + * - SSH_OPTIONS_USER: + * The username for authentication (string).\n + * \n + * If the value is NULL, the username is set to the + * default username. + * + * - SSH_OPTIONS_SSH_DIR: + * Set the ssh directory (format string).\n + * \n + * If the value is NULL, the directory is set to the + * default ssh directory.\n + * \n + * The ssh directory is used for files like known_hosts + * and identity (private and public key). It may include + * "%s" which will be replaced by the user home + * directory. + * + * - SSH_OPTIONS_KNOWNHOSTS: + * Set the known hosts file name (format string).\n + * \n + * If the value is NULL, the directory is set to the + * default known hosts file, normally + * ~/.ssh/known_hosts.\n + * \n + * The known hosts file is used to certify remote hosts + * are genuine. It may include "%s" which will be + * replaced by the user home directory. + * + * - SSH_OPTIONS_IDENTITY: + * Set the identity file name (format string).\n + * \n + * By default identity, id_dsa and id_rsa are checked.\n + * \n + * The identity file used authenticate with public key. + * It may include "%s" which will be replaced by the + * user home directory. + * + * - SSH_OPTIONS_TIMEOUT: + * Set a timeout for the connection in seconds (integer). + * + * - SSH_OPTIONS_TIMEOUT_USEC: + * Set a timeout for the connection in micro seconds + * (integer). + * + * - SSH_OPTIONS_SSH1: + * Allow or deny the connection to SSH1 servers + * (integer). + * + * - SSH_OPTIONS_SSH2: + * Allow or deny the connection to SSH2 servers + * (integer). + * + * - SSH_OPTIONS_LOG_VERBOSITY: + * Set the session logging verbosity (integer).\n + * \n + * The verbosity of the messages. Every log smaller or + * equal to verbosity will be shown. + * - SSH_LOG_NOLOG: No logging + * - SSH_LOG_RARE: Rare conditions or warnings + * - SSH_LOG_ENTRY: API-accessible entrypoints + * - SSH_LOG_PACKET: Packet id and size + * - SSH_LOG_FUNCTIONS: Function entering and leaving + * + * - SSH_OPTIONS_LOG_VERBOSITY_STR: + * Set the session logging verbosity (string).\n + * \n + * The verbosity of the messages. Every log smaller or + * equal to verbosity will be shown. + * - SSH_LOG_NOLOG: No logging + * - SSH_LOG_RARE: Rare conditions or warnings + * - SSH_LOG_ENTRY: API-accessible entrypoints + * - SSH_LOG_PACKET: Packet id and size + * - SSH_LOG_FUNCTIONS: Function entering and leaving + * \n + * See the corresponding numbers in libssh.h. + * + * - SSH_OPTTIONS_AUTH_CALLBACK: + * Set a callback to use your own authentication function + * (function pointer). + * + * - SSH_OPTTIONS_AUTH_USERDATA: + * Set the user data passed to the authentication + * function (generic pointer). + * + * - SSH_OPTTIONS_LOG_CALLBACK: + * Set a callback to use your own logging function + * (function pointer). + * + * - SSH_OPTTIONS_LOG_USERDATA: + * Set the user data passed to the logging function + * (generic pointer). + * + * - SSH_OPTTIONS_STATUS_CALLBACK: + * Set a callback to show connection status in realtime + * (function pointer).\n + * \n + * @code + * fn(void *arg, float status) + * @endcode + * \n + * During ssh_connect(), libssh will call the callback + * with status from 0.0 to 1.0. + * + * - SSH_OPTTIONS_STATUS_ARG: + * Set the status argument which should be passed to the + * status callback (generic pointer). + * + * - SSH_OPTIONS_CIPHERS_C_S: + * Set the symmetric cipher client to server (string, + * comma-separated list). + * + * - SSH_OPTIONS_CIPHERS_S_C: + * Set the symmetric cipher server to client (string, + * comma-separated list). + * + * - SSH_OPTIONS_COMPRESSION_C_S: + * Set the compression to use for client to server + * communication (string, "none" or "zlib"). + * + * - SSH_OPTIONS_COMPRESSION_S_C: + * Set the compression to use for server to client + * communication (string, "none" or "zlib"). + * + * - SSH_OPTIONS_HOSTKEYCHECK: + * Set the parameter StrictHostKeyChecking to avoid + * asking about a fingerprint + * - SSH_OPTIONS_PROXYCOMMAND: + * Set the command to be executed in order to connect to + * server. + * + * @param value The value to set. This is a generic pointer and the + * datatype which is used should be set according to the + * type set. + * + * @return 0 on success, < 0 on error. + */ +int ssh_options_set(ssh_session session, enum ssh_options_e type, + const void *value) { + char *p, *q; + long int i; + int rc; + + if (session == NULL) { + return -1; + } + + switch (type) { + case SSH_OPTIONS_HOST: + q = strdup(value); + if (q == NULL) { + ssh_set_error_oom(session); + return -1; + } + p = strchr(q, '@'); + + SAFE_FREE(session->host); + + if (p) { + *p = '\0'; + session->host = strdup(p + 1); + if (session->host == NULL) { + SAFE_FREE(q); + ssh_set_error_oom(session); + return -1; + } + + SAFE_FREE(session->username); + session->username = strdup(q); + SAFE_FREE(q); + if (session->username == NULL) { + ssh_set_error_oom(session); + return -1; + } + } else { + session->host = q; + } + break; + case SSH_OPTIONS_PORT: + if (value == NULL) { + session->port = 22 & 0xffff; + } else { + int *x = (int *) value; + + session->port = *x & 0xffff; + } + break; + case SSH_OPTIONS_PORT_STR: + if (value == NULL) { + session->port = 22 & 0xffff; + } else { + q = strdup(value); + if (q == NULL) { + ssh_set_error_oom(session); + return -1; + } + i = strtol(q, &p, 10); + if (q == p) { + SAFE_FREE(q); + } + SAFE_FREE(q); + + session->port = i & 0xffff; + } + break; + case SSH_OPTIONS_FD: + if (value == NULL) { + session->fd = SSH_INVALID_SOCKET; + } else { + socket_t *x = (socket_t *) value; + + session->fd = *x & 0xffff; + } + break; + case SSH_OPTIONS_BINDADDR: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } + q = strdup(value); + if (q == NULL) { + return -1; + } + SAFE_FREE(session->bindaddr); + session->bindaddr = q; + break; + case SSH_OPTIONS_USER: + SAFE_FREE(session->username); + if (value == NULL) { /* set default username */ + q = ssh_get_local_username(session); + if (q == NULL) { + return -1; + } + session->username = q; + } else { /* username provided */ + session->username = strdup(value); + if (session->username == NULL) { + ssh_set_error_oom(session); + return -1; + } + } + break; + case SSH_OPTIONS_SSH_DIR: + if (value == NULL) { + SAFE_FREE(session->sshdir); + + session->sshdir = ssh_path_expand_tilde("~/.ssh"); + if (session->sshdir == NULL) { + return -1; + } + } else { + SAFE_FREE(session->sshdir); + session->sshdir = ssh_path_expand_tilde(value); + if (session->sshdir == NULL) { + return -1; + } + } + break; + case SSH_OPTIONS_IDENTITY: + case SSH_OPTIONS_ADD_IDENTITY: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } + q = strdup(value); + if (q == NULL) { + return -1; + } + rc = ssh_list_prepend(session->identity, q); + if (rc < 0) { + return -1; + } + break; + case SSH_OPTIONS_KNOWNHOSTS: + if (value == NULL) { + SAFE_FREE(session->knownhosts); + if (session->sshdir == NULL) { + return -1; + } + session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts"); + if (session->knownhosts == NULL) { + return -1; + } + } else { + SAFE_FREE(session->knownhosts); + session->knownhosts = strdup(value); + if (session->knownhosts == NULL) { + return -1; + } + } + break; + case SSH_OPTIONS_TIMEOUT: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + long *x = (long *) value; + + session->timeout = *x & 0xffffffff; + } + break; + case SSH_OPTIONS_TIMEOUT_USEC: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + long *x = (long *) value; + + session->timeout_usec = *x & 0xffffffff; + } + break; + case SSH_OPTIONS_SSH1: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + int *x = (int *) value; + session->ssh1 = *x; + } + break; + case SSH_OPTIONS_SSH2: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + int *x = (int *) value; + session->ssh2 = *x & 0xffff; + } + break; + case SSH_OPTIONS_LOG_VERBOSITY: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + int *x = (int *) value; + + session->log_verbosity = *x & 0xffff; + } + break; + case SSH_OPTIONS_LOG_VERBOSITY_STR: + if (value == NULL) { + session->log_verbosity = 0 & 0xffff; + } else { + q = strdup(value); + if (q == NULL) { + ssh_set_error_oom(session); + return -1; + } + i = strtol(q, &p, 10); + if (q == p) { + SAFE_FREE(q); + } + SAFE_FREE(q); + + session->log_verbosity = i & 0xffff; + } + break; + case SSH_OPTIONS_CIPHERS_C_S: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + if (ssh_options_set_algo(session, SSH_CRYPT_C_S, value) < 0) + return -1; + } + break; + case SSH_OPTIONS_CIPHERS_S_C: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + if (ssh_options_set_algo(session, SSH_CRYPT_S_C, value) < 0) + return -1; + } + break; + case SSH_OPTIONS_COMPRESSION_C_S: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + if (ssh_options_set_algo(session, SSH_COMP_C_S, value) < 0) + return -1; + } + break; + case SSH_OPTIONS_COMPRESSION_S_C: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + if (ssh_options_set_algo(session, SSH_COMP_S_C, value) < 0) + return -1; + } + break; + case SSH_OPTIONS_HOSTKEYCHECK: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + session->StrictHostKeyChecking = *(int*)value; + } + break; + case SSH_OPTIONS_PROXYCOMMAND: + if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } else { + SAFE_FREE(session->ProxyCommand); + q = strdup(value); + if (q == NULL) { + return -1; + } + session->ProxyCommand = q; + } + break; + default: + ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); + return -1; + break; + } + + return 0; +} + + +/** + * @brief Parse command line arguments. + * + * This is a helper for your application to generate the appropriate + * options from the command line arguments.\n + * The argv array and argc value are changed so that the parsed + * arguments wont appear anymore in them.\n + * The single arguments (without switches) are not parsed. thus, + * myssh -l user localhost\n + * The command wont set the hostname value of options to localhost. + * + * @param session The session to configure. + * + * @param argcptr The pointer to the argument count. + * + * @param argv The arguments list pointer. + * + * @returns 0 on success, < 0 on error. + * + * @see ssh_session_new() + */ +int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) { + char *user = NULL; + char *cipher = NULL; + char *localaddr = NULL; + char *identity = NULL; + char *port = NULL; + char *bindport = NULL; + char **save = NULL; + int i = 0; + int argc = *argcptr; + int debuglevel = 0; + int usersa = 0; + int usedss = 0; + int compress = 0; + int cont = 1; + int current = 0; +#ifdef WITH_SSH1 + int ssh1 = 1; +#else + int ssh1 = 0; +#endif + int ssh2 = 1; +#ifdef _MSC_VER + /* Not supported with a Microsoft compiler */ + return -1; +#else + int saveoptind = optind; /* need to save 'em */ + int saveopterr = opterr; + + save = malloc(argc * sizeof(char *)); + if (save == NULL) { + ssh_set_error_oom(session); + return -1; + } + + opterr = 0; /* shut up getopt */ + while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:t:rd12")) != -1)) { + switch(i) { + case 'l': + user = optarg; + break; + case 'p': + port = optarg; + break; + case 't': + bindport = optarg; + break; + case 'v': + debuglevel++; + break; + case 'r': + usersa++; + break; + case 'd': + usedss++; + break; + case 'c': + cipher = optarg; + break; + case 'i': + identity = optarg; + break; + case 'b': + localaddr = optarg; + break; + case 'C': + compress++; + break; + case '2': + ssh2 = 1; + ssh1 = 0; + break; + case '1': + ssh2 = 0; + ssh1 = 1; + break; + default: + { + char opt[3]="- "; + opt[1] = optopt; + save[current] = strdup(opt); + if (save[current] == NULL) { + SAFE_FREE(save); + ssh_set_error_oom(session); + return -1; + } + current++; + if (optarg) { + save[current++] = argv[optind + 1]; + } + } + } /* switch */ + } /* while */ + opterr = saveopterr; + while (optind < argc) { + save[current++] = argv[optind++]; + } + + if (usersa && usedss) { + ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen"); + cont = 0; + } + + ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &debuglevel); + + optind = saveoptind; + + if(!cont) { + SAFE_FREE(save); + return -1; + } + + /* first recopy the save vector into the original's */ + for (i = 0; i < current; i++) { + /* don't erase argv[0] */ + argv[ i + 1] = save[i]; + } + argv[current + 1] = NULL; + *argcptr = current + 1; + SAFE_FREE(save); + + /* set a new option struct */ + if (compress) { + if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib,none") < 0) { + cont = 0; + } + if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib,none") < 0) { + cont = 0; + } + } + + if (cont && cipher) { + if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) { + cont = 0; + } + if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) { + cont = 0; + } + } + + if (cont && user) { + if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { + cont = 0; + } + } + + if (cont && identity) { + if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) { + cont = 0; + } + } + + ssh_options_set(session, SSH_OPTIONS_PORT_STR, port); + + ssh_options_set(session, SSH_OPTIONS_SSH1, &ssh1); + ssh_options_set(session, SSH_OPTIONS_SSH2, &ssh2); + + if (!cont) { + return SSH_ERROR; + } + + return SSH_OK; +#endif +} + +/** + * @brief Parse the ssh config file. + * + * This should be the last call of all options, it may overwrite options which + * are already set. It requires that the host name is already set with + * ssh_options_set_host(). + * + * @param session SSH session handle + * + * @param filename The options file to use, if NULL the default + * ~/.ssh/config will be used. + * + * @return 0 on success, < 0 on error. + * + * @see ssh_options_set_host() + */ +int ssh_options_parse_config(ssh_session session, const char *filename) { + char *expanded_filename; + int r; + + if (session == NULL) { + return -1; + } + if (session->host == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); + return -1; + } + + if (session->sshdir == NULL) { + r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); + if (r < 0) { + ssh_set_error_oom(session); + return -1; + } + } + + /* set default filename */ + if (filename == NULL) { + expanded_filename = ssh_path_expand_escape(session, "%d/config"); + } else { + expanded_filename = ssh_path_expand_escape(session, filename); + } + if (expanded_filename == NULL) { + return -1; + } + + r = ssh_config_parse_file(session, expanded_filename); + if (r < 0) { + goto out; + } + if (filename == NULL) { + r = ssh_config_parse_file(session, "/etc/ssh/ssh_config"); + } + +out: + free(expanded_filename); + return r; +} + +int ssh_options_apply(ssh_session session) { + struct ssh_iterator *it; + char *tmp; + int rc; + + if (session->sshdir == NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); + if (rc < 0) { + return -1; + } + } + + if (session->username == NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL); + if (rc < 0) { + return -1; + } + } + + if (session->knownhosts == NULL) { + tmp = ssh_path_expand_escape(session, "%d/known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, session->knownhosts); + } + if (tmp == NULL) { + return -1; + } + free(session->knownhosts); + session->knownhosts = tmp; + + if (session->ProxyCommand != NULL) { + tmp = ssh_path_expand_escape(session, session->ProxyCommand); + if (tmp == NULL) { + return -1; + } + free(session->ProxyCommand); + session->ProxyCommand = tmp; + } + + for (it = ssh_list_get_iterator(session->identity); + it != NULL; + it = it->next) { + char *id = (char *) it->data; + tmp = ssh_path_expand_escape(session, id); + if (tmp == NULL) { + return -1; + } + free(id); + it->data = tmp; + } + + return 0; +} + +/** @} */ + +#ifdef WITH_SERVER +/** + * @addtogroup libssh_server + * @{ + */ +static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo, + const char *list) { + if (!verify_existing_algo(algo, list)) { + ssh_set_error(sshbind, SSH_REQUEST_DENIED, + "Setting method: no algorithm for method \"%s\" (%s)\n", + ssh_kex_nums[algo], list); + return -1; + } + + SAFE_FREE(sshbind->wanted_methods[algo]); + sshbind->wanted_methods[algo] = strdup(list); + if (sshbind->wanted_methods[algo] == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + + return 0; +} + +/** + * @brief This function can set all possible ssh bind options. + * + * @param session An allocated ssh option structure. + * + * @param type The option type to set. This could be one of the + * following: + * + * SSH_BIND_OPTIONS_LOG_VERBOSITY: + * Set the session logging verbosity (integer). + * + * The verbosity of the messages. Every log smaller or + * equal to verbosity will be shown. + * SSH_LOG_NOLOG: No logging + * SSH_LOG_RARE: Rare conditions or warnings + * SSH_LOG_ENTRY: API-accessible entrypoints + * SSH_LOG_PACKET: Packet id and size + * SSH_LOG_FUNCTIONS: Function entering and leaving + * + * SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: + * Set the session logging verbosity (integer). + * + * The verbosity of the messages. Every log smaller or + * equal to verbosity will be shown. + * SSH_LOG_NOLOG: No logging + * SSH_LOG_RARE: Rare conditions or warnings + * SSH_LOG_ENTRY: API-accessible entrypoints + * SSH_LOG_PACKET: Packet id and size + * SSH_LOG_FUNCTIONS: Function entering and leaving + * + * SSH_BIND_OPTIONS_BINDADDR: + * Set the bind address. + * + * SSH_BIND_OPTIONS_BINDPORT: + * Set the bind port, default is 22. + * + * SSH_BIND_OPTIONS_HOSTKEY: + * Set the server public key type: ssh-rsa or ssh-dss + * (string). + * + * SSH_BIND_OPTIONS_DSAKEY: + * Set the path to the dsa ssh host key (string). + * + * SSH_BIND_OPTIONS_RSAKEY: + * Set the path to the ssh host rsa key (string). + * + * SSH_BIND_OPTIONS_BANNER: + * Set the server banner sent to clients (string). + * + * @param value The value to set. This is a generic pointer and the + * datatype which is used should be set according to the + * type set. + * + * @return 0 on success, < 0 on error. + */ +int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, + const void *value) { + char *p, *q; + int i; + + if (sshbind == NULL) { + return -1; + } + + switch (type) { + case SSH_BIND_OPTIONS_HOSTKEY: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + if (ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value) < 0) + return -1; + } + break; + case SSH_BIND_OPTIONS_BINDADDR: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + SAFE_FREE(sshbind->bindaddr); + sshbind->bindaddr = strdup(value); + if (sshbind->bindaddr == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + } + break; + case SSH_BIND_OPTIONS_BINDPORT: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + int *x = (int *) value; + sshbind->bindport = *x & 0xffff; + } + break; + case SSH_BIND_OPTIONS_BINDPORT_STR: + if (value == NULL) { + sshbind->bindport = 22 & 0xffff; + } else { + q = strdup(value); + if (q == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + i = strtol(q, &p, 10); + if (q == p) { + SAFE_FREE(q); + } + SAFE_FREE(q); + + sshbind->bindport = i & 0xffff; + } + break; + case SSH_BIND_OPTIONS_LOG_VERBOSITY: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + int *x = (int *) value; + sshbind->log_verbosity = *x & 0xffff; + } + break; + case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: + if (value == NULL) { + sshbind->log_verbosity = 0; + } else { + q = strdup(value); + if (q == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + i = strtol(q, &p, 10); + if (q == p) { + SAFE_FREE(q); + } + SAFE_FREE(q); + + sshbind->log_verbosity = i & 0xffff; + } + break; + case SSH_BIND_OPTIONS_DSAKEY: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + SAFE_FREE(sshbind->dsakey); + sshbind->dsakey = strdup(value); + if (sshbind->dsakey == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + } + break; + case SSH_BIND_OPTIONS_RSAKEY: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + SAFE_FREE(sshbind->rsakey); + sshbind->rsakey = strdup(value); + if (sshbind->rsakey == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + } + break; + case SSH_BIND_OPTIONS_BANNER: + if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); + return -1; + } else { + SAFE_FREE(sshbind->banner); + sshbind->banner = strdup(value); + if (sshbind->banner == NULL) { + ssh_set_error_oom(sshbind); + return -1; + } + } + break; + default: + ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); + return -1; + break; + } + + return 0; +} +#endif + +/** @} */ + +/* vim: set ts=4 sw=4 et cindent: */ |