comparison src/ch/ethz/ssh2/transport/ServerKexManager.java @ 273:91a31873c42a ganymed

start conversion from trilead to ganymed
author Carl Byington <carl@five-ten-sg.com>
date Fri, 18 Jul 2014 11:21:46 -0700
parents
children b4ca341c318d
comparison
equal deleted inserted replaced
272:ce2f4e397703 273:91a31873c42a
1 /*
2 * Copyright (c) 2006-2013 Christian Plattner. All rights reserved.
3 * Please refer to the LICENSE.txt for licensing details.
4 */
5 package ch.ethz.ssh2.transport;
6
7 import java.io.IOException;
8 import java.security.DigestException;
9
10 import ch.ethz.ssh2.ConnectionInfo;
11 import ch.ethz.ssh2.PacketTypeException;
12 import ch.ethz.ssh2.auth.ServerAuthenticationManager;
13 import ch.ethz.ssh2.crypto.cipher.BlockCipher;
14 import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory;
15 import ch.ethz.ssh2.crypto.dh.DhExchange;
16 import ch.ethz.ssh2.crypto.digest.MAC;
17 import ch.ethz.ssh2.packets.PacketKexDHInit;
18 import ch.ethz.ssh2.packets.PacketKexDHReply;
19 import ch.ethz.ssh2.packets.PacketKexInit;
20 import ch.ethz.ssh2.packets.Packets;
21 import ch.ethz.ssh2.server.ServerConnectionState;
22 import ch.ethz.ssh2.signature.DSASHA1Verify;
23 import ch.ethz.ssh2.signature.DSASignature;
24 import ch.ethz.ssh2.signature.RSASHA1Verify;
25 import ch.ethz.ssh2.signature.RSASignature;
26
27 /**
28 * @version $Id: ServerKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $
29 */
30 public class ServerKexManager extends KexManager {
31
32 private final ServerConnectionState state;
33
34 private boolean authenticationStarted = false;
35
36 public ServerKexManager(ServerConnectionState state) {
37 super(state.tm, state.csh, state.next_cryptoWishList, state.generator);
38 this.state = state;
39 }
40
41 @Override
42 public void handleFailure(final IOException failure) {
43 synchronized(accessLock) {
44 connectionClosed = true;
45 accessLock.notifyAll();
46 }
47 }
48
49 @Override
50 public void handleMessage(byte[] msg) throws IOException {
51 PacketKexInit kip;
52
53 if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) {
54 throw new PacketTypeException(msg[0]);
55 }
56
57 if(ignore_next_kex_packet) {
58 ignore_next_kex_packet = false;
59 return;
60 }
61
62 if(msg[0] == Packets.SSH_MSG_KEXINIT) {
63 if((kxs != null) && (kxs.state != 0)) {
64 throw new PacketTypeException(msg[0]);
65 }
66
67 if(kxs == null) {
68 /*
69 * Ah, OK, peer wants to do KEX. Let's be nice and play
70 * together.
71 */
72 kxs = new KexState();
73 kxs.local_dsa_key = nextKEXdsakey;
74 kxs.local_rsa_key = nextKEXrsakey;
75 kxs.dhgexParameters = nextKEXdhgexParameters;
76 kip = new PacketKexInit(nextKEXcryptoWishList, rnd);
77 kxs.localKEX = kip;
78 tm.sendKexMessage(kip.getPayload());
79 }
80
81 kip = new PacketKexInit(msg);
82 kxs.remoteKEX = kip;
83
84 kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters());
85
86 if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) {
87 // Guess was wrong, we need to ignore the next kex packet.
88 ignore_next_kex_packet = true;
89 }
90
91 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
92 || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
93 kxs.dhx = new DhExchange();
94
95 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) {
96 kxs.dhx.serverInit(1, rnd);
97 }
98 else {
99 kxs.dhx.serverInit(14, rnd);
100 }
101
102 kxs.state = 1;
103 return;
104 }
105
106 throw new IllegalStateException("Unkown KEX method!");
107 }
108
109 if(msg[0] == Packets.SSH_MSG_NEWKEYS) {
110 if(km == null) {
111 throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!");
112 }
113
114 BlockCipher cbc;
115 MAC mac;
116
117 try {
118 cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false,
119 km.enc_key_client_to_server, km.initial_iv_client_to_server);
120
121 try {
122 mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server);
123 }
124 catch(DigestException e) {
125 throw new IOException(e);
126 }
127
128 }
129 catch(IllegalArgumentException e) {
130 throw new IOException(e);
131 }
132
133 tm.changeRecvCipher(cbc, mac);
134
135 ConnectionInfo sci = new ConnectionInfo();
136
137 kexCount++;
138
139 sci.keyExchangeAlgorithm = kxs.np.kex_algo;
140 sci.keyExchangeCounter = kexCount;
141 sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server;
142 sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client;
143 sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server;
144 sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client;
145 sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo;
146 sci.serverHostKey = kxs.remote_hostkey;
147
148 synchronized(accessLock) {
149 lastConnInfo = sci;
150 accessLock.notifyAll();
151 }
152
153 kxs = null;
154 return;
155 }
156
157 if((kxs == null) || (kxs.state == 0)) {
158 throw new IOException("Unexpected Kex submessage!");
159 }
160
161 if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")
162 || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) {
163 if(kxs.state == 1) {
164 PacketKexDHInit dhi = new PacketKexDHInit(msg);
165
166 kxs.dhx.setE(dhi.getE());
167
168 byte[] hostKey = null;
169
170 if(kxs.np.server_host_key_algo.equals("ssh-rsa")) {
171 hostKey = RSASHA1Verify.encodeSSHRSAPublicKey(kxs.local_rsa_key.getPublicKey());
172 }
173
174 if(kxs.np.server_host_key_algo.equals("ssh-dss")) {
175 hostKey = DSASHA1Verify.encodeSSHDSAPublicKey(kxs.local_dsa_key.getPublicKey());
176 }
177
178 try {
179 kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(),
180 kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey);
181 }
182 catch(IllegalArgumentException e) {
183 throw new IOException("KEX error.", e);
184 }
185
186 kxs.K = kxs.dhx.getK();
187
188 byte[] signature = null;
189
190 if(kxs.np.server_host_key_algo.equals("ssh-rsa")) {
191 RSASignature rs = RSASHA1Verify.generateSignature(kxs.H, kxs.local_rsa_key);
192 signature = RSASHA1Verify.encodeSSHRSASignature(rs);
193 }
194
195 if(kxs.np.server_host_key_algo.equals("ssh-dss")) {
196 DSASignature ds = DSASHA1Verify.generateSignature(kxs.H, kxs.local_dsa_key, rnd);
197 signature = DSASHA1Verify.encodeSSHDSASignature(ds);
198 }
199
200 PacketKexDHReply dhr = new PacketKexDHReply(hostKey, kxs.dhx.getF(), signature);
201 tm.sendKexMessage(dhr.getPayload());
202
203 finishKex(false);
204 kxs.state = -1;
205
206 if(authenticationStarted == false) {
207 authenticationStarted = true;
208 state.am = new ServerAuthenticationManager(state);
209 }
210
211 return;
212 }
213 }
214 throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo));
215 }
216 }