blob: 0657c37e8e82eb9608f435409a04166f0f819fec [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 * Created: Sat Mar 18 22:15:47 1995 ylo
6 * Code to connect to a remote host, and to perform the client side of the
7 * login (authentication) dialog.
8 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10009
10#include "includes.h"
Damien Miller95def091999-11-25 00:26:21 +110011RCSID("$Id: sshconnect.c,v 1.14 1999/11/24 13:26:23 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100012
Damien Miller7f6ea021999-10-28 13:25:17 +100013#ifdef HAVE_OPENSSL
Damien Millerd4a8b7e1999-10-27 13:42:43 +100014#include <openssl/bn.h>
Damien Miller7f6ea021999-10-28 13:25:17 +100015#include <openssl/md5.h>
16#endif
17#ifdef HAVE_SSL
18#include <ssl/bn.h>
19#include <ssl/md5.h>
20#endif
21
Damien Millerd4a8b7e1999-10-27 13:42:43 +100022#include "xmalloc.h"
23#include "rsa.h"
24#include "ssh.h"
25#include "packet.h"
26#include "authfd.h"
27#include "cipher.h"
28#include "mpaux.h"
29#include "uidswap.h"
30#include "compat.h"
Damien Miller6d7b2cd1999-11-12 15:19:27 +110031#include "readconf.h"
Damien Miller81428f91999-11-18 09:28:11 +110032#include "fingerprint.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100033
34/* Session id for the current session. */
35unsigned char session_id[16];
36
Damien Miller95def091999-11-25 00:26:21 +110037/*
38 * Connect to the given ssh server using a proxy command.
39 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100040int
41ssh_proxy_connect(const char *host, int port, uid_t original_real_uid,
42 const char *proxy_command)
43{
Damien Miller95def091999-11-25 00:26:21 +110044 Buffer command;
45 const char *cp;
46 char *command_string;
47 int pin[2], pout[2];
48 int pid;
49 char portstring[100];
Damien Millerd4a8b7e1999-10-27 13:42:43 +100050
Damien Miller95def091999-11-25 00:26:21 +110051 /* Convert the port number into a string. */
52 snprintf(portstring, sizeof portstring, "%d", port);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100053
Damien Miller95def091999-11-25 00:26:21 +110054 /* Build the final command string in the buffer by making the
55 appropriate substitutions to the given proxy command. */
56 buffer_init(&command);
57 for (cp = proxy_command; *cp; cp++) {
58 if (cp[0] == '%' && cp[1] == '%') {
59 buffer_append(&command, "%", 1);
60 cp++;
61 continue;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100062 }
Damien Miller95def091999-11-25 00:26:21 +110063 if (cp[0] == '%' && cp[1] == 'h') {
64 buffer_append(&command, host, strlen(host));
65 cp++;
66 continue;
67 }
68 if (cp[0] == '%' && cp[1] == 'p') {
69 buffer_append(&command, portstring, strlen(portstring));
70 cp++;
71 continue;
72 }
73 buffer_append(&command, cp, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100074 }
Damien Miller95def091999-11-25 00:26:21 +110075 buffer_append(&command, "\0", 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100076
Damien Miller95def091999-11-25 00:26:21 +110077 /* Get the final command string. */
78 command_string = buffer_ptr(&command);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100079
Damien Miller95def091999-11-25 00:26:21 +110080 /* Create pipes for communicating with the proxy. */
81 if (pipe(pin) < 0 || pipe(pout) < 0)
82 fatal("Could not create pipes to communicate with the proxy: %.100s",
83 strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +100084
Damien Miller95def091999-11-25 00:26:21 +110085 debug("Executing proxy command: %.500s", command_string);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100086
Damien Miller95def091999-11-25 00:26:21 +110087 /* Fork and execute the proxy command. */
88 if ((pid = fork()) == 0) {
89 char *argv[10];
Damien Millerd4a8b7e1999-10-27 13:42:43 +100090
Damien Miller95def091999-11-25 00:26:21 +110091 /* Child. Permanently give up superuser privileges. */
92 permanently_set_uid(original_real_uid);
93
94 /* Redirect stdin and stdout. */
95 close(pin[1]);
96 if (pin[0] != 0) {
97 if (dup2(pin[0], 0) < 0)
98 perror("dup2 stdin");
99 close(pin[0]);
100 }
101 close(pout[0]);
102 if (dup2(pout[1], 1) < 0)
103 perror("dup2 stdout");
104 /* Cannot be 1 because pin allocated two descriptors. */
105 close(pout[1]);
106
107 /* Stderr is left as it is so that error messages get
108 printed on the user's terminal. */
109 argv[0] = "/bin/sh";
110 argv[1] = "-c";
111 argv[2] = command_string;
112 argv[3] = NULL;
113
114 /* Execute the proxy command. Note that we gave up any
115 extra privileges above. */
116 execv("/bin/sh", argv);
117 perror("/bin/sh");
118 exit(1);
119 }
120 /* Parent. */
121 if (pid < 0)
122 fatal("fork failed: %.100s", strerror(errno));
123
124 /* Close child side of the descriptors. */
125 close(pin[0]);
126 close(pout[1]);
127
128 /* Free the command name. */
129 buffer_free(&command);
130
131 /* Set the connection file descriptors. */
132 packet_set_connection(pout[0], pin[1]);
133
134 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000135}
136
Damien Miller95def091999-11-25 00:26:21 +1100137/*
138 * Creates a (possibly privileged) socket for use as the ssh connection.
139 */
140int
141ssh_create_socket(uid_t original_real_uid, int privileged)
142{
143 int sock;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000144
Damien Miller95def091999-11-25 00:26:21 +1100145 /* If we are running as root and want to connect to a privileged
146 port, bind our own socket to a privileged port. */
147 if (privileged) {
148 int p = IPPORT_RESERVED - 1;
149
150 sock = rresvport(&p);
151 if (sock < 0)
152 fatal("rresvport: %.100s", strerror(errno));
153 debug("Allocated local port %d.", p);
154 } else {
155 /* Just create an ordinary socket on arbitrary port. We
156 use the user's uid to create the socket. */
157 temporarily_use_uid(original_real_uid);
158 sock = socket(AF_INET, SOCK_STREAM, 0);
159 if (sock < 0)
160 fatal("socket: %.100s", strerror(errno));
161 restore_uid();
162 }
163 return sock;
164}
165
166/*
167 * Opens a TCP/IP connection to the remote server on the given host. If
168 * port is 0, the default port will be used. If anonymous is zero,
169 * a privileged port will be allocated to make the connection.
170 * This requires super-user privileges if anonymous is false.
171 * Connection_attempts specifies the maximum number of tries (one per
172 * second). If proxy_command is non-NULL, it specifies the command (with %h
173 * and %p substituted for host and port, respectively) to use to contact
174 * the daemon.
175 */
176int
177ssh_connect(const char *host, struct sockaddr_in * hostaddr,
178 int port, int connection_attempts,
179 int anonymous, uid_t original_real_uid,
180 const char *proxy_command)
181{
182 int sock = -1, attempt, i;
183 int on = 1;
184 struct servent *sp;
185 struct hostent *hp;
186 struct linger linger;
187
188 debug("ssh_connect: getuid %d geteuid %d anon %d",
189 (int) getuid(), (int) geteuid(), anonymous);
190
191 /* Get default port if port has not been set. */
192 if (port == 0) {
193 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
194 if (sp)
195 port = ntohs(sp->s_port);
196 else
197 port = SSH_DEFAULT_PORT;
198 }
199 /* If a proxy command is given, connect using it. */
200 if (proxy_command != NULL)
201 return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
202
203 /* No proxy command. */
204
205 /* No host lookup made yet. */
206 hp = NULL;
207
208 /* Try to connect several times. On some machines, the first time
209 will sometimes fail. In general socket code appears to behave
210 quite magically on many machines. */
211 for (attempt = 0; attempt < connection_attempts; attempt++) {
212 if (attempt > 0)
213 debug("Trying again...");
214
215 /* Try to parse the host name as a numeric inet address. */
216 memset(hostaddr, 0, sizeof(hostaddr));
217 hostaddr->sin_family = AF_INET;
218 hostaddr->sin_port = htons(port);
219 hostaddr->sin_addr.s_addr = inet_addr(host);
220 if ((hostaddr->sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
221 /* Valid numeric IP address */
222 debug("Connecting to %.100s port %d.",
223 inet_ntoa(hostaddr->sin_addr), port);
224
225 /* Create a socket. */
226 sock = ssh_create_socket(original_real_uid,
227 !anonymous && geteuid() == 0 &&
228 port < IPPORT_RESERVED);
229
230 /* Connect to the host. We use the user's uid in
231 the hope that it will help with the problems of
232 tcp_wrappers showing the remote uid as root. */
233 temporarily_use_uid(original_real_uid);
234 if (connect(sock, (struct sockaddr *) hostaddr, sizeof(*hostaddr))
235 >= 0) {
236 /* Successful connect. */
237 restore_uid();
238 break;
239 }
240 debug("connect: %.100s", strerror(errno));
241 restore_uid();
242
243 /* Destroy the failed socket. */
244 shutdown(sock, SHUT_RDWR);
245 close(sock);
246 } else {
247 /* Not a valid numeric inet address. */
248 /* Map host name to an address. */
249 if (!hp)
250 hp = gethostbyname(host);
251 if (!hp)
252 fatal("Bad host name: %.100s", host);
253 if (!hp->h_addr_list[0])
254 fatal("Host does not have an IP address: %.100s", host);
255
256 /* Loop through addresses for this host, and try
257 each one in sequence until the connection
258 succeeds. */
259 for (i = 0; hp->h_addr_list[i]; i++) {
260 /* Set the address to connect to. */
261 hostaddr->sin_family = hp->h_addrtype;
262 memcpy(&hostaddr->sin_addr, hp->h_addr_list[i],
263 sizeof(hostaddr->sin_addr));
264
265 debug("Connecting to %.200s [%.100s] port %d.",
266 host, inet_ntoa(hostaddr->sin_addr), port);
267
268 /* Create a socket for connecting. */
269 sock = ssh_create_socket(original_real_uid,
270 !anonymous && geteuid() == 0 &&
271 port < IPPORT_RESERVED);
272
273 /* Connect to the host. We use the user's uid in the hope that
274 it will help with tcp_wrappers showing the remote uid as root. */
275 temporarily_use_uid(original_real_uid);
276 if (connect(sock, (struct sockaddr *) hostaddr,
277 sizeof(*hostaddr)) >= 0) {
278 /* Successful connection. */
279 restore_uid();
280 break;
281 }
282 debug("connect: %.100s", strerror(errno));
283 restore_uid();
284
285 /* Close the failed socket; there appear to be some problems when
286 reusing a socket for which connect() has already returned an error. */
287 shutdown(sock, SHUT_RDWR);
288 close(sock);
289 }
290 if (hp->h_addr_list[i])
291 break; /* Successful connection. */
292 }
293
294 /* Sleep a moment before retrying. */
295 sleep(1);
296 }
297 /* Return failure if we didn't get a successful connection. */
298 if (attempt >= connection_attempts)
299 return 0;
300
301 debug("Connection established.");
302
303 /* Set socket options. We would like the socket to disappear as
304 soon as it has been closed for whatever reason. */
305 /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
306 sizeof(on)); */
307 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
308 linger.l_onoff = 1;
309 linger.l_linger = 5;
310 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
311
312 /* Set the connection. */
313 packet_set_connection(sock, sock);
314
315 return 1;
316}
317
318/*
319 * Checks if the user has an authentication agent, and if so, tries to
320 * authenticate using the agent.
321 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000322int
323try_agent_authentication()
324{
Damien Miller95def091999-11-25 00:26:21 +1100325 int status, type;
326 char *comment;
327 AuthenticationConnection *auth;
328 unsigned char response[16];
329 unsigned int i;
330 BIGNUM *e, *n, *challenge;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000331
Damien Miller95def091999-11-25 00:26:21 +1100332 /* Get connection to the agent. */
333 auth = ssh_get_authentication_connection();
334 if (!auth)
335 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000336
Damien Miller95def091999-11-25 00:26:21 +1100337 e = BN_new();
338 n = BN_new();
339 challenge = BN_new();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000340
Damien Miller95def091999-11-25 00:26:21 +1100341 /* Loop through identities served by the agent. */
342 for (status = ssh_get_first_identity(auth, e, n, &comment);
343 status;
344 status = ssh_get_next_identity(auth, e, n, &comment)) {
345 int plen, clen;
346
347 /* Try this identity. */
348 debug("Trying RSA authentication via agent with '%.100s'", comment);
349 xfree(comment);
350
351 /* Tell the server that we are willing to authenticate using this key. */
352 packet_start(SSH_CMSG_AUTH_RSA);
353 packet_put_bignum(n);
354 packet_send();
355 packet_write_wait();
356
357 /* Wait for server's response. */
358 type = packet_read(&plen);
359
360 /* The server sends failure if it doesn\'t like our key or
361 does not support RSA authentication. */
362 if (type == SSH_SMSG_FAILURE) {
363 debug("Server refused our key.");
364 continue;
365 }
366 /* Otherwise it should have sent a challenge. */
367 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
368 packet_disconnect("Protocol error during RSA authentication: %d",
369 type);
370
371 packet_get_bignum(challenge, &clen);
372
373 packet_integrity_check(plen, clen, type);
374
375 debug("Received RSA challenge from server.");
376
377 /* Ask the agent to decrypt the challenge. */
378 if (!ssh_decrypt_challenge(auth, e, n, challenge,
379 session_id, 1, response)) {
380 /* The agent failed to authenticate this identifier although it
381 advertised it supports this. Just return a wrong value. */
382 log("Authentication agent failed to decrypt challenge.");
383 memset(response, 0, sizeof(response));
384 }
385 debug("Sending response to RSA challenge.");
386
387 /* Send the decrypted challenge back to the server. */
388 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
389 for (i = 0; i < 16; i++)
390 packet_put_char(response[i]);
391 packet_send();
392 packet_write_wait();
393
394 /* Wait for response from the server. */
395 type = packet_read(&plen);
396
397 /* The server returns success if it accepted the authentication. */
398 if (type == SSH_SMSG_SUCCESS) {
399 debug("RSA authentication accepted by server.");
400 BN_clear_free(e);
401 BN_clear_free(n);
402 BN_clear_free(challenge);
403 return 1;
404 }
405 /* Otherwise it should return failure. */
406 if (type != SSH_SMSG_FAILURE)
407 packet_disconnect("Protocol error waiting RSA auth response: %d",
408 type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000409 }
410
Damien Miller95def091999-11-25 00:26:21 +1100411 BN_clear_free(e);
412 BN_clear_free(n);
413 BN_clear_free(challenge);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000414
Damien Miller95def091999-11-25 00:26:21 +1100415 debug("RSA authentication using agent refused.");
416 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000417}
418
Damien Miller95def091999-11-25 00:26:21 +1100419/*
420 * Computes the proper response to a RSA challenge, and sends the response to
421 * the server.
422 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000423void
Damien Miller95def091999-11-25 00:26:21 +1100424respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000425{
Damien Miller95def091999-11-25 00:26:21 +1100426 unsigned char buf[32], response[16];
427 MD5_CTX md;
428 int i, len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000429
Damien Miller95def091999-11-25 00:26:21 +1100430 /* Decrypt the challenge using the private key. */
431 rsa_private_decrypt(challenge, challenge, prv);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000432
Damien Miller95def091999-11-25 00:26:21 +1100433 /* Compute the response. */
434 /* The response is MD5 of decrypted challenge plus session id. */
435 len = BN_num_bytes(challenge);
436 if (len <= 0 || len > sizeof(buf))
437 packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
438 len);
Damien Millerfd7c9111999-11-08 16:15:55 +1100439
Damien Miller95def091999-11-25 00:26:21 +1100440 memset(buf, 0, sizeof(buf));
441 BN_bn2bin(challenge, buf + sizeof(buf) - len);
442 MD5_Init(&md);
443 MD5_Update(&md, buf, 32);
444 MD5_Update(&md, session_id, 16);
445 MD5_Final(response, &md);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000446
Damien Miller95def091999-11-25 00:26:21 +1100447 debug("Sending response to host key RSA challenge.");
448
449 /* Send the response back to the server. */
450 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
451 for (i = 0; i < 16; i++)
452 packet_put_char(response[i]);
453 packet_send();
454 packet_write_wait();
455
456 memset(buf, 0, sizeof(buf));
457 memset(response, 0, sizeof(response));
458 memset(&md, 0, sizeof(md));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000459}
460
Damien Miller95def091999-11-25 00:26:21 +1100461/*
462 * Checks if the user has authentication file, and if so, tries to authenticate
463 * the user using it.
464 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000465int
Damien Miller95def091999-11-25 00:26:21 +1100466try_rsa_authentication(struct passwd * pw, const char *authfile)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000467{
Damien Miller95def091999-11-25 00:26:21 +1100468 extern Options options;
469 BIGNUM *challenge;
470 RSA *private_key;
471 RSA *public_key;
472 char *passphrase, *comment;
473 int type, i;
474 int plen, clen;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000475
Damien Miller95def091999-11-25 00:26:21 +1100476 /* Try to load identification for the authentication key. */
477 public_key = RSA_new();
478 if (!load_public_key(authfile, public_key, &comment)) {
479 RSA_free(public_key);
480 return 0; /* Could not load it. Fail. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000481 }
Damien Miller95def091999-11-25 00:26:21 +1100482 debug("Trying RSA authentication with key '%.100s'", comment);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000483
Damien Miller95def091999-11-25 00:26:21 +1100484 /* Tell the server that we are willing to authenticate using this key. */
485 packet_start(SSH_CMSG_AUTH_RSA);
486 packet_put_bignum(public_key->n);
487 packet_send();
488 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000489
Damien Miller95def091999-11-25 00:26:21 +1100490 /* We no longer need the public key. */
491 RSA_free(public_key);
492
493 /* Wait for server's response. */
494 type = packet_read(&plen);
495
496 /* The server responds with failure if it doesn\'t like our key or
497 doesn\'t support RSA authentication. */
498 if (type == SSH_SMSG_FAILURE) {
499 debug("Server refused our key.");
500 xfree(comment);
501 return 0; /* Server refuses to authenticate with
502 this key. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000503 }
Damien Miller95def091999-11-25 00:26:21 +1100504 /* Otherwise, the server should respond with a challenge. */
505 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
506 packet_disconnect("Protocol error during RSA authentication: %d", type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000507
Damien Miller95def091999-11-25 00:26:21 +1100508 /* Get the challenge from the packet. */
509 challenge = BN_new();
510 packet_get_bignum(challenge, &clen);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000511
Damien Miller95def091999-11-25 00:26:21 +1100512 packet_integrity_check(plen, clen, type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000513
Damien Miller95def091999-11-25 00:26:21 +1100514 debug("Received RSA challenge from server.");
515
516 private_key = RSA_new();
517 /* Load the private key. Try first with empty passphrase; if it
518 fails, ask for a passphrase. */
519 if (!load_private_key(authfile, "", private_key, NULL)) {
520 char buf[300];
521 snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
522 comment);
523 if (!options.batch_mode)
524 passphrase = read_passphrase(buf, 0);
525 else {
526 debug("Will not query passphrase for %.100s in batch mode.",
527 comment);
528 passphrase = xstrdup("");
529 }
530
531 /* Load the authentication file using the pasphrase. */
532 if (!load_private_key(authfile, passphrase, private_key, NULL)) {
533 memset(passphrase, 0, strlen(passphrase));
534 xfree(passphrase);
535 error("Bad passphrase.");
536
537 /* Send a dummy response packet to avoid protocol error. */
538 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
539 for (i = 0; i < 16; i++)
540 packet_put_char(0);
541 packet_send();
542 packet_write_wait();
543
544 /* Expect the server to reject it... */
545 packet_read_expect(&plen, SSH_SMSG_FAILURE);
546 xfree(comment);
547 return 0;
548 }
549 /* Destroy the passphrase. */
550 memset(passphrase, 0, strlen(passphrase));
551 xfree(passphrase);
552 }
553 /* We no longer need the comment. */
554 xfree(comment);
555
556 /* Compute and send a response to the challenge. */
557 respond_to_rsa_challenge(challenge, private_key);
558
559 /* Destroy the private key. */
560 RSA_free(private_key);
561
562 /* We no longer need the challenge. */
563 BN_clear_free(challenge);
564
565 /* Wait for response from the server. */
566 type = packet_read(&plen);
567 if (type == SSH_SMSG_SUCCESS) {
568 debug("RSA authentication accepted by server.");
569 return 1;
570 }
571 if (type != SSH_SMSG_FAILURE)
572 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
573 debug("RSA authentication refused.");
574 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000575}
576
Damien Miller95def091999-11-25 00:26:21 +1100577/*
578 * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
579 * authentication and RSA host authentication.
580 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000581int
Damien Miller95def091999-11-25 00:26:21 +1100582try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000583{
Damien Miller95def091999-11-25 00:26:21 +1100584 int type;
585 BIGNUM *challenge;
586 int plen, clen;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000587
Damien Miller95def091999-11-25 00:26:21 +1100588 debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000589
Damien Miller95def091999-11-25 00:26:21 +1100590 /* Tell the server that we are willing to authenticate using this key. */
591 packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
592 packet_put_string(local_user, strlen(local_user));
593 packet_put_int(BN_num_bits(host_key->n));
594 packet_put_bignum(host_key->e);
595 packet_put_bignum(host_key->n);
596 packet_send();
597 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000598
Damien Miller95def091999-11-25 00:26:21 +1100599 /* Wait for server's response. */
600 type = packet_read(&plen);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000601
Damien Miller95def091999-11-25 00:26:21 +1100602 /* The server responds with failure if it doesn't admit our
603 .rhosts authentication or doesn't know our host key. */
604 if (type == SSH_SMSG_FAILURE) {
605 debug("Server refused our rhosts authentication or host key.");
606 return 0;
607 }
608 /* Otherwise, the server should respond with a challenge. */
609 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
610 packet_disconnect("Protocol error during RSA authentication: %d", type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000611
Damien Miller95def091999-11-25 00:26:21 +1100612 /* Get the challenge from the packet. */
613 challenge = BN_new();
614 packet_get_bignum(challenge, &clen);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000615
Damien Miller95def091999-11-25 00:26:21 +1100616 packet_integrity_check(plen, clen, type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000617
Damien Miller95def091999-11-25 00:26:21 +1100618 debug("Received RSA challenge for host key from server.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000619
Damien Miller95def091999-11-25 00:26:21 +1100620 /* Compute a response to the challenge. */
621 respond_to_rsa_challenge(challenge, host_key);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000622
Damien Miller95def091999-11-25 00:26:21 +1100623 /* We no longer need the challenge. */
624 BN_clear_free(challenge);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000625
Damien Miller95def091999-11-25 00:26:21 +1100626 /* Wait for response from the server. */
627 type = packet_read(&plen);
628 if (type == SSH_SMSG_SUCCESS) {
629 debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
630 return 1;
631 }
632 if (type != SSH_SMSG_FAILURE)
633 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
634 debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
635 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000636}
637
638#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100639int
640try_kerberos_authentication()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000641{
Damien Miller95def091999-11-25 00:26:21 +1100642 KTEXT_ST auth; /* Kerberos data */
643 char *reply;
644 char inst[INST_SZ];
645 char *realm;
646 CREDENTIALS cred;
647 int r, type, plen;
648 Key_schedule schedule;
649 u_long checksum, cksum;
650 MSG_DAT msg_data;
651 struct sockaddr_in local, foreign;
652 struct stat st;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000653
Damien Miller95def091999-11-25 00:26:21 +1100654 /* Don't do anything if we don't have any tickets. */
655 if (stat(tkt_string(), &st) < 0)
656 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000657
Damien Miller95def091999-11-25 00:26:21 +1100658 strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
659
660 realm = (char *) krb_realmofhost(get_canonical_hostname());
661 if (!realm) {
662 debug("Kerberos V4: no realm for %s", get_canonical_hostname());
663 return 0;
664 }
665 /* This can really be anything. */
666 checksum = (u_long) getpid();
667
668 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
669 if (r != KSUCCESS) {
670 debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
671 return 0;
672 }
673 /* Get session key to decrypt the server's reply with. */
674 r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
675 if (r != KSUCCESS) {
676 debug("get_cred failed: %s", krb_err_txt[r]);
677 return 0;
678 }
679 des_key_sched((des_cblock *) cred.session, schedule);
680
681 /* Send authentication info to server. */
682 packet_start(SSH_CMSG_AUTH_KERBEROS);
683 packet_put_string((char *) auth.dat, auth.length);
684 packet_send();
685 packet_write_wait();
686
687 /* Zero the buffer. */
688 (void) memset(auth.dat, 0, MAX_KTXT_LEN);
689
690 r = sizeof(local);
691 memset(&local, 0, sizeof(local));
692 if (getsockname(packet_get_connection_in(),
693 (struct sockaddr *) & local, &r) < 0)
694 debug("getsockname failed: %s", strerror(errno));
695
696 r = sizeof(foreign);
697 memset(&foreign, 0, sizeof(foreign));
698 if (getpeername(packet_get_connection_in(),
699 (struct sockaddr *) & foreign, &r) < 0) {
700 debug("getpeername failed: %s", strerror(errno));
701 fatal_cleanup();
702 }
703 /* Get server reply. */
704 type = packet_read(&plen);
705 switch (type) {
706 case SSH_SMSG_FAILURE:
707 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
708 debug("Kerberos V4 authentication failed.");
709 return 0;
710 break;
711
712 case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
713 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
714 debug("Kerberos V4 authentication accepted.");
715
716 /* Get server's response. */
717 reply = packet_get_string((unsigned int *) &auth.length);
718 memcpy(auth.dat, reply, auth.length);
719 xfree(reply);
720
721 packet_integrity_check(plen, 4 + auth.length, type);
722
723 /* If his response isn't properly encrypted with the
724 session key, and the decrypted checksum fails to match,
725 he's bogus. Bail out. */
726 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
727 &foreign, &local, &msg_data);
728 if (r != KSUCCESS) {
729 debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
730 packet_disconnect("Kerberos V4 challenge failed!");
731 }
732 /* Fetch the (incremented) checksum that we supplied in the request. */
733 (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum));
734 cksum = ntohl(cksum);
735
736 /* If it matches, we're golden. */
737 if (cksum == checksum + 1) {
738 debug("Kerberos V4 challenge successful.");
739 return 1;
740 } else
741 packet_disconnect("Kerberos V4 challenge failed!");
742 break;
743
744 default:
745 packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
746 }
747 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000748}
Damien Miller95def091999-11-25 00:26:21 +1100749
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000750#endif /* KRB4 */
751
752#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100753int
754send_kerberos_tgt()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000755{
Damien Miller95def091999-11-25 00:26:21 +1100756 CREDENTIALS *creds;
757 char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
758 int r, type, plen;
759 unsigned char buffer[8192];
760 struct stat st;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000761
Damien Miller95def091999-11-25 00:26:21 +1100762 /* Don't do anything if we don't have any tickets. */
763 if (stat(tkt_string(), &st) < 0)
764 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000765
Damien Miller95def091999-11-25 00:26:21 +1100766 creds = xmalloc(sizeof(*creds));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000767
Damien Miller95def091999-11-25 00:26:21 +1100768 if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) {
769 debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]);
770 return 0;
771 }
772 if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
773 debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
774 return 0;
775 }
776 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
777 debug("Kerberos V4 ticket expired: %s", TKT_FILE);
778 return 0;
779 }
780 creds_to_radix(creds, buffer);
781 xfree(creds);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000782
Damien Miller95def091999-11-25 00:26:21 +1100783 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
784 packet_put_string((char *) buffer, strlen(buffer));
785 packet_send();
786 packet_write_wait();
787
788 type = packet_read(&plen);
789
790 if (type == SSH_SMSG_FAILURE)
791 debug("Kerberos TGT for realm %s rejected.", prealm);
792 else if (type != SSH_SMSG_SUCCESS)
793 packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
794
795 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000796}
797
Damien Miller95def091999-11-25 00:26:21 +1100798void
799send_afs_tokens(void)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000800{
Damien Miller95def091999-11-25 00:26:21 +1100801 CREDENTIALS creds;
802 struct ViceIoctl parms;
803 struct ClearToken ct;
804 int i, type, len, plen;
805 char buf[2048], *p, *server_cell;
806 unsigned char buffer[8192];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000807
Damien Miller95def091999-11-25 00:26:21 +1100808 /* Move over ktc_GetToken, here's something leaner. */
809 for (i = 0; i < 100; i++) { /* just in case */
810 parms.in = (char *) &i;
811 parms.in_size = sizeof(i);
812 parms.out = buf;
813 parms.out_size = sizeof(buf);
814 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
815 break;
816 p = buf;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000817
Damien Miller95def091999-11-25 00:26:21 +1100818 /* Get secret token. */
819 memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
820 if (creds.ticket_st.length > MAX_KTXT_LEN)
821 break;
822 p += sizeof(unsigned int);
823 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
824 p += creds.ticket_st.length;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000825
Damien Miller95def091999-11-25 00:26:21 +1100826 /* Get clear token. */
827 memcpy(&len, p, sizeof(len));
828 if (len != sizeof(struct ClearToken))
829 break;
830 p += sizeof(len);
831 memcpy(&ct, p, len);
832 p += len;
833 p += sizeof(len); /* primary flag */
834 server_cell = p;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000835
Damien Miller95def091999-11-25 00:26:21 +1100836 /* Flesh out our credentials. */
837 strlcpy(creds.service, "afs", sizeof creds.service);
838 creds.instance[0] = '\0';
839 strlcpy(creds.realm, server_cell, REALM_SZ);
840 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
841 creds.issue_date = ct.BeginTimestamp;
842 creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
843 creds.kvno = ct.AuthHandle;
844 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
845 creds.pinst[0] = '\0';
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000846
Damien Miller95def091999-11-25 00:26:21 +1100847 /* Encode token, ship it off. */
848 if (!creds_to_radix(&creds, buffer))
849 break;
850 packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
851 packet_put_string((char *) buffer, strlen(buffer));
852 packet_send();
853 packet_write_wait();
854
855 /* Roger, Roger. Clearance, Clarence. What's your vector,
856 Victor? */
857 type = packet_read(&plen);
858
859 if (type == SSH_SMSG_FAILURE)
860 debug("AFS token for cell %s rejected.", server_cell);
861 else if (type != SSH_SMSG_SUCCESS)
862 packet_disconnect("Protocol error on AFS token response: %d", type);
863 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000864}
Damien Miller95def091999-11-25 00:26:21 +1100865
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000866#endif /* AFS */
867
Damien Miller95def091999-11-25 00:26:21 +1100868/*
869 * Waits for the server identification string, and sends our own
870 * identification string.
871 */
872void
873ssh_exchange_identification()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000874{
Damien Miller95def091999-11-25 00:26:21 +1100875 char buf[256], remote_version[256]; /* must be same size! */
876 int remote_major, remote_minor, i;
877 int connection_in = packet_get_connection_in();
878 int connection_out = packet_get_connection_out();
879 extern Options options;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000880
Damien Miller95def091999-11-25 00:26:21 +1100881 /* Read other side\'s version identification. */
882 for (i = 0; i < sizeof(buf) - 1; i++) {
883 if (read(connection_in, &buf[i], 1) != 1)
884 fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
885 if (buf[i] == '\r') {
886 buf[i] = '\n';
887 buf[i + 1] = 0;
888 break;
889 }
890 if (buf[i] == '\n') {
891 buf[i + 1] = 0;
892 break;
893 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000894 }
Damien Miller95def091999-11-25 00:26:21 +1100895 buf[sizeof(buf) - 1] = 0;
896
897 /* Check that the versions match. In future this might accept
898 several versions and set appropriate flags to handle them. */
899 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
900 remote_version) != 3)
901 fatal("Bad remote protocol version identification: '%.100s'", buf);
902 debug("Remote protocol version %d.%d, remote software version %.100s",
903 remote_major, remote_minor, remote_version);
904
905 /* Check if the remote protocol version is too old. */
906 if (remote_major == 1 && remote_minor < 3)
907 fatal("Remote machine has too old SSH software version.");
908
909 /* We speak 1.3, too. */
910 if (remote_major == 1 && remote_minor == 3) {
911 enable_compat13();
912 if (options.forward_agent && strcmp(remote_version, SSH_VERSION) != 0) {
913 log("Agent forwarding disabled, remote version '%s' is not compatible.",
914 remote_version);
915 options.forward_agent = 0;
916 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000917 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000918#if 0
Damien Miller95def091999-11-25 00:26:21 +1100919 /* Removed for now, to permit compatibility with latter versions.
920 The server will reject our version and disconnect if it doesn't
921 support it. */
922 if (remote_major != PROTOCOL_MAJOR)
923 fatal("Protocol major versions differ: %d vs. %d",
924 PROTOCOL_MAJOR, remote_major);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000925#endif
926
Damien Miller95def091999-11-25 00:26:21 +1100927 /* Send our own protocol version identification. */
928 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
929 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
930 if (write(connection_out, buf, strlen(buf)) != strlen(buf))
931 fatal("write: %.100s", strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000932}
933
934int ssh_cipher_default = SSH_CIPHER_3DES;
935
Damien Miller95def091999-11-25 00:26:21 +1100936int
937read_yes_or_no(const char *prompt, int defval)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000938{
Damien Miller95def091999-11-25 00:26:21 +1100939 char buf[1024];
940 FILE *f;
941 int retval = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000942
Damien Miller95def091999-11-25 00:26:21 +1100943 if (isatty(0))
944 f = stdin;
945 else
946 f = fopen("/dev/tty", "rw");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000947
Damien Miller95def091999-11-25 00:26:21 +1100948 if (f == NULL)
949 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000950
Damien Miller95def091999-11-25 00:26:21 +1100951 fflush(stdout);
952
953 while (1) {
954 fprintf(stderr, "%s", prompt);
955 if (fgets(buf, sizeof(buf), f) == NULL) {
956 /* Print a newline (the prompt probably didn\'t have one). */
957 fprintf(stderr, "\n");
958 strlcpy(buf, "no", sizeof buf);
959 }
960 /* Remove newline from response. */
961 if (strchr(buf, '\n'))
962 *strchr(buf, '\n') = 0;
963
964 if (buf[0] == 0)
965 retval = defval;
966 if (strcmp(buf, "yes") == 0)
967 retval = 1;
968 if (strcmp(buf, "no") == 0)
969 retval = 0;
970
971 if (retval != -1) {
972 if (f != stdin)
973 fclose(f);
974 return retval;
975 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000976 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000977}
978
Damien Miller95def091999-11-25 00:26:21 +1100979/*
980 * Starts a dialog with the server, and authenticates the current user on the
981 * server. This does not need any extra privileges. The basic connection
982 * to the server must already have been established before this is called.
983 * User is the remote user; if it is NULL, the current local user name will
984 * be used. Anonymous indicates that no rhosts authentication will be used.
985 * If login fails, this function prints an error and never returns.
986 * This function does not require super-user privileges.
987 */
988void
989ssh_login(int host_key_valid,
990 RSA *own_host_key,
991 const char *orighost,
992 struct sockaddr_in *hostaddr,
993 uid_t original_real_uid)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000994{
Damien Miller95def091999-11-25 00:26:21 +1100995 extern Options options;
996 int i, type;
997 char *password;
998 struct passwd *pw;
999 BIGNUM *key;
1000 RSA *host_key, *file_key;
1001 RSA *public_key;
1002 int bits, rbits;
1003 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
1004 const char *server_user, *local_user;
1005 char *cp, *host, *ip = NULL;
1006 char hostline[1000], *hostp;
1007 unsigned char check_bytes[8];
1008 unsigned int supported_ciphers, supported_authentications, protocol_flags;
1009 HostStatus host_status;
1010 HostStatus ip_status;
1011 int host_ip_differ = 0;
1012 int local = (ntohl(hostaddr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
1013 int payload_len, clen, sum_len = 0;
1014 u_int32_t rand = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001015
Damien Miller95def091999-11-25 00:26:21 +11001016 if (options.check_host_ip)
1017 ip = xstrdup(inet_ntoa(hostaddr->sin_addr));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001018
Damien Miller95def091999-11-25 00:26:21 +11001019 /* Convert the user-supplied hostname into all lowercase. */
1020 host = xstrdup(orighost);
1021 for (cp = host; *cp; cp++)
1022 if (isupper(*cp))
1023 *cp = tolower(*cp);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001024
Damien Miller95def091999-11-25 00:26:21 +11001025 /* Exchange protocol version identification strings with the server. */
1026 ssh_exchange_identification();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001027
Damien Miller95def091999-11-25 00:26:21 +11001028 /* Put the connection into non-blocking mode. */
1029 packet_set_nonblocking();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001030
Damien Miller95def091999-11-25 00:26:21 +11001031 /* Get local user name. Use it as server user if no user name was given. */
1032 pw = getpwuid(original_real_uid);
1033 if (!pw)
1034 fatal("User id %d not found from user database.", original_real_uid);
1035 local_user = xstrdup(pw->pw_name);
1036 server_user = options.user ? options.user : local_user;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001037
Damien Miller95def091999-11-25 00:26:21 +11001038 debug("Waiting for server public key.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001039
Damien Miller95def091999-11-25 00:26:21 +11001040 /* Wait for a public key packet from the server. */
1041 packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001042
Damien Miller95def091999-11-25 00:26:21 +11001043 /* Get check bytes from the packet. */
1044 for (i = 0; i < 8; i++)
1045 check_bytes[i] = packet_get_char();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001046
Damien Miller95def091999-11-25 00:26:21 +11001047 /* Get the public key. */
1048 public_key = RSA_new();
1049 bits = packet_get_int();/* bits */
1050 public_key->e = BN_new();
1051 packet_get_bignum(public_key->e, &clen);
1052 sum_len += clen;
1053 public_key->n = BN_new();
1054 packet_get_bignum(public_key->n, &clen);
1055 sum_len += clen;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001056
Damien Miller95def091999-11-25 00:26:21 +11001057 rbits = BN_num_bits(public_key->n);
1058 if (bits != rbits) {
1059 log("Warning: Server lies about size of server public key: "
1060 "actual size is %d bits vs. announced %d.", rbits, bits);
1061 log("Warning: This may be due to an old implementation of ssh.");
1062 }
1063 /* Get the host key. */
1064 host_key = RSA_new();
1065 bits = packet_get_int();/* bits */
1066 host_key->e = BN_new();
1067 packet_get_bignum(host_key->e, &clen);
1068 sum_len += clen;
1069 host_key->n = BN_new();
1070 packet_get_bignum(host_key->n, &clen);
1071 sum_len += clen;
Damien Millerda217a01999-11-09 10:35:52 +11001072
Damien Miller95def091999-11-25 00:26:21 +11001073 rbits = BN_num_bits(host_key->n);
1074 if (bits != rbits) {
1075 log("Warning: Server lies about size of server host key: "
1076 "actual size is %d bits vs. announced %d.", rbits, bits);
1077 log("Warning: This may be due to an old implementation of ssh.");
1078 }
1079 /* Store the host key from the known host file in here so that we
1080 can compare it with the key for the IP address. */
1081 file_key = RSA_new();
1082 file_key->n = BN_new();
1083 file_key->e = BN_new();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001084
Damien Miller95def091999-11-25 00:26:21 +11001085 /* Get protocol flags. */
1086 protocol_flags = packet_get_int();
1087 packet_set_protocol_flags(protocol_flags);
Damien Millerda217a01999-11-09 10:35:52 +11001088
Damien Miller95def091999-11-25 00:26:21 +11001089 /* Get supported cipher types. */
1090 supported_ciphers = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001091
Damien Miller95def091999-11-25 00:26:21 +11001092 /* Get supported authentication types. */
1093 supported_authentications = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001094
Damien Miller95def091999-11-25 00:26:21 +11001095 debug("Received server public key (%d bits) and host key (%d bits).",
1096 BN_num_bits(public_key->n), BN_num_bits(host_key->n));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001097
Damien Miller95def091999-11-25 00:26:21 +11001098 packet_integrity_check(payload_len,
1099 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
1100 SSH_SMSG_PUBLIC_KEY);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001101
Damien Miller95def091999-11-25 00:26:21 +11001102 /* Compute the session id. */
1103 compute_session_id(session_id, check_bytes, host_key->n, public_key->n);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001104
Damien Miller95def091999-11-25 00:26:21 +11001105 /* Check if the host key is present in the user\'s list of known
1106 hosts or in the systemwide list. */
1107 host_status = check_host_in_hostfile(options.user_hostfile, host,
1108 host_key->e, host_key->n,
1109 file_key->e, file_key->n);
1110 if (host_status == HOST_NEW)
1111 host_status = check_host_in_hostfile(options.system_hostfile, host,
1112 host_key->e, host_key->n,
1113 file_key->e, file_key->n);
1114 /* Force accepting of the host key for localhost and 127.0.0.1.
1115 The problem is that if the home directory is NFS-mounted to
1116 multiple machines, localhost will refer to a different machine
1117 in each of them, and the user will get bogus HOST_CHANGED
1118 warnings. This essentially disables host authentication for
1119 localhost; however, this is probably not a real problem. */
1120 if (local) {
1121 debug("Forcing accepting of host key for localhost.");
1122 host_status = HOST_OK;
1123 }
1124 /* Also perform check for the ip address, skip the check if we are
1125 localhost or the hostname was an ip address to begin with */
1126 if (options.check_host_ip && !local && strcmp(host, ip)) {
1127 RSA *ip_key = RSA_new();
1128 ip_key->n = BN_new();
1129 ip_key->e = BN_new();
1130 ip_status = check_host_in_hostfile(options.user_hostfile, ip,
1131 host_key->e, host_key->n,
1132 ip_key->e, ip_key->n);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001133
Damien Miller95def091999-11-25 00:26:21 +11001134 if (ip_status == HOST_NEW)
1135 ip_status = check_host_in_hostfile(options.system_hostfile, ip,
1136 host_key->e, host_key->n,
1137 ip_key->e, ip_key->n);
1138 if (host_status == HOST_CHANGED &&
1139 (ip_status != HOST_CHANGED ||
1140 (BN_cmp(ip_key->e, file_key->e) || BN_cmp(ip_key->n, file_key->n))))
1141 host_ip_differ = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001142
Damien Miller95def091999-11-25 00:26:21 +11001143 RSA_free(ip_key);
1144 } else
1145 ip_status = host_status;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001146
Damien Miller95def091999-11-25 00:26:21 +11001147 RSA_free(file_key);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001148
Damien Miller95def091999-11-25 00:26:21 +11001149 switch (host_status) {
1150 case HOST_OK:
1151 /* The host is known and the key matches. */
1152 debug("Host '%.200s' is known and matches the host key.", host);
1153 if (options.check_host_ip) {
1154 if (ip_status == HOST_NEW) {
1155 if (!add_host_to_hostfile(options.user_hostfile, ip,
1156 host_key->e, host_key->n))
1157 log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).",
1158 ip, options.user_hostfile);
1159 else
1160 log("Warning: Permanently added host key for IP address '%.30s' to the list of known hosts.",
1161 ip);
1162 } else if (ip_status != HOST_OK)
1163 log("Warning: the host key for '%.200s' differs from the key for the IP address '%.30s'",
1164 host, ip);
1165 }
1166 break;
1167 case HOST_NEW:
1168 /* The host is new. */
1169 if (options.strict_host_key_checking == 1) {
1170 /* User has requested strict host key checking. We will not add the host key
1171 automatically. The only alternative left is to abort. */
1172 fatal("No host key is known for %.200s and you have requested strict checking.", host);
1173 } else if (options.strict_host_key_checking == 2) {
1174 /* The default */
1175 char prompt[1024];
1176 char *fp = fingerprint(host_key->e, host_key->n);
1177 snprintf(prompt, sizeof(prompt),
1178 "The authenticity of host '%.200s' can't be established.\n"
1179 "Key fingerprint is %d %s.\n"
1180 "Are you sure you want to continue connecting (yes/no)? ",
1181 host, BN_num_bits(host_key->n), fp);
1182 if (!read_yes_or_no(prompt, -1))
1183 fatal("Aborted by user!\n");
1184 }
1185 if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
1186 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
1187 hostp = hostline;
1188 } else
1189 hostp = host;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001190
Damien Miller95def091999-11-25 00:26:21 +11001191 /* If not in strict mode, add the key automatically to the local known_hosts file. */
1192 if (!add_host_to_hostfile(options.user_hostfile, hostp,
1193 host_key->e, host_key->n))
1194 log("Failed to add the host to the list of known hosts (%.500s).",
1195 options.user_hostfile);
1196 else
1197 log("Warning: Permanently added '%.200s' to the list of known hosts.",
1198 hostp);
1199 break;
1200 case HOST_CHANGED:
1201 if (options.check_host_ip && host_ip_differ) {
1202 char *msg;
1203 if (ip_status == HOST_NEW)
1204 msg = "is unknown";
1205 else if (ip_status == HOST_OK)
1206 msg = "is unchanged";
1207 else
1208 msg = "has a different value";
1209 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1210 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
1211 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1212 error("The host key for %s has changed,", host);
1213 error("and the key for the according IP address %s", ip);
1214 error("%s. This could either mean that", msg);
1215 error("DNS SPOOFING is happening or the IP address for the host");
1216 error("and its host key have changed at the same time");
1217 }
1218 /* The host key has changed. */
1219 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1220 error("@ WARNING: HOST IDENTIFICATION HAS CHANGED! @");
1221 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1222 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
1223 error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
1224 error("It is also possible that the host key has just been changed.");
1225 error("Please contact your system administrator.");
1226 error("Add correct host key in %.100s to get rid of this message.",
1227 options.user_hostfile);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001228
Damien Miller95def091999-11-25 00:26:21 +11001229 /* If strict host key checking is in use, the user will
1230 have to edit the key manually and we can only abort. */
1231 if (options.strict_host_key_checking)
1232 fatal("Host key for %.200s has changed and you have requested strict checking.", host);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001233
Damien Miller95def091999-11-25 00:26:21 +11001234 /* If strict host key checking has not been requested, allow the connection
1235 but without password authentication or agent forwarding. */
1236 if (options.password_authentication) {
1237 error("Password authentication is disabled to avoid trojan horses.");
1238 options.password_authentication = 0;
1239 }
1240 if (options.forward_agent) {
1241 error("Agent forwarding is disabled to avoid trojan horses.");
1242 options.forward_agent = 0;
1243 }
1244 /* XXX Should permit the user to change to use the new id.
1245 This could be done by converting the host key to an
1246 identifying sentence, tell that the host identifies
1247 itself by that sentence, and ask the user if he/she
1248 whishes to accept the authentication. */
1249 break;
1250 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001251
Damien Miller95def091999-11-25 00:26:21 +11001252 if (options.check_host_ip)
1253 xfree(ip);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001254
Damien Miller95def091999-11-25 00:26:21 +11001255 /* Generate a session key. */
1256 arc4random_stir();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001257
Damien Miller95def091999-11-25 00:26:21 +11001258 /* Generate an encryption key for the session. The key is a 256
1259 bit random number, interpreted as a 32-byte key, with the least
1260 significant 8 bits being the first byte of the key. */
1261 for (i = 0; i < 32; i++) {
1262 if (i % 4 == 0)
1263 rand = arc4random();
1264 session_key[i] = rand & 0xff;
1265 rand >>= 8;
1266 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001267
Damien Miller95def091999-11-25 00:26:21 +11001268 /* According to the protocol spec, the first byte of the session
1269 key is the highest byte of the integer. The session key is
1270 xored with the first 16 bytes of the session id. */
1271 key = BN_new();
1272 BN_set_word(key, 0);
1273 for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
1274 BN_lshift(key, key, 8);
1275 if (i < 16)
1276 BN_add_word(key, session_key[i] ^ session_id[i]);
1277 else
1278 BN_add_word(key, session_key[i]);
1279 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001280
Damien Miller95def091999-11-25 00:26:21 +11001281 /* Encrypt the integer using the public key and host key of the
1282 server (key with smaller modulus first). */
1283 if (BN_cmp(public_key->n, host_key->n) < 0) {
1284 /* Public key has smaller modulus. */
1285 if (BN_num_bits(host_key->n) <
1286 BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) {
1287 fatal("respond_to_rsa_challenge: host_key %d < public_key %d + "
1288 "SSH_KEY_BITS_RESERVED %d",
1289 BN_num_bits(host_key->n),
1290 BN_num_bits(public_key->n),
1291 SSH_KEY_BITS_RESERVED);
1292 }
1293 rsa_public_encrypt(key, key, public_key);
1294 rsa_public_encrypt(key, key, host_key);
1295 } else {
1296 /* Host key has smaller modulus (or they are equal). */
1297 if (BN_num_bits(public_key->n) <
1298 BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) {
1299 fatal("respond_to_rsa_challenge: public_key %d < host_key %d + "
1300 "SSH_KEY_BITS_RESERVED %d",
1301 BN_num_bits(public_key->n),
1302 BN_num_bits(host_key->n),
1303 SSH_KEY_BITS_RESERVED);
1304 }
1305 rsa_public_encrypt(key, key, host_key);
1306 rsa_public_encrypt(key, key, public_key);
1307 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001308
Damien Miller95def091999-11-25 00:26:21 +11001309 if (options.cipher == SSH_CIPHER_NOT_SET) {
1310 if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default))
1311 options.cipher = ssh_cipher_default;
1312 else {
1313 debug("Cipher %s not supported, using %.100s instead.",
1314 cipher_name(ssh_cipher_default),
1315 cipher_name(SSH_FALLBACK_CIPHER));
1316 options.cipher = SSH_FALLBACK_CIPHER;
1317 }
1318 }
1319 /* Check that the selected cipher is supported. */
1320 if (!(supported_ciphers & (1 << options.cipher)))
1321 fatal("Selected cipher type %.100s not supported by server.",
1322 cipher_name(options.cipher));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001323
Damien Miller95def091999-11-25 00:26:21 +11001324 debug("Encryption type: %.100s", cipher_name(options.cipher));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001325
Damien Miller95def091999-11-25 00:26:21 +11001326 /* Send the encrypted session key to the server. */
1327 packet_start(SSH_CMSG_SESSION_KEY);
1328 packet_put_char(options.cipher);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001329
Damien Miller95def091999-11-25 00:26:21 +11001330 /* Send the check bytes back to the server. */
1331 for (i = 0; i < 8; i++)
1332 packet_put_char(check_bytes[i]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001333
Damien Miller95def091999-11-25 00:26:21 +11001334 /* Send the encrypted encryption key. */
1335 packet_put_bignum(key);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001336
Damien Miller95def091999-11-25 00:26:21 +11001337 /* Send protocol flags. */
1338 packet_put_int(SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001339
Damien Miller95def091999-11-25 00:26:21 +11001340 /* Send the packet now. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001341 packet_send();
1342 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001343
Damien Miller95def091999-11-25 00:26:21 +11001344 /* Destroy the session key integer and the public keys since we no longer need them. */
1345 BN_clear_free(key);
1346 RSA_free(public_key);
1347 RSA_free(host_key);
1348
1349 debug("Sent encrypted session key.");
1350
1351 /* Set the encryption key. */
1352 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
1353
1354 /* We will no longer need the session key here. Destroy any extra copies. */
1355 memset(session_key, 0, sizeof(session_key));
1356
1357 /* Expect a success message from the server. Note that this
1358 message will be received in encrypted form. */
1359 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
1360
1361 debug("Received encrypted confirmation.");
1362
1363 /* Send the name of the user to log in as on the server. */
1364 packet_start(SSH_CMSG_USER);
1365 packet_put_string(server_user, strlen(server_user));
1366 packet_send();
1367 packet_write_wait();
1368
1369 /* The server should respond with success if no authentication is
1370 needed (the user has no password). Otherwise the server
1371 responds with failure. */
1372 type = packet_read(&payload_len);
1373
1374 /* check whether the connection was accepted without authentication. */
1375 if (type == SSH_SMSG_SUCCESS)
1376 return;
1377 if (type != SSH_SMSG_FAILURE)
1378 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
1379 type);
1380
1381#ifdef AFS
1382 /* Try Kerberos tgt passing if the server supports it. */
1383 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
1384 options.kerberos_tgt_passing) {
1385 if (options.cipher == SSH_CIPHER_NONE)
1386 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
1387 (void) send_kerberos_tgt();
1388 }
1389 /* Try AFS token passing if the server supports it. */
1390 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
1391 options.afs_token_passing && k_hasafs()) {
1392 if (options.cipher == SSH_CIPHER_NONE)
1393 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
1394 send_afs_tokens();
1395 }
1396#endif /* AFS */
1397
1398#ifdef KRB4
1399 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
1400 options.kerberos_authentication) {
1401 debug("Trying Kerberos authentication.");
1402 if (try_kerberos_authentication()) {
1403 /* The server should respond with success or failure. */
1404 type = packet_read(&payload_len);
1405 if (type == SSH_SMSG_SUCCESS)
1406 return;
1407 if (type != SSH_SMSG_FAILURE)
1408 packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
1409 }
1410 }
1411#endif /* KRB4 */
1412
1413 /* Use rhosts authentication if running in privileged socket and
1414 we do not wish to remain anonymous. */
1415 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
1416 options.rhosts_authentication) {
1417 debug("Trying rhosts authentication.");
1418 packet_start(SSH_CMSG_AUTH_RHOSTS);
1419 packet_put_string(local_user, strlen(local_user));
1420 packet_send();
1421 packet_write_wait();
1422
1423 /* The server should respond with success or failure. */
1424 type = packet_read(&payload_len);
1425 if (type == SSH_SMSG_SUCCESS)
1426 return;
1427 if (type != SSH_SMSG_FAILURE)
1428 packet_disconnect("Protocol error: got %d in response to rhosts auth",
1429 type);
1430 }
1431 /* Try .rhosts or /etc/hosts.equiv authentication with RSA host
1432 authentication. */
1433 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
1434 options.rhosts_rsa_authentication && host_key_valid) {
1435 if (try_rhosts_rsa_authentication(local_user, own_host_key))
1436 return;
1437 }
1438 /* Try RSA authentication if the server supports it. */
1439 if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
1440 options.rsa_authentication) {
1441 /* Try RSA authentication using the authentication agent.
1442 The agent is tried first because no passphrase is
1443 needed for it, whereas identity files may require
1444 passphrases. */
1445 if (try_agent_authentication())
1446 return;
1447
1448 /* Try RSA authentication for each identity. */
1449 for (i = 0; i < options.num_identity_files; i++)
1450 if (try_rsa_authentication(pw, options.identity_files[i]))
1451 return;
1452 }
1453 /* Try skey authentication if the server supports it. */
1454 if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
1455 options.skey_authentication && !options.batch_mode) {
1456 debug("Doing skey authentication.");
1457
1458 /* request a challenge */
1459 packet_start(SSH_CMSG_AUTH_TIS);
1460 packet_send();
1461 packet_write_wait();
1462
1463 type = packet_read(&payload_len);
1464 if (type != SSH_SMSG_FAILURE &&
1465 type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
1466 packet_disconnect("Protocol error: got %d in response "
1467 "to skey auth", type);
1468 }
1469 if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
1470 debug("No challenge for skey authentication.");
1471 } else {
1472 char *challenge, *response;
1473 challenge = packet_get_string(&payload_len);
1474 if (options.cipher == SSH_CIPHER_NONE)
1475 log("WARNING: Encryption is disabled! "
1476 "Reponse will be transmitted in clear text.");
1477 fprintf(stderr, "%s\n", challenge);
1478 fflush(stderr);
1479 for (i = 0; i < options.number_of_password_prompts; i++) {
1480 if (i != 0)
1481 error("Permission denied, please try again.");
1482 response = read_passphrase("Response: ", 0);
1483 packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
1484 packet_put_string(response, strlen(response));
1485 memset(response, 0, strlen(response));
1486 xfree(response);
1487 packet_send();
1488 packet_write_wait();
1489 type = packet_read(&payload_len);
1490 if (type == SSH_SMSG_SUCCESS)
1491 return;
1492 if (type != SSH_SMSG_FAILURE)
1493 packet_disconnect("Protocol error: got %d in response "
1494 "to skey auth", type);
1495 }
1496 }
1497 }
1498 /* Try password authentication if the server supports it. */
1499 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
1500 options.password_authentication && !options.batch_mode) {
1501 char prompt[80];
1502 snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ",
1503 server_user, host);
1504 debug("Doing password authentication.");
1505 if (options.cipher == SSH_CIPHER_NONE)
1506 log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
1507 for (i = 0; i < options.number_of_password_prompts; i++) {
1508 if (i != 0)
1509 error("Permission denied, please try again.");
1510 password = read_passphrase(prompt, 0);
1511 packet_start(SSH_CMSG_AUTH_PASSWORD);
1512 packet_put_string(password, strlen(password));
1513 memset(password, 0, strlen(password));
1514 xfree(password);
1515 packet_send();
1516 packet_write_wait();
1517
1518 type = packet_read(&payload_len);
1519 if (type == SSH_SMSG_SUCCESS)
1520 return;
1521 if (type != SSH_SMSG_FAILURE)
1522 packet_disconnect("Protocol error: got %d in response to passwd auth", type);
1523 }
1524 }
1525 /* All authentication methods have failed. Exit with an error message. */
1526 fatal("Permission denied.");
1527 /* NOTREACHED */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001528}