1 /* $OpenBSD: readconf.c,v 1.375 2023/03/10 02:24:56 dtucker 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>
23 #include <netinet/in.h>
24 #include <netinet/in_systm.h>
25 #include <netinet/ip.h>
26 #include <arpa/inet.h>
42 #ifdef USE_SYSTEM_GLOB
45 # include "openbsd-compat/glob.h"
50 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
58 #include "pathnames.h"
67 #include "myproposal.h"
70 /* Format of the configuration file:
72 # Configuration data is parsed as follows:
73 # 1. command line options
74 # 2. user-specific file
76 # Any configuration value is only changed the first time it is set.
77 # Thus, host-specific definitions should be at the beginning of the
78 # configuration file, and defaults at the end.
80 # Host-specific declarations. These may override anything above. A single
81 # host may match multiple declarations; these are processed in the order
82 # that they are given in.
88 Hostname another.host.name.real.org
95 RemoteForward 9999 shadows.cs.hut.fi:9999
101 PasswordAuthentication no
105 ProxyCommand ssh-proxy %h %p
108 PublicKeyAuthentication no
112 PasswordAuthentication no
118 # Defaults for various options
122 PasswordAuthentication yes
123 StrictHostKeyChecking yes
125 IdentityFile ~/.ssh/identity
131 static int read_config_file_depth(const char *filename, struct passwd *pw,
132 const char *host, const char *original_host, Options *options,
133 int flags, int *activep, int *want_final_pass, int depth);
134 static int process_config_line_depth(Options *options, struct passwd *pw,
135 const char *host, const char *original_host, char *line,
136 const char *filename, int linenum, int *activep, int flags,
137 int *want_final_pass, int depth);
139 /* Keyword tokens. */
143 oHost, oMatch, oInclude,
144 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
145 oGatewayPorts, oExitOnForwardFailure,
146 oPasswordAuthentication,
148 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
150 oCertificateFile, oAddKeysToAgent, oIdentityAgent,
151 oUser, oEscapeChar, oProxyCommand,
152 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
153 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
154 oTCPKeepAlive, oNumberOfPasswordPrompts,
155 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
156 oPubkeyAuthentication,
157 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
158 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
159 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
160 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
161 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
162 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
163 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
164 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
166 oTunnel, oTunnelDevice,
167 oLocalCommand, oPermitLocalCommand, oRemoteCommand,
169 oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
170 oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
171 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
172 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
173 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
174 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
175 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
176 oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
177 oEnableEscapeCommandline,
178 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
181 /* Textual representations of the tokens. */
187 /* Deprecated options */
188 { "protocol", oIgnore }, /* NB. silently ignored */
189 { "cipher", oDeprecated },
190 { "fallbacktorsh", oDeprecated },
191 { "globalknownhostsfile2", oDeprecated },
192 { "rhostsauthentication", oDeprecated },
193 { "userknownhostsfile2", oDeprecated },
194 { "useroaming", oDeprecated },
195 { "usersh", oDeprecated },
196 { "useprivilegedport", oDeprecated },
198 /* Unsupported options */
199 { "afstokenpassing", oUnsupported },
200 { "kerberosauthentication", oUnsupported },
201 { "kerberostgtpassing", oUnsupported },
202 { "rsaauthentication", oUnsupported },
203 { "rhostsrsaauthentication", oUnsupported },
204 { "compressionlevel", oUnsupported },
206 /* Sometimes-unsupported options */
208 { "gssapiauthentication", oGssAuthentication },
209 { "gssapidelegatecredentials", oGssDelegateCreds },
211 { "gssapiauthentication", oUnsupported },
212 { "gssapidelegatecredentials", oUnsupported },
215 { "pkcs11provider", oPKCS11Provider },
216 { "smartcarddevice", oPKCS11Provider },
218 { "smartcarddevice", oUnsupported },
219 { "pkcs11provider", oUnsupported },
222 { "forwardagent", oForwardAgent },
223 { "forwardx11", oForwardX11 },
224 { "forwardx11trusted", oForwardX11Trusted },
225 { "forwardx11timeout", oForwardX11Timeout },
226 { "exitonforwardfailure", oExitOnForwardFailure },
227 { "xauthlocation", oXAuthLocation },
228 { "gatewayports", oGatewayPorts },
229 { "passwordauthentication", oPasswordAuthentication },
230 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
231 { "kbdinteractivedevices", oKbdInteractiveDevices },
232 { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
233 { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
234 { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */
235 { "pubkeyauthentication", oPubkeyAuthentication },
236 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
237 { "hostbasedauthentication", oHostbasedAuthentication },
238 { "identityfile", oIdentityFile },
239 { "identityfile2", oIdentityFile }, /* obsolete */
240 { "identitiesonly", oIdentitiesOnly },
241 { "certificatefile", oCertificateFile },
242 { "addkeystoagent", oAddKeysToAgent },
243 { "identityagent", oIdentityAgent },
244 { "hostname", oHostname },
245 { "hostkeyalias", oHostKeyAlias },
246 { "proxycommand", oProxyCommand },
248 { "ciphers", oCiphers },
250 { "remoteforward", oRemoteForward },
251 { "localforward", oLocalForward },
252 { "permitremoteopen", oPermitRemoteOpen },
256 { "escapechar", oEscapeChar },
257 { "globalknownhostsfile", oGlobalKnownHostsFile },
258 { "userknownhostsfile", oUserKnownHostsFile },
259 { "connectionattempts", oConnectionAttempts },
260 { "batchmode", oBatchMode },
261 { "checkhostip", oCheckHostIP },
262 { "stricthostkeychecking", oStrictHostKeyChecking },
263 { "compression", oCompression },
264 { "tcpkeepalive", oTCPKeepAlive },
265 { "keepalive", oTCPKeepAlive }, /* obsolete */
266 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
267 { "syslogfacility", oLogFacility },
268 { "loglevel", oLogLevel },
269 { "logverbose", oLogVerbose },
270 { "dynamicforward", oDynamicForward },
271 { "preferredauthentications", oPreferredAuthentications },
272 { "hostkeyalgorithms", oHostKeyAlgorithms },
273 { "casignaturealgorithms", oCASignatureAlgorithms },
274 { "bindaddress", oBindAddress },
275 { "bindinterface", oBindInterface },
276 { "clearallforwardings", oClearAllForwardings },
277 { "enablesshkeysign", oEnableSSHKeysign },
278 { "verifyhostkeydns", oVerifyHostKeyDNS },
279 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
280 { "rekeylimit", oRekeyLimit },
281 { "connecttimeout", oConnectTimeout },
282 { "addressfamily", oAddressFamily },
283 { "serveraliveinterval", oServerAliveInterval },
284 { "serveralivecountmax", oServerAliveCountMax },
285 { "sendenv", oSendEnv },
286 { "setenv", oSetEnv },
287 { "controlpath", oControlPath },
288 { "controlmaster", oControlMaster },
289 { "controlpersist", oControlPersist },
290 { "hashknownhosts", oHashKnownHosts },
291 { "include", oInclude },
292 { "tunnel", oTunnel },
293 { "tunneldevice", oTunnelDevice },
294 { "localcommand", oLocalCommand },
295 { "permitlocalcommand", oPermitLocalCommand },
296 { "remotecommand", oRemoteCommand },
297 { "visualhostkey", oVisualHostKey },
298 { "kexalgorithms", oKexAlgorithms },
300 { "requesttty", oRequestTTY },
301 { "sessiontype", oSessionType },
302 { "stdinnull", oStdinNull },
303 { "forkafterauthentication", oForkAfterAuthentication },
304 { "proxyusefdpass", oProxyUseFdpass },
305 { "canonicaldomains", oCanonicalDomains },
306 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
307 { "canonicalizehostname", oCanonicalizeHostname },
308 { "canonicalizemaxdots", oCanonicalizeMaxDots },
309 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
310 { "streamlocalbindmask", oStreamLocalBindMask },
311 { "streamlocalbindunlink", oStreamLocalBindUnlink },
312 { "revokedhostkeys", oRevokedHostKeys },
313 { "fingerprinthash", oFingerprintHash },
314 { "updatehostkeys", oUpdateHostkeys },
315 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
316 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
317 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
318 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
319 { "ignoreunknown", oIgnoreUnknown },
320 { "proxyjump", oProxyJump },
321 { "securitykeyprovider", oSecurityKeyProvider },
322 { "knownhostscommand", oKnownHostsCommand },
323 { "requiredrsasize", oRequiredRSASize },
324 { "enableescapecommandline", oEnableEscapeCommandline },
326 { "hpndisabled", oDeprecated },
327 { "hpnbuffersize", oDeprecated },
328 { "tcprcvbufpoll", oDeprecated },
329 { "tcprcvbuf", oDeprecated },
330 { "noneenabled", oUnsupported },
331 { "noneswitch", oUnsupported },
332 { "versionaddendum", oDeprecated },
337 static const char *lookup_opcode_name(OpCodes code);
340 kex_default_pk_alg(void)
344 if (pkalgs == NULL) {
347 all_key = sshkey_alg_list(0, 0, 1, ',');
348 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
355 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
358 struct ssh_digest_ctx *md;
359 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
361 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
362 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
363 ssh_digest_update(md, host, strlen(host)) < 0 ||
364 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
365 ssh_digest_update(md, user, strlen(user)) < 0 ||
366 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
367 fatal_f("mux digest failed");
369 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
373 * Adds a local TCP/IP port forward to options. Never returns if there is an
378 add_local_forward(Options *options, const struct Forward *newfwd)
383 /* Don't add duplicates */
384 for (i = 0; i < options->num_local_forwards; i++) {
385 if (forward_equals(newfwd, options->local_forwards + i))
388 options->local_forwards = xreallocarray(options->local_forwards,
389 options->num_local_forwards + 1,
390 sizeof(*options->local_forwards));
391 fwd = &options->local_forwards[options->num_local_forwards++];
393 fwd->listen_host = newfwd->listen_host;
394 fwd->listen_port = newfwd->listen_port;
395 fwd->listen_path = newfwd->listen_path;
396 fwd->connect_host = newfwd->connect_host;
397 fwd->connect_port = newfwd->connect_port;
398 fwd->connect_path = newfwd->connect_path;
402 * Adds a remote TCP/IP port forward to options. Never returns if there is
407 add_remote_forward(Options *options, const struct Forward *newfwd)
412 /* Don't add duplicates */
413 for (i = 0; i < options->num_remote_forwards; i++) {
414 if (forward_equals(newfwd, options->remote_forwards + i))
417 options->remote_forwards = xreallocarray(options->remote_forwards,
418 options->num_remote_forwards + 1,
419 sizeof(*options->remote_forwards));
420 fwd = &options->remote_forwards[options->num_remote_forwards++];
422 fwd->listen_host = newfwd->listen_host;
423 fwd->listen_port = newfwd->listen_port;
424 fwd->listen_path = newfwd->listen_path;
425 fwd->connect_host = newfwd->connect_host;
426 fwd->connect_port = newfwd->connect_port;
427 fwd->connect_path = newfwd->connect_path;
428 fwd->handle = newfwd->handle;
429 fwd->allocated_port = 0;
433 clear_forwardings(Options *options)
437 for (i = 0; i < options->num_local_forwards; i++) {
438 free(options->local_forwards[i].listen_host);
439 free(options->local_forwards[i].listen_path);
440 free(options->local_forwards[i].connect_host);
441 free(options->local_forwards[i].connect_path);
443 if (options->num_local_forwards > 0) {
444 free(options->local_forwards);
445 options->local_forwards = NULL;
447 options->num_local_forwards = 0;
448 for (i = 0; i < options->num_remote_forwards; i++) {
449 free(options->remote_forwards[i].listen_host);
450 free(options->remote_forwards[i].listen_path);
451 free(options->remote_forwards[i].connect_host);
452 free(options->remote_forwards[i].connect_path);
454 if (options->num_remote_forwards > 0) {
455 free(options->remote_forwards);
456 options->remote_forwards = NULL;
458 options->num_remote_forwards = 0;
459 options->tun_open = SSH_TUNMODE_NO;
463 add_certificate_file(Options *options, const char *path, int userprovided)
467 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
468 fatal("Too many certificate files specified (max %d)",
469 SSH_MAX_CERTIFICATE_FILES);
471 /* Avoid registering duplicates */
472 for (i = 0; i < options->num_certificate_files; i++) {
473 if (options->certificate_file_userprovided[i] == userprovided &&
474 strcmp(options->certificate_files[i], path) == 0) {
475 debug2_f("ignoring duplicate key %s", path);
480 options->certificate_file_userprovided[options->num_certificate_files] =
482 options->certificate_files[options->num_certificate_files++] =
487 add_identity_file(Options *options, const char *dir, const char *filename,
493 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
494 fatal("Too many identity files specified (max %d)",
495 SSH_MAX_IDENTITY_FILES);
497 if (dir == NULL) /* no dir, filename is absolute */
498 path = xstrdup(filename);
499 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
500 fatal("Identity file path %s too long", path);
502 /* Avoid registering duplicates */
503 for (i = 0; i < options->num_identity_files; i++) {
504 if (options->identity_file_userprovided[i] == userprovided &&
505 strcmp(options->identity_files[i], path) == 0) {
506 debug2_f("ignoring duplicate key %s", path);
512 options->identity_file_userprovided[options->num_identity_files] =
514 options->identity_files[options->num_identity_files++] = path;
518 default_ssh_port(void)
524 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
525 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
531 * Execute a command in a shell.
532 * Return its exit status or -1 on abnormal exit.
535 execute_in_shell(const char *cmd)
541 if ((shell = getenv("SHELL")) == NULL)
542 shell = _PATH_BSHELL;
544 if (access(shell, X_OK) == -1) {
545 fatal("Shell \"%s\" is not executable: %s",
546 shell, strerror(errno));
549 debug("Executing command: '%.500s'", cmd);
551 /* Fork and execute the command. */
552 if ((pid = fork()) == 0) {
555 if (stdfd_devnull(1, 1, 0) == -1)
556 fatal_f("stdfd_devnull failed");
557 closefrom(STDERR_FILENO + 1);
561 argv[2] = xstrdup(cmd);
564 execv(argv[0], argv);
565 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
566 /* Die with signal to make this error apparent to parent. */
567 ssh_signal(SIGTERM, SIG_DFL);
568 kill(getpid(), SIGTERM);
573 fatal_f("fork: %.100s", strerror(errno));
575 while (waitpid(pid, &status, 0) == -1) {
576 if (errno != EINTR && errno != EAGAIN)
577 fatal_f("waitpid: %s", strerror(errno));
579 if (!WIFEXITED(status)) {
580 error("command '%.100s' exited abnormally", cmd);
583 debug3("command returned status %d", WEXITSTATUS(status));
584 return WEXITSTATUS(status);
588 * Parse and execute a Match directive.
591 match_cfg_line(Options *options, char **condition, struct passwd *pw,
592 const char *host_arg, const char *original_host, int final_pass,
593 int *want_final_pass, const char *filename, int linenum)
595 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
597 int r, port, this_result, result = 1, attributes = 0, negate;
598 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
602 * Configuration is likely to be incomplete at this point so we
603 * must be prepared to use default values.
605 port = options->port <= 0 ? default_ssh_port() : options->port;
606 ruser = options->user == NULL ? pw->pw_name : options->user;
608 host = xstrdup(options->hostname);
609 } else if (options->hostname != NULL) {
610 /* NB. Please keep in sync with ssh.c:main() */
611 host = percent_expand(options->hostname,
612 "h", host_arg, (char *)NULL);
614 host = xstrdup(host_arg);
617 debug2("checking match for '%s' host %s originally %s",
618 cp, host, original_host);
619 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
620 /* Terminate on comment */
621 if (*attrib == '#') {
622 cp = NULL; /* mark all arguments consumed */
625 arg = criteria = NULL;
627 if ((negate = (attrib[0] == '!')))
629 /* Criterion "all" has no argument and must appear alone */
630 if (strcasecmp(attrib, "all") == 0) {
631 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
632 *arg != '\0' && *arg != '#')) {
633 error("%.200s line %d: '%s' cannot be combined "
634 "with other Match attributes",
635 filename, linenum, oattrib);
639 if (arg != NULL && *arg == '#')
640 cp = NULL; /* mark all arguments consumed */
642 result = negate ? 0 : 1;
646 /* criteria "final" and "canonical" have no argument */
647 if (strcasecmp(attrib, "canonical") == 0 ||
648 strcasecmp(attrib, "final") == 0) {
650 * If the config requests "Match final" then remember
651 * this so we can perform a second pass later.
653 if (strcasecmp(attrib, "final") == 0 &&
654 want_final_pass != NULL)
655 *want_final_pass = 1;
656 r = !!final_pass; /* force bitmask member to boolean */
657 if (r == (negate ? 1 : 0))
658 this_result = result = 0;
659 debug3("%.200s line %d: %smatched '%s'",
661 this_result ? "" : "not ", oattrib);
664 /* All other criteria require an argument */
665 if ((arg = strdelim(&cp)) == NULL ||
666 *arg == '\0' || *arg == '#') {
667 error("Missing Match criteria for %s", attrib);
671 if (strcasecmp(attrib, "host") == 0) {
672 criteria = xstrdup(host);
673 r = match_hostname(host, arg) == 1;
674 if (r == (negate ? 1 : 0))
675 this_result = result = 0;
676 } else if (strcasecmp(attrib, "originalhost") == 0) {
677 criteria = xstrdup(original_host);
678 r = match_hostname(original_host, arg) == 1;
679 if (r == (negate ? 1 : 0))
680 this_result = result = 0;
681 } else if (strcasecmp(attrib, "user") == 0) {
682 criteria = xstrdup(ruser);
683 r = match_pattern_list(ruser, arg, 0) == 1;
684 if (r == (negate ? 1 : 0))
685 this_result = result = 0;
686 } else if (strcasecmp(attrib, "localuser") == 0) {
687 criteria = xstrdup(pw->pw_name);
688 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
689 if (r == (negate ? 1 : 0))
690 this_result = result = 0;
691 } else if (strcasecmp(attrib, "exec") == 0) {
692 char *conn_hash_hex, *keyalias;
694 if (gethostname(thishost, sizeof(thishost)) == -1)
695 fatal("gethostname: %s", strerror(errno));
696 strlcpy(shorthost, thishost, sizeof(shorthost));
697 shorthost[strcspn(thishost, ".")] = '\0';
698 snprintf(portstr, sizeof(portstr), "%d", port);
699 snprintf(uidstr, sizeof(uidstr), "%llu",
700 (unsigned long long)pw->pw_uid);
701 conn_hash_hex = ssh_connection_hash(thishost, host,
703 keyalias = options->host_key_alias ?
704 options->host_key_alias : host;
706 cmd = percent_expand(arg,
721 /* skip execution if prior predicate failed */
722 debug3("%.200s line %d: skipped exec "
723 "\"%.100s\"", filename, linenum, cmd);
727 r = execute_in_shell(cmd);
729 fatal("%.200s line %d: match exec "
730 "'%.100s' error", filename,
733 criteria = xstrdup(cmd);
735 /* Force exit status to boolean */
737 if (r == (negate ? 1 : 0))
738 this_result = result = 0;
740 error("Unsupported Match attribute %s", attrib);
744 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
745 filename, linenum, this_result ? "": "not ",
749 if (attributes == 0) {
750 error("One or more attributes required for Match");
756 debug2("match %sfound", result ? "" : "not ");
762 /* Remove environment variable by pattern */
764 rm_env(Options *options, const char *arg, const char *filename, int linenum)
766 u_int i, j, onum_send_env = options->num_send_env;
768 /* Remove an environment variable */
769 for (i = 0; i < options->num_send_env; ) {
770 if (!match_pattern(options->send_env[i], arg + 1)) {
774 debug3("%s line %d: removing environment %s",
775 filename, linenum, options->send_env[i]);
776 free(options->send_env[i]);
777 options->send_env[i] = NULL;
778 for (j = i; j < options->num_send_env - 1; j++) {
779 options->send_env[j] = options->send_env[j + 1];
780 options->send_env[j + 1] = NULL;
782 options->num_send_env--;
783 /* NB. don't increment i */
785 if (onum_send_env != options->num_send_env) {
786 options->send_env = xrecallocarray(options->send_env,
787 onum_send_env, options->num_send_env,
788 sizeof(*options->send_env));
793 * Returns the number of the token pointed to by cp or oBadOption.
796 parse_token(const char *cp, const char *filename, int linenum,
797 const char *ignored_unknown)
801 for (i = 0; keywords[i].name; i++)
802 if (strcmp(cp, keywords[i].name) == 0)
803 return keywords[i].opcode;
804 if (ignored_unknown != NULL &&
805 match_pattern_list(cp, ignored_unknown, 1) == 1)
806 return oIgnoredUnknownOption;
807 error("%s: line %d: Bad configuration option: %s",
808 filename, linenum, cp);
812 /* Multistate option parsing */
817 static const struct multistate multistate_flag[] = {
824 static const struct multistate multistate_yesnoask[] = {
832 static const struct multistate multistate_strict_hostkey[] = {
833 { "true", SSH_STRICT_HOSTKEY_YES },
834 { "false", SSH_STRICT_HOSTKEY_OFF },
835 { "yes", SSH_STRICT_HOSTKEY_YES },
836 { "no", SSH_STRICT_HOSTKEY_OFF },
837 { "ask", SSH_STRICT_HOSTKEY_ASK },
838 { "off", SSH_STRICT_HOSTKEY_OFF },
839 { "accept-new", SSH_STRICT_HOSTKEY_NEW },
842 static const struct multistate multistate_yesnoaskconfirm[] = {
851 static const struct multistate multistate_addressfamily[] = {
853 { "inet6", AF_INET6 },
854 { "any", AF_UNSPEC },
857 static const struct multistate multistate_controlmaster[] = {
858 { "true", SSHCTL_MASTER_YES },
859 { "yes", SSHCTL_MASTER_YES },
860 { "false", SSHCTL_MASTER_NO },
861 { "no", SSHCTL_MASTER_NO },
862 { "auto", SSHCTL_MASTER_AUTO },
863 { "ask", SSHCTL_MASTER_ASK },
864 { "autoask", SSHCTL_MASTER_AUTO_ASK },
867 static const struct multistate multistate_tunnel[] = {
868 { "ethernet", SSH_TUNMODE_ETHERNET },
869 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
870 { "true", SSH_TUNMODE_DEFAULT },
871 { "yes", SSH_TUNMODE_DEFAULT },
872 { "false", SSH_TUNMODE_NO },
873 { "no", SSH_TUNMODE_NO },
876 static const struct multistate multistate_requesttty[] = {
877 { "true", REQUEST_TTY_YES },
878 { "yes", REQUEST_TTY_YES },
879 { "false", REQUEST_TTY_NO },
880 { "no", REQUEST_TTY_NO },
881 { "force", REQUEST_TTY_FORCE },
882 { "auto", REQUEST_TTY_AUTO },
885 static const struct multistate multistate_sessiontype[] = {
886 { "none", SESSION_TYPE_NONE },
887 { "subsystem", SESSION_TYPE_SUBSYSTEM },
888 { "default", SESSION_TYPE_DEFAULT },
891 static const struct multistate multistate_canonicalizehostname[] = {
892 { "true", SSH_CANONICALISE_YES },
893 { "false", SSH_CANONICALISE_NO },
894 { "yes", SSH_CANONICALISE_YES },
895 { "no", SSH_CANONICALISE_NO },
896 { "always", SSH_CANONICALISE_ALWAYS },
899 static const struct multistate multistate_pubkey_auth[] = {
900 { "true", SSH_PUBKEY_AUTH_ALL },
901 { "false", SSH_PUBKEY_AUTH_NO },
902 { "yes", SSH_PUBKEY_AUTH_ALL },
903 { "no", SSH_PUBKEY_AUTH_NO },
904 { "unbound", SSH_PUBKEY_AUTH_UNBOUND },
905 { "host-bound", SSH_PUBKEY_AUTH_HBOUND },
908 static const struct multistate multistate_compression[] = {
910 { "yes", COMP_ZLIB },
917 parse_multistate_value(const char *arg, const char *filename, int linenum,
918 const struct multistate *multistate_ptr)
922 if (!arg || *arg == '\0') {
923 error("%s line %d: missing argument.", filename, linenum);
926 for (i = 0; multistate_ptr[i].key != NULL; i++) {
927 if (strcasecmp(arg, multistate_ptr[i].key) == 0)
928 return multistate_ptr[i].value;
934 * Processes a single option line as used in the configuration files. This
935 * only sets those values that have not already been set.
938 process_config_line(Options *options, struct passwd *pw, const char *host,
939 const char *original_host, char *line, const char *filename,
940 int linenum, int *activep, int flags)
942 return process_config_line_depth(options, pw, host, original_host,
943 line, filename, linenum, activep, flags, NULL, 0);
946 #define WHITESPACE " \t\r\n"
948 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
949 const char *original_host, char *line, const char *filename,
950 int linenum, int *activep, int flags, int *want_final_pass, int depth)
952 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
953 char **cpptr, ***cppptr, fwdarg[256];
954 u_int i, *uintptr, uvalue, max_entries = 0;
955 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
956 int remotefwd, dynamicfwd;
957 LogLevel *log_level_ptr;
958 SyslogFacility *log_facility_ptr;
962 const struct multistate *multistate_ptr;
963 struct allowed_cname *cname;
966 char **oav = NULL, **av;
970 if (activep == NULL) { /* We are processing a command line directive */
975 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
976 if ((len = strlen(line)) == 0)
978 for (len--; len > 0; len--) {
979 if (strchr(WHITESPACE "\f", line[len]) == NULL)
985 /* Get the keyword. (Each line is supposed to begin with a keyword). */
986 if ((keyword = strdelim(&str)) == NULL)
988 /* Ignore leading whitespace. */
989 if (*keyword == '\0')
990 keyword = strdelim(&str);
991 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
993 /* Match lowercase keyword */
996 /* Prepare to parse remainder of line */
998 str += strspn(str, WHITESPACE);
999 if (str == NULL || *str == '\0') {
1000 error("%s line %d: no argument after keyword \"%s\"",
1001 filename, linenum, keyword);
1004 opcode = parse_token(keyword, filename, linenum,
1005 options->ignored_unknown);
1006 if (argv_split(str, &oac, &oav, 1) != 0) {
1007 error("%s line %d: invalid quotes", filename, linenum);
1015 /* don't panic, but count bad options */
1020 case oIgnoredUnknownOption:
1021 debug("%s line %d: Ignored unknown option \"%s\"",
1022 filename, linenum, keyword);
1025 case oConnectTimeout:
1026 intptr = &options->connection_timeout;
1028 arg = argv_next(&ac, &av);
1029 if (!arg || *arg == '\0') {
1030 error("%s line %d: missing time value.",
1034 if (strcmp(arg, "none") == 0)
1036 else if ((value = convtime(arg)) == -1) {
1037 error("%s line %d: invalid time value.",
1041 if (*activep && *intptr == -1)
1046 intptr = &options->forward_agent;
1048 arg = argv_next(&ac, &av);
1049 if (!arg || *arg == '\0') {
1050 error("%s line %d: missing argument.",
1056 multistate_ptr = multistate_flag;
1057 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1058 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1059 value = multistate_ptr[i].value;
1064 if (*activep && *intptr == -1)
1068 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1069 if (*activep && *intptr == -1)
1072 charptr = &options->forward_agent_sock_path;
1073 goto parse_agent_path;
1076 intptr = &options->forward_x11;
1078 multistate_ptr = multistate_flag;
1080 arg = argv_next(&ac, &av);
1081 if ((value = parse_multistate_value(arg, filename, linenum,
1082 multistate_ptr)) == -1) {
1083 error("%s line %d: unsupported option \"%s\".",
1084 filename, linenum, arg);
1087 if (*activep && *intptr == -1)
1091 case oForwardX11Trusted:
1092 intptr = &options->forward_x11_trusted;
1095 case oForwardX11Timeout:
1096 intptr = &options->forward_x11_timeout;
1100 intptr = &options->fwd_opts.gateway_ports;
1103 case oExitOnForwardFailure:
1104 intptr = &options->exit_on_forward_failure;
1107 case oPasswordAuthentication:
1108 intptr = &options->password_authentication;
1111 case oKbdInteractiveAuthentication:
1112 intptr = &options->kbd_interactive_authentication;
1115 case oKbdInteractiveDevices:
1116 charptr = &options->kbd_interactive_devices;
1119 case oPubkeyAuthentication:
1120 multistate_ptr = multistate_pubkey_auth;
1121 intptr = &options->pubkey_authentication;
1122 goto parse_multistate;
1124 case oHostbasedAuthentication:
1125 intptr = &options->hostbased_authentication;
1128 case oGssAuthentication:
1129 intptr = &options->gss_authentication;
1132 case oGssDelegateCreds:
1133 intptr = &options->gss_deleg_creds;
1137 intptr = &options->batch_mode;
1141 intptr = &options->check_host_ip;
1144 case oVerifyHostKeyDNS:
1145 intptr = &options->verify_host_key_dns;
1146 multistate_ptr = multistate_yesnoask;
1147 goto parse_multistate;
1149 case oStrictHostKeyChecking:
1150 intptr = &options->strict_host_key_checking;
1151 multistate_ptr = multistate_strict_hostkey;
1152 goto parse_multistate;
1155 intptr = &options->compression;
1156 multistate_ptr = multistate_compression;
1157 goto parse_multistate;
1160 intptr = &options->tcp_keep_alive;
1163 case oNoHostAuthenticationForLocalhost:
1164 intptr = &options->no_host_authentication_for_localhost;
1167 case oNumberOfPasswordPrompts:
1168 intptr = &options->number_of_password_prompts;
1172 arg = argv_next(&ac, &av);
1173 if (!arg || *arg == '\0') {
1174 error("%.200s line %d: Missing argument.", filename,
1178 if (strcmp(arg, "default") == 0) {
1181 if (scan_scaled(arg, &val64) == -1) {
1182 error("%.200s line %d: Bad number '%s': %s",
1183 filename, linenum, arg, strerror(errno));
1186 if (val64 != 0 && val64 < 16) {
1187 error("%.200s line %d: RekeyLimit too small",
1192 if (*activep && options->rekey_limit == -1)
1193 options->rekey_limit = val64;
1194 if (ac != 0) { /* optional rekey interval present */
1195 if (strcmp(av[0], "none") == 0) {
1196 (void)argv_next(&ac, &av); /* discard */
1199 intptr = &options->rekey_interval;
1205 arg = argv_next(&ac, &av);
1206 if (!arg || *arg == '\0') {
1207 error("%.200s line %d: Missing argument.",
1212 intptr = &options->num_identity_files;
1213 if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1214 error("%.200s line %d: Too many identity files "
1215 "specified (max %d).", filename, linenum,
1216 SSH_MAX_IDENTITY_FILES);
1219 add_identity_file(options, NULL,
1220 arg, flags & SSHCONF_USERCONF);
1224 case oCertificateFile:
1225 arg = argv_next(&ac, &av);
1226 if (!arg || *arg == '\0') {
1227 error("%.200s line %d: Missing argument.",
1232 intptr = &options->num_certificate_files;
1233 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1234 error("%.200s line %d: Too many certificate "
1235 "files specified (max %d).",
1237 SSH_MAX_CERTIFICATE_FILES);
1240 add_certificate_file(options, arg,
1241 flags & SSHCONF_USERCONF);
1245 case oXAuthLocation:
1246 charptr=&options->xauth_location;
1250 charptr = &options->user;
1252 arg = argv_next(&ac, &av);
1253 if (!arg || *arg == '\0') {
1254 error("%.200s line %d: Missing argument.",
1258 if (*activep && *charptr == NULL)
1259 *charptr = xstrdup(arg);
1262 case oGlobalKnownHostsFile:
1263 cpptr = (char **)&options->system_hostfiles;
1264 uintptr = &options->num_system_hostfiles;
1265 max_entries = SSH_MAX_HOSTS_FILES;
1268 value = *uintptr == 0; /* was array empty when we started? */
1269 while ((arg = argv_next(&ac, &av)) != NULL) {
1271 error("%s line %d: keyword %s empty argument",
1272 filename, linenum, keyword);
1275 /* Allow "none" only in first position */
1276 if (strcasecmp(arg, "none") == 0) {
1277 if (i > 0 || ac > 0) {
1278 error("%s line %d: keyword %s \"none\" "
1279 "argument must appear alone.",
1280 filename, linenum, keyword);
1285 if (*activep && value) {
1286 if ((*uintptr) >= max_entries) {
1287 error("%s line %d: too many %s "
1288 "entries.", filename, linenum,
1292 cpptr[(*uintptr)++] = xstrdup(arg);
1297 case oUserKnownHostsFile:
1298 cpptr = (char **)&options->user_hostfiles;
1299 uintptr = &options->num_user_hostfiles;
1300 max_entries = SSH_MAX_HOSTS_FILES;
1301 goto parse_char_array;
1304 charptr = &options->hostname;
1308 charptr = &options->host_key_alias;
1311 case oPreferredAuthentications:
1312 charptr = &options->preferred_authentications;
1316 charptr = &options->bind_address;
1319 case oBindInterface:
1320 charptr = &options->bind_interface;
1323 case oPKCS11Provider:
1324 charptr = &options->pkcs11_provider;
1327 case oSecurityKeyProvider:
1328 charptr = &options->sk_provider;
1331 case oKnownHostsCommand:
1332 charptr = &options->known_hosts_command;
1336 charptr = &options->proxy_command;
1337 /* Ignore ProxyCommand if ProxyJump already specified */
1338 if (options->jump_host != NULL)
1339 charptr = &options->jump_host; /* Skip below */
1342 error("%.200s line %d: Missing argument.",
1346 len = strspn(str, WHITESPACE "=");
1347 if (*activep && *charptr == NULL)
1348 *charptr = xstrdup(str + len);
1354 error("%.200s line %d: Missing argument.",
1358 len = strspn(str, WHITESPACE "=");
1360 if (parse_jump(str + len, options, *activep) == -1) {
1361 error("%.200s line %d: Invalid ProxyJump \"%s\"",
1362 filename, linenum, str + len);
1369 arg = argv_next(&ac, &av);
1370 if (!arg || *arg == '\0') {
1371 error("%.200s line %d: Missing argument.",
1375 value = a2port(arg);
1377 error("%.200s line %d: Bad port '%s'.",
1378 filename, linenum, arg);
1381 if (*activep && options->port == -1)
1382 options->port = value;
1385 case oConnectionAttempts:
1386 intptr = &options->connection_attempts;
1388 arg = argv_next(&ac, &av);
1389 if ((errstr = atoi_err(arg, &value)) != NULL) {
1390 error("%s line %d: integer value %s.",
1391 filename, linenum, errstr);
1394 if (*activep && *intptr == -1)
1399 arg = argv_next(&ac, &av);
1400 if (!arg || *arg == '\0') {
1401 error("%.200s line %d: Missing argument.",
1406 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1407 error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1408 filename, linenum, arg ? arg : "<NONE>");
1411 if (*activep && options->ciphers == NULL)
1412 options->ciphers = xstrdup(arg);
1416 arg = argv_next(&ac, &av);
1417 if (!arg || *arg == '\0') {
1418 error("%.200s line %d: Missing argument.",
1423 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1424 error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1425 filename, linenum, arg ? arg : "<NONE>");
1428 if (*activep && options->macs == NULL)
1429 options->macs = xstrdup(arg);
1432 case oKexAlgorithms:
1433 arg = argv_next(&ac, &av);
1434 if (!arg || *arg == '\0') {
1435 error("%.200s line %d: Missing argument.",
1440 !kex_names_valid(*arg == '+' || *arg == '^' ?
1442 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1443 filename, linenum, arg ? arg : "<NONE>");
1446 if (*activep && options->kex_algorithms == NULL)
1447 options->kex_algorithms = xstrdup(arg);
1450 case oHostKeyAlgorithms:
1451 charptr = &options->hostkeyalgorithms;
1453 arg = argv_next(&ac, &av);
1454 if (!arg || *arg == '\0') {
1455 error("%.200s line %d: Missing argument.",
1460 !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1461 arg + 1 : arg, 1)) {
1462 error("%s line %d: Bad key types '%s'.",
1463 filename, linenum, arg ? arg : "<NONE>");
1466 if (*activep && *charptr == NULL)
1467 *charptr = xstrdup(arg);
1470 case oCASignatureAlgorithms:
1471 charptr = &options->ca_sign_algorithms;
1472 goto parse_pubkey_algos;
1475 log_level_ptr = &options->log_level;
1476 arg = argv_next(&ac, &av);
1477 value = log_level_number(arg);
1478 if (value == SYSLOG_LEVEL_NOT_SET) {
1479 error("%.200s line %d: unsupported log level '%s'",
1480 filename, linenum, arg ? arg : "<NONE>");
1483 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1484 *log_level_ptr = (LogLevel) value;
1488 log_facility_ptr = &options->log_facility;
1489 arg = argv_next(&ac, &av);
1490 value = log_facility_number(arg);
1491 if (value == SYSLOG_FACILITY_NOT_SET) {
1492 error("%.200s line %d: unsupported log facility '%s'",
1493 filename, linenum, arg ? arg : "<NONE>");
1496 if (*log_facility_ptr == -1)
1497 *log_facility_ptr = (SyslogFacility) value;
1501 cppptr = &options->log_verbose;
1502 uintptr = &options->num_log_verbose;
1504 while ((arg = argv_next(&ac, &av)) != NULL) {
1506 error("%s line %d: keyword %s empty argument",
1507 filename, linenum, keyword);
1510 /* Allow "none" only in first position */
1511 if (strcasecmp(arg, "none") == 0) {
1512 if (i > 0 || ac > 0) {
1513 error("%s line %d: keyword %s \"none\" "
1514 "argument must appear alone.",
1515 filename, linenum, keyword);
1520 if (*activep && *uintptr == 0) {
1521 *cppptr = xrecallocarray(*cppptr, *uintptr,
1522 *uintptr + 1, sizeof(**cppptr));
1523 (*cppptr)[(*uintptr)++] = xstrdup(arg);
1529 case oRemoteForward:
1530 case oDynamicForward:
1531 arg = argv_next(&ac, &av);
1532 if (!arg || *arg == '\0') {
1533 error("%.200s line %d: Missing argument.",
1538 remotefwd = (opcode == oRemoteForward);
1539 dynamicfwd = (opcode == oDynamicForward);
1542 arg2 = argv_next(&ac, &av);
1543 if (arg2 == NULL || *arg2 == '\0') {
1547 error("%.200s line %d: Missing target "
1548 "argument.", filename, linenum);
1552 /* construct a string for parse_forward */
1553 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1558 strlcpy(fwdarg, arg, sizeof(fwdarg));
1560 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1561 error("%.200s line %d: Bad forwarding specification.",
1568 add_remote_forward(options, &fwd);
1570 add_local_forward(options, &fwd);
1575 case oPermitRemoteOpen:
1576 uintptr = &options->num_permitted_remote_opens;
1577 cppptr = &options->permitted_remote_opens;
1578 uvalue = *uintptr; /* modified later */
1580 while ((arg = argv_next(&ac, &av)) != NULL) {
1581 arg2 = xstrdup(arg);
1582 /* Allow any/none only in first position */
1583 if (strcasecmp(arg, "none") == 0 ||
1584 strcasecmp(arg, "any") == 0) {
1585 if (i > 0 || ac > 0) {
1586 error("%s line %d: keyword %s \"%s\" "
1587 "argument must appear alone.",
1588 filename, linenum, keyword, arg);
1594 fatal("%s line %d: missing host in %s",
1596 lookup_opcode_name(opcode));
1598 p = cleanhostname(p);
1600 * don't want to use permitopen_port to avoid
1601 * dependency on channels.[ch] here.
1603 if (arg == NULL || (strcmp(arg, "*") != 0 &&
1604 a2port(arg) <= 0)) {
1605 fatal("%s line %d: bad port number "
1606 "in %s", filename, linenum,
1607 lookup_opcode_name(opcode));
1610 if (*activep && uvalue == 0) {
1611 opt_array_append(filename, linenum,
1612 lookup_opcode_name(opcode),
1613 cppptr, uintptr, arg2);
1619 fatal("%s line %d: missing %s specification",
1620 filename, linenum, lookup_opcode_name(opcode));
1623 case oClearAllForwardings:
1624 intptr = &options->clear_forwardings;
1629 error("Host directive not supported as a command-line "
1635 while ((arg = argv_next(&ac, &av)) != NULL) {
1637 error("%s line %d: keyword %s empty argument",
1638 filename, linenum, keyword);
1641 if ((flags & SSHCONF_NEVERMATCH) != 0) {
1645 negated = *arg == '!';
1648 if (match_pattern(host, arg)) {
1650 debug("%.200s line %d: Skipping Host "
1651 "block because of negated match "
1652 "for %.100s", filename, linenum,
1659 arg2 = arg; /* logged below */
1664 debug("%.200s line %d: Applying options for %.100s",
1665 filename, linenum, arg2);
1670 error("Host directive not supported as a command-line "
1674 value = match_cfg_line(options, &str, pw, host, original_host,
1675 flags & SSHCONF_FINAL, want_final_pass,
1678 error("%.200s line %d: Bad Match condition", filename,
1682 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1684 * If match_cfg_line() didn't consume all its arguments then
1685 * arrange for the extra arguments check below to fail.
1688 if (str == NULL || *str == '\0')
1693 intptr = &options->escape_char;
1694 arg = argv_next(&ac, &av);
1695 if (!arg || *arg == '\0') {
1696 error("%.200s line %d: Missing argument.",
1700 if (strcmp(arg, "none") == 0)
1701 value = SSH_ESCAPECHAR_NONE;
1702 else if (arg[1] == '\0')
1703 value = (u_char) arg[0];
1704 else if (arg[0] == '^' && arg[2] == 0 &&
1705 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1706 value = (u_char) arg[1] & 31;
1708 error("%.200s line %d: Bad escape character.",
1712 if (*activep && *intptr == -1)
1716 case oAddressFamily:
1717 intptr = &options->address_family;
1718 multistate_ptr = multistate_addressfamily;
1719 goto parse_multistate;
1721 case oEnableSSHKeysign:
1722 intptr = &options->enable_ssh_keysign;
1725 case oIdentitiesOnly:
1726 intptr = &options->identities_only;
1729 case oServerAliveInterval:
1730 intptr = &options->server_alive_interval;
1733 case oServerAliveCountMax:
1734 intptr = &options->server_alive_count_max;
1738 while ((arg = argv_next(&ac, &av)) != NULL) {
1739 if (*arg == '\0' || strchr(arg, '=') != NULL) {
1740 error("%s line %d: Invalid environment name.",
1747 /* Removing an env var */
1748 rm_env(options, arg, filename, linenum);
1751 opt_array_append(filename, linenum,
1752 lookup_opcode_name(opcode),
1753 &options->send_env, &options->num_send_env, arg);
1758 value = options->num_setenv;
1759 while ((arg = argv_next(&ac, &av)) != NULL) {
1760 if (strchr(arg, '=') == NULL) {
1761 error("%s line %d: Invalid SetEnv.",
1765 if (!*activep || value != 0)
1767 if (lookup_setenv_in_list(arg, options->setenv,
1768 options->num_setenv) != NULL) {
1769 debug2("%s line %d: ignoring duplicate env "
1770 "name \"%.64s\"", filename, linenum, arg);
1773 opt_array_append(filename, linenum,
1774 lookup_opcode_name(opcode),
1775 &options->setenv, &options->num_setenv, arg);
1780 charptr = &options->control_path;
1783 case oControlMaster:
1784 intptr = &options->control_master;
1785 multistate_ptr = multistate_controlmaster;
1786 goto parse_multistate;
1788 case oControlPersist:
1789 /* no/false/yes/true, or a time spec */
1790 intptr = &options->control_persist;
1791 arg = argv_next(&ac, &av);
1792 if (!arg || *arg == '\0') {
1793 error("%.200s line %d: Missing ControlPersist"
1794 " argument.", filename, linenum);
1798 value2 = 0; /* timeout */
1799 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1801 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1803 else if ((value2 = convtime(arg)) >= 0)
1806 error("%.200s line %d: Bad ControlPersist argument.",
1810 if (*activep && *intptr == -1) {
1812 options->control_persist_timeout = value2;
1816 case oHashKnownHosts:
1817 intptr = &options->hash_known_hosts;
1821 intptr = &options->tun_open;
1822 multistate_ptr = multistate_tunnel;
1823 goto parse_multistate;
1826 arg = argv_next(&ac, &av);
1827 if (!arg || *arg == '\0') {
1828 error("%.200s line %d: Missing argument.",
1832 value = a2tun(arg, &value2);
1833 if (value == SSH_TUNID_ERR) {
1834 error("%.200s line %d: Bad tun device.",
1838 if (*activep && options->tun_local == -1) {
1839 options->tun_local = value;
1840 options->tun_remote = value2;
1845 charptr = &options->local_command;
1848 case oPermitLocalCommand:
1849 intptr = &options->permit_local_command;
1852 case oRemoteCommand:
1853 charptr = &options->remote_command;
1856 case oVisualHostKey:
1857 intptr = &options->visual_host_key;
1862 error("Include directive not supported as a "
1863 "command-line option");
1867 while ((arg = argv_next(&ac, &av)) != NULL) {
1869 error("%s line %d: keyword %s empty argument",
1870 filename, linenum, keyword);
1874 * Ensure all paths are anchored. User configuration
1875 * files may begin with '~/' but system configurations
1876 * must not. If the path is relative, then treat it
1877 * as living in ~/.ssh for user configurations or
1878 * /etc/ssh for system ones.
1880 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1881 error("%.200s line %d: bad include path %s.",
1882 filename, linenum, arg);
1885 if (!path_absolute(arg) && *arg != '~') {
1886 xasprintf(&arg2, "%s/%s",
1887 (flags & SSHCONF_USERCONF) ?
1888 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1890 arg2 = xstrdup(arg);
1891 memset(&gl, 0, sizeof(gl));
1892 r = glob(arg2, GLOB_TILDE, NULL, &gl);
1893 if (r == GLOB_NOMATCH) {
1894 debug("%.200s line %d: include %s matched no "
1895 "files",filename, linenum, arg2);
1898 } else if (r != 0) {
1899 error("%.200s line %d: glob failed for %s.",
1900 filename, linenum, arg2);
1905 for (i = 0; i < gl.gl_pathc; i++) {
1906 debug3("%.200s line %d: Including file %s "
1907 "depth %d%s", filename, linenum,
1908 gl.gl_pathv[i], depth,
1909 oactive ? "" : " (parse only)");
1910 r = read_config_file_depth(gl.gl_pathv[i],
1911 pw, host, original_host, options,
1912 flags | SSHCONF_CHECKPERM |
1913 (oactive ? 0 : SSHCONF_NEVERMATCH),
1914 activep, want_final_pass, depth + 1);
1915 if (r != 1 && errno != ENOENT) {
1916 error("Can't open user config file "
1917 "%.100s: %.100s", gl.gl_pathv[i],
1923 * don't let Match in includes clobber the
1924 * containing file's Match state.
1937 arg = argv_next(&ac, &av);
1938 if ((value = parse_ipqos(arg)) == -1) {
1939 error("%s line %d: Bad IPQoS value: %s",
1940 filename, linenum, arg);
1943 arg = argv_next(&ac, &av);
1946 else if ((value2 = parse_ipqos(arg)) == -1) {
1947 error("%s line %d: Bad IPQoS value: %s",
1948 filename, linenum, arg);
1951 if (*activep && options->ip_qos_interactive == -1) {
1952 options->ip_qos_interactive = value;
1953 options->ip_qos_bulk = value2;
1958 intptr = &options->request_tty;
1959 multistate_ptr = multistate_requesttty;
1960 goto parse_multistate;
1963 intptr = &options->session_type;
1964 multistate_ptr = multistate_sessiontype;
1965 goto parse_multistate;
1968 intptr = &options->stdin_null;
1971 case oForkAfterAuthentication:
1972 intptr = &options->fork_after_authentication;
1975 case oIgnoreUnknown:
1976 charptr = &options->ignored_unknown;
1979 case oProxyUseFdpass:
1980 intptr = &options->proxy_use_fdpass;
1983 case oCanonicalDomains:
1984 value = options->num_canonical_domains != 0;
1986 while ((arg = argv_next(&ac, &av)) != NULL) {
1988 error("%s line %d: keyword %s empty argument",
1989 filename, linenum, keyword);
1992 /* Allow "none" only in first position */
1993 if (strcasecmp(arg, "none") == 0) {
1994 if (i > 0 || ac > 0) {
1995 error("%s line %d: keyword %s \"none\" "
1996 "argument must appear alone.",
1997 filename, linenum, keyword);
2002 if (!valid_domain(arg, 1, &errstr)) {
2003 error("%s line %d: %s", filename, linenum,
2007 if (!*activep || value)
2009 if (options->num_canonical_domains >=
2010 MAX_CANON_DOMAINS) {
2011 error("%s line %d: too many hostname suffixes.",
2015 options->canonical_domains[
2016 options->num_canonical_domains++] = xstrdup(arg);
2020 case oCanonicalizePermittedCNAMEs:
2021 value = options->num_permitted_cnames != 0;
2023 while ((arg = argv_next(&ac, &av)) != NULL) {
2025 * Either 'none' (only in first position), '*' for
2026 * everything or 'list:list'
2028 if (strcasecmp(arg, "none") == 0) {
2029 if (i > 0 || ac > 0) {
2030 error("%s line %d: keyword %s \"none\" "
2031 "argument must appear alone.",
2032 filename, linenum, keyword);
2036 } else if (strcmp(arg, "*") == 0) {
2040 if ((arg2 = strchr(arg, ':')) == NULL ||
2042 error("%s line %d: "
2043 "Invalid permitted CNAME \"%s\"",
2044 filename, linenum, arg);
2051 if (!*activep || value)
2053 if (options->num_permitted_cnames >=
2054 MAX_CANON_DOMAINS) {
2055 error("%s line %d: too many permitted CNAMEs.",
2059 cname = options->permitted_cnames +
2060 options->num_permitted_cnames++;
2061 cname->source_list = xstrdup(arg);
2062 cname->target_list = xstrdup(arg2);
2066 case oCanonicalizeHostname:
2067 intptr = &options->canonicalize_hostname;
2068 multistate_ptr = multistate_canonicalizehostname;
2069 goto parse_multistate;
2071 case oCanonicalizeMaxDots:
2072 intptr = &options->canonicalize_max_dots;
2075 case oCanonicalizeFallbackLocal:
2076 intptr = &options->canonicalize_fallback_local;
2079 case oStreamLocalBindMask:
2080 arg = argv_next(&ac, &av);
2081 if (!arg || *arg == '\0') {
2082 error("%.200s line %d: Missing StreamLocalBindMask "
2083 "argument.", filename, linenum);
2086 /* Parse mode in octal format */
2087 value = strtol(arg, &endofnumber, 8);
2088 if (arg == endofnumber || value < 0 || value > 0777) {
2089 error("%.200s line %d: Bad mask.", filename, linenum);
2092 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2095 case oStreamLocalBindUnlink:
2096 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2099 case oRevokedHostKeys:
2100 charptr = &options->revoked_host_keys;
2103 case oFingerprintHash:
2104 intptr = &options->fingerprint_hash;
2105 arg = argv_next(&ac, &av);
2106 if (!arg || *arg == '\0') {
2107 error("%.200s line %d: Missing argument.",
2111 if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2112 error("%.200s line %d: Invalid hash algorithm \"%s\".",
2113 filename, linenum, arg);
2116 if (*activep && *intptr == -1)
2120 case oUpdateHostkeys:
2121 intptr = &options->update_hostkeys;
2122 multistate_ptr = multistate_yesnoask;
2123 goto parse_multistate;
2125 case oHostbasedAcceptedAlgorithms:
2126 charptr = &options->hostbased_accepted_algos;
2127 goto parse_pubkey_algos;
2129 case oPubkeyAcceptedAlgorithms:
2130 charptr = &options->pubkey_accepted_algos;
2131 goto parse_pubkey_algos;
2133 case oAddKeysToAgent:
2134 arg = argv_next(&ac, &av);
2135 arg2 = argv_next(&ac, &av);
2136 value = parse_multistate_value(arg, filename, linenum,
2137 multistate_yesnoaskconfirm);
2138 value2 = 0; /* unlimited lifespan by default */
2139 if (value == 3 && arg2 != NULL) {
2140 /* allow "AddKeysToAgent confirm 5m" */
2141 if ((value2 = convtime(arg2)) == -1) {
2142 error("%s line %d: invalid time value.",
2146 } else if (value == -1 && arg2 == NULL) {
2147 if ((value2 = convtime(arg)) == -1) {
2148 error("%s line %d: unsupported option",
2152 value = 1; /* yes */
2153 } else if (value == -1 || arg2 != NULL) {
2154 error("%s line %d: unsupported option",
2158 if (*activep && options->add_keys_to_agent == -1) {
2159 options->add_keys_to_agent = value;
2160 options->add_keys_to_agent_lifespan = value2;
2164 case oIdentityAgent:
2165 charptr = &options->identity_agent;
2166 arg = argv_next(&ac, &av);
2167 if (!arg || *arg == '\0') {
2168 error("%.200s line %d: Missing argument.",
2173 /* Extra validation if the string represents an env var. */
2174 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2175 error("%.200s line %d: Invalid environment expansion "
2176 "%s.", filename, linenum, arg);
2180 /* check for legacy environment format */
2181 if (arg[0] == '$' && arg[1] != '{' &&
2182 !valid_env_name(arg + 1)) {
2183 error("%.200s line %d: Invalid environment name %s.",
2184 filename, linenum, arg);
2187 if (*activep && *charptr == NULL)
2188 *charptr = xstrdup(arg);
2191 case oEnableEscapeCommandline:
2192 intptr = &options->enable_escape_commandline;
2195 case oRequiredRSASize:
2196 intptr = &options->required_rsa_size;
2200 debug("%s line %d: Deprecated option \"%s\"",
2201 filename, linenum, keyword);
2206 error("%s line %d: Unsupported option \"%s\"",
2207 filename, linenum, keyword);
2212 error("%s line %d: Unimplemented opcode %d",
2213 filename, linenum, opcode);
2217 /* Check that there is no garbage at end of line. */
2219 error("%.200s line %d: keyword %s extra arguments "
2220 "at end of line", filename, linenum, keyword);
2227 argv_free(oav, oac);
2232 * Reads the config file and modifies the options accordingly. Options
2233 * should already be initialized before this call. This never returns if
2234 * there is an error. If the file does not exist, this returns 0.
2237 read_config_file(const char *filename, struct passwd *pw, const char *host,
2238 const char *original_host, Options *options, int flags,
2239 int *want_final_pass)
2243 return read_config_file_depth(filename, pw, host, original_host,
2244 options, flags, &active, want_final_pass, 0);
2247 #define READCONF_MAX_DEPTH 16
2249 read_config_file_depth(const char *filename, struct passwd *pw,
2250 const char *host, const char *original_host, Options *options,
2251 int flags, int *activep, int *want_final_pass, int depth)
2255 size_t linesize = 0;
2257 int bad_options = 0;
2259 if (depth < 0 || depth > READCONF_MAX_DEPTH)
2260 fatal("Too many recursive configuration includes");
2262 if ((f = fopen(filename, "r")) == NULL)
2265 if (flags & SSHCONF_CHECKPERM) {
2268 if (fstat(fileno(f), &sb) == -1)
2269 fatal("fstat %s: %s", filename, strerror(errno));
2270 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2271 (sb.st_mode & 022) != 0))
2272 fatal("Bad owner or permissions on %s", filename);
2275 debug("Reading configuration data %.200s", filename);
2278 * Mark that we are now processing the options. This flag is turned
2279 * on/off by Host specifications.
2282 while (getline(&line, &linesize, f) != -1) {
2283 /* Update line number counter. */
2286 * Trim out comments and strip whitespace.
2287 * NB - preserve newlines, they are needed to reproduce
2288 * line numbers later for error messages.
2290 if (process_config_line_depth(options, pw, host, original_host,
2291 line, filename, linenum, activep, flags, want_final_pass,
2297 if (bad_options > 0)
2298 fatal("%s: terminating, %d bad configuration options",
2299 filename, bad_options);
2303 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2305 option_clear_or_none(const char *o)
2307 return o == NULL || strcasecmp(o, "none") == 0;
2311 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2312 * Allowed to be called on non-final configuration.
2315 config_has_permitted_cnames(Options *options)
2317 if (options->num_permitted_cnames == 1 &&
2318 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2319 strcmp(options->permitted_cnames[0].target_list, "") == 0)
2321 return options->num_permitted_cnames > 0;
2325 * Initializes options to special values that indicate that they have not yet
2326 * been set. Read_config_file will only set options with this value. Options
2327 * are processed in the following order: command line, user config file,
2328 * system config file. Last, fill_default_options is called.
2332 initialize_options(Options * options)
2334 memset(options, 'X', sizeof(*options));
2335 options->host_arg = NULL;
2336 options->forward_agent = -1;
2337 options->forward_agent_sock_path = NULL;
2338 options->forward_x11 = -1;
2339 options->forward_x11_trusted = -1;
2340 options->forward_x11_timeout = -1;
2341 options->stdio_forward_host = NULL;
2342 options->stdio_forward_port = 0;
2343 options->clear_forwardings = -1;
2344 options->exit_on_forward_failure = -1;
2345 options->xauth_location = NULL;
2346 options->fwd_opts.gateway_ports = -1;
2347 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2348 options->fwd_opts.streamlocal_bind_unlink = -1;
2349 options->pubkey_authentication = -1;
2350 options->gss_authentication = -1;
2351 options->gss_deleg_creds = -1;
2352 options->password_authentication = -1;
2353 options->kbd_interactive_authentication = -1;
2354 options->kbd_interactive_devices = NULL;
2355 options->hostbased_authentication = -1;
2356 options->batch_mode = -1;
2357 options->check_host_ip = -1;
2358 options->strict_host_key_checking = -1;
2359 options->compression = -1;
2360 options->tcp_keep_alive = -1;
2362 options->address_family = -1;
2363 options->connection_attempts = -1;
2364 options->connection_timeout = -1;
2365 options->number_of_password_prompts = -1;
2366 options->ciphers = NULL;
2367 options->macs = NULL;
2368 options->kex_algorithms = NULL;
2369 options->hostkeyalgorithms = NULL;
2370 options->ca_sign_algorithms = NULL;
2371 options->num_identity_files = 0;
2372 memset(options->identity_keys, 0, sizeof(options->identity_keys));
2373 options->num_certificate_files = 0;
2374 memset(options->certificates, 0, sizeof(options->certificates));
2375 options->hostname = NULL;
2376 options->host_key_alias = NULL;
2377 options->proxy_command = NULL;
2378 options->jump_user = NULL;
2379 options->jump_host = NULL;
2380 options->jump_port = -1;
2381 options->jump_extra = NULL;
2382 options->user = NULL;
2383 options->escape_char = -1;
2384 options->num_system_hostfiles = 0;
2385 options->num_user_hostfiles = 0;
2386 options->local_forwards = NULL;
2387 options->num_local_forwards = 0;
2388 options->remote_forwards = NULL;
2389 options->num_remote_forwards = 0;
2390 options->permitted_remote_opens = NULL;
2391 options->num_permitted_remote_opens = 0;
2392 options->log_facility = SYSLOG_FACILITY_NOT_SET;
2393 options->log_level = SYSLOG_LEVEL_NOT_SET;
2394 options->num_log_verbose = 0;
2395 options->log_verbose = NULL;
2396 options->preferred_authentications = NULL;
2397 options->bind_address = NULL;
2398 options->bind_interface = NULL;
2399 options->pkcs11_provider = NULL;
2400 options->sk_provider = NULL;
2401 options->enable_ssh_keysign = - 1;
2402 options->no_host_authentication_for_localhost = - 1;
2403 options->identities_only = - 1;
2404 options->rekey_limit = - 1;
2405 options->rekey_interval = -1;
2406 options->verify_host_key_dns = -1;
2407 options->server_alive_interval = -1;
2408 options->server_alive_count_max = -1;
2409 options->send_env = NULL;
2410 options->num_send_env = 0;
2411 options->setenv = NULL;
2412 options->num_setenv = 0;
2413 options->control_path = NULL;
2414 options->control_master = -1;
2415 options->control_persist = -1;
2416 options->control_persist_timeout = 0;
2417 options->hash_known_hosts = -1;
2418 options->tun_open = -1;
2419 options->tun_local = -1;
2420 options->tun_remote = -1;
2421 options->local_command = NULL;
2422 options->permit_local_command = -1;
2423 options->remote_command = NULL;
2424 options->add_keys_to_agent = -1;
2425 options->add_keys_to_agent_lifespan = -1;
2426 options->identity_agent = NULL;
2427 options->visual_host_key = -1;
2428 options->ip_qos_interactive = -1;
2429 options->ip_qos_bulk = -1;
2430 options->request_tty = -1;
2431 options->session_type = -1;
2432 options->stdin_null = -1;
2433 options->fork_after_authentication = -1;
2434 options->proxy_use_fdpass = -1;
2435 options->ignored_unknown = NULL;
2436 options->num_canonical_domains = 0;
2437 options->num_permitted_cnames = 0;
2438 options->canonicalize_max_dots = -1;
2439 options->canonicalize_fallback_local = -1;
2440 options->canonicalize_hostname = -1;
2441 options->revoked_host_keys = NULL;
2442 options->fingerprint_hash = -1;
2443 options->update_hostkeys = -1;
2444 options->hostbased_accepted_algos = NULL;
2445 options->pubkey_accepted_algos = NULL;
2446 options->known_hosts_command = NULL;
2447 options->required_rsa_size = -1;
2448 options->enable_escape_commandline = -1;
2452 * A petite version of fill_default_options() that just fills the options
2453 * needed for hostname canonicalization to proceed.
2456 fill_default_options_for_canonicalization(Options *options)
2458 if (options->canonicalize_max_dots == -1)
2459 options->canonicalize_max_dots = 1;
2460 if (options->canonicalize_fallback_local == -1)
2461 options->canonicalize_fallback_local = 1;
2462 if (options->canonicalize_hostname == -1)
2463 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2467 * Called after processing other sources of option data, this fills those
2468 * options for which no value has been specified with their default values.
2471 fill_default_options(Options * options)
2473 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2474 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2477 if (options->forward_agent == -1)
2478 options->forward_agent = 0;
2479 if (options->forward_x11 == -1)
2480 options->forward_x11 = 0;
2481 if (options->forward_x11_trusted == -1)
2482 options->forward_x11_trusted = 0;
2483 if (options->forward_x11_timeout == -1)
2484 options->forward_x11_timeout = 1200;
2486 * stdio forwarding (-W) changes the default for these but we defer
2487 * setting the values so they can be overridden.
2489 if (options->exit_on_forward_failure == -1)
2490 options->exit_on_forward_failure =
2491 options->stdio_forward_host != NULL ? 1 : 0;
2492 if (options->clear_forwardings == -1)
2493 options->clear_forwardings =
2494 options->stdio_forward_host != NULL ? 1 : 0;
2495 if (options->clear_forwardings == 1)
2496 clear_forwardings(options);
2498 if (options->xauth_location == NULL)
2499 options->xauth_location = xstrdup(_PATH_XAUTH);
2500 if (options->fwd_opts.gateway_ports == -1)
2501 options->fwd_opts.gateway_ports = 0;
2502 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2503 options->fwd_opts.streamlocal_bind_mask = 0177;
2504 if (options->fwd_opts.streamlocal_bind_unlink == -1)
2505 options->fwd_opts.streamlocal_bind_unlink = 0;
2506 if (options->pubkey_authentication == -1)
2507 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2508 if (options->gss_authentication == -1)
2509 options->gss_authentication = 0;
2510 if (options->gss_deleg_creds == -1)
2511 options->gss_deleg_creds = 0;
2512 if (options->password_authentication == -1)
2513 options->password_authentication = 1;
2514 if (options->kbd_interactive_authentication == -1)
2515 options->kbd_interactive_authentication = 1;
2516 if (options->hostbased_authentication == -1)
2517 options->hostbased_authentication = 0;
2518 if (options->batch_mode == -1)
2519 options->batch_mode = 0;
2520 if (options->check_host_ip == -1)
2521 options->check_host_ip = 0;
2522 if (options->strict_host_key_checking == -1)
2523 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2524 if (options->compression == -1)
2525 options->compression = 0;
2526 if (options->tcp_keep_alive == -1)
2527 options->tcp_keep_alive = 1;
2528 if (options->port == -1)
2529 options->port = 0; /* Filled in ssh_connect. */
2530 if (options->address_family == -1)
2531 options->address_family = AF_UNSPEC;
2532 if (options->connection_attempts == -1)
2533 options->connection_attempts = 1;
2534 if (options->number_of_password_prompts == -1)
2535 options->number_of_password_prompts = 3;
2536 /* options->hostkeyalgorithms, default set in myproposals.h */
2537 if (options->add_keys_to_agent == -1) {
2538 options->add_keys_to_agent = 0;
2539 options->add_keys_to_agent_lifespan = 0;
2541 if (options->num_identity_files == 0) {
2542 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2543 #ifdef OPENSSL_HAS_ECC
2544 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2545 add_identity_file(options, "~/",
2546 _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2548 add_identity_file(options, "~/",
2549 _PATH_SSH_CLIENT_ID_ED25519, 0);
2550 add_identity_file(options, "~/",
2551 _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2552 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2553 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2555 if (options->escape_char == -1)
2556 options->escape_char = '~';
2557 if (options->num_system_hostfiles == 0) {
2558 options->system_hostfiles[options->num_system_hostfiles++] =
2559 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2560 options->system_hostfiles[options->num_system_hostfiles++] =
2561 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2563 if (options->update_hostkeys == -1) {
2564 if (options->verify_host_key_dns <= 0 &&
2565 (options->num_user_hostfiles == 0 ||
2566 (options->num_user_hostfiles == 1 && strcmp(options->
2567 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2568 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2570 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2572 if (options->num_user_hostfiles == 0) {
2573 options->user_hostfiles[options->num_user_hostfiles++] =
2574 xstrdup(_PATH_SSH_USER_HOSTFILE);
2575 options->user_hostfiles[options->num_user_hostfiles++] =
2576 xstrdup(_PATH_SSH_USER_HOSTFILE2);
2578 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2579 options->log_level = SYSLOG_LEVEL_INFO;
2580 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2581 options->log_facility = SYSLOG_FACILITY_USER;
2582 if (options->no_host_authentication_for_localhost == - 1)
2583 options->no_host_authentication_for_localhost = 0;
2584 if (options->identities_only == -1)
2585 options->identities_only = 0;
2586 if (options->enable_ssh_keysign == -1)
2587 options->enable_ssh_keysign = 0;
2588 if (options->rekey_limit == -1)
2589 options->rekey_limit = 0;
2590 if (options->rekey_interval == -1)
2591 options->rekey_interval = 0;
2592 if (options->verify_host_key_dns == -1)
2593 options->verify_host_key_dns = 0;
2594 if (options->server_alive_interval == -1)
2595 options->server_alive_interval = 0;
2596 if (options->server_alive_count_max == -1)
2597 options->server_alive_count_max = 3;
2598 if (options->control_master == -1)
2599 options->control_master = 0;
2600 if (options->control_persist == -1) {
2601 options->control_persist = 0;
2602 options->control_persist_timeout = 0;
2604 if (options->hash_known_hosts == -1)
2605 options->hash_known_hosts = 0;
2606 if (options->tun_open == -1)
2607 options->tun_open = SSH_TUNMODE_NO;
2608 if (options->tun_local == -1)
2609 options->tun_local = SSH_TUNID_ANY;
2610 if (options->tun_remote == -1)
2611 options->tun_remote = SSH_TUNID_ANY;
2612 if (options->permit_local_command == -1)
2613 options->permit_local_command = 0;
2614 if (options->visual_host_key == -1)
2615 options->visual_host_key = 0;
2616 if (options->ip_qos_interactive == -1)
2617 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2618 if (options->ip_qos_bulk == -1)
2619 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2620 if (options->request_tty == -1)
2621 options->request_tty = REQUEST_TTY_AUTO;
2622 if (options->session_type == -1)
2623 options->session_type = SESSION_TYPE_DEFAULT;
2624 if (options->stdin_null == -1)
2625 options->stdin_null = 0;
2626 if (options->fork_after_authentication == -1)
2627 options->fork_after_authentication = 0;
2628 if (options->proxy_use_fdpass == -1)
2629 options->proxy_use_fdpass = 0;
2630 if (options->canonicalize_max_dots == -1)
2631 options->canonicalize_max_dots = 1;
2632 if (options->canonicalize_fallback_local == -1)
2633 options->canonicalize_fallback_local = 1;
2634 if (options->canonicalize_hostname == -1)
2635 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2636 if (options->fingerprint_hash == -1)
2637 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2638 #ifdef ENABLE_SK_INTERNAL
2639 if (options->sk_provider == NULL)
2640 options->sk_provider = xstrdup("internal");
2642 if (options->sk_provider == NULL)
2643 options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2645 if (options->required_rsa_size == -1)
2646 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2647 if (options->enable_escape_commandline == -1)
2648 options->enable_escape_commandline = 0;
2650 /* Expand KEX name lists */
2651 all_cipher = cipher_alg_list(',', 0);
2652 all_mac = mac_alg_list(',');
2653 all_kex = kex_alg_list(',');
2654 all_key = sshkey_alg_list(0, 0, 1, ',');
2655 all_sig = sshkey_alg_list(0, 1, 1, ',');
2656 /* remove unsupported algos from default lists */
2657 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2658 def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2659 def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2660 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2661 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2662 #define ASSEMBLE(what, defaults, all) \
2664 if ((r = kex_assemble_names(&options->what, \
2665 defaults, all)) != 0) { \
2666 error_fr(r, "%s", #what); \
2670 ASSEMBLE(ciphers, def_cipher, all_cipher);
2671 ASSEMBLE(macs, def_mac, all_mac);
2672 ASSEMBLE(kex_algorithms, def_kex, all_kex);
2673 ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2674 ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2675 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2678 #define CLEAR_ON_NONE(v) \
2680 if (option_clear_or_none(v)) { \
2685 CLEAR_ON_NONE(options->local_command);
2686 CLEAR_ON_NONE(options->remote_command);
2687 CLEAR_ON_NONE(options->proxy_command);
2688 CLEAR_ON_NONE(options->control_path);
2689 CLEAR_ON_NONE(options->revoked_host_keys);
2690 CLEAR_ON_NONE(options->pkcs11_provider);
2691 CLEAR_ON_NONE(options->sk_provider);
2692 CLEAR_ON_NONE(options->known_hosts_command);
2693 if (options->jump_host != NULL &&
2694 strcmp(options->jump_host, "none") == 0 &&
2695 options->jump_port == 0 && options->jump_user == NULL) {
2696 free(options->jump_host);
2697 options->jump_host = NULL;
2699 if (options->num_permitted_cnames == 1 &&
2700 !config_has_permitted_cnames(options)) {
2701 /* clean up CanonicalizePermittedCNAMEs=none */
2702 free(options->permitted_cnames[0].source_list);
2703 free(options->permitted_cnames[0].target_list);
2704 memset(options->permitted_cnames, '\0',
2705 sizeof(*options->permitted_cnames));
2706 options->num_permitted_cnames = 0;
2708 /* options->identity_agent distinguishes NULL from 'none' */
2709 /* options->user will be set in the main program if appropriate */
2710 /* options->hostname will be set in the main program if appropriate */
2711 /* options->host_key_alias should not be set by default */
2712 /* options->preferred_authentications will be set in ssh */
2731 free_options(Options *o)
2738 #define FREE_ARRAY(type, n, a) \
2741 for (_i = 0; _i < (n); _i++) \
2745 free(o->forward_agent_sock_path);
2746 free(o->xauth_location);
2747 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2748 free(o->log_verbose);
2751 free(o->hostkeyalgorithms);
2752 free(o->kex_algorithms);
2753 free(o->ca_sign_algorithms);
2755 free(o->host_key_alias);
2756 free(o->proxy_command);
2758 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2759 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2760 free(o->preferred_authentications);
2761 free(o->bind_address);
2762 free(o->bind_interface);
2763 free(o->pkcs11_provider);
2764 free(o->sk_provider);
2765 for (i = 0; i < o->num_identity_files; i++) {
2766 free(o->identity_files[i]);
2767 sshkey_free(o->identity_keys[i]);
2769 for (i = 0; i < o->num_certificate_files; i++) {
2770 free(o->certificate_files[i]);
2771 sshkey_free(o->certificates[i]);
2773 free(o->identity_agent);
2774 for (i = 0; i < o->num_local_forwards; i++) {
2775 free(o->local_forwards[i].listen_host);
2776 free(o->local_forwards[i].listen_path);
2777 free(o->local_forwards[i].connect_host);
2778 free(o->local_forwards[i].connect_path);
2780 free(o->local_forwards);
2781 for (i = 0; i < o->num_remote_forwards; i++) {
2782 free(o->remote_forwards[i].listen_host);
2783 free(o->remote_forwards[i].listen_path);
2784 free(o->remote_forwards[i].connect_host);
2785 free(o->remote_forwards[i].connect_path);
2787 free(o->remote_forwards);
2788 free(o->stdio_forward_host);
2789 FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2791 FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2793 free(o->control_path);
2794 free(o->local_command);
2795 free(o->remote_command);
2796 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2797 for (i = 0; i < o->num_permitted_cnames; i++) {
2798 free(o->permitted_cnames[i].source_list);
2799 free(o->permitted_cnames[i].target_list);
2801 free(o->revoked_host_keys);
2802 free(o->hostbased_accepted_algos);
2803 free(o->pubkey_accepted_algos);
2806 free(o->jump_extra);
2807 free(o->ignored_unknown);
2808 explicit_bzero(o, sizeof(*o));
2819 * parses the next field in a port forwarding specification.
2820 * sets fwd to the parsed field and advances p past the colon
2821 * or sets it to NULL at end of string.
2822 * returns 0 on success, else non-zero.
2825 parse_fwd_field(char **p, struct fwdarg *fwd)
2832 return -1; /* end of string */
2836 * A field escaped with square brackets is used literally.
2837 * XXX - allow ']' to be escaped via backslash?
2840 /* find matching ']' */
2841 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2845 /* no matching ']' or not at end of field. */
2846 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2848 /* NUL terminate the field and advance p past the colon */
2853 fwd->ispath = ispath;
2858 for (cp = *p; *cp != '\0'; cp++) {
2861 memmove(cp, cp + 1, strlen(cp + 1) + 1);
2875 fwd->ispath = ispath;
2882 * parses a string containing a port forwarding specification of the form:
2884 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2885 * listenpath:connectpath
2887 * [listenhost:]listenport
2888 * returns number of arguments parsed or zero on error
2891 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2893 struct fwdarg fwdargs[4];
2897 memset(fwd, 0, sizeof(*fwd));
2898 memset(fwdargs, 0, sizeof(fwdargs));
2901 * We expand environment variables before checking if we think they're
2902 * paths so that if ${VAR} expands to a fully qualified path it is
2903 * treated as a path.
2905 cp = p = dollar_expand(&err, fwdspec);
2906 if (p == NULL || err)
2909 /* skip leading spaces */
2910 while (isspace((u_char)*cp))
2913 for (i = 0; i < 4; ++i) {
2914 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2918 /* Check for trailing garbage */
2919 if (cp != NULL && *cp != '\0') {
2920 i = 0; /* failure */
2925 if (fwdargs[0].ispath) {
2926 fwd->listen_path = xstrdup(fwdargs[0].arg);
2927 fwd->listen_port = PORT_STREAMLOCAL;
2929 fwd->listen_host = NULL;
2930 fwd->listen_port = a2port(fwdargs[0].arg);
2932 fwd->connect_host = xstrdup("socks");
2936 if (fwdargs[0].ispath && fwdargs[1].ispath) {
2937 fwd->listen_path = xstrdup(fwdargs[0].arg);
2938 fwd->listen_port = PORT_STREAMLOCAL;
2939 fwd->connect_path = xstrdup(fwdargs[1].arg);
2940 fwd->connect_port = PORT_STREAMLOCAL;
2941 } else if (fwdargs[1].ispath) {
2942 fwd->listen_host = NULL;
2943 fwd->listen_port = a2port(fwdargs[0].arg);
2944 fwd->connect_path = xstrdup(fwdargs[1].arg);
2945 fwd->connect_port = PORT_STREAMLOCAL;
2947 fwd->listen_host = xstrdup(fwdargs[0].arg);
2948 fwd->listen_port = a2port(fwdargs[1].arg);
2949 fwd->connect_host = xstrdup("socks");
2954 if (fwdargs[0].ispath) {
2955 fwd->listen_path = xstrdup(fwdargs[0].arg);
2956 fwd->listen_port = PORT_STREAMLOCAL;
2957 fwd->connect_host = xstrdup(fwdargs[1].arg);
2958 fwd->connect_port = a2port(fwdargs[2].arg);
2959 } else if (fwdargs[2].ispath) {
2960 fwd->listen_host = xstrdup(fwdargs[0].arg);
2961 fwd->listen_port = a2port(fwdargs[1].arg);
2962 fwd->connect_path = xstrdup(fwdargs[2].arg);
2963 fwd->connect_port = PORT_STREAMLOCAL;
2965 fwd->listen_host = NULL;
2966 fwd->listen_port = a2port(fwdargs[0].arg);
2967 fwd->connect_host = xstrdup(fwdargs[1].arg);
2968 fwd->connect_port = a2port(fwdargs[2].arg);
2973 fwd->listen_host = xstrdup(fwdargs[0].arg);
2974 fwd->listen_port = a2port(fwdargs[1].arg);
2975 fwd->connect_host = xstrdup(fwdargs[2].arg);
2976 fwd->connect_port = a2port(fwdargs[3].arg);
2979 i = 0; /* failure */
2985 if (!(i == 1 || i == 2))
2988 if (!(i == 3 || i == 4)) {
2989 if (fwd->connect_path == NULL &&
2990 fwd->listen_path == NULL)
2993 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2997 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2998 (!remotefwd && fwd->listen_port == 0))
3000 if (fwd->connect_host != NULL &&
3001 strlen(fwd->connect_host) >= NI_MAXHOST)
3004 * XXX - if connecting to a remote socket, max sun len may not
3007 if (fwd->connect_path != NULL &&
3008 strlen(fwd->connect_path) >= PATH_MAX_SUN)
3010 if (fwd->listen_host != NULL &&
3011 strlen(fwd->listen_host) >= NI_MAXHOST)
3013 if (fwd->listen_path != NULL &&
3014 strlen(fwd->listen_path) >= PATH_MAX_SUN)
3020 free(fwd->connect_host);
3021 fwd->connect_host = NULL;
3022 free(fwd->connect_path);
3023 fwd->connect_path = NULL;
3024 free(fwd->listen_host);
3025 fwd->listen_host = NULL;
3026 free(fwd->listen_path);
3027 fwd->listen_path = NULL;
3032 parse_jump(const char *s, Options *o, int active)
3034 char *orig, *sdup, *cp;
3035 char *host = NULL, *user = NULL;
3036 int r, ret = -1, port = -1, first;
3038 active &= o->proxy_command == NULL && o->jump_host == NULL;
3040 orig = sdup = xstrdup(s);
3042 /* Remove comment and trailing whitespace */
3043 if ((cp = strchr(orig, '#')) != NULL)
3049 if (strcasecmp(s, "none") == 0)
3051 if ((cp = strrchr(sdup, ',')) == NULL)
3052 cp = sdup; /* last */
3057 /* First argument and configuration is active */
3058 r = parse_ssh_uri(cp, &user, &host, &port);
3059 if (r == -1 || (r == 1 &&
3060 parse_user_host_port(cp, &user, &host, &port) != 0))
3063 /* Subsequent argument or inactive configuration */
3064 r = parse_ssh_uri(cp, NULL, NULL, NULL);
3065 if (r == -1 || (r == 1 &&
3066 parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3069 first = 0; /* only check syntax for subsequent hosts */
3070 } while (cp != sdup);
3073 if (strcasecmp(s, "none") == 0) {
3074 o->jump_host = xstrdup("none");
3077 o->jump_user = user;
3078 o->jump_host = host;
3079 o->jump_port = port;
3080 o->proxy_command = xstrdup("none");
3082 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3083 o->jump_extra = xstrdup(s);
3084 o->jump_extra[cp - s] = '\0';
3097 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3099 char *user = NULL, *host = NULL, *path = NULL;
3102 r = parse_uri("ssh", uri, &user, &host, &port, &path);
3103 if (r == 0 && path != NULL)
3104 r = -1; /* path not allowed */
3106 if (userp != NULL) {
3110 if (hostp != NULL) {
3123 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3125 fmt_multistate_int(int val, const struct multistate *m)
3129 for (i = 0; m[i].key != NULL; i++) {
3130 if (m[i].value == val)
3137 fmt_intarg(OpCodes code, int val)
3142 case oAddressFamily:
3143 return fmt_multistate_int(val, multistate_addressfamily);
3144 case oVerifyHostKeyDNS:
3145 case oUpdateHostkeys:
3146 return fmt_multistate_int(val, multistate_yesnoask);
3147 case oStrictHostKeyChecking:
3148 return fmt_multistate_int(val, multistate_strict_hostkey);
3149 case oControlMaster:
3150 return fmt_multistate_int(val, multistate_controlmaster);
3152 return fmt_multistate_int(val, multistate_tunnel);
3154 return fmt_multistate_int(val, multistate_requesttty);
3156 return fmt_multistate_int(val, multistate_sessiontype);
3157 case oCanonicalizeHostname:
3158 return fmt_multistate_int(val, multistate_canonicalizehostname);
3159 case oAddKeysToAgent:
3160 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3161 case oPubkeyAuthentication:
3162 return fmt_multistate_int(val, multistate_pubkey_auth);
3163 case oFingerprintHash:
3164 return ssh_digest_alg_name(val);
3178 lookup_opcode_name(OpCodes code)
3182 for (i = 0; keywords[i].name != NULL; i++)
3183 if (keywords[i].opcode == code)
3184 return(keywords[i].name);
3189 dump_cfg_int(OpCodes code, int val)
3191 printf("%s %d\n", lookup_opcode_name(code), val);
3195 dump_cfg_fmtint(OpCodes code, int val)
3197 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3201 dump_cfg_string(OpCodes code, const char *val)
3205 printf("%s %s\n", lookup_opcode_name(code), val);
3209 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3213 for (i = 0; i < count; i++)
3214 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3218 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3222 printf("%s", lookup_opcode_name(code));
3225 for (i = 0; i < count; i++)
3226 printf(" %s", vals[i]);
3231 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3233 const struct Forward *fwd;
3236 /* oDynamicForward */
3237 for (i = 0; i < count; i++) {
3239 if (code == oDynamicForward && fwd->connect_host != NULL &&
3240 strcmp(fwd->connect_host, "socks") != 0)
3242 if (code == oLocalForward && fwd->connect_host != NULL &&
3243 strcmp(fwd->connect_host, "socks") == 0)
3245 printf("%s", lookup_opcode_name(code));
3246 if (fwd->listen_port == PORT_STREAMLOCAL)
3247 printf(" %s", fwd->listen_path);
3248 else if (fwd->listen_host == NULL)
3249 printf(" %d", fwd->listen_port);
3252 fwd->listen_host, fwd->listen_port);
3254 if (code != oDynamicForward) {
3255 if (fwd->connect_port == PORT_STREAMLOCAL)
3256 printf(" %s", fwd->connect_path);
3257 else if (fwd->connect_host == NULL)
3258 printf(" %d", fwd->connect_port);
3261 fwd->connect_host, fwd->connect_port);
3269 dump_client_config(Options *o, const char *host)
3272 char buf[8], *all_key;
3275 * Expand HostKeyAlgorithms name lists. This isn't handled in
3276 * fill_default_options() like the other algorithm lists because
3277 * the host key algorithms are by default dynamically chosen based
3278 * on the host's keys found in known_hosts.
3280 all_key = sshkey_alg_list(0, 0, 1, ',');
3281 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3283 fatal_fr(r, "expand HostKeyAlgorithms");
3286 /* Most interesting options first: user, host, port */
3287 dump_cfg_string(oHost, o->host_arg);
3288 dump_cfg_string(oUser, o->user);
3289 dump_cfg_string(oHostname, host);
3290 dump_cfg_int(oPort, o->port);
3293 dump_cfg_fmtint(oAddressFamily, o->address_family);
3294 dump_cfg_fmtint(oBatchMode, o->batch_mode);
3295 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3296 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3297 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3298 dump_cfg_fmtint(oCompression, o->compression);
3299 dump_cfg_fmtint(oControlMaster, o->control_master);
3300 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3301 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3302 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3303 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3304 dump_cfg_fmtint(oForwardX11, o->forward_x11);
3305 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3306 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3308 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3309 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3311 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3312 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3313 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3314 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3315 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3316 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3317 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3318 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3319 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3320 dump_cfg_fmtint(oRequestTTY, o->request_tty);
3321 dump_cfg_fmtint(oSessionType, o->session_type);
3322 dump_cfg_fmtint(oStdinNull, o->stdin_null);
3323 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3324 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3325 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3326 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3327 dump_cfg_fmtint(oTunnel, o->tun_open);
3328 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3329 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3330 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3331 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3333 /* Integer options */
3334 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3335 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3336 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3337 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3338 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3339 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3340 dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3342 /* String options */
3343 dump_cfg_string(oBindAddress, o->bind_address);
3344 dump_cfg_string(oBindInterface, o->bind_interface);
3345 dump_cfg_string(oCiphers, o->ciphers);
3346 dump_cfg_string(oControlPath, o->control_path);
3347 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3348 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3349 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3350 dump_cfg_string(oIdentityAgent, o->identity_agent);
3351 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3352 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3353 dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3354 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3355 dump_cfg_string(oLocalCommand, o->local_command);
3356 dump_cfg_string(oRemoteCommand, o->remote_command);
3357 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3358 dump_cfg_string(oMacs, o->macs);
3359 #ifdef ENABLE_PKCS11
3360 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3362 dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3363 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3364 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3365 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3366 dump_cfg_string(oXAuthLocation, o->xauth_location);
3367 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3370 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3371 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3372 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3374 /* String array options */
3375 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3376 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3377 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3378 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3379 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3380 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3381 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3382 dump_cfg_strarray_oneline(oLogVerbose,
3383 o->num_log_verbose, o->log_verbose);
3387 /* PermitRemoteOpen */
3388 if (o->num_permitted_remote_opens == 0)
3389 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3391 dump_cfg_strarray_oneline(oPermitRemoteOpen,
3392 o->num_permitted_remote_opens, o->permitted_remote_opens);
3394 /* AddKeysToAgent */
3395 if (o->add_keys_to_agent_lifespan <= 0)
3396 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3398 printf("addkeystoagent%s %d\n",
3399 o->add_keys_to_agent == 3 ? " confirm" : "",
3400 o->add_keys_to_agent_lifespan);
3404 if (o->forward_agent_sock_path == NULL)
3405 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3407 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3409 /* oConnectTimeout */
3410 if (o->connection_timeout == -1)
3411 printf("connecttimeout none\n");
3413 dump_cfg_int(oConnectTimeout, o->connection_timeout);
3416 printf("tunneldevice");
3417 if (o->tun_local == SSH_TUNID_ANY)
3420 printf(" %d", o->tun_local);
3421 if (o->tun_remote == SSH_TUNID_ANY)
3424 printf(":%d", o->tun_remote);
3427 /* oCanonicalizePermittedCNAMEs */
3428 printf("canonicalizePermittedcnames");
3429 if (o->num_permitted_cnames == 0)
3431 for (i = 0; i < o->num_permitted_cnames; i++) {
3432 printf(" %s:%s", o->permitted_cnames[i].source_list,
3433 o->permitted_cnames[i].target_list);
3437 /* oControlPersist */
3438 if (o->control_persist == 0 || o->control_persist_timeout == 0)
3439 dump_cfg_fmtint(oControlPersist, o->control_persist);
3441 dump_cfg_int(oControlPersist, o->control_persist_timeout);
3444 if (o->escape_char == SSH_ESCAPECHAR_NONE)
3445 printf("escapechar none\n");
3447 vis(buf, o->escape_char, VIS_WHITE, 0);
3448 printf("escapechar %s\n", buf);
3452 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3453 printf("%s\n", iptos2str(o->ip_qos_bulk));
3456 printf("rekeylimit %llu %d\n",
3457 (unsigned long long)o->rekey_limit, o->rekey_interval);
3459 /* oStreamLocalBindMask */
3460 printf("streamlocalbindmask 0%o\n",
3461 o->fwd_opts.streamlocal_bind_mask);
3464 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3466 /* oProxyCommand / oProxyJump */
3467 if (o->jump_host == NULL)
3468 dump_cfg_string(oProxyCommand, o->proxy_command);
3470 /* Check for numeric addresses */
3471 i = strchr(o->jump_host, ':') != NULL ||
3472 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3473 snprintf(buf, sizeof(buf), "%d", o->jump_port);
3474 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3475 /* optional additional jump spec */
3476 o->jump_extra == NULL ? "" : o->jump_extra,
3477 o->jump_extra == NULL ? "" : ",",
3479 o->jump_user == NULL ? "" : o->jump_user,
3480 o->jump_user == NULL ? "" : "@",
3481 /* opening [ if hostname is numeric */
3483 /* mandatory hostname */
3485 /* closing ] if hostname is numeric */
3487 /* optional port number */
3488 o->jump_port <= 0 ? "" : ":",
3489 o->jump_port <= 0 ? "" : buf);