diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 249 |
1 files changed, 168 insertions, 81 deletions
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "includes.h" | 13 | #include "includes.h" |
14 | RCSID("$Id: sshd.c,v 1.49 1999/12/30 04:08:44 damien Exp $"); | 14 | RCSID("$Id: sshd.c,v 1.50 2000/01/14 04:45:52 damien Exp $"); |
15 | 15 | ||
16 | #include "xmalloc.h" | 16 | #include "xmalloc.h" |
17 | #include "rsa.h" | 17 | #include "rsa.h" |
@@ -45,6 +45,12 @@ ServerOptions options; | |||
45 | /* Name of the server configuration file. */ | 45 | /* Name of the server configuration file. */ |
46 | char *config_file_name = SERVER_CONFIG_FILE; | 46 | char *config_file_name = SERVER_CONFIG_FILE; |
47 | 47 | ||
48 | /* | ||
49 | * Flag indicating whether IPv4 or IPv6. This can be set on the command line. | ||
50 | * Default value is AF_UNSPEC means both IPv4 and IPv6. | ||
51 | */ | ||
52 | int IPv4or6 = AF_UNSPEC; | ||
53 | |||
48 | /* | 54 | /* |
49 | * Debug mode flag. This can be set on the command line. If debug | 55 | * Debug mode flag. This can be set on the command line. If debug |
50 | * mode is enabled, extra debugging output will be sent to the system | 56 | * mode is enabled, extra debugging output will be sent to the system |
@@ -66,10 +72,12 @@ char *av0; | |||
66 | char **saved_argv; | 72 | char **saved_argv; |
67 | 73 | ||
68 | /* | 74 | /* |
69 | * This is set to the socket that the server is listening; this is used in | 75 | * The sockets that the server is listening; this is used in the SIGHUP |
70 | * the SIGHUP signal handler. | 76 | * signal handler. |
71 | */ | 77 | */ |
72 | int listen_sock; | 78 | #define MAX_LISTEN_SOCKS 16 |
79 | int listen_socks[MAX_LISTEN_SOCKS]; | ||
80 | int num_listen_socks = 0; | ||
73 | 81 | ||
74 | /* | 82 | /* |
75 | * the client's version string, passed by sshd2 in compat mode. if != NULL, | 83 | * the client's version string, passed by sshd2 in compat mode. if != NULL, |
@@ -136,6 +144,18 @@ void do_child(const char *command, struct passwd * pw, const char *term, | |||
136 | const char *auth_data, const char *ttyname); | 144 | const char *auth_data, const char *ttyname); |
137 | 145 | ||
138 | /* | 146 | /* |
147 | * Close all listening sockets | ||
148 | */ | ||
149 | void | ||
150 | close_listen_socks(void) | ||
151 | { | ||
152 | int i; | ||
153 | for (i = 0; i < num_listen_socks; i++) | ||
154 | close(listen_socks[i]); | ||
155 | num_listen_socks = -1; | ||
156 | } | ||
157 | |||
158 | /* | ||
139 | * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; | 159 | * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; |
140 | * the effect is to reread the configuration file (and to regenerate | 160 | * the effect is to reread the configuration file (and to regenerate |
141 | * the server key). | 161 | * the server key). |
@@ -155,7 +175,7 @@ void | |||
155 | sighup_restart() | 175 | sighup_restart() |
156 | { | 176 | { |
157 | log("Received SIGHUP; restarting."); | 177 | log("Received SIGHUP; restarting."); |
158 | close(listen_sock); | 178 | close_listen_socks(); |
159 | execv(saved_argv[0], saved_argv); | 179 | execv(saved_argv[0], saved_argv); |
160 | log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno)); | 180 | log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno)); |
161 | exit(1); | 181 | exit(1); |
@@ -170,7 +190,7 @@ void | |||
170 | sigterm_handler(int sig) | 190 | sigterm_handler(int sig) |
171 | { | 191 | { |
172 | log("Received signal %d; terminating.", sig); | 192 | log("Received signal %d; terminating.", sig); |
173 | close(listen_sock); | 193 | close_listen_socks(); |
174 | exit(255); | 194 | exit(255); |
175 | } | 195 | } |
176 | 196 | ||
@@ -277,11 +297,12 @@ main(int ac, char **av) | |||
277 | { | 297 | { |
278 | extern char *optarg; | 298 | extern char *optarg; |
279 | extern int optind; | 299 | extern int optind; |
280 | int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1; | 300 | int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, pid, on = 1; |
301 | socklen_t fromlen; | ||
281 | int remote_major, remote_minor; | 302 | int remote_major, remote_minor; |
282 | int silentrsa = 0; | 303 | int silentrsa = 0; |
283 | struct pollfd fds; | 304 | fd_set *fdset; |
284 | struct sockaddr_in sin; | 305 | struct sockaddr_storage from; |
285 | char buf[100]; /* Must not be larger than remote_version. */ | 306 | char buf[100]; /* Must not be larger than remote_version. */ |
286 | char remote_version[100]; /* Must be at least as big as buf. */ | 307 | char remote_version[100]; /* Must be at least as big as buf. */ |
287 | const char *remote_ip; | 308 | const char *remote_ip; |
@@ -289,6 +310,9 @@ main(int ac, char **av) | |||
289 | char *comment; | 310 | char *comment; |
290 | FILE *f; | 311 | FILE *f; |
291 | struct linger linger; | 312 | struct linger linger; |
313 | struct addrinfo *ai; | ||
314 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | ||
315 | int listen_sock, maxfd; | ||
292 | 316 | ||
293 | /* Save argv[0]. */ | 317 | /* Save argv[0]. */ |
294 | saved_argv = av; | 318 | saved_argv = av; |
@@ -301,8 +325,14 @@ main(int ac, char **av) | |||
301 | initialize_server_options(&options); | 325 | initialize_server_options(&options); |
302 | 326 | ||
303 | /* Parse command-line arguments. */ | 327 | /* Parse command-line arguments. */ |
304 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ")) != EOF) { | 328 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) { |
305 | switch (opt) { | 329 | switch (opt) { |
330 | case '4': | ||
331 | IPv4or6 = AF_INET; | ||
332 | break; | ||
333 | case '6': | ||
334 | IPv4or6 = AF_INET6; | ||
335 | break; | ||
306 | case 'f': | 336 | case 'f': |
307 | config_file_name = optarg; | 337 | config_file_name = optarg; |
308 | break; | 338 | break; |
@@ -323,7 +353,10 @@ main(int ac, char **av) | |||
323 | options.server_key_bits = atoi(optarg); | 353 | options.server_key_bits = atoi(optarg); |
324 | break; | 354 | break; |
325 | case 'p': | 355 | case 'p': |
326 | options.port = atoi(optarg); | 356 | options.ports_from_cmdline = 1; |
357 | if (options.num_ports >= MAX_PORTS) | ||
358 | fatal("too many ports.\n"); | ||
359 | options.ports[options.num_ports++] = atoi(optarg); | ||
327 | break; | 360 | break; |
328 | case 'g': | 361 | case 'g': |
329 | options.login_grace_time = atoi(optarg); | 362 | options.login_grace_time = atoi(optarg); |
@@ -356,11 +389,22 @@ main(int ac, char **av) | |||
356 | fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n"); | 389 | fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n"); |
357 | fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); | 390 | fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); |
358 | fprintf(stderr, " -h file File from which to read host key (default: %s)\n", | 391 | fprintf(stderr, " -h file File from which to read host key (default: %s)\n", |
359 | HOST_KEY_FILE); | 392 | HOST_KEY_FILE); |
393 | fprintf(stderr, " -4 Use IPv4 only\n"); | ||
394 | fprintf(stderr, " -6 Use IPv6 only\n"); | ||
360 | exit(1); | 395 | exit(1); |
361 | } | 396 | } |
362 | } | 397 | } |
363 | 398 | ||
399 | /* | ||
400 | * Force logging to stderr until we have loaded the private host | ||
401 | * key (unless started from inetd) | ||
402 | */ | ||
403 | log_init(av0, | ||
404 | options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, | ||
405 | options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility, | ||
406 | !inetd_flag); | ||
407 | |||
364 | /* check if RSA support exists */ | 408 | /* check if RSA support exists */ |
365 | if (rsa_alive() == 0) { | 409 | if (rsa_alive() == 0) { |
366 | if (silentrsa == 0) | 410 | if (silentrsa == 0) |
@@ -380,18 +424,11 @@ main(int ac, char **av) | |||
380 | fprintf(stderr, "Bad server key size.\n"); | 424 | fprintf(stderr, "Bad server key size.\n"); |
381 | exit(1); | 425 | exit(1); |
382 | } | 426 | } |
383 | if (options.port < 1 || options.port > 65535) { | ||
384 | fprintf(stderr, "Bad port number.\n"); | ||
385 | exit(1); | ||
386 | } | ||
387 | /* Check that there are no remaining arguments. */ | 427 | /* Check that there are no remaining arguments. */ |
388 | if (optind < ac) { | 428 | if (optind < ac) { |
389 | fprintf(stderr, "Extra argument %s.\n", av[optind]); | 429 | fprintf(stderr, "Extra argument %s.\n", av[optind]); |
390 | exit(1); | 430 | exit(1); |
391 | } | 431 | } |
392 | /* Force logging to stderr while loading the private host key | ||
393 | unless started from inetd */ | ||
394 | log_init(av0, options.log_level, options.log_facility, !inetd_flag); | ||
395 | 432 | ||
396 | debug("sshd version %.100s", SSH_VERSION); | 433 | debug("sshd version %.100s", SSH_VERSION); |
397 | 434 | ||
@@ -480,32 +517,66 @@ main(int ac, char **av) | |||
480 | arc4random_stir(); | 517 | arc4random_stir(); |
481 | log("RSA key generation complete."); | 518 | log("RSA key generation complete."); |
482 | } else { | 519 | } else { |
483 | /* Create socket for listening. */ | 520 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { |
484 | listen_sock = socket(AF_INET, SOCK_STREAM, 0); | 521 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) |
485 | if (listen_sock < 0) | 522 | continue; |
486 | fatal("socket: %.100s", strerror(errno)); | 523 | if (num_listen_socks >= MAX_LISTEN_SOCKS) |
487 | 524 | fatal("Too many listen sockets. " | |
488 | /* Set socket options. We try to make the port reusable | 525 | "Enlarge MAX_LISTEN_SOCKS"); |
489 | and have it close as fast as possible without waiting | 526 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, |
490 | in unnecessary wait states on close. */ | 527 | ntop, sizeof(ntop), strport, sizeof(strport), |
491 | setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, | 528 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
492 | sizeof(on)); | 529 | error("getnameinfo failed"); |
493 | linger.l_onoff = 1; | 530 | continue; |
494 | linger.l_linger = 5; | 531 | } |
495 | setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *) &linger, | 532 | /* Create socket for listening. */ |
496 | sizeof(linger)); | 533 | listen_sock = socket(ai->ai_family, SOCK_STREAM, 0); |
497 | 534 | if (listen_sock < 0) { | |
498 | memset(&sin, 0, sizeof(sin)); | 535 | /* kernel may not support ipv6 */ |
499 | sin.sin_family = AF_INET; | 536 | verbose("socket: %.100s", strerror(errno)); |
500 | sin.sin_addr = options.listen_addr; | 537 | continue; |
501 | sin.sin_port = htons(options.port); | 538 | } |
502 | 539 | if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { | |
503 | if (bind(listen_sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) { | 540 | error("listen_sock O_NONBLOCK: %s", strerror(errno)); |
504 | error("bind: %.100s", strerror(errno)); | 541 | close(listen_sock); |
505 | shutdown(listen_sock, SHUT_RDWR); | 542 | continue; |
506 | close(listen_sock); | 543 | } |
507 | fatal("Bind to port %d failed.", options.port); | 544 | /* |
545 | * Set socket options. We try to make the port | ||
546 | * reusable and have it close as fast as possible | ||
547 | * without waiting in unnecessary wait states on | ||
548 | * close. | ||
549 | */ | ||
550 | setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, | ||
551 | (void *) &on, sizeof(on)); | ||
552 | linger.l_onoff = 1; | ||
553 | linger.l_linger = 5; | ||
554 | setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, | ||
555 | (void *) &linger, sizeof(linger)); | ||
556 | |||
557 | debug("Bind to port %s on %s.", strport, ntop); | ||
558 | |||
559 | /* Bind the socket to the desired port. */ | ||
560 | if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { | ||
561 | error("Bind to port %s on %s failed: %.200s.", | ||
562 | strport, ntop, strerror(errno)); | ||
563 | close(listen_sock); | ||
564 | continue; | ||
565 | } | ||
566 | listen_socks[num_listen_socks] = listen_sock; | ||
567 | num_listen_socks++; | ||
568 | |||
569 | /* Start listening on the port. */ | ||
570 | log("Server listening on %s port %s.", ntop, strport); | ||
571 | if (listen(listen_sock, 5) < 0) | ||
572 | fatal("listen: %.100s", strerror(errno)); | ||
573 | |||
508 | } | 574 | } |
575 | freeaddrinfo(options.listen_addrs); | ||
576 | |||
577 | if (!num_listen_socks) | ||
578 | fatal("Cannot bind any address."); | ||
579 | |||
509 | if (!debug_flag) { | 580 | if (!debug_flag) { |
510 | /* | 581 | /* |
511 | * Record our pid in /etc/sshd_pid to make it easier | 582 | * Record our pid in /etc/sshd_pid to make it easier |
@@ -521,10 +592,6 @@ main(int ac, char **av) | |||
521 | } | 592 | } |
522 | } | 593 | } |
523 | 594 | ||
524 | log("Server listening on port %d.", options.port); | ||
525 | if (listen(listen_sock, 5) < 0) | ||
526 | fatal("listen: %.100s", strerror(errno)); | ||
527 | |||
528 | public_key = RSA_new(); | 595 | public_key = RSA_new(); |
529 | sensitive_data.private_key = RSA_new(); | 596 | sensitive_data.private_key = RSA_new(); |
530 | 597 | ||
@@ -546,6 +613,14 @@ main(int ac, char **av) | |||
546 | /* Arrange SIGCHLD to be caught. */ | 613 | /* Arrange SIGCHLD to be caught. */ |
547 | signal(SIGCHLD, main_sigchld_handler); | 614 | signal(SIGCHLD, main_sigchld_handler); |
548 | 615 | ||
616 | /* setup fd set for listen */ | ||
617 | maxfd = 0; | ||
618 | for (i = 0; i < num_listen_socks; i++) | ||
619 | if (listen_socks[i] > maxfd) | ||
620 | maxfd = listen_socks[i]; | ||
621 | fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask); | ||
622 | fdset = (fd_set *)xmalloc(fdsetsz); | ||
623 | |||
549 | /* | 624 | /* |
550 | * Stay listening for connections until the system crashes or | 625 | * Stay listening for connections until the system crashes or |
551 | * the daemon is killed with a signal. | 626 | * the daemon is killed with a signal. |
@@ -553,26 +628,28 @@ main(int ac, char **av) | |||
553 | for (;;) { | 628 | for (;;) { |
554 | if (received_sighup) | 629 | if (received_sighup) |
555 | sighup_restart(); | 630 | sighup_restart(); |
556 | /* Wait in poll until there is a connection. */ | 631 | /* Wait in select until there is a connection. */ |
557 | memset(&fds, 0, sizeof(fds)); | 632 | memset(fdset, 0, fdsetsz); |
558 | fds.fd = listen_sock; | 633 | for (i = 0; i < num_listen_socks; i++) |
559 | fds.events = POLLIN; | 634 | FD_SET(listen_socks[i], fdset); |
560 | if (poll(&fds, 1, -1) == -1) { | 635 | if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) { |
561 | if (errno == EINTR) | 636 | if (errno != EINTR) |
562 | continue; | 637 | error("select: %.100s", strerror(errno)); |
563 | fatal("poll: %.100s", strerror(errno)); | ||
564 | /*NOTREACHED*/ | ||
565 | } | ||
566 | if (fds.revents == 0) | ||
567 | continue; | 638 | continue; |
568 | aux = sizeof(sin); | 639 | } |
569 | newsock = accept(listen_sock, (struct sockaddr *) & sin, &aux); | 640 | for (i = 0; i < num_listen_socks; i++) { |
570 | if (received_sighup) | 641 | if (!FD_ISSET(listen_socks[i], fdset)) |
571 | sighup_restart(); | ||
572 | if (newsock < 0) { | ||
573 | if (errno == EINTR) | ||
574 | continue; | 642 | continue; |
575 | error("accept: %.100s", strerror(errno)); | 643 | fromlen = sizeof(from); |
644 | newsock = accept(listen_socks[i], (struct sockaddr *)&from, | ||
645 | &fromlen); | ||
646 | if (newsock < 0) { | ||
647 | if (errno != EINTR && errno != EWOULDBLOCK) | ||
648 | error("accept: %.100s", strerror(errno)); | ||
649 | continue; | ||
650 | } | ||
651 | if (fcntl(newsock, F_SETFL, 0) < 0) { | ||
652 | error("newsock del O_NONBLOCK: %s", strerror(errno)); | ||
576 | continue; | 653 | continue; |
577 | } | 654 | } |
578 | /* | 655 | /* |
@@ -586,7 +663,7 @@ main(int ac, char **av) | |||
586 | * connection without forking. | 663 | * connection without forking. |
587 | */ | 664 | */ |
588 | debug("Server will not fork when running in debugging mode."); | 665 | debug("Server will not fork when running in debugging mode."); |
589 | close(listen_sock); | 666 | close_listen_socks(); |
590 | sock_in = newsock; | 667 | sock_in = newsock; |
591 | sock_out = newsock; | 668 | sock_out = newsock; |
592 | pid = getpid(); | 669 | pid = getpid(); |
@@ -603,7 +680,7 @@ main(int ac, char **av) | |||
603 | * accepted socket. Reinitialize logging (since our pid has | 680 | * accepted socket. Reinitialize logging (since our pid has |
604 | * changed). We break out of the loop to handle the connection. | 681 | * changed). We break out of the loop to handle the connection. |
605 | */ | 682 | */ |
606 | close(listen_sock); | 683 | close_listen_socks(); |
607 | sock_in = newsock; | 684 | sock_in = newsock; |
608 | sock_out = newsock; | 685 | sock_out = newsock; |
609 | log_init(av0, options.log_level, options.log_facility, log_stderr); | 686 | log_init(av0, options.log_level, options.log_facility, log_stderr); |
@@ -624,6 +701,10 @@ main(int ac, char **av) | |||
624 | 701 | ||
625 | /* Close the new socket (the child is now taking care of it). */ | 702 | /* Close the new socket (the child is now taking care of it). */ |
626 | close(newsock); | 703 | close(newsock); |
704 | } /* for (i = 0; i < num_listen_socks; i++) */ | ||
705 | /* child process check (or debug mode) */ | ||
706 | if (num_listen_socks < 0) | ||
707 | break; | ||
627 | } | 708 | } |
628 | } | 709 | } |
629 | 710 | ||
@@ -662,6 +743,7 @@ main(int ac, char **av) | |||
662 | 743 | ||
663 | /* Check whether logins are denied from this host. */ | 744 | /* Check whether logins are denied from this host. */ |
664 | #ifdef LIBWRAP | 745 | #ifdef LIBWRAP |
746 | /* XXX LIBWRAP noes not know about IPv6 */ | ||
665 | { | 747 | { |
666 | struct request_info req; | 748 | struct request_info req; |
667 | 749 | ||
@@ -673,12 +755,11 @@ main(int ac, char **av) | |||
673 | close(sock_out); | 755 | close(sock_out); |
674 | refuse(&req); | 756 | refuse(&req); |
675 | } | 757 | } |
676 | verbose("Connection from %.500s port %d", eval_client(&req), remote_port); | 758 | /*XXX IPv6 verbose("Connection from %.500s port %d", eval_client(&req), remote_port); */ |
677 | } | 759 | } |
678 | #else | 760 | #endif /* LIBWRAP */ |
679 | /* Log the connection. */ | 761 | /* Log the connection. */ |
680 | verbose("Connection from %.500s port %d", remote_ip, remote_port); | 762 | verbose("Connection from %.500s port %d", remote_ip, remote_port); |
681 | #endif /* LIBWRAP */ | ||
682 | 763 | ||
683 | /* | 764 | /* |
684 | * We don\'t want to listen forever unless the other side | 765 | * We don\'t want to listen forever unless the other side |
@@ -700,12 +781,12 @@ main(int ac, char **av) | |||
700 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", | 781 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", |
701 | PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); | 782 | PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); |
702 | if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf)) | 783 | if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf)) |
703 | fatal("Could not write ident string to %s.", get_remote_ipaddr()); | 784 | fatal("Could not write ident string to %s.", remote_ip); |
704 | 785 | ||
705 | /* Read other side\'s version identification. */ | 786 | /* Read other side\'s version identification. */ |
706 | for (i = 0; i < sizeof(buf) - 1; i++) { | 787 | for (i = 0; i < sizeof(buf) - 1; i++) { |
707 | if (read(sock_in, &buf[i], 1) != 1) | 788 | if (read(sock_in, &buf[i], 1) != 1) |
708 | fatal("Did not receive ident string from %s.", get_remote_ipaddr()); | 789 | fatal("Did not receive ident string from %s.", remote_ip); |
709 | if (buf[i] == '\r') { | 790 | if (buf[i] == '\r') { |
710 | buf[i] = '\n'; | 791 | buf[i] = '\n'; |
711 | buf[i + 1] = 0; | 792 | buf[i + 1] = 0; |
@@ -732,7 +813,7 @@ main(int ac, char **av) | |||
732 | close(sock_in); | 813 | close(sock_in); |
733 | close(sock_out); | 814 | close(sock_out); |
734 | fatal("Bad protocol version identification '%.100s' from %s", | 815 | fatal("Bad protocol version identification '%.100s' from %s", |
735 | buf, get_remote_ipaddr()); | 816 | buf, remote_ip); |
736 | } | 817 | } |
737 | debug("Client protocol version %d.%d; client software version %.100s", | 818 | debug("Client protocol version %d.%d; client software version %.100s", |
738 | remote_major, remote_minor, remote_version); | 819 | remote_major, remote_minor, remote_version); |
@@ -743,8 +824,7 @@ main(int ac, char **av) | |||
743 | close(sock_in); | 824 | close(sock_in); |
744 | close(sock_out); | 825 | close(sock_out); |
745 | fatal("Protocol major versions differ for %s: %d vs. %d", | 826 | fatal("Protocol major versions differ for %s: %d vs. %d", |
746 | get_remote_ipaddr(), | 827 | remote_ip, PROTOCOL_MAJOR, remote_major); |
747 | PROTOCOL_MAJOR, remote_major); | ||
748 | } | 828 | } |
749 | /* Check that the client has sufficiently high software version. */ | 829 | /* Check that the client has sufficiently high software version. */ |
750 | if (remote_major == 1 && remote_minor < 3) | 830 | if (remote_major == 1 && remote_minor < 3) |
@@ -769,6 +849,14 @@ main(int ac, char **av) | |||
769 | options.rhosts_authentication = 0; | 849 | options.rhosts_authentication = 0; |
770 | options.rhosts_rsa_authentication = 0; | 850 | options.rhosts_rsa_authentication = 0; |
771 | } | 851 | } |
852 | #ifdef KRB4 | ||
853 | if (!packet_connection_is_ipv4() && | ||
854 | options.kerberos_authentication) { | ||
855 | debug("Kerberos Authentication disabled, only available for IPv4."); | ||
856 | options.kerberos_authentication = 0; | ||
857 | } | ||
858 | #endif /* KRB4 */ | ||
859 | |||
772 | packet_set_nonblocking(); | 860 | packet_set_nonblocking(); |
773 | 861 | ||
774 | /* Handle the connection. */ | 862 | /* Handle the connection. */ |
@@ -1935,8 +2023,8 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
1935 | char line[256]; | 2023 | char line[256]; |
1936 | struct stat st; | 2024 | struct stat st; |
1937 | int quiet_login; | 2025 | int quiet_login; |
1938 | struct sockaddr_in from; | 2026 | struct sockaddr_storage from; |
1939 | int fromlen; | 2027 | socklen_t fromlen; |
1940 | struct pty_cleanup_context cleanup_context; | 2028 | struct pty_cleanup_context cleanup_context; |
1941 | 2029 | ||
1942 | /* Get remote host name. */ | 2030 | /* Get remote host name. */ |
@@ -1997,7 +2085,7 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd, | |||
1997 | } | 2085 | } |
1998 | /* Record that there was a login on that terminal. */ | 2086 | /* Record that there was a login on that terminal. */ |
1999 | record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname, | 2087 | record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname, |
2000 | &from); | 2088 | (struct sockaddr *)&from); |
2001 | 2089 | ||
2002 | /* Check if .hushlogin exists. */ | 2090 | /* Check if .hushlogin exists. */ |
2003 | snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); | 2091 | snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); |
@@ -2318,7 +2406,7 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
2318 | } | 2406 | } |
2319 | 2407 | ||
2320 | snprintf(buf, sizeof buf, "%.50s %d %d", | 2408 | snprintf(buf, sizeof buf, "%.50s %d %d", |
2321 | get_remote_ipaddr(), get_remote_port(), options.port); | 2409 | get_remote_ipaddr(), get_remote_port(), get_local_port()); |
2322 | child_set_env(&env, &envsize, "SSH_CLIENT", buf); | 2410 | child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
2323 | 2411 | ||
2324 | if (ttyname) | 2412 | if (ttyname) |
@@ -2385,7 +2473,6 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
2385 | * descriptors left by system functions. They will be closed later. | 2473 | * descriptors left by system functions. They will be closed later. |
2386 | */ | 2474 | */ |
2387 | endpwent(); | 2475 | endpwent(); |
2388 | endhostent(); | ||
2389 | 2476 | ||
2390 | /* | 2477 | /* |
2391 | * Close any extra open file descriptors so that we don\'t have them | 2478 | * Close any extra open file descriptors so that we don\'t have them |