kex.c   kex.c 
skipping to change at line 24 skipping to change at line 24
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details. * License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * 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 * along with the SSH Library; see the file COPYING. If not, write to
* 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.
*/ */
#include "config.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#ifndef _WIN32 #ifndef _WIN32
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#include "config.h"
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/ssh1.h" #include "libssh/ssh1.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/wrapper.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc," #define BLOWFISH "blowfish-cbc,"
#define AES "aes256-cbc,aes192-cbc,aes128-cbc," #define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#define DES "3des-cbc" #define DES "3des-cbc"
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_BLOWFISH_H #ifdef HAVE_OPENSSL_BLOWFISH_H
#define BLOWFISH "blowfish-cbc," #define BLOWFISH "blowfish-cbc,"
#else #else
#define BLOWFISH "" #define BLOWFISH ""
skipping to change at line 235 skipping to change at line 242
} }
} }
} }
free(tok_in[0]); free(tok_in[0]);
free(tok_what[0]); free(tok_what[0]);
free(tok_in); free(tok_in);
free(tok_what); free(tok_what);
return NULL; return NULL;
} }
int ssh_get_kex(SSH_SESSION *session, int server_kex) { int ssh_get_kex(ssh_session session, int server_kex) {
STRING *str = NULL; ssh_string str = NULL;
char *strings[10]; char *strings[10];
int i; int i;
enter_function(); enter_function();
if (packet_wait(session, SSH2_MSG_KEXINIT, 1) != SSH_OK) { if (packet_wait(session, SSH2_MSG_KEXINIT, 1) != SSH_OK) {
leave_function(); leave_function();
return -1; return -1;
} }
skipping to change at line 314 skipping to change at line 321
error: error:
string_free(str); string_free(str);
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
SAFE_FREE(strings[i]); SAFE_FREE(strings[i]);
} }
leave_function(); leave_function();
return -1; return -1;
} }
void ssh_list_kex(struct ssh_session *session, KEX *kex) { void ssh_list_kex(ssh_session session, KEX *kex) {
int i = 0; int i = 0;
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("session cookie", kex->cookie, 16); ssh_print_hexa("session cookie", kex->cookie, 16);
#endif #endif
for(i = 0; i < 10; i++) { for(i = 0; i < 10; i++) {
ssh_log(session, SSH_LOG_FUNCTIONS, "%s: %s", ssh_log(session, SSH_LOG_FUNCTIONS, "%s: %s",
ssh_kex_nums[i], kex->methods[i]); ssh_kex_nums[i], kex->methods[i]);
} }
} }
/* set_kex basicaly look at the option structure of the session and set the output kex message */ /* set_kex basicaly look at the option structure of the session and set the output kex message */
/* it must be aware of the server kex message */ /* it must be aware of the server kex message */
/* it can fail if option is null, not any user specified kex method matches the server one, if not any default kex matches */ /* it can fail if option is null, not any user specified kex method matches the server one, if not any default kex matches */
int set_kex(SSH_SESSION *session){ int set_kex(ssh_session session){
KEX *server = &session->server_kex; KEX *server = &session->server_kex;
KEX *client=&session->client_kex; KEX *client=&session->client_kex;
SSH_OPTIONS *options=session->options;
int i; int i;
const char *wanted; const char *wanted;
enter_function(); enter_function();
/* the client might ask for a specific cookie to be sent. useful for se ssh_get_random(client->cookie,16,0);
rver debugging */
if(options->wanted_cookie)
memcpy(client->cookie,options->wanted_cookie,16);
else
ssh_get_random(client->cookie,16,0);
client->methods=malloc(10 * sizeof(char **)); client->methods=malloc(10 * sizeof(char **));
if (client->methods == NULL) { if (client->methods == NULL) {
ssh_set_error(session, SSH_FATAL, "No space left"); ssh_set_error(session, SSH_FATAL, "No space left");
leave_function(); leave_function();
return -1; return -1;
} }
memset(client->methods,0,10*sizeof(char **)); memset(client->methods,0,10*sizeof(char **));
for (i=0;i<10;i++){ for (i=0;i<10;i++){
if(!(wanted=options->wanted_methods[i])) if(!(wanted=session->wanted_methods[i]))
wanted=default_methods[i]; wanted=default_methods[i];
client->methods[i]=ssh_find_matching(server->methods[i],wanted); client->methods[i]=ssh_find_matching(server->methods[i],wanted);
if(!client->methods[i] && i < SSH_LANG_C_S){ if(!client->methods[i] && i < SSH_LANG_C_S){
ssh_set_error(session,SSH_FATAL,"kex error : did not find one o f algos %s in list %s for %s", ssh_set_error(session,SSH_FATAL,"kex error : did not find one o f algos %s in list %s for %s",
wanted,server->methods[i],ssh_kex_nums[i]); wanted,server->methods[i],ssh_kex_nums[i]);
leave_function(); leave_function();
return -1; return -1;
} else { } else {
if ((i >= SSH_LANG_C_S) && (client->methods[i] == NULL)) { if ((i >= SSH_LANG_C_S) && (client->methods[i] == NULL)) {
/* we can safely do that for languages */ /* we can safely do that for languages */
skipping to change at line 374 skipping to change at line 376
return -1; return -1;
} }
} }
} }
} }
leave_function(); leave_function();
return 0; return 0;
} }
/* this function only sends the predefined set of kex methods */ /* this function only sends the predefined set of kex methods */
int ssh_send_kex(SSH_SESSION *session, int server_kex) { int ssh_send_kex(ssh_session session, int server_kex) {
KEX *kex = (server_kex ? &session->server_kex : &session->client_kex); KEX *kex = (server_kex ? &session->server_kex : &session->client_kex);
STRING *str = NULL; ssh_string str = NULL;
int i; int i;
enter_function(); enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXINIT) < 0) { if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXINIT) < 0) {
goto error; goto error;
} }
if (buffer_add_data(session->out_buffer, kex->cookie, 16) < 0) { if (buffer_add_data(session->out_buffer, kex->cookie, 16) < 0) {
goto error; goto error;
} }
skipping to change at line 447 skipping to change at line 449
ptr=ssh_find_matching(supported_methods[algo],name); ptr=ssh_find_matching(supported_methods[algo],name);
if(ptr){ if(ptr){
free(ptr); free(ptr);
return 1; return 1;
} }
return 0; return 0;
} }
/* makes a STRING contating 3 strings : ssh-rsa1,e and n */ /* makes a STRING contating 3 strings : ssh-rsa1,e and n */
/* this is a public key in openssh's format */ /* this is a public key in openssh's format */
static STRING *make_rsa1_string(STRING *e, STRING *n){ static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
BUFFER *buffer = NULL; ssh_buffer buffer = NULL;
STRING *rsa = NULL; ssh_string rsa = NULL;
STRING *ret = NULL; ssh_string ret = NULL;
buffer = buffer_new(); buffer = buffer_new();
rsa = string_from_char("ssh-rsa1"); rsa = string_from_char("ssh-rsa1");
if (buffer_add_ssh_string(buffer, rsa) < 0) { if (buffer_add_ssh_string(buffer, rsa) < 0) {
goto error; goto error;
} }
if (buffer_add_ssh_string(buffer, e) < 0) { if (buffer_add_ssh_string(buffer, e) < 0) {
goto error; goto error;
} }
skipping to change at line 478 skipping to change at line 480
} }
string_fill(ret, buffer_get(buffer), buffer_get_len(buffer)); string_fill(ret, buffer_get(buffer), buffer_get_len(buffer));
error: error:
buffer_free(buffer); buffer_free(buffer);
string_free(rsa); string_free(rsa);
return ret; return ret;
} }
static int build_session_id1(SSH_SESSION *session, STRING *servern, static int build_session_id1(ssh_session session, ssh_string servern,
STRING *hostn) { ssh_string hostn) {
MD5CTX md5 = NULL; MD5CTX md5 = NULL;
md5 = md5_init(); md5 = md5_init();
if (md5 == NULL) { if (md5 == NULL) {
return -1; return -1;
} }
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",hostn->string,string_len(hostn)); ssh_print_hexa("host modulus",hostn->string,string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern)); ssh_print_hexa("server modulus",servern->string,string_len(servern));
#endif #endif
md5_update(md5,hostn->string,string_len(hostn)); md5_update(md5,string_data(hostn),string_len(hostn));
md5_update(md5,servern->string,string_len(servern)); md5_update(md5,string_data(servern),string_len(servern));
md5_update(md5,session->server_kex.cookie,8); md5_update(md5,session->server_kex.cookie,8);
md5_final(session->next_crypto->session_id,md5); md5_final(session->next_crypto->session_id,md5);
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("session_id",session->next_crypto->session_id,MD5_DIGEST_L EN); ssh_print_hexa("session_id",session->next_crypto->session_id,MD5_DIGEST_L EN);
#endif #endif
return 0; return 0;
} }
/* returns 1 if the modulus of k1 is < than the one of k2 */ /* returns 1 if the modulus of k1 is < than the one of k2 */
static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){ static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){
bignum n1; bignum n1;
bignum n2; bignum n2;
int res; int res;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t sexp; gcry_sexp_t sexp;
sexp=gcry_sexp_find_token(k1->rsa_pub,"n",0); sexp=gcry_sexp_find_token(k1->rsa_pub,"n",0);
n1=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG); n1=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
gcry_sexp_release(sexp); gcry_sexp_release(sexp);
sexp=gcry_sexp_find_token(k2->rsa_pub,"n",0); sexp=gcry_sexp_find_token(k2->rsa_pub,"n",0);
n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG); n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
skipping to change at line 532 skipping to change at line 534
res=0; res=0;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_free(n1); bignum_free(n1);
bignum_free(n2); bignum_free(n2);
#endif #endif
return res; return res;
} }
#define ABS(A) ( (A)<0 ? -(A):(A) ) #define ABS(A) ( (A)<0 ? -(A):(A) )
static STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *srvkey static ssh_string encrypt_session_key(ssh_session session, ssh_public_key s
, rvkey,
PUBLIC_KEY *hostkey, int slen, int hlen) { ssh_public_key hostkey, int slen, int hlen) {
unsigned char buffer[32] = {0}; unsigned char buffer[32] = {0};
int i; int i;
STRING *data1 = NULL; ssh_string data1 = NULL;
STRING *data2 = NULL; ssh_string data2 = NULL;
/* first, generate a session key */ /* first, generate a session key */
ssh_get_random(session->next_crypto->encryptkey, 32, 1); ssh_get_random(session->next_crypto->encryptkey, 32, 1);
memcpy(buffer, session->next_crypto->encryptkey, 32); memcpy(buffer, session->next_crypto->encryptkey, 32);
memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey , 32); memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey , 32);
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("session key",buffer,32); ssh_print_hexa("session key",buffer,32);
#endif #endif
skipping to change at line 608 skipping to change at line 610
* mp-int server_key_public_exponent * mp-int server_key_public_exponent
* mp-int server_key_public_modulus * mp-int server_key_public_modulus
* 32-bit int host_key_bits * 32-bit int host_key_bits
* mp-int host_key_public_exponent * mp-int host_key_public_exponent
* mp-int host_key_public_modulus * mp-int host_key_public_modulus
* 32-bit int protocol_flags * 32-bit int protocol_flags
* 32-bit int supported_ciphers_mask * 32-bit int supported_ciphers_mask
* 32-bit int supported_authentications_mask * 32-bit int supported_authentications_mask
*/ */
int ssh_get_kex1(SSH_SESSION *session) { int ssh_get_kex1(ssh_session session) {
STRING *server_exp = NULL; ssh_string server_exp = NULL;
STRING *server_mod = NULL; ssh_string server_mod = NULL;
STRING *host_exp = NULL; ssh_string host_exp = NULL;
STRING *host_mod = NULL; ssh_string host_mod = NULL;
STRING *serverkey = NULL; ssh_string serverkey = NULL;
STRING *hostkey = NULL; ssh_string hostkey = NULL;
STRING *enc_session = NULL; ssh_string enc_session = NULL;
PUBLIC_KEY *srv = NULL; ssh_public_key srv = NULL;
PUBLIC_KEY *host = NULL; ssh_public_key host = NULL;
u32 server_bits; uint32_t server_bits;
u32 host_bits; uint32_t host_bits;
u32 protocol_flags; uint32_t protocol_flags;
u32 supported_ciphers_mask; uint32_t supported_ciphers_mask;
u32 supported_authentications_mask; uint32_t supported_authentications_mask;
u16 bits; uint16_t bits;
int rc = -1; int rc = -1;
int ko; int ko;
enter_function(); enter_function();
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) { if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) {
leave_function(); leave_function();
return -1; return -1;
} }
skipping to change at line 663 skipping to change at line 665
goto error; goto error;
} }
host_mod = buffer_get_mpint(session->in_buffer); host_mod = buffer_get_mpint(session->in_buffer);
if (host_mod == NULL) { if (host_mod == NULL) {
goto error; goto error;
} }
buffer_get_u32(session->in_buffer, &protocol_flags); buffer_get_u32(session->in_buffer, &protocol_flags);
buffer_get_u32(session->in_buffer, &supported_ciphers_mask); buffer_get_u32(session->in_buffer, &supported_ciphers_mask);
ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask); ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask);
if ((ko != sizeof(u32)) || !host_mod || !host_exp if ((ko != sizeof(uint32_t)) || !host_mod || !host_exp
|| !server_mod || !server_exp) { || !server_mod || !server_exp) {
ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet"); ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet");
ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet") ; ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet") ;
goto error; goto error;
} }
server_bits = ntohl(server_bits); server_bits = ntohl(server_bits);
host_bits = ntohl(host_bits); host_bits = ntohl(host_bits);
protocol_flags = ntohl(protocol_flags); protocol_flags = ntohl(protocol_flags);
supported_ciphers_mask = ntohl(supported_ciphers_mask); supported_ciphers_mask = ntohl(supported_ciphers_mask);
skipping to change at line 740 skipping to change at line 742
enc_session = encrypt_session_key(session, srv, host, server_bits, host_b its); enc_session = encrypt_session_key(session, srv, host, server_bits, host_b its);
if (enc_session == NULL) { if (enc_session == NULL) {
goto error; goto error;
} }
bits = string_len(enc_session) * 8 - 7; bits = string_len(enc_session) * 8 - 7;
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session" , ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session" ,
bits, string_len(enc_session)); bits, string_len(enc_session));
bits = htons(bits); bits = htons(bits);
/* the encrypted mpint */ /* the encrypted mpint */
if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) { if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) {
goto error; goto error;
} }
if (buffer_add_data(session->out_buffer, enc_session->string, if (buffer_add_data(session->out_buffer, string_data(enc_session),
string_len(enc_session)) < 0) { string_len(enc_session)) < 0) {
goto error; goto error;
} }
/* the protocol flags */ /* the protocol flags */
if (buffer_add_u32(session->out_buffer, 0) < 0) { if (buffer_add_u32(session->out_buffer, 0) < 0) {
goto error; goto error;
} }
if (packet_send(session) != SSH_OK) { if (packet_send(session) != SSH_OK) {
goto error; goto error;
 End of changes. 21 change blocks. 
48 lines changed or deleted 49 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/