|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* session.c - non-networking functions
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This file is part of the SSH Library
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Copyright (c) 2005-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 <string.h>
|
|
Packit Service |
31306d |
#include <stdlib.h>
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#include "libssh/priv.h"
|
|
Packit Service |
31306d |
#include "libssh/libssh.h"
|
|
Packit Service |
31306d |
#include "libssh/crypto.h"
|
|
Packit Service |
31306d |
#include "libssh/server.h"
|
|
Packit Service |
31306d |
#include "libssh/socket.h"
|
|
Packit Service |
31306d |
#include "libssh/ssh2.h"
|
|
Packit Service |
31306d |
#include "libssh/agent.h"
|
|
Packit Service |
31306d |
#include "libssh/packet.h"
|
|
Packit Service |
31306d |
#include "libssh/session.h"
|
|
Packit Service |
31306d |
#include "libssh/misc.h"
|
|
Packit Service |
31306d |
#include "libssh/buffer.h"
|
|
Packit Service |
31306d |
#include "libssh/poll.h"
|
|
Packit Service |
31306d |
#include "libssh/pki.h"
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @defgroup libssh_session The SSH session functions.
|
|
Packit Service |
31306d |
* @ingroup libssh
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Functions that manage a session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @{
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Create a new ssh session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @returns A new ssh_session pointer, NULL on error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
ssh_session ssh_new(void)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
ssh_session session;
|
|
Packit Service |
31306d |
char *id = NULL;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session = calloc(1, sizeof (struct ssh_session_struct));
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->next_crypto = crypto_new();
|
|
Packit Service |
31306d |
if (session->next_crypto == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->socket = ssh_socket_new(session);
|
|
Packit Service |
31306d |
if (session->socket == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->out_buffer = ssh_buffer_new();
|
|
Packit Service |
31306d |
if (session->out_buffer == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->in_buffer = ssh_buffer_new();
|
|
Packit Service |
31306d |
if (session->in_buffer == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->out_queue = ssh_list_new();
|
|
Packit Service |
31306d |
if (session->out_queue == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->alive = 0;
|
|
Packit Service |
31306d |
session->auth.supported_methods = 0;
|
|
Packit Service |
31306d |
ssh_set_blocking(session, 1);
|
|
Packit Service |
31306d |
session->maxchannel = FIRST_CHANNEL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifndef _WIN32
|
|
Packit Service |
31306d |
session->agent = ssh_agent_new(session);
|
|
Packit Service |
31306d |
if (session->agent == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif /* _WIN32 */
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* OPTIONS */
|
|
Packit Service |
31306d |
session->opts.StrictHostKeyChecking = 1;
|
|
Packit Service |
31306d |
session->opts.port = 0;
|
|
Packit Service |
31306d |
session->opts.fd = -1;
|
|
Packit Service |
31306d |
session->opts.compressionlevel = 7;
|
|
Packit Service |
31306d |
session->opts.nodelay = 0;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->opts.flags = SSH_OPT_FLAG_PASSWORD_AUTH |
|
|
Packit Service |
31306d |
SSH_OPT_FLAG_PUBKEY_AUTH |
|
|
Packit Service |
31306d |
SSH_OPT_FLAG_KBDINT_AUTH |
|
|
Packit Service |
31306d |
SSH_OPT_FLAG_GSSAPI_AUTH;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->opts.identity = ssh_list_new();
|
|
Packit Service |
31306d |
if (session->opts.identity == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
id = strdup("%d/id_ed25519");
|
|
Packit Service |
31306d |
if (id == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_list_append(session->opts.identity, id);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifdef HAVE_ECC
|
|
Packit Service |
31306d |
id = strdup("%d/id_ecdsa");
|
|
Packit Service |
31306d |
if (id == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_list_append(session->opts.identity, id);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
id = strdup("%d/id_rsa");
|
|
Packit Service |
31306d |
if (id == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_list_append(session->opts.identity, id);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifdef HAVE_DSA
|
|
Packit Service |
31306d |
id = strdup("%d/id_dsa");
|
|
Packit Service |
31306d |
if (id == NULL) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_list_append(session->opts.identity, id);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
goto err;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Explicitly initialize states */
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_NONE;
|
|
Packit Service |
31306d |
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
|
Packit Service |
31306d |
session->packet_state = PACKET_STATE_INIT;
|
|
Packit Service |
31306d |
session->dh_handshake_state = DH_STATE_INIT;
|
|
Packit Service |
31306d |
session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->auth.state = SSH_AUTH_STATE_NONE;
|
|
Packit Service |
31306d |
session->auth.service_state = SSH_AUTH_SERVICE_NONE;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return session;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
err:
|
|
Packit Service |
31306d |
free(id);
|
|
Packit Service |
31306d |
ssh_free(session);
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Deallocate a SSH session handle.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session to free.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @see ssh_disconnect()
|
|
Packit Service |
31306d |
* @see ssh_new()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_free(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int i;
|
|
Packit Service |
31306d |
struct ssh_iterator *it = NULL;
|
|
Packit Service |
31306d |
struct ssh_buffer_struct *b = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
* Delete all channels
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This needs the first thing we clean up cause if there is still an open
|
|
Packit Service |
31306d |
* channel we call ssh_channel_close() first. So we need a working socket
|
|
Packit Service |
31306d |
* and poll context for it.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
for (it = ssh_list_get_iterator(session->channels);
|
|
Packit Service |
31306d |
it != NULL;
|
|
Packit Service |
31306d |
it = ssh_list_get_iterator(session->channels)) {
|
|
Packit Service |
31306d |
ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
|
|
Packit Service |
31306d |
ssh_list_remove(session->channels, it);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_list_free(session->channels);
|
|
Packit Service |
31306d |
session->channels = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifdef WITH_PCAP
|
|
Packit Service |
31306d |
if (session->pcap_ctx) {
|
|
Packit Service |
31306d |
ssh_pcap_context_free(session->pcap_ctx);
|
|
Packit Service |
31306d |
session->pcap_ctx = NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_socket_free(session->socket);
|
|
Packit Service |
31306d |
session->socket = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->default_poll_ctx) {
|
|
Packit Service |
31306d |
ssh_poll_ctx_free(session->default_poll_ctx);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_BUFFER_FREE(session->in_buffer);
|
|
Packit Service |
31306d |
SSH_BUFFER_FREE(session->out_buffer);
|
|
Packit Service |
31306d |
session->in_buffer = session->out_buffer = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->in_hashbuf != NULL) {
|
|
Packit Service |
31306d |
SSH_BUFFER_FREE(session->in_hashbuf);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (session->out_hashbuf != NULL) {
|
|
Packit Service |
31306d |
SSH_BUFFER_FREE(session->out_hashbuf);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
crypto_free(session->current_crypto);
|
|
Packit Service |
31306d |
crypto_free(session->next_crypto);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifndef _WIN32
|
|
Packit Service |
31306d |
ssh_agent_free(session->agent);
|
|
Packit Service |
31306d |
#endif /* _WIN32 */
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_key_free(session->srv.dsa_key);
|
|
Packit Service |
31306d |
session->srv.dsa_key = NULL;
|
|
Packit Service |
31306d |
ssh_key_free(session->srv.rsa_key);
|
|
Packit Service |
31306d |
session->srv.rsa_key = NULL;
|
|
Packit Service |
31306d |
ssh_key_free(session->srv.ecdsa_key);
|
|
Packit Service |
31306d |
session->srv.ecdsa_key = NULL;
|
|
Packit Service |
31306d |
ssh_key_free(session->srv.ed25519_key);
|
|
Packit Service |
31306d |
session->srv.ed25519_key = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->ssh_message_list) {
|
|
Packit Service |
31306d |
ssh_message msg;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
|
|
Packit Service |
31306d |
msg != NULL;
|
|
Packit Service |
31306d |
msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) {
|
|
Packit Service |
31306d |
ssh_message_free(msg);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_list_free(session->ssh_message_list);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->kbdint != NULL) {
|
|
Packit Service |
31306d |
ssh_kbdint_free(session->kbdint);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->packet_callbacks) {
|
|
Packit Service |
31306d |
ssh_list_free(session->packet_callbacks);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* options */
|
|
Packit Service |
31306d |
if (session->opts.identity) {
|
|
Packit Service |
31306d |
char *id;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (id = ssh_list_pop_head(char *, session->opts.identity);
|
|
Packit Service |
31306d |
id != NULL;
|
|
Packit Service |
31306d |
id = ssh_list_pop_head(char *, session->opts.identity)) {
|
|
Packit Service |
31306d |
SAFE_FREE(id);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_list_free(session->opts.identity);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
|
|
Packit Service |
31306d |
session->out_queue)) != NULL) {
|
|
Packit Service |
31306d |
SSH_BUFFER_FREE(b);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_list_free(session->out_queue);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
#ifndef _WIN32
|
|
Packit Service |
31306d |
ssh_agent_state_free (session->agent_state);
|
|
Packit Service |
31306d |
#endif
|
|
Packit Service |
31306d |
session->agent_state = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SAFE_FREE(session->auth.auto_state);
|
|
Packit Service |
31306d |
SAFE_FREE(session->serverbanner);
|
|
Packit Service |
31306d |
SAFE_FREE(session->clientbanner);
|
|
Packit Service |
31306d |
SAFE_FREE(session->banner);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.bindaddr);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.custombanner);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.username);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.host);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.sshdir);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.knownhosts);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.global_knownhosts);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.ProxyCommand);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.gss_server_identity);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.gss_client_identity);
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.pubkey_accepted_types);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
|
Packit Service |
31306d |
if (session->opts.wanted_methods[i]) {
|
|
Packit Service |
31306d |
SAFE_FREE(session->opts.wanted_methods[i]);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* burn connection, it could contain sensitive data */
|
|
Packit Service |
31306d |
explicit_bzero(session, sizeof(struct ssh_session_struct));
|
|
Packit Service |
31306d |
SAFE_FREE(session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the client banner
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns the client banner string or NULL.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_clientbanner(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return session->clientbanner;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the server banner
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns the server banner string or NULL.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_serverbanner(ssh_session session) {
|
|
Packit Service |
31306d |
if(!session) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return session->serverbanner;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the name of the current key exchange algorithm.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns the key exchange algorithm string or NULL.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_kex_algo(ssh_session session) {
|
|
Packit Service |
31306d |
if ((session == NULL) ||
|
|
Packit Service |
31306d |
(session->current_crypto == NULL)) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
switch (session->current_crypto->kex_type) {
|
|
Packit Service |
31306d |
case SSH_KEX_DH_GROUP1_SHA1:
|
|
Packit Service |
31306d |
return "diffie-hellman-group1-sha1";
|
|
Packit Service |
31306d |
case SSH_KEX_DH_GROUP14_SHA1:
|
|
Packit Service |
31306d |
return "diffie-hellman-group14-sha1";
|
|
Packit Service |
31306d |
case SSH_KEX_DH_GROUP14_SHA256:
|
|
Packit Service |
31306d |
return "diffie-hellman-group14-sha256";
|
|
Packit Service |
31306d |
case SSH_KEX_DH_GROUP16_SHA512:
|
|
Packit Service |
31306d |
return "diffie-hellman-group16-sha512";
|
|
Packit Service |
31306d |
case SSH_KEX_DH_GROUP18_SHA512:
|
|
Packit Service |
31306d |
return "diffie-hellman-group18-sha512";
|
|
Packit Service |
31306d |
case SSH_KEX_ECDH_SHA2_NISTP256:
|
|
Packit Service |
31306d |
return "ecdh-sha2-nistp256";
|
|
Packit Service |
31306d |
case SSH_KEX_ECDH_SHA2_NISTP384:
|
|
Packit Service |
31306d |
return "ecdh-sha2-nistp384";
|
|
Packit Service |
31306d |
case SSH_KEX_ECDH_SHA2_NISTP521:
|
|
Packit Service |
31306d |
return "ecdh-sha2-nistp521";
|
|
Packit Service |
31306d |
case SSH_KEX_CURVE25519_SHA256:
|
|
Packit Service |
31306d |
return "curve25519-sha256";
|
|
Packit Service |
31306d |
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
|
Packit Service |
31306d |
return "curve25519-sha256@libssh.org";
|
|
Packit Service |
31306d |
default:
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the name of the input cipher for the given session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns cipher name or NULL.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_cipher_in(ssh_session session) {
|
|
Packit Service |
31306d |
if ((session != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto->in_cipher != NULL)) {
|
|
Packit Service |
31306d |
return session->current_crypto->in_cipher->name;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the name of the output cipher for the given session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns cipher name or NULL.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_cipher_out(ssh_session session) {
|
|
Packit Service |
31306d |
if ((session != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto->out_cipher != NULL)) {
|
|
Packit Service |
31306d |
return session->current_crypto->out_cipher->name;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the name of the input HMAC algorithm for the given session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns HMAC algorithm name or NULL if unknown.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_hmac_in(ssh_session session) {
|
|
Packit Service |
31306d |
if ((session != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto != NULL)) {
|
|
Packit Service |
31306d |
return ssh_hmac_type_to_string(session->current_crypto->in_hmac, session->current_crypto->in_hmac_etm);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief get the name of the output HMAC algorithm for the given session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return Returns HMAC algorithm name or NULL if unknown.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char* ssh_get_hmac_out(ssh_session session) {
|
|
Packit Service |
31306d |
if ((session != NULL) &&
|
|
Packit Service |
31306d |
(session->current_crypto != NULL)) {
|
|
Packit Service |
31306d |
return ssh_hmac_type_to_string(session->current_crypto->out_hmac, session->current_crypto->out_hmac_etm);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Disconnect impolitely from a remote host by closing the socket.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* Suitable if you forked and want to destroy this session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session to disconnect.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_silent_disconnect(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_socket_close(session->socket);
|
|
Packit Service |
31306d |
session->alive = 0;
|
|
Packit Service |
31306d |
ssh_disconnect(session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Set the session in blocking/nonblocking mode.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The ssh session to change.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] blocking Zero for nonblocking mode.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_blocking(ssh_session session, int blocking)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
session->flags &= ~SSH_SESSION_FLAG_BLOCKING;
|
|
Packit Service |
31306d |
session->flags |= blocking ? SSH_SESSION_FLAG_BLOCKING : 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Return the blocking mode of libssh
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
* @returns 0 if the session is nonblocking,
|
|
Packit Service |
31306d |
* @returns 1 if the functions may block.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_is_blocking(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
return (session->flags & SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* Waits until the output socket is empty */
|
|
Packit Service |
31306d |
static int ssh_flush_termination(void *c){
|
|
Packit Service |
31306d |
ssh_session session = c;
|
|
Packit Service |
31306d |
if (ssh_socket_buffered_write_bytes(session->socket) == 0 ||
|
|
Packit Service |
31306d |
session->session_state == SSH_SESSION_STATE_ERROR)
|
|
Packit Service |
31306d |
return 1;
|
|
Packit Service |
31306d |
else
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Blocking flush of the outgoing buffer
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
* @param[in] timeout Set an upper limit on the time for which this function
|
|
Packit Service |
31306d |
* will block, in milliseconds. Specifying -1
|
|
Packit Service |
31306d |
* means an infinite timeout. This parameter is passed to
|
|
Packit Service |
31306d |
* the poll() function.
|
|
Packit Service |
31306d |
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
|
Packit Service |
31306d |
* SSH_ERROR otherwise.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
int ssh_blocking_flush(ssh_session session, int timeout){
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_handle_packets_termination(session, timeout,
|
|
Packit Service |
31306d |
ssh_flush_termination, session);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (!ssh_flush_termination(session)) {
|
|
Packit Service |
31306d |
rc = SSH_AGAIN;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Check if we are connected.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The session to check if it is connected.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return 1 if we are connected, 0 if not.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_is_connected(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return session->alive;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get the fd of a connection.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* In case you'd need the file descriptor of the connection to the server/client.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The ssh session to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return The file descriptor of the connection, or -1 if it is
|
|
Packit Service |
31306d |
* not connected
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
socket_t ssh_get_fd(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ssh_socket_get_fd(session->socket);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Tell the session it has data to read on the file descriptor without
|
|
Packit Service |
31306d |
* blocking.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The ssh session to use.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_fd_toread(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_socket_set_read_wontblock(session->socket);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Tell the session it may write to the file descriptor without blocking.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The ssh session to use.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_fd_towrite(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_socket_set_write_wontblock(session->socket);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Tell the session it has an exception to catch on the file descriptor.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* \param[in] session The ssh session to use.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_fd_except(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_socket_set_except(session->socket);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Poll the current session for an event and call the appropriate
|
|
Packit Service |
31306d |
* callbacks. This function will not loop until the timeout is expired.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This will block until one event happens.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The session handle to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] timeout Set an upper limit on the time for which this function
|
|
Packit Service |
31306d |
* will block, in milliseconds. Specifying SSH_TIMEOUT_INFINITE
|
|
Packit Service |
31306d |
* (-1) means an infinite timeout.
|
|
Packit Service |
31306d |
* Specifying SSH_TIMEOUT_USER means to use the timeout
|
|
Packit Service |
31306d |
* specified in options. 0 means poll will return immediately.
|
|
Packit Service |
31306d |
* This parameter is passed to the poll() function.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return SSH_OK on success, SSH_ERROR otherwise.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_handle_packets(ssh_session session, int timeout) {
|
|
Packit Service |
31306d |
ssh_poll_handle spoll;
|
|
Packit Service |
31306d |
ssh_poll_ctx ctx;
|
|
Packit Service |
31306d |
int tm = timeout;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session == NULL || session->socket == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
spoll = ssh_socket_get_poll_handle(session->socket);
|
|
Packit Service |
31306d |
ssh_poll_add_events(spoll, POLLIN);
|
|
Packit Service |
31306d |
ctx = ssh_poll_get_ctx(spoll);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (!ctx) {
|
|
Packit Service |
31306d |
ctx = ssh_poll_get_default_ctx(session);
|
|
Packit Service |
31306d |
ssh_poll_ctx_add(ctx, spoll);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (timeout == SSH_TIMEOUT_USER) {
|
|
Packit Service |
31306d |
if (ssh_is_blocking(session))
|
|
Packit Service |
31306d |
tm = ssh_make_milliseconds(session->opts.timeout,
|
|
Packit Service |
31306d |
session->opts.timeout_usec);
|
|
Packit Service |
31306d |
else
|
|
Packit Service |
31306d |
tm = 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_poll_ctx_dopoll(ctx, tm);
|
|
Packit Service |
31306d |
if (rc == SSH_ERROR) {
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @brief Poll the current session for an event and call the appropriate
|
|
Packit Service |
31306d |
* callbacks.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This will block until termination function returns true, or timeout expired.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The session handle to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] timeout Set an upper limit on the time for which this function
|
|
Packit Service |
31306d |
* will block, in milliseconds. Specifying
|
|
Packit Service |
31306d |
* SSH_TIMEOUT_INFINITE (-1) means an infinite timeout.
|
|
Packit Service |
31306d |
* Specifying SSH_TIMEOUT_USER means to use the timeout
|
|
Packit Service |
31306d |
* specified in options. 0 means poll will return
|
|
Packit Service |
31306d |
* immediately.
|
|
Packit Service |
31306d |
* SSH_TIMEOUT_DEFAULT uses the session timeout if set or
|
|
Packit Service |
31306d |
* uses blocking parameters of the session.
|
|
Packit Service |
31306d |
* This parameter is passed to the poll() function.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] fct Termination function to be used to determine if it is
|
|
Packit Service |
31306d |
* possible to stop polling.
|
|
Packit Service |
31306d |
* @param[in] user User parameter to be passed to fct termination function.
|
|
Packit Service |
31306d |
* @return SSH_OK on success, SSH_ERROR otherwise.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_handle_packets_termination(ssh_session session,
|
|
Packit Service |
31306d |
long timeout,
|
|
Packit Service |
31306d |
ssh_termination_function fct,
|
|
Packit Service |
31306d |
void *user)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
struct ssh_timestamp ts;
|
|
Packit Service |
31306d |
long timeout_ms = SSH_TIMEOUT_INFINITE;
|
|
Packit Service |
31306d |
long tm;
|
|
Packit Service |
31306d |
int ret = SSH_OK;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* If a timeout has been provided, use it */
|
|
Packit Service |
31306d |
if (timeout >= 0) {
|
|
Packit Service |
31306d |
timeout_ms = timeout;
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
if (ssh_is_blocking(session)) {
|
|
Packit Service |
31306d |
if (timeout == SSH_TIMEOUT_USER || timeout == SSH_TIMEOUT_DEFAULT) {
|
|
Packit Service |
31306d |
if (session->opts.timeout > 0 ||
|
|
Packit Service |
31306d |
session->opts.timeout_usec > 0) {
|
|
Packit Service |
31306d |
timeout_ms =
|
|
Packit Service |
31306d |
ssh_make_milliseconds(session->opts.timeout,
|
|
Packit Service |
31306d |
session->opts.timeout_usec);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
timeout_ms = SSH_TIMEOUT_NONBLOCKING;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */
|
|
Packit Service |
31306d |
if (timeout_ms != SSH_TIMEOUT_NONBLOCKING) {
|
|
Packit Service |
31306d |
ssh_timestamp_init(&ts);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
tm = timeout_ms;
|
|
Packit Service |
31306d |
while(!fct(user)) {
|
|
Packit Service |
31306d |
ret = ssh_handle_packets(session, tm);
|
|
Packit Service |
31306d |
if (ret == SSH_ERROR) {
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (ssh_timeout_elapsed(&ts, timeout_ms)) {
|
|
Packit Service |
31306d |
ret = fct(user) ? SSH_OK : SSH_AGAIN;
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
tm = ssh_timeout_update(&ts, timeout_ms);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ret;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get session status
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param session The ssh session to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @returns A bitmask including SSH_CLOSED, SSH_READ_PENDING, SSH_WRITE_PENDING
|
|
Packit Service |
31306d |
* or SSH_CLOSED_ERROR which respectively means the session is closed,
|
|
Packit Service |
31306d |
* has data to read on the connection socket and session was closed
|
|
Packit Service |
31306d |
* due to an error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_status(ssh_session session) {
|
|
Packit Service |
31306d |
int socketstate;
|
|
Packit Service |
31306d |
int r = 0;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
socketstate = ssh_socket_get_status(session->socket);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
|
Packit Service |
31306d |
r |= SSH_CLOSED;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (socketstate & SSH_READ_PENDING) {
|
|
Packit Service |
31306d |
r |= SSH_READ_PENDING;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (socketstate & SSH_WRITE_PENDING) {
|
|
Packit Service |
31306d |
r |= SSH_WRITE_PENDING;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if ((session->session_state == SSH_SESSION_STATE_DISCONNECTED &&
|
|
Packit Service |
31306d |
(socketstate & SSH_CLOSED_ERROR)) ||
|
|
Packit Service |
31306d |
session->session_state == SSH_SESSION_STATE_ERROR) {
|
|
Packit Service |
31306d |
r |= SSH_CLOSED_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return r;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get poll flags for an external mainloop
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param session The ssh session to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @returns A bitmask including SSH_READ_PENDING or SSH_WRITE_PENDING.
|
|
Packit Service |
31306d |
* For SSH_READ_PENDING, your invocation of poll() should include
|
|
Packit Service |
31306d |
* POLLIN. For SSH_WRITE_PENDING, your invocation of poll() should
|
|
Packit Service |
31306d |
* include POLLOUT.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_poll_flags(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return 0;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return ssh_socket_get_poll_flags (session->socket);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get the disconnect message from the server.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The ssh session to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return The message sent by the server along with the
|
|
Packit Service |
31306d |
* disconnect, or NULL in which case the reason of the
|
|
Packit Service |
31306d |
* disconnect may be found with ssh_get_error.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @see ssh_get_error()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
const char *ssh_get_disconnect_message(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session->session_state != SSH_SESSION_STATE_DISCONNECTED) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_REQUEST_DENIED,
|
|
Packit Service |
31306d |
"Connection not closed yet");
|
|
Packit Service |
31306d |
} else if(!session->discon_msg) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL,
|
|
Packit Service |
31306d |
"Connection correctly closed but no disconnect message");
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
return session->discon_msg;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return NULL;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get the protocol version of the session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param session The ssh session to use.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return The SSH version as integer, < 0 on error.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_version(ssh_session session) {
|
|
Packit Service |
31306d |
if (session == NULL) {
|
|
Packit Service |
31306d |
return -1;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return 2;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @internal
|
|
Packit Service |
31306d |
* @brief Callback to be called when the socket received an exception code.
|
|
Packit Service |
31306d |
* @param user is a pointer to session
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_socket_exception_callback(int code, int errno_code, void *user){
|
|
Packit Service |
31306d |
ssh_session session=(ssh_session)user;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code);
|
|
Packit Service |
31306d |
session->session_state = SSH_SESSION_STATE_ERROR;
|
|
Packit Service |
31306d |
if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL, "Socket error: disconnected");
|
|
Packit Service |
31306d |
} else {
|
|
Packit Service |
31306d |
ssh_set_error(session, SSH_FATAL, "Socket error: %s", strerror(errno_code));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
session->ssh_connection_callback(session);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Send a message that should be ignored
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
* @param[in] data Data to be sent
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return SSH_OK on success, SSH_ERROR otherwise.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_send_ignore (ssh_session session, const char *data) {
|
|
Packit Service |
31306d |
const int type = SSH2_MSG_IGNORE;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (ssh_socket_is_open(session->socket)) {
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(session->out_buffer,
|
|
Packit Service |
31306d |
"bs",
|
|
Packit Service |
31306d |
type,
|
|
Packit Service |
31306d |
data);
|
|
Packit Service |
31306d |
if (rc != SSH_OK){
|
|
Packit Service |
31306d |
ssh_set_error_oom(session);
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_packet_send(session);
|
|
Packit Service |
31306d |
ssh_handle_packets(session, 0);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
ssh_buffer_reinit(session->out_buffer);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Send a debug message
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session
|
|
Packit Service |
31306d |
* @param[in] message Data to be sent
|
|
Packit Service |
31306d |
* @param[in] always_display Message SHOULD be displayed by the server. It
|
|
Packit Service |
31306d |
* SHOULD NOT be displayed unless debugging
|
|
Packit Service |
31306d |
* information has been explicitly requested.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return SSH_OK on success, SSH_ERROR otherwise.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_send_debug (ssh_session session, const char *message, int always_display) {
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (ssh_socket_is_open(session->socket)) {
|
|
Packit Service |
31306d |
rc = ssh_buffer_pack(session->out_buffer,
|
|
Packit Service |
31306d |
"bbsd",
|
|
Packit Service |
31306d |
SSH2_MSG_DEBUG,
|
|
Packit Service |
31306d |
always_display != 0 ? 1 : 0,
|
|
Packit Service |
31306d |
message,
|
|
Packit Service |
31306d |
0); /* empty language tag */
|
|
Packit Service |
31306d |
if (rc != SSH_OK) {
|
|
Packit Service |
31306d |
ssh_set_error_oom(session);
|
|
Packit Service |
31306d |
goto error;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
ssh_packet_send(session);
|
|
Packit Service |
31306d |
ssh_handle_packets(session, 0);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
error:
|
|
Packit Service |
31306d |
ssh_buffer_reinit(session->out_buffer);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Set the session data counters.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This functions sets the counter structures to be used to calculate data
|
|
Packit Service |
31306d |
* which comes in and goes out through the session at different levels.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @code
|
|
Packit Service |
31306d |
* struct ssh_counter_struct scounter = {
|
|
Packit Service |
31306d |
* .in_bytes = 0,
|
|
Packit Service |
31306d |
* .out_bytes = 0,
|
|
Packit Service |
31306d |
* .in_packets = 0,
|
|
Packit Service |
31306d |
* .out_packets = 0
|
|
Packit Service |
31306d |
* };
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* struct ssh_counter_struct rcounter = {
|
|
Packit Service |
31306d |
* .in_bytes = 0,
|
|
Packit Service |
31306d |
* .out_bytes = 0,
|
|
Packit Service |
31306d |
* .in_packets = 0,
|
|
Packit Service |
31306d |
* .out_packets = 0
|
|
Packit Service |
31306d |
* };
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* ssh_set_counters(session, &scounter, &rcounter);
|
|
Packit Service |
31306d |
* @endcode
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The SSH session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] scounter Counter for byte data handled by the session sockets.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] rcounter Counter for byte and packet data handled by the session,
|
|
Packit Service |
31306d |
* prior compression and SSH overhead.
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_set_counters(ssh_session session, ssh_counter scounter,
|
|
Packit Service |
31306d |
ssh_counter rcounter) {
|
|
Packit Service |
31306d |
if (session != NULL) {
|
|
Packit Service |
31306d |
session->socket_counter = scounter;
|
|
Packit Service |
31306d |
session->raw_counter = rcounter;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @deprecated Use ssh_get_publickey_hash()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
ssh_key pubkey = NULL;
|
|
Packit Service |
31306d |
ssh_string pubkey_blob = NULL;
|
|
Packit Service |
31306d |
MD5CTX ctx;
|
|
Packit Service |
31306d |
unsigned char *h;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session == NULL || hash == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* In FIPS mode, we cannot use MD5 */
|
|
Packit Service |
31306d |
if (ssh_fips_mode()) {
|
|
Packit Service |
31306d |
ssh_set_error(session,
|
|
Packit Service |
31306d |
SSH_FATAL,
|
|
Packit Service |
31306d |
"In FIPS mode MD5 is not allowed."
|
|
Packit Service |
31306d |
"Try ssh_get_publickey_hash() with"
|
|
Packit Service |
31306d |
"SSH_PUBLICKEY_HASH_SHA256");
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hash = NULL;
|
|
Packit Service |
31306d |
if (session->current_crypto == NULL ||
|
|
Packit Service |
31306d |
session->current_crypto->server_pubkey == NULL) {
|
|
Packit Service |
31306d |
ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
h = calloc(MD5_DIGEST_LEN, sizeof(unsigned char));
|
|
Packit Service |
31306d |
if (h == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ctx = md5_init();
|
|
Packit Service |
31306d |
if (ctx == NULL) {
|
|
Packit Service |
31306d |
SAFE_FREE(h);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_get_server_publickey(session, &pubkey);
|
|
Packit Service |
31306d |
if (rc != SSH_OK) {
|
|
Packit Service |
31306d |
md5_final(h, ctx);
|
|
Packit Service |
31306d |
SAFE_FREE(h);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
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 != SSH_OK) {
|
|
Packit Service |
31306d |
md5_final(h, ctx);
|
|
Packit Service |
31306d |
SAFE_FREE(h);
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob));
|
|
Packit Service |
31306d |
SSH_STRING_FREE(pubkey_blob);
|
|
Packit Service |
31306d |
md5_final(h, ctx);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hash = h;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return MD5_DIGEST_LEN;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Deallocate the hash obtained by ssh_get_pubkey_hash.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This is required under Microsoft platform as this library might use a
|
|
Packit Service |
31306d |
* different C library than your software, hence a different heap.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] hash The buffer to deallocate.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @see ssh_get_pubkey_hash()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
void ssh_clean_pubkey_hash(unsigned char **hash) {
|
|
Packit Service |
31306d |
SAFE_FREE(*hash);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Get the server public key from a session.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] session The session to get the key from.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[out] key A pointer to store the allocated key. You need to free
|
|
Packit Service |
31306d |
* the key.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return SSH_OK on success, SSH_ERROR on errror.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @see ssh_key_free()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_server_publickey(ssh_session session, ssh_key *key)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
ssh_key pubkey = NULL;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (session == NULL ||
|
|
Packit Service |
31306d |
session->current_crypto == NULL ||
|
|
Packit Service |
31306d |
session->current_crypto->server_pubkey == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
pubkey = ssh_key_dup(session->current_crypto->server_pubkey);
|
|
Packit Service |
31306d |
if (pubkey == NULL) {
|
|
Packit Service |
31306d |
return SSH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*key = pubkey;
|
|
Packit Service |
31306d |
return SSH_OK;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @deprecated Use ssh_get_server_publickey()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_publickey(ssh_session session, ssh_key *key)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
return ssh_get_server_publickey(session, key);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
* @brief Allocates a buffer with the hash of the public key.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* This function allows you to get a hash of the public key. You can then
|
|
Packit Service |
31306d |
* print this hash in a human-readable form to the user so that he is able to
|
|
Packit Service |
31306d |
* verify it. Use ssh_get_hexa() or ssh_print_hash() to display it.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] key The public key to create the hash for.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] type The type of the hash you want.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] hash A pointer to store the allocated buffer. It can be
|
|
Packit Service |
31306d |
* freed using ssh_clean_pubkey_hash().
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @param[in] hlen The length of the hash.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @return 0 on success, -1 if an error occured.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @warning It is very important that you verify at some moment that the hash
|
|
Packit Service |
31306d |
* matches a known server. If you don't do it, cryptography wont help
|
|
Packit Service |
31306d |
* you at making things secure.
|
|
Packit Service |
31306d |
* OpenSSH uses SHA256 to print public key digests.
|
|
Packit Service |
31306d |
*
|
|
Packit Service |
31306d |
* @see ssh_session_update_known_hosts()
|
|
Packit Service |
31306d |
* @see ssh_get_hexa()
|
|
Packit Service |
31306d |
* @see ssh_print_hash()
|
|
Packit Service |
31306d |
* @see ssh_clean_pubkey_hash()
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
int ssh_get_publickey_hash(const ssh_key key,
|
|
Packit Service |
31306d |
enum ssh_publickey_hash_type type,
|
|
Packit Service |
31306d |
unsigned char **hash,
|
|
Packit Service |
31306d |
size_t *hlen)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
ssh_string blob;
|
|
Packit Service |
31306d |
unsigned char *h;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_pki_export_pubkey_blob(key, &blob;;
|
|
Packit Service |
31306d |
if (rc < 0) {
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
switch (type) {
|
|
Packit Service |
31306d |
case SSH_PUBLICKEY_HASH_SHA1:
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
SHACTX ctx;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
h = calloc(1, SHA_DIGEST_LEN);
|
|
Packit Service |
31306d |
if (h == NULL) {
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ctx = sha1_init();
|
|
Packit Service |
31306d |
if (ctx == NULL) {
|
|
Packit Service |
31306d |
free(h);
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
|
Packit Service |
31306d |
sha1_final(h, ctx);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hlen = SHA_DIGEST_LEN;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_PUBLICKEY_HASH_SHA256:
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
SHA256CTX ctx;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
h = calloc(1, SHA256_DIGEST_LEN);
|
|
Packit Service |
31306d |
if (h == NULL) {
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ctx = sha256_init();
|
|
Packit Service |
31306d |
if (ctx == NULL) {
|
|
Packit Service |
31306d |
free(h);
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
|
Packit Service |
31306d |
sha256_final(h, ctx);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hlen = SHA256_DIGEST_LEN;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
case SSH_PUBLICKEY_HASH_MD5:
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
MD5CTX ctx;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/* In FIPS mode, we cannot use MD5 */
|
|
Packit Service |
31306d |
if (ssh_fips_mode()) {
|
|
Packit Service |
31306d |
SSH_LOG(SSH_LOG_WARN, "In FIPS mode MD5 is not allowed."
|
|
Packit Service |
31306d |
"Try using SSH_PUBLICKEY_HASH_SHA256");
|
|
Packit Service |
31306d |
rc = SSH_ERROR;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
h = calloc(1, MD5_DIGEST_LEN);
|
|
Packit Service |
31306d |
if (h == NULL) {
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ctx = md5_init();
|
|
Packit Service |
31306d |
if (ctx == NULL) {
|
|
Packit Service |
31306d |
free(h);
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
|
Packit Service |
31306d |
md5_final(h, ctx);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hlen = MD5_DIGEST_LEN;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
break;
|
|
Packit Service |
31306d |
default:
|
|
Packit Service |
31306d |
rc = -1;
|
|
Packit Service |
31306d |
goto out;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*hash = h;
|
|
Packit Service |
31306d |
rc = 0;
|
|
Packit Service |
31306d |
out:
|
|
Packit Service |
31306d |
SSH_STRING_FREE(blob);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/** @} */
|