Split ssh_bind functions in a new .c file
Этот коммит содержится в:
родитель
98221f4e36
Коммит
ea4aa26dbb
@ -138,6 +138,7 @@ if (WITH_SERVER)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
server.c
|
||||
bind.c
|
||||
)
|
||||
endif (WITH_SERVER)
|
||||
|
||||
|
372
src/bind.c
Обычный файл
372
src/bind.c
Обычный файл
@ -0,0 +1,372 @@
|
||||
/*
|
||||
* bind.c : all ssh_bind functions
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2004-2005 by Aris Adamantiadis
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/server.h"
|
||||
#include "libssh/keyfiles.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/socket.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
/**
|
||||
* @addtogroup libssh_server
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <winsock2.h>
|
||||
#define SOCKOPT_TYPE_ARG4 char
|
||||
|
||||
/* We need to provide hstrerror. Not we can't call the parameter h_errno because it's #defined */
|
||||
static char *hstrerror(int h_errno_val) {
|
||||
static char text[50] = {0};
|
||||
|
||||
snprintf(text, sizeof(text), "gethostbyname error %d\n", h_errno_val);
|
||||
|
||||
return text;
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#define SOCKOPT_TYPE_ARG4 int
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* TODO FIXME: must use getaddrinfo */
|
||||
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
||||
int port) {
|
||||
struct sockaddr_in myaddr;
|
||||
struct hostent *hp=NULL;
|
||||
socket_t s;
|
||||
int opt = 1;
|
||||
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETHOSTBYNAME
|
||||
hp = gethostbyname(hostname);
|
||||
#endif
|
||||
|
||||
if (hp == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Resolving %s: %s", hostname, hstrerror(h_errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&myaddr, 0, sizeof(myaddr));
|
||||
memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length);
|
||||
myaddr.sin_family = hp->h_addrtype;
|
||||
myaddr.sin_port = htons(port);
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Setting socket options failed: %s", hstrerror(h_errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s",
|
||||
hostname,
|
||||
port,
|
||||
strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
ssh_bind ssh_bind_new(void) {
|
||||
ssh_bind ptr;
|
||||
|
||||
ptr = malloc(sizeof(struct ssh_bind_struct));
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(ptr);
|
||||
ptr->bindfd = SSH_INVALID_SOCKET;
|
||||
ptr->bindport= 22;
|
||||
ptr->log_verbosity = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host;
|
||||
socket_t fd;
|
||||
|
||||
if (ssh_init() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
host = sshbind->bindaddr;
|
||||
if (host == NULL) {
|
||||
host = "0.0.0.0";
|
||||
}
|
||||
|
||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
sshbind->bindfd = fd;
|
||||
|
||||
if (listen(fd, 10) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Listening to socket %d: %s",
|
||||
fd, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set the bind callbacks for ssh_bind
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
* @param sshbind the ssh_bind structure to set
|
||||
* @param callbacks a ssh_bind_callbacks instance already set up. Do
|
||||
* use ssh_callbacks_init() to initialize it.
|
||||
* @param userdata userdata to be used with each callback called
|
||||
* within callbacks.
|
||||
* @returns SSH_OK on success,
|
||||
* SSH_ERROR on error.
|
||||
*/
|
||||
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata){
|
||||
if (sshbind == NULL || callbacks == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
||||
ssh_set_error(sshbind,SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sshbind->bind_callbacks = callbacks;
|
||||
sshbind->bind_callbacks_userdata=userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief callback being called by poll when an event happens
|
||||
*
|
||||
*/
|
||||
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
|
||||
socket_t fd, int revents, void *user){
|
||||
ssh_bind sshbind=(ssh_bind)user;
|
||||
(void)sshpoll;
|
||||
(void)fd;
|
||||
|
||||
if(revents & POLLIN){
|
||||
/* new incoming connection */
|
||||
if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
|
||||
sshbind->bind_callbacks->incoming_connection(sshbind,
|
||||
sshbind->bind_callbacks_userdata);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief returns the current poll handle, or create it
|
||||
* @param sshbind the ssh_bind object
|
||||
* @returns a ssh_poll handle suitable for operation
|
||||
*/
|
||||
ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind){
|
||||
if(sshbind->poll)
|
||||
return sshbind->poll;
|
||||
sshbind->poll=ssh_poll_new(sshbind->bindfd,POLLIN,
|
||||
ssh_bind_poll_callback,sshbind);
|
||||
return sshbind->poll;
|
||||
}
|
||||
|
||||
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
|
||||
sshbind->blocking = blocking ? 1 : 0;
|
||||
}
|
||||
|
||||
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
|
||||
return sshbind->bindfd;
|
||||
}
|
||||
|
||||
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
|
||||
sshbind->bindfd = fd;
|
||||
}
|
||||
|
||||
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
|
||||
sshbind->toaccept = 1;
|
||||
}
|
||||
|
||||
void ssh_bind_free(ssh_bind sshbind){
|
||||
int i;
|
||||
|
||||
if (sshbind == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sshbind->bindfd >= 0) {
|
||||
#ifdef _WIN32
|
||||
closesocket(sshbind->bindfd);
|
||||
#else
|
||||
close(sshbind->bindfd);
|
||||
#endif
|
||||
}
|
||||
sshbind->bindfd = SSH_INVALID_SOCKET;
|
||||
|
||||
/* options */
|
||||
SAFE_FREE(sshbind->banner);
|
||||
SAFE_FREE(sshbind->dsakey);
|
||||
SAFE_FREE(sshbind->rsakey);
|
||||
SAFE_FREE(sshbind->bindaddr);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
SAFE_FREE(sshbind->wanted_methods[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(sshbind);
|
||||
}
|
||||
|
||||
|
||||
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
||||
ssh_private_key dsa = NULL;
|
||||
ssh_private_key rsa = NULL;
|
||||
socket_t fd = SSH_INVALID_SOCKET;
|
||||
int i;
|
||||
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Can't accept new clients on a not bound socket.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(session == NULL){
|
||||
ssh_set_error(sshbind, SSH_FATAL,"session is null");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"DSA or RSA host key file must be set before accept()");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (sshbind->dsakey) {
|
||||
dsa = _privatekey_from_file(sshbind, sshbind->dsakey, SSH_KEYTYPE_DSS);
|
||||
if (dsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->rsakey) {
|
||||
rsa = _privatekey_from_file(sshbind, sshbind->rsakey, SSH_KEYTYPE_RSA);
|
||||
if (rsa == NULL) {
|
||||
privatekey_free(dsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
fd = accept(sshbind->bindfd, NULL, NULL);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Accepting a new connection: %s",
|
||||
strerror(errno));
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->server = 1;
|
||||
session->version = 2;
|
||||
|
||||
/* copy options */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
|
||||
if (session->wanted_methods[i] == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->bindaddr == NULL)
|
||||
session->bindaddr = NULL;
|
||||
else {
|
||||
SAFE_FREE(session->bindaddr);
|
||||
session->bindaddr = strdup(sshbind->bindaddr);
|
||||
if (session->bindaddr == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
session->log_verbosity = sshbind->log_verbosity;
|
||||
|
||||
ssh_socket_free(session->socket);
|
||||
session->socket = ssh_socket_new(session);
|
||||
if (session->socket == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
ssh_socket_set_fd(session->socket, fd);
|
||||
ssh_socket_get_poll_handle_out(session->socket);
|
||||
session->dsa_key = dsa;
|
||||
session->rsa_key = rsa;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
322
src/server.c
322
src/server.c
@ -43,8 +43,6 @@
|
||||
#include "libssh/keys.h"
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/messages.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/poll.h"
|
||||
|
||||
#define set_status(session, status) do {\
|
||||
if (session->callbacks && session->callbacks->connect_status_function) \
|
||||
@ -60,236 +58,6 @@ static int dh_handshake_server(ssh_session session);
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <winsock2.h>
|
||||
#define SOCKOPT_TYPE_ARG4 char
|
||||
|
||||
/* We need to provide hstrerror. Not we can't call the parameter h_errno because it's #defined */
|
||||
static char *hstrerror(int h_errno_val) {
|
||||
static char text[50] = {0};
|
||||
|
||||
snprintf(text, sizeof(text), "gethostbyname error %d\n", h_errno_val);
|
||||
|
||||
return text;
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#define SOCKOPT_TYPE_ARG4 int
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* TODO FIXME: must use getaddrinfo */
|
||||
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
||||
int port) {
|
||||
struct sockaddr_in myaddr;
|
||||
struct hostent *hp=NULL;
|
||||
socket_t s;
|
||||
int opt = 1;
|
||||
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETHOSTBYNAME
|
||||
hp = gethostbyname(hostname);
|
||||
#endif
|
||||
|
||||
if (hp == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Resolving %s: %s", hostname, hstrerror(h_errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&myaddr, 0, sizeof(myaddr));
|
||||
memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length);
|
||||
myaddr.sin_family = hp->h_addrtype;
|
||||
myaddr.sin_port = htons(port);
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Setting socket options failed: %s", hstrerror(h_errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s",
|
||||
hostname,
|
||||
port,
|
||||
strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
ssh_bind ssh_bind_new(void) {
|
||||
ssh_bind ptr;
|
||||
|
||||
ptr = malloc(sizeof(struct ssh_bind_struct));
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(ptr);
|
||||
ptr->bindfd = SSH_INVALID_SOCKET;
|
||||
ptr->bindport= 22;
|
||||
ptr->log_verbosity = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host;
|
||||
socket_t fd;
|
||||
|
||||
if (ssh_init() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
host = sshbind->bindaddr;
|
||||
if (host == NULL) {
|
||||
host = "0.0.0.0";
|
||||
}
|
||||
|
||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
sshbind->bindfd = fd;
|
||||
|
||||
if (listen(fd, 10) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Listening to socket %d: %s",
|
||||
fd, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set the bind callbacks for ssh_bind
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
* @param sshbind the ssh_bind structure to set
|
||||
* @param callbacks a ssh_bind_callbacks instance already set up. Do
|
||||
* use ssh_callbacks_init() to initialize it.
|
||||
* @param userdata userdata to be used with each callback called
|
||||
* within callbacks.
|
||||
* @returns SSH_OK on success,
|
||||
* SSH_ERROR on error.
|
||||
*/
|
||||
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata){
|
||||
if (sshbind == NULL || callbacks == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
||||
ssh_set_error(sshbind,SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sshbind->bind_callbacks = callbacks;
|
||||
sshbind->bind_callbacks_userdata=userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief callback being called by poll when an event happens
|
||||
*
|
||||
*/
|
||||
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
|
||||
socket_t fd, int revents, void *user){
|
||||
ssh_bind sshbind=(ssh_bind)user;
|
||||
(void)sshpoll;
|
||||
(void)fd;
|
||||
|
||||
if(revents & POLLIN){
|
||||
/* new incoming connection */
|
||||
if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
|
||||
sshbind->bind_callbacks->incoming_connection(sshbind,
|
||||
sshbind->bind_callbacks_userdata);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief returns the current poll handle, or create it
|
||||
* @param sshbind the ssh_bind object
|
||||
* @returns a ssh_poll handle suitable for operation
|
||||
*/
|
||||
ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind){
|
||||
if(sshbind->poll)
|
||||
return sshbind->poll;
|
||||
sshbind->poll=ssh_poll_new(sshbind->bindfd,POLLIN,
|
||||
ssh_bind_poll_callback,sshbind);
|
||||
return sshbind->poll;
|
||||
}
|
||||
|
||||
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
|
||||
sshbind->blocking = blocking ? 1 : 0;
|
||||
}
|
||||
|
||||
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
|
||||
return sshbind->bindfd;
|
||||
}
|
||||
|
||||
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
|
||||
sshbind->bindfd = fd;
|
||||
}
|
||||
|
||||
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
|
||||
sshbind->toaccept = 1;
|
||||
}
|
||||
|
||||
void ssh_bind_free(ssh_bind sshbind){
|
||||
int i;
|
||||
|
||||
if (sshbind == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sshbind->bindfd >= 0) {
|
||||
#ifdef _WIN32
|
||||
closesocket(sshbind->bindfd);
|
||||
#else
|
||||
close(sshbind->bindfd);
|
||||
#endif
|
||||
}
|
||||
sshbind->bindfd = SSH_INVALID_SOCKET;
|
||||
|
||||
/* options */
|
||||
SAFE_FREE(sshbind->banner);
|
||||
SAFE_FREE(sshbind->dsakey);
|
||||
SAFE_FREE(sshbind->rsakey);
|
||||
SAFE_FREE(sshbind->bindaddr);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
SAFE_FREE(sshbind->wanted_methods[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(sshbind);
|
||||
}
|
||||
|
||||
extern char *supported_methods[];
|
||||
/** @internal
|
||||
* This functions sets the Key Exchange protocols to be accepted
|
||||
@ -667,96 +435,6 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
||||
ssh_private_key dsa = NULL;
|
||||
ssh_private_key rsa = NULL;
|
||||
socket_t fd = SSH_INVALID_SOCKET;
|
||||
int i;
|
||||
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Can't accept new clients on a not bound socket.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(session == NULL){
|
||||
ssh_set_error(sshbind, SSH_FATAL,"session is null");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"DSA or RSA host key file must be set before accept()");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (sshbind->dsakey) {
|
||||
dsa = _privatekey_from_file(sshbind, sshbind->dsakey, SSH_KEYTYPE_DSS);
|
||||
if (dsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->rsakey) {
|
||||
rsa = _privatekey_from_file(sshbind, sshbind->rsakey, SSH_KEYTYPE_RSA);
|
||||
if (rsa == NULL) {
|
||||
privatekey_free(dsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
fd = accept(sshbind->bindfd, NULL, NULL);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Accepting a new connection: %s",
|
||||
strerror(errno));
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->server = 1;
|
||||
session->version = 2;
|
||||
|
||||
/* copy options */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
|
||||
if (session->wanted_methods[i] == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->bindaddr == NULL)
|
||||
session->bindaddr = NULL;
|
||||
else {
|
||||
SAFE_FREE(session->bindaddr);
|
||||
session->bindaddr = strdup(sshbind->bindaddr);
|
||||
if (session->bindaddr == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
session->log_verbosity = sshbind->log_verbosity;
|
||||
|
||||
ssh_socket_free(session->socket);
|
||||
session->socket = ssh_socket_new(session);
|
||||
if (session->socket == NULL) {
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
ssh_socket_set_fd(session->socket, fd);
|
||||
ssh_socket_get_poll_handle_out(session->socket);
|
||||
session->dsa_key = dsa;
|
||||
session->rsa_key = rsa;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/* Do the banner and key exchange */
|
||||
int ssh_handle_key_exchange(ssh_session session) {
|
||||
int rc;
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user