1 /* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 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, oChannelTimeout,
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 },
331 { "channeltimeout", oChannelTimeout },
333 /* Client VersionAddendum - retired in bffe60ead024 */
334 { "versionaddendum", oDeprecated },
339 static const char *lookup_opcode_name(OpCodes code);
342 kex_default_pk_alg(void)
346 if (pkalgs == NULL) {
349 all_key = sshkey_alg_list(0, 0, 1, ',');
350 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
357 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
358 const char *user, const char *jumphost)
360 struct ssh_digest_ctx *md;
361 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
363 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
364 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
365 ssh_digest_update(md, host, strlen(host)) < 0 ||
366 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
367 ssh_digest_update(md, user, strlen(user)) < 0 ||
368 ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 ||
369 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
370 fatal_f("mux digest failed");
372 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
376 * Adds a local TCP/IP port forward to options. Never returns if there is an
381 add_local_forward(Options *options, const struct Forward *newfwd)
386 /* Don't add duplicates */
387 for (i = 0; i < options->num_local_forwards; i++) {
388 if (forward_equals(newfwd, options->local_forwards + i))
391 options->local_forwards = xreallocarray(options->local_forwards,
392 options->num_local_forwards + 1,
393 sizeof(*options->local_forwards));
394 fwd = &options->local_forwards[options->num_local_forwards++];
396 fwd->listen_host = newfwd->listen_host;
397 fwd->listen_port = newfwd->listen_port;
398 fwd->listen_path = newfwd->listen_path;
399 fwd->connect_host = newfwd->connect_host;
400 fwd->connect_port = newfwd->connect_port;
401 fwd->connect_path = newfwd->connect_path;
405 * Adds a remote TCP/IP port forward to options. Never returns if there is
410 add_remote_forward(Options *options, const struct Forward *newfwd)
415 /* Don't add duplicates */
416 for (i = 0; i < options->num_remote_forwards; i++) {
417 if (forward_equals(newfwd, options->remote_forwards + i))
420 options->remote_forwards = xreallocarray(options->remote_forwards,
421 options->num_remote_forwards + 1,
422 sizeof(*options->remote_forwards));
423 fwd = &options->remote_forwards[options->num_remote_forwards++];
425 fwd->listen_host = newfwd->listen_host;
426 fwd->listen_port = newfwd->listen_port;
427 fwd->listen_path = newfwd->listen_path;
428 fwd->connect_host = newfwd->connect_host;
429 fwd->connect_port = newfwd->connect_port;
430 fwd->connect_path = newfwd->connect_path;
431 fwd->handle = newfwd->handle;
432 fwd->allocated_port = 0;
436 clear_forwardings(Options *options)
440 for (i = 0; i < options->num_local_forwards; i++) {
441 free(options->local_forwards[i].listen_host);
442 free(options->local_forwards[i].listen_path);
443 free(options->local_forwards[i].connect_host);
444 free(options->local_forwards[i].connect_path);
446 if (options->num_local_forwards > 0) {
447 free(options->local_forwards);
448 options->local_forwards = NULL;
450 options->num_local_forwards = 0;
451 for (i = 0; i < options->num_remote_forwards; i++) {
452 free(options->remote_forwards[i].listen_host);
453 free(options->remote_forwards[i].listen_path);
454 free(options->remote_forwards[i].connect_host);
455 free(options->remote_forwards[i].connect_path);
457 if (options->num_remote_forwards > 0) {
458 free(options->remote_forwards);
459 options->remote_forwards = NULL;
461 options->num_remote_forwards = 0;
462 options->tun_open = SSH_TUNMODE_NO;
466 add_certificate_file(Options *options, const char *path, int userprovided)
470 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
471 fatal("Too many certificate files specified (max %d)",
472 SSH_MAX_CERTIFICATE_FILES);
474 /* Avoid registering duplicates */
475 for (i = 0; i < options->num_certificate_files; i++) {
476 if (options->certificate_file_userprovided[i] == userprovided &&
477 strcmp(options->certificate_files[i], path) == 0) {
478 debug2_f("ignoring duplicate key %s", path);
483 options->certificate_file_userprovided[options->num_certificate_files] =
485 options->certificate_files[options->num_certificate_files++] =
490 add_identity_file(Options *options, const char *dir, const char *filename,
496 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
497 fatal("Too many identity files specified (max %d)",
498 SSH_MAX_IDENTITY_FILES);
500 if (dir == NULL) /* no dir, filename is absolute */
501 path = xstrdup(filename);
502 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
503 fatal("Identity file path %s too long", path);
505 /* Avoid registering duplicates */
506 for (i = 0; i < options->num_identity_files; i++) {
507 if (options->identity_file_userprovided[i] == userprovided &&
508 strcmp(options->identity_files[i], path) == 0) {
509 debug2_f("ignoring duplicate key %s", path);
515 options->identity_file_userprovided[options->num_identity_files] =
517 options->identity_files[options->num_identity_files++] = path;
521 default_ssh_port(void)
527 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
528 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
534 * Execute a command in a shell.
535 * Return its exit status or -1 on abnormal exit.
538 execute_in_shell(const char *cmd)
544 if ((shell = getenv("SHELL")) == NULL)
545 shell = _PATH_BSHELL;
547 if (access(shell, X_OK) == -1) {
548 fatal("Shell \"%s\" is not executable: %s",
549 shell, strerror(errno));
552 debug("Executing command: '%.500s'", cmd);
554 /* Fork and execute the command. */
555 if ((pid = fork()) == 0) {
558 if (stdfd_devnull(1, 1, 0) == -1)
559 fatal_f("stdfd_devnull failed");
560 closefrom(STDERR_FILENO + 1);
564 argv[2] = xstrdup(cmd);
567 execv(argv[0], argv);
568 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
569 /* Die with signal to make this error apparent to parent. */
570 ssh_signal(SIGTERM, SIG_DFL);
571 kill(getpid(), SIGTERM);
576 fatal_f("fork: %.100s", strerror(errno));
578 while (waitpid(pid, &status, 0) == -1) {
579 if (errno != EINTR && errno != EAGAIN)
580 fatal_f("waitpid: %s", strerror(errno));
582 if (!WIFEXITED(status)) {
583 error("command '%.100s' exited abnormally", cmd);
586 debug3("command returned status %d", WEXITSTATUS(status));
587 return WEXITSTATUS(status);
591 * Check whether a local network interface address appears in CIDR pattern-
592 * list 'addrlist'. Returns 1 if matched or 0 otherwise.
595 check_match_ifaddrs(const char *addrlist)
597 #ifdef HAVE_IFADDRS_H
598 struct ifaddrs *ifa, *ifaddrs = NULL;
600 char addr[NI_MAXHOST];
603 if (getifaddrs(&ifaddrs) != 0) {
604 error("match localnetwork: getifaddrs failed: %s",
608 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
609 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
610 (ifa->ifa_flags & IFF_UP) == 0)
612 switch (ifa->ifa_addr->sa_family) {
614 salen = sizeof(struct sockaddr_in);
617 salen = sizeof(struct sockaddr_in6);
625 debug2_f("interface %s: unsupported address family %d",
626 ifa->ifa_name, ifa->ifa_addr->sa_family);
629 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
630 NULL, 0, NI_NUMERICHOST)) != 0) {
631 debug2_f("interface %s getnameinfo failed: %s",
632 ifa->ifa_name, gai_strerror(r));
635 debug3_f("interface %s addr %s", ifa->ifa_name, addr);
636 if (addr_match_cidr_list(addr, addrlist) == 1) {
637 debug3_f("matched interface %s: address %s in %s",
638 ifa->ifa_name, addr, addrlist);
643 freeifaddrs(ifaddrs);
645 #else /* HAVE_IFADDRS_H */
646 error("match localnetwork: not supported on this platform");
648 #endif /* HAVE_IFADDRS_H */
652 * Parse and execute a Match directive.
655 match_cfg_line(Options *options, char **condition, struct passwd *pw,
656 const char *host_arg, const char *original_host, int final_pass,
657 int *want_final_pass, const char *filename, int linenum)
659 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
661 int r, port, this_result, result = 1, attributes = 0, negate;
662 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
666 * Configuration is likely to be incomplete at this point so we
667 * must be prepared to use default values.
669 port = options->port <= 0 ? default_ssh_port() : options->port;
670 ruser = options->user == NULL ? pw->pw_name : options->user;
672 host = xstrdup(options->hostname);
673 } else if (options->hostname != NULL) {
674 /* NB. Please keep in sync with ssh.c:main() */
675 host = percent_expand(options->hostname,
676 "h", host_arg, (char *)NULL);
678 host = xstrdup(host_arg);
681 debug2("checking match for '%s' host %s originally %s",
682 cp, host, original_host);
683 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
684 /* Terminate on comment */
685 if (*attrib == '#') {
686 cp = NULL; /* mark all arguments consumed */
689 arg = criteria = NULL;
691 if ((negate = (attrib[0] == '!')))
693 /* Criterion "all" has no argument and must appear alone */
694 if (strcasecmp(attrib, "all") == 0) {
695 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
696 *arg != '\0' && *arg != '#')) {
697 error("%.200s line %d: '%s' cannot be combined "
698 "with other Match attributes",
699 filename, linenum, oattrib);
703 if (arg != NULL && *arg == '#')
704 cp = NULL; /* mark all arguments consumed */
706 result = negate ? 0 : 1;
710 /* criteria "final" and "canonical" have no argument */
711 if (strcasecmp(attrib, "canonical") == 0 ||
712 strcasecmp(attrib, "final") == 0) {
714 * If the config requests "Match final" then remember
715 * this so we can perform a second pass later.
717 if (strcasecmp(attrib, "final") == 0 &&
718 want_final_pass != NULL)
719 *want_final_pass = 1;
720 r = !!final_pass; /* force bitmask member to boolean */
721 if (r == (negate ? 1 : 0))
722 this_result = result = 0;
723 debug3("%.200s line %d: %smatched '%s'",
725 this_result ? "" : "not ", oattrib);
728 /* All other criteria require an argument */
729 if ((arg = strdelim(&cp)) == NULL ||
730 *arg == '\0' || *arg == '#') {
731 error("Missing Match criteria for %s", attrib);
735 if (strcasecmp(attrib, "host") == 0) {
736 criteria = xstrdup(host);
737 r = match_hostname(host, arg) == 1;
738 if (r == (negate ? 1 : 0))
739 this_result = result = 0;
740 } else if (strcasecmp(attrib, "originalhost") == 0) {
741 criteria = xstrdup(original_host);
742 r = match_hostname(original_host, arg) == 1;
743 if (r == (negate ? 1 : 0))
744 this_result = result = 0;
745 } else if (strcasecmp(attrib, "user") == 0) {
746 criteria = xstrdup(ruser);
747 r = match_pattern_list(ruser, arg, 0) == 1;
748 if (r == (negate ? 1 : 0))
749 this_result = result = 0;
750 } else if (strcasecmp(attrib, "localuser") == 0) {
751 criteria = xstrdup(pw->pw_name);
752 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
753 if (r == (negate ? 1 : 0))
754 this_result = result = 0;
755 } else if (strcasecmp(attrib, "localnetwork") == 0) {
756 if (addr_match_cidr_list(NULL, arg) == -1) {
757 /* Error already printed */
761 r = check_match_ifaddrs(arg) == 1;
762 if (r == (negate ? 1 : 0))
763 this_result = result = 0;
764 } else if (strcasecmp(attrib, "tagged") == 0) {
765 criteria = xstrdup(options->tag == NULL ? "" :
767 r = match_pattern_list(criteria, arg, 0) == 1;
768 if (r == (negate ? 1 : 0))
769 this_result = result = 0;
770 } else if (strcasecmp(attrib, "exec") == 0) {
771 char *conn_hash_hex, *keyalias, *jmphost;
773 if (gethostname(thishost, sizeof(thishost)) == -1)
774 fatal("gethostname: %s", strerror(errno));
775 jmphost = option_clear_or_none(options->jump_host) ?
776 "" : options->jump_host;
777 strlcpy(shorthost, thishost, sizeof(shorthost));
778 shorthost[strcspn(thishost, ".")] = '\0';
779 snprintf(portstr, sizeof(portstr), "%d", port);
780 snprintf(uidstr, sizeof(uidstr), "%llu",
781 (unsigned long long)pw->pw_uid);
782 conn_hash_hex = ssh_connection_hash(thishost, host,
783 portstr, ruser, jmphost);
784 keyalias = options->host_key_alias ?
785 options->host_key_alias : host;
787 cmd = percent_expand(arg,
803 /* skip execution if prior predicate failed */
804 debug3("%.200s line %d: skipped exec "
805 "\"%.100s\"", filename, linenum, cmd);
809 r = execute_in_shell(cmd);
811 fatal("%.200s line %d: match exec "
812 "'%.100s' error", filename,
815 criteria = xstrdup(cmd);
817 /* Force exit status to boolean */
819 if (r == (negate ? 1 : 0))
820 this_result = result = 0;
822 error("Unsupported Match attribute %s", attrib);
826 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
827 filename, linenum, this_result ? "": "not ", oattrib,
828 criteria == NULL ? "" : " \"",
829 criteria == NULL ? "" : criteria,
830 criteria == NULL ? "" : "\"");
833 if (attributes == 0) {
834 error("One or more attributes required for Match");
840 debug2("match %sfound", result ? "" : "not ");
846 /* Remove environment variable by pattern */
848 rm_env(Options *options, const char *arg, const char *filename, int linenum)
850 u_int i, j, onum_send_env = options->num_send_env;
852 /* Remove an environment variable */
853 for (i = 0; i < options->num_send_env; ) {
854 if (!match_pattern(options->send_env[i], arg + 1)) {
858 debug3("%s line %d: removing environment %s",
859 filename, linenum, options->send_env[i]);
860 free(options->send_env[i]);
861 options->send_env[i] = NULL;
862 for (j = i; j < options->num_send_env - 1; j++) {
863 options->send_env[j] = options->send_env[j + 1];
864 options->send_env[j + 1] = NULL;
866 options->num_send_env--;
867 /* NB. don't increment i */
869 if (onum_send_env != options->num_send_env) {
870 options->send_env = xrecallocarray(options->send_env,
871 onum_send_env, options->num_send_env,
872 sizeof(*options->send_env));
877 * Returns the number of the token pointed to by cp or oBadOption.
880 parse_token(const char *cp, const char *filename, int linenum,
881 const char *ignored_unknown)
885 for (i = 0; keywords[i].name; i++)
886 if (strcmp(cp, keywords[i].name) == 0)
887 return keywords[i].opcode;
888 if (ignored_unknown != NULL &&
889 match_pattern_list(cp, ignored_unknown, 1) == 1)
890 return oIgnoredUnknownOption;
891 error("%s: line %d: Bad configuration option: %s",
892 filename, linenum, cp);
896 /* Multistate option parsing */
901 static const struct multistate multistate_flag[] = {
908 static const struct multistate multistate_yesnoask[] = {
916 static const struct multistate multistate_strict_hostkey[] = {
917 { "true", SSH_STRICT_HOSTKEY_YES },
918 { "false", SSH_STRICT_HOSTKEY_OFF },
919 { "yes", SSH_STRICT_HOSTKEY_YES },
920 { "no", SSH_STRICT_HOSTKEY_OFF },
921 { "ask", SSH_STRICT_HOSTKEY_ASK },
922 { "off", SSH_STRICT_HOSTKEY_OFF },
923 { "accept-new", SSH_STRICT_HOSTKEY_NEW },
926 static const struct multistate multistate_yesnoaskconfirm[] = {
935 static const struct multistate multistate_addressfamily[] = {
937 { "inet6", AF_INET6 },
938 { "any", AF_UNSPEC },
941 static const struct multistate multistate_controlmaster[] = {
942 { "true", SSHCTL_MASTER_YES },
943 { "yes", SSHCTL_MASTER_YES },
944 { "false", SSHCTL_MASTER_NO },
945 { "no", SSHCTL_MASTER_NO },
946 { "auto", SSHCTL_MASTER_AUTO },
947 { "ask", SSHCTL_MASTER_ASK },
948 { "autoask", SSHCTL_MASTER_AUTO_ASK },
951 static const struct multistate multistate_tunnel[] = {
952 { "ethernet", SSH_TUNMODE_ETHERNET },
953 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
954 { "true", SSH_TUNMODE_DEFAULT },
955 { "yes", SSH_TUNMODE_DEFAULT },
956 { "false", SSH_TUNMODE_NO },
957 { "no", SSH_TUNMODE_NO },
960 static const struct multistate multistate_requesttty[] = {
961 { "true", REQUEST_TTY_YES },
962 { "yes", REQUEST_TTY_YES },
963 { "false", REQUEST_TTY_NO },
964 { "no", REQUEST_TTY_NO },
965 { "force", REQUEST_TTY_FORCE },
966 { "auto", REQUEST_TTY_AUTO },
969 static const struct multistate multistate_sessiontype[] = {
970 { "none", SESSION_TYPE_NONE },
971 { "subsystem", SESSION_TYPE_SUBSYSTEM },
972 { "default", SESSION_TYPE_DEFAULT },
975 static const struct multistate multistate_canonicalizehostname[] = {
976 { "true", SSH_CANONICALISE_YES },
977 { "false", SSH_CANONICALISE_NO },
978 { "yes", SSH_CANONICALISE_YES },
979 { "no", SSH_CANONICALISE_NO },
980 { "always", SSH_CANONICALISE_ALWAYS },
983 static const struct multistate multistate_pubkey_auth[] = {
984 { "true", SSH_PUBKEY_AUTH_ALL },
985 { "false", SSH_PUBKEY_AUTH_NO },
986 { "yes", SSH_PUBKEY_AUTH_ALL },
987 { "no", SSH_PUBKEY_AUTH_NO },
988 { "unbound", SSH_PUBKEY_AUTH_UNBOUND },
989 { "host-bound", SSH_PUBKEY_AUTH_HBOUND },
992 static const struct multistate multistate_compression[] = {
994 { "yes", COMP_ZLIB },
1001 parse_multistate_value(const char *arg, const char *filename, int linenum,
1002 const struct multistate *multistate_ptr)
1006 if (!arg || *arg == '\0') {
1007 error("%s line %d: missing argument.", filename, linenum);
1010 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1011 if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1012 return multistate_ptr[i].value;
1018 * Processes a single option line as used in the configuration files. This
1019 * only sets those values that have not already been set.
1022 process_config_line(Options *options, struct passwd *pw, const char *host,
1023 const char *original_host, char *line, const char *filename,
1024 int linenum, int *activep, int flags)
1026 return process_config_line_depth(options, pw, host, original_host,
1027 line, filename, linenum, activep, flags, NULL, 0);
1030 #define WHITESPACE " \t\r\n"
1032 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1033 const char *original_host, char *line, const char *filename,
1034 int linenum, int *activep, int flags, int *want_final_pass, int depth)
1036 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1037 char **cpptr, ***cppptr, fwdarg[256];
1038 u_int i, *uintptr, uvalue, max_entries = 0;
1039 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1040 int remotefwd, dynamicfwd, ca_only = 0;
1041 LogLevel *log_level_ptr;
1042 SyslogFacility *log_facility_ptr;
1046 const struct multistate *multistate_ptr;
1047 struct allowed_cname *cname;
1050 char **oav = NULL, **av;
1054 if (activep == NULL) { /* We are processing a command line directive */
1059 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1060 if ((len = strlen(line)) == 0)
1062 for (len--; len > 0; len--) {
1063 if (strchr(WHITESPACE "\f", line[len]) == NULL)
1069 /* Get the keyword. (Each line is supposed to begin with a keyword). */
1070 if ((keyword = strdelim(&str)) == NULL)
1072 /* Ignore leading whitespace. */
1073 if (*keyword == '\0')
1074 keyword = strdelim(&str);
1075 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1077 /* Match lowercase keyword */
1080 /* Prepare to parse remainder of line */
1082 str += strspn(str, WHITESPACE);
1083 if (str == NULL || *str == '\0') {
1084 error("%s line %d: no argument after keyword \"%s\"",
1085 filename, linenum, keyword);
1088 opcode = parse_token(keyword, filename, linenum,
1089 options->ignored_unknown);
1090 if (argv_split(str, &oac, &oav, 1) != 0) {
1091 error("%s line %d: invalid quotes", filename, linenum);
1099 /* don't panic, but count bad options */
1104 case oIgnoredUnknownOption:
1105 debug("%s line %d: Ignored unknown option \"%s\"",
1106 filename, linenum, keyword);
1109 case oConnectTimeout:
1110 intptr = &options->connection_timeout;
1112 arg = argv_next(&ac, &av);
1113 if (!arg || *arg == '\0') {
1114 error("%s line %d: missing time value.",
1118 if (strcmp(arg, "none") == 0)
1120 else if ((value = convtime(arg)) == -1) {
1121 error("%s line %d: invalid time value.",
1125 if (*activep && *intptr == -1)
1130 intptr = &options->forward_agent;
1132 arg = argv_next(&ac, &av);
1133 if (!arg || *arg == '\0') {
1134 error("%s line %d: missing argument.",
1140 multistate_ptr = multistate_flag;
1141 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1142 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1143 value = multistate_ptr[i].value;
1148 if (*activep && *intptr == -1)
1152 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1153 if (*activep && *intptr == -1)
1156 charptr = &options->forward_agent_sock_path;
1157 goto parse_agent_path;
1160 intptr = &options->forward_x11;
1162 multistate_ptr = multistate_flag;
1164 arg = argv_next(&ac, &av);
1165 if ((value = parse_multistate_value(arg, filename, linenum,
1166 multistate_ptr)) == -1) {
1167 error("%s line %d: unsupported option \"%s\".",
1168 filename, linenum, arg);
1171 if (*activep && *intptr == -1)
1175 case oForwardX11Trusted:
1176 intptr = &options->forward_x11_trusted;
1179 case oForwardX11Timeout:
1180 intptr = &options->forward_x11_timeout;
1184 intptr = &options->fwd_opts.gateway_ports;
1187 case oExitOnForwardFailure:
1188 intptr = &options->exit_on_forward_failure;
1191 case oPasswordAuthentication:
1192 intptr = &options->password_authentication;
1195 case oKbdInteractiveAuthentication:
1196 intptr = &options->kbd_interactive_authentication;
1199 case oKbdInteractiveDevices:
1200 charptr = &options->kbd_interactive_devices;
1203 case oPubkeyAuthentication:
1204 multistate_ptr = multistate_pubkey_auth;
1205 intptr = &options->pubkey_authentication;
1206 goto parse_multistate;
1208 case oHostbasedAuthentication:
1209 intptr = &options->hostbased_authentication;
1212 case oGssAuthentication:
1213 intptr = &options->gss_authentication;
1216 case oGssDelegateCreds:
1217 intptr = &options->gss_deleg_creds;
1221 intptr = &options->batch_mode;
1225 intptr = &options->check_host_ip;
1228 case oVerifyHostKeyDNS:
1229 intptr = &options->verify_host_key_dns;
1230 multistate_ptr = multistate_yesnoask;
1231 goto parse_multistate;
1233 case oStrictHostKeyChecking:
1234 intptr = &options->strict_host_key_checking;
1235 multistate_ptr = multistate_strict_hostkey;
1236 goto parse_multistate;
1239 intptr = &options->compression;
1240 multistate_ptr = multistate_compression;
1241 goto parse_multistate;
1244 intptr = &options->tcp_keep_alive;
1247 case oNoHostAuthenticationForLocalhost:
1248 intptr = &options->no_host_authentication_for_localhost;
1251 case oNumberOfPasswordPrompts:
1252 intptr = &options->number_of_password_prompts;
1256 arg = argv_next(&ac, &av);
1257 if (!arg || *arg == '\0') {
1258 error("%.200s line %d: Missing argument.", filename,
1262 if (strcmp(arg, "default") == 0) {
1265 if (scan_scaled(arg, &val64) == -1) {
1266 error("%.200s line %d: Bad number '%s': %s",
1267 filename, linenum, arg, strerror(errno));
1270 if (val64 != 0 && val64 < 16) {
1271 error("%.200s line %d: RekeyLimit too small",
1276 if (*activep && options->rekey_limit == -1)
1277 options->rekey_limit = val64;
1278 if (ac != 0) { /* optional rekey interval present */
1279 if (strcmp(av[0], "none") == 0) {
1280 (void)argv_next(&ac, &av); /* discard */
1283 intptr = &options->rekey_interval;
1289 arg = argv_next(&ac, &av);
1290 if (!arg || *arg == '\0') {
1291 error("%.200s line %d: Missing argument.",
1296 intptr = &options->num_identity_files;
1297 if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1298 error("%.200s line %d: Too many identity files "
1299 "specified (max %d).", filename, linenum,
1300 SSH_MAX_IDENTITY_FILES);
1303 add_identity_file(options, NULL,
1304 arg, flags & SSHCONF_USERCONF);
1308 case oCertificateFile:
1309 arg = argv_next(&ac, &av);
1310 if (!arg || *arg == '\0') {
1311 error("%.200s line %d: Missing argument.",
1316 intptr = &options->num_certificate_files;
1317 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1318 error("%.200s line %d: Too many certificate "
1319 "files specified (max %d).",
1321 SSH_MAX_CERTIFICATE_FILES);
1324 add_certificate_file(options, arg,
1325 flags & SSHCONF_USERCONF);
1329 case oXAuthLocation:
1330 charptr=&options->xauth_location;
1334 charptr = &options->user;
1336 arg = argv_next(&ac, &av);
1337 if (!arg || *arg == '\0') {
1338 error("%.200s line %d: Missing argument.",
1342 if (*activep && *charptr == NULL)
1343 *charptr = xstrdup(arg);
1346 case oGlobalKnownHostsFile:
1347 cpptr = (char **)&options->system_hostfiles;
1348 uintptr = &options->num_system_hostfiles;
1349 max_entries = SSH_MAX_HOSTS_FILES;
1352 value = *uintptr == 0; /* was array empty when we started? */
1353 while ((arg = argv_next(&ac, &av)) != NULL) {
1355 error("%s line %d: keyword %s empty argument",
1356 filename, linenum, keyword);
1359 /* Allow "none" only in first position */
1360 if (strcasecmp(arg, "none") == 0) {
1361 if (i > 0 || ac > 0) {
1362 error("%s line %d: keyword %s \"none\" "
1363 "argument must appear alone.",
1364 filename, linenum, keyword);
1369 if (*activep && value) {
1370 if ((*uintptr) >= max_entries) {
1371 error("%s line %d: too many %s "
1372 "entries.", filename, linenum,
1376 cpptr[(*uintptr)++] = xstrdup(arg);
1381 case oUserKnownHostsFile:
1382 cpptr = (char **)&options->user_hostfiles;
1383 uintptr = &options->num_user_hostfiles;
1384 max_entries = SSH_MAX_HOSTS_FILES;
1385 goto parse_char_array;
1388 charptr = &options->hostname;
1392 charptr = &options->tag;
1396 charptr = &options->host_key_alias;
1399 case oPreferredAuthentications:
1400 charptr = &options->preferred_authentications;
1404 charptr = &options->bind_address;
1407 case oBindInterface:
1408 charptr = &options->bind_interface;
1411 case oPKCS11Provider:
1412 charptr = &options->pkcs11_provider;
1415 case oSecurityKeyProvider:
1416 charptr = &options->sk_provider;
1419 case oKnownHostsCommand:
1420 charptr = &options->known_hosts_command;
1424 charptr = &options->proxy_command;
1425 /* Ignore ProxyCommand if ProxyJump already specified */
1426 if (options->jump_host != NULL)
1427 charptr = &options->jump_host; /* Skip below */
1430 error("%.200s line %d: Missing argument.",
1434 len = strspn(str, WHITESPACE "=");
1435 if (*activep && *charptr == NULL)
1436 *charptr = xstrdup(str + len);
1442 error("%.200s line %d: Missing argument.",
1446 len = strspn(str, WHITESPACE "=");
1448 if (parse_jump(str + len, options, *activep) == -1) {
1449 error("%.200s line %d: Invalid ProxyJump \"%s\"",
1450 filename, linenum, str + len);
1457 arg = argv_next(&ac, &av);
1458 if (!arg || *arg == '\0') {
1459 error("%.200s line %d: Missing argument.",
1463 value = a2port(arg);
1465 error("%.200s line %d: Bad port '%s'.",
1466 filename, linenum, arg);
1469 if (*activep && options->port == -1)
1470 options->port = value;
1473 case oConnectionAttempts:
1474 intptr = &options->connection_attempts;
1476 arg = argv_next(&ac, &av);
1477 if ((errstr = atoi_err(arg, &value)) != NULL) {
1478 error("%s line %d: integer value %s.",
1479 filename, linenum, errstr);
1482 if (*activep && *intptr == -1)
1487 arg = argv_next(&ac, &av);
1488 if (!arg || *arg == '\0') {
1489 error("%.200s line %d: Missing argument.",
1494 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1495 error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1496 filename, linenum, arg ? arg : "<NONE>");
1499 if (*activep && options->ciphers == NULL)
1500 options->ciphers = xstrdup(arg);
1504 arg = argv_next(&ac, &av);
1505 if (!arg || *arg == '\0') {
1506 error("%.200s line %d: Missing argument.",
1511 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1512 error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1513 filename, linenum, arg ? arg : "<NONE>");
1516 if (*activep && options->macs == NULL)
1517 options->macs = xstrdup(arg);
1520 case oKexAlgorithms:
1521 arg = argv_next(&ac, &av);
1522 if (!arg || *arg == '\0') {
1523 error("%.200s line %d: Missing argument.",
1528 !kex_names_valid(*arg == '+' || *arg == '^' ?
1530 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1531 filename, linenum, arg ? arg : "<NONE>");
1534 if (*activep && options->kex_algorithms == NULL)
1535 options->kex_algorithms = xstrdup(arg);
1538 case oHostKeyAlgorithms:
1539 charptr = &options->hostkeyalgorithms;
1542 arg = argv_next(&ac, &av);
1543 if (!arg || *arg == '\0') {
1544 error("%.200s line %d: Missing argument.",
1549 !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1550 arg + 1 : arg, 1, ca_only)) {
1551 error("%s line %d: Bad key types '%s'.",
1552 filename, linenum, arg ? arg : "<NONE>");
1555 if (*activep && *charptr == NULL)
1556 *charptr = xstrdup(arg);
1559 case oCASignatureAlgorithms:
1560 charptr = &options->ca_sign_algorithms;
1562 goto parse_pubkey_algos;
1565 log_level_ptr = &options->log_level;
1566 arg = argv_next(&ac, &av);
1567 value = log_level_number(arg);
1568 if (value == SYSLOG_LEVEL_NOT_SET) {
1569 error("%.200s line %d: unsupported log level '%s'",
1570 filename, linenum, arg ? arg : "<NONE>");
1573 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1574 *log_level_ptr = (LogLevel) value;
1578 log_facility_ptr = &options->log_facility;
1579 arg = argv_next(&ac, &av);
1580 value = log_facility_number(arg);
1581 if (value == SYSLOG_FACILITY_NOT_SET) {
1582 error("%.200s line %d: unsupported log facility '%s'",
1583 filename, linenum, arg ? arg : "<NONE>");
1586 if (*log_facility_ptr == -1)
1587 *log_facility_ptr = (SyslogFacility) value;
1591 cppptr = &options->log_verbose;
1592 uintptr = &options->num_log_verbose;
1594 while ((arg = argv_next(&ac, &av)) != NULL) {
1596 error("%s line %d: keyword %s empty argument",
1597 filename, linenum, keyword);
1600 /* Allow "none" only in first position */
1601 if (strcasecmp(arg, "none") == 0) {
1602 if (i > 0 || ac > 0) {
1603 error("%s line %d: keyword %s \"none\" "
1604 "argument must appear alone.",
1605 filename, linenum, keyword);
1610 if (*activep && *uintptr == 0) {
1611 *cppptr = xrecallocarray(*cppptr, *uintptr,
1612 *uintptr + 1, sizeof(**cppptr));
1613 (*cppptr)[(*uintptr)++] = xstrdup(arg);
1619 case oRemoteForward:
1620 case oDynamicForward:
1621 arg = argv_next(&ac, &av);
1622 if (!arg || *arg == '\0') {
1623 error("%.200s line %d: Missing argument.",
1628 remotefwd = (opcode == oRemoteForward);
1629 dynamicfwd = (opcode == oDynamicForward);
1632 arg2 = argv_next(&ac, &av);
1633 if (arg2 == NULL || *arg2 == '\0') {
1637 error("%.200s line %d: Missing target "
1638 "argument.", filename, linenum);
1642 /* construct a string for parse_forward */
1643 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1648 strlcpy(fwdarg, arg, sizeof(fwdarg));
1650 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1651 error("%.200s line %d: Bad forwarding specification.",
1658 add_remote_forward(options, &fwd);
1660 add_local_forward(options, &fwd);
1665 case oPermitRemoteOpen:
1666 uintptr = &options->num_permitted_remote_opens;
1667 cppptr = &options->permitted_remote_opens;
1668 uvalue = *uintptr; /* modified later */
1670 while ((arg = argv_next(&ac, &av)) != NULL) {
1671 arg2 = xstrdup(arg);
1672 /* Allow any/none only in first position */
1673 if (strcasecmp(arg, "none") == 0 ||
1674 strcasecmp(arg, "any") == 0) {
1675 if (i > 0 || ac > 0) {
1676 error("%s line %d: keyword %s \"%s\" "
1677 "argument must appear alone.",
1678 filename, linenum, keyword, arg);
1685 fatal("%s line %d: missing host in %s",
1687 lookup_opcode_name(opcode));
1689 p = cleanhostname(p);
1691 * don't want to use permitopen_port to avoid
1692 * dependency on channels.[ch] here.
1694 if (arg == NULL || (strcmp(arg, "*") != 0 &&
1695 a2port(arg) <= 0)) {
1696 fatal("%s line %d: bad port number "
1697 "in %s", filename, linenum,
1698 lookup_opcode_name(opcode));
1701 if (*activep && uvalue == 0) {
1702 opt_array_append(filename, linenum,
1703 lookup_opcode_name(opcode),
1704 cppptr, uintptr, arg2);
1710 fatal("%s line %d: missing %s specification",
1711 filename, linenum, lookup_opcode_name(opcode));
1714 case oClearAllForwardings:
1715 intptr = &options->clear_forwardings;
1720 error("Host directive not supported as a command-line "
1726 while ((arg = argv_next(&ac, &av)) != NULL) {
1728 error("%s line %d: keyword %s empty argument",
1729 filename, linenum, keyword);
1732 if ((flags & SSHCONF_NEVERMATCH) != 0) {
1736 negated = *arg == '!';
1739 if (match_pattern(host, arg)) {
1741 debug("%.200s line %d: Skipping Host "
1742 "block because of negated match "
1743 "for %.100s", filename, linenum,
1750 arg2 = arg; /* logged below */
1755 debug("%.200s line %d: Applying options for %.100s",
1756 filename, linenum, arg2);
1761 error("Host directive not supported as a command-line "
1765 value = match_cfg_line(options, &str, pw, host, original_host,
1766 flags & SSHCONF_FINAL, want_final_pass,
1769 error("%.200s line %d: Bad Match condition", filename,
1773 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1775 * If match_cfg_line() didn't consume all its arguments then
1776 * arrange for the extra arguments check below to fail.
1779 if (str == NULL || *str == '\0')
1784 intptr = &options->escape_char;
1785 arg = argv_next(&ac, &av);
1786 if (!arg || *arg == '\0') {
1787 error("%.200s line %d: Missing argument.",
1791 if (strcmp(arg, "none") == 0)
1792 value = SSH_ESCAPECHAR_NONE;
1793 else if (arg[1] == '\0')
1794 value = (u_char) arg[0];
1795 else if (arg[0] == '^' && arg[2] == 0 &&
1796 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1797 value = (u_char) arg[1] & 31;
1799 error("%.200s line %d: Bad escape character.",
1803 if (*activep && *intptr == -1)
1807 case oAddressFamily:
1808 intptr = &options->address_family;
1809 multistate_ptr = multistate_addressfamily;
1810 goto parse_multistate;
1812 case oEnableSSHKeysign:
1813 intptr = &options->enable_ssh_keysign;
1816 case oIdentitiesOnly:
1817 intptr = &options->identities_only;
1820 case oServerAliveInterval:
1821 intptr = &options->server_alive_interval;
1824 case oServerAliveCountMax:
1825 intptr = &options->server_alive_count_max;
1829 while ((arg = argv_next(&ac, &av)) != NULL) {
1830 if (*arg == '\0' || strchr(arg, '=') != NULL) {
1831 error("%s line %d: Invalid environment name.",
1838 /* Removing an env var */
1839 rm_env(options, arg, filename, linenum);
1842 opt_array_append(filename, linenum,
1843 lookup_opcode_name(opcode),
1844 &options->send_env, &options->num_send_env, arg);
1849 value = options->num_setenv;
1850 while ((arg = argv_next(&ac, &av)) != NULL) {
1851 if (strchr(arg, '=') == NULL) {
1852 error("%s line %d: Invalid SetEnv.",
1856 if (!*activep || value != 0)
1858 if (lookup_setenv_in_list(arg, options->setenv,
1859 options->num_setenv) != NULL) {
1860 debug2("%s line %d: ignoring duplicate env "
1861 "name \"%.64s\"", filename, linenum, arg);
1864 opt_array_append(filename, linenum,
1865 lookup_opcode_name(opcode),
1866 &options->setenv, &options->num_setenv, arg);
1871 charptr = &options->control_path;
1874 case oControlMaster:
1875 intptr = &options->control_master;
1876 multistate_ptr = multistate_controlmaster;
1877 goto parse_multistate;
1879 case oControlPersist:
1880 /* no/false/yes/true, or a time spec */
1881 intptr = &options->control_persist;
1882 arg = argv_next(&ac, &av);
1883 if (!arg || *arg == '\0') {
1884 error("%.200s line %d: Missing ControlPersist"
1885 " argument.", filename, linenum);
1889 value2 = 0; /* timeout */
1890 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1892 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1894 else if ((value2 = convtime(arg)) >= 0)
1897 error("%.200s line %d: Bad ControlPersist argument.",
1901 if (*activep && *intptr == -1) {
1903 options->control_persist_timeout = value2;
1907 case oHashKnownHosts:
1908 intptr = &options->hash_known_hosts;
1912 intptr = &options->tun_open;
1913 multistate_ptr = multistate_tunnel;
1914 goto parse_multistate;
1917 arg = argv_next(&ac, &av);
1918 if (!arg || *arg == '\0') {
1919 error("%.200s line %d: Missing argument.",
1923 value = a2tun(arg, &value2);
1924 if (value == SSH_TUNID_ERR) {
1925 error("%.200s line %d: Bad tun device.",
1929 if (*activep && options->tun_local == -1) {
1930 options->tun_local = value;
1931 options->tun_remote = value2;
1936 charptr = &options->local_command;
1939 case oPermitLocalCommand:
1940 intptr = &options->permit_local_command;
1943 case oRemoteCommand:
1944 charptr = &options->remote_command;
1947 case oVisualHostKey:
1948 intptr = &options->visual_host_key;
1953 error("Include directive not supported as a "
1954 "command-line option");
1958 while ((arg = argv_next(&ac, &av)) != NULL) {
1960 error("%s line %d: keyword %s empty argument",
1961 filename, linenum, keyword);
1965 * Ensure all paths are anchored. User configuration
1966 * files may begin with '~/' but system configurations
1967 * must not. If the path is relative, then treat it
1968 * as living in ~/.ssh for user configurations or
1969 * /etc/ssh for system ones.
1971 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1972 error("%.200s line %d: bad include path %s.",
1973 filename, linenum, arg);
1976 if (!path_absolute(arg) && *arg != '~') {
1977 xasprintf(&arg2, "%s/%s",
1978 (flags & SSHCONF_USERCONF) ?
1979 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1981 arg2 = xstrdup(arg);
1982 memset(&gl, 0, sizeof(gl));
1983 r = glob(arg2, GLOB_TILDE, NULL, &gl);
1984 if (r == GLOB_NOMATCH) {
1985 debug("%.200s line %d: include %s matched no "
1986 "files",filename, linenum, arg2);
1989 } else if (r != 0) {
1990 error("%.200s line %d: glob failed for %s.",
1991 filename, linenum, arg2);
1996 for (i = 0; i < gl.gl_pathc; i++) {
1997 debug3("%.200s line %d: Including file %s "
1998 "depth %d%s", filename, linenum,
1999 gl.gl_pathv[i], depth,
2000 oactive ? "" : " (parse only)");
2001 r = read_config_file_depth(gl.gl_pathv[i],
2002 pw, host, original_host, options,
2003 flags | SSHCONF_CHECKPERM |
2004 (oactive ? 0 : SSHCONF_NEVERMATCH),
2005 activep, want_final_pass, depth + 1);
2006 if (r != 1 && errno != ENOENT) {
2007 error("Can't open user config file "
2008 "%.100s: %.100s", gl.gl_pathv[i],
2014 * don't let Match in includes clobber the
2015 * containing file's Match state.
2028 arg = argv_next(&ac, &av);
2029 if ((value = parse_ipqos(arg)) == -1) {
2030 error("%s line %d: Bad IPQoS value: %s",
2031 filename, linenum, arg);
2034 arg = argv_next(&ac, &av);
2037 else if ((value2 = parse_ipqos(arg)) == -1) {
2038 error("%s line %d: Bad IPQoS value: %s",
2039 filename, linenum, arg);
2042 if (*activep && options->ip_qos_interactive == -1) {
2043 options->ip_qos_interactive = value;
2044 options->ip_qos_bulk = value2;
2049 intptr = &options->request_tty;
2050 multistate_ptr = multistate_requesttty;
2051 goto parse_multistate;
2054 intptr = &options->session_type;
2055 multistate_ptr = multistate_sessiontype;
2056 goto parse_multistate;
2059 intptr = &options->stdin_null;
2062 case oForkAfterAuthentication:
2063 intptr = &options->fork_after_authentication;
2066 case oIgnoreUnknown:
2067 charptr = &options->ignored_unknown;
2070 case oProxyUseFdpass:
2071 intptr = &options->proxy_use_fdpass;
2074 case oCanonicalDomains:
2075 value = options->num_canonical_domains != 0;
2077 while ((arg = argv_next(&ac, &av)) != NULL) {
2079 error("%s line %d: keyword %s empty argument",
2080 filename, linenum, keyword);
2083 /* Allow "none" only in first position */
2084 if (strcasecmp(arg, "none") == 0) {
2085 if (i > 0 || ac > 0) {
2086 error("%s line %d: keyword %s \"none\" "
2087 "argument must appear alone.",
2088 filename, linenum, keyword);
2093 if (!valid_domain(arg, 1, &errstr)) {
2094 error("%s line %d: %s", filename, linenum,
2098 if (!*activep || value)
2100 if (options->num_canonical_domains >=
2101 MAX_CANON_DOMAINS) {
2102 error("%s line %d: too many hostname suffixes.",
2106 options->canonical_domains[
2107 options->num_canonical_domains++] = xstrdup(arg);
2111 case oCanonicalizePermittedCNAMEs:
2112 value = options->num_permitted_cnames != 0;
2114 while ((arg = argv_next(&ac, &av)) != NULL) {
2116 * Either 'none' (only in first position), '*' for
2117 * everything or 'list:list'
2119 if (strcasecmp(arg, "none") == 0) {
2120 if (i > 0 || ac > 0) {
2121 error("%s line %d: keyword %s \"none\" "
2122 "argument must appear alone.",
2123 filename, linenum, keyword);
2127 } else if (strcmp(arg, "*") == 0) {
2131 if ((arg2 = strchr(arg, ':')) == NULL ||
2133 error("%s line %d: "
2134 "Invalid permitted CNAME \"%s\"",
2135 filename, linenum, arg);
2142 if (!*activep || value)
2144 if (options->num_permitted_cnames >=
2145 MAX_CANON_DOMAINS) {
2146 error("%s line %d: too many permitted CNAMEs.",
2150 cname = options->permitted_cnames +
2151 options->num_permitted_cnames++;
2152 cname->source_list = xstrdup(arg);
2153 cname->target_list = xstrdup(arg2);
2157 case oCanonicalizeHostname:
2158 intptr = &options->canonicalize_hostname;
2159 multistate_ptr = multistate_canonicalizehostname;
2160 goto parse_multistate;
2162 case oCanonicalizeMaxDots:
2163 intptr = &options->canonicalize_max_dots;
2166 case oCanonicalizeFallbackLocal:
2167 intptr = &options->canonicalize_fallback_local;
2170 case oStreamLocalBindMask:
2171 arg = argv_next(&ac, &av);
2172 if (!arg || *arg == '\0') {
2173 error("%.200s line %d: Missing StreamLocalBindMask "
2174 "argument.", filename, linenum);
2177 /* Parse mode in octal format */
2178 value = strtol(arg, &endofnumber, 8);
2179 if (arg == endofnumber || value < 0 || value > 0777) {
2180 error("%.200s line %d: Bad mask.", filename, linenum);
2183 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2186 case oStreamLocalBindUnlink:
2187 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2190 case oRevokedHostKeys:
2191 charptr = &options->revoked_host_keys;
2194 case oFingerprintHash:
2195 intptr = &options->fingerprint_hash;
2196 arg = argv_next(&ac, &av);
2197 if (!arg || *arg == '\0') {
2198 error("%.200s line %d: Missing argument.",
2202 if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2203 error("%.200s line %d: Invalid hash algorithm \"%s\".",
2204 filename, linenum, arg);
2207 if (*activep && *intptr == -1)
2211 case oUpdateHostkeys:
2212 intptr = &options->update_hostkeys;
2213 multistate_ptr = multistate_yesnoask;
2214 goto parse_multistate;
2216 case oHostbasedAcceptedAlgorithms:
2217 charptr = &options->hostbased_accepted_algos;
2219 goto parse_pubkey_algos;
2221 case oPubkeyAcceptedAlgorithms:
2222 charptr = &options->pubkey_accepted_algos;
2224 goto parse_pubkey_algos;
2226 case oAddKeysToAgent:
2227 arg = argv_next(&ac, &av);
2228 arg2 = argv_next(&ac, &av);
2229 value = parse_multistate_value(arg, filename, linenum,
2230 multistate_yesnoaskconfirm);
2231 value2 = 0; /* unlimited lifespan by default */
2232 if (value == 3 && arg2 != NULL) {
2233 /* allow "AddKeysToAgent confirm 5m" */
2234 if ((value2 = convtime(arg2)) == -1) {
2235 error("%s line %d: invalid time value.",
2239 } else if (value == -1 && arg2 == NULL) {
2240 if ((value2 = convtime(arg)) == -1) {
2241 error("%s line %d: unsupported option",
2245 value = 1; /* yes */
2246 } else if (value == -1 || arg2 != NULL) {
2247 error("%s line %d: unsupported option",
2251 if (*activep && options->add_keys_to_agent == -1) {
2252 options->add_keys_to_agent = value;
2253 options->add_keys_to_agent_lifespan = value2;
2257 case oIdentityAgent:
2258 charptr = &options->identity_agent;
2259 arg = argv_next(&ac, &av);
2260 if (!arg || *arg == '\0') {
2261 error("%.200s line %d: Missing argument.",
2266 /* Extra validation if the string represents an env var. */
2267 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2268 error("%.200s line %d: Invalid environment expansion "
2269 "%s.", filename, linenum, arg);
2273 /* check for legacy environment format */
2274 if (arg[0] == '$' && arg[1] != '{' &&
2275 !valid_env_name(arg + 1)) {
2276 error("%.200s line %d: Invalid environment name %s.",
2277 filename, linenum, arg);
2280 if (*activep && *charptr == NULL)
2281 *charptr = xstrdup(arg);
2284 case oEnableEscapeCommandline:
2285 intptr = &options->enable_escape_commandline;
2288 case oRequiredRSASize:
2289 intptr = &options->required_rsa_size;
2292 case oObscureKeystrokeTiming:
2294 while ((arg = argv_next(&ac, &av)) != NULL) {
2296 error("%s line %d: invalid arguments",
2300 if (strcmp(arg, "yes") == 0 ||
2301 strcmp(arg, "true") == 0)
2302 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2303 else if (strcmp(arg, "no") == 0 ||
2304 strcmp(arg, "false") == 0)
2306 else if (strncmp(arg, "interval:", 9) == 0) {
2307 if ((errstr = atoi_err(arg + 9,
2309 error("%s line %d: integer value %s.",
2310 filename, linenum, errstr);
2313 if (value <= 0 || value > 1000) {
2314 error("%s line %d: value out of range.",
2319 error("%s line %d: unsupported argument \"%s\"",
2320 filename, linenum, arg);
2325 error("%s line %d: missing argument",
2329 intptr = &options->obscure_keystroke_timing_interval;
2330 if (*activep && *intptr == -1)
2334 case oChannelTimeout:
2335 uvalue = options->num_channel_timeouts;
2337 while ((arg = argv_next(&ac, &av)) != NULL) {
2338 /* Allow "none" only in first position */
2339 if (strcasecmp(arg, "none") == 0) {
2340 if (i > 0 || ac > 0) {
2341 error("%s line %d: keyword %s \"none\" "
2342 "argument must appear alone.",
2343 filename, linenum, keyword);
2346 } else if (parse_pattern_interval(arg,
2348 fatal("%s line %d: invalid channel timeout %s",
2349 filename, linenum, arg);
2351 if (!*activep || uvalue != 0)
2353 opt_array_append(filename, linenum, keyword,
2354 &options->channel_timeouts,
2355 &options->num_channel_timeouts, arg);
2360 debug("%s line %d: Deprecated option \"%s\"",
2361 filename, linenum, keyword);
2366 error("%s line %d: Unsupported option \"%s\"",
2367 filename, linenum, keyword);
2372 error("%s line %d: Unimplemented opcode %d",
2373 filename, linenum, opcode);
2377 /* Check that there is no garbage at end of line. */
2379 error("%.200s line %d: keyword %s extra arguments "
2380 "at end of line", filename, linenum, keyword);
2387 argv_free(oav, oac);
2392 * Reads the config file and modifies the options accordingly. Options
2393 * should already be initialized before this call. This never returns if
2394 * there is an error. If the file does not exist, this returns 0.
2397 read_config_file(const char *filename, struct passwd *pw, const char *host,
2398 const char *original_host, Options *options, int flags,
2399 int *want_final_pass)
2403 return read_config_file_depth(filename, pw, host, original_host,
2404 options, flags, &active, want_final_pass, 0);
2407 #define READCONF_MAX_DEPTH 16
2409 read_config_file_depth(const char *filename, struct passwd *pw,
2410 const char *host, const char *original_host, Options *options,
2411 int flags, int *activep, int *want_final_pass, int depth)
2415 size_t linesize = 0;
2417 int bad_options = 0;
2419 if (depth < 0 || depth > READCONF_MAX_DEPTH)
2420 fatal("Too many recursive configuration includes");
2422 if ((f = fopen(filename, "r")) == NULL)
2425 if (flags & SSHCONF_CHECKPERM) {
2428 if (fstat(fileno(f), &sb) == -1)
2429 fatal("fstat %s: %s", filename, strerror(errno));
2430 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2431 (sb.st_mode & 022) != 0))
2432 fatal("Bad owner or permissions on %s", filename);
2435 debug("Reading configuration data %.200s", filename);
2438 * Mark that we are now processing the options. This flag is turned
2439 * on/off by Host specifications.
2442 while (getline(&line, &linesize, f) != -1) {
2443 /* Update line number counter. */
2446 * Trim out comments and strip whitespace.
2447 * NB - preserve newlines, they are needed to reproduce
2448 * line numbers later for error messages.
2450 if (process_config_line_depth(options, pw, host, original_host,
2451 line, filename, linenum, activep, flags, want_final_pass,
2457 if (bad_options > 0)
2458 fatal("%s: terminating, %d bad configuration options",
2459 filename, bad_options);
2463 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2465 option_clear_or_none(const char *o)
2467 return o == NULL || strcasecmp(o, "none") == 0;
2471 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2472 * Allowed to be called on non-final configuration.
2475 config_has_permitted_cnames(Options *options)
2477 if (options->num_permitted_cnames == 1 &&
2478 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2479 strcmp(options->permitted_cnames[0].target_list, "") == 0)
2481 return options->num_permitted_cnames > 0;
2485 * Initializes options to special values that indicate that they have not yet
2486 * been set. Read_config_file will only set options with this value. Options
2487 * are processed in the following order: command line, user config file,
2488 * system config file. Last, fill_default_options is called.
2492 initialize_options(Options * options)
2494 memset(options, 'X', sizeof(*options));
2495 options->host_arg = NULL;
2496 options->forward_agent = -1;
2497 options->forward_agent_sock_path = NULL;
2498 options->forward_x11 = -1;
2499 options->forward_x11_trusted = -1;
2500 options->forward_x11_timeout = -1;
2501 options->stdio_forward_host = NULL;
2502 options->stdio_forward_port = 0;
2503 options->clear_forwardings = -1;
2504 options->exit_on_forward_failure = -1;
2505 options->xauth_location = NULL;
2506 options->fwd_opts.gateway_ports = -1;
2507 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2508 options->fwd_opts.streamlocal_bind_unlink = -1;
2509 options->pubkey_authentication = -1;
2510 options->gss_authentication = -1;
2511 options->gss_deleg_creds = -1;
2512 options->password_authentication = -1;
2513 options->kbd_interactive_authentication = -1;
2514 options->kbd_interactive_devices = NULL;
2515 options->hostbased_authentication = -1;
2516 options->batch_mode = -1;
2517 options->check_host_ip = -1;
2518 options->strict_host_key_checking = -1;
2519 options->compression = -1;
2520 options->tcp_keep_alive = -1;
2522 options->address_family = -1;
2523 options->connection_attempts = -1;
2524 options->connection_timeout = -1;
2525 options->number_of_password_prompts = -1;
2526 options->ciphers = NULL;
2527 options->macs = NULL;
2528 options->kex_algorithms = NULL;
2529 options->hostkeyalgorithms = NULL;
2530 options->ca_sign_algorithms = NULL;
2531 options->num_identity_files = 0;
2532 memset(options->identity_keys, 0, sizeof(options->identity_keys));
2533 options->num_certificate_files = 0;
2534 memset(options->certificates, 0, sizeof(options->certificates));
2535 options->hostname = NULL;
2536 options->host_key_alias = NULL;
2537 options->proxy_command = NULL;
2538 options->jump_user = NULL;
2539 options->jump_host = NULL;
2540 options->jump_port = -1;
2541 options->jump_extra = NULL;
2542 options->user = NULL;
2543 options->escape_char = -1;
2544 options->num_system_hostfiles = 0;
2545 options->num_user_hostfiles = 0;
2546 options->local_forwards = NULL;
2547 options->num_local_forwards = 0;
2548 options->remote_forwards = NULL;
2549 options->num_remote_forwards = 0;
2550 options->permitted_remote_opens = NULL;
2551 options->num_permitted_remote_opens = 0;
2552 options->log_facility = SYSLOG_FACILITY_NOT_SET;
2553 options->log_level = SYSLOG_LEVEL_NOT_SET;
2554 options->num_log_verbose = 0;
2555 options->log_verbose = NULL;
2556 options->preferred_authentications = NULL;
2557 options->bind_address = NULL;
2558 options->bind_interface = NULL;
2559 options->pkcs11_provider = NULL;
2560 options->sk_provider = NULL;
2561 options->enable_ssh_keysign = - 1;
2562 options->no_host_authentication_for_localhost = - 1;
2563 options->identities_only = - 1;
2564 options->rekey_limit = - 1;
2565 options->rekey_interval = -1;
2566 options->verify_host_key_dns = -1;
2567 options->server_alive_interval = -1;
2568 options->server_alive_count_max = -1;
2569 options->send_env = NULL;
2570 options->num_send_env = 0;
2571 options->setenv = NULL;
2572 options->num_setenv = 0;
2573 options->control_path = NULL;
2574 options->control_master = -1;
2575 options->control_persist = -1;
2576 options->control_persist_timeout = 0;
2577 options->hash_known_hosts = -1;
2578 options->tun_open = -1;
2579 options->tun_local = -1;
2580 options->tun_remote = -1;
2581 options->local_command = NULL;
2582 options->permit_local_command = -1;
2583 options->remote_command = NULL;
2584 options->add_keys_to_agent = -1;
2585 options->add_keys_to_agent_lifespan = -1;
2586 options->identity_agent = NULL;
2587 options->visual_host_key = -1;
2588 options->ip_qos_interactive = -1;
2589 options->ip_qos_bulk = -1;
2590 options->request_tty = -1;
2591 options->session_type = -1;
2592 options->stdin_null = -1;
2593 options->fork_after_authentication = -1;
2594 options->proxy_use_fdpass = -1;
2595 options->ignored_unknown = NULL;
2596 options->num_canonical_domains = 0;
2597 options->num_permitted_cnames = 0;
2598 options->canonicalize_max_dots = -1;
2599 options->canonicalize_fallback_local = -1;
2600 options->canonicalize_hostname = -1;
2601 options->revoked_host_keys = NULL;
2602 options->fingerprint_hash = -1;
2603 options->update_hostkeys = -1;
2604 options->hostbased_accepted_algos = NULL;
2605 options->pubkey_accepted_algos = NULL;
2606 options->known_hosts_command = NULL;
2607 options->required_rsa_size = -1;
2608 options->enable_escape_commandline = -1;
2609 options->obscure_keystroke_timing_interval = -1;
2610 options->tag = NULL;
2611 options->channel_timeouts = NULL;
2612 options->num_channel_timeouts = 0;
2616 * A petite version of fill_default_options() that just fills the options
2617 * needed for hostname canonicalization to proceed.
2620 fill_default_options_for_canonicalization(Options *options)
2622 if (options->canonicalize_max_dots == -1)
2623 options->canonicalize_max_dots = 1;
2624 if (options->canonicalize_fallback_local == -1)
2625 options->canonicalize_fallback_local = 1;
2626 if (options->canonicalize_hostname == -1)
2627 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2631 * Called after processing other sources of option data, this fills those
2632 * options for which no value has been specified with their default values.
2635 fill_default_options(Options * options)
2637 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2638 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2641 if (options->forward_agent == -1)
2642 options->forward_agent = 0;
2643 if (options->forward_x11 == -1)
2644 options->forward_x11 = 0;
2645 if (options->forward_x11_trusted == -1)
2646 options->forward_x11_trusted = 0;
2647 if (options->forward_x11_timeout == -1)
2648 options->forward_x11_timeout = 1200;
2650 * stdio forwarding (-W) changes the default for these but we defer
2651 * setting the values so they can be overridden.
2653 if (options->exit_on_forward_failure == -1)
2654 options->exit_on_forward_failure =
2655 options->stdio_forward_host != NULL ? 1 : 0;
2656 if (options->clear_forwardings == -1)
2657 options->clear_forwardings =
2658 options->stdio_forward_host != NULL ? 1 : 0;
2659 if (options->clear_forwardings == 1)
2660 clear_forwardings(options);
2662 if (options->xauth_location == NULL)
2663 options->xauth_location = xstrdup(_PATH_XAUTH);
2664 if (options->fwd_opts.gateway_ports == -1)
2665 options->fwd_opts.gateway_ports = 0;
2666 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2667 options->fwd_opts.streamlocal_bind_mask = 0177;
2668 if (options->fwd_opts.streamlocal_bind_unlink == -1)
2669 options->fwd_opts.streamlocal_bind_unlink = 0;
2670 if (options->pubkey_authentication == -1)
2671 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2672 if (options->gss_authentication == -1)
2673 options->gss_authentication = 0;
2674 if (options->gss_deleg_creds == -1)
2675 options->gss_deleg_creds = 0;
2676 if (options->password_authentication == -1)
2677 options->password_authentication = 1;
2678 if (options->kbd_interactive_authentication == -1)
2679 options->kbd_interactive_authentication = 1;
2680 if (options->hostbased_authentication == -1)
2681 options->hostbased_authentication = 0;
2682 if (options->batch_mode == -1)
2683 options->batch_mode = 0;
2684 if (options->check_host_ip == -1)
2685 options->check_host_ip = 0;
2686 if (options->strict_host_key_checking == -1)
2687 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2688 if (options->compression == -1)
2689 options->compression = 0;
2690 if (options->tcp_keep_alive == -1)
2691 options->tcp_keep_alive = 1;
2692 if (options->port == -1)
2693 options->port = 0; /* Filled in ssh_connect. */
2694 if (options->address_family == -1)
2695 options->address_family = AF_UNSPEC;
2696 if (options->connection_attempts == -1)
2697 options->connection_attempts = 1;
2698 if (options->number_of_password_prompts == -1)
2699 options->number_of_password_prompts = 3;
2700 /* options->hostkeyalgorithms, default set in myproposals.h */
2701 if (options->add_keys_to_agent == -1) {
2702 options->add_keys_to_agent = 0;
2703 options->add_keys_to_agent_lifespan = 0;
2705 if (options->num_identity_files == 0) {
2706 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2707 #ifdef OPENSSL_HAS_ECC
2708 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2709 add_identity_file(options, "~/",
2710 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2712 add_identity_file(options, "~/",
2713 _PATH_SSH_CLIENT_ID_ED25519, 0);
2714 add_identity_file(options, "~/",
2715 _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2716 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2717 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2719 if (options->escape_char == -1)
2720 options->escape_char = '~';
2721 if (options->num_system_hostfiles == 0) {
2722 options->system_hostfiles[options->num_system_hostfiles++] =
2723 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2724 options->system_hostfiles[options->num_system_hostfiles++] =
2725 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2727 if (options->update_hostkeys == -1) {
2728 if (options->verify_host_key_dns <= 0 &&
2729 (options->num_user_hostfiles == 0 ||
2730 (options->num_user_hostfiles == 1 && strcmp(options->
2731 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2732 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2734 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2736 if (options->num_user_hostfiles == 0) {
2737 options->user_hostfiles[options->num_user_hostfiles++] =
2738 xstrdup(_PATH_SSH_USER_HOSTFILE);
2739 options->user_hostfiles[options->num_user_hostfiles++] =
2740 xstrdup(_PATH_SSH_USER_HOSTFILE2);
2742 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2743 options->log_level = SYSLOG_LEVEL_INFO;
2744 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2745 options->log_facility = SYSLOG_FACILITY_USER;
2746 if (options->no_host_authentication_for_localhost == - 1)
2747 options->no_host_authentication_for_localhost = 0;
2748 if (options->identities_only == -1)
2749 options->identities_only = 0;
2750 if (options->enable_ssh_keysign == -1)
2751 options->enable_ssh_keysign = 0;
2752 if (options->rekey_limit == -1)
2753 options->rekey_limit = 0;
2754 if (options->rekey_interval == -1)
2755 options->rekey_interval = 0;
2756 if (options->verify_host_key_dns == -1)
2757 options->verify_host_key_dns = 0;
2758 if (options->server_alive_interval == -1)
2759 options->server_alive_interval = 0;
2760 if (options->server_alive_count_max == -1)
2761 options->server_alive_count_max = 3;
2762 if (options->control_master == -1)
2763 options->control_master = 0;
2764 if (options->control_persist == -1) {
2765 options->control_persist = 0;
2766 options->control_persist_timeout = 0;
2768 if (options->hash_known_hosts == -1)
2769 options->hash_known_hosts = 0;
2770 if (options->tun_open == -1)
2771 options->tun_open = SSH_TUNMODE_NO;
2772 if (options->tun_local == -1)
2773 options->tun_local = SSH_TUNID_ANY;
2774 if (options->tun_remote == -1)
2775 options->tun_remote = SSH_TUNID_ANY;
2776 if (options->permit_local_command == -1)
2777 options->permit_local_command = 0;
2778 if (options->visual_host_key == -1)
2779 options->visual_host_key = 0;
2780 if (options->ip_qos_interactive == -1)
2781 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2782 if (options->ip_qos_bulk == -1)
2783 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2784 if (options->request_tty == -1)
2785 options->request_tty = REQUEST_TTY_AUTO;
2786 if (options->session_type == -1)
2787 options->session_type = SESSION_TYPE_DEFAULT;
2788 if (options->stdin_null == -1)
2789 options->stdin_null = 0;
2790 if (options->fork_after_authentication == -1)
2791 options->fork_after_authentication = 0;
2792 if (options->proxy_use_fdpass == -1)
2793 options->proxy_use_fdpass = 0;
2794 if (options->canonicalize_max_dots == -1)
2795 options->canonicalize_max_dots = 1;
2796 if (options->canonicalize_fallback_local == -1)
2797 options->canonicalize_fallback_local = 1;
2798 if (options->canonicalize_hostname == -1)
2799 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2800 if (options->fingerprint_hash == -1)
2801 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2802 #ifdef ENABLE_SK_INTERNAL
2803 if (options->sk_provider == NULL)
2804 options->sk_provider = xstrdup("internal");
2806 if (options->sk_provider == NULL)
2807 options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2809 if (options->required_rsa_size == -1)
2810 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2811 if (options->enable_escape_commandline == -1)
2812 options->enable_escape_commandline = 0;
2813 if (options->obscure_keystroke_timing_interval == -1) {
2814 options->obscure_keystroke_timing_interval =
2815 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2818 /* Expand KEX name lists */
2819 all_cipher = cipher_alg_list(',', 0);
2820 all_mac = mac_alg_list(',');
2821 all_kex = kex_alg_list(',');
2822 all_key = sshkey_alg_list(0, 0, 1, ',');
2823 all_sig = sshkey_alg_list(0, 1, 1, ',');
2824 /* remove unsupported algos from default lists */
2825 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2826 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2827 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2828 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2829 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2830 #define ASSEMBLE(what, defaults, all) \
2832 if ((r = kex_assemble_names(&options->what, \
2833 defaults, all)) != 0) { \
2834 error_fr(r, "%s", #what); \
2838 ASSEMBLE(ciphers, def_cipher, all_cipher);
2839 ASSEMBLE(macs, def_mac, all_mac);
2840 ASSEMBLE(kex_algorithms, def_kex, all_kex);
2841 ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2842 ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2843 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2846 #define CLEAR_ON_NONE(v) \
2848 if (option_clear_or_none(v)) { \
2853 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2855 if (options->nv == 1 && \
2856 strcasecmp(options->v[0], none) == 0) { \
2857 free(options->v[0]); \
2859 options->v = NULL; \
2863 CLEAR_ON_NONE(options->local_command);
2864 CLEAR_ON_NONE(options->remote_command);
2865 CLEAR_ON_NONE(options->proxy_command);
2866 CLEAR_ON_NONE(options->control_path);
2867 CLEAR_ON_NONE(options->revoked_host_keys);
2868 CLEAR_ON_NONE(options->pkcs11_provider);
2869 CLEAR_ON_NONE(options->sk_provider);
2870 CLEAR_ON_NONE(options->known_hosts_command);
2871 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2872 #undef CLEAR_ON_NONE
2873 #undef CLEAR_ON_NONE_ARRAY
2874 if (options->jump_host != NULL &&
2875 strcmp(options->jump_host, "none") == 0 &&
2876 options->jump_port == 0 && options->jump_user == NULL) {
2877 free(options->jump_host);
2878 options->jump_host = NULL;
2880 if (options->num_permitted_cnames == 1 &&
2881 !config_has_permitted_cnames(options)) {
2882 /* clean up CanonicalizePermittedCNAMEs=none */
2883 free(options->permitted_cnames[0].source_list);
2884 free(options->permitted_cnames[0].target_list);
2885 memset(options->permitted_cnames, '\0',
2886 sizeof(*options->permitted_cnames));
2887 options->num_permitted_cnames = 0;
2889 /* options->identity_agent distinguishes NULL from 'none' */
2890 /* options->user will be set in the main program if appropriate */
2891 /* options->hostname will be set in the main program if appropriate */
2892 /* options->host_key_alias should not be set by default */
2893 /* options->preferred_authentications will be set in ssh */
2912 free_options(Options *o)
2919 #define FREE_ARRAY(type, n, a) \
2922 for (_i = 0; _i < (n); _i++) \
2926 free(o->forward_agent_sock_path);
2927 free(o->xauth_location);
2928 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2929 free(o->log_verbose);
2932 free(o->hostkeyalgorithms);
2933 free(o->kex_algorithms);
2934 free(o->ca_sign_algorithms);
2936 free(o->host_key_alias);
2937 free(o->proxy_command);
2939 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2940 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2941 free(o->preferred_authentications);
2942 free(o->bind_address);
2943 free(o->bind_interface);
2944 free(o->pkcs11_provider);
2945 free(o->sk_provider);
2946 for (i = 0; i < o->num_identity_files; i++) {
2947 free(o->identity_files[i]);
2948 sshkey_free(o->identity_keys[i]);
2950 for (i = 0; i < o->num_certificate_files; i++) {
2951 free(o->certificate_files[i]);
2952 sshkey_free(o->certificates[i]);
2954 free(o->identity_agent);
2955 for (i = 0; i < o->num_local_forwards; i++) {
2956 free(o->local_forwards[i].listen_host);
2957 free(o->local_forwards[i].listen_path);
2958 free(o->local_forwards[i].connect_host);
2959 free(o->local_forwards[i].connect_path);
2961 free(o->local_forwards);
2962 for (i = 0; i < o->num_remote_forwards; i++) {
2963 free(o->remote_forwards[i].listen_host);
2964 free(o->remote_forwards[i].listen_path);
2965 free(o->remote_forwards[i].connect_host);
2966 free(o->remote_forwards[i].connect_path);
2968 free(o->remote_forwards);
2969 free(o->stdio_forward_host);
2970 FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2972 FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2974 free(o->control_path);
2975 free(o->local_command);
2976 free(o->remote_command);
2977 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2978 for (i = 0; i < o->num_permitted_cnames; i++) {
2979 free(o->permitted_cnames[i].source_list);
2980 free(o->permitted_cnames[i].target_list);
2982 free(o->revoked_host_keys);
2983 free(o->hostbased_accepted_algos);
2984 free(o->pubkey_accepted_algos);
2987 free(o->jump_extra);
2988 free(o->ignored_unknown);
2989 explicit_bzero(o, sizeof(*o));
3000 * parses the next field in a port forwarding specification.
3001 * sets fwd to the parsed field and advances p past the colon
3002 * or sets it to NULL at end of string.
3003 * returns 0 on success, else non-zero.
3006 parse_fwd_field(char **p, struct fwdarg *fwd)
3013 return -1; /* end of string */
3017 * A field escaped with square brackets is used literally.
3018 * XXX - allow ']' to be escaped via backslash?
3021 /* find matching ']' */
3022 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
3026 /* no matching ']' or not at end of field. */
3027 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
3029 /* NUL terminate the field and advance p past the colon */
3034 fwd->ispath = ispath;
3039 for (cp = *p; *cp != '\0'; cp++) {
3042 memmove(cp, cp + 1, strlen(cp + 1) + 1);
3056 fwd->ispath = ispath;
3063 * parses a string containing a port forwarding specification of the form:
3065 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3066 * listenpath:connectpath
3068 * [listenhost:]listenport
3069 * returns number of arguments parsed or zero on error
3072 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3074 struct fwdarg fwdargs[4];
3078 memset(fwd, 0, sizeof(*fwd));
3079 memset(fwdargs, 0, sizeof(fwdargs));
3082 * We expand environment variables before checking if we think they're
3083 * paths so that if ${VAR} expands to a fully qualified path it is
3084 * treated as a path.
3086 cp = p = dollar_expand(&err, fwdspec);
3087 if (p == NULL || err)
3090 /* skip leading spaces */
3091 while (isspace((u_char)*cp))
3094 for (i = 0; i < 4; ++i) {
3095 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3099 /* Check for trailing garbage */
3100 if (cp != NULL && *cp != '\0') {
3101 i = 0; /* failure */
3106 if (fwdargs[0].ispath) {
3107 fwd->listen_path = xstrdup(fwdargs[0].arg);
3108 fwd->listen_port = PORT_STREAMLOCAL;
3110 fwd->listen_host = NULL;
3111 fwd->listen_port = a2port(fwdargs[0].arg);
3113 fwd->connect_host = xstrdup("socks");
3117 if (fwdargs[0].ispath && fwdargs[1].ispath) {
3118 fwd->listen_path = xstrdup(fwdargs[0].arg);
3119 fwd->listen_port = PORT_STREAMLOCAL;
3120 fwd->connect_path = xstrdup(fwdargs[1].arg);
3121 fwd->connect_port = PORT_STREAMLOCAL;
3122 } else if (fwdargs[1].ispath) {
3123 fwd->listen_host = NULL;
3124 fwd->listen_port = a2port(fwdargs[0].arg);
3125 fwd->connect_path = xstrdup(fwdargs[1].arg);
3126 fwd->connect_port = PORT_STREAMLOCAL;
3128 fwd->listen_host = xstrdup(fwdargs[0].arg);
3129 fwd->listen_port = a2port(fwdargs[1].arg);
3130 fwd->connect_host = xstrdup("socks");
3135 if (fwdargs[0].ispath) {
3136 fwd->listen_path = xstrdup(fwdargs[0].arg);
3137 fwd->listen_port = PORT_STREAMLOCAL;
3138 fwd->connect_host = xstrdup(fwdargs[1].arg);
3139 fwd->connect_port = a2port(fwdargs[2].arg);
3140 } else if (fwdargs[2].ispath) {
3141 fwd->listen_host = xstrdup(fwdargs[0].arg);
3142 fwd->listen_port = a2port(fwdargs[1].arg);
3143 fwd->connect_path = xstrdup(fwdargs[2].arg);
3144 fwd->connect_port = PORT_STREAMLOCAL;
3146 fwd->listen_host = NULL;
3147 fwd->listen_port = a2port(fwdargs[0].arg);
3148 fwd->connect_host = xstrdup(fwdargs[1].arg);
3149 fwd->connect_port = a2port(fwdargs[2].arg);
3154 fwd->listen_host = xstrdup(fwdargs[0].arg);
3155 fwd->listen_port = a2port(fwdargs[1].arg);
3156 fwd->connect_host = xstrdup(fwdargs[2].arg);
3157 fwd->connect_port = a2port(fwdargs[3].arg);
3160 i = 0; /* failure */
3166 if (!(i == 1 || i == 2))
3169 if (!(i == 3 || i == 4)) {
3170 if (fwd->connect_path == NULL &&
3171 fwd->listen_path == NULL)
3174 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3178 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3179 (!remotefwd && fwd->listen_port == 0))
3181 if (fwd->connect_host != NULL &&
3182 strlen(fwd->connect_host) >= NI_MAXHOST)
3185 * XXX - if connecting to a remote socket, max sun len may not
3188 if (fwd->connect_path != NULL &&
3189 strlen(fwd->connect_path) >= PATH_MAX_SUN)
3191 if (fwd->listen_host != NULL &&
3192 strlen(fwd->listen_host) >= NI_MAXHOST)
3194 if (fwd->listen_path != NULL &&
3195 strlen(fwd->listen_path) >= PATH_MAX_SUN)
3201 free(fwd->connect_host);
3202 fwd->connect_host = NULL;
3203 free(fwd->connect_path);
3204 fwd->connect_path = NULL;
3205 free(fwd->listen_host);
3206 fwd->listen_host = NULL;
3207 free(fwd->listen_path);
3208 fwd->listen_path = NULL;
3213 parse_jump(const char *s, Options *o, int active)
3215 char *orig, *sdup, *cp;
3216 char *host = NULL, *user = NULL;
3217 int r, ret = -1, port = -1, first;
3219 active &= o->proxy_command == NULL && o->jump_host == NULL;
3221 orig = sdup = xstrdup(s);
3223 /* Remove comment and trailing whitespace */
3224 if ((cp = strchr(orig, '#')) != NULL)
3230 if (strcasecmp(s, "none") == 0)
3232 if ((cp = strrchr(sdup, ',')) == NULL)
3233 cp = sdup; /* last */
3238 /* First argument and configuration is active */
3239 r = parse_ssh_uri(cp, &user, &host, &port);
3240 if (r == -1 || (r == 1 &&
3241 parse_user_host_port(cp, &user, &host, &port) != 0))
3244 /* Subsequent argument or inactive configuration */
3245 r = parse_ssh_uri(cp, NULL, NULL, NULL);
3246 if (r == -1 || (r == 1 &&
3247 parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3250 first = 0; /* only check syntax for subsequent hosts */
3251 } while (cp != sdup);
3254 if (strcasecmp(s, "none") == 0) {
3255 o->jump_host = xstrdup("none");
3258 o->jump_user = user;
3259 o->jump_host = host;
3260 o->jump_port = port;
3261 o->proxy_command = xstrdup("none");
3263 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3264 o->jump_extra = xstrdup(s);
3265 o->jump_extra[cp - s] = '\0';
3278 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3280 char *user = NULL, *host = NULL, *path = NULL;
3283 r = parse_uri("ssh", uri, &user, &host, &port, &path);
3284 if (r == 0 && path != NULL)
3285 r = -1; /* path not allowed */
3287 if (userp != NULL) {
3291 if (hostp != NULL) {
3304 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3306 fmt_multistate_int(int val, const struct multistate *m)
3310 for (i = 0; m[i].key != NULL; i++) {
3311 if (m[i].value == val)
3318 fmt_intarg(OpCodes code, int val)
3323 case oAddressFamily:
3324 return fmt_multistate_int(val, multistate_addressfamily);
3325 case oVerifyHostKeyDNS:
3326 case oUpdateHostkeys:
3327 return fmt_multistate_int(val, multistate_yesnoask);
3328 case oStrictHostKeyChecking:
3329 return fmt_multistate_int(val, multistate_strict_hostkey);
3330 case oControlMaster:
3331 return fmt_multistate_int(val, multistate_controlmaster);
3333 return fmt_multistate_int(val, multistate_tunnel);
3335 return fmt_multistate_int(val, multistate_requesttty);
3337 return fmt_multistate_int(val, multistate_sessiontype);
3338 case oCanonicalizeHostname:
3339 return fmt_multistate_int(val, multistate_canonicalizehostname);
3340 case oAddKeysToAgent:
3341 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3342 case oPubkeyAuthentication:
3343 return fmt_multistate_int(val, multistate_pubkey_auth);
3344 case oFingerprintHash:
3345 return ssh_digest_alg_name(val);
3359 lookup_opcode_name(OpCodes code)
3363 for (i = 0; keywords[i].name != NULL; i++)
3364 if (keywords[i].opcode == code)
3365 return(keywords[i].name);
3370 dump_cfg_int(OpCodes code, int val)
3372 if (code == oObscureKeystrokeTiming) {
3374 printf("%s no\n", lookup_opcode_name(code));
3376 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3377 printf("%s yes\n", lookup_opcode_name(code));
3382 printf("%s %d\n", lookup_opcode_name(code), val);
3386 dump_cfg_fmtint(OpCodes code, int val)
3388 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3392 dump_cfg_string(OpCodes code, const char *val)
3396 printf("%s %s\n", lookup_opcode_name(code), val);
3400 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3404 for (i = 0; i < count; i++)
3405 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3409 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3413 printf("%s", lookup_opcode_name(code));
3416 for (i = 0; i < count; i++)
3417 printf(" %s", vals[i]);
3422 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3424 const struct Forward *fwd;
3427 /* oDynamicForward */
3428 for (i = 0; i < count; i++) {
3430 if (code == oDynamicForward && fwd->connect_host != NULL &&
3431 strcmp(fwd->connect_host, "socks") != 0)
3433 if (code == oLocalForward && fwd->connect_host != NULL &&
3434 strcmp(fwd->connect_host, "socks") == 0)
3436 printf("%s", lookup_opcode_name(code));
3437 if (fwd->listen_port == PORT_STREAMLOCAL)
3438 printf(" %s", fwd->listen_path);
3439 else if (fwd->listen_host == NULL)
3440 printf(" %d", fwd->listen_port);
3443 fwd->listen_host, fwd->listen_port);
3445 if (code != oDynamicForward) {
3446 if (fwd->connect_port == PORT_STREAMLOCAL)
3447 printf(" %s", fwd->connect_path);
3448 else if (fwd->connect_host == NULL)
3449 printf(" %d", fwd->connect_port);
3452 fwd->connect_host, fwd->connect_port);
3460 dump_client_config(Options *o, const char *host)
3463 char buf[8], *all_key;
3466 * Expand HostKeyAlgorithms name lists. This isn't handled in
3467 * fill_default_options() like the other algorithm lists because
3468 * the host key algorithms are by default dynamically chosen based
3469 * on the host's keys found in known_hosts.
3471 all_key = sshkey_alg_list(0, 0, 1, ',');
3472 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3474 fatal_fr(r, "expand HostKeyAlgorithms");
3477 /* Most interesting options first: user, host, port */
3478 dump_cfg_string(oHost, o->host_arg);
3479 dump_cfg_string(oUser, o->user);
3480 dump_cfg_string(oHostname, host);
3481 dump_cfg_int(oPort, o->port);
3484 dump_cfg_fmtint(oAddressFamily, o->address_family);
3485 dump_cfg_fmtint(oBatchMode, o->batch_mode);
3486 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3487 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3488 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3489 dump_cfg_fmtint(oCompression, o->compression);
3490 dump_cfg_fmtint(oControlMaster, o->control_master);
3491 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3492 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3493 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3494 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3495 dump_cfg_fmtint(oForwardX11, o->forward_x11);
3496 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3497 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3499 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3500 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3502 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3503 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3504 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3505 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3506 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3507 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3508 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3509 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3510 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3511 dump_cfg_fmtint(oRequestTTY, o->request_tty);
3512 dump_cfg_fmtint(oSessionType, o->session_type);
3513 dump_cfg_fmtint(oStdinNull, o->stdin_null);
3514 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3515 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3516 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3517 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3518 dump_cfg_fmtint(oTunnel, o->tun_open);
3519 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3520 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3521 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3522 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3524 /* Integer options */
3525 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3526 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3527 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3528 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3529 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3530 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3531 dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3532 dump_cfg_int(oObscureKeystrokeTiming,
3533 o->obscure_keystroke_timing_interval);
3535 /* String options */
3536 dump_cfg_string(oBindAddress, o->bind_address);
3537 dump_cfg_string(oBindInterface, o->bind_interface);
3538 dump_cfg_string(oCiphers, o->ciphers);
3539 dump_cfg_string(oControlPath, o->control_path);
3540 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3541 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3542 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3543 dump_cfg_string(oIdentityAgent, o->identity_agent);
3544 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3545 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3546 dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3547 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3548 dump_cfg_string(oLocalCommand, o->local_command);
3549 dump_cfg_string(oRemoteCommand, o->remote_command);
3550 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3551 dump_cfg_string(oMacs, o->macs);
3552 #ifdef ENABLE_PKCS11
3553 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3555 dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3556 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3557 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3558 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3559 dump_cfg_string(oXAuthLocation, o->xauth_location);
3560 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3561 dump_cfg_string(oTag, o->tag);
3564 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3565 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3566 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3568 /* String array options */
3569 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3570 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3571 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3572 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3573 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3574 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3575 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3576 dump_cfg_strarray_oneline(oLogVerbose,
3577 o->num_log_verbose, o->log_verbose);
3578 dump_cfg_strarray_oneline(oChannelTimeout,
3579 o->num_channel_timeouts, o->channel_timeouts);
3583 /* PermitRemoteOpen */
3584 if (o->num_permitted_remote_opens == 0)
3585 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3587 dump_cfg_strarray_oneline(oPermitRemoteOpen,
3588 o->num_permitted_remote_opens, o->permitted_remote_opens);
3590 /* AddKeysToAgent */
3591 if (o->add_keys_to_agent_lifespan <= 0)
3592 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3594 printf("addkeystoagent%s %d\n",
3595 o->add_keys_to_agent == 3 ? " confirm" : "",
3596 o->add_keys_to_agent_lifespan);
3600 if (o->forward_agent_sock_path == NULL)
3601 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3603 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3605 /* oConnectTimeout */
3606 if (o->connection_timeout == -1)
3607 printf("connecttimeout none\n");
3609 dump_cfg_int(oConnectTimeout, o->connection_timeout);
3612 printf("tunneldevice");
3613 if (o->tun_local == SSH_TUNID_ANY)
3616 printf(" %d", o->tun_local);
3617 if (o->tun_remote == SSH_TUNID_ANY)
3620 printf(":%d", o->tun_remote);
3623 /* oCanonicalizePermittedCNAMEs */
3624 printf("canonicalizePermittedcnames");
3625 if (o->num_permitted_cnames == 0)
3627 for (i = 0; i < o->num_permitted_cnames; i++) {
3628 printf(" %s:%s", o->permitted_cnames[i].source_list,
3629 o->permitted_cnames[i].target_list);
3633 /* oControlPersist */
3634 if (o->control_persist == 0 || o->control_persist_timeout == 0)
3635 dump_cfg_fmtint(oControlPersist, o->control_persist);
3637 dump_cfg_int(oControlPersist, o->control_persist_timeout);
3640 if (o->escape_char == SSH_ESCAPECHAR_NONE)
3641 printf("escapechar none\n");
3643 vis(buf, o->escape_char, VIS_WHITE, 0);
3644 printf("escapechar %s\n", buf);
3648 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3649 printf("%s\n", iptos2str(o->ip_qos_bulk));
3652 printf("rekeylimit %llu %d\n",
3653 (unsigned long long)o->rekey_limit, o->rekey_interval);
3655 /* oStreamLocalBindMask */
3656 printf("streamlocalbindmask 0%o\n",
3657 o->fwd_opts.streamlocal_bind_mask);
3660 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3662 /* oProxyCommand / oProxyJump */
3663 if (o->jump_host == NULL)
3664 dump_cfg_string(oProxyCommand, o->proxy_command);
3666 /* Check for numeric addresses */
3667 i = strchr(o->jump_host, ':') != NULL ||
3668 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3669 snprintf(buf, sizeof(buf), "%d", o->jump_port);
3670 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3671 /* optional additional jump spec */
3672 o->jump_extra == NULL ? "" : o->jump_extra,
3673 o->jump_extra == NULL ? "" : ",",
3675 o->jump_user == NULL ? "" : o->jump_user,
3676 o->jump_user == NULL ? "" : "@",
3677 /* opening [ if hostname is numeric */
3679 /* mandatory hostname */
3681 /* closing ] if hostname is numeric */
3683 /* optional port number */
3684 o->jump_port <= 0 ? "" : ":",
3685 o->jump_port <= 0 ? "" : buf);