summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2016-02-29 12:15:15 +0000
committerColin Watson <cjwatson@debian.org>2016-03-08 11:51:22 +0000
commit46961f5704f8e86cea3e99253faad55aef4d8f35 (patch)
tree0dd97fa4fb649a62b4639fe2674380872b1f3e98 /ssh.c
parentc753fe267efb1b027424fa8706cf0385fc3d14c1 (diff)
parent85e40e87a75fb80a0bf893ac05a417d6c353537d (diff)
New upstream release (7.2).
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c148
1 files changed, 106 insertions, 42 deletions
diff --git a/ssh.c b/ssh.c
index eb739035e..314dd528d 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.420 2015/07/30 00:01:34 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.436 2016/02/15 09:47:49 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
@@ -105,7 +105,6 @@
105#include "match.h" 105#include "match.h"
106#include "msg.h" 106#include "msg.h"
107#include "uidswap.h" 107#include "uidswap.h"
108#include "roaming.h"
109#include "version.h" 108#include "version.h"
110#include "ssherr.h" 109#include "ssherr.h"
111#include "myproposal.h" 110#include "myproposal.h"
@@ -203,11 +202,9 @@ usage(void)
203 fprintf(stderr, 202 fprintf(stderr,
204"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" 203"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
205" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" 204" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n"
206" [-F configfile] [-I pkcs11] [-i identity_file]\n" 205" [-F configfile] [-I pkcs11] [-i identity_file] [-L address]\n"
207" [-L address] [-l login_name] [-m mac_spec]\n" 206" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
208" [-O ctl_cmd] [-o option] [-p port]\n" 207" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
209" [-Q cipher | cipher-auth | mac | kex | key]\n"
210" [-R address] [-S ctl_path] [-W host:port]\n"
211" [-w local_tun[:remote_tun]] [user@]hostname [command]\n" 208" [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
212 ); 209 );
213 exit(255); 210 exit(255);
@@ -252,7 +249,7 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
252 if (port <= 0) 249 if (port <= 0)
253 port = default_ssh_port(); 250 port = default_ssh_port();
254 251
255 snprintf(strport, sizeof strport, "%u", port); 252 snprintf(strport, sizeof strport, "%d", port);
256 memset(&hints, 0, sizeof(hints)); 253 memset(&hints, 0, sizeof(hints));
257 hints.ai_family = options.address_family == -1 ? 254 hints.ai_family = options.address_family == -1 ?
258 AF_UNSPEC : options.address_family; 255 AF_UNSPEC : options.address_family;
@@ -406,6 +403,17 @@ resolve_canonicalize(char **hostp, int port)
406 return addrs; 403 return addrs;
407 } 404 }
408 405
406 /* If domain name is anchored, then resolve it now */
407 if ((*hostp)[strlen(*hostp) - 1] == '.') {
408 debug3("%s: name is fully qualified", __func__);
409 fullhost = xstrdup(*hostp);
410 if ((addrs = resolve_host(fullhost, port, 0,
411 newname, sizeof(newname))) != NULL)
412 goto found;
413 free(fullhost);
414 goto notfound;
415 }
416
409 /* Don't apply canonicalization to sufficiently-qualified hostnames */ 417 /* Don't apply canonicalization to sufficiently-qualified hostnames */
410 ndots = 0; 418 ndots = 0;
411 for (cp = *hostp; *cp != '\0'; cp++) { 419 for (cp = *hostp; *cp != '\0'; cp++) {
@@ -429,6 +437,7 @@ resolve_canonicalize(char **hostp, int port)
429 free(fullhost); 437 free(fullhost);
430 continue; 438 continue;
431 } 439 }
440 found:
432 /* Remove trailing '.' */ 441 /* Remove trailing '.' */
433 fullhost[strlen(fullhost) - 1] = '\0'; 442 fullhost[strlen(fullhost) - 1] = '\0';
434 /* Follow CNAME if requested */ 443 /* Follow CNAME if requested */
@@ -440,6 +449,7 @@ resolve_canonicalize(char **hostp, int port)
440 *hostp = fullhost; 449 *hostp = fullhost;
441 return addrs; 450 return addrs;
442 } 451 }
452 notfound:
443 if (!options.canonicalize_fallback_local) 453 if (!options.canonicalize_fallback_local)
444 fatal("%s: Could not resolve host \"%s\"", __progname, *hostp); 454 fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
445 debug2("%s: host %s not found in any suffix", __func__, *hostp); 455 debug2("%s: host %s not found in any suffix", __func__, *hostp);
@@ -506,7 +516,7 @@ main(int ac, char **av)
506 int i, r, opt, exit_status, use_syslog, config_test = 0; 516 int i, r, opt, exit_status, use_syslog, config_test = 0;
507 char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile; 517 char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
508 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 518 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
509 char cname[NI_MAXHOST]; 519 char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex;
510 struct stat st; 520 struct stat st;
511 struct passwd *pw; 521 struct passwd *pw;
512 int timeout_ms; 522 int timeout_ms;
@@ -516,8 +526,8 @@ main(int ac, char **av)
516 struct addrinfo *addrs = NULL; 526 struct addrinfo *addrs = NULL;
517 struct ssh_digest_ctx *md; 527 struct ssh_digest_ctx *md;
518 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 528 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
519 char *conn_hash_hex;
520 529
530 ssh_malloc_init(); /* must be called before any mallocs */
521 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 531 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
522 sanitise_stdfd(); 532 sanitise_stdfd();
523 533
@@ -627,7 +637,7 @@ main(int ac, char **av)
627 use_syslog = 1; 637 use_syslog = 1;
628 break; 638 break;
629 case 'E': 639 case 'E':
630 logfile = xstrdup(optarg); 640 logfile = optarg;
631 break; 641 break;
632 case 'G': 642 case 'G':
633 config_test = 1; 643 config_test = 1;
@@ -704,16 +714,18 @@ main(int ac, char **av)
704 options.gss_deleg_creds = 1; 714 options.gss_deleg_creds = 1;
705 break; 715 break;
706 case 'i': 716 case 'i':
707 if (stat(optarg, &st) < 0) { 717 p = tilde_expand_filename(optarg, original_real_uid);
718 if (stat(p, &st) < 0)
708 fprintf(stderr, "Warning: Identity file %s " 719 fprintf(stderr, "Warning: Identity file %s "
709 "not accessible: %s.\n", optarg, 720 "not accessible: %s.\n", p,
710 strerror(errno)); 721 strerror(errno));
711 break; 722 else
712 } 723 add_identity_file(&options, NULL, p, 1);
713 add_identity_file(&options, NULL, optarg, 1); 724 free(p);
714 break; 725 break;
715 case 'I': 726 case 'I':
716#ifdef ENABLE_PKCS11 727#ifdef ENABLE_PKCS11
728 free(options.pkcs11_provider);
717 options.pkcs11_provider = xstrdup(optarg); 729 options.pkcs11_provider = xstrdup(optarg);
718#else 730#else
719 fprintf(stderr, "no support for PKCS#11.\n"); 731 fprintf(stderr, "no support for PKCS#11.\n");
@@ -798,6 +810,7 @@ main(int ac, char **av)
798 if (ciphers_valid(*optarg == '+' ? 810 if (ciphers_valid(*optarg == '+' ?
799 optarg + 1 : optarg)) { 811 optarg + 1 : optarg)) {
800 /* SSH2 only */ 812 /* SSH2 only */
813 free(options.ciphers);
801 options.ciphers = xstrdup(optarg); 814 options.ciphers = xstrdup(optarg);
802 options.cipher = SSH_CIPHER_INVALID; 815 options.cipher = SSH_CIPHER_INVALID;
803 break; 816 break;
@@ -817,9 +830,10 @@ main(int ac, char **av)
817 options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT); 830 options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT);
818 break; 831 break;
819 case 'm': 832 case 'm':
820 if (mac_valid(optarg)) 833 if (mac_valid(optarg)) {
834 free(options.macs);
821 options.macs = xstrdup(optarg); 835 options.macs = xstrdup(optarg);
822 else { 836 } else {
823 fprintf(stderr, "Unknown mac type '%s'\n", 837 fprintf(stderr, "Unknown mac type '%s'\n",
824 optarg); 838 optarg);
825 exit(255); 839 exit(255);
@@ -897,8 +911,7 @@ main(int ac, char **av)
897 subsystem_flag = 1; 911 subsystem_flag = 1;
898 break; 912 break;
899 case 'S': 913 case 'S':
900 if (options.control_path != NULL) 914 free(options.control_path);
901 free(options.control_path);
902 options.control_path = xstrdup(optarg); 915 options.control_path = xstrdup(optarg);
903 break; 916 break;
904 case 'b': 917 case 'b':
@@ -980,10 +993,8 @@ main(int ac, char **av)
980 */ 993 */
981 if (use_syslog && logfile != NULL) 994 if (use_syslog && logfile != NULL)
982 fatal("Can't specify both -y and -E"); 995 fatal("Can't specify both -y and -E");
983 if (logfile != NULL) { 996 if (logfile != NULL)
984 log_redirect_stderr_to(logfile); 997 log_redirect_stderr_to(logfile);
985 free(logfile);
986 }
987 log_init(argv0, 998 log_init(argv0,
988 options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, 999 options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
989 SYSLOG_FACILITY_USER, !use_syslog); 1000 SYSLOG_FACILITY_USER, !use_syslog);
@@ -1084,6 +1095,8 @@ main(int ac, char **av)
1084 "disabling"); 1095 "disabling");
1085 options.update_hostkeys = 0; 1096 options.update_hostkeys = 0;
1086 } 1097 }
1098 if (options.connection_attempts <= 0)
1099 fatal("Invalid number of ConnectionAttempts");
1087#ifndef HAVE_CYGWIN 1100#ifndef HAVE_CYGWIN
1088 if (original_effective_uid != 0) 1101 if (original_effective_uid != 0)
1089 options.use_privileged_port = 0; 1102 options.use_privileged_port = 0;
@@ -1122,6 +1135,7 @@ main(int ac, char **av)
1122 strlcpy(shorthost, thishost, sizeof(shorthost)); 1135 strlcpy(shorthost, thishost, sizeof(shorthost));
1123 shorthost[strcspn(thishost, ".")] = '\0'; 1136 shorthost[strcspn(thishost, ".")] = '\0';
1124 snprintf(portstr, sizeof(portstr), "%d", options.port); 1137 snprintf(portstr, sizeof(portstr), "%d", options.port);
1138 snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
1125 1139
1126 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 1140 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
1127 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 1141 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
@@ -1164,6 +1178,7 @@ main(int ac, char **av)
1164 "p", portstr, 1178 "p", portstr,
1165 "r", options.user, 1179 "r", options.user,
1166 "u", pw->pw_name, 1180 "u", pw->pw_name,
1181 "i", uidstr,
1167 (char *)NULL); 1182 (char *)NULL);
1168 free(cp); 1183 free(cp);
1169 } 1184 }
@@ -1184,6 +1199,7 @@ main(int ac, char **av)
1184 * have yet resolved the hostname. Do so now. 1199 * have yet resolved the hostname. Do so now.
1185 */ 1200 */
1186 if (addrs == NULL && options.proxy_command == NULL) { 1201 if (addrs == NULL && options.proxy_command == NULL) {
1202 debug2("resolving \"%s\" port %d", host, options.port);
1187 if ((addrs = resolve_host(host, options.port, 1, 1203 if ((addrs = resolve_host(host, options.port, 1,
1188 cname, sizeof(cname))) == NULL) 1204 cname, sizeof(cname))) == NULL)
1189 cleanup_exit(255); /* resolve_host logs the error */ 1205 cleanup_exit(255); /* resolve_host logs the error */
@@ -1227,8 +1243,10 @@ main(int ac, char **av)
1227 sensitive_data.keys[i] = NULL; 1243 sensitive_data.keys[i] = NULL;
1228 1244
1229 PRIV_START; 1245 PRIV_START;
1246#if WITH_SSH1
1230 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, 1247 sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
1231 _PATH_HOST_KEY_FILE, "", NULL, NULL); 1248 _PATH_HOST_KEY_FILE, "", NULL, NULL);
1249#endif
1232#ifdef OPENSSL_HAS_ECC 1250#ifdef OPENSSL_HAS_ECC
1233 sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA, 1251 sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA,
1234 _PATH_HOST_ECDSA_KEY_FILE, "", NULL); 1252 _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
@@ -1353,6 +1371,10 @@ main(int ac, char **av)
1353 options.identity_keys[i] = NULL; 1371 options.identity_keys[i] = NULL;
1354 } 1372 }
1355 } 1373 }
1374 for (i = 0; i < options.num_certificate_files; i++) {
1375 free(options.certificate_files[i]);
1376 options.certificate_files[i] = NULL;
1377 }
1356 1378
1357 exit_status = compat20 ? ssh_session2() : ssh_session(); 1379 exit_status = compat20 ? ssh_session2() : ssh_session();
1358 packet_close(); 1380 packet_close();
@@ -1604,6 +1626,7 @@ ssh_session(void)
1604 struct winsize ws; 1626 struct winsize ws;
1605 char *cp; 1627 char *cp;
1606 const char *display; 1628 const char *display;
1629 char *proto = NULL, *data = NULL;
1607 1630
1608 /* Enable compression if requested. */ 1631 /* Enable compression if requested. */
1609 if (options.compression) { 1632 if (options.compression) {
@@ -1674,13 +1697,9 @@ ssh_session(void)
1674 display = getenv("DISPLAY"); 1697 display = getenv("DISPLAY");
1675 if (display == NULL && options.forward_x11) 1698 if (display == NULL && options.forward_x11)
1676 debug("X11 forwarding requested but DISPLAY not set"); 1699 debug("X11 forwarding requested but DISPLAY not set");
1677 if (options.forward_x11 && display != NULL) { 1700 if (options.forward_x11 && client_x11_get_proto(display,
1678 char *proto, *data; 1701 options.xauth_location, options.forward_x11_trusted,
1679 /* Get reasonable local authentication information. */ 1702 options.forward_x11_timeout, &proto, &data) == 0) {
1680 client_x11_get_proto(display, options.xauth_location,
1681 options.forward_x11_trusted,
1682 options.forward_x11_timeout,
1683 &proto, &data);
1684 /* Request forwarding with authentication spoofing. */ 1703 /* Request forwarding with authentication spoofing. */
1685 debug("Requesting X11 forwarding with authentication " 1704 debug("Requesting X11 forwarding with authentication "
1686 "spoofing."); 1705 "spoofing.");
@@ -1770,6 +1789,7 @@ ssh_session2_setup(int id, int success, void *arg)
1770 extern char **environ; 1789 extern char **environ;
1771 const char *display; 1790 const char *display;
1772 int interactive = tty_flag; 1791 int interactive = tty_flag;
1792 char *proto = NULL, *data = NULL;
1773 1793
1774 if (!success) 1794 if (!success)
1775 return; /* No need for error message, channels code sens one */ 1795 return; /* No need for error message, channels code sens one */
@@ -1777,12 +1797,9 @@ ssh_session2_setup(int id, int success, void *arg)
1777 display = getenv("DISPLAY"); 1797 display = getenv("DISPLAY");
1778 if (display == NULL && options.forward_x11) 1798 if (display == NULL && options.forward_x11)
1779 debug("X11 forwarding requested but DISPLAY not set"); 1799 debug("X11 forwarding requested but DISPLAY not set");
1780 if (options.forward_x11 && display != NULL) { 1800 if (options.forward_x11 && client_x11_get_proto(display,
1781 char *proto, *data; 1801 options.xauth_location, options.forward_x11_trusted,
1782 /* Get reasonable local authentication information. */ 1802 options.forward_x11_timeout, &proto, &data) == 0) {
1783 client_x11_get_proto(display, options.xauth_location,
1784 options.forward_x11_trusted,
1785 options.forward_x11_timeout, &proto, &data);
1786 /* Request forwarding with authentication spoofing. */ 1803 /* Request forwarding with authentication spoofing. */
1787 debug("Requesting X11 forwarding with authentication " 1804 debug("Requesting X11 forwarding with authentication "
1788 "spoofing."); 1805 "spoofing.");
@@ -1936,25 +1953,30 @@ ssh_session2(void)
1936 options.escape_char : SSH_ESCAPECHAR_NONE, id); 1953 options.escape_char : SSH_ESCAPECHAR_NONE, id);
1937} 1954}
1938 1955
1956/* Loads all IdentityFile and CertificateFile keys */
1939static void 1957static void
1940load_public_identity_files(void) 1958load_public_identity_files(void)
1941{ 1959{
1942 char *filename, *cp, thishost[NI_MAXHOST]; 1960 char *filename, *cp, thishost[NI_MAXHOST];
1943 char *pwdir = NULL, *pwname = NULL; 1961 char *pwdir = NULL, *pwname = NULL;
1944 int i = 0;
1945 Key *public; 1962 Key *public;
1946 struct passwd *pw; 1963 struct passwd *pw;
1947 u_int n_ids; 1964 int i;
1965 u_int n_ids, n_certs;
1948 char *identity_files[SSH_MAX_IDENTITY_FILES]; 1966 char *identity_files[SSH_MAX_IDENTITY_FILES];
1949 Key *identity_keys[SSH_MAX_IDENTITY_FILES]; 1967 Key *identity_keys[SSH_MAX_IDENTITY_FILES];
1968 char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
1969 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
1950#ifdef ENABLE_PKCS11 1970#ifdef ENABLE_PKCS11
1951 Key **keys; 1971 Key **keys;
1952 int nkeys; 1972 int nkeys;
1953#endif /* PKCS11 */ 1973#endif /* PKCS11 */
1954 1974
1955 n_ids = 0; 1975 n_ids = n_certs = 0;
1956 memset(identity_files, 0, sizeof(identity_files)); 1976 memset(identity_files, 0, sizeof(identity_files));
1957 memset(identity_keys, 0, sizeof(identity_keys)); 1977 memset(identity_keys, 0, sizeof(identity_keys));
1978 memset(certificate_files, 0, sizeof(certificate_files));
1979 memset(certificates, 0, sizeof(certificates));
1958 1980
1959#ifdef ENABLE_PKCS11 1981#ifdef ENABLE_PKCS11
1960 if (options.pkcs11_provider != NULL && 1982 if (options.pkcs11_provider != NULL &&
@@ -1986,6 +2008,7 @@ load_public_identity_files(void)
1986 if (n_ids >= SSH_MAX_IDENTITY_FILES || 2008 if (n_ids >= SSH_MAX_IDENTITY_FILES ||
1987 strcasecmp(options.identity_files[i], "none") == 0) { 2009 strcasecmp(options.identity_files[i], "none") == 0) {
1988 free(options.identity_files[i]); 2010 free(options.identity_files[i]);
2011 options.identity_files[i] = NULL;
1989 continue; 2012 continue;
1990 } 2013 }
1991 cp = tilde_expand_filename(options.identity_files[i], 2014 cp = tilde_expand_filename(options.identity_files[i],
@@ -2004,7 +2027,12 @@ load_public_identity_files(void)
2004 if (++n_ids >= SSH_MAX_IDENTITY_FILES) 2027 if (++n_ids >= SSH_MAX_IDENTITY_FILES)
2005 continue; 2028 continue;
2006 2029
2007 /* Try to add the certificate variant too */ 2030 /*
2031 * If no certificates have been explicitly listed then try
2032 * to add the default certificate variant too.
2033 */
2034 if (options.num_certificate_files != 0)
2035 continue;
2008 xasprintf(&cp, "%s-cert", filename); 2036 xasprintf(&cp, "%s-cert", filename);
2009 public = key_load_public(cp, NULL); 2037 public = key_load_public(cp, NULL);
2010 debug("identity file %s type %d", cp, 2038 debug("identity file %s type %d", cp,
@@ -2021,14 +2049,50 @@ load_public_identity_files(void)
2021 continue; 2049 continue;
2022 } 2050 }
2023 identity_keys[n_ids] = public; 2051 identity_keys[n_ids] = public;
2024 /* point to the original path, most likely the private key */ 2052 identity_files[n_ids] = cp;
2025 identity_files[n_ids] = xstrdup(filename);
2026 n_ids++; 2053 n_ids++;
2027 } 2054 }
2055
2056 if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
2057 fatal("%s: too many certificates", __func__);
2058 for (i = 0; i < options.num_certificate_files; i++) {
2059 cp = tilde_expand_filename(options.certificate_files[i],
2060 original_real_uid);
2061 filename = percent_expand(cp, "d", pwdir,
2062 "u", pwname, "l", thishost, "h", host,
2063 "r", options.user, (char *)NULL);
2064 free(cp);
2065
2066 public = key_load_public(filename, NULL);
2067 debug("certificate file %s type %d", filename,
2068 public ? public->type : -1);
2069 free(options.certificate_files[i]);
2070 options.certificate_files[i] = NULL;
2071 if (public == NULL) {
2072 free(filename);
2073 continue;
2074 }
2075 if (!key_is_cert(public)) {
2076 debug("%s: key %s type %s is not a certificate",
2077 __func__, filename, key_type(public));
2078 key_free(public);
2079 free(filename);
2080 continue;
2081 }
2082 certificate_files[n_certs] = filename;
2083 certificates[n_certs] = public;
2084 ++n_certs;
2085 }
2086
2028 options.num_identity_files = n_ids; 2087 options.num_identity_files = n_ids;
2029 memcpy(options.identity_files, identity_files, sizeof(identity_files)); 2088 memcpy(options.identity_files, identity_files, sizeof(identity_files));
2030 memcpy(options.identity_keys, identity_keys, sizeof(identity_keys)); 2089 memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
2031 2090
2091 options.num_certificate_files = n_certs;
2092 memcpy(options.certificate_files,
2093 certificate_files, sizeof(certificate_files));
2094 memcpy(options.certificates, certificates, sizeof(certificates));
2095
2032 explicit_bzero(pwname, strlen(pwname)); 2096 explicit_bzero(pwname, strlen(pwname));
2033 free(pwname); 2097 free(pwname);
2034 explicit_bzero(pwdir, strlen(pwdir)); 2098 explicit_bzero(pwdir, strlen(pwdir));