summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c117
1 files changed, 104 insertions, 13 deletions
diff --git a/sshd.c b/sshd.c
index bf2e76cc8..0c3c04e4e 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.372 2010/01/29 00:20:41 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.373 2010/02/26 20:29:54 djm 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
@@ -205,6 +205,7 @@ struct {
205 Key *server_key; /* ephemeral server key */ 205 Key *server_key; /* ephemeral server key */
206 Key *ssh1_host_key; /* ssh1 host key */ 206 Key *ssh1_host_key; /* ssh1 host key */
207 Key **host_keys; /* all private host keys */ 207 Key **host_keys; /* all private host keys */
208 Key **host_certificates; /* all public host certificates */
208 int have_ssh1_key; 209 int have_ssh1_key;
209 int have_ssh2_key; 210 int have_ssh2_key;
210 u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; 211 u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH];
@@ -545,6 +546,10 @@ destroy_sensitive_data(void)
545 key_free(sensitive_data.host_keys[i]); 546 key_free(sensitive_data.host_keys[i]);
546 sensitive_data.host_keys[i] = NULL; 547 sensitive_data.host_keys[i] = NULL;
547 } 548 }
549 if (sensitive_data.host_certificates[i]) {
550 key_free(sensitive_data.host_certificates[i]);
551 sensitive_data.host_certificates[i] = NULL;
552 }
548 } 553 }
549 sensitive_data.ssh1_host_key = NULL; 554 sensitive_data.ssh1_host_key = NULL;
550 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); 555 memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
@@ -571,6 +576,7 @@ demote_sensitive_data(void)
571 if (tmp->type == KEY_RSA1) 576 if (tmp->type == KEY_RSA1)
572 sensitive_data.ssh1_host_key = tmp; 577 sensitive_data.ssh1_host_key = tmp;
573 } 578 }
579 /* Certs do not need demotion */
574 } 580 }
575 581
576 /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ 582 /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
@@ -717,10 +723,11 @@ list_hostkey_types(void)
717 const char *p; 723 const char *p;
718 char *ret; 724 char *ret;
719 int i; 725 int i;
726 Key *key;
720 727
721 buffer_init(&b); 728 buffer_init(&b);
722 for (i = 0; i < options.num_host_key_files; i++) { 729 for (i = 0; i < options.num_host_key_files; i++) {
723 Key *key = sensitive_data.host_keys[i]; 730 key = sensitive_data.host_keys[i];
724 if (key == NULL) 731 if (key == NULL)
725 continue; 732 continue;
726 switch (key->type) { 733 switch (key->type) {
@@ -732,6 +739,19 @@ list_hostkey_types(void)
732 buffer_append(&b, p, strlen(p)); 739 buffer_append(&b, p, strlen(p));
733 break; 740 break;
734 } 741 }
742 /* If the private key has a cert peer, then list that too */
743 key = sensitive_data.host_certificates[i];
744 if (key == NULL)
745 continue;
746 switch (key->type) {
747 case KEY_RSA_CERT:
748 case KEY_DSA_CERT:
749 if (buffer_len(&b) > 0)
750 buffer_append(&b, ",", 1);
751 p = key_ssh_name(key);
752 buffer_append(&b, p, strlen(p));
753 break;
754 }
735 } 755 }
736 buffer_append(&b, "\0", 1); 756 buffer_append(&b, "\0", 1);
737 ret = xstrdup(buffer_ptr(&b)); 757 ret = xstrdup(buffer_ptr(&b));
@@ -740,20 +760,37 @@ list_hostkey_types(void)
740 return ret; 760 return ret;
741} 761}
742 762
743Key * 763static Key *
744get_hostkey_by_type(int type) 764get_hostkey_by_type(int type, int need_private)
745{ 765{
746 int i; 766 int i;
767 Key *key;
747 768
748 for (i = 0; i < options.num_host_key_files; i++) { 769 for (i = 0; i < options.num_host_key_files; i++) {
749 Key *key = sensitive_data.host_keys[i]; 770 if (type == KEY_RSA_CERT || type == KEY_DSA_CERT)
771 key = sensitive_data.host_certificates[i];
772 else
773 key = sensitive_data.host_keys[i];
750 if (key != NULL && key->type == type) 774 if (key != NULL && key->type == type)
751 return key; 775 return need_private ?
776 sensitive_data.host_keys[i] : key;
752 } 777 }
753 return NULL; 778 return NULL;
754} 779}
755 780
756Key * 781Key *
782get_hostkey_public_by_type(int type)
783{
784 return get_hostkey_by_type(type, 0);
785}
786
787Key *
788get_hostkey_private_by_type(int type)
789{
790 return get_hostkey_by_type(type, 1);
791}
792
793Key *
757get_hostkey_by_index(int ind) 794get_hostkey_by_index(int ind)
758{ 795{
759 if (ind < 0 || ind >= options.num_host_key_files) 796 if (ind < 0 || ind >= options.num_host_key_files)
@@ -767,8 +804,13 @@ get_hostkey_index(Key *key)
767 int i; 804 int i;
768 805
769 for (i = 0; i < options.num_host_key_files; i++) { 806 for (i = 0; i < options.num_host_key_files; i++) {
770 if (key == sensitive_data.host_keys[i]) 807 if (key_is_cert(key)) {
771 return (i); 808 if (key == sensitive_data.host_certificates[i])
809 return (i);
810 } else {
811 if (key == sensitive_data.host_keys[i])
812 return (i);
813 }
772 } 814 }
773 return (-1); 815 return (-1);
774} 816}
@@ -807,9 +849,9 @@ usage(void)
807 fprintf(stderr, "%s, %s\n", 849 fprintf(stderr, "%s, %s\n",
808 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); 850 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
809 fprintf(stderr, 851 fprintf(stderr,
810"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-f config_file]\n" 852"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
811" [-g login_grace_time] [-h host_key_file] [-k key_gen_time]\n" 853" [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
812" [-o option] [-p port] [-u len]\n" 854" [-k key_gen_time] [-o option] [-p port] [-u len]\n"
813 ); 855 );
814 exit(1); 856 exit(1);
815} 857}
@@ -1236,7 +1278,7 @@ main(int ac, char **av)
1236{ 1278{
1237 extern char *optarg; 1279 extern char *optarg;
1238 extern int optind; 1280 extern int optind;
1239 int opt, i, on = 1; 1281 int opt, i, j, on = 1;
1240 int sock_in = -1, sock_out = -1, newsock = -1; 1282 int sock_in = -1, sock_out = -1, newsock = -1;
1241 const char *remote_ip; 1283 const char *remote_ip;
1242 char *test_user = NULL, *test_host = NULL, *test_addr = NULL; 1284 char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
@@ -1289,6 +1331,14 @@ main(int ac, char **av)
1289 case 'f': 1331 case 'f':
1290 config_file_name = optarg; 1332 config_file_name = optarg;
1291 break; 1333 break;
1334 case 'c':
1335 if (options.num_host_cert_files >= MAX_HOSTCERTS) {
1336 fprintf(stderr, "too many host certificates.\n");
1337 exit(1);
1338 }
1339 options.host_cert_files[options.num_host_cert_files++] =
1340 derelativise_path(optarg);
1341 break;
1292 case 'd': 1342 case 'd':
1293 if (debug_flag == 0) { 1343 if (debug_flag == 0) {
1294 debug_flag = 1; 1344 debug_flag = 1;
@@ -1536,6 +1586,46 @@ main(int ac, char **av)
1536 exit(1); 1586 exit(1);
1537 } 1587 }
1538 1588
1589 /*
1590 * Load certificates. They are stored in an array at identical
1591 * indices to the public keys that they relate to.
1592 */
1593 sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
1594 sizeof(Key *));
1595 for (i = 0; i < options.num_host_key_files; i++)
1596 sensitive_data.host_certificates[i] = NULL;
1597
1598 for (i = 0; i < options.num_host_cert_files; i++) {
1599 key = key_load_public(options.host_cert_files[i], NULL);
1600 if (key == NULL) {
1601 error("Could not load host certificate: %s",
1602 options.host_cert_files[i]);
1603 continue;
1604 }
1605 if (!key_is_cert(key)) {
1606 error("Certificate file is not a certificate: %s",
1607 options.host_cert_files[i]);
1608 key_free(key);
1609 continue;
1610 }
1611 /* Find matching private key */
1612 for (j = 0; j < options.num_host_key_files; j++) {
1613 if (key_equal_public(key,
1614 sensitive_data.host_keys[j])) {
1615 sensitive_data.host_certificates[j] = key;
1616 break;
1617 }
1618 }
1619 if (j >= options.num_host_key_files) {
1620 error("No matching private key for certificate: %s",
1621 options.host_cert_files[i]);
1622 key_free(key);
1623 continue;
1624 }
1625 sensitive_data.host_certificates[j] = key;
1626 debug("host certificate: #%d type %d %s", j, key->type,
1627 key_type(key));
1628 }
1539 /* Check certain values for sanity. */ 1629 /* Check certain values for sanity. */
1540 if (options.protocol & SSH_PROTO_1) { 1630 if (options.protocol & SSH_PROTO_1) {
1541 if (options.server_key_bits < 512 || 1631 if (options.server_key_bits < 512 ||
@@ -2205,7 +2295,8 @@ do_ssh2_kex(void)
2205 kex->server = 1; 2295 kex->server = 1;
2206 kex->client_version_string=client_version_string; 2296 kex->client_version_string=client_version_string;
2207 kex->server_version_string=server_version_string; 2297 kex->server_version_string=server_version_string;
2208 kex->load_host_key=&get_hostkey_by_type; 2298 kex->load_host_public_key=&get_hostkey_public_by_type;
2299 kex->load_host_private_key=&get_hostkey_private_by_type;
2209 kex->host_key_index=&get_hostkey_index; 2300 kex->host_key_index=&get_hostkey_index;
2210 2301
2211 xxx_kex = kex; 2302 xxx_kex = kex;