server.c   server.c 
skipping to change at line 30 skipping to change at line 30
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
/** /**
* \defgroup ssh_server SSH Server * \defgroup ssh_server SSH Server
* \addtogroup ssh_server * \addtogroup ssh_server
* @{ * @{
*/ */
#include "config.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/server.h" #include "libssh/server.h"
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/keyfiles.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#define SOCKOPT_TYPE_ARG4 char #define SOCKOPT_TYPE_ARG4 char
/* We need to provide hstrerror. Not we can't call the parameter h_errno be cause it's #defined */ /* We need to provide hstrerror. Not we can't call the parameter h_errno be cause it's #defined */
inline char *hstrerror(int h_errno_val) { static char *hstrerror(int h_errno_val) {
static char text[50] = {0}; static char text[50] = {0};
snprintf(text, sizeof(text), "gethostbyname error %d\n", h_errno_val); snprintf(text, sizeof(text), "gethostbyname error %d\n", h_errno_val);
return text; return text;
} }
#else /* _WIN32 */ #else /* _WIN32 */
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#define SOCKOPT_TYPE_ARG4 int #define SOCKOPT_TYPE_ARG4 int
#endif /* _WIN32 */ #endif /* _WIN32 */
/* TODO FIXME: must use getaddrinfo */ /* TODO FIXME: must use getaddrinfo */
static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname, static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
int port) { int port) {
struct sockaddr_in myaddr; struct sockaddr_in myaddr;
struct hostent *hp=NULL; struct hostent *hp=NULL;
socket_t s; socket_t s;
int opt = 1; int opt = 1;
s = socket(PF_INET, SOCK_STREAM, 0); s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) { if (s < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, "%s", strerror(errno)); ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
return -1; return -1;
} }
#ifdef HAVE_GETHOSTBYNAME #ifdef HAVE_GETHOSTBYNAME
hp = gethostbyname(hostname); hp = gethostbyname(hostname);
#endif #endif
if (hp == NULL) { if (hp == NULL) {
ssh_set_error(ssh_bind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Resolving %s: %s", hostname, hstrerror(h_errno)); "Resolving %s: %s", hostname, hstrerror(h_errno));
close(s); close(s);
return -1; return -1;
} }
memset(&myaddr, 0, sizeof(myaddr)); memset(&myaddr, 0, sizeof(myaddr));
memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length); memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length);
myaddr.sin_family = hp->h_addrtype; myaddr.sin_family = hp->h_addrtype;
myaddr.sin_port = htons(port); myaddr.sin_port = htons(port);
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Setting socket options failed: %s", hstrerror(h_errno)); "Setting socket options failed: %s", hstrerror(h_errno));
close(s); close(s);
return -1; return -1;
} }
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) { if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, "Binding to %s:%d: %s", ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s",
hostname, hostname,
port, port,
strerror(errno)); strerror(errno));
close(s); close(s);
return -1; return -1;
} }
return s; return s;
} }
SSH_BIND *ssh_bind_new(void) { ssh_bind ssh_bind_new(void) {
SSH_BIND *ptr; ssh_bind ptr;
ptr = malloc(sizeof(SSH_BIND)); ptr = malloc(sizeof(struct ssh_bind_struct));
if (ptr == NULL) { if (ptr == NULL) {
return NULL; return NULL;
} }
ZERO_STRUCTP(ptr); ZERO_STRUCTP(ptr);
ptr->bindfd = -1; ptr->bindfd = -1;
ptr->bindport= 22;
ptr->log_verbosity = 0;
return ptr; return ptr;
} }
void ssh_bind_set_options(SSH_BIND *ssh_bind, SSH_OPTIONS *options) { int ssh_bind_listen(ssh_bind sshbind) {
ssh_bind->options = options;
}
int ssh_bind_listen(SSH_BIND *ssh_bind) {
const char *host; const char *host;
int fd; int fd;
if (ssh_bind->options == NULL) {
return -1;
}
if (ssh_init() < 0) { if (ssh_init() < 0) {
return -1; return -1;
} }
host = ssh_bind->options->bindaddr; host = sshbind->bindaddr;
if (host == NULL) { if (host == NULL) {
host = "0.0.0.0"; host = "0.0.0.0";
} }
fd = bind_socket(ssh_bind, host, ssh_bind->options->bindport); fd = bind_socket(sshbind, host, sshbind->bindport);
if (fd < 0) { if (fd < 0) {
return -1; return -1;
} }
ssh_bind->bindfd = fd; sshbind->bindfd = fd;
if (listen(fd, 10) < 0) { if (listen(fd, 10) < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Listening to socket %d: %s", "Listening to socket %d: %s",
fd, strerror(errno)); fd, strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
return 0; return 0;
} }
void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking) { void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
ssh_bind->blocking = blocking ? 1 : 0; sshbind->blocking = blocking ? 1 : 0;
} }
socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind) { socket_t ssh_bind_get_fd(ssh_bind sshbind) {
return ssh_bind->bindfd; return sshbind->bindfd;
} }
void ssh_bind_set_fd(SSH_BIND *ssh_bind, socket_t fd) { void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
ssh_bind->bindfd = fd; sshbind->bindfd = fd;
} }
void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind) { void ssh_bind_fd_toaccept(ssh_bind sshbind) {
ssh_bind->toaccept = 1; sshbind->toaccept = 1;
} }
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind) { int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
SSH_SESSION *session; ssh_private_key dsa = NULL;
PRIVATE_KEY *dsa = NULL; ssh_private_key rsa = NULL;
PRIVATE_KEY *rsa = NULL;
int fd = -1; int fd = -1;
int i;
if (ssh_bind->bindfd < 0) { if (sshbind->bindfd < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Can't accept new clients on a not bound socket."); "Can't accept new clients on a not bound socket.");
return NULL; return SSH_ERROR;
} }
if(session == NULL){
if (ssh_bind->options->dsakey == NULL || ssh_bind->options->rsakey == NUL ssh_set_error(sshbind, SSH_FATAL,"session is null");
L) { return SSH_ERROR;
ssh_set_error(ssh_bind, SSH_FATAL, }
if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
"DSA or RSA host key file must be set before accept()"); "DSA or RSA host key file must be set before accept()");
return NULL; return SSH_ERROR;
} }
if (ssh_bind->options->dsakey) { if (sshbind->dsakey) {
dsa = _privatekey_from_file(ssh_bind, ssh_bind->options->dsakey, TYPE_D dsa = _privatekey_from_file(sshbind, sshbind->dsakey, TYPE_DSS);
SS);
if (dsa == NULL) { if (dsa == NULL) {
return NULL; return SSH_ERROR;
} }
} }
if (ssh_bind->options->rsakey) { if (sshbind->rsakey) {
rsa = _privatekey_from_file(ssh_bind, ssh_bind->options->rsakey, TYPE_R rsa = _privatekey_from_file(sshbind, sshbind->rsakey, TYPE_RSA);
SA);
if (rsa == NULL) { if (rsa == NULL) {
privatekey_free(dsa); privatekey_free(dsa);
return NULL; return SSH_ERROR;
} }
} }
fd = accept(ssh_bind->bindfd, NULL, NULL); fd = accept(sshbind->bindfd, NULL, NULL);
if (fd < 0) { if (fd < 0) {
ssh_set_error(ssh_bind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Accepting a new connection: %s", "Accepting a new connection: %s",
strerror(errno)); strerror(errno));
privatekey_free(dsa); privatekey_free(dsa);
privatekey_free(rsa); privatekey_free(rsa);
return NULL; return SSH_ERROR;
} }
session = ssh_new();
if (session == NULL) {
ssh_set_error(ssh_bind, SSH_FATAL, "Not enough space");
privatekey_free(dsa);
privatekey_free(rsa);
return NULL;
}
session->server = 1; session->server = 1;
session->version = 2; session->version = 2;
session->options = ssh_options_copy(ssh_bind->options);
if (session->options == NULL) { /* copy options */
ssh_set_error(ssh_bind, SSH_FATAL, "No space left"); for (i = 0; i < 10; ++i) {
privatekey_free(dsa); if (sshbind->wanted_methods[i]) {
privatekey_free(rsa); session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
ssh_cleanup(session); if (session->wanted_methods[i] == NULL) {
return NULL; privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
}
}
if (sshbind->bindaddr == NULL)
session->bindaddr = NULL;
else {
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); ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session); session->socket = ssh_socket_new(session);
if (session->socket == NULL) { if (session->socket == NULL) {
privatekey_free(dsa); privatekey_free(dsa);
privatekey_free(rsa); privatekey_free(rsa);
ssh_cleanup(session); return SSH_ERROR;
return NULL;
} }
ssh_socket_set_fd(session->socket,fd); ssh_socket_set_fd(session->socket, fd);
session->dsa_key = dsa; session->dsa_key = dsa;
session->rsa_key = rsa; session->rsa_key = rsa;
return session; return SSH_OK;
} }
void ssh_bind_free(SSH_BIND *ssh_bind){ void ssh_bind_free(ssh_bind sshbind){
if (ssh_bind == NULL) { int i;
if (sshbind == NULL) {
return; return;
} }
if (ssh_bind->bindfd >= 0) { if (sshbind->bindfd >= 0) {
close(ssh_bind->bindfd); close(sshbind->bindfd);
} }
ssh_bind->bindfd = -1; sshbind->bindfd = -1;
if (ssh_bind->options) {
ssh_options_free(ssh_bind->options); /* 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(ssh_bind);
SAFE_FREE(sshbind);
} }
extern char *supported_methods[]; extern char *supported_methods[];
/** @internal
* This functions sets the Key Exchange protocols to be accepted
* by the server. They depend on
* -What the user asked (via options)
* -What is available (keys)
* It should then accept the intersection of what the user asked
* and what is available, and return an error if nothing matches
*/
static int server_set_kex(SSH_SESSION * session) { static int server_set_kex(ssh_session session) {
KEX *server = &session->server_kex; KEX *server = &session->server_kex;
SSH_OPTIONS *options = session->options;
int i, j; int i, j;
char *wanted; char *wanted;
ZERO_STRUCTP(server); ZERO_STRUCTP(server);
/* ssh_get_random(server->cookie, 16, 0);
* The program might ask for a specific cookie to be sent. Useful for ser
ver
* debugging
*/
if (options->wanted_cookie) {
memcpy(server->cookie, options->wanted_cookie, 16);
} else {
ssh_get_random(server->cookie, 16, 0);
}
if (session->dsa_key != NULL && session->rsa_key != NULL) { if (session->dsa_key != NULL && session->rsa_key != NULL) {
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, if (ssh_options_set_algo(session, SSH_HOSTKEYS,
"ssh-dss,ssh-rsa") < 0) { "ssh-dss,ssh-rsa") < 0) {
return -1; return -1;
} }
} else if (session->dsa_key != NULL) { } else if (session->dsa_key != NULL) {
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-dss") < 0) { if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-dss") < 0) {
return -1; return -1;
} }
} else { } else {
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-rsa") < 0) { if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-rsa") < 0) {
return -1; return -1;
} }
} }
server->methods = malloc(10 * sizeof(char **)); server->methods = malloc(10 * sizeof(char **));
if (server->methods == NULL) { if (server->methods == NULL) {
return -1; return -1;
} }
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if ((wanted = options->wanted_methods[i]) == NULL) { if ((wanted = session->wanted_methods[i]) == NULL) {
wanted = supported_methods[i]; wanted = supported_methods[i];
} }
server->methods[i] = strdup(wanted); server->methods[i] = strdup(wanted);
if (server->methods[i] == NULL) { if (server->methods[i] == NULL) {
for (j = i - 1; j <= 0; j--) { for (j = i - 1; j <= 0; j--) {
SAFE_FREE(server->methods[j]); SAFE_FREE(server->methods[j]);
} }
SAFE_FREE(server->methods); SAFE_FREE(server->methods);
return -1; return -1;
} }
} }
return 0; return 0;
} }
static int dh_handshake_server(SSH_SESSION *session) { static int dh_handshake_server(ssh_session session) {
STRING *e; ssh_string e;
STRING *f; ssh_string f;
STRING *pubkey; ssh_string pubkey;
STRING *sign; ssh_string sign;
PUBLIC_KEY *pub; ssh_public_key pub;
PRIVATE_KEY *prv; ssh_private_key prv;
if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) { if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) {
return -1; return -1;
} }
e = buffer_get_ssh_string(session->in_buffer); e = buffer_get_ssh_string(session->in_buffer);
if (e == NULL) { if (e == NULL) {
ssh_set_error(session, SSH_FATAL, "No e number in client request"); ssh_set_error(session, SSH_FATAL, "No e number in client request");
return -1; return -1;
} }
skipping to change at line 477 skipping to change at line 504
session->current_crypto = session->next_crypto; session->current_crypto = session->next_crypto;
session->next_crypto = crypto_new(); session->next_crypto = crypto_new();
if (session->next_crypto == NULL) { if (session->next_crypto == NULL) {
return -1; return -1;
} }
return 0; return 0;
} }
/* Do the banner and key exchange */ /* Do the banner and key exchange */
int ssh_accept(SSH_SESSION *session) { int ssh_accept(ssh_session session) {
if (ssh_send_banner(session, 1) < 0) { if (ssh_send_banner(session, 1) < 0) {
return -1; return -1;
} }
session->alive = 1; session->alive = 1;
session->clientbanner = ssh_get_banner(session); session->clientbanner = ssh_get_banner(session);
if (session->clientbanner == NULL) { if (session->clientbanner == NULL) {
return -1; return -1;
} }
skipping to change at line 513 skipping to change at line 540
if (dh_handshake_server(session) < 0) { if (dh_handshake_server(session) < 0) {
return -1; return -1;
} }
session->connected = 1; session->connected = 1;
return 0; return 0;
} }
/**
* @brief Blocking write on channel for stderr.
*
* @param channel The channel to write to.
*
* @param data A pointer to the data to write.
*
* @param len The length of the buffer to write to.
*
* @return The number of bytes written, SSH_ERROR on error.
*
* @see channel_read()
*/
int channel_write_stderr(ssh_channel channel, const void *data, uint32_t le
n) {
return channel_write_common(channel, data, len, 1);
}
/* messages */
static int ssh_message_auth_reply_default(ssh_message msg,int partial) {
ssh_session session = msg->session;
char methods_c[128] = {0};
ssh_string methods = NULL;
int rc = SSH_ERROR;
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) {
return rc;
}
if (session->auth_methods == 0) {
session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PAS
SWORD;
}
if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
strcat(methods_c, "publickey,");
}
if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
strcat(methods_c, "keyboard-interactive,");
}
if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
strcat(methods_c, "password,");
}
if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) {
strcat(methods_c, "hostbased,");
}
/* Strip the comma. */
methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure
there is at
ssh_log(session, SSH_LOG_PACKET,
"Sending a auth failure. methods that can continue: %s", methods_c);
methods = string_from_char(methods_c);
if (methods == NULL) {
goto error;
}
if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) {
goto error;
}
if (partial) {
if (buffer_add_u8(session->out_buffer, 1) < 0) {
goto error;
}
} else {
if (buffer_add_u8(session->out_buffer, 0) < 0) {
goto error;
}
}
rc = packet_send(msg->session);
error:
string_free(methods);
leave_function();
return rc;
}
static int ssh_message_channel_request_open_reply_default(ssh_message msg)
{
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Refusing a channel");
if (buffer_add_u8(msg->session->out_buffer
, SSH2_MSG_CHANNEL_OPEN_FAILURE) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(msg->channel_request_open.sender)) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) < 0) {
goto error;
}
/* reason is an empty string */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
/* language too */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
return packet_send(msg->session);
error:
return SSH_ERROR;
}
static int ssh_message_channel_request_reply_default(ssh_message msg) {
uint32_t channel;
if (msg->channel_request.want_reply) {
channel = msg->channel_request.channel->remote_channel;
ssh_log(msg->session, SSH_LOG_PACKET,
"Sending a default channel_request denied to channel %d", channel);
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_FAILURE) <
0) {
return SSH_ERROR;
}
if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
ssh_log(msg->session, SSH_LOG_PACKET,
"The client doesn't want to know the request failed!");
return SSH_OK;
}
static int ssh_message_service_request_reply_default(ssh_message msg) {
/* The only return code accepted by specifications are success or disconn
ect */
return ssh_message_service_reply_success(msg);
}
int ssh_message_service_reply_success(ssh_message msg) {
struct ssh_string_struct *service;
ssh_session session=msg->session;
if (msg == NULL) {
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET,
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.servi
ce);
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
return -1;
}
service=string_from_char(msg->service_request.service);
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
string_free(service);
return -1;
}
string_free(service);
return packet_send(msg->session);
}
int ssh_message_reply_default(ssh_message msg) {
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
return ssh_message_auth_reply_default(msg, 0);
case SSH_REQUEST_CHANNEL_OPEN:
return ssh_message_channel_request_open_reply_default(msg);
case SSH_REQUEST_CHANNEL:
return ssh_message_channel_request_reply_default(msg);
case SSH_REQUEST_SERVICE:
return ssh_message_service_request_reply_default(msg);
default:
ssh_log(msg->session, SSH_LOG_PACKET,
"Don't know what to default reply to %d type",
msg->type);
break;
}
return -1;
}
char *ssh_message_service_service(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->service_request.service;
}
char *ssh_message_auth_user(ssh_message msg) {
if (msg == NULL) {
return NULL;
}
return msg->auth_request.username;
}
char *ssh_message_auth_password(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.password;
}
/* Get the publickey of an auth request */
ssh_public_key ssh_message_auth_publickey(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.public_key;
}
int ssh_message_auth_set_methods(ssh_message msg, int methods) {
if (msg == NULL || msg->session == NULL) {
return -1;
}
msg->session->auth_methods = methods;
return 0;
}
int ssh_message_auth_reply_success(ssh_message msg, int partial) {
if (msg == NULL) {
return SSH_ERROR;
}
if (partial) {
return ssh_message_auth_reply_default(msg, partial);
}
if (buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0
) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
/* Answer OK to a pubkey auth request */
int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_stri
ng pubkey) {
if (msg == NULL) {
return SSH_ERROR;
}
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_USERAUTH_PK_OK) < 0
||
buffer_add_ssh_string(msg->session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(msg->session->out_buffer, pubkey) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
char *ssh_message_channel_request_open_originator(ssh_message msg){
return msg->channel_request_open.originator;
}
int ssh_message_channel_request_open_originator_port(ssh_message msg){
return msg->channel_request_open.originator_port;
}
char *ssh_message_channel_request_open_destination(ssh_message msg){
return msg->channel_request_open.destination;
}
int ssh_message_channel_request_open_destination_port(ssh_message msg){
return msg->channel_request_open.destination_port;
}
ssh_channel ssh_message_channel_request_channel(ssh_message msg){
return msg->channel_request.channel;
}
char *ssh_message_channel_request_pty_term(ssh_message msg){
return msg->channel_request.TERM;
}
int ssh_message_channel_request_pty_width(ssh_message msg){
return msg->channel_request.width;
}
int ssh_message_channel_request_pty_height(ssh_message msg){
return msg->channel_request.height;
}
int ssh_message_channel_request_pty_pxwidth(ssh_message msg){
return msg->channel_request.pxwidth;
}
int ssh_message_channel_request_pty_pxheight(ssh_message msg){
return msg->channel_request.pxheight;
}
char *ssh_message_channel_request_env_name(ssh_message msg){
return msg->channel_request.var_name;
}
char *ssh_message_channel_request_env_value(ssh_message msg){
return msg->channel_request.var_value;
}
char *ssh_message_channel_request_command(ssh_message msg){
return msg->channel_request.command;
}
char *ssh_message_channel_request_subsystem(ssh_message msg){
return msg->channel_request.subsystem;
}
/** @brief defines the SSH_MESSAGE callback
* @param session the current ssh session
* @param ssh_message_callback a function pointer to a callback taking the
* current ssh session and received message as parameters. the function ret
urns
* 0 if the message has been parsed and treated sucessfuly, 1 otherwise (li
bssh
* must take care of the response).
*/
void ssh_set_message_callback(ssh_session session,
int(*ssh_message_callback)(ssh_session session, ssh_message msg)){
session->ssh_message_callback=ssh_message_callback;
}
int ssh_execute_message_callbacks(ssh_session session){
ssh_message msg=NULL;
int ret;
if(!session->ssh_message_list)
return SSH_OK;
if(session->ssh_message_callback){
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list))
!= NULL){
ret=session->ssh_message_callback(session,msg);
if(ret==1){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;
}
}
} else {
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list))
!= NULL){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;
}
}
return SSH_OK;
}
/** @} /** @}
*/ */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */
 End of changes. 56 change blocks. 
105 lines changed or deleted 489 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/