/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect2.c,v 1.39 2001/01/22 23:06:40 markus Exp $");
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/dh.h>
#include <openssl/hmac.h>
#include "ssh.h"
#include "ssh2.h"
#include "xmalloc.h"
#include "rsa.h"
#include "buffer.h"
#include "packet.h"
#include "uidswap.h"
#include "compat.h"
#include "bufaux.h"
#include "cipher.h"
#include "kex.h"
#include "myproposal.h"
#include "key.h"
#include "sshconnect.h"
#include "authfile.h"
#include "cli.h"
#include "dispatch.h"
#include "authfd.h"
#include "log.h"
#include "readconf.h"
#include "readpass.h"
void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
/* import */
extern char *client_version_string;
extern char *server_version_string;
extern Options options;
/*
* SSH2 key exchange
*/
u_char *session_id2 = NULL;
int session_id2_len = 0;
void
ssh_kex2(char *host, struct sockaddr *hostaddr)
{
int i, plen;
Kex *kex;
Buffer *client_kexinit, *server_kexinit;
char *sprop[PROPOSAL_MAX];
if (options.ciphers == (char *)-1) {
log("No valid ciphers for protocol version 2 given, using defaults.");
options.ciphers = NULL;
}
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
}
if (options.compression) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
} else {
myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
}
/* buffers with raw kexinit messages */
server_kexinit = xmalloc(sizeof(*server_kexinit));
buffer_init(server_kexinit);
client_kexinit = kex_init(myproposal);
/* algorithm negotiation */
kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
kex = kex_choose_conf(myproposal, sprop, 0);
for (i = 0; i < PROPOSAL_MAX; i++)
xfree(sprop[i]);
/* server authentication and session key agreement */
switch(kex->kex_type) {
case DH_GRP1_SHA1:
ssh_dh1_client(kex, host, hostaddr,
client_kexinit, server_kexinit);
break;
case DH_GEX_SHA1:
ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
server_kexinit);
break;
default:
fatal("Unsupported key exchange %d", kex->kex_type);
}
buffer_free(client_kexinit);
buffer_free(server_kexinit);
xfree(client_kexinit);
xfree(server_kexinit);
debug("Wait SSH2_MSG_NEWKEYS.");
packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
packet_done();
debug("GOT SSH2_MSG_NEWKEYS.");
debug("send SSH2_MSG_NEWKEYS.");
packet_start(SSH2_MSG_NEWKEYS);
packet_sen