aboutsummaryrefslogtreecommitdiff
path: root/libssh/server.c
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2005-08-07 10:48:08 +0000
committerAris Adamantiadis <aris@0xbadc0de.be>2005-08-07 10:48:08 +0000
commit5c26ae735483d140f802d58b1872b2fe9468d219 (patch)
treee8e8e8dea72c371e15f6e510ecc97948a4139383 /libssh/server.c
parent3113d8756628f463fda33b93801aee3c6ee9aa32 (diff)
downloadlibssh-5c26ae735483d140f802d58b1872b2fe9468d219.tar.gz
libssh-5c26ae735483d140f802d58b1872b2fe9468d219.tar.xz
libssh-5c26ae735483d140f802d58b1872b2fe9468d219.zip
server kex done :)
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@6 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh/server.c')
-rw-r--r--libssh/server.c141
1 files changed, 117 insertions, 24 deletions
diff --git a/libssh/server.c b/libssh/server.c
index 25f760ad..62294436 100644
--- a/libssh/server.c
+++ b/libssh/server.c
@@ -1,9 +1,6 @@
/* server.c */
-
-/* No. It doesn't work yet. It's just hard to have 2 separated trees, one for releases
- * and one for development */
/*
-Copyright 2004 Aris Adamantiadis
+Copyright 2004,2005 Aris Adamantiadis
This file is part of the SSH Library
@@ -35,6 +32,7 @@ MA 02111-1307, USA. */
#include <string.h>
#include "libssh/libssh.h"
#include "libssh/server.h"
+#include "libssh/ssh2.h"
static int bind_socket(SSH_BIND *ssh_bind,char *hostname, int port) {
struct sockaddr_in myaddr;
int opt = 1;
@@ -113,55 +111,79 @@ void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind){
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind){
SSH_SESSION *session;
+ PRIVATE_KEY *dsa=NULL, *rsa=NULL;
if(ssh_bind->bindfd<0){
ssh_set_error(ssh_bind,SSH_FATAL,"Can't accept new clients on a "
"not bound socket.");
return NULL;
}
+ if(!ssh_bind->options->dsakey && !ssh_bind->options->rsakey){
+ ssh_set_error(ssh_bind,SSH_FATAL,"DSA or RSA host key file must be set before accept()");
+ return NULL;
+ }
+ if(ssh_bind->options->dsakey){
+ dsa=_privatekey_from_file(ssh_bind,ssh_bind->options->dsakey,TYPE_DSS);
+ if(!dsa)
+ return NULL;
+ ssh_say(2,"Dsa private key read successfuly\n");
+ }
+ if(ssh_bind->options->rsakey){
+ rsa=_privatekey_from_file(ssh_bind,ssh_bind->options->rsakey,TYPE_RSA);
+ if(!rsa){
+ if(dsa)
+ private_key_free(dsa);
+ return NULL;
+ }
+ ssh_say(2,"RSA private key read successfuly\n");
+ }
int fd=accept(ssh_bind->bindfd,NULL,NULL);
if(fd<0){
ssh_set_error(ssh_bind,SSH_FATAL,"Accepting a new connection: %s",
strerror(errno));
+ if(dsa)
+ private_key_free(dsa);
+ if(rsa)
+ private_key_free(rsa);
return NULL;
}
- session=ssh_new(ssh_options_copy(ssh_bind->options));
+ session=ssh_new();
session->server=1;
+ session->version=2;
session->fd=fd;
session->options=ssh_options_copy(ssh_bind->options);
+ session->dsa_key=dsa;
+ session->rsa_key=rsa;
return session;
}
-
-/* do the banner and key exchange */
-int ssh_accept(SSH_SESSION *session){
- ssh_send_banner(session,1);
- return 0;
-}
-
-/*
extern char *supported_methods[];
+
int server_set_kex(SSH_SESSION * session) {
KEX *server = &session->server_kex;
SSH_OPTIONS *options = session->options;
int i;
char *wanted;
- if (!options) {
- ssh_set_error(session, SSH_FATAL,
- "Options structure is null(client's bug)");
- return -1;
- }
memset(server,0,sizeof(KEX));
// the program might ask for a specific cookie to be sent. useful for server
// debugging
if (options->wanted_cookie)
memcpy(server->cookie, options->wanted_cookie, 16);
else
- ssh_get_random(server->cookie, 16);
+ ssh_get_random(server->cookie, 16,0);
+ if(session->dsa_key && session->rsa_key){
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss,ssh-rsa");
+ } else {
+ if(session->dsa_key)
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss");
+ else
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-rsa");
+ }
server->methods = malloc(10 * sizeof(char **));
for (i = 0; i < 10; i++) {
- if (!(wanted = options->wanted_methods[i]))
- wanted = supported_methods[i];
- server->methods[i] = wanted;
- printf("server->methods[%d]=%s\n",i,wanted);
+ if (!(wanted = options->wanted_methods[i]))
+ wanted = supported_methods[i];
+ server->methods[i] = wanted;
+ printf("server->methods[%d]=%s\n",i,wanted);
+ }
if (!server->methods[i]) {
ssh_set_error(session, SSH_FATAL,
"kex error : did not find algo");
@@ -170,5 +192,76 @@ int server_set_kex(SSH_SESSION * session) {
return 0;
}
-*/
+static int dh_handshake_server(SSH_SESSION *session){
+ STRING *e,*f,*pubkey,*sign;
+ PUBLIC_KEY *pub;
+ PRIVATE_KEY *prv;
+ BUFFER *buf=buffer_new();
+ if(packet_wait(session, SSH2_MSG_KEXDH_INIT ,1))
+ return -1;
+ e=buffer_get_ssh_string(session->in_buffer);
+ if(!e){
+ ssh_set_error(session,SSH_FATAL,"No e number in client request");
+ return -1;
+ }
+ dh_import_e(session,e);
+ dh_generate_y(session);
+ dh_generate_f(session);
+ f=dh_get_f(session);
+ switch(session->hostkeys){
+ case TYPE_DSS:
+ prv=session->dsa_key;
+ break;
+ case TYPE_RSA:
+ prv=session->rsa_key;
+ break;
+ }
+ pub=publickey_from_privatekey(prv);
+ pubkey=publickey_to_string(pub);
+ publickey_free(pub);
+ dh_import_pubkey(session,pubkey);
+ dh_build_k(session);
+ make_sessionid(session);
+ sign=ssh_sign_session_id(session,prv);
+ buffer_free(buf);
+ private_key_free(prv);
+ buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_REPLY);
+ buffer_add_ssh_string(session->out_buffer,pubkey);
+ buffer_add_ssh_string(session->out_buffer,f);
+ buffer_add_ssh_string(session->out_buffer,sign);
+ free(sign);
+ packet_send(session);
+ free(f);
+ packet_clear_out(session);
+ buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
+ packet_send(session);
+ ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
+
+ packet_wait(session,SSH2_MSG_NEWKEYS,1);
+ ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
+ generate_session_keys(session);
+ /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
+ if(session->current_crypto)
+ crypto_free(session->current_crypto);
+ /* XXX later, include a function to change keys */
+ session->current_crypto=session->next_crypto;
+ session->next_crypto=crypto_new();
+ return 0;
+}
+/* do the banner and key exchange */
+int ssh_accept(SSH_SESSION *session){
+ ssh_send_banner(session,1);
+ ssh_crypto_init();
+ session->clientbanner=ssh_get_banner(session);
+ server_set_kex(session);
+ ssh_send_kex(session,1);
+ if(ssh_get_kex(session,1))
+ return -1;
+ ssh_list_kex(&session->client_kex);
+ crypt_set_algorithms_server(session);
+ if(dh_handshake_server(session))
+ return -1;
+ session->connected=1;
+ return 0;
+}