|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* server.c - functions for creating a SSH server
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This file is part of the SSH Library
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Copyright (c) 2004-2013 by Aris Adamantiadis
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is free software; you can redistribute it and/or modify
|
|
Packit Service |
31306d |
* it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
31306d |
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
|
Packit Service |
31306d |
* option) any later version.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The SSH Library is distributed in the hope that it will be useful, but
|
|
Packit Service |
31306d |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit Service |
31306d |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
Packit Service |
31306d |
* License for more details.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
31306d |
* along with the SSH Library; see the file COPYING. If not, write to
|
|
Packit Service |
31306d |
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
Packit Service |
31306d |
* MA 02111-1307, USA.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "config.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include <errno.h>
|
|
Packit Service |
31306d |
#include <fcntl.h>
|
|
Packit Service |
31306d |
#include <stdio.h>
|
|
Packit Service |
31306d |
#include <string.h>
|
|
Packit Service |
31306d |
#include <stdlib.h>
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifdef _WIN32
|
|
Packit Service |
31306d |
# include <winsock2.h>
|
|
Packit Service |
31306d |
# include <ws2tcpip.h>
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
|
|
Packit Service |
31306d |
* available on some platforms like MinGW.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
# ifdef HAVE_WSPIAPI_H
|
|
Packit Service |
31306d |
# include <wspiapi.h>
|
|
Packit Service |
31306d |
# endif
|
|
Packit Service |
31306d |
#else
|
|
Packit Service |
31306d |
# include <netinet/in.h>
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "libssh/priv.h"
|
|
Packit Service |
31306d |
#include "libssh/libssh.h"
|
|
Packit Service |
31306d |
#include "libssh/server.h"
|
|
Packit Service |
31306d |
#include "libssh/ssh2.h"
|
|
Packit Service |
31306d |
#include "libssh/buffer.h"
|
|
Packit Service |
31306d |
#include "libssh/packet.h"
|
|
Packit Service |
31306d |
#include "libssh/socket.h"
|
|
Packit Service |
31306d |
#include "libssh/session.h"
|
|
Packit Service |
31306d |
#include "libssh/kex.h"
|
|
Packit Service |
31306d |
#include "libssh/misc.h"
|
|
Packit Service |
31306d |
#include "libssh/pki.h"
|
|
Packit Service |
31306d |
#include "libssh/dh.h"
|
|
Packit Service |
31306d |
#include "libssh/messages.h"
|
|
Packit Service |
31306d |
#include "libssh/options.h"
|
|
Packit Service |
31306d |
#include "libssh/curve25519.h"
|
|
Packit Service |
31306d |
#include "libssh/token.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#define set_status(session, status) do {\
|
|
Packit Service |
31306d |
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
|
Packit Service |
31306d |
session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
|
|
Packit Service |
31306d |
} while (0)
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @addtogroup libssh_server
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @{
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/** @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief initialize the set of key exchange, hostkey, ciphers, MACs, and
|
|
Packit Service |
31306d |
* compression algorithms for the given ssh_session
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The selection of algorithms and keys used are determined by the
|
|
Packit Service |
31306d |
* options that are currently set in the given ssh_session structure.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int server_set_kex(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
|
Packit Service |
31306d |
int i, j, rc;
|
|
Packit Service |
31306d |
const char *wanted, *allowed;
|
|
Packit Service |
31306d |
char *kept;
|
|
Packit Service |
31306d |
char hostkeys[128] = {0};
|
|
Packit Service |
31306d |
enum ssh_keytypes_e keytype;
|
|
Packit Service |
31306d |
size_t len;
|
|
Packit Service |
31306d |
int ok;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ZERO_STRUCTP(server);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ok = ssh_get_random(server->cookie, 16, 0);
|
|
Packit Service |
31306d |
if (!ok) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->srv.ed25519_key != NULL) {
|
|
Packit Service |
31306d |
snprintf(hostkeys,
|
|
Packit Service |
31306d |
sizeof(hostkeys),
|
|
Packit Service |
31306d |
"%s",
|
|
Packit Service |
31306d |
ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key)));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#ifdef HAVE_ECC
|
|
Packit Service |
31306d |
if (session->srv.ecdsa_key != NULL) {
|
|
Packit Service |
31306d |
len = strlen(hostkeys);
|
|
Packit Service |
31306d |
snprintf(hostkeys + len, sizeof(hostkeys) - len,
|
|
Packit Service |
31306d |
",%s", session->srv.ecdsa_key->type_c);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
#ifdef HAVE_DSA
|
|
Packit Service |
31306d |
if (session->srv.dsa_key != NULL) {
|
|
Packit Service |
31306d |
len = strlen(hostkeys);
|
|
Packit Service |
31306d |
keytype = ssh_key_type(session->srv.dsa_key);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
snprintf(hostkeys + len, sizeof(hostkeys) - len,
|
|
Packit Service |
31306d |
",%s", ssh_key_type_to_char(keytype));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
if (session->srv.rsa_key != NULL) {
|
|
Packit Service |
31306d |
/* We support also the SHA2 variants */
|
|
Packit Service |
31306d |
len = strlen(hostkeys);
|
|
Packit Service |
31306d |
snprintf(hostkeys + len, sizeof(hostkeys) - len,
|
|
Packit Service |
31306d |
",rsa-sha2-512,rsa-sha2-256");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
len = strlen(hostkeys);
|
|
Packit Service |
31306d |
keytype = ssh_key_type(session->srv.rsa_key);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
snprintf(hostkeys + len, sizeof(hostkeys) - len,
|
|
Packit Service |
31306d |
",%s", ssh_key_type_to_char(keytype));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (strlen(hostkeys) == 0) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
|
|
Packit Service |
31306d |
allowed = session->opts.wanted_methods[SSH_HOSTKEYS];
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
if (ssh_fips_mode()) {
|
|
Packit Service |
31306d |
allowed = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* It is expected for the list of allowed hostkeys to be ordered by
|
|
Packit Service |
31306d |
* preference */
|
|
Packit Service |
31306d |
kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys,
|
|
Packit Service |
31306d |
allowed);
|
|
Packit Service |
31306d |
if (kept == NULL) {
|
|
Packit Service |
31306d |
/* Nothing was allowed */
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_options_set_algo(session,
|
|
Packit Service |
31306d |
SSH_HOSTKEYS,
|
|
Packit Service |
31306d |
kept);
|
|
Packit Service |
31306d |
SAFE_FREE(kept);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
|
Packit Service |
31306d |
wanted = session->opts.wanted_methods[i];
|
|
Packit Service |
31306d |
if (wanted == NULL) {
|
|
Packit Service |
31306d |
if (ssh_fips_mode()) {
|
|
Packit Service |
31306d |
wanted = ssh_kex_get_fips_methods(i);
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
wanted = ssh_kex_get_default_methods(i);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (wanted == NULL) {
|
|
Packit Service |
31306d |
for (j = 0; j < i; j++) {
|
|
Packit Service |
31306d |
SAFE_FREE(server->methods[j]);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
server->methods[i] = strdup(wanted);
|
|
Packit Service |
31306d |
if (server->methods[i] == NULL) {
|
|
Packit Service |
31306d |
for (j = 0; j < i; j++) {
|
|
Packit Service |
31306d |
SAFE_FREE(server->methods[j]);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_server_init_kex(ssh_session session) {
|
|
Packit Service |
31306d |
int i;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->session_state > SSH_SESSION_STATE_BANNER_RECEIVED) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* free any currently-set methods: server_set_kex will allocate new ones */
|
|
Packit Service |
31306d |
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
|
Packit Service |
31306d |
SAFE_FREE(session->next_crypto->server_kex.methods[i]);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return server_set_kex(session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
static int ssh_server_send_extensions(ssh_session session) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
const char *hostkey_algorithms;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->opts.pubkey_accepted_types) {
|
|
Packit Service |
31306d |
hostkey_algorithms = session->opts.pubkey_accepted_types;
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
if (ssh_fips_mode()) {
|
|
Packit Service |
31306d |
hostkey_algorithms = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
/* There are no restrictions to the accepted public keys */
|
|
Packit Service |
31306d |
hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(session->out_buffer,
|
|
Packit Service |
31306d |
"bdss",
|
|
Packit Service |
31306d |
SSH2_MSG_EXT_INFO,
|
|
Packit Service |
31306d |
1, /* nr. of extensions */
|
|
Packit Service |
31306d |
"server-sig-algs",
|
|
Packit Service |
31306d |
hostkey_algorithms);
|
|
Packit Service |
31306d |
if (rc != SSH_OK) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (ssh_packet_send(session) == SSH_ERROR) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
ssh_buffer_reinit(session->out_buffer);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
|
Packit Service |
31306d |
(void)packet;
|
|
Packit Service |
31306d |
(void)type;
|
|
Packit Service |
31306d |
(void)user;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_KEXDH_INIT");
|
|
Packit Service |
31306d |
if(session->dh_handshake_state != DH_STATE_INIT){
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_RARE,"Invalid state for SSH_MSG_KEXDH_INIT");
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_ERROR;
|
|
Packit Service |
31306d |
return SSH_PACKET_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* If first_kex_packet_follows guess was wrong, ignore this message. */
|
|
Packit Service |
31306d |
if (session->first_kex_follows_guess_wrong != 0) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_RARE, "first_kex_packet_follows guess was wrong, "
|
|
Packit Service |
31306d |
"ignoring first SSH_MSG_KEXDH_INIT message");
|
|
Packit Service |
31306d |
session->first_kex_follows_guess_wrong = 0;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_PACKET_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_DEBUG, "Calling next KEXDH handler");
|
|
Packit Service |
31306d |
return SSH_PACKET_NOT_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int
|
|
Packit Service |
31306d |
ssh_get_key_params(ssh_session session,
|
|
Packit Service |
31306d |
ssh_key *privkey,
|
|
Packit Service |
31306d |
enum ssh_digest_e *digest)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
ssh_key pubkey;
|
|
Packit Service |
31306d |
ssh_string pubkey_blob;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
switch(session->srv.hostkey) {
|
|
Packit Service |
31306d |
case SSH_KEYTYPE_DSS:
|
|
Packit Service |
31306d |
*privkey = session->srv.dsa_key;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_KEYTYPE_RSA:
|
|
Packit Service |
31306d |
*privkey = session->srv.rsa_key;
|
|
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 |
*privkey = session->srv.ecdsa_key;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_KEYTYPE_ED25519:
|
|
Packit Service |
31306d |
*privkey = session->srv.ed25519_key;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_KEYTYPE_RSA1:
|
|
Packit Service |
31306d |
case SSH_KEYTYPE_UNKNOWN:
|
|
Packit Service |
31306d |
default:
|
|
Packit Service |
31306d |
*privkey = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*digest = session->srv.hostkey_digest;
|
|
Packit Service |
31306d |
rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL,
|
|
Packit Service |
31306d |
"Could not get the public key from the private key");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob);
|
|
Packit Service |
31306d |
ssh_key_free(pubkey);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(session);
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
|
Packit Service |
31306d |
SSH_STRING_FREE(pubkey_blob);
|
|
Packit Service |
31306d |
if (rc != 0) {
|
|
Packit Service |
31306d |
ssh_set_error(session,
|
|
Packit Service |
31306d |
SSH_FATAL,
|
|
Packit Service |
31306d |
"Could not import server public key");
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief A function to be called each time a step has been done in the
|
|
Packit Service |
31306d |
* connection.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
static void ssh_server_connection_callback(ssh_session session){
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
switch(session->session_state){
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_NONE:
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_CONNECTING:
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
|
Packit Service |
31306d |
if (session->clientbanner == NULL) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
set_status(session, 0.4f);
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PROTOCOL,
|
|
Packit Service |
31306d |
"SSH client banner: %s", session->clientbanner);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Here we analyze the different protocols the server allows. */
|
|
Packit Service |
31306d |
rc = ssh_analyze_banner(session, 1);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL,
|
|
Packit Service |
31306d |
"No version of SSH protocol usable (banner: %s)",
|
|
Packit Service |
31306d |
session->clientbanner);
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* from now, the packet layer is handling incoming packets */
|
|
Packit Service |
31306d |
session->socket_callbacks.data=ssh_packet_socket_callback;
|
|
Packit Service |
31306d |
ssh_packet_register_socket_callback(session, session->socket);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_packet_set_default_callbacks(session);
|
|
Packit Service |
31306d |
set_status(session, 0.5f);
|
|
Packit Service |
31306d |
session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
|
|
Packit Service |
31306d |
if (ssh_send_kex(session, 1) < 0) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_INITIAL_KEX:
|
|
Packit Service |
31306d |
/* TODO: This state should disappear in favor of get_key handle */
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
|
Packit Service |
31306d |
set_status(session,0.6f);
|
|
Packit Service |
31306d |
if(session->next_crypto->server_kex.methods[0]==NULL){
|
|
Packit Service |
31306d |
if(server_set_kex(session) == SSH_ERROR)
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
/* We are in a rekeying, so we need to send the server kex */
|
|
Packit Service |
31306d |
if(ssh_send_kex(session, 1) < 0)
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_list_kex(&session->next_crypto->client_kex); // log client kex
|
|
Packit Service |
31306d |
if (ssh_kex_select_methods(session) < 0) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (crypt_set_algorithms_server(session) == SSH_ERROR)
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
set_status(session,0.8f);
|
|
Packit Service |
31306d |
session->session_state=SSH_SESSION_STATE_DH;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_DH:
|
|
Packit Service |
31306d |
if(session->dh_handshake_state==DH_STATE_FINISHED){
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN);
|
|
Packit Service |
31306d |
if (rc != SSH_OK) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* If the client supports extension negotiation, we will send
|
|
Packit Service |
31306d |
* our supported extensions now. This is the first message after
|
|
Packit Service |
31306d |
* sending NEWKEYS message and after turning on crypto.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
if (session->extensions & SSH_EXT_NEGOTIATION &&
|
|
Packit Service |
31306d |
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* Only send an SSH_MSG_EXT_INFO message the first time the client
|
|
Packit Service |
31306d |
* undergoes NEWKEYS. It is unexpected for this message to be sent
|
|
Packit Service |
31306d |
* upon rekey, and may cause clients to log error messages.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* The session_state can not be used for this purpose because it is
|
|
Packit Service |
31306d |
* re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So,
|
|
Packit Service |
31306d |
* use the connected flag which transitions from non-zero below.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* See also:
|
|
Packit Service |
31306d |
* - https://bugzilla.mindrot.org/show_bug.cgi?id=2929
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
if (session->connected == 0) {
|
|
Packit Service |
31306d |
ssh_server_send_extensions(session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
set_status(session,1.0f);
|
|
Packit Service |
31306d |
session->connected = 1;
|
|
Packit Service |
31306d |
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
|
Packit Service |
31306d |
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_AUTHENTICATING:
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_SESSION_STATE_ERROR:
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
default:
|
|
Packit Service |
31306d |
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
ssh_socket_close(session->socket);
|
|
Packit Service |
31306d |
session->alive = 0;
|
|
Packit Service |
31306d |
session->session_state=SSH_SESSION_STATE_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Gets the banner from socket and saves it in session.
|
|
Packit Service |
31306d |
* Updates the session state
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param data pointer to the beginning of header
|
|
Packit Service |
31306d |
* @param len size of the banner
|
|
Packit Service |
31306d |
* @param user is a pointer to session
|
|
Packit Service |
31306d |
* @returns Number of bytes processed, or zero if the banner is not complete.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
static int callback_receive_banner(const void *data, size_t len, void *user) {
|
|
Packit Service |
31306d |
char *buffer = (char *) data;
|
|
Packit Service |
31306d |
ssh_session session = (ssh_session) user;
|
|
Packit Service |
31306d |
char *str = NULL;
|
|
Packit Service |
31306d |
size_t i;
|
|
Packit Service |
31306d |
int ret=0;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; i < len; i++) {
|
|
Packit Service |
31306d |
#ifdef WITH_PCAP
|
|
Packit Service |
31306d |
if(session->pcap_ctx && buffer[i] == '\n') {
|
|
Packit Service |
31306d |
ssh_pcap_context_write(session->pcap_ctx,
|
|
Packit Service |
31306d |
SSH_PCAP_DIR_IN,
|
|
Packit Service |
31306d |
buffer,
|
|
Packit Service |
31306d |
i + 1,
|
|
Packit Service |
31306d |
i + 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
if (buffer[i] == '\r') {
|
|
Packit Service |
31306d |
buffer[i]='\0';
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (buffer[i] == '\n') {
|
|
Packit Service |
31306d |
buffer[i]='\0';
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
str = strdup(buffer);
|
|
Packit Service |
31306d |
/* number of bytes read */
|
|
Packit Service |
31306d |
ret = i + 1;
|
|
Packit Service |
31306d |
session->clientbanner = str;
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_BANNER_RECEIVED;
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET, "Received banner: %s", str);
|
|
Packit Service |
31306d |
session->ssh_connection_callback(session);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if(i > 127) {
|
|
Packit Service |
31306d |
/* Too big banner */
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_ERROR;
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* returns 0 until the key exchange is not finished */
|
|
Packit Service |
31306d |
static int ssh_server_kex_termination(void *s){
|
|
Packit Service |
31306d |
ssh_session session = s;
|
|
Packit Service |
31306d |
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
|
Packit Service |
31306d |
session->session_state != SSH_SESSION_STATE_AUTHENTICATING &&
|
|
Packit Service |
31306d |
session->session_state != SSH_SESSION_STATE_DISCONNECTED)
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
else
|
|
Packit Service |
31306d |
return 1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* FIXME: auth_methods should be unsigned */
|
|
Packit Service |
31306d |
void ssh_set_auth_methods(ssh_session session, int auth_methods)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
/* accept only methods in range */
|
|
Packit Service |
31306d |
session->auth.supported_methods = (uint32_t)auth_methods & 0x3fU;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Do the banner and key exchange */
|
|
Packit Service |
31306d |
int ssh_handle_key_exchange(ssh_session session) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
if (session->session_state != SSH_SESSION_STATE_NONE)
|
|
Packit Service |
31306d |
goto pending;
|
|
Packit Service |
31306d |
rc = ssh_send_banner(session, 1);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->alive = 1;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->ssh_connection_callback = ssh_server_connection_callback;
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
|
Packit Service |
31306d |
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
|
Packit Service |
31306d |
session->socket_callbacks.data=callback_receive_banner;
|
|
Packit Service |
31306d |
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
|
Packit Service |
31306d |
session->socket_callbacks.userdata=session;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = server_set_kex(session);
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
pending:
|
|
Packit Service |
31306d |
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
|
Packit Service |
31306d |
ssh_server_kex_termination,session);
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d",
|
|
Packit Service |
31306d |
session->session_state);
|
|
Packit Service |
31306d |
if (rc != SSH_OK)
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
|
Packit Service |
31306d |
session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* messages */
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/** @internal
|
|
Packit Service |
31306d |
* replies to an SSH_AUTH packet with a default (denied) response.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_auth_reply_default(ssh_session session,int partial) {
|
|
Packit Service |
31306d |
char methods_c[128] = {0};
|
|
Packit Service |
31306d |
int rc = SSH_ERROR;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->auth.supported_methods == 0) {
|
|
Packit Service |
31306d |
session->auth.supported_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->auth.supported_methods & SSH_AUTH_METHOD_PUBLICKEY) {
|
|
Packit Service |
31306d |
strncat(methods_c, "publickey,",
|
|
Packit Service |
31306d |
sizeof(methods_c) - strlen(methods_c) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->auth.supported_methods & SSH_AUTH_METHOD_GSSAPI_MIC){
|
|
Packit Service |
31306d |
strncat(methods_c,"gssapi-with-mic,",
|
|
Packit Service |
31306d |
sizeof(methods_c) - strlen(methods_c) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->auth.supported_methods & SSH_AUTH_METHOD_INTERACTIVE) {
|
|
Packit Service |
31306d |
strncat(methods_c, "keyboard-interactive,",
|
|
Packit Service |
31306d |
sizeof(methods_c) - strlen(methods_c) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->auth.supported_methods & SSH_AUTH_METHOD_PASSWORD) {
|
|
Packit Service |
31306d |
strncat(methods_c, "password,",
|
|
Packit Service |
31306d |
sizeof(methods_c) - strlen(methods_c) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->auth.supported_methods & SSH_AUTH_METHOD_HOSTBASED) {
|
|
Packit Service |
31306d |
strncat(methods_c, "hostbased,",
|
|
Packit Service |
31306d |
sizeof(methods_c) - strlen(methods_c) - 1);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Strip the comma. */
|
|
Packit Service |
31306d |
methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"Sending a auth failure. methods that can continue: %s", methods_c);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(session->out_buffer,
|
|
Packit Service |
31306d |
"bsb",
|
|
Packit Service |
31306d |
SSH2_MSG_USERAUTH_FAILURE,
|
|
Packit Service |
31306d |
methods_c,
|
|
Packit Service |
31306d |
partial ? 1 : 0);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_packet_send(session);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
static int ssh_message_channel_request_open_reply_default(ssh_message msg) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer,
|
|
Packit Service |
31306d |
"bdddd",
|
|
Packit Service |
31306d |
SSH2_MSG_CHANNEL_OPEN_FAILURE,
|
|
Packit Service |
31306d |
msg->channel_request_open.sender,
|
|
Packit Service |
31306d |
SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
|
|
Packit Service |
31306d |
0, /* reason is empty string */
|
|
Packit Service |
31306d |
0); /* language string */
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
static int ssh_message_channel_request_reply_default(ssh_message msg) {
|
|
Packit Service |
31306d |
uint32_t channel;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (msg->channel_request.want_reply) {
|
|
Packit Service |
31306d |
channel = msg->channel_request.channel->remote_channel;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"Sending a default channel_request denied to channel %d", channel);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer,
|
|
Packit Service |
31306d |
"bd",
|
|
Packit Service |
31306d |
SSH2_MSG_CHANNEL_FAILURE,
|
|
Packit Service |
31306d |
channel);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"The client doesn't want to know the request failed!");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
static int ssh_message_service_request_reply_default(ssh_message msg) {
|
|
Packit Service |
31306d |
/* The only return code accepted by specifications are success or disconnect */
|
|
Packit Service |
31306d |
return ssh_message_service_reply_success(msg);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_service_reply_success(ssh_message msg) {
|
|
Packit Service |
31306d |
ssh_session session;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
session = msg->session;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(session->out_buffer,
|
|
Packit Service |
31306d |
"bs",
|
|
Packit Service |
31306d |
SSH2_MSG_SERVICE_ACCEPT,
|
|
Packit Service |
31306d |
msg->service_request.service);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_FUNCTIONS, "Accepting a global request");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (msg->global_request.want_reply) {
|
|
Packit Service |
31306d |
if (ssh_buffer_add_u8(msg->session->out_buffer
|
|
Packit Service |
31306d |
, SSH2_MSG_REQUEST_SUCCESS) < 0) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD
|
|
Packit Service |
31306d |
&& msg->global_request.bind_port == 0) {
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port);
|
|
Packit Service |
31306d |
if (rc != SSH_OK) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD
|
|
Packit Service |
31306d |
&& msg->global_request.bind_port == 0) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"The client doesn't want to know the remote port!");
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
static int ssh_message_global_request_reply_default(ssh_message msg) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a global request");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (msg->global_request.want_reply) {
|
|
Packit Service |
31306d |
if (ssh_buffer_add_u8(msg->session->out_buffer
|
|
Packit Service |
31306d |
, SSH2_MSG_REQUEST_FAILURE) < 0) {
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"The client doesn't want to know the request failed!");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_reply_default(ssh_message msg) {
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
switch(msg->type) {
|
|
Packit Service |
31306d |
case SSH_REQUEST_AUTH:
|
|
Packit Service |
31306d |
return ssh_auth_reply_default(msg->session, 0);
|
|
Packit Service |
31306d |
case SSH_REQUEST_CHANNEL_OPEN:
|
|
Packit Service |
31306d |
return ssh_message_channel_request_open_reply_default(msg);
|
|
Packit Service |
31306d |
case SSH_REQUEST_CHANNEL:
|
|
Packit Service |
31306d |
return ssh_message_channel_request_reply_default(msg);
|
|
Packit Service |
31306d |
case SSH_REQUEST_SERVICE:
|
|
Packit Service |
31306d |
return ssh_message_service_request_reply_default(msg);
|
|
Packit Service |
31306d |
case SSH_REQUEST_GLOBAL:
|
|
Packit Service |
31306d |
return ssh_message_global_request_reply_default(msg);
|
|
Packit Service |
31306d |
default:
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PACKET,
|
|
Packit Service |
31306d |
"Don't know what to default reply to %d type",
|
|
Packit Service |
31306d |
msg->type);
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_service_service(ssh_message msg){
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return msg->service_request.service;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_auth_user(ssh_message msg) {
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return msg->auth_request.username;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_auth_password(ssh_message msg){
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return msg->auth_request.password;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_key ssh_message_auth_pubkey(ssh_message msg) {
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return msg->auth_request.pubkey;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Get the publickey of an auth request */
|
|
Packit Service |
31306d |
ssh_public_key ssh_message_auth_publickey(ssh_message msg){
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ssh_pki_convert_key_to_publickey(msg->auth_request.pubkey);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg){
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return msg->auth_request.signature_state;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_auth_kbdint_is_response(ssh_message msg) {
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return msg->auth_request.kbdint_response != 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* FIXME: methods should be unsigned */
|
|
Packit Service |
31306d |
int ssh_message_auth_set_methods(ssh_message msg, int methods) {
|
|
Packit Service |
31306d |
if (msg == NULL || msg->session == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (methods < 0) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
msg->session->auth.supported_methods = (uint32_t)methods;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
|
|
Packit Service |
31306d |
const char *instruction, unsigned int num_prompts,
|
|
Packit Service |
31306d |
const char **prompts, char *echo) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
unsigned int i = 0;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if(name == NULL || instruction == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if(num_prompts > 0 && (prompts == NULL || echo == NULL)) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer,
|
|
Packit Service |
31306d |
"bsssd",
|
|
Packit Service |
31306d |
SSH2_MSG_USERAUTH_INFO_REQUEST,
|
|
Packit Service |
31306d |
name,
|
|
Packit Service |
31306d |
instruction,
|
|
Packit Service |
31306d |
"", /* language tag */
|
|
Packit Service |
31306d |
num_prompts);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for(i = 0; i < num_prompts; i++) {
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer,
|
|
Packit Service |
31306d |
"sb",
|
|
Packit Service |
31306d |
prompts[i],
|
|
Packit Service |
31306d |
echo[i] ? 1 : 0);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* fill in the kbdint structure */
|
|
Packit Service |
31306d |
if (msg->session->kbdint == NULL) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a "
|
|
Packit Service |
31306d |
"keyboard-interactive response but it "
|
|
Packit Service |
31306d |
"seems we didn't send the request.");
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
msg->session->kbdint = ssh_kbdint_new();
|
|
Packit Service |
31306d |
if (msg->session->kbdint == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
ssh_kbdint_clean(msg->session->kbdint);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
msg->session->kbdint->name = strdup(name);
|
|
Packit Service |
31306d |
if(msg->session->kbdint->name == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
ssh_kbdint_free(msg->session->kbdint);
|
|
Packit Service |
31306d |
msg->session->kbdint = NULL;
|
|
Packit Service |
31306d |
return SSH_PACKET_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
msg->session->kbdint->instruction = strdup(instruction);
|
|
Packit Service |
31306d |
if(msg->session->kbdint->instruction == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
ssh_kbdint_free(msg->session->kbdint);
|
|
Packit Service |
31306d |
msg->session->kbdint = NULL;
|
|
Packit Service |
31306d |
return SSH_PACKET_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
msg->session->kbdint->nprompts = num_prompts;
|
|
Packit Service |
31306d |
if(num_prompts > 0) {
|
|
Packit Service |
31306d |
msg->session->kbdint->prompts = calloc(num_prompts, sizeof(char *));
|
|
Packit Service |
31306d |
if (msg->session->kbdint->prompts == NULL) {
|
|
Packit Service |
31306d |
msg->session->kbdint->nprompts = 0;
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
ssh_kbdint_free(msg->session->kbdint);
|
|
Packit Service |
31306d |
msg->session->kbdint = NULL;
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
msg->session->kbdint->echo = calloc(num_prompts, sizeof(unsigned char));
|
|
Packit Service |
31306d |
if (msg->session->kbdint->echo == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
ssh_kbdint_free(msg->session->kbdint);
|
|
Packit Service |
31306d |
msg->session->kbdint = NULL;
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
for (i = 0; i < num_prompts; i++) {
|
|
Packit Service |
31306d |
msg->session->kbdint->echo[i] = echo[i];
|
|
Packit Service |
31306d |
msg->session->kbdint->prompts[i] = strdup(prompts[i]);
|
|
Packit Service |
31306d |
if (msg->session->kbdint->prompts[i] == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
msg->session->kbdint->nprompts = i;
|
|
Packit Service |
31306d |
ssh_kbdint_free(msg->session->kbdint);
|
|
Packit Service |
31306d |
msg->session->kbdint = NULL;
|
|
Packit Service |
31306d |
return SSH_PACKET_USED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
msg->session->kbdint->prompts = NULL;
|
|
Packit Service |
31306d |
msg->session->kbdint->echo = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
msg->session->auth.state = SSH_AUTH_STATE_INFO;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_auth_reply_success(ssh_session session, int partial)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_crypto_struct *crypto = NULL;
|
|
Packit Service |
31306d |
int r;
|
|
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 (partial) {
|
|
Packit Service |
31306d |
return ssh_auth_reply_default(session, partial);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
r = ssh_buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS);
|
|
Packit Service |
31306d |
if (r < 0) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
r = ssh_packet_send(session);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* Consider the session as having been authenticated only after sending
|
|
Packit Service |
31306d |
* the USERAUTH_SUCCESS message. Setting these flags after ssh_packet_send
|
|
Packit Service |
31306d |
* ensures that a rekey is not triggered prematurely, causing the message
|
|
Packit Service |
31306d |
* to be queued.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
|
Packit Service |
31306d |
session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT);
|
|
Packit Service |
31306d |
if (crypto != NULL && crypto->delayed_compress_out) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression OUT");
|
|
Packit Service |
31306d |
crypto->do_compress_out = 1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
|
Packit Service |
31306d |
if (crypto != NULL && crypto->delayed_compress_in) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression IN");
|
|
Packit Service |
31306d |
crypto->do_compress_in = 1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return r;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_auth_reply_success(ssh_message msg, int partial) {
|
|
Packit Service |
31306d |
if(msg == NULL)
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
return ssh_auth_reply_success(msg->session, partial);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Answer OK to a pubkey auth request */
|
|
Packit Service |
31306d |
int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
if (msg == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(msg->session->out_buffer,
|
|
Packit Service |
31306d |
"bSS",
|
|
Packit Service |
31306d |
SSH2_MSG_USERAUTH_PK_OK,
|
|
Packit Service |
31306d |
algo,
|
|
Packit Service |
31306d |
pubkey);
|
|
Packit Service |
31306d |
if(rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(msg->session);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_packet_send(msg->session);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) {
|
|
Packit Service |
31306d |
ssh_string algo;
|
|
Packit Service |
31306d |
ssh_string pubkey_blob = NULL;
|
|
Packit Service |
31306d |
int ret;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
algo = ssh_string_from_char(msg->auth_request.pubkey->type_c);
|
|
Packit Service |
31306d |
if (algo == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ret = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &pubkey_blob);
|
|
Packit Service |
31306d |
if (ret < 0) {
|
|
Packit Service |
31306d |
SSH_STRING_FREE(algo);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ret = ssh_message_auth_reply_pk_ok(msg, algo, pubkey_blob);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_STRING_FREE(algo);
|
|
Packit Service |
31306d |
SSH_STRING_FREE(pubkey_blob);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_open_originator(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request_open.originator;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_open_originator_port(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request_open.originator_port;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_open_destination(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request_open.destination;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_open_destination_port(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request_open.destination_port;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_channel ssh_message_channel_request_channel(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.channel;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_pty_term(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.TERM;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_pty_width(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.width;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_pty_height(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.height;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_pty_pxwidth(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.pxwidth;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_pty_pxheight(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.pxheight;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_env_name(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.var_name;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_env_value(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.var_value;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_command(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.command;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_subsystem(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.subsystem;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_x11_single_connection(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.x11_single_connection ? 1 : 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.x11_auth_protocol;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.x11_auth_cookie;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_channel_request_x11_screen_number(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->channel_request.x11_screen_number;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
const char *ssh_message_global_request_address(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->global_request.bind_address;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_message_global_request_port(ssh_message msg){
|
|
Packit Service |
31306d |
return msg->global_request.bind_port;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/** @brief defines the ssh_message callback
|
|
Packit Service |
31306d |
* @param session the current ssh session
|
|
Packit Service |
31306d |
* @param[in] ssh_bind_message_callback a function pointer to a callback taking the
|
|
Packit Service |
31306d |
* current ssh session and received message as parameters. the function returns
|
|
Packit Service |
31306d |
* 0 if the message has been parsed and treated successfully, 1 otherwise (libssh
|
|
Packit Service |
31306d |
* must take care of the response).
|
|
Packit Service |
31306d |
* @param[in] data void pointer to be passed to callback functions
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_message_callback(ssh_session session,
|
|
Packit Service |
31306d |
int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data),
|
|
Packit Service |
31306d |
void *data) {
|
|
Packit Service |
31306d |
session->ssh_message_callback = ssh_bind_message_callback;
|
|
Packit Service |
31306d |
session->ssh_message_callback_data = data;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_execute_message_callbacks(ssh_session session){
|
|
Packit Service |
31306d |
ssh_message msg=NULL;
|
|
Packit Service |
31306d |
int ret;
|
|
Packit Service |
31306d |
ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);
|
|
Packit Service |
31306d |
if(!session->ssh_message_list)
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
if(session->ssh_message_callback){
|
|
Packit Service |
31306d |
while((msg=ssh_message_pop_head(session)) != NULL) {
|
|
Packit Service |
31306d |
ret=session->ssh_message_callback(session,msg,
|
|
Packit Service |
31306d |
session->ssh_message_callback_data);
|
|
Packit Service |
31306d |
if(ret==1){
|
|
Packit Service |
31306d |
ret = ssh_message_reply_default(msg);
|
|
Packit Service |
31306d |
ssh_message_free(msg);
|
|
Packit Service |
31306d |
if(ret != SSH_OK)
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
ssh_message_free(msg);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
while((msg=ssh_message_pop_head(session)) != NULL) {
|
|
Packit Service |
31306d |
ret = ssh_message_reply_default(msg);
|
|
Packit Service |
31306d |
ssh_message_free(msg);
|
|
Packit Service |
31306d |
if(ret != SSH_OK)
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_send_keepalive(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
/* Client denies the request, so the error code is not meaningful */
|
|
Packit Service |
31306d |
(void)ssh_global_request(session, "keepalive@openssh.com", NULL, 1);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/** @} */
|