summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c177
1 files changed, 115 insertions, 62 deletions
diff --git a/sshd.c b/sshd.c
index 248ad2976..df6c9d24e 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.367 2009/05/28 16:50:16 andreas Exp $ */ 1/* $OpenBSD: sshd.c,v 1.374 2010/03/07 11:57:13 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -209,6 +209,7 @@ struct {
209 Key *server_key; /* ephemeral server key */ 209 Key *server_key; /* ephemeral server key */
210 Key *ssh1_host_key; /* ssh1 host key */ 210 Key *ssh1_host_key; /* ssh1 host key */
211 Key **host_keys; /* all private host keys */ 211 Key **host_keys; /* all private host keys */
212 Key **host_certificates; /* all public host certificates */
212 int have_ssh1_key; 213 int have_ssh1_key;
213 int have_ssh2_key; 214 int have_ssh2_key;
214 u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; 215 u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH];
@@ -254,11 +255,6 @@ Buffer loginmsg;
254/* Unprivileged user */ 255/* Unprivileged user */
255struct passwd *privsep_pw = NULL; 256struct passwd *privsep_pw = NULL;
256 257
257#ifdef OOM_ADJUST
258/* Linux out-of-memory killer adjustment */
259static char oom_adj_save[8];
260#endif
261
262/* Prototypes for various functions defined later in this file. */ 258/* Prototypes for various functions defined later in this file. */
263void destroy_sensitive_data(void); 259void destroy_sensitive_data(void);
264void demote_sensitive_data(void); 260void demote_sensitive_data(void);
@@ -555,6 +551,10 @@ destroy_sensitive_data(void)
555 key_free(sensitive_data.host_keys[i]); 551 key_free(sensitive_data.host_keys[i]);
556 sensitive_data.host_keys[i] = NULL; 552 sensitive_data.host_keys[i] = NULL;
557 } 553 }
554 if (sensitive_data.host_certificates[i]) {
555 key_free(sensitive_data.host_certificates[i]);
556 sensitive_data.host_certificates[i] = NULL;
557 }
558 } 558 }
559 sensitive_data.ssh1_host_key = NULL; 559 sensitive_data.ssh1_host_key = NULL;
560 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); 560 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
@@ -581,6 +581,7 @@ demote_sensitive_data(void)
581 if (tmp->type == KEY_RSA1) 581 if (tmp->type == KEY_RSA1)
582 sensitive_data.ssh1_host_key = tmp; 582 sensitive_data.ssh1_host_key = tmp;
583 } 583 }
584 /* Certs do not need demotion */
584 } 585 }
585 586
586 /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ 587 /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
@@ -727,10 +728,11 @@ list_hostkey_types(void)
727 const char *p; 728 const char *p;
728 char *ret; 729 char *ret;
729 int i; 730 int i;
731 Key *key;
730 732
731 buffer_init(&b); 733 buffer_init(&b);
732 for (i = 0; i < options.num_host_key_files; i++) { 734 for (i = 0; i < options.num_host_key_files; i++) {
733 Key *key = sensitive_data.host_keys[i]; 735 key = sensitive_data.host_keys[i];
734 if (key == NULL) 736 if (key == NULL)
735 continue; 737 continue;
736 switch (key->type) { 738 switch (key->type) {
@@ -742,6 +744,19 @@ list_hostkey_types(void)
742 buffer_append(&b, p, strlen(p)); 744 buffer_append(&b, p, strlen(p));
743 break; 745 break;
744 } 746 }
747 /* If the private key has a cert peer, then list that too */
748 key = sensitive_data.host_certificates[i];
749 if (key == NULL)
750 continue;
751 switch (key->type) {
752 case KEY_RSA_CERT:
753 case KEY_DSA_CERT:
754 if (buffer_len(&b) > 0)
755 buffer_append(&b, ",", 1);
756 p = key_ssh_name(key);
757 buffer_append(&b, p, strlen(p));
758 break;
759 }
745 } 760 }
746 buffer_append(&b, "\0", 1); 761 buffer_append(&b, "\0", 1);
747 ret = xstrdup(buffer_ptr(&b)); 762 ret = xstrdup(buffer_ptr(&b));
@@ -750,20 +765,37 @@ list_hostkey_types(void)
750 return ret; 765 return ret;
751} 766}
752 767
753Key * 768static Key *
754get_hostkey_by_type(int type) 769get_hostkey_by_type(int type, int need_private)
755{ 770{
756 int i; 771 int i;
772 Key *key;
757 773
758 for (i = 0; i < options.num_host_key_files; i++) { 774 for (i = 0; i < options.num_host_key_files; i++) {
759 Key *key = sensitive_data.host_keys[i]; 775 if (type == KEY_RSA_CERT || type == KEY_DSA_CERT)
776 key = sensitive_data.host_certificates[i];
777 else
778 key = sensitive_data.host_keys[i];
760 if (key != NULL && key->type == type) 779 if (key != NULL && key->type == type)
761 return key; 780 return need_private ?
781 sensitive_data.host_keys[i] : key;
762 } 782 }
763 return NULL; 783 return NULL;
764} 784}
765 785
766Key * 786Key *
787get_hostkey_public_by_type(int type)
788{
789 return get_hostkey_by_type(type, 0);
790}
791
792Key *
793get_hostkey_private_by_type(int type)
794{
795 return get_hostkey_by_type(type, 1);
796}
797
798Key *
767get_hostkey_by_index(int ind) 799get_hostkey_by_index(int ind)
768{ 800{
769 if (ind < 0 || ind >= options.num_host_key_files) 801 if (ind < 0 || ind >= options.num_host_key_files)
@@ -777,8 +809,13 @@ get_hostkey_index(Key *key)
777 int i; 809 int i;
778 810
779 for (i = 0; i < options.num_host_key_files; i++) { 811 for (i = 0; i < options.num_host_key_files; i++) {
780 if (key == sensitive_data.host_keys[i]) 812 if (key_is_cert(key)) {
781 return (i); 813 if (key == sensitive_data.host_certificates[i])
814 return (i);
815 } else {
816 if (key == sensitive_data.host_keys[i])
817 return (i);
818 }
782 } 819 }
783 return (-1); 820 return (-1);
784} 821}
@@ -817,9 +854,9 @@ usage(void)
817 fprintf(stderr, "%s, %s\n", 854 fprintf(stderr, "%s, %s\n",
818 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); 855 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
819 fprintf(stderr, 856 fprintf(stderr,
820"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-f config_file]\n" 857"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
821" [-g login_grace_time] [-h host_key_file] [-k key_gen_time]\n" 858" [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
822" [-o option] [-p port] [-u len]\n" 859" [-k key_gen_time] [-o option] [-p port] [-u len]\n"
823 ); 860 );
824 exit(1); 861 exit(1);
825} 862}
@@ -915,31 +952,6 @@ recv_rexec_state(int fd, Buffer *conf)
915 debug3("%s: done", __func__); 952 debug3("%s: done", __func__);
916} 953}
917 954
918#ifdef OOM_ADJUST
919/*
920 * If requested in the environment, tell the Linux kernel's out-of-memory
921 * killer to avoid sshd. The old state will be restored when forking child
922 * processes.
923 */
924static void
925oom_adjust_startup(void)
926{
927 const char *oom_adj = getenv("SSHD_OOM_ADJUST");
928
929 if (!oom_adj || !*oom_adj)
930 return;
931 oom_adj_get(oom_adj_save, sizeof(oom_adj_save));
932 oom_adj_set(oom_adj);
933}
934
935static void
936oom_restore(void)
937{
938 if (oom_adj_save[0])
939 oom_adj_set(oom_adj_save);
940}
941#endif
942
943/* Accept a connection from inetd */ 955/* Accept a connection from inetd */
944static void 956static void
945server_accept_inetd(int *sock_in, int *sock_out) 957server_accept_inetd(int *sock_in, int *sock_out)
@@ -1015,15 +1027,9 @@ server_listen(void)
1015 &on, sizeof(on)) == -1) 1027 &on, sizeof(on)) == -1)
1016 error("setsockopt SO_REUSEADDR: %s", strerror(errno)); 1028 error("setsockopt SO_REUSEADDR: %s", strerror(errno));
1017 1029
1018#ifdef IPV6_V6ONLY
1019 /* Only communicate in IPv6 over AF_INET6 sockets. */ 1030 /* Only communicate in IPv6 over AF_INET6 sockets. */
1020 if (ai->ai_family == AF_INET6) { 1031 if (ai->ai_family == AF_INET6)
1021 if (setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, 1032 sock_set_v6only(listen_sock);
1022 &on, sizeof(on)) == -1)
1023 error("setsockopt IPV6_V6ONLY: %s",
1024 strerror(errno));
1025 }
1026#endif
1027 1033
1028 debug("Bind to port %s on %s.", strport, ntop); 1034 debug("Bind to port %s on %s.", strport, ntop);
1029 1035
@@ -1277,7 +1283,7 @@ main(int ac, char **av)
1277{ 1283{
1278 extern char *optarg; 1284 extern char *optarg;
1279 extern int optind; 1285 extern int optind;
1280 int opt, i, on = 1; 1286 int opt, i, j, on = 1;
1281 int sock_in = -1, sock_out = -1, newsock = -1; 1287 int sock_in = -1, sock_out = -1, newsock = -1;
1282 const char *remote_ip; 1288 const char *remote_ip;
1283 char *test_user = NULL, *test_host = NULL, *test_addr = NULL; 1289 char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
@@ -1330,6 +1336,14 @@ main(int ac, char **av)
1330 case 'f': 1336 case 'f':
1331 config_file_name = optarg; 1337 config_file_name = optarg;
1332 break; 1338 break;
1339 case 'c':
1340 if (options.num_host_cert_files >= MAX_HOSTCERTS) {
1341 fprintf(stderr, "too many host certificates.\n");
1342 exit(1);
1343 }
1344 options.host_cert_files[options.num_host_cert_files++] =
1345 derelativise_path(optarg);
1346 break;
1333 case 'd': 1347 case 'd':
1334 if (debug_flag == 0) { 1348 if (debug_flag == 0) {
1335 debug_flag = 1; 1349 debug_flag = 1;
@@ -1397,7 +1411,8 @@ main(int ac, char **av)
1397 fprintf(stderr, "too many host keys.\n"); 1411 fprintf(stderr, "too many host keys.\n");
1398 exit(1); 1412 exit(1);
1399 } 1413 }
1400 options.host_key_files[options.num_host_key_files++] = optarg; 1414 options.host_key_files[options.num_host_key_files++] =
1415 derelativise_path(optarg);
1401 break; 1416 break;
1402 case 't': 1417 case 't':
1403 test_flag = 1; 1418 test_flag = 1;
@@ -1555,7 +1570,7 @@ main(int ac, char **av)
1555 sensitive_data.host_keys[i] = NULL; 1570 sensitive_data.host_keys[i] = NULL;
1556 continue; 1571 continue;
1557 } 1572 }
1558 if (reject_blacklisted_key(key, 1) == 1) { 1573 if (auth_key_is_revoked(key, 1)) {
1559 key_free(key); 1574 key_free(key);
1560 sensitive_data.host_keys[i] = NULL; 1575 sensitive_data.host_keys[i] = NULL;
1561 continue; 1576 continue;
@@ -1589,6 +1604,46 @@ main(int ac, char **av)
1589 exit(1); 1604 exit(1);
1590 } 1605 }
1591 1606
1607 /*
1608 * Load certificates. They are stored in an array at identical
1609 * indices to the public keys that they relate to.
1610 */
1611 sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
1612 sizeof(Key *));
1613 for (i = 0; i < options.num_host_key_files; i++)
1614 sensitive_data.host_certificates[i] = NULL;
1615
1616 for (i = 0; i < options.num_host_cert_files; i++) {
1617 key = key_load_public(options.host_cert_files[i], NULL);
1618 if (key == NULL) {
1619 error("Could not load host certificate: %s",
1620 options.host_cert_files[i]);
1621 continue;
1622 }
1623 if (!key_is_cert(key)) {
1624 error("Certificate file is not a certificate: %s",
1625 options.host_cert_files[i]);
1626 key_free(key);
1627 continue;
1628 }
1629 /* Find matching private key */
1630 for (j = 0; j < options.num_host_key_files; j++) {
1631 if (key_equal_public(key,
1632 sensitive_data.host_keys[j])) {
1633 sensitive_data.host_certificates[j] = key;
1634 break;
1635 }
1636 }
1637 if (j >= options.num_host_key_files) {
1638 error("No matching private key for certificate: %s",
1639 options.host_cert_files[i]);
1640 key_free(key);
1641 continue;
1642 }
1643 sensitive_data.host_certificates[j] = key;
1644 debug("host certificate: #%d type %d %s", j, key->type,
1645 key_type(key));
1646 }
1592 /* Check certain values for sanity. */ 1647 /* Check certain values for sanity. */
1593 if (options.protocol & SSH_PROTO_1) { 1648 if (options.protocol & SSH_PROTO_1) {
1594 if (options.server_key_bits < 512 || 1649 if (options.server_key_bits < 512 ||
@@ -1707,15 +1762,11 @@ main(int ac, char **av)
1707 /* ignore SIGPIPE */ 1762 /* ignore SIGPIPE */
1708 signal(SIGPIPE, SIG_IGN); 1763 signal(SIGPIPE, SIG_IGN);
1709 1764
1710#ifdef OOM_ADJUST
1711 /* Adjust out-of-memory killer */
1712 oom_adjust_startup();
1713#endif
1714
1715 /* Get a connection, either from inetd or a listening TCP socket */ 1765 /* Get a connection, either from inetd or a listening TCP socket */
1716 if (inetd_flag) { 1766 if (inetd_flag) {
1717 server_accept_inetd(&sock_in, &sock_out); 1767 server_accept_inetd(&sock_in, &sock_out);
1718 } else { 1768 } else {
1769 platform_pre_listen();
1719 server_listen(); 1770 server_listen();
1720 1771
1721 if (options.protocol & SSH_PROTO_1) 1772 if (options.protocol & SSH_PROTO_1)
@@ -1750,10 +1801,6 @@ main(int ac, char **av)
1750 /* This is the child processing a new connection. */ 1801 /* This is the child processing a new connection. */
1751 setproctitle("%s", "[accepted]"); 1802 setproctitle("%s", "[accepted]");
1752 1803
1753#ifdef OOM_ADJUST
1754 oom_restore();
1755#endif
1756
1757 /* 1804 /*
1758 * Create a new session and process group since the 4.4BSD 1805 * Create a new session and process group since the 4.4BSD
1759 * setlogin() affects the entire process group. We don't 1806 * setlogin() affects the entire process group. We don't
@@ -1809,6 +1856,10 @@ main(int ac, char **av)
1809 sock_in, sock_out, newsock, startup_pipe, config_s[0]); 1856 sock_in, sock_out, newsock, startup_pipe, config_s[0]);
1810 } 1857 }
1811 1858
1859 /* Executed child processes don't need these. */
1860 fcntl(sock_out, F_SETFD, FD_CLOEXEC);
1861 fcntl(sock_in, F_SETFD, FD_CLOEXEC);
1862
1812 /* 1863 /*
1813 * Disable the key regeneration alarm. We will not regenerate the 1864 * Disable the key regeneration alarm. We will not regenerate the
1814 * key since we are no longer in a position to give it to anyone. We 1865 * key since we are no longer in a position to give it to anyone. We
@@ -1960,6 +2011,7 @@ main(int ac, char **av)
1960 2011
1961 /* prepare buffer to collect messages to display to user after login */ 2012 /* prepare buffer to collect messages to display to user after login */
1962 buffer_init(&loginmsg); 2013 buffer_init(&loginmsg);
2014 auth_debug_reset();
1963 2015
1964 if (use_privsep) 2016 if (use_privsep)
1965 if (privsep_preauth(authctxt) == 1) 2017 if (privsep_preauth(authctxt) == 1)
@@ -2365,7 +2417,8 @@ do_ssh2_kex(void)
2365 kex->server = 1; 2417 kex->server = 1;
2366 kex->client_version_string=client_version_string; 2418 kex->client_version_string=client_version_string;
2367 kex->server_version_string=server_version_string; 2419 kex->server_version_string=server_version_string;
2368 kex->load_host_key=&get_hostkey_by_type; 2420 kex->load_host_public_key=&get_hostkey_public_by_type;
2421 kex->load_host_private_key=&get_hostkey_private_by_type;
2369 kex->host_key_index=&get_hostkey_index; 2422 kex->host_key_index=&get_hostkey_index;
2370 2423
2371 xxx_kex = kex; 2424 xxx_kex = kex;