1 /* $OpenBSD: readconf.c,v 1.381 2023/08/28 03:31:16 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * Functions for reading the configuration files.
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
17 #include <sys/types.h>
19 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <arpa/inet.h>
46 #ifdef USE_SYSTEM_GLOB
49 # include "openbsd-compat/glob.h"
54 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
62 #include "pathnames.h"
71 #include "myproposal.h"
74 /* Format of the configuration file:
76 # Configuration data is parsed as follows:
77 # 1. command line options
78 # 2. user-specific file
80 # Any configuration value is only changed the first time it is set.
81 # Thus, host-specific definitions should be at the beginning of the
82 # configuration file, and defaults at the end.
84 # Host-specific declarations. These may override anything above. A single
85 # host may match multiple declarations; these are processed in the order
86 # that they are given in.
92 Hostname another.host.name.real.org
99 RemoteForward 9999 shadows.cs.hut.fi:9999
102 Host fascist.blob.com
105 PasswordAuthentication no
109 ProxyCommand ssh-proxy %h %p
112 PublicKeyAuthentication no
116 PasswordAuthentication no
122 # Defaults for various options
126 PasswordAuthentication yes
127 StrictHostKeyChecking yes
129 IdentityFile ~/.ssh/identity
135 static int read_config_file_depth(const char *filename, struct passwd *pw,
136 const char *host, const char *original_host, Options *options,
137 int flags, int *activep, int *want_final_pass, int depth);
138 static int process_config_line_depth(Options *options, struct passwd *pw,
139 const char *host, const char *original_host, char *line,
140 const char *filename, int linenum, int *activep, int flags,
141 int *want_final_pass, int depth);
143 /* Keyword tokens. */
147 oHost, oMatch, oInclude, oTag,
148 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
149 oGatewayPorts, oExitOnForwardFailure,
150 oPasswordAuthentication,
152 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
154 oCertificateFile, oAddKeysToAgent, oIdentityAgent,
155 oUser, oEscapeChar, oProxyCommand,
156 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
157 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
158 oTCPKeepAlive, oNumberOfPasswordPrompts,
159 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
160 oPubkeyAuthentication,
161 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
162 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
163 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
164 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
165 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
166 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
167 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
168 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
170 oTunnel, oTunnelDevice,
171 oLocalCommand, oPermitLocalCommand, oRemoteCommand,
173 oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
174 oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
175 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
176 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
177 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
178 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
179 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
180 oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
181 oEnableEscapeCommandline, oObscureKeystrokeTiming,
182 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
185 /* Textual representations of the tokens. */
191 /* Deprecated options */
192 { "protocol", oIgnore }, /* NB. silently ignored */
193 { "cipher", oDeprecated },
194 { "fallbacktorsh", oDeprecated },
195 { "globalknownhostsfile2", oDeprecated },
196 { "rhostsauthentication", oDeprecated },
197 { "userknownhostsfile2", oDeprecated },
198 { "useroaming", oDeprecated },
199 { "usersh", oDeprecated },
200 { "useprivilegedport", oDeprecated },
202 /* Unsupported options */
203 { "afstokenpassing", oUnsupported },
204 { "kerberosauthentication", oUnsupported },
205 { "kerberostgtpassing", oUnsupported },
206 { "rsaauthentication", oUnsupported },
207 { "rhostsrsaauthentication", oUnsupported },
208 { "compressionlevel", oUnsupported },
210 /* Sometimes-unsupported options */
212 { "gssapiauthentication", oGssAuthentication },
213 { "gssapidelegatecredentials", oGssDelegateCreds },
215 { "gssapiauthentication", oUnsupported },
216 { "gssapidelegatecredentials", oUnsupported },
219 { "pkcs11provider", oPKCS11Provider },
220 { "smartcarddevice", oPKCS11Provider },
222 { "smartcarddevice", oUnsupported },
223 { "pkcs11provider", oUnsupported },
226 { "forwardagent", oForwardAgent },
227 { "forwardx11", oForwardX11 },
228 { "forwardx11trusted", oForwardX11Trusted },
229 { "forwardx11timeout", oForwardX11Timeout },
230 { "exitonforwardfailure", oExitOnForwardFailure },
231 { "xauthlocation", oXAuthLocation },
232 { "gatewayports", oGatewayPorts },
233 { "passwordauthentication", oPasswordAuthentication },
234 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
235 { "kbdinteractivedevices", oKbdInteractiveDevices },
236 { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
237 { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
238 { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */
239 { "pubkeyauthentication", oPubkeyAuthentication },
240 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
241 { "hostbasedauthentication", oHostbasedAuthentication },
242 { "identityfile", oIdentityFile },
243 { "identityfile2", oIdentityFile }, /* obsolete */
244 { "identitiesonly", oIdentitiesOnly },
245 { "certificatefile", oCertificateFile },
246 { "addkeystoagent", oAddKeysToAgent },
247 { "identityagent", oIdentityAgent },
248 { "hostname", oHostname },
249 { "hostkeyalias", oHostKeyAlias },
250 { "proxycommand", oProxyCommand },
252 { "ciphers", oCiphers },
254 { "remoteforward", oRemoteForward },
255 { "localforward", oLocalForward },
256 { "permitremoteopen", oPermitRemoteOpen },
261 { "escapechar", oEscapeChar },
262 { "globalknownhostsfile", oGlobalKnownHostsFile },
263 { "userknownhostsfile", oUserKnownHostsFile },
264 { "connectionattempts", oConnectionAttempts },
265 { "batchmode", oBatchMode },
266 { "checkhostip", oCheckHostIP },
267 { "stricthostkeychecking", oStrictHostKeyChecking },
268 { "compression", oCompression },
269 { "tcpkeepalive", oTCPKeepAlive },
270 { "keepalive", oTCPKeepAlive }, /* obsolete */
271 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
272 { "syslogfacility", oLogFacility },
273 { "loglevel", oLogLevel },
274 { "logverbose", oLogVerbose },
275 { "dynamicforward", oDynamicForward },
276 { "preferredauthentications", oPreferredAuthentications },
277 { "hostkeyalgorithms", oHostKeyAlgorithms },
278 { "casignaturealgorithms", oCASignatureAlgorithms },
279 { "bindaddress", oBindAddress },
280 { "bindinterface", oBindInterface },
281 { "clearallforwardings", oClearAllForwardings },
282 { "enablesshkeysign", oEnableSSHKeysign },
283 { "verifyhostkeydns", oVerifyHostKeyDNS },
284 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
285 { "rekeylimit", oRekeyLimit },
286 { "connecttimeout", oConnectTimeout },
287 { "addressfamily", oAddressFamily },
288 { "serveraliveinterval", oServerAliveInterval },
289 { "serveralivecountmax", oServerAliveCountMax },
290 { "sendenv", oSendEnv },
291 { "setenv", oSetEnv },
292 { "controlpath", oControlPath },
293 { "controlmaster", oControlMaster },
294 { "controlpersist", oControlPersist },
295 { "hashknownhosts", oHashKnownHosts },
296 { "include", oInclude },
297 { "tunnel", oTunnel },
298 { "tunneldevice", oTunnelDevice },
299 { "localcommand", oLocalCommand },
300 { "permitlocalcommand", oPermitLocalCommand },
301 { "remotecommand", oRemoteCommand },
302 { "visualhostkey", oVisualHostKey },
303 { "kexalgorithms", oKexAlgorithms },
305 { "requesttty", oRequestTTY },
306 { "sessiontype", oSessionType },
307 { "stdinnull", oStdinNull },
308 { "forkafterauthentication", oForkAfterAuthentication },
309 { "proxyusefdpass", oProxyUseFdpass },
310 { "canonicaldomains", oCanonicalDomains },
311 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
312 { "canonicalizehostname", oCanonicalizeHostname },
313 { "canonicalizemaxdots", oCanonicalizeMaxDots },
314 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
315 { "streamlocalbindmask", oStreamLocalBindMask },
316 { "streamlocalbindunlink", oStreamLocalBindUnlink },
317 { "revokedhostkeys", oRevokedHostKeys },
318 { "fingerprinthash", oFingerprintHash },
319 { "updatehostkeys", oUpdateHostkeys },
320 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
321 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
322 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
323 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
324 { "ignoreunknown", oIgnoreUnknown },
325 { "proxyjump", oProxyJump },
326 { "securitykeyprovider", oSecurityKeyProvider },
327 { "knownhostscommand", oKnownHostsCommand },
328 { "requiredrsasize", oRequiredRSASize },
329 { "enableescapecommandline", oEnableEscapeCommandline },
330 { "obscurekeystroketiming", oObscureKeystrokeTiming },
332 /* Client VersionAddendum - retired in bffe60ead024 */
333 { "versionaddendum", oDeprecated },
338 static const char *lookup_opcode_name(OpCodes code);
341 kex_default_pk_alg(void)
345 if (pkalgs == NULL) {
348 all_key = sshkey_alg_list(0, 0, 1, ',');
349 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
356 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
359 struct ssh_digest_ctx *md;
360 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
362 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
363 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
364 ssh_digest_update(md, host, strlen(host)) < 0 ||
365 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
366 ssh_digest_update(md, user, strlen(user)) < 0 ||
367 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
368 fatal_f("mux digest failed");
370 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
374 * Adds a local TCP/IP port forward to options. Never returns if there is an
379 add_local_forward(Options *options, const struct Forward *newfwd)
384 /* Don't add duplicates */
385 for (i = 0; i < options->num_local_forwards; i++) {
386 if (forward_equals(newfwd, options->local_forwards + i))
389 options->local_forwards = xreallocarray(options->local_forwards,
390 options->num_local_forwards + 1,
391 sizeof(*options->local_forwards));
392 fwd = &options->local_forwards[options->num_local_forwards++];
394 fwd->listen_host = newfwd->listen_host;
395 fwd->listen_port = newfwd->listen_port;
396 fwd->listen_path = newfwd->listen_path;
397 fwd->connect_host = newfwd->connect_host;
398 fwd->connect_port = newfwd->connect_port;
399 fwd->connect_path = newfwd->connect_path;
403 * Adds a remote TCP/IP port forward to options. Never returns if there is
408 add_remote_forward(Options *options, const struct Forward *newfwd)
413 /* Don't add duplicates */
414 for (i = 0; i < options->num_remote_forwards; i++) {
415 if (forward_equals(newfwd, options->remote_forwards + i))
418 options->remote_forwards = xreallocarray(options->remote_forwards,
419 options->num_remote_forwards + 1,
420 sizeof(*options->remote_forwards));
421 fwd = &options->remote_forwards[options->num_remote_forwards++];
423 fwd->listen_host = newfwd->listen_host;
424 fwd->listen_port = newfwd->listen_port;
425 fwd->listen_path = newfwd->listen_path;
426 fwd->connect_host = newfwd->connect_host;
427 fwd->connect_port = newfwd->connect_port;
428 fwd->connect_path = newfwd->connect_path;
429 fwd->handle = newfwd->handle;
430 fwd->allocated_port = 0;
434 clear_forwardings(Options *options)
438 for (i = 0; i < options->num_local_forwards; i++) {
439 free(options->local_forwards[i].listen_host);
440 free(options->local_forwards[i].listen_path);
441 free(options->local_forwards[i].connect_host);
442 free(options->local_forwards[i].connect_path);
444 if (options->num_local_forwards > 0) {
445 free(options->local_forwards);
446 options->local_forwards = NULL;
448 options->num_local_forwards = 0;
449 for (i = 0; i < options->num_remote_forwards; i++) {
450 free(options->remote_forwards[i].listen_host);
451 free(options->remote_forwards[i].listen_path);
452 free(options->remote_forwards[i].connect_host);
453 free(options->remote_forwards[i].connect_path);
455 if (options->num_remote_forwards > 0) {
456 free(options->remote_forwards);
457 options->remote_forwards = NULL;
459 options->num_remote_forwards = 0;
460 options->tun_open = SSH_TUNMODE_NO;
464 add_certificate_file(Options *options, const char *path, int userprovided)
468 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
469 fatal("Too many certificate files specified (max %d)",
470 SSH_MAX_CERTIFICATE_FILES);
472 /* Avoid registering duplicates */
473 for (i = 0; i < options->num_certificate_files; i++) {
474 if (options->certificate_file_userprovided[i] == userprovided &&
475 strcmp(options->certificate_files[i], path) == 0) {
476 debug2_f("ignoring duplicate key %s", path);
481 options->certificate_file_userprovided[options->num_certificate_files] =
483 options->certificate_files[options->num_certificate_files++] =
488 add_identity_file(Options *options, const char *dir, const char *filename,
494 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
495 fatal("Too many identity files specified (max %d)",
496 SSH_MAX_IDENTITY_FILES);
498 if (dir == NULL) /* no dir, filename is absolute */
499 path = xstrdup(filename);
500 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
501 fatal("Identity file path %s too long", path);
503 /* Avoid registering duplicates */
504 for (i = 0; i < options->num_identity_files; i++) {
505 if (options->identity_file_userprovided[i] == userprovided &&
506 strcmp(options->identity_files[i], path) == 0) {
507 debug2_f("ignoring duplicate key %s", path);
513 options->identity_file_userprovided[options->num_identity_files] =
515 options->identity_files[options->num_identity_files++] = path;
519 default_ssh_port(void)
525 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
526 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
532 * Execute a command in a shell.
533 * Return its exit status or -1 on abnormal exit.
536 execute_in_shell(const char *cmd)
542 if ((shell = getenv("SHELL")) == NULL)
543 shell = _PATH_BSHELL;
545 if (access(shell, X_OK) == -1) {
546 fatal("Shell \"%s\" is not executable: %s",
547 shell, strerror(errno));
550 debug("Executing command: '%.500s'", cmd);
552 /* Fork and execute the command. */
553 if ((pid = fork()) == 0) {
556 if (stdfd_devnull(1, 1, 0) == -1)
557 fatal_f("stdfd_devnull failed");
558 closefrom(STDERR_FILENO + 1);
562 argv[2] = xstrdup(cmd);
565 execv(argv[0], argv);
566 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
567 /* Die with signal to make this error apparent to parent. */
568 ssh_signal(SIGTERM, SIG_DFL);
569 kill(getpid(), SIGTERM);
574 fatal_f("fork: %.100s", strerror(errno));
576 while (waitpid(pid, &status, 0) == -1) {
577 if (errno != EINTR && errno != EAGAIN)
578 fatal_f("waitpid: %s", strerror(errno));
580 if (!WIFEXITED(status)) {
581 error("command '%.100s' exited abnormally", cmd);
584 debug3("command returned status %d", WEXITSTATUS(status));
585 return WEXITSTATUS(status);
589 * Check whether a local network interface address appears in CIDR pattern-
590 * list 'addrlist'. Returns 1 if matched or 0 otherwise.
593 check_match_ifaddrs(const char *addrlist)
595 #ifdef HAVE_IFADDRS_H
596 struct ifaddrs *ifa, *ifaddrs = NULL;
598 char addr[NI_MAXHOST];
601 if (getifaddrs(&ifaddrs) != 0) {
602 error("match localnetwork: getifaddrs failed: %s",
606 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
607 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
608 (ifa->ifa_flags & IFF_UP) == 0)
610 switch (ifa->ifa_addr->sa_family) {
612 salen = sizeof(struct sockaddr_in);
615 salen = sizeof(struct sockaddr_in6);
623 debug2_f("interface %s: unsupported address family %d",
624 ifa->ifa_name, ifa->ifa_addr->sa_family);
627 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
628 NULL, 0, NI_NUMERICHOST)) != 0) {
629 debug2_f("interface %s getnameinfo failed: %s",
630 ifa->ifa_name, gai_strerror(r));
633 debug3_f("interface %s addr %s", ifa->ifa_name, addr);
634 if (addr_match_cidr_list(addr, addrlist) == 1) {
635 debug3_f("matched interface %s: address %s in %s",
636 ifa->ifa_name, addr, addrlist);
641 freeifaddrs(ifaddrs);
643 #else /* HAVE_IFADDRS_H */
644 error("match localnetwork: not supported on this platform");
646 #endif /* HAVE_IFADDRS_H */
650 * Parse and execute a Match directive.
653 match_cfg_line(Options *options, char **condition, struct passwd *pw,
654 const char *host_arg, const char *original_host, int final_pass,
655 int *want_final_pass, const char *filename, int linenum)
657 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
659 int r, port, this_result, result = 1, attributes = 0, negate;
660 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
664 * Configuration is likely to be incomplete at this point so we
665 * must be prepared to use default values.
667 port = options->port <= 0 ? default_ssh_port() : options->port;
668 ruser = options->user == NULL ? pw->pw_name : options->user;
670 host = xstrdup(options->hostname);
671 } else if (options->hostname != NULL) {
672 /* NB. Please keep in sync with ssh.c:main() */
673 host = percent_expand(options->hostname,
674 "h", host_arg, (char *)NULL);
676 host = xstrdup(host_arg);
679 debug2("checking match for '%s' host %s originally %s",
680 cp, host, original_host);
681 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
682 /* Terminate on comment */
683 if (*attrib == '#') {
684 cp = NULL; /* mark all arguments consumed */
687 arg = criteria = NULL;
689 if ((negate = (attrib[0] == '!')))
691 /* Criterion "all" has no argument and must appear alone */
692 if (strcasecmp(attrib, "all") == 0) {
693 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
694 *arg != '\0' && *arg != '#')) {
695 error("%.200s line %d: '%s' cannot be combined "
696 "with other Match attributes",
697 filename, linenum, oattrib);
701 if (arg != NULL && *arg == '#')
702 cp = NULL; /* mark all arguments consumed */
704 result = negate ? 0 : 1;
708 /* criteria "final" and "canonical" have no argument */
709 if (strcasecmp(attrib, "canonical") == 0 ||
710 strcasecmp(attrib, "final") == 0) {
712 * If the config requests "Match final" then remember
713 * this so we can perform a second pass later.
715 if (strcasecmp(attrib, "final") == 0 &&
716 want_final_pass != NULL)
717 *want_final_pass = 1;
718 r = !!final_pass; /* force bitmask member to boolean */
719 if (r == (negate ? 1 : 0))
720 this_result = result = 0;
721 debug3("%.200s line %d: %smatched '%s'",
723 this_result ? "" : "not ", oattrib);
726 /* All other criteria require an argument */
727 if ((arg = strdelim(&cp)) == NULL ||
728 *arg == '\0' || *arg == '#') {
729 error("Missing Match criteria for %s", attrib);
733 if (strcasecmp(attrib, "host") == 0) {
734 criteria = xstrdup(host);
735 r = match_hostname(host, arg) == 1;
736 if (r == (negate ? 1 : 0))
737 this_result = result = 0;
738 } else if (strcasecmp(attrib, "originalhost") == 0) {
739 criteria = xstrdup(original_host);
740 r = match_hostname(original_host, arg) == 1;
741 if (r == (negate ? 1 : 0))
742 this_result = result = 0;
743 } else if (strcasecmp(attrib, "user") == 0) {
744 criteria = xstrdup(ruser);
745 r = match_pattern_list(ruser, arg, 0) == 1;
746 if (r == (negate ? 1 : 0))
747 this_result = result = 0;
748 } else if (strcasecmp(attrib, "localuser") == 0) {
749 criteria = xstrdup(pw->pw_name);
750 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
751 if (r == (negate ? 1 : 0))
752 this_result = result = 0;
753 } else if (strcasecmp(attrib, "localnetwork") == 0) {
754 if (addr_match_cidr_list(NULL, arg) == -1) {
755 /* Error already printed */
759 r = check_match_ifaddrs(arg) == 1;
760 if (r == (negate ? 1 : 0))
761 this_result = result = 0;
762 } else if (strcasecmp(attrib, "tagged") == 0) {
763 criteria = xstrdup(options->tag == NULL ? "" :
765 r = match_pattern_list(criteria, arg, 0) == 1;
766 if (r == (negate ? 1 : 0))
767 this_result = result = 0;
768 } else if (strcasecmp(attrib, "exec") == 0) {
769 char *conn_hash_hex, *keyalias;
771 if (gethostname(thishost, sizeof(thishost)) == -1)
772 fatal("gethostname: %s", strerror(errno));
773 strlcpy(shorthost, thishost, sizeof(shorthost));
774 shorthost[strcspn(thishost, ".")] = '\0';
775 snprintf(portstr, sizeof(portstr), "%d", port);
776 snprintf(uidstr, sizeof(uidstr), "%llu",
777 (unsigned long long)pw->pw_uid);
778 conn_hash_hex = ssh_connection_hash(thishost, host,
780 keyalias = options->host_key_alias ?
781 options->host_key_alias : host;
783 cmd = percent_expand(arg,
798 /* skip execution if prior predicate failed */
799 debug3("%.200s line %d: skipped exec "
800 "\"%.100s\"", filename, linenum, cmd);
804 r = execute_in_shell(cmd);
806 fatal("%.200s line %d: match exec "
807 "'%.100s' error", filename,
810 criteria = xstrdup(cmd);
812 /* Force exit status to boolean */
814 if (r == (negate ? 1 : 0))
815 this_result = result = 0;
817 error("Unsupported Match attribute %s", attrib);
821 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
822 filename, linenum, this_result ? "": "not ", oattrib,
823 criteria == NULL ? "" : " \"",
824 criteria == NULL ? "" : criteria,
825 criteria == NULL ? "" : "\"");
828 if (attributes == 0) {
829 error("One or more attributes required for Match");
835 debug2("match %sfound", result ? "" : "not ");
841 /* Remove environment variable by pattern */
843 rm_env(Options *options, const char *arg, const char *filename, int linenum)
845 u_int i, j, onum_send_env = options->num_send_env;
847 /* Remove an environment variable */
848 for (i = 0; i < options->num_send_env; ) {
849 if (!match_pattern(options->send_env[i], arg + 1)) {
853 debug3("%s line %d: removing environment %s",
854 filename, linenum, options->send_env[i]);
855 free(options->send_env[i]);
856 options->send_env[i] = NULL;
857 for (j = i; j < options->num_send_env - 1; j++) {
858 options->send_env[j] = options->send_env[j + 1];
859 options->send_env[j + 1] = NULL;
861 options->num_send_env--;
862 /* NB. don't increment i */
864 if (onum_send_env != options->num_send_env) {
865 options->send_env = xrecallocarray(options->send_env,
866 onum_send_env, options->num_send_env,
867 sizeof(*options->send_env));
872 * Returns the number of the token pointed to by cp or oBadOption.
875 parse_token(const char *cp, const char *filename, int linenum,
876 const char *ignored_unknown)
880 for (i = 0; keywords[i].name; i++)
881 if (strcmp(cp, keywords[i].name) == 0)
882 return keywords[i].opcode;
883 if (ignored_unknown != NULL &&
884 match_pattern_list(cp, ignored_unknown, 1) == 1)
885 return oIgnoredUnknownOption;
886 error("%s: line %d: Bad configuration option: %s",
887 filename, linenum, cp);
891 /* Multistate option parsing */
896 static const struct multistate multistate_flag[] = {
903 static const struct multistate multistate_yesnoask[] = {
911 static const struct multistate multistate_strict_hostkey[] = {
912 { "true", SSH_STRICT_HOSTKEY_YES },
913 { "false", SSH_STRICT_HOSTKEY_OFF },
914 { "yes", SSH_STRICT_HOSTKEY_YES },
915 { "no", SSH_STRICT_HOSTKEY_OFF },
916 { "ask", SSH_STRICT_HOSTKEY_ASK },
917 { "off", SSH_STRICT_HOSTKEY_OFF },
918 { "accept-new", SSH_STRICT_HOSTKEY_NEW },
921 static const struct multistate multistate_yesnoaskconfirm[] = {
930 static const struct multistate multistate_addressfamily[] = {
932 { "inet6", AF_INET6 },
933 { "any", AF_UNSPEC },
936 static const struct multistate multistate_controlmaster[] = {
937 { "true", SSHCTL_MASTER_YES },
938 { "yes", SSHCTL_MASTER_YES },
939 { "false", SSHCTL_MASTER_NO },
940 { "no", SSHCTL_MASTER_NO },
941 { "auto", SSHCTL_MASTER_AUTO },
942 { "ask", SSHCTL_MASTER_ASK },
943 { "autoask", SSHCTL_MASTER_AUTO_ASK },
946 static const struct multistate multistate_tunnel[] = {
947 { "ethernet", SSH_TUNMODE_ETHERNET },
948 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
949 { "true", SSH_TUNMODE_DEFAULT },
950 { "yes", SSH_TUNMODE_DEFAULT },
951 { "false", SSH_TUNMODE_NO },
952 { "no", SSH_TUNMODE_NO },
955 static const struct multistate multistate_requesttty[] = {
956 { "true", REQUEST_TTY_YES },
957 { "yes", REQUEST_TTY_YES },
958 { "false", REQUEST_TTY_NO },
959 { "no", REQUEST_TTY_NO },
960 { "force", REQUEST_TTY_FORCE },
961 { "auto", REQUEST_TTY_AUTO },
964 static const struct multistate multistate_sessiontype[] = {
965 { "none", SESSION_TYPE_NONE },
966 { "subsystem", SESSION_TYPE_SUBSYSTEM },
967 { "default", SESSION_TYPE_DEFAULT },
970 static const struct multistate multistate_canonicalizehostname[] = {
971 { "true", SSH_CANONICALISE_YES },
972 { "false", SSH_CANONICALISE_NO },
973 { "yes", SSH_CANONICALISE_YES },
974 { "no", SSH_CANONICALISE_NO },
975 { "always", SSH_CANONICALISE_ALWAYS },
978 static const struct multistate multistate_pubkey_auth[] = {
979 { "true", SSH_PUBKEY_AUTH_ALL },
980 { "false", SSH_PUBKEY_AUTH_NO },
981 { "yes", SSH_PUBKEY_AUTH_ALL },
982 { "no", SSH_PUBKEY_AUTH_NO },
983 { "unbound", SSH_PUBKEY_AUTH_UNBOUND },
984 { "host-bound", SSH_PUBKEY_AUTH_HBOUND },
987 static const struct multistate multistate_compression[] = {
989 { "yes", COMP_ZLIB },
996 parse_multistate_value(const char *arg, const char *filename, int linenum,
997 const struct multistate *multistate_ptr)
1001 if (!arg || *arg == '\0') {
1002 error("%s line %d: missing argument.", filename, linenum);
1005 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1006 if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1007 return multistate_ptr[i].value;
1013 * Processes a single option line as used in the configuration files. This
1014 * only sets those values that have not already been set.
1017 process_config_line(Options *options, struct passwd *pw, const char *host,
1018 const char *original_host, char *line, const char *filename,
1019 int linenum, int *activep, int flags)
1021 return process_config_line_depth(options, pw, host, original_host,
1022 line, filename, linenum, activep, flags, NULL, 0);
1025 #define WHITESPACE " \t\r\n"
1027 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1028 const char *original_host, char *line, const char *filename,
1029 int linenum, int *activep, int flags, int *want_final_pass, int depth)
1031 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1032 char **cpptr, ***cppptr, fwdarg[256];
1033 u_int i, *uintptr, uvalue, max_entries = 0;
1034 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1035 int remotefwd, dynamicfwd, ca_only = 0;
1036 LogLevel *log_level_ptr;
1037 SyslogFacility *log_facility_ptr;
1041 const struct multistate *multistate_ptr;
1042 struct allowed_cname *cname;
1045 char **oav = NULL, **av;
1049 if (activep == NULL) { /* We are processing a command line directive */
1054 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1055 if ((len = strlen(line)) == 0)
1057 for (len--; len > 0; len--) {
1058 if (strchr(WHITESPACE "\f", line[len]) == NULL)
1064 /* Get the keyword. (Each line is supposed to begin with a keyword). */
1065 if ((keyword = strdelim(&str)) == NULL)
1067 /* Ignore leading whitespace. */
1068 if (*keyword == '\0')
1069 keyword = strdelim(&str);
1070 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1072 /* Match lowercase keyword */
1075 /* Prepare to parse remainder of line */
1077 str += strspn(str, WHITESPACE);
1078 if (str == NULL || *str == '\0') {
1079 error("%s line %d: no argument after keyword \"%s\"",
1080 filename, linenum, keyword);
1083 opcode = parse_token(keyword, filename, linenum,
1084 options->ignored_unknown);
1085 if (argv_split(str, &oac, &oav, 1) != 0) {
1086 error("%s line %d: invalid quotes", filename, linenum);
1094 /* don't panic, but count bad options */
1099 case oIgnoredUnknownOption:
1100 debug("%s line %d: Ignored unknown option \"%s\"",
1101 filename, linenum, keyword);
1104 case oConnectTimeout:
1105 intptr = &options->connection_timeout;
1107 arg = argv_next(&ac, &av);
1108 if (!arg || *arg == '\0') {
1109 error("%s line %d: missing time value.",
1113 if (strcmp(arg, "none") == 0)
1115 else if ((value = convtime(arg)) == -1) {
1116 error("%s line %d: invalid time value.",
1120 if (*activep && *intptr == -1)
1125 intptr = &options->forward_agent;
1127 arg = argv_next(&ac, &av);
1128 if (!arg || *arg == '\0') {
1129 error("%s line %d: missing argument.",
1135 multistate_ptr = multistate_flag;
1136 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1137 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1138 value = multistate_ptr[i].value;
1143 if (*activep && *intptr == -1)
1147 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1148 if (*activep && *intptr == -1)
1151 charptr = &options->forward_agent_sock_path;
1152 goto parse_agent_path;
1155 intptr = &options->forward_x11;
1157 multistate_ptr = multistate_flag;
1159 arg = argv_next(&ac, &av);
1160 if ((value = parse_multistate_value(arg, filename, linenum,
1161 multistate_ptr)) == -1) {
1162 error("%s line %d: unsupported option \"%s\".",
1163 filename, linenum, arg);
1166 if (*activep && *intptr == -1)
1170 case oForwardX11Trusted:
1171 intptr = &options->forward_x11_trusted;
1174 case oForwardX11Timeout:
1175 intptr = &options->forward_x11_timeout;
1179 intptr = &options->fwd_opts.gateway_ports;
1182 case oExitOnForwardFailure:
1183 intptr = &options->exit_on_forward_failure;
1186 case oPasswordAuthentication:
1187 intptr = &options->password_authentication;
1190 case oKbdInteractiveAuthentication:
1191 intptr = &options->kbd_interactive_authentication;
1194 case oKbdInteractiveDevices:
1195 charptr = &options->kbd_interactive_devices;
1198 case oPubkeyAuthentication:
1199 multistate_ptr = multistate_pubkey_auth;
1200 intptr = &options->pubkey_authentication;
1201 goto parse_multistate;
1203 case oHostbasedAuthentication:
1204 intptr = &options->hostbased_authentication;
1207 case oGssAuthentication:
1208 intptr = &options->gss_authentication;
1211 case oGssDelegateCreds:
1212 intptr = &options->gss_deleg_creds;
1216 intptr = &options->batch_mode;
1220 intptr = &options->check_host_ip;
1223 case oVerifyHostKeyDNS:
1224 intptr = &options->verify_host_key_dns;
1225 multistate_ptr = multistate_yesnoask;
1226 goto parse_multistate;
1228 case oStrictHostKeyChecking:
1229 intptr = &options->strict_host_key_checking;
1230 multistate_ptr = multistate_strict_hostkey;
1231 goto parse_multistate;
1234 intptr = &options->compression;
1235 multistate_ptr = multistate_compression;
1236 goto parse_multistate;
1239 intptr = &options->tcp_keep_alive;
1242 case oNoHostAuthenticationForLocalhost:
1243 intptr = &options->no_host_authentication_for_localhost;
1246 case oNumberOfPasswordPrompts:
1247 intptr = &options->number_of_password_prompts;
1251 arg = argv_next(&ac, &av);
1252 if (!arg || *arg == '\0') {
1253 error("%.200s line %d: Missing argument.", filename,
1257 if (strcmp(arg, "default") == 0) {
1260 if (scan_scaled(arg, &val64) == -1) {
1261 error("%.200s line %d: Bad number '%s': %s",
1262 filename, linenum, arg, strerror(errno));
1265 if (val64 != 0 && val64 < 16) {
1266 error("%.200s line %d: RekeyLimit too small",
1271 if (*activep && options->rekey_limit == -1)
1272 options->rekey_limit = val64;
1273 if (ac != 0) { /* optional rekey interval present */
1274 if (strcmp(av[0], "none") == 0) {
1275 (void)argv_next(&ac, &av); /* discard */
1278 intptr = &options->rekey_interval;
1284 arg = argv_next(&ac, &av);
1285 if (!arg || *arg == '\0') {
1286 error("%.200s line %d: Missing argument.",
1291 intptr = &options->num_identity_files;
1292 if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1293 error("%.200s line %d: Too many identity files "
1294 "specified (max %d).", filename, linenum,
1295 SSH_MAX_IDENTITY_FILES);
1298 add_identity_file(options, NULL,
1299 arg, flags & SSHCONF_USERCONF);
1303 case oCertificateFile:
1304 arg = argv_next(&ac, &av);
1305 if (!arg || *arg == '\0') {
1306 error("%.200s line %d: Missing argument.",
1311 intptr = &options->num_certificate_files;
1312 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1313 error("%.200s line %d: Too many certificate "
1314 "files specified (max %d).",
1316 SSH_MAX_CERTIFICATE_FILES);
1319 add_certificate_file(options, arg,
1320 flags & SSHCONF_USERCONF);
1324 case oXAuthLocation:
1325 charptr=&options->xauth_location;
1329 charptr = &options->user;
1331 arg = argv_next(&ac, &av);
1332 if (!arg || *arg == '\0') {
1333 error("%.200s line %d: Missing argument.",
1337 if (*activep && *charptr == NULL)
1338 *charptr = xstrdup(arg);
1341 case oGlobalKnownHostsFile:
1342 cpptr = (char **)&options->system_hostfiles;
1343 uintptr = &options->num_system_hostfiles;
1344 max_entries = SSH_MAX_HOSTS_FILES;
1347 value = *uintptr == 0; /* was array empty when we started? */
1348 while ((arg = argv_next(&ac, &av)) != NULL) {
1350 error("%s line %d: keyword %s empty argument",
1351 filename, linenum, keyword);
1354 /* Allow "none" only in first position */
1355 if (strcasecmp(arg, "none") == 0) {
1356 if (i > 0 || ac > 0) {
1357 error("%s line %d: keyword %s \"none\" "
1358 "argument must appear alone.",
1359 filename, linenum, keyword);
1364 if (*activep && value) {
1365 if ((*uintptr) >= max_entries) {
1366 error("%s line %d: too many %s "
1367 "entries.", filename, linenum,
1371 cpptr[(*uintptr)++] = xstrdup(arg);
1376 case oUserKnownHostsFile:
1377 cpptr = (char **)&options->user_hostfiles;
1378 uintptr = &options->num_user_hostfiles;
1379 max_entries = SSH_MAX_HOSTS_FILES;
1380 goto parse_char_array;
1383 charptr = &options->hostname;
1387 charptr = &options->tag;
1391 charptr = &options->host_key_alias;
1394 case oPreferredAuthentications:
1395 charptr = &options->preferred_authentications;
1399 charptr = &options->bind_address;
1402 case oBindInterface:
1403 charptr = &options->bind_interface;
1406 case oPKCS11Provider:
1407 charptr = &options->pkcs11_provider;
1410 case oSecurityKeyProvider:
1411 charptr = &options->sk_provider;
1414 case oKnownHostsCommand:
1415 charptr = &options->known_hosts_command;
1419 charptr = &options->proxy_command;
1420 /* Ignore ProxyCommand if ProxyJump already specified */
1421 if (options->jump_host != NULL)
1422 charptr = &options->jump_host; /* Skip below */
1425 error("%.200s line %d: Missing argument.",
1429 len = strspn(str, WHITESPACE "=");
1430 if (*activep && *charptr == NULL)
1431 *charptr = xstrdup(str + len);
1437 error("%.200s line %d: Missing argument.",
1441 len = strspn(str, WHITESPACE "=");
1443 if (parse_jump(str + len, options, *activep) == -1) {
1444 error("%.200s line %d: Invalid ProxyJump \"%s\"",
1445 filename, linenum, str + len);
1452 arg = argv_next(&ac, &av);
1453 if (!arg || *arg == '\0') {
1454 error("%.200s line %d: Missing argument.",
1458 value = a2port(arg);
1460 error("%.200s line %d: Bad port '%s'.",
1461 filename, linenum, arg);
1464 if (*activep && options->port == -1)
1465 options->port = value;
1468 case oConnectionAttempts:
1469 intptr = &options->connection_attempts;
1471 arg = argv_next(&ac, &av);
1472 if ((errstr = atoi_err(arg, &value)) != NULL) {
1473 error("%s line %d: integer value %s.",
1474 filename, linenum, errstr);
1477 if (*activep && *intptr == -1)
1482 arg = argv_next(&ac, &av);
1483 if (!arg || *arg == '\0') {
1484 error("%.200s line %d: Missing argument.",
1489 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1490 error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1491 filename, linenum, arg ? arg : "<NONE>");
1494 if (*activep && options->ciphers == NULL)
1495 options->ciphers = xstrdup(arg);
1499 arg = argv_next(&ac, &av);
1500 if (!arg || *arg == '\0') {
1501 error("%.200s line %d: Missing argument.",
1506 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1507 error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1508 filename, linenum, arg ? arg : "<NONE>");
1511 if (*activep && options->macs == NULL)
1512 options->macs = xstrdup(arg);
1515 case oKexAlgorithms:
1516 arg = argv_next(&ac, &av);
1517 if (!arg || *arg == '\0') {
1518 error("%.200s line %d: Missing argument.",
1523 !kex_names_valid(*arg == '+' || *arg == '^' ?
1525 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1526 filename, linenum, arg ? arg : "<NONE>");
1529 if (*activep && options->kex_algorithms == NULL)
1530 options->kex_algorithms = xstrdup(arg);
1533 case oHostKeyAlgorithms:
1534 charptr = &options->hostkeyalgorithms;
1537 arg = argv_next(&ac, &av);
1538 if (!arg || *arg == '\0') {
1539 error("%.200s line %d: Missing argument.",
1544 !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1545 arg + 1 : arg, 1, ca_only)) {
1546 error("%s line %d: Bad key types '%s'.",
1547 filename, linenum, arg ? arg : "<NONE>");
1550 if (*activep && *charptr == NULL)
1551 *charptr = xstrdup(arg);
1554 case oCASignatureAlgorithms:
1555 charptr = &options->ca_sign_algorithms;
1557 goto parse_pubkey_algos;
1560 log_level_ptr = &options->log_level;
1561 arg = argv_next(&ac, &av);
1562 value = log_level_number(arg);
1563 if (value == SYSLOG_LEVEL_NOT_SET) {
1564 error("%.200s line %d: unsupported log level '%s'",
1565 filename, linenum, arg ? arg : "<NONE>");
1568 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1569 *log_level_ptr = (LogLevel) value;
1573 log_facility_ptr = &options->log_facility;
1574 arg = argv_next(&ac, &av);
1575 value = log_facility_number(arg);
1576 if (value == SYSLOG_FACILITY_NOT_SET) {
1577 error("%.200s line %d: unsupported log facility '%s'",
1578 filename, linenum, arg ? arg : "<NONE>");
1581 if (*log_facility_ptr == -1)
1582 *log_facility_ptr = (SyslogFacility) value;
1586 cppptr = &options->log_verbose;
1587 uintptr = &options->num_log_verbose;
1589 while ((arg = argv_next(&ac, &av)) != NULL) {
1591 error("%s line %d: keyword %s empty argument",
1592 filename, linenum, keyword);
1595 /* Allow "none" only in first position */
1596 if (strcasecmp(arg, "none") == 0) {
1597 if (i > 0 || ac > 0) {
1598 error("%s line %d: keyword %s \"none\" "
1599 "argument must appear alone.",
1600 filename, linenum, keyword);
1605 if (*activep && *uintptr == 0) {
1606 *cppptr = xrecallocarray(*cppptr, *uintptr,
1607 *uintptr + 1, sizeof(**cppptr));
1608 (*cppptr)[(*uintptr)++] = xstrdup(arg);
1614 case oRemoteForward:
1615 case oDynamicForward:
1616 arg = argv_next(&ac, &av);
1617 if (!arg || *arg == '\0') {
1618 error("%.200s line %d: Missing argument.",
1623 remotefwd = (opcode == oRemoteForward);
1624 dynamicfwd = (opcode == oDynamicForward);
1627 arg2 = argv_next(&ac, &av);
1628 if (arg2 == NULL || *arg2 == '\0') {
1632 error("%.200s line %d: Missing target "
1633 "argument.", filename, linenum);
1637 /* construct a string for parse_forward */
1638 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1643 strlcpy(fwdarg, arg, sizeof(fwdarg));
1645 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1646 error("%.200s line %d: Bad forwarding specification.",
1653 add_remote_forward(options, &fwd);
1655 add_local_forward(options, &fwd);
1660 case oPermitRemoteOpen:
1661 uintptr = &options->num_permitted_remote_opens;
1662 cppptr = &options->permitted_remote_opens;
1663 uvalue = *uintptr; /* modified later */
1665 while ((arg = argv_next(&ac, &av)) != NULL) {
1666 arg2 = xstrdup(arg);
1667 /* Allow any/none only in first position */
1668 if (strcasecmp(arg, "none") == 0 ||
1669 strcasecmp(arg, "any") == 0) {
1670 if (i > 0 || ac > 0) {
1671 error("%s line %d: keyword %s \"%s\" "
1672 "argument must appear alone.",
1673 filename, linenum, keyword, arg);
1680 fatal("%s line %d: missing host in %s",
1682 lookup_opcode_name(opcode));
1684 p = cleanhostname(p);
1686 * don't want to use permitopen_port to avoid
1687 * dependency on channels.[ch] here.
1689 if (arg == NULL || (strcmp(arg, "*") != 0 &&
1690 a2port(arg) <= 0)) {
1691 fatal("%s line %d: bad port number "
1692 "in %s", filename, linenum,
1693 lookup_opcode_name(opcode));
1696 if (*activep && uvalue == 0) {
1697 opt_array_append(filename, linenum,
1698 lookup_opcode_name(opcode),
1699 cppptr, uintptr, arg2);
1705 fatal("%s line %d: missing %s specification",
1706 filename, linenum, lookup_opcode_name(opcode));
1709 case oClearAllForwardings:
1710 intptr = &options->clear_forwardings;
1715 error("Host directive not supported as a command-line "
1721 while ((arg = argv_next(&ac, &av)) != NULL) {
1723 error("%s line %d: keyword %s empty argument",
1724 filename, linenum, keyword);
1727 if ((flags & SSHCONF_NEVERMATCH) != 0) {
1731 negated = *arg == '!';
1734 if (match_pattern(host, arg)) {
1736 debug("%.200s line %d: Skipping Host "
1737 "block because of negated match "
1738 "for %.100s", filename, linenum,
1745 arg2 = arg; /* logged below */
1750 debug("%.200s line %d: Applying options for %.100s",
1751 filename, linenum, arg2);
1756 error("Host directive not supported as a command-line "
1760 value = match_cfg_line(options, &str, pw, host, original_host,
1761 flags & SSHCONF_FINAL, want_final_pass,
1764 error("%.200s line %d: Bad Match condition", filename,
1768 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1770 * If match_cfg_line() didn't consume all its arguments then
1771 * arrange for the extra arguments check below to fail.
1774 if (str == NULL || *str == '\0')
1779 intptr = &options->escape_char;
1780 arg = argv_next(&ac, &av);
1781 if (!arg || *arg == '\0') {
1782 error("%.200s line %d: Missing argument.",
1786 if (strcmp(arg, "none") == 0)
1787 value = SSH_ESCAPECHAR_NONE;
1788 else if (arg[1] == '\0')
1789 value = (u_char) arg[0];
1790 else if (arg[0] == '^' && arg[2] == 0 &&
1791 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1792 value = (u_char) arg[1] & 31;
1794 error("%.200s line %d: Bad escape character.",
1798 if (*activep && *intptr == -1)
1802 case oAddressFamily:
1803 intptr = &options->address_family;
1804 multistate_ptr = multistate_addressfamily;
1805 goto parse_multistate;
1807 case oEnableSSHKeysign:
1808 intptr = &options->enable_ssh_keysign;
1811 case oIdentitiesOnly:
1812 intptr = &options->identities_only;
1815 case oServerAliveInterval:
1816 intptr = &options->server_alive_interval;
1819 case oServerAliveCountMax:
1820 intptr = &options->server_alive_count_max;
1824 while ((arg = argv_next(&ac, &av)) != NULL) {
1825 if (*arg == '\0' || strchr(arg, '=') != NULL) {
1826 error("%s line %d: Invalid environment name.",
1833 /* Removing an env var */
1834 rm_env(options, arg, filename, linenum);
1837 opt_array_append(filename, linenum,
1838 lookup_opcode_name(opcode),
1839 &options->send_env, &options->num_send_env, arg);
1844 value = options->num_setenv;
1845 while ((arg = argv_next(&ac, &av)) != NULL) {
1846 if (strchr(arg, '=') == NULL) {
1847 error("%s line %d: Invalid SetEnv.",
1851 if (!*activep || value != 0)
1853 if (lookup_setenv_in_list(arg, options->setenv,
1854 options->num_setenv) != NULL) {
1855 debug2("%s line %d: ignoring duplicate env "
1856 "name \"%.64s\"", filename, linenum, arg);
1859 opt_array_append(filename, linenum,
1860 lookup_opcode_name(opcode),
1861 &options->setenv, &options->num_setenv, arg);
1866 charptr = &options->control_path;
1869 case oControlMaster:
1870 intptr = &options->control_master;
1871 multistate_ptr = multistate_controlmaster;
1872 goto parse_multistate;
1874 case oControlPersist:
1875 /* no/false/yes/true, or a time spec */
1876 intptr = &options->control_persist;
1877 arg = argv_next(&ac, &av);
1878 if (!arg || *arg == '\0') {
1879 error("%.200s line %d: Missing ControlPersist"
1880 " argument.", filename, linenum);
1884 value2 = 0; /* timeout */
1885 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1887 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1889 else if ((value2 = convtime(arg)) >= 0)
1892 error("%.200s line %d: Bad ControlPersist argument.",
1896 if (*activep && *intptr == -1) {
1898 options->control_persist_timeout = value2;
1902 case oHashKnownHosts:
1903 intptr = &options->hash_known_hosts;
1907 intptr = &options->tun_open;
1908 multistate_ptr = multistate_tunnel;
1909 goto parse_multistate;
1912 arg = argv_next(&ac, &av);
1913 if (!arg || *arg == '\0') {
1914 error("%.200s line %d: Missing argument.",
1918 value = a2tun(arg, &value2);
1919 if (value == SSH_TUNID_ERR) {
1920 error("%.200s line %d: Bad tun device.",
1924 if (*activep && options->tun_local == -1) {
1925 options->tun_local = value;
1926 options->tun_remote = value2;
1931 charptr = &options->local_command;
1934 case oPermitLocalCommand:
1935 intptr = &options->permit_local_command;
1938 case oRemoteCommand:
1939 charptr = &options->remote_command;
1942 case oVisualHostKey:
1943 intptr = &options->visual_host_key;
1948 error("Include directive not supported as a "
1949 "command-line option");
1953 while ((arg = argv_next(&ac, &av)) != NULL) {
1955 error("%s line %d: keyword %s empty argument",
1956 filename, linenum, keyword);
1960 * Ensure all paths are anchored. User configuration
1961 * files may begin with '~/' but system configurations
1962 * must not. If the path is relative, then treat it
1963 * as living in ~/.ssh for user configurations or
1964 * /etc/ssh for system ones.
1966 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1967 error("%.200s line %d: bad include path %s.",
1968 filename, linenum, arg);
1971 if (!path_absolute(arg) && *arg != '~') {
1972 xasprintf(&arg2, "%s/%s",
1973 (flags & SSHCONF_USERCONF) ?
1974 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1976 arg2 = xstrdup(arg);
1977 memset(&gl, 0, sizeof(gl));
1978 r = glob(arg2, GLOB_TILDE, NULL, &gl);
1979 if (r == GLOB_NOMATCH) {
1980 debug("%.200s line %d: include %s matched no "
1981 "files",filename, linenum, arg2);
1984 } else if (r != 0) {
1985 error("%.200s line %d: glob failed for %s.",
1986 filename, linenum, arg2);
1991 for (i = 0; i < gl.gl_pathc; i++) {
1992 debug3("%.200s line %d: Including file %s "
1993 "depth %d%s", filename, linenum,
1994 gl.gl_pathv[i], depth,
1995 oactive ? "" : " (parse only)");
1996 r = read_config_file_depth(gl.gl_pathv[i],
1997 pw, host, original_host, options,
1998 flags | SSHCONF_CHECKPERM |
1999 (oactive ? 0 : SSHCONF_NEVERMATCH),
2000 activep, want_final_pass, depth + 1);
2001 if (r != 1 && errno != ENOENT) {
2002 error("Can't open user config file "
2003 "%.100s: %.100s", gl.gl_pathv[i],
2009 * don't let Match in includes clobber the
2010 * containing file's Match state.
2023 arg = argv_next(&ac, &av);
2024 if ((value = parse_ipqos(arg)) == -1) {
2025 error("%s line %d: Bad IPQoS value: %s",
2026 filename, linenum, arg);
2029 arg = argv_next(&ac, &av);
2032 else if ((value2 = parse_ipqos(arg)) == -1) {
2033 error("%s line %d: Bad IPQoS value: %s",
2034 filename, linenum, arg);
2037 if (*activep && options->ip_qos_interactive == -1) {
2038 options->ip_qos_interactive = value;
2039 options->ip_qos_bulk = value2;
2044 intptr = &options->request_tty;
2045 multistate_ptr = multistate_requesttty;
2046 goto parse_multistate;
2049 intptr = &options->session_type;
2050 multistate_ptr = multistate_sessiontype;
2051 goto parse_multistate;
2054 intptr = &options->stdin_null;
2057 case oForkAfterAuthentication:
2058 intptr = &options->fork_after_authentication;
2061 case oIgnoreUnknown:
2062 charptr = &options->ignored_unknown;
2065 case oProxyUseFdpass:
2066 intptr = &options->proxy_use_fdpass;
2069 case oCanonicalDomains:
2070 value = options->num_canonical_domains != 0;
2072 while ((arg = argv_next(&ac, &av)) != NULL) {
2074 error("%s line %d: keyword %s empty argument",
2075 filename, linenum, keyword);
2078 /* Allow "none" only in first position */
2079 if (strcasecmp(arg, "none") == 0) {
2080 if (i > 0 || ac > 0) {
2081 error("%s line %d: keyword %s \"none\" "
2082 "argument must appear alone.",
2083 filename, linenum, keyword);
2088 if (!valid_domain(arg, 1, &errstr)) {
2089 error("%s line %d: %s", filename, linenum,
2093 if (!*activep || value)
2095 if (options->num_canonical_domains >=
2096 MAX_CANON_DOMAINS) {
2097 error("%s line %d: too many hostname suffixes.",
2101 options->canonical_domains[
2102 options->num_canonical_domains++] = xstrdup(arg);
2106 case oCanonicalizePermittedCNAMEs:
2107 value = options->num_permitted_cnames != 0;
2109 while ((arg = argv_next(&ac, &av)) != NULL) {
2111 * Either 'none' (only in first position), '*' for
2112 * everything or 'list:list'
2114 if (strcasecmp(arg, "none") == 0) {
2115 if (i > 0 || ac > 0) {
2116 error("%s line %d: keyword %s \"none\" "
2117 "argument must appear alone.",
2118 filename, linenum, keyword);
2122 } else if (strcmp(arg, "*") == 0) {
2126 if ((arg2 = strchr(arg, ':')) == NULL ||
2128 error("%s line %d: "
2129 "Invalid permitted CNAME \"%s\"",
2130 filename, linenum, arg);
2137 if (!*activep || value)
2139 if (options->num_permitted_cnames >=
2140 MAX_CANON_DOMAINS) {
2141 error("%s line %d: too many permitted CNAMEs.",
2145 cname = options->permitted_cnames +
2146 options->num_permitted_cnames++;
2147 cname->source_list = xstrdup(arg);
2148 cname->target_list = xstrdup(arg2);
2152 case oCanonicalizeHostname:
2153 intptr = &options->canonicalize_hostname;
2154 multistate_ptr = multistate_canonicalizehostname;
2155 goto parse_multistate;
2157 case oCanonicalizeMaxDots:
2158 intptr = &options->canonicalize_max_dots;
2161 case oCanonicalizeFallbackLocal:
2162 intptr = &options->canonicalize_fallback_local;
2165 case oStreamLocalBindMask:
2166 arg = argv_next(&ac, &av);
2167 if (!arg || *arg == '\0') {
2168 error("%.200s line %d: Missing StreamLocalBindMask "
2169 "argument.", filename, linenum);
2172 /* Parse mode in octal format */
2173 value = strtol(arg, &endofnumber, 8);
2174 if (arg == endofnumber || value < 0 || value > 0777) {
2175 error("%.200s line %d: Bad mask.", filename, linenum);
2178 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2181 case oStreamLocalBindUnlink:
2182 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2185 case oRevokedHostKeys:
2186 charptr = &options->revoked_host_keys;
2189 case oFingerprintHash:
2190 intptr = &options->fingerprint_hash;
2191 arg = argv_next(&ac, &av);
2192 if (!arg || *arg == '\0') {
2193 error("%.200s line %d: Missing argument.",
2197 if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2198 error("%.200s line %d: Invalid hash algorithm \"%s\".",
2199 filename, linenum, arg);
2202 if (*activep && *intptr == -1)
2206 case oUpdateHostkeys:
2207 intptr = &options->update_hostkeys;
2208 multistate_ptr = multistate_yesnoask;
2209 goto parse_multistate;
2211 case oHostbasedAcceptedAlgorithms:
2212 charptr = &options->hostbased_accepted_algos;
2214 goto parse_pubkey_algos;
2216 case oPubkeyAcceptedAlgorithms:
2217 charptr = &options->pubkey_accepted_algos;
2219 goto parse_pubkey_algos;
2221 case oAddKeysToAgent:
2222 arg = argv_next(&ac, &av);
2223 arg2 = argv_next(&ac, &av);
2224 value = parse_multistate_value(arg, filename, linenum,
2225 multistate_yesnoaskconfirm);
2226 value2 = 0; /* unlimited lifespan by default */
2227 if (value == 3 && arg2 != NULL) {
2228 /* allow "AddKeysToAgent confirm 5m" */
2229 if ((value2 = convtime(arg2)) == -1) {
2230 error("%s line %d: invalid time value.",
2234 } else if (value == -1 && arg2 == NULL) {
2235 if ((value2 = convtime(arg)) == -1) {
2236 error("%s line %d: unsupported option",
2240 value = 1; /* yes */
2241 } else if (value == -1 || arg2 != NULL) {
2242 error("%s line %d: unsupported option",
2246 if (*activep && options->add_keys_to_agent == -1) {
2247 options->add_keys_to_agent = value;
2248 options->add_keys_to_agent_lifespan = value2;
2252 case oIdentityAgent:
2253 charptr = &options->identity_agent;
2254 arg = argv_next(&ac, &av);
2255 if (!arg || *arg == '\0') {
2256 error("%.200s line %d: Missing argument.",
2261 /* Extra validation if the string represents an env var. */
2262 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2263 error("%.200s line %d: Invalid environment expansion "
2264 "%s.", filename, linenum, arg);
2268 /* check for legacy environment format */
2269 if (arg[0] == '$' && arg[1] != '{' &&
2270 !valid_env_name(arg + 1)) {
2271 error("%.200s line %d: Invalid environment name %s.",
2272 filename, linenum, arg);
2275 if (*activep && *charptr == NULL)
2276 *charptr = xstrdup(arg);
2279 case oEnableEscapeCommandline:
2280 intptr = &options->enable_escape_commandline;
2283 case oRequiredRSASize:
2284 intptr = &options->required_rsa_size;
2287 case oObscureKeystrokeTiming:
2289 while ((arg = argv_next(&ac, &av)) != NULL) {
2291 error("%s line %d: invalid arguments",
2295 if (strcmp(arg, "yes") == 0 ||
2296 strcmp(arg, "true") == 0)
2297 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2298 else if (strcmp(arg, "no") == 0 ||
2299 strcmp(arg, "false") == 0)
2301 else if (strncmp(arg, "interval:", 9) == 0) {
2302 if ((errstr = atoi_err(arg + 9,
2304 error("%s line %d: integer value %s.",
2305 filename, linenum, errstr);
2308 if (value <= 0 || value > 1000) {
2309 error("%s line %d: value out of range.",
2314 error("%s line %d: unsupported argument \"%s\"",
2315 filename, linenum, arg);
2320 error("%s line %d: missing argument",
2324 intptr = &options->obscure_keystroke_timing_interval;
2325 if (*activep && *intptr == -1)
2330 debug("%s line %d: Deprecated option \"%s\"",
2331 filename, linenum, keyword);
2336 error("%s line %d: Unsupported option \"%s\"",
2337 filename, linenum, keyword);
2342 error("%s line %d: Unimplemented opcode %d",
2343 filename, linenum, opcode);
2347 /* Check that there is no garbage at end of line. */
2349 error("%.200s line %d: keyword %s extra arguments "
2350 "at end of line", filename, linenum, keyword);
2357 argv_free(oav, oac);
2362 * Reads the config file and modifies the options accordingly. Options
2363 * should already be initialized before this call. This never returns if
2364 * there is an error. If the file does not exist, this returns 0.
2367 read_config_file(const char *filename, struct passwd *pw, const char *host,
2368 const char *original_host, Options *options, int flags,
2369 int *want_final_pass)
2373 return read_config_file_depth(filename, pw, host, original_host,
2374 options, flags, &active, want_final_pass, 0);
2377 #define READCONF_MAX_DEPTH 16
2379 read_config_file_depth(const char *filename, struct passwd *pw,
2380 const char *host, const char *original_host, Options *options,
2381 int flags, int *activep, int *want_final_pass, int depth)
2385 size_t linesize = 0;
2387 int bad_options = 0;
2389 if (depth < 0 || depth > READCONF_MAX_DEPTH)
2390 fatal("Too many recursive configuration includes");
2392 if ((f = fopen(filename, "r")) == NULL)
2395 if (flags & SSHCONF_CHECKPERM) {
2398 if (fstat(fileno(f), &sb) == -1)
2399 fatal("fstat %s: %s", filename, strerror(errno));
2400 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2401 (sb.st_mode & 022) != 0))
2402 fatal("Bad owner or permissions on %s", filename);
2405 debug("Reading configuration data %.200s", filename);
2408 * Mark that we are now processing the options. This flag is turned
2409 * on/off by Host specifications.
2412 while (getline(&line, &linesize, f) != -1) {
2413 /* Update line number counter. */
2416 * Trim out comments and strip whitespace.
2417 * NB - preserve newlines, they are needed to reproduce
2418 * line numbers later for error messages.
2420 if (process_config_line_depth(options, pw, host, original_host,
2421 line, filename, linenum, activep, flags, want_final_pass,
2427 if (bad_options > 0)
2428 fatal("%s: terminating, %d bad configuration options",
2429 filename, bad_options);
2433 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2435 option_clear_or_none(const char *o)
2437 return o == NULL || strcasecmp(o, "none") == 0;
2441 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2442 * Allowed to be called on non-final configuration.
2445 config_has_permitted_cnames(Options *options)
2447 if (options->num_permitted_cnames == 1 &&
2448 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2449 strcmp(options->permitted_cnames[0].target_list, "") == 0)
2451 return options->num_permitted_cnames > 0;
2455 * Initializes options to special values that indicate that they have not yet
2456 * been set. Read_config_file will only set options with this value. Options
2457 * are processed in the following order: command line, user config file,
2458 * system config file. Last, fill_default_options is called.
2462 initialize_options(Options * options)
2464 memset(options, 'X', sizeof(*options));
2465 options->host_arg = NULL;
2466 options->forward_agent = -1;
2467 options->forward_agent_sock_path = NULL;
2468 options->forward_x11 = -1;
2469 options->forward_x11_trusted = -1;
2470 options->forward_x11_timeout = -1;
2471 options->stdio_forward_host = NULL;
2472 options->stdio_forward_port = 0;
2473 options->clear_forwardings = -1;
2474 options->exit_on_forward_failure = -1;
2475 options->xauth_location = NULL;
2476 options->fwd_opts.gateway_ports = -1;
2477 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2478 options->fwd_opts.streamlocal_bind_unlink = -1;
2479 options->pubkey_authentication = -1;
2480 options->gss_authentication = -1;
2481 options->gss_deleg_creds = -1;
2482 options->password_authentication = -1;
2483 options->kbd_interactive_authentication = -1;
2484 options->kbd_interactive_devices = NULL;
2485 options->hostbased_authentication = -1;
2486 options->batch_mode = -1;
2487 options->check_host_ip = -1;
2488 options->strict_host_key_checking = -1;
2489 options->compression = -1;
2490 options->tcp_keep_alive = -1;
2492 options->address_family = -1;
2493 options->connection_attempts = -1;
2494 options->connection_timeout = -1;
2495 options->number_of_password_prompts = -1;
2496 options->ciphers = NULL;
2497 options->macs = NULL;
2498 options->kex_algorithms = NULL;
2499 options->hostkeyalgorithms = NULL;
2500 options->ca_sign_algorithms = NULL;
2501 options->num_identity_files = 0;
2502 memset(options->identity_keys, 0, sizeof(options->identity_keys));
2503 options->num_certificate_files = 0;
2504 memset(options->certificates, 0, sizeof(options->certificates));
2505 options->hostname = NULL;
2506 options->host_key_alias = NULL;
2507 options->proxy_command = NULL;
2508 options->jump_user = NULL;
2509 options->jump_host = NULL;
2510 options->jump_port = -1;
2511 options->jump_extra = NULL;
2512 options->user = NULL;
2513 options->escape_char = -1;
2514 options->num_system_hostfiles = 0;
2515 options->num_user_hostfiles = 0;
2516 options->local_forwards = NULL;
2517 options->num_local_forwards = 0;
2518 options->remote_forwards = NULL;
2519 options->num_remote_forwards = 0;
2520 options->permitted_remote_opens = NULL;
2521 options->num_permitted_remote_opens = 0;
2522 options->log_facility = SYSLOG_FACILITY_NOT_SET;
2523 options->log_level = SYSLOG_LEVEL_NOT_SET;
2524 options->num_log_verbose = 0;
2525 options->log_verbose = NULL;
2526 options->preferred_authentications = NULL;
2527 options->bind_address = NULL;
2528 options->bind_interface = NULL;
2529 options->pkcs11_provider = NULL;
2530 options->sk_provider = NULL;
2531 options->enable_ssh_keysign = - 1;
2532 options->no_host_authentication_for_localhost = - 1;
2533 options->identities_only = - 1;
2534 options->rekey_limit = - 1;
2535 options->rekey_interval = -1;
2536 options->verify_host_key_dns = -1;
2537 options->server_alive_interval = -1;
2538 options->server_alive_count_max = -1;
2539 options->send_env = NULL;
2540 options->num_send_env = 0;
2541 options->setenv = NULL;
2542 options->num_setenv = 0;
2543 options->control_path = NULL;
2544 options->control_master = -1;
2545 options->control_persist = -1;
2546 options->control_persist_timeout = 0;
2547 options->hash_known_hosts = -1;
2548 options->tun_open = -1;
2549 options->tun_local = -1;
2550 options->tun_remote = -1;
2551 options->local_command = NULL;
2552 options->permit_local_command = -1;
2553 options->remote_command = NULL;
2554 options->add_keys_to_agent = -1;
2555 options->add_keys_to_agent_lifespan = -1;
2556 options->identity_agent = NULL;
2557 options->visual_host_key = -1;
2558 options->ip_qos_interactive = -1;
2559 options->ip_qos_bulk = -1;
2560 options->request_tty = -1;
2561 options->session_type = -1;
2562 options->stdin_null = -1;
2563 options->fork_after_authentication = -1;
2564 options->proxy_use_fdpass = -1;
2565 options->ignored_unknown = NULL;
2566 options->num_canonical_domains = 0;
2567 options->num_permitted_cnames = 0;
2568 options->canonicalize_max_dots = -1;
2569 options->canonicalize_fallback_local = -1;
2570 options->canonicalize_hostname = -1;
2571 options->revoked_host_keys = NULL;
2572 options->fingerprint_hash = -1;
2573 options->update_hostkeys = -1;
2574 options->hostbased_accepted_algos = NULL;
2575 options->pubkey_accepted_algos = NULL;
2576 options->known_hosts_command = NULL;
2577 options->required_rsa_size = -1;
2578 options->enable_escape_commandline = -1;
2579 options->obscure_keystroke_timing_interval = -1;
2580 options->tag = NULL;
2584 * A petite version of fill_default_options() that just fills the options
2585 * needed for hostname canonicalization to proceed.
2588 fill_default_options_for_canonicalization(Options *options)
2590 if (options->canonicalize_max_dots == -1)
2591 options->canonicalize_max_dots = 1;
2592 if (options->canonicalize_fallback_local == -1)
2593 options->canonicalize_fallback_local = 1;
2594 if (options->canonicalize_hostname == -1)
2595 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2599 * Called after processing other sources of option data, this fills those
2600 * options for which no value has been specified with their default values.
2603 fill_default_options(Options * options)
2605 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2606 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2609 if (options->forward_agent == -1)
2610 options->forward_agent = 0;
2611 if (options->forward_x11 == -1)
2612 options->forward_x11 = 0;
2613 if (options->forward_x11_trusted == -1)
2614 options->forward_x11_trusted = 0;
2615 if (options->forward_x11_timeout == -1)
2616 options->forward_x11_timeout = 1200;
2618 * stdio forwarding (-W) changes the default for these but we defer
2619 * setting the values so they can be overridden.
2621 if (options->exit_on_forward_failure == -1)
2622 options->exit_on_forward_failure =
2623 options->stdio_forward_host != NULL ? 1 : 0;
2624 if (options->clear_forwardings == -1)
2625 options->clear_forwardings =
2626 options->stdio_forward_host != NULL ? 1 : 0;
2627 if (options->clear_forwardings == 1)
2628 clear_forwardings(options);
2630 if (options->xauth_location == NULL)
2631 options->xauth_location = xstrdup(_PATH_XAUTH);
2632 if (options->fwd_opts.gateway_ports == -1)
2633 options->fwd_opts.gateway_ports = 0;
2634 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2635 options->fwd_opts.streamlocal_bind_mask = 0177;
2636 if (options->fwd_opts.streamlocal_bind_unlink == -1)
2637 options->fwd_opts.streamlocal_bind_unlink = 0;
2638 if (options->pubkey_authentication == -1)
2639 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2640 if (options->gss_authentication == -1)
2641 options->gss_authentication = 0;
2642 if (options->gss_deleg_creds == -1)
2643 options->gss_deleg_creds = 0;
2644 if (options->password_authentication == -1)
2645 options->password_authentication = 1;
2646 if (options->kbd_interactive_authentication == -1)
2647 options->kbd_interactive_authentication = 1;
2648 if (options->hostbased_authentication == -1)
2649 options->hostbased_authentication = 0;
2650 if (options->batch_mode == -1)
2651 options->batch_mode = 0;
2652 if (options->check_host_ip == -1)
2653 options->check_host_ip = 0;
2654 if (options->strict_host_key_checking == -1)
2655 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2656 if (options->compression == -1)
2657 options->compression = 0;
2658 if (options->tcp_keep_alive == -1)
2659 options->tcp_keep_alive = 1;
2660 if (options->port == -1)
2661 options->port = 0; /* Filled in ssh_connect. */
2662 if (options->address_family == -1)
2663 options->address_family = AF_UNSPEC;
2664 if (options->connection_attempts == -1)
2665 options->connection_attempts = 1;
2666 if (options->number_of_password_prompts == -1)
2667 options->number_of_password_prompts = 3;
2668 /* options->hostkeyalgorithms, default set in myproposals.h */
2669 if (options->add_keys_to_agent == -1) {
2670 options->add_keys_to_agent = 0;
2671 options->add_keys_to_agent_lifespan = 0;
2673 if (options->num_identity_files == 0) {
2674 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2675 #ifdef OPENSSL_HAS_ECC
2676 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2677 add_identity_file(options, "~/",
2678 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2680 add_identity_file(options, "~/",
2681 _PATH_SSH_CLIENT_ID_ED25519, 0);
2682 add_identity_file(options, "~/",
2683 _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2684 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2685 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2687 if (options->escape_char == -1)
2688 options->escape_char = '~';
2689 if (options->num_system_hostfiles == 0) {
2690 options->system_hostfiles[options->num_system_hostfiles++] =
2691 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2692 options->system_hostfiles[options->num_system_hostfiles++] =
2693 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2695 if (options->update_hostkeys == -1) {
2696 if (options->verify_host_key_dns <= 0 &&
2697 (options->num_user_hostfiles == 0 ||
2698 (options->num_user_hostfiles == 1 && strcmp(options->
2699 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2700 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2702 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2704 if (options->num_user_hostfiles == 0) {
2705 options->user_hostfiles[options->num_user_hostfiles++] =
2706 xstrdup(_PATH_SSH_USER_HOSTFILE);
2707 options->user_hostfiles[options->num_user_hostfiles++] =
2708 xstrdup(_PATH_SSH_USER_HOSTFILE2);
2710 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2711 options->log_level = SYSLOG_LEVEL_INFO;
2712 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2713 options->log_facility = SYSLOG_FACILITY_USER;
2714 if (options->no_host_authentication_for_localhost == - 1)
2715 options->no_host_authentication_for_localhost = 0;
2716 if (options->identities_only == -1)
2717 options->identities_only = 0;
2718 if (options->enable_ssh_keysign == -1)
2719 options->enable_ssh_keysign = 0;
2720 if (options->rekey_limit == -1)
2721 options->rekey_limit = 0;
2722 if (options->rekey_interval == -1)
2723 options->rekey_interval = 0;
2724 if (options->verify_host_key_dns == -1)
2725 options->verify_host_key_dns = 0;
2726 if (options->server_alive_interval == -1)
2727 options->server_alive_interval = 0;
2728 if (options->server_alive_count_max == -1)
2729 options->server_alive_count_max = 3;
2730 if (options->control_master == -1)
2731 options->control_master = 0;
2732 if (options->control_persist == -1) {
2733 options->control_persist = 0;
2734 options->control_persist_timeout = 0;
2736 if (options->hash_known_hosts == -1)
2737 options->hash_known_hosts = 0;
2738 if (options->tun_open == -1)
2739 options->tun_open = SSH_TUNMODE_NO;
2740 if (options->tun_local == -1)
2741 options->tun_local = SSH_TUNID_ANY;
2742 if (options->tun_remote == -1)
2743 options->tun_remote = SSH_TUNID_ANY;
2744 if (options->permit_local_command == -1)
2745 options->permit_local_command = 0;
2746 if (options->visual_host_key == -1)
2747 options->visual_host_key = 0;
2748 if (options->ip_qos_interactive == -1)
2749 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2750 if (options->ip_qos_bulk == -1)
2751 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2752 if (options->request_tty == -1)
2753 options->request_tty = REQUEST_TTY_AUTO;
2754 if (options->session_type == -1)
2755 options->session_type = SESSION_TYPE_DEFAULT;
2756 if (options->stdin_null == -1)
2757 options->stdin_null = 0;
2758 if (options->fork_after_authentication == -1)
2759 options->fork_after_authentication = 0;
2760 if (options->proxy_use_fdpass == -1)
2761 options->proxy_use_fdpass = 0;
2762 if (options->canonicalize_max_dots == -1)
2763 options->canonicalize_max_dots = 1;
2764 if (options->canonicalize_fallback_local == -1)
2765 options->canonicalize_fallback_local = 1;
2766 if (options->canonicalize_hostname == -1)
2767 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2768 if (options->fingerprint_hash == -1)
2769 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2770 #ifdef ENABLE_SK_INTERNAL
2771 if (options->sk_provider == NULL)
2772 options->sk_provider = xstrdup("internal");
2774 if (options->sk_provider == NULL)
2775 options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2777 if (options->required_rsa_size == -1)
2778 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2779 if (options->enable_escape_commandline == -1)
2780 options->enable_escape_commandline = 0;
2781 if (options->obscure_keystroke_timing_interval == -1) {
2782 options->obscure_keystroke_timing_interval =
2783 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2786 /* Expand KEX name lists */
2787 all_cipher = cipher_alg_list(',', 0);
2788 all_mac = mac_alg_list(',');
2789 all_kex = kex_alg_list(',');
2790 all_key = sshkey_alg_list(0, 0, 1, ',');
2791 all_sig = sshkey_alg_list(0, 1, 1, ',');
2792 /* remove unsupported algos from default lists */
2793 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2794 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2795 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2796 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2797 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2798 #define ASSEMBLE(what, defaults, all) \
2800 if ((r = kex_assemble_names(&options->what, \
2801 defaults, all)) != 0) { \
2802 error_fr(r, "%s", #what); \
2806 ASSEMBLE(ciphers, def_cipher, all_cipher);
2807 ASSEMBLE(macs, def_mac, all_mac);
2808 ASSEMBLE(kex_algorithms, def_kex, all_kex);
2809 ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2810 ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2811 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2814 #define CLEAR_ON_NONE(v) \
2816 if (option_clear_or_none(v)) { \
2821 CLEAR_ON_NONE(options->local_command);
2822 CLEAR_ON_NONE(options->remote_command);
2823 CLEAR_ON_NONE(options->proxy_command);
2824 CLEAR_ON_NONE(options->control_path);
2825 CLEAR_ON_NONE(options->revoked_host_keys);
2826 CLEAR_ON_NONE(options->pkcs11_provider);
2827 CLEAR_ON_NONE(options->sk_provider);
2828 CLEAR_ON_NONE(options->known_hosts_command);
2829 if (options->jump_host != NULL &&
2830 strcmp(options->jump_host, "none") == 0 &&
2831 options->jump_port == 0 && options->jump_user == NULL) {
2832 free(options->jump_host);
2833 options->jump_host = NULL;
2835 if (options->num_permitted_cnames == 1 &&
2836 !config_has_permitted_cnames(options)) {
2837 /* clean up CanonicalizePermittedCNAMEs=none */
2838 free(options->permitted_cnames[0].source_list);
2839 free(options->permitted_cnames[0].target_list);
2840 memset(options->permitted_cnames, '\0',
2841 sizeof(*options->permitted_cnames));
2842 options->num_permitted_cnames = 0;
2844 /* options->identity_agent distinguishes NULL from 'none' */
2845 /* options->user will be set in the main program if appropriate */
2846 /* options->hostname will be set in the main program if appropriate */
2847 /* options->host_key_alias should not be set by default */
2848 /* options->preferred_authentications will be set in ssh */
2867 free_options(Options *o)
2874 #define FREE_ARRAY(type, n, a) \
2877 for (_i = 0; _i < (n); _i++) \
2881 free(o->forward_agent_sock_path);
2882 free(o->xauth_location);
2883 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2884 free(o->log_verbose);
2887 free(o->hostkeyalgorithms);
2888 free(o->kex_algorithms);
2889 free(o->ca_sign_algorithms);
2891 free(o->host_key_alias);
2892 free(o->proxy_command);
2894 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2895 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2896 free(o->preferred_authentications);
2897 free(o->bind_address);
2898 free(o->bind_interface);
2899 free(o->pkcs11_provider);
2900 free(o->sk_provider);
2901 for (i = 0; i < o->num_identity_files; i++) {
2902 free(o->identity_files[i]);
2903 sshkey_free(o->identity_keys[i]);
2905 for (i = 0; i < o->num_certificate_files; i++) {
2906 free(o->certificate_files[i]);
2907 sshkey_free(o->certificates[i]);
2909 free(o->identity_agent);
2910 for (i = 0; i < o->num_local_forwards; i++) {
2911 free(o->local_forwards[i].listen_host);
2912 free(o->local_forwards[i].listen_path);
2913 free(o->local_forwards[i].connect_host);
2914 free(o->local_forwards[i].connect_path);
2916 free(o->local_forwards);
2917 for (i = 0; i < o->num_remote_forwards; i++) {
2918 free(o->remote_forwards[i].listen_host);
2919 free(o->remote_forwards[i].listen_path);
2920 free(o->remote_forwards[i].connect_host);
2921 free(o->remote_forwards[i].connect_path);
2923 free(o->remote_forwards);
2924 free(o->stdio_forward_host);
2925 FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2927 FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2929 free(o->control_path);
2930 free(o->local_command);
2931 free(o->remote_command);
2932 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2933 for (i = 0; i < o->num_permitted_cnames; i++) {
2934 free(o->permitted_cnames[i].source_list);
2935 free(o->permitted_cnames[i].target_list);
2937 free(o->revoked_host_keys);
2938 free(o->hostbased_accepted_algos);
2939 free(o->pubkey_accepted_algos);
2942 free(o->jump_extra);
2943 free(o->ignored_unknown);
2944 explicit_bzero(o, sizeof(*o));
2955 * parses the next field in a port forwarding specification.
2956 * sets fwd to the parsed field and advances p past the colon
2957 * or sets it to NULL at end of string.
2958 * returns 0 on success, else non-zero.
2961 parse_fwd_field(char **p, struct fwdarg *fwd)
2968 return -1; /* end of string */
2972 * A field escaped with square brackets is used literally.
2973 * XXX - allow ']' to be escaped via backslash?
2976 /* find matching ']' */
2977 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2981 /* no matching ']' or not at end of field. */
2982 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2984 /* NUL terminate the field and advance p past the colon */
2989 fwd->ispath = ispath;
2994 for (cp = *p; *cp != '\0'; cp++) {
2997 memmove(cp, cp + 1, strlen(cp + 1) + 1);
3011 fwd->ispath = ispath;
3018 * parses a string containing a port forwarding specification of the form:
3020 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3021 * listenpath:connectpath
3023 * [listenhost:]listenport
3024 * returns number of arguments parsed or zero on error
3027 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3029 struct fwdarg fwdargs[4];
3033 memset(fwd, 0, sizeof(*fwd));
3034 memset(fwdargs, 0, sizeof(fwdargs));
3037 * We expand environment variables before checking if we think they're
3038 * paths so that if ${VAR} expands to a fully qualified path it is
3039 * treated as a path.
3041 cp = p = dollar_expand(&err, fwdspec);
3042 if (p == NULL || err)
3045 /* skip leading spaces */
3046 while (isspace((u_char)*cp))
3049 for (i = 0; i < 4; ++i) {
3050 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3054 /* Check for trailing garbage */
3055 if (cp != NULL && *cp != '\0') {
3056 i = 0; /* failure */
3061 if (fwdargs[0].ispath) {
3062 fwd->listen_path = xstrdup(fwdargs[0].arg);
3063 fwd->listen_port = PORT_STREAMLOCAL;
3065 fwd->listen_host = NULL;
3066 fwd->listen_port = a2port(fwdargs[0].arg);
3068 fwd->connect_host = xstrdup("socks");
3072 if (fwdargs[0].ispath && fwdargs[1].ispath) {
3073 fwd->listen_path = xstrdup(fwdargs[0].arg);
3074 fwd->listen_port = PORT_STREAMLOCAL;
3075 fwd->connect_path = xstrdup(fwdargs[1].arg);
3076 fwd->connect_port = PORT_STREAMLOCAL;
3077 } else if (fwdargs[1].ispath) {
3078 fwd->listen_host = NULL;
3079 fwd->listen_port = a2port(fwdargs[0].arg);
3080 fwd->connect_path = xstrdup(fwdargs[1].arg);
3081 fwd->connect_port = PORT_STREAMLOCAL;
3083 fwd->listen_host = xstrdup(fwdargs[0].arg);
3084 fwd->listen_port = a2port(fwdargs[1].arg);
3085 fwd->connect_host = xstrdup("socks");
3090 if (fwdargs[0].ispath) {
3091 fwd->listen_path = xstrdup(fwdargs[0].arg);
3092 fwd->listen_port = PORT_STREAMLOCAL;
3093 fwd->connect_host = xstrdup(fwdargs[1].arg);
3094 fwd->connect_port = a2port(fwdargs[2].arg);
3095 } else if (fwdargs[2].ispath) {
3096 fwd->listen_host = xstrdup(fwdargs[0].arg);
3097 fwd->listen_port = a2port(fwdargs[1].arg);
3098 fwd->connect_path = xstrdup(fwdargs[2].arg);
3099 fwd->connect_port = PORT_STREAMLOCAL;
3101 fwd->listen_host = NULL;
3102 fwd->listen_port = a2port(fwdargs[0].arg);
3103 fwd->connect_host = xstrdup(fwdargs[1].arg);
3104 fwd->connect_port = a2port(fwdargs[2].arg);
3109 fwd->listen_host = xstrdup(fwdargs[0].arg);
3110 fwd->listen_port = a2port(fwdargs[1].arg);
3111 fwd->connect_host = xstrdup(fwdargs[2].arg);
3112 fwd->connect_port = a2port(fwdargs[3].arg);
3115 i = 0; /* failure */
3121 if (!(i == 1 || i == 2))
3124 if (!(i == 3 || i == 4)) {
3125 if (fwd->connect_path == NULL &&
3126 fwd->listen_path == NULL)
3129 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3133 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3134 (!remotefwd && fwd->listen_port == 0))
3136 if (fwd->connect_host != NULL &&
3137 strlen(fwd->connect_host) >= NI_MAXHOST)
3140 * XXX - if connecting to a remote socket, max sun len may not
3143 if (fwd->connect_path != NULL &&
3144 strlen(fwd->connect_path) >= PATH_MAX_SUN)
3146 if (fwd->listen_host != NULL &&
3147 strlen(fwd->listen_host) >= NI_MAXHOST)
3149 if (fwd->listen_path != NULL &&
3150 strlen(fwd->listen_path) >= PATH_MAX_SUN)
3156 free(fwd->connect_host);
3157 fwd->connect_host = NULL;
3158 free(fwd->connect_path);
3159 fwd->connect_path = NULL;
3160 free(fwd->listen_host);
3161 fwd->listen_host = NULL;
3162 free(fwd->listen_path);
3163 fwd->listen_path = NULL;
3168 parse_jump(const char *s, Options *o, int active)
3170 char *orig, *sdup, *cp;
3171 char *host = NULL, *user = NULL;
3172 int r, ret = -1, port = -1, first;
3174 active &= o->proxy_command == NULL && o->jump_host == NULL;
3176 orig = sdup = xstrdup(s);
3178 /* Remove comment and trailing whitespace */
3179 if ((cp = strchr(orig, '#')) != NULL)
3185 if (strcasecmp(s, "none") == 0)
3187 if ((cp = strrchr(sdup, ',')) == NULL)
3188 cp = sdup; /* last */
3193 /* First argument and configuration is active */
3194 r = parse_ssh_uri(cp, &user, &host, &port);
3195 if (r == -1 || (r == 1 &&
3196 parse_user_host_port(cp, &user, &host, &port) != 0))
3199 /* Subsequent argument or inactive configuration */
3200 r = parse_ssh_uri(cp, NULL, NULL, NULL);
3201 if (r == -1 || (r == 1 &&
3202 parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3205 first = 0; /* only check syntax for subsequent hosts */
3206 } while (cp != sdup);
3209 if (strcasecmp(s, "none") == 0) {
3210 o->jump_host = xstrdup("none");
3213 o->jump_user = user;
3214 o->jump_host = host;
3215 o->jump_port = port;
3216 o->proxy_command = xstrdup("none");
3218 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3219 o->jump_extra = xstrdup(s);
3220 o->jump_extra[cp - s] = '\0';
3233 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3235 char *user = NULL, *host = NULL, *path = NULL;
3238 r = parse_uri("ssh", uri, &user, &host, &port, &path);
3239 if (r == 0 && path != NULL)
3240 r = -1; /* path not allowed */
3242 if (userp != NULL) {
3246 if (hostp != NULL) {
3259 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3261 fmt_multistate_int(int val, const struct multistate *m)
3265 for (i = 0; m[i].key != NULL; i++) {
3266 if (m[i].value == val)
3273 fmt_intarg(OpCodes code, int val)
3278 case oAddressFamily:
3279 return fmt_multistate_int(val, multistate_addressfamily);
3280 case oVerifyHostKeyDNS:
3281 case oUpdateHostkeys:
3282 return fmt_multistate_int(val, multistate_yesnoask);
3283 case oStrictHostKeyChecking:
3284 return fmt_multistate_int(val, multistate_strict_hostkey);
3285 case oControlMaster:
3286 return fmt_multistate_int(val, multistate_controlmaster);
3288 return fmt_multistate_int(val, multistate_tunnel);
3290 return fmt_multistate_int(val, multistate_requesttty);
3292 return fmt_multistate_int(val, multistate_sessiontype);
3293 case oCanonicalizeHostname:
3294 return fmt_multistate_int(val, multistate_canonicalizehostname);
3295 case oAddKeysToAgent:
3296 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3297 case oPubkeyAuthentication:
3298 return fmt_multistate_int(val, multistate_pubkey_auth);
3299 case oFingerprintHash:
3300 return ssh_digest_alg_name(val);
3314 lookup_opcode_name(OpCodes code)
3318 for (i = 0; keywords[i].name != NULL; i++)
3319 if (keywords[i].opcode == code)
3320 return(keywords[i].name);
3325 dump_cfg_int(OpCodes code, int val)
3327 if (code == oObscureKeystrokeTiming) {
3329 printf("%s no\n", lookup_opcode_name(code));
3331 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3332 printf("%s yes\n", lookup_opcode_name(code));
3337 printf("%s %d\n", lookup_opcode_name(code), val);
3341 dump_cfg_fmtint(OpCodes code, int val)
3343 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3347 dump_cfg_string(OpCodes code, const char *val)
3351 printf("%s %s\n", lookup_opcode_name(code), val);
3355 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3359 for (i = 0; i < count; i++)
3360 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3364 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3368 printf("%s", lookup_opcode_name(code));
3371 for (i = 0; i < count; i++)
3372 printf(" %s", vals[i]);
3377 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3379 const struct Forward *fwd;
3382 /* oDynamicForward */
3383 for (i = 0; i < count; i++) {
3385 if (code == oDynamicForward && fwd->connect_host != NULL &&
3386 strcmp(fwd->connect_host, "socks") != 0)
3388 if (code == oLocalForward && fwd->connect_host != NULL &&
3389 strcmp(fwd->connect_host, "socks") == 0)
3391 printf("%s", lookup_opcode_name(code));
3392 if (fwd->listen_port == PORT_STREAMLOCAL)
3393 printf(" %s", fwd->listen_path);
3394 else if (fwd->listen_host == NULL)
3395 printf(" %d", fwd->listen_port);
3398 fwd->listen_host, fwd->listen_port);
3400 if (code != oDynamicForward) {
3401 if (fwd->connect_port == PORT_STREAMLOCAL)
3402 printf(" %s", fwd->connect_path);
3403 else if (fwd->connect_host == NULL)
3404 printf(" %d", fwd->connect_port);
3407 fwd->connect_host, fwd->connect_port);
3415 dump_client_config(Options *o, const char *host)
3418 char buf[8], *all_key;
3421 * Expand HostKeyAlgorithms name lists. This isn't handled in
3422 * fill_default_options() like the other algorithm lists because
3423 * the host key algorithms are by default dynamically chosen based
3424 * on the host's keys found in known_hosts.
3426 all_key = sshkey_alg_list(0, 0, 1, ',');
3427 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3429 fatal_fr(r, "expand HostKeyAlgorithms");
3432 /* Most interesting options first: user, host, port */
3433 dump_cfg_string(oHost, o->host_arg);
3434 dump_cfg_string(oUser, o->user);
3435 dump_cfg_string(oHostname, host);
3436 dump_cfg_int(oPort, o->port);
3439 dump_cfg_fmtint(oAddressFamily, o->address_family);
3440 dump_cfg_fmtint(oBatchMode, o->batch_mode);
3441 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3442 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3443 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3444 dump_cfg_fmtint(oCompression, o->compression);
3445 dump_cfg_fmtint(oControlMaster, o->control_master);
3446 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3447 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3448 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3449 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3450 dump_cfg_fmtint(oForwardX11, o->forward_x11);
3451 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3452 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3454 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3455 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3457 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3458 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3459 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3460 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3461 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3462 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3463 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3464 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3465 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3466 dump_cfg_fmtint(oRequestTTY, o->request_tty);
3467 dump_cfg_fmtint(oSessionType, o->session_type);
3468 dump_cfg_fmtint(oStdinNull, o->stdin_null);
3469 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3470 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3471 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3472 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3473 dump_cfg_fmtint(oTunnel, o->tun_open);
3474 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3475 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3476 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3477 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3479 /* Integer options */
3480 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3481 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3482 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3483 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3484 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3485 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3486 dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3487 dump_cfg_int(oObscureKeystrokeTiming,
3488 o->obscure_keystroke_timing_interval);
3490 /* String options */
3491 dump_cfg_string(oBindAddress, o->bind_address);
3492 dump_cfg_string(oBindInterface, o->bind_interface);
3493 dump_cfg_string(oCiphers, o->ciphers);
3494 dump_cfg_string(oControlPath, o->control_path);
3495 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3496 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3497 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3498 dump_cfg_string(oIdentityAgent, o->identity_agent);
3499 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3500 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3501 dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3502 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3503 dump_cfg_string(oLocalCommand, o->local_command);
3504 dump_cfg_string(oRemoteCommand, o->remote_command);
3505 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3506 dump_cfg_string(oMacs, o->macs);
3507 #ifdef ENABLE_PKCS11
3508 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3510 dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3511 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3512 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3513 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3514 dump_cfg_string(oXAuthLocation, o->xauth_location);
3515 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3516 dump_cfg_string(oTag, o->tag);
3519 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3520 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3521 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3523 /* String array options */
3524 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3525 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3526 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3527 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3528 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3529 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3530 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3531 dump_cfg_strarray_oneline(oLogVerbose,
3532 o->num_log_verbose, o->log_verbose);
3536 /* PermitRemoteOpen */
3537 if (o->num_permitted_remote_opens == 0)
3538 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3540 dump_cfg_strarray_oneline(oPermitRemoteOpen,
3541 o->num_permitted_remote_opens, o->permitted_remote_opens);
3543 /* AddKeysToAgent */
3544 if (o->add_keys_to_agent_lifespan <= 0)
3545 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3547 printf("addkeystoagent%s %d\n",
3548 o->add_keys_to_agent == 3 ? " confirm" : "",
3549 o->add_keys_to_agent_lifespan);
3553 if (o->forward_agent_sock_path == NULL)
3554 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3556 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3558 /* oConnectTimeout */
3559 if (o->connection_timeout == -1)
3560 printf("connecttimeout none\n");
3562 dump_cfg_int(oConnectTimeout, o->connection_timeout);
3565 printf("tunneldevice");
3566 if (o->tun_local == SSH_TUNID_ANY)
3569 printf(" %d", o->tun_local);
3570 if (o->tun_remote == SSH_TUNID_ANY)
3573 printf(":%d", o->tun_remote);
3576 /* oCanonicalizePermittedCNAMEs */
3577 printf("canonicalizePermittedcnames");
3578 if (o->num_permitted_cnames == 0)
3580 for (i = 0; i < o->num_permitted_cnames; i++) {
3581 printf(" %s:%s", o->permitted_cnames[i].source_list,
3582 o->permitted_cnames[i].target_list);
3586 /* oControlPersist */
3587 if (o->control_persist == 0 || o->control_persist_timeout == 0)
3588 dump_cfg_fmtint(oControlPersist, o->control_persist);
3590 dump_cfg_int(oControlPersist, o->control_persist_timeout);
3593 if (o->escape_char == SSH_ESCAPECHAR_NONE)
3594 printf("escapechar none\n");
3596 vis(buf, o->escape_char, VIS_WHITE, 0);
3597 printf("escapechar %s\n", buf);
3601 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3602 printf("%s\n", iptos2str(o->ip_qos_bulk));
3605 printf("rekeylimit %llu %d\n",
3606 (unsigned long long)o->rekey_limit, o->rekey_interval);
3608 /* oStreamLocalBindMask */
3609 printf("streamlocalbindmask 0%o\n",
3610 o->fwd_opts.streamlocal_bind_mask);
3613 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3615 /* oProxyCommand / oProxyJump */
3616 if (o->jump_host == NULL)
3617 dump_cfg_string(oProxyCommand, o->proxy_command);
3619 /* Check for numeric addresses */
3620 i = strchr(o->jump_host, ':') != NULL ||
3621 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3622 snprintf(buf, sizeof(buf), "%d", o->jump_port);
3623 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3624 /* optional additional jump spec */
3625 o->jump_extra == NULL ? "" : o->jump_extra,
3626 o->jump_extra == NULL ? "" : ",",
3628 o->jump_user == NULL ? "" : o->jump_user,
3629 o->jump_user == NULL ? "" : "@",
3630 /* opening [ if hostname is numeric */
3632 /* mandatory hostname */
3634 /* closing ] if hostname is numeric */
3636 /* optional port number */
3637 o->jump_port <= 0 ? "" : ":",
3638 o->jump_port <= 0 ? "" : buf);