~ubuntu-branches/ubuntu/jaunty/fqterm/jaunty

« back to all changes in this revision

Viewing changes to src/protocol/internal/fqterm_ssh_kex.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LI Daobing
  • Date: 2009-02-14 09:32:53 UTC
  • Revision ID: james.westby@ubuntu.com-20090214093253-s2e6544ox2aj79rj
Tags: upstream-0.9.3+svn632
ImportĀ upstreamĀ versionĀ 0.9.3+svn632

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   fqterm, a terminal emulator for both BBS and *nix.                    *
 
3
 *   Copyright (C) 2008 fqterm development group.                          *
 
4
 *                                                                         *
 
5
 *   This program is free software; you can redistribute it and/or modify  *
 
6
 *   it under the terms of the GNU General Public License as published by  *
 
7
 *   the Free Software Foundation; either version 2 of the License, or     *
 
8
 *   (at your option) any later version.                                   *
 
9
 *                                                                         *
 
10
 *   This program is distributed in the hope that it will be useful,       *
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
13
 *   GNU General Public License for more details.                          *
 
14
 *                                                                         *
 
15
 *   You should have received a copy of the GNU General Public License     *
 
16
 *   along with this program; if not, write to the                         *
 
17
 *   Free Software Foundation, Inc.,                                       *
 
18
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.               *
 
19
 ***************************************************************************/
 
20
 
 
21
#include "fqterm_ssh_kex.h"
 
22
#include "fqterm_ssh_md5.h"
 
23
#include "fqterm_trace.h"
 
24
 
 
25
namespace FQTerm {
 
26
 
 
27
FQTermSSHKex::FQTermSSHKex(const char *V_C, const char *V_S) {
 
28
  V_C_ = new char[strlen(V_C) + 1];
 
29
  V_S_ = new char[strlen(V_S) + 1];
 
30
 
 
31
  strcpy(V_C_, V_C);
 
32
  strcpy(V_S_, V_S);
 
33
}
 
34
 
 
35
FQTermSSHKex::~FQTermSSHKex() {
 
36
  delete[] V_C_;
 
37
  delete[] V_S_;
 
38
}
 
39
 
 
40
 
 
41
//==============================================================================
 
42
//FQTermSSH1Kex
 
43
//==============================================================================
 
44
 
 
45
FQTermSSH1Kex::FQTermSSH1Kex(const char *V_C, const char *V_S)
 
46
    : FQTermSSHKex(V_C, V_S) {
 
47
  is_first_kex_ = true;
 
48
  kex_state_ = FQTermSSH1Kex::BEFORE_PUBLICKEY;
 
49
}
 
50
 
 
51
FQTermSSH1Kex::~FQTermSSH1Kex(){}
 
52
 
 
53
void FQTermSSH1Kex::initKex(FQTermSSHPacketReceiver *packetReceiver,
 
54
                            FQTermSSHPacketSender       *packetSender) {
 
55
  packet_receiver_ = packetReceiver;
 
56
  packet_sender_ = packetSender;
 
57
  packet_receiver_->disconnect(this);
 
58
  FQ_VERIFY(connect(packet_receiver_, SIGNAL(packetAvaliable(int)),
 
59
                    this, SLOT(handlePacket(int))));
 
60
  kex_state_ = FQTermSSH1Kex::BEFORE_PUBLICKEY;
 
61
  emit reKex();
 
62
}
 
63
 
 
64
void FQTermSSH1Kex::handlePacket(int type) {
 
65
  switch (kex_state_) {
 
66
    case FQTermSSH1Kex::BEFORE_PUBLICKEY:
 
67
      makeSessionKey();
 
68
      kex_state_ = FQTermSSH1Kex::SESSIONKEY_SENT;
 
69
      break;
 
70
    case FQTermSSH1Kex::SESSIONKEY_SENT:
 
71
      if (type != SSH1_SMSG_SUCCESS) {
 
72
        emit kexError("Kex exchange failed!");
 
73
        break;
 
74
      }
 
75
      emit kexOK();
 
76
      kex_state_ = FQTermSSH1Kex::KEYEX_OK;
 
77
      break;
 
78
    case FQTermSSH1Kex::KEYEX_OK:
 
79
      break;
 
80
  }
 
81
}
 
82
 
 
83
void FQTermSSH1Kex::makeSessionKey() {
 
84
  int i;
 
85
  BIGNUM *key;
 
86
  u_int32_t rand_val;
 
87
  int bits;
 
88
  int rbits;
 
89
 
 
90
  if (packet_receiver_->packetType() != SSH1_SMSG_PUBLIC_KEY) {
 
91
    emit kexError("startKex: First packet is not public key");
 
92
    return ;
 
93
  }
 
94
  packet_receiver_->getRawData((char*)cookie_, 8);
 
95
 
 
96
  // Get the public key.
 
97
  server_key_ = new FQTermSSHRSA;
 
98
  bits = packet_receiver_->getInt();
 
99
  packet_receiver_->getBN(server_key_->d_rsa->e);
 
100
  packet_receiver_->getBN(server_key_->d_rsa->n);
 
101
 
 
102
  rbits = BN_num_bits(server_key_->d_rsa->n);
 
103
  if (bits != rbits) {
 
104
    FQ_TRACE("sshkex", 0) << "Warning: Server lies about "
 
105
                          << "size of server public key: "
 
106
                          << "actual size: " << rbits
 
107
                          << " vs. anounced: " << bits;
 
108
    FQ_TRACE("sshkex", 0) << "Warning: This may be due to "
 
109
                          << "an old implementation of ssh.";
 
110
  }
 
111
 
 
112
  // Get the host key.
 
113
  host_key_ = new FQTermSSHRSA;
 
114
  bits = packet_receiver_->getInt();
 
115
  packet_receiver_->getBN(host_key_->d_rsa->e);
 
116
  packet_receiver_->getBN(host_key_->d_rsa->n);
 
117
 
 
118
  rbits = BN_num_bits(host_key_->d_rsa->n);
 
119
  if (bits != rbits) {
 
120
    FQ_TRACE("sshkex", 0) << "Warning: Server lies about "
 
121
                          << "size of server public key: "
 
122
                          << "actual size: " << rbits
 
123
                          << " vs. anounced: " << bits;
 
124
    FQ_TRACE("sshkex", 0) << "Warning: This may be due to "
 
125
                          << "an old implementation of ssh.";
 
126
  }
 
127
 
 
128
  // Get protocol flags.
 
129
  server_flag_ = packet_receiver_->getInt();
 
130
  ciphers_ = packet_receiver_->getInt();
 
131
  auth_ = packet_receiver_->getInt();
 
132
 
 
133
  if ((ciphers_ &(1 << SSH_CIPHER_3DES)) == 0) {
 
134
    FQ_VERIFY(false); // server do not support my cipher
 
135
  } 
 
136
 
 
137
  makeSessionId();
 
138
 
 
139
  // Generate an encryption key for the session. The key is a 256 bit
 
140
  // random number, interpreted as a 32-byte key, with the least
 
141
  // significant 8 bits being the first byte of the key.
 
142
 
 
143
  for (i = 0; i < 32; i++) {
 
144
    if (i % 4 == 0) {
 
145
      rand_val = rand();
 
146
    } 
 
147
    
 
148
    session_key_[i] = (rand_val &0xff);
 
149
    rand_val >>= 8;
 
150
  }
 
151
 
 
152
  key = BN_new();
 
153
 
 
154
  BN_set_word(key, 0);
 
155
  for (i = 0; i < 32; i++) {
 
156
    BN_lshift(key, key, 8);
 
157
    if (i < 16) {
 
158
      BN_add_word(key, session_key_[i] ^ session_id_[i]);
 
159
    } else {
 
160
      BN_add_word(key, session_key_[i]);
 
161
    } 
 
162
  }
 
163
 
 
164
  if (BN_cmp(server_key_->d_rsa->n, host_key_->d_rsa->n) < 0) {
 
165
    server_key_->publicEncrypt(key, key);
 
166
    host_key_->publicEncrypt(key, key);
 
167
  } else {
 
168
    host_key_->publicEncrypt(key, key);
 
169
    server_key_->publicEncrypt(key, key);
 
170
  }
 
171
 
 
172
  delete host_key_;
 
173
  delete server_key_;
 
174
 
 
175
  packet_sender_->startPacket(SSH1_CMSG_SESSION_KEY);
 
176
  packet_sender_->putByte(SSH_CIPHER_3DES);
 
177
  packet_sender_->putRawData((const char*)cookie_, 8);
 
178
  packet_sender_->putBN(key);
 
179
 
 
180
  BN_free(key);
 
181
 
 
182
  packet_sender_->putInt(1);
 
183
  packet_sender_->write();
 
184
 
 
185
  emit startEncryption(session_key_);
 
186
}
 
187
 
 
188
void FQTermSSH1Kex::makeSessionId() {
 
189
  u_char *p;
 
190
  FQTermSSHMD5 *md5;
 
191
  int servlen, hostlen;
 
192
 
 
193
  md5 = new FQTermSSHMD5;
 
194
  servlen = BN_num_bytes(server_key_->d_rsa->n);
 
195
  hostlen = BN_num_bytes(host_key_->d_rsa->n);
 
196
 
 
197
  p = new u_char[servlen + hostlen];
 
198
 
 
199
  BN_bn2bin(host_key_->d_rsa->n, p);
 
200
  BN_bn2bin(server_key_->d_rsa->n, p + hostlen);
 
201
  md5->update(p, servlen + hostlen);
 
202
  md5->update(cookie_, 8);
 
203
  md5->final(session_id_);
 
204
  delete md5;
 
205
  delete [] p;
 
206
}
 
207
 
 
208
}  // namespace FQTerm
 
209
 
 
210
#include "fqterm_ssh_kex.moc"