comparison cli-session.c @ 801:7dcb46da72d9 ecc

merge in HEAD
author Matt Johnston <matt@ucc.asn.au>
date Tue, 21 May 2013 12:09:35 +0800
parents 7f604f9b3756 2400b8685762
children c19acba28590
comparison
equal deleted inserted replaced
799:c344607b7341 801:7dcb46da72d9
40 40
41 static void cli_remoteclosed(); 41 static void cli_remoteclosed();
42 static void cli_sessionloop(); 42 static void cli_sessionloop();
43 static void cli_session_init(); 43 static void cli_session_init();
44 static void cli_finished(); 44 static void cli_finished();
45 static void recv_msg_service_accept(void);
46 static void cli_session_cleanup(void);
45 47
46 struct clientsession cli_ses; /* GLOBAL */ 48 struct clientsession cli_ses; /* GLOBAL */
47 49
48 /* Sorted in decreasing frequency will be more efficient - data and window 50 /* Sorted in decreasing frequency will be more efficient - data and window
49 * should be first */ 51 * should be first */
94 96
95 /* Ready to go */ 97 /* Ready to go */
96 sessinitdone = 1; 98 sessinitdone = 1;
97 99
98 /* Exchange identification */ 100 /* Exchange identification */
99 session_identification(); 101 send_session_identification();
100 102
101 send_msg_kexinit(); 103 send_msg_kexinit();
102 104
103 session_loop(cli_sessionloop); 105 session_loop(cli_sessionloop);
104 106
105 /* Not reached */ 107 /* Not reached */
106 108
107 } 109 }
110
111 #ifdef USE_KEX_FIRST_FOLLOWS
112 static void cli_send_kex_first_guess() {
113 send_msg_kexdh_init();
114 }
115 #endif
108 116
109 static void cli_session_init() { 117 static void cli_session_init() {
110 118
111 cli_ses.state = STATE_NOTHING; 119 cli_ses.state = STATE_NOTHING;
112 cli_ses.kex_state = KEX_NOTHING; 120 cli_ses.kex_state = KEX_NOTHING;
137 cli_ses.cipher_none_after_auth = 0; 145 cli_ses.cipher_none_after_auth = 0;
138 #endif 146 #endif
139 147
140 /* For printing "remote host closed" for the user */ 148 /* For printing "remote host closed" for the user */
141 ses.remoteclosed = cli_remoteclosed; 149 ses.remoteclosed = cli_remoteclosed;
142 ses.buf_match_algo = cli_buf_match_algo; 150
151 ses.extra_session_cleanup = cli_session_cleanup;
143 152
144 /* packet handlers */ 153 /* packet handlers */
145 ses.packettypes = cli_packettypes; 154 ses.packettypes = cli_packettypes;
146 155
147 ses.isserver = 0; 156 ses.isserver = 0;
157
158 #ifdef USE_KEX_FIRST_FOLLOWS
159 ses.send_kex_first_guess = cli_send_kex_first_guess;
160 #endif
161
162 }
163
164 static void send_msg_service_request(char* servicename) {
165
166 TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
167
168 CHECKCLEARTOWRITE();
169
170 buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
171 buf_putstring(ses.writepayload, servicename, strlen(servicename));
172
173 encrypt_packet();
174 TRACE(("leave send_msg_service_request"))
175 }
176
177 static void recv_msg_service_accept(void) {
178 // do nothing, if it failed then the server MUST have disconnected
148 } 179 }
149 180
150 /* This function drives the progress of the session - it initiates KEX, 181 /* This function drives the progress of the session - it initiates KEX,
151 * service, userauth and channel requests */ 182 * service, userauth and channel requests */
152 static void cli_sessionloop() { 183 static void cli_sessionloop() {
153 184
154 TRACE(("enter cli_sessionloop")) 185 TRACE2(("enter cli_sessionloop"))
186
187 if (ses.lastpacket == 0) {
188 TRACE2(("exit cli_sessionloop: no real packets yet"))
189 return;
190 }
155 191
156 if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) { 192 if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
157 cli_ses.kex_state = KEXINIT_RCVD;
158 }
159
160 if (cli_ses.kex_state == KEXINIT_RCVD) {
161
162 /* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT 193 /* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
163 * negotiation would have failed. */ 194 * negotiation would have failed. */
164 send_msg_kexdh_init(); 195 if (!ses.kexstate.our_first_follows_matches) {
165 cli_ses.kex_state = KEXDH_INIT_SENT; 196 send_msg_kexdh_init();
197 }
198 cli_ses.kex_state = KEXDH_INIT_SENT;
166 TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD")) 199 TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
167 return; 200 return;
168 } 201 }
169 202
170 /* A KEX has finished, so we should go back to our KEX_NOTHING state */ 203 /* A KEX has finished, so we should go back to our KEX_NOTHING state */
171 if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0 204 if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
172 && ses.kexstate.sentkexinit == 0) {
173 cli_ses.kex_state = KEX_NOTHING; 205 cli_ses.kex_state = KEX_NOTHING;
174 } 206 }
175 207
176 /* We shouldn't do anything else if a KEX is in progress */ 208 /* We shouldn't do anything else if a KEX is in progress */
177 if (cli_ses.kex_state != KEX_NOTHING) { 209 if (cli_ses.kex_state != KEX_NOTHING) {
178 TRACE(("leave cli_sessionloop: kex_state != KEX_NOTHING")) 210 TRACE(("leave cli_sessionloop: kex_state != KEX_NOTHING"))
179 return; 211 return;
180 } 212 }
181 213
182 /* We should exit if we haven't donefirstkex: we shouldn't reach here
183 * in normal operation */
184 if (ses.kexstate.donefirstkex == 0) { 214 if (ses.kexstate.donefirstkex == 0) {
185 TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex")) 215 /* We might reach here if we have partial packet reads or have
216 * received SSG_MSG_IGNORE etc. Just skip it */
217 TRACE2(("donefirstkex false\n"))
186 return; 218 return;
187 } 219 }
188 220
189 switch (cli_ses.state) { 221 switch (cli_ses.state) {
190 222
191 case STATE_NOTHING: 223 case STATE_NOTHING:
192 /* We've got the transport layer sorted, we now need to request 224 /* We've got the transport layer sorted, we now need to request
193 * userauth */ 225 * userauth */
194 send_msg_service_request(SSH_SERVICE_USERAUTH); 226 send_msg_service_request(SSH_SERVICE_USERAUTH);
195 cli_ses.state = SERVICE_AUTH_REQ_SENT;
196 TRACE(("leave cli_sessionloop: sent userauth service req"))
197 return;
198
199 /* userauth code */
200 case SERVICE_AUTH_ACCEPT_RCVD:
201 cli_auth_getmethods(); 227 cli_auth_getmethods();
202 cli_ses.state = USERAUTH_REQ_SENT; 228 cli_ses.state = USERAUTH_REQ_SENT;
203 TRACE(("leave cli_sessionloop: sent userauth methods req")) 229 TRACE(("leave cli_sessionloop: sent userauth methods req"))
204 return; 230 return;
205 231
206 case USERAUTH_FAIL_RCVD: 232 case USERAUTH_FAIL_RCVD:
207 cli_auth_try(); 233 if (cli_auth_try() == DROPBEAR_FAILURE) {
234 dropbear_exit("No auth methods could be used.");
235 }
208 cli_ses.state = USERAUTH_REQ_SENT; 236 cli_ses.state = USERAUTH_REQ_SENT;
209 TRACE(("leave cli_sessionloop: cli_auth_try")) 237 TRACE(("leave cli_sessionloop: cli_auth_try"))
210 return; 238 return;
211 239
212 case USERAUTH_SUCCESS_RCVD: 240 case USERAUTH_SUCCESS_RCVD:
233 dropbear_exit("Backgrounding failed: %d %s", 261 dropbear_exit("Backgrounding failed: %d %s",
234 errno, strerror(errno)); 262 errno, strerror(errno));
235 } 263 }
236 } 264 }
237 265
238 #ifdef ENABLE_CLI_LOCALTCPFWD
239 setup_localtcp();
240 #endif
241 #ifdef ENABLE_CLI_REMOTETCPFWD
242 setup_remotetcp();
243 #endif
244
245 #ifdef ENABLE_CLI_NETCAT 266 #ifdef ENABLE_CLI_NETCAT
246 if (cli_opts.netcat_host) { 267 if (cli_opts.netcat_host) {
247 cli_send_netcat_request(); 268 cli_send_netcat_request();
248 } else 269 } else
249 #endif 270 #endif
250 if (!cli_opts.no_cmd) { 271 if (!cli_opts.no_cmd) {
251 cli_send_chansess_request(); 272 cli_send_chansess_request();
252 } 273 }
274
275 #ifdef ENABLE_CLI_LOCALTCPFWD
276 setup_localtcp();
277 #endif
278 #ifdef ENABLE_CLI_REMOTETCPFWD
279 setup_remotetcp();
280 #endif
281
253 TRACE(("leave cli_sessionloop: running")) 282 TRACE(("leave cli_sessionloop: running"))
254 cli_ses.state = SESSION_RUNNING; 283 cli_ses.state = SESSION_RUNNING;
255 return; 284 return;
256 285
257 case SESSION_RUNNING: 286 case SESSION_RUNNING:
269 298
270 default: 299 default:
271 break; 300 break;
272 } 301 }
273 302
274 TRACE(("leave cli_sessionloop: fell out")) 303 TRACE2(("leave cli_sessionloop: fell out"))
275 304
276 } 305 }
277 306
278 void cli_session_cleanup() { 307 static void cli_session_cleanup(void) {
279 308
280 if (!sessinitdone) { 309 if (!sessinitdone) {
281 return; 310 return;
282 } 311 }
283 312
291 320
292 } 321 }
293 322
294 static void cli_finished() { 323 static void cli_finished() {
295 324
296 cli_session_cleanup(); 325 session_cleanup();
297 common_session_cleanup();
298 fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, 326 fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
299 cli_opts.remotehost, cli_opts.remoteport); 327 cli_opts.remotehost, cli_opts.remoteport);
300 exit(cli_ses.retval); 328 exit(cli_ses.retval);
301 } 329 }
302 330