summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c125
1 files changed, 104 insertions, 21 deletions
diff --git a/sshd.c b/sshd.c
index d8faaebd5..4eddeb8d8 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.397 2013/02/11 21:21:58 dtucker Exp $ */ 1/* $OpenBSD: sshd.c,v 1.404 2013/07/19 07:37:48 markus 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
@@ -106,6 +106,7 @@
106#include "canohost.h" 106#include "canohost.h"
107#include "hostfile.h" 107#include "hostfile.h"
108#include "auth.h" 108#include "auth.h"
109#include "authfd.h"
109#include "misc.h" 110#include "misc.h"
110#include "msg.h" 111#include "msg.h"
111#include "dispatch.h" 112#include "dispatch.h"
@@ -198,6 +199,10 @@ char *server_version_string = NULL;
198/* for rekeying XXX fixme */ 199/* for rekeying XXX fixme */
199Kex *xxx_kex; 200Kex *xxx_kex;
200 201
202/* Daemon's agent connection */
203AuthenticationConnection *auth_conn = NULL;
204int have_agent = 0;
205
201/* 206/*
202 * Any really sensitive data in the application is contained in this 207 * Any really sensitive data in the application is contained in this
203 * structure. The idea is that this structure could be locked into memory so 208 * structure. The idea is that this structure could be locked into memory so
@@ -210,6 +215,7 @@ struct {
210 Key *server_key; /* ephemeral server key */ 215 Key *server_key; /* ephemeral server key */
211 Key *ssh1_host_key; /* ssh1 host key */ 216 Key *ssh1_host_key; /* ssh1 host key */
212 Key **host_keys; /* all private host keys */ 217 Key **host_keys; /* all private host keys */
218 Key **host_pubkeys; /* all public host keys */
213 Key **host_certificates; /* all public host certificates */ 219 Key **host_certificates; /* all public host certificates */
214 int have_ssh1_key; 220 int have_ssh1_key;
215 int have_ssh2_key; 221 int have_ssh2_key;
@@ -657,6 +663,8 @@ privsep_preauth(Authctxt *authctxt)
657 debug2("Network child is on pid %ld", (long)pid); 663 debug2("Network child is on pid %ld", (long)pid);
658 664
659 pmonitor->m_pid = pid; 665 pmonitor->m_pid = pid;
666 if (have_agent)
667 auth_conn = ssh_get_authentication_connection();
660 if (box != NULL) 668 if (box != NULL)
661 ssh_sandbox_parent_preauth(box, pid); 669 ssh_sandbox_parent_preauth(box, pid);
662 monitor_child_preauth(authctxt, pmonitor); 670 monitor_child_preauth(authctxt, pmonitor);
@@ -771,6 +779,8 @@ list_hostkey_types(void)
771 for (i = 0; i < options.num_host_key_files; i++) { 779 for (i = 0; i < options.num_host_key_files; i++) {
772 key = sensitive_data.host_keys[i]; 780 key = sensitive_data.host_keys[i];
773 if (key == NULL) 781 if (key == NULL)
782 key = sensitive_data.host_pubkeys[i];
783 if (key == NULL)
774 continue; 784 continue;
775 switch (key->type) { 785 switch (key->type) {
776 case KEY_RSA: 786 case KEY_RSA:
@@ -823,6 +833,8 @@ get_hostkey_by_type(int type, int need_private)
823 break; 833 break;
824 default: 834 default:
825 key = sensitive_data.host_keys[i]; 835 key = sensitive_data.host_keys[i];
836 if (key == NULL && !need_private)
837 key = sensitive_data.host_pubkeys[i];
826 break; 838 break;
827 } 839 }
828 if (key != NULL && key->type == type) 840 if (key != NULL && key->type == type)
@@ -852,6 +864,14 @@ get_hostkey_by_index(int ind)
852 return (sensitive_data.host_keys[ind]); 864 return (sensitive_data.host_keys[ind]);
853} 865}
854 866
867Key *
868get_hostkey_public_by_index(int ind)
869{
870 if (ind < 0 || ind >= options.num_host_key_files)
871 return (NULL);
872 return (sensitive_data.host_pubkeys[ind]);
873}
874
855int 875int
856get_hostkey_index(Key *key) 876get_hostkey_index(Key *key)
857{ 877{
@@ -864,6 +884,8 @@ get_hostkey_index(Key *key)
864 } else { 884 } else {
865 if (key == sensitive_data.host_keys[i]) 885 if (key == sensitive_data.host_keys[i])
866 return (i); 886 return (i);
887 if (key == sensitive_data.host_pubkeys[i])
888 return (i);
867 } 889 }
868 } 890 }
869 return (-1); 891 return (-1);
@@ -904,8 +926,9 @@ usage(void)
904 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); 926 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
905 fprintf(stderr, 927 fprintf(stderr,
906"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" 928"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
907" [-f config_file] [-g login_grace_time] [-h host_key_file]\n" 929" [-E log_file] [-f config_file] [-g login_grace_time]\n"
908" [-k key_gen_time] [-o option] [-p port] [-u len]\n" 930" [-h host_key_file] [-k key_gen_time] [-o option] [-p port]\n"
931" [-u len]\n"
909 ); 932 );
910 exit(1); 933 exit(1);
911} 934}
@@ -976,7 +999,7 @@ recv_rexec_state(int fd, Buffer *conf)
976 cp = buffer_get_string(&m, &len); 999 cp = buffer_get_string(&m, &len);
977 if (conf != NULL) 1000 if (conf != NULL)
978 buffer_append(conf, cp, len + 1); 1001 buffer_append(conf, cp, len + 1);
979 xfree(cp); 1002 free(cp);
980 1003
981 if (buffer_get_int(&m)) { 1004 if (buffer_get_int(&m)) {
982 if (sensitive_data.server_key != NULL) 1005 if (sensitive_data.server_key != NULL)
@@ -1027,7 +1050,9 @@ server_accept_inetd(int *sock_in, int *sock_out)
1027 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 1050 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
1028 dup2(fd, STDIN_FILENO); 1051 dup2(fd, STDIN_FILENO);
1029 dup2(fd, STDOUT_FILENO); 1052 dup2(fd, STDOUT_FILENO);
1030 if (fd > STDOUT_FILENO) 1053 if (!log_stderr)
1054 dup2(fd, STDERR_FILENO);
1055 if (fd > (log_stderr ? STDERR_FILENO : STDOUT_FILENO))
1031 close(fd); 1056 close(fd);
1032 } 1057 }
1033 debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out); 1058 debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
@@ -1138,7 +1163,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
1138 if (received_sighup) 1163 if (received_sighup)
1139 sighup_restart(); 1164 sighup_restart();
1140 if (fdset != NULL) 1165 if (fdset != NULL)
1141 xfree(fdset); 1166 free(fdset);
1142 fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS), 1167 fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
1143 sizeof(fd_mask)); 1168 sizeof(fd_mask));
1144 1169
@@ -1187,8 +1212,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
1187 *newsock = accept(listen_socks[i], 1212 *newsock = accept(listen_socks[i],
1188 (struct sockaddr *)&from, &fromlen); 1213 (struct sockaddr *)&from, &fromlen);
1189 if (*newsock < 0) { 1214 if (*newsock < 0) {
1190 if (errno != EINTR && errno != EAGAIN && 1215 if (errno != EINTR && errno != EWOULDBLOCK &&
1191 errno != EWOULDBLOCK) 1216 errno != ECONNABORTED && errno != EAGAIN)
1192 error("accept: %.100s", 1217 error("accept: %.100s",
1193 strerror(errno)); 1218 strerror(errno));
1194 if (errno == EMFILE || errno == ENFILE) 1219 if (errno == EMFILE || errno == ENFILE)
@@ -1339,12 +1364,14 @@ main(int ac, char **av)
1339 int sock_in = -1, sock_out = -1, newsock = -1; 1364 int sock_in = -1, sock_out = -1, newsock = -1;
1340 const char *remote_ip; 1365 const char *remote_ip;
1341 int remote_port; 1366 int remote_port;
1342 char *line; 1367 char *line, *logfile = NULL;
1343 int config_s[2] = { -1 , -1 }; 1368 int config_s[2] = { -1 , -1 };
1344 u_int n; 1369 u_int n;
1345 u_int64_t ibytes, obytes; 1370 u_int64_t ibytes, obytes;
1346 mode_t new_umask; 1371 mode_t new_umask;
1347 Key *key; 1372 Key *key;
1373 Key *pubkey;
1374 int keytype;
1348 Authctxt *authctxt; 1375 Authctxt *authctxt;
1349 struct connection_info *connection_info = get_connection_info(0, 0); 1376 struct connection_info *connection_info = get_connection_info(0, 0);
1350 1377
@@ -1377,7 +1404,7 @@ main(int ac, char **av)
1377 initialize_server_options(&options); 1404 initialize_server_options(&options);
1378 1405
1379 /* Parse command-line arguments. */ 1406 /* Parse command-line arguments. */
1380 while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) { 1407 while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) {
1381 switch (opt) { 1408 switch (opt) {
1382 case '4': 1409 case '4':
1383 options.address_family = AF_INET; 1410 options.address_family = AF_INET;
@@ -1406,6 +1433,9 @@ main(int ac, char **av)
1406 case 'D': 1433 case 'D':
1407 no_daemon_flag = 1; 1434 no_daemon_flag = 1;
1408 break; 1435 break;
1436 case 'E':
1437 logfile = xstrdup(optarg);
1438 /* FALLTHROUGH */
1409 case 'e': 1439 case 'e':
1410 log_stderr = 1; 1440 log_stderr = 1;
1411 break; 1441 break;
@@ -1484,7 +1514,7 @@ main(int ac, char **av)
1484 if (process_server_config_line(&options, line, 1514 if (process_server_config_line(&options, line,
1485 "command-line", 0, NULL, NULL) != 0) 1515 "command-line", 0, NULL, NULL) != 0)
1486 exit(1); 1516 exit(1);
1487 xfree(line); 1517 free(line);
1488 break; 1518 break;
1489 case '?': 1519 case '?':
1490 default: 1520 default:
@@ -1503,6 +1533,11 @@ main(int ac, char **av)
1503 1533
1504 OpenSSL_add_all_algorithms(); 1534 OpenSSL_add_all_algorithms();
1505 1535
1536 /* If requested, redirect the logs to the specified logfile. */
1537 if (logfile != NULL) {
1538 log_redirect_stderr_to(logfile);
1539 free(logfile);
1540 }
1506 /* 1541 /*
1507 * Force logging to stderr until we have loaded the private host 1542 * Force logging to stderr until we have loaded the private host
1508 * key (unless started from inetd) 1543 * key (unless started from inetd)
@@ -1611,27 +1646,50 @@ main(int ac, char **av)
1611 } else { 1646 } else {
1612 memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd)); 1647 memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
1613 privsep_pw = pwcopy(privsep_pw); 1648 privsep_pw = pwcopy(privsep_pw);
1614 xfree(privsep_pw->pw_passwd); 1649 free(privsep_pw->pw_passwd);
1615 privsep_pw->pw_passwd = xstrdup("*"); 1650 privsep_pw->pw_passwd = xstrdup("*");
1616 } 1651 }
1617 endpwent(); 1652 endpwent();
1618 1653
1619 /* load private host keys */ 1654 /* load host keys */
1620 sensitive_data.host_keys = xcalloc(options.num_host_key_files, 1655 sensitive_data.host_keys = xcalloc(options.num_host_key_files,
1621 sizeof(Key *)); 1656 sizeof(Key *));
1622 for (i = 0; i < options.num_host_key_files; i++) 1657 sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files,
1658 sizeof(Key *));
1659 for (i = 0; i < options.num_host_key_files; i++) {
1623 sensitive_data.host_keys[i] = NULL; 1660 sensitive_data.host_keys[i] = NULL;
1661 sensitive_data.host_pubkeys[i] = NULL;
1662 }
1663
1664 if (options.host_key_agent) {
1665 if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
1666 setenv(SSH_AUTHSOCKET_ENV_NAME,
1667 options.host_key_agent, 1);
1668 have_agent = ssh_agent_present();
1669 }
1624 1670
1625 for (i = 0; i < options.num_host_key_files; i++) { 1671 for (i = 0; i < options.num_host_key_files; i++) {
1626 key = key_load_private(options.host_key_files[i], "", NULL); 1672 key = key_load_private(options.host_key_files[i], "", NULL);
1673 pubkey = key_load_public(options.host_key_files[i], NULL);
1627 sensitive_data.host_keys[i] = key; 1674 sensitive_data.host_keys[i] = key;
1628 if (key == NULL) { 1675 sensitive_data.host_pubkeys[i] = pubkey;
1676
1677 if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 &&
1678 have_agent) {
1679 debug("will rely on agent for hostkey %s",
1680 options.host_key_files[i]);
1681 keytype = pubkey->type;
1682 } else if (key != NULL) {
1683 keytype = key->type;
1684 } else {
1629 error("Could not load host key: %s", 1685 error("Could not load host key: %s",
1630 options.host_key_files[i]); 1686 options.host_key_files[i]);
1631 sensitive_data.host_keys[i] = NULL; 1687 sensitive_data.host_keys[i] = NULL;
1688 sensitive_data.host_pubkeys[i] = NULL;
1632 continue; 1689 continue;
1633 } 1690 }
1634 switch (key->type) { 1691
1692 switch (keytype) {
1635 case KEY_RSA1: 1693 case KEY_RSA1:
1636 sensitive_data.ssh1_host_key = key; 1694 sensitive_data.ssh1_host_key = key;
1637 sensitive_data.have_ssh1_key = 1; 1695 sensitive_data.have_ssh1_key = 1;
@@ -1642,8 +1700,8 @@ main(int ac, char **av)
1642 sensitive_data.have_ssh2_key = 1; 1700 sensitive_data.have_ssh2_key = 1;
1643 break; 1701 break;
1644 } 1702 }
1645 debug("private host key: #%d type %d %s", i, key->type, 1703 debug("private host key: #%d type %d %s", i, keytype,
1646 key_type(key)); 1704 key_type(key ? key : pubkey));
1647 } 1705 }
1648 if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { 1706 if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
1649 logit("Disabling protocol version 1. Could not load host key"); 1707 logit("Disabling protocol version 1. Could not load host key");
@@ -1813,7 +1871,8 @@ main(int ac, char **av)
1813 1871
1814 /* Chdir to the root directory so that the current disk can be 1872 /* Chdir to the root directory so that the current disk can be
1815 unmounted if desired. */ 1873 unmounted if desired. */
1816 chdir("/"); 1874 if (chdir("/") == -1)
1875 error("chdir(\"/\"): %s", strerror(errno));
1817 1876
1818 /* ignore SIGPIPE */ 1877 /* ignore SIGPIPE */
1819 signal(SIGPIPE, SIG_IGN); 1878 signal(SIGPIPE, SIG_IGN);
@@ -2069,9 +2128,11 @@ main(int ac, char **av)
2069 buffer_init(&loginmsg); 2128 buffer_init(&loginmsg);
2070 auth_debug_reset(); 2129 auth_debug_reset();
2071 2130
2072 if (use_privsep) 2131 if (use_privsep) {
2073 if (privsep_preauth(authctxt) == 1) 2132 if (privsep_preauth(authctxt) == 1)
2074 goto authenticated; 2133 goto authenticated;
2134 } else if (compat20 && have_agent)
2135 auth_conn = ssh_get_authentication_connection();
2075 2136
2076 /* perform the key exchange */ 2137 /* perform the key exchange */
2077 /* authenticate user and start session */ 2138 /* authenticate user and start session */
@@ -2358,7 +2419,7 @@ do_ssh1_kex(void)
2358 MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); 2419 MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
2359 MD5_Final(session_key + 16, &md); 2420 MD5_Final(session_key + 16, &md);
2360 memset(buf, 0, bytes); 2421 memset(buf, 0, bytes);
2361 xfree(buf); 2422 free(buf);
2362 for (i = 0; i < 16; i++) 2423 for (i = 0; i < 16; i++)
2363 session_id[i] = session_key[i] ^ session_key[i + 16]; 2424 session_id[i] = session_key[i] ^ session_key[i + 16];
2364 } 2425 }
@@ -2385,6 +2446,23 @@ do_ssh1_kex(void)
2385 packet_write_wait(); 2446 packet_write_wait();
2386} 2447}
2387 2448
2449void
2450sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
2451 u_char *data, u_int dlen)
2452{
2453 if (privkey) {
2454 if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0))
2455 fatal("%s: key_sign failed", __func__);
2456 } else if (use_privsep) {
2457 if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0)
2458 fatal("%s: pubkey_sign failed", __func__);
2459 } else {
2460 if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data,
2461 dlen))
2462 fatal("%s: ssh_agent_sign failed", __func__);
2463 }
2464}
2465
2388/* 2466/*
2389 * SSH2 key exchange: diffie-hellman-group1-sha1 2467 * SSH2 key exchange: diffie-hellman-group1-sha1
2390 */ 2468 */
@@ -2416,6 +2494,10 @@ do_ssh2_kex(void)
2416 if (options.kex_algorithms != NULL) 2494 if (options.kex_algorithms != NULL)
2417 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 2495 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
2418 2496
2497 if (options.rekey_limit || options.rekey_interval)
2498 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
2499 (time_t)options.rekey_interval);
2500
2419 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); 2501 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
2420 2502
2421#ifdef GSSAPI 2503#ifdef GSSAPI
@@ -2480,6 +2562,7 @@ do_ssh2_kex(void)
2480 kex->load_host_public_key=&get_hostkey_public_by_type; 2562 kex->load_host_public_key=&get_hostkey_public_by_type;
2481 kex->load_host_private_key=&get_hostkey_private_by_type; 2563 kex->load_host_private_key=&get_hostkey_private_by_type;
2482 kex->host_key_index=&get_hostkey_index; 2564 kex->host_key_index=&get_hostkey_index;
2565 kex->sign = sshd_hostkey_sign;
2483 2566
2484 xxx_kex = kex; 2567 xxx_kex = kex;
2485 2568