1 /* $OpenBSD: readconf.c,v 1.297 2018/08/12 20:19:13 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>
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)
59 #include "pathnames.h"
68 #include "myproposal.h"
71 /* Format of the configuration file:
73 # Configuration data is parsed as follows:
74 # 1. command line options
75 # 2. user-specific file
77 # Any configuration value is only changed the first time it is set.
78 # Thus, host-specific definitions should be at the beginning of the
79 # configuration file, and defaults at the end.
81 # Host-specific declarations. These may override anything above. A single
82 # host may match multiple declarations; these are processed in the order
83 # that they are given in.
89 HostName another.host.name.real.org
96 RemoteForward 9999 shadows.cs.hut.fi:9999
102 PasswordAuthentication no
106 ProxyCommand ssh-proxy %h %p
109 PublicKeyAuthentication no
113 PasswordAuthentication no
119 # Defaults for various options
123 PasswordAuthentication yes
124 RSAAuthentication yes
125 RhostsRSAAuthentication yes
126 StrictHostKeyChecking yes
128 IdentityFile ~/.ssh/identity
134 static int read_config_file_depth(const char *filename, struct passwd *pw,
135 const char *host, const char *original_host, Options *options,
136 int flags, int *activep, int depth);
137 static int process_config_line_depth(Options *options, struct passwd *pw,
138 const char *host, const char *original_host, char *line,
139 const char *filename, int linenum, int *activep, int flags, int depth);
141 /* Keyword tokens. */
145 oHost, oMatch, oInclude,
146 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
147 oGatewayPorts, oExitOnForwardFailure,
148 oPasswordAuthentication, oRSAAuthentication,
149 oChallengeResponseAuthentication, oXAuthLocation,
150 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
151 oCertificateFile, oAddKeysToAgent, oIdentityAgent,
152 oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
153 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
154 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
155 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
156 oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs,
157 oPubkeyAuthentication,
158 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
159 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
160 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
161 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
162 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
163 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
164 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
165 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
167 oTunnel, oTunnelDevice,
168 oLocalCommand, oPermitLocalCommand, oRemoteCommand,
170 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
171 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
172 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
173 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
174 oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
175 oPubkeyAcceptedKeyTypes, oProxyJump,
176 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
179 /* Textual representations of the tokens. */
185 /* Deprecated options */
186 { "protocol", oIgnore }, /* NB. silently ignored */
187 { "cipher", oDeprecated },
188 { "fallbacktorsh", oDeprecated },
189 { "globalknownhostsfile2", oDeprecated },
190 { "rhostsauthentication", oDeprecated },
191 { "userknownhostsfile2", oDeprecated },
192 { "useroaming", oDeprecated },
193 { "usersh", oDeprecated },
194 { "useprivilegedport", oDeprecated },
196 /* Unsupported options */
197 { "afstokenpassing", oUnsupported },
198 { "kerberosauthentication", oUnsupported },
199 { "kerberostgtpassing", oUnsupported },
201 /* Sometimes-unsupported options */
203 { "gssapiauthentication", oGssAuthentication },
204 { "gssapidelegatecredentials", oGssDelegateCreds },
206 { "gssapiauthentication", oUnsupported },
207 { "gssapidelegatecredentials", oUnsupported },
210 { "smartcarddevice", oPKCS11Provider },
211 { "pkcs11provider", oPKCS11Provider },
213 { "smartcarddevice", oUnsupported },
214 { "pkcs11provider", oUnsupported },
216 { "rsaauthentication", oUnsupported },
217 { "rhostsrsaauthentication", oUnsupported },
218 { "compressionlevel", oUnsupported },
220 { "forwardagent", oForwardAgent },
221 { "forwardx11", oForwardX11 },
222 { "forwardx11trusted", oForwardX11Trusted },
223 { "forwardx11timeout", oForwardX11Timeout },
224 { "exitonforwardfailure", oExitOnForwardFailure },
225 { "xauthlocation", oXAuthLocation },
226 { "gatewayports", oGatewayPorts },
227 { "passwordauthentication", oPasswordAuthentication },
228 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
229 { "kbdinteractivedevices", oKbdInteractiveDevices },
230 { "pubkeyauthentication", oPubkeyAuthentication },
231 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
232 { "hostbasedauthentication", oHostbasedAuthentication },
233 { "challengeresponseauthentication", oChallengeResponseAuthentication },
234 { "skeyauthentication", oUnsupported },
235 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
236 { "identityfile", oIdentityFile },
237 { "identityfile2", oIdentityFile }, /* obsolete */
238 { "identitiesonly", oIdentitiesOnly },
239 { "certificatefile", oCertificateFile },
240 { "addkeystoagent", oAddKeysToAgent },
241 { "identityagent", oIdentityAgent },
242 { "hostname", oHostName },
243 { "hostkeyalias", oHostKeyAlias },
244 { "proxycommand", oProxyCommand },
246 { "ciphers", oCiphers },
248 { "remoteforward", oRemoteForward },
249 { "localforward", oLocalForward },
253 { "escapechar", oEscapeChar },
254 { "globalknownhostsfile", oGlobalKnownHostsFile },
255 { "userknownhostsfile", oUserKnownHostsFile },
256 { "connectionattempts", oConnectionAttempts },
257 { "batchmode", oBatchMode },
258 { "checkhostip", oCheckHostIP },
259 { "stricthostkeychecking", oStrictHostKeyChecking },
260 { "compression", oCompression },
261 { "tcpkeepalive", oTCPKeepAlive },
262 { "keepalive", oTCPKeepAlive }, /* obsolete */
263 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
264 { "syslogfacility", oLogFacility },
265 { "loglevel", oLogLevel },
266 { "dynamicforward", oDynamicForward },
267 { "preferredauthentications", oPreferredAuthentications },
268 { "hostkeyalgorithms", oHostKeyAlgorithms },
269 { "bindaddress", oBindAddress },
270 { "bindinterface", oBindInterface },
271 { "clearallforwardings", oClearAllForwardings },
272 { "enablesshkeysign", oEnableSSHKeysign },
273 { "verifyhostkeydns", oVerifyHostKeyDNS },
274 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
275 { "rekeylimit", oRekeyLimit },
276 { "connecttimeout", oConnectTimeout },
277 { "addressfamily", oAddressFamily },
278 { "serveraliveinterval", oServerAliveInterval },
279 { "serveralivecountmax", oServerAliveCountMax },
280 { "sendenv", oSendEnv },
281 { "setenv", oSetEnv },
282 { "controlpath", oControlPath },
283 { "controlmaster", oControlMaster },
284 { "controlpersist", oControlPersist },
285 { "hashknownhosts", oHashKnownHosts },
286 { "include", oInclude },
287 { "tunnel", oTunnel },
288 { "tunneldevice", oTunnelDevice },
289 { "localcommand", oLocalCommand },
290 { "permitlocalcommand", oPermitLocalCommand },
291 { "remotecommand", oRemoteCommand },
292 { "visualhostkey", oVisualHostKey },
293 { "kexalgorithms", oKexAlgorithms },
295 { "requesttty", oRequestTTY },
296 { "proxyusefdpass", oProxyUseFdpass },
297 { "canonicaldomains", oCanonicalDomains },
298 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
299 { "canonicalizehostname", oCanonicalizeHostname },
300 { "canonicalizemaxdots", oCanonicalizeMaxDots },
301 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
302 { "streamlocalbindmask", oStreamLocalBindMask },
303 { "streamlocalbindunlink", oStreamLocalBindUnlink },
304 { "revokedhostkeys", oRevokedHostKeys },
305 { "fingerprinthash", oFingerprintHash },
306 { "updatehostkeys", oUpdateHostkeys },
307 { "hostbasedkeytypes", oHostbasedKeyTypes },
308 { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
309 { "ignoreunknown", oIgnoreUnknown },
310 { "proxyjump", oProxyJump },
316 * Adds a local TCP/IP port forward to options. Never returns if there is an
321 add_local_forward(Options *options, const struct Forward *newfwd)
326 /* Don't add duplicates */
327 for (i = 0; i < options->num_local_forwards; i++) {
328 if (forward_equals(newfwd, options->local_forwards + i))
331 options->local_forwards = xreallocarray(options->local_forwards,
332 options->num_local_forwards + 1,
333 sizeof(*options->local_forwards));
334 fwd = &options->local_forwards[options->num_local_forwards++];
336 fwd->listen_host = newfwd->listen_host;
337 fwd->listen_port = newfwd->listen_port;
338 fwd->listen_path = newfwd->listen_path;
339 fwd->connect_host = newfwd->connect_host;
340 fwd->connect_port = newfwd->connect_port;
341 fwd->connect_path = newfwd->connect_path;
345 * Adds a remote TCP/IP port forward to options. Never returns if there is
350 add_remote_forward(Options *options, const struct Forward *newfwd)
355 /* Don't add duplicates */
356 for (i = 0; i < options->num_remote_forwards; i++) {
357 if (forward_equals(newfwd, options->remote_forwards + i))
360 options->remote_forwards = xreallocarray(options->remote_forwards,
361 options->num_remote_forwards + 1,
362 sizeof(*options->remote_forwards));
363 fwd = &options->remote_forwards[options->num_remote_forwards++];
365 fwd->listen_host = newfwd->listen_host;
366 fwd->listen_port = newfwd->listen_port;
367 fwd->listen_path = newfwd->listen_path;
368 fwd->connect_host = newfwd->connect_host;
369 fwd->connect_port = newfwd->connect_port;
370 fwd->connect_path = newfwd->connect_path;
371 fwd->handle = newfwd->handle;
372 fwd->allocated_port = 0;
376 clear_forwardings(Options *options)
380 for (i = 0; i < options->num_local_forwards; i++) {
381 free(options->local_forwards[i].listen_host);
382 free(options->local_forwards[i].listen_path);
383 free(options->local_forwards[i].connect_host);
384 free(options->local_forwards[i].connect_path);
386 if (options->num_local_forwards > 0) {
387 free(options->local_forwards);
388 options->local_forwards = NULL;
390 options->num_local_forwards = 0;
391 for (i = 0; i < options->num_remote_forwards; i++) {
392 free(options->remote_forwards[i].listen_host);
393 free(options->remote_forwards[i].listen_path);
394 free(options->remote_forwards[i].connect_host);
395 free(options->remote_forwards[i].connect_path);
397 if (options->num_remote_forwards > 0) {
398 free(options->remote_forwards);
399 options->remote_forwards = NULL;
401 options->num_remote_forwards = 0;
402 options->tun_open = SSH_TUNMODE_NO;
406 add_certificate_file(Options *options, const char *path, int userprovided)
410 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
411 fatal("Too many certificate files specified (max %d)",
412 SSH_MAX_CERTIFICATE_FILES);
414 /* Avoid registering duplicates */
415 for (i = 0; i < options->num_certificate_files; i++) {
416 if (options->certificate_file_userprovided[i] == userprovided &&
417 strcmp(options->certificate_files[i], path) == 0) {
418 debug2("%s: ignoring duplicate key %s", __func__, path);
423 options->certificate_file_userprovided[options->num_certificate_files] =
425 options->certificate_files[options->num_certificate_files++] =
430 add_identity_file(Options *options, const char *dir, const char *filename,
436 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
437 fatal("Too many identity files specified (max %d)",
438 SSH_MAX_IDENTITY_FILES);
440 if (dir == NULL) /* no dir, filename is absolute */
441 path = xstrdup(filename);
442 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
443 fatal("Identity file path %s too long", path);
445 /* Avoid registering duplicates */
446 for (i = 0; i < options->num_identity_files; i++) {
447 if (options->identity_file_userprovided[i] == userprovided &&
448 strcmp(options->identity_files[i], path) == 0) {
449 debug2("%s: ignoring duplicate key %s", __func__, path);
455 options->identity_file_userprovided[options->num_identity_files] =
457 options->identity_files[options->num_identity_files++] = path;
461 default_ssh_port(void)
467 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
468 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
474 * Execute a command in a shell.
475 * Return its exit status or -1 on abnormal exit.
478 execute_in_shell(const char *cmd)
484 if ((shell = getenv("SHELL")) == NULL)
485 shell = _PATH_BSHELL;
487 /* Need this to redirect subprocess stdin/out */
488 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
489 fatal("open(/dev/null): %s", strerror(errno));
491 debug("Executing command: '%.500s'", cmd);
493 /* Fork and execute the command. */
494 if ((pid = fork()) == 0) {
497 /* Redirect child stdin and stdout. Leave stderr */
498 if (dup2(devnull, STDIN_FILENO) == -1)
499 fatal("dup2: %s", strerror(errno));
500 if (dup2(devnull, STDOUT_FILENO) == -1)
501 fatal("dup2: %s", strerror(errno));
502 if (devnull > STDERR_FILENO)
504 closefrom(STDERR_FILENO + 1);
508 argv[2] = xstrdup(cmd);
511 execv(argv[0], argv);
512 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
513 /* Die with signal to make this error apparent to parent. */
514 signal(SIGTERM, SIG_DFL);
515 kill(getpid(), SIGTERM);
520 fatal("%s: fork: %.100s", __func__, strerror(errno));
524 while (waitpid(pid, &status, 0) == -1) {
525 if (errno != EINTR && errno != EAGAIN)
526 fatal("%s: waitpid: %s", __func__, strerror(errno));
528 if (!WIFEXITED(status)) {
529 error("command '%.100s' exited abnormally", cmd);
532 debug3("command returned status %d", WEXITSTATUS(status));
533 return WEXITSTATUS(status);
537 * Parse and execute a Match directive.
540 match_cfg_line(Options *options, char **condition, struct passwd *pw,
541 const char *host_arg, const char *original_host, int post_canon,
542 const char *filename, int linenum)
544 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
546 int r, port, this_result, result = 1, attributes = 0, negate;
547 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
551 * Configuration is likely to be incomplete at this point so we
552 * must be prepared to use default values.
554 port = options->port <= 0 ? default_ssh_port() : options->port;
555 ruser = options->user == NULL ? pw->pw_name : options->user;
557 host = xstrdup(options->hostname);
558 } else if (options->hostname != NULL) {
559 /* NB. Please keep in sync with ssh.c:main() */
560 host = percent_expand(options->hostname,
561 "h", host_arg, (char *)NULL);
563 host = xstrdup(host_arg);
566 debug2("checking match for '%s' host %s originally %s",
567 cp, host, original_host);
568 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
571 if ((negate = attrib[0] == '!'))
573 /* criteria "all" and "canonical" have no argument */
574 if (strcasecmp(attrib, "all") == 0) {
575 if (attributes > 1 ||
576 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
577 error("%.200s line %d: '%s' cannot be combined "
578 "with other Match attributes",
579 filename, linenum, oattrib);
584 result = negate ? 0 : 1;
588 if (strcasecmp(attrib, "canonical") == 0) {
589 r = !!post_canon; /* force bitmask member to boolean */
590 if (r == (negate ? 1 : 0))
591 this_result = result = 0;
592 debug3("%.200s line %d: %smatched '%s'",
594 this_result ? "" : "not ", oattrib);
597 /* All other criteria require an argument */
598 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
599 error("Missing Match criteria for %s", attrib);
603 if (strcasecmp(attrib, "host") == 0) {
604 criteria = xstrdup(host);
605 r = match_hostname(host, arg) == 1;
606 if (r == (negate ? 1 : 0))
607 this_result = result = 0;
608 } else if (strcasecmp(attrib, "originalhost") == 0) {
609 criteria = xstrdup(original_host);
610 r = match_hostname(original_host, arg) == 1;
611 if (r == (negate ? 1 : 0))
612 this_result = result = 0;
613 } else if (strcasecmp(attrib, "user") == 0) {
614 criteria = xstrdup(ruser);
615 r = match_pattern_list(ruser, arg, 0) == 1;
616 if (r == (negate ? 1 : 0))
617 this_result = result = 0;
618 } else if (strcasecmp(attrib, "localuser") == 0) {
619 criteria = xstrdup(pw->pw_name);
620 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
621 if (r == (negate ? 1 : 0))
622 this_result = result = 0;
623 } else if (strcasecmp(attrib, "exec") == 0) {
624 if (gethostname(thishost, sizeof(thishost)) == -1)
625 fatal("gethostname: %s", strerror(errno));
626 strlcpy(shorthost, thishost, sizeof(shorthost));
627 shorthost[strcspn(thishost, ".")] = '\0';
628 snprintf(portstr, sizeof(portstr), "%d", port);
629 snprintf(uidstr, sizeof(uidstr), "%llu",
630 (unsigned long long)pw->pw_uid);
632 cmd = percent_expand(arg,
644 /* skip execution if prior predicate failed */
645 debug3("%.200s line %d: skipped exec "
646 "\"%.100s\"", filename, linenum, cmd);
650 r = execute_in_shell(cmd);
652 fatal("%.200s line %d: match exec "
653 "'%.100s' error", filename,
656 criteria = xstrdup(cmd);
658 /* Force exit status to boolean */
660 if (r == (negate ? 1 : 0))
661 this_result = result = 0;
663 error("Unsupported Match attribute %s", attrib);
667 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
668 filename, linenum, this_result ? "": "not ",
672 if (attributes == 0) {
673 error("One or more attributes required for Match");
679 debug2("match %sfound", result ? "" : "not ");
685 /* Remove environment variable by pattern */
687 rm_env(Options *options, const char *arg, const char *filename, int linenum)
692 /* Remove an environment variable */
693 for (i = 0; i < options->num_send_env; ) {
694 cp = xstrdup(options->send_env[i]);
695 if (!match_pattern(cp, arg + 1)) {
700 debug3("%s line %d: removing environment %s",
701 filename, linenum, cp);
703 free(options->send_env[i]);
704 options->send_env[i] = NULL;
705 for (j = i; j < options->num_send_env - 1; j++) {
706 options->send_env[j] = options->send_env[j + 1];
707 options->send_env[j + 1] = NULL;
709 options->num_send_env--;
710 /* NB. don't increment i */
715 * Returns the number of the token pointed to by cp or oBadOption.
718 parse_token(const char *cp, const char *filename, int linenum,
719 const char *ignored_unknown)
723 for (i = 0; keywords[i].name; i++)
724 if (strcmp(cp, keywords[i].name) == 0)
725 return keywords[i].opcode;
726 if (ignored_unknown != NULL &&
727 match_pattern_list(cp, ignored_unknown, 1) == 1)
728 return oIgnoredUnknownOption;
729 error("%s: line %d: Bad configuration option: %s",
730 filename, linenum, cp);
734 /* Multistate option parsing */
739 static const struct multistate multistate_flag[] = {
746 static const struct multistate multistate_yesnoask[] = {
754 static const struct multistate multistate_strict_hostkey[] = {
755 { "true", SSH_STRICT_HOSTKEY_YES },
756 { "false", SSH_STRICT_HOSTKEY_OFF },
757 { "yes", SSH_STRICT_HOSTKEY_YES },
758 { "no", SSH_STRICT_HOSTKEY_OFF },
759 { "ask", SSH_STRICT_HOSTKEY_ASK },
760 { "off", SSH_STRICT_HOSTKEY_OFF },
761 { "accept-new", SSH_STRICT_HOSTKEY_NEW },
764 static const struct multistate multistate_yesnoaskconfirm[] = {
773 static const struct multistate multistate_addressfamily[] = {
775 { "inet6", AF_INET6 },
776 { "any", AF_UNSPEC },
779 static const struct multistate multistate_controlmaster[] = {
780 { "true", SSHCTL_MASTER_YES },
781 { "yes", SSHCTL_MASTER_YES },
782 { "false", SSHCTL_MASTER_NO },
783 { "no", SSHCTL_MASTER_NO },
784 { "auto", SSHCTL_MASTER_AUTO },
785 { "ask", SSHCTL_MASTER_ASK },
786 { "autoask", SSHCTL_MASTER_AUTO_ASK },
789 static const struct multistate multistate_tunnel[] = {
790 { "ethernet", SSH_TUNMODE_ETHERNET },
791 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
792 { "true", SSH_TUNMODE_DEFAULT },
793 { "yes", SSH_TUNMODE_DEFAULT },
794 { "false", SSH_TUNMODE_NO },
795 { "no", SSH_TUNMODE_NO },
798 static const struct multistate multistate_requesttty[] = {
799 { "true", REQUEST_TTY_YES },
800 { "yes", REQUEST_TTY_YES },
801 { "false", REQUEST_TTY_NO },
802 { "no", REQUEST_TTY_NO },
803 { "force", REQUEST_TTY_FORCE },
804 { "auto", REQUEST_TTY_AUTO },
807 static const struct multistate multistate_canonicalizehostname[] = {
808 { "true", SSH_CANONICALISE_YES },
809 { "false", SSH_CANONICALISE_NO },
810 { "yes", SSH_CANONICALISE_YES },
811 { "no", SSH_CANONICALISE_NO },
812 { "always", SSH_CANONICALISE_ALWAYS },
817 * Processes a single option line as used in the configuration files. This
818 * only sets those values that have not already been set.
821 process_config_line(Options *options, struct passwd *pw, const char *host,
822 const char *original_host, char *line, const char *filename,
823 int linenum, int *activep, int flags)
825 return process_config_line_depth(options, pw, host, original_host,
826 line, filename, linenum, activep, flags, 0);
829 #define WHITESPACE " \t\r\n"
831 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
832 const char *original_host, char *line, const char *filename,
833 int linenum, int *activep, int flags, int depth)
835 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
836 char **cpptr, fwdarg[256];
837 u_int i, *uintptr, max_entries = 0;
838 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
839 int remotefwd, dynamicfwd;
840 LogLevel *log_level_ptr;
841 SyslogFacility *log_facility_ptr;
845 const struct multistate *multistate_ptr;
846 struct allowed_cname *cname;
850 if (activep == NULL) { /* We are processing a command line directive */
855 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
856 if ((len = strlen(line)) == 0)
858 for (len--; len > 0; len--) {
859 if (strchr(WHITESPACE "\f", line[len]) == NULL)
865 /* Get the keyword. (Each line is supposed to begin with a keyword). */
866 if ((keyword = strdelim(&s)) == NULL)
868 /* Ignore leading whitespace. */
869 if (*keyword == '\0')
870 keyword = strdelim(&s);
871 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
873 /* Match lowercase keyword */
876 opcode = parse_token(keyword, filename, linenum,
877 options->ignored_unknown);
881 /* don't panic, but count bad options */
885 case oIgnoredUnknownOption:
886 debug("%s line %d: Ignored unknown option \"%s\"",
887 filename, linenum, keyword);
889 case oConnectTimeout:
890 intptr = &options->connection_timeout;
893 if (!arg || *arg == '\0')
894 fatal("%s line %d: missing time value.",
896 if (strcmp(arg, "none") == 0)
898 else if ((value = convtime(arg)) == -1)
899 fatal("%s line %d: invalid time value.",
901 if (*activep && *intptr == -1)
906 intptr = &options->forward_agent;
908 multistate_ptr = multistate_flag;
911 if (!arg || *arg == '\0')
912 fatal("%s line %d: missing argument.",
915 for (i = 0; multistate_ptr[i].key != NULL; i++) {
916 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
917 value = multistate_ptr[i].value;
922 fatal("%s line %d: unsupported option \"%s\".",
923 filename, linenum, arg);
924 if (*activep && *intptr == -1)
929 intptr = &options->forward_x11;
932 case oForwardX11Trusted:
933 intptr = &options->forward_x11_trusted;
936 case oForwardX11Timeout:
937 intptr = &options->forward_x11_timeout;
941 intptr = &options->fwd_opts.gateway_ports;
944 case oExitOnForwardFailure:
945 intptr = &options->exit_on_forward_failure;
948 case oPasswordAuthentication:
949 intptr = &options->password_authentication;
952 case oKbdInteractiveAuthentication:
953 intptr = &options->kbd_interactive_authentication;
956 case oKbdInteractiveDevices:
957 charptr = &options->kbd_interactive_devices;
960 case oPubkeyAuthentication:
961 intptr = &options->pubkey_authentication;
964 case oHostbasedAuthentication:
965 intptr = &options->hostbased_authentication;
968 case oChallengeResponseAuthentication:
969 intptr = &options->challenge_response_authentication;
972 case oGssAuthentication:
973 intptr = &options->gss_authentication;
976 case oGssDelegateCreds:
977 intptr = &options->gss_deleg_creds;
981 intptr = &options->batch_mode;
985 intptr = &options->check_host_ip;
988 case oVerifyHostKeyDNS:
989 intptr = &options->verify_host_key_dns;
990 multistate_ptr = multistate_yesnoask;
991 goto parse_multistate;
993 case oStrictHostKeyChecking:
994 intptr = &options->strict_host_key_checking;
995 multistate_ptr = multistate_strict_hostkey;
996 goto parse_multistate;
999 intptr = &options->compression;
1003 intptr = &options->tcp_keep_alive;
1006 case oNoHostAuthenticationForLocalhost:
1007 intptr = &options->no_host_authentication_for_localhost;
1010 case oNumberOfPasswordPrompts:
1011 intptr = &options->number_of_password_prompts;
1016 if (!arg || *arg == '\0')
1017 fatal("%.200s line %d: Missing argument.", filename,
1019 if (strcmp(arg, "default") == 0) {
1022 if (scan_scaled(arg, &val64) == -1)
1023 fatal("%.200s line %d: Bad number '%s': %s",
1024 filename, linenum, arg, strerror(errno));
1025 if (val64 != 0 && val64 < 16)
1026 fatal("%.200s line %d: RekeyLimit too small",
1029 if (*activep && options->rekey_limit == -1)
1030 options->rekey_limit = val64;
1031 if (s != NULL) { /* optional rekey interval present */
1032 if (strcmp(s, "none") == 0) {
1033 (void)strdelim(&s); /* discard */
1036 intptr = &options->rekey_interval;
1043 if (!arg || *arg == '\0')
1044 fatal("%.200s line %d: Missing argument.", filename, linenum);
1046 intptr = &options->num_identity_files;
1047 if (*intptr >= SSH_MAX_IDENTITY_FILES)
1048 fatal("%.200s line %d: Too many identity files specified (max %d).",
1049 filename, linenum, SSH_MAX_IDENTITY_FILES);
1050 add_identity_file(options, NULL,
1051 arg, flags & SSHCONF_USERCONF);
1055 case oCertificateFile:
1057 if (!arg || *arg == '\0')
1058 fatal("%.200s line %d: Missing argument.",
1061 intptr = &options->num_certificate_files;
1062 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1063 fatal("%.200s line %d: Too many certificate "
1064 "files specified (max %d).",
1066 SSH_MAX_CERTIFICATE_FILES);
1068 add_certificate_file(options, arg,
1069 flags & SSHCONF_USERCONF);
1073 case oXAuthLocation:
1074 charptr=&options->xauth_location;
1078 charptr = &options->user;
1081 if (!arg || *arg == '\0')
1082 fatal("%.200s line %d: Missing argument.",
1084 if (*activep && *charptr == NULL)
1085 *charptr = xstrdup(arg);
1088 case oGlobalKnownHostsFile:
1089 cpptr = (char **)&options->system_hostfiles;
1090 uintptr = &options->num_system_hostfiles;
1091 max_entries = SSH_MAX_HOSTS_FILES;
1093 if (*activep && *uintptr == 0) {
1094 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1095 if ((*uintptr) >= max_entries)
1096 fatal("%s line %d: "
1097 "too many authorized keys files.",
1099 cpptr[(*uintptr)++] = xstrdup(arg);
1104 case oUserKnownHostsFile:
1105 cpptr = (char **)&options->user_hostfiles;
1106 uintptr = &options->num_user_hostfiles;
1107 max_entries = SSH_MAX_HOSTS_FILES;
1108 goto parse_char_array;
1111 charptr = &options->hostname;
1115 charptr = &options->host_key_alias;
1118 case oPreferredAuthentications:
1119 charptr = &options->preferred_authentications;
1123 charptr = &options->bind_address;
1126 case oBindInterface:
1127 charptr = &options->bind_interface;
1130 case oPKCS11Provider:
1131 charptr = &options->pkcs11_provider;
1135 charptr = &options->proxy_command;
1136 /* Ignore ProxyCommand if ProxyJump already specified */
1137 if (options->jump_host != NULL)
1138 charptr = &options->jump_host; /* Skip below */
1141 fatal("%.200s line %d: Missing argument.", filename, linenum);
1142 len = strspn(s, WHITESPACE "=");
1143 if (*activep && *charptr == NULL)
1144 *charptr = xstrdup(s + len);
1149 fatal("%.200s line %d: Missing argument.",
1152 len = strspn(s, WHITESPACE "=");
1153 if (parse_jump(s + len, options, *activep) == -1) {
1154 fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
1155 filename, linenum, s + len);
1160 intptr = &options->port;
1163 if ((errstr = atoi_err(arg, &value)) != NULL)
1164 fatal("%s line %d: integer value %s.",
1165 filename, linenum, errstr);
1166 if (*activep && *intptr == -1)
1170 case oConnectionAttempts:
1171 intptr = &options->connection_attempts;
1176 if (!arg || *arg == '\0')
1177 fatal("%.200s line %d: Missing argument.", filename, linenum);
1178 if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
1179 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1180 filename, linenum, arg ? arg : "<NONE>");
1181 if (*activep && options->ciphers == NULL)
1182 options->ciphers = xstrdup(arg);
1187 if (!arg || *arg == '\0')
1188 fatal("%.200s line %d: Missing argument.", filename, linenum);
1189 if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
1190 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1191 filename, linenum, arg ? arg : "<NONE>");
1192 if (*activep && options->macs == NULL)
1193 options->macs = xstrdup(arg);
1196 case oKexAlgorithms:
1198 if (!arg || *arg == '\0')
1199 fatal("%.200s line %d: Missing argument.",
1202 !kex_names_valid(*arg == '+' ? arg + 1 : arg))
1203 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1204 filename, linenum, arg ? arg : "<NONE>");
1205 if (*activep && options->kex_algorithms == NULL)
1206 options->kex_algorithms = xstrdup(arg);
1209 case oHostKeyAlgorithms:
1210 charptr = &options->hostkeyalgorithms;
1213 if (!arg || *arg == '\0')
1214 fatal("%.200s line %d: Missing argument.",
1217 !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1218 fatal("%s line %d: Bad key types '%s'.",
1219 filename, linenum, arg ? arg : "<NONE>");
1220 if (*activep && *charptr == NULL)
1221 *charptr = xstrdup(arg);
1225 log_level_ptr = &options->log_level;
1227 value = log_level_number(arg);
1228 if (value == SYSLOG_LEVEL_NOT_SET)
1229 fatal("%.200s line %d: unsupported log level '%s'",
1230 filename, linenum, arg ? arg : "<NONE>");
1231 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1232 *log_level_ptr = (LogLevel) value;
1236 log_facility_ptr = &options->log_facility;
1238 value = log_facility_number(arg);
1239 if (value == SYSLOG_FACILITY_NOT_SET)
1240 fatal("%.200s line %d: unsupported log facility '%s'",
1241 filename, linenum, arg ? arg : "<NONE>");
1242 if (*log_facility_ptr == -1)
1243 *log_facility_ptr = (SyslogFacility) value;
1247 case oRemoteForward:
1248 case oDynamicForward:
1250 if (arg == NULL || *arg == '\0')
1251 fatal("%.200s line %d: Missing port argument.",
1254 remotefwd = (opcode == oRemoteForward);
1255 dynamicfwd = (opcode == oDynamicForward);
1258 arg2 = strdelim(&s);
1259 if (arg2 == NULL || *arg2 == '\0') {
1263 fatal("%.200s line %d: Missing target "
1264 "argument.", filename, linenum);
1266 /* construct a string for parse_forward */
1267 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1272 strlcpy(fwdarg, arg, sizeof(fwdarg));
1274 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1275 fatal("%.200s line %d: Bad forwarding specification.",
1280 add_remote_forward(options, &fwd);
1282 add_local_forward(options, &fwd);
1287 case oClearAllForwardings:
1288 intptr = &options->clear_forwardings;
1293 fatal("Host directive not supported as a command-line "
1297 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1298 if ((flags & SSHCONF_NEVERMATCH) != 0)
1300 negated = *arg == '!';
1303 if (match_pattern(host, arg)) {
1305 debug("%.200s line %d: Skipping Host "
1306 "block because of negated match "
1307 "for %.100s", filename, linenum,
1313 arg2 = arg; /* logged below */
1318 debug("%.200s line %d: Applying options for %.100s",
1319 filename, linenum, arg2);
1320 /* Avoid garbage check below, as strdelim is done. */
1325 fatal("Host directive not supported as a command-line "
1327 value = match_cfg_line(options, &s, pw, host, original_host,
1328 flags & SSHCONF_POSTCANON, filename, linenum);
1330 fatal("%.200s line %d: Bad Match condition", filename,
1332 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1336 intptr = &options->escape_char;
1338 if (!arg || *arg == '\0')
1339 fatal("%.200s line %d: Missing argument.", filename, linenum);
1340 if (strcmp(arg, "none") == 0)
1341 value = SSH_ESCAPECHAR_NONE;
1342 else if (arg[1] == '\0')
1343 value = (u_char) arg[0];
1344 else if (arg[0] == '^' && arg[2] == 0 &&
1345 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1346 value = (u_char) arg[1] & 31;
1348 fatal("%.200s line %d: Bad escape character.",
1351 value = 0; /* Avoid compiler warning. */
1353 if (*activep && *intptr == -1)
1357 case oAddressFamily:
1358 intptr = &options->address_family;
1359 multistate_ptr = multistate_addressfamily;
1360 goto parse_multistate;
1362 case oEnableSSHKeysign:
1363 intptr = &options->enable_ssh_keysign;
1366 case oIdentitiesOnly:
1367 intptr = &options->identities_only;
1370 case oServerAliveInterval:
1371 intptr = &options->server_alive_interval;
1374 case oServerAliveCountMax:
1375 intptr = &options->server_alive_count_max;
1379 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1380 if (strchr(arg, '=') != NULL)
1381 fatal("%s line %d: Invalid environment name.",
1386 /* Removing an env var */
1387 rm_env(options, arg, filename, linenum);
1390 /* Adding an env var */
1391 if (options->num_send_env >= INT_MAX)
1392 fatal("%s line %d: too many send env.",
1394 options->send_env = xrecallocarray(
1395 options->send_env, options->num_send_env,
1396 options->num_send_env + 1,
1397 sizeof(*options->send_env));
1398 options->send_env[options->num_send_env++] =
1405 value = options->num_setenv;
1406 while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
1407 if (strchr(arg, '=') == NULL)
1408 fatal("%s line %d: Invalid SetEnv.",
1410 if (!*activep || value != 0)
1412 /* Adding a setenv var */
1413 if (options->num_setenv >= INT_MAX)
1414 fatal("%s line %d: too many SetEnv.",
1416 options->setenv = xrecallocarray(
1417 options->setenv, options->num_setenv,
1418 options->num_setenv + 1, sizeof(*options->setenv));
1419 options->setenv[options->num_setenv++] = xstrdup(arg);
1424 charptr = &options->control_path;
1427 case oControlMaster:
1428 intptr = &options->control_master;
1429 multistate_ptr = multistate_controlmaster;
1430 goto parse_multistate;
1432 case oControlPersist:
1433 /* no/false/yes/true, or a time spec */
1434 intptr = &options->control_persist;
1436 if (!arg || *arg == '\0')
1437 fatal("%.200s line %d: Missing ControlPersist"
1438 " argument.", filename, linenum);
1440 value2 = 0; /* timeout */
1441 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1443 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1445 else if ((value2 = convtime(arg)) >= 0)
1448 fatal("%.200s line %d: Bad ControlPersist argument.",
1450 if (*activep && *intptr == -1) {
1452 options->control_persist_timeout = value2;
1456 case oHashKnownHosts:
1457 intptr = &options->hash_known_hosts;
1461 intptr = &options->tun_open;
1462 multistate_ptr = multistate_tunnel;
1463 goto parse_multistate;
1467 if (!arg || *arg == '\0')
1468 fatal("%.200s line %d: Missing argument.", filename, linenum);
1469 value = a2tun(arg, &value2);
1470 if (value == SSH_TUNID_ERR)
1471 fatal("%.200s line %d: Bad tun device.", filename, linenum);
1473 options->tun_local = value;
1474 options->tun_remote = value2;
1479 charptr = &options->local_command;
1482 case oPermitLocalCommand:
1483 intptr = &options->permit_local_command;
1486 case oRemoteCommand:
1487 charptr = &options->remote_command;
1490 case oVisualHostKey:
1491 intptr = &options->visual_host_key;
1496 fatal("Include directive not supported as a "
1497 "command-line option");
1499 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1501 * Ensure all paths are anchored. User configuration
1502 * files may begin with '~/' but system configurations
1503 * must not. If the path is relative, then treat it
1504 * as living in ~/.ssh for user configurations or
1505 * /etc/ssh for system ones.
1507 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
1508 fatal("%.200s line %d: bad include path %s.",
1509 filename, linenum, arg);
1510 if (*arg != '/' && *arg != '~') {
1511 xasprintf(&arg2, "%s/%s",
1512 (flags & SSHCONF_USERCONF) ?
1513 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1515 arg2 = xstrdup(arg);
1516 memset(&gl, 0, sizeof(gl));
1517 r = glob(arg2, GLOB_TILDE, NULL, &gl);
1518 if (r == GLOB_NOMATCH) {
1519 debug("%.200s line %d: include %s matched no "
1520 "files",filename, linenum, arg2);
1523 } else if (r != 0 || gl.gl_pathc < 0)
1524 fatal("%.200s line %d: glob failed for %s.",
1525 filename, linenum, arg2);
1528 for (i = 0; i < (u_int)gl.gl_pathc; i++) {
1529 debug3("%.200s line %d: Including file %s "
1530 "depth %d%s", filename, linenum,
1531 gl.gl_pathv[i], depth,
1532 oactive ? "" : " (parse only)");
1533 r = read_config_file_depth(gl.gl_pathv[i],
1534 pw, host, original_host, options,
1535 flags | SSHCONF_CHECKPERM |
1536 (oactive ? 0 : SSHCONF_NEVERMATCH),
1537 activep, depth + 1);
1538 if (r != 1 && errno != ENOENT) {
1539 fatal("Can't open user config file "
1540 "%.100s: %.100s", gl.gl_pathv[i],
1544 * don't let Match in includes clobber the
1545 * containing file's Match state.
1559 if ((value = parse_ipqos(arg)) == -1)
1560 fatal("%s line %d: Bad IPQoS value: %s",
1561 filename, linenum, arg);
1565 else if ((value2 = parse_ipqos(arg)) == -1)
1566 fatal("%s line %d: Bad IPQoS value: %s",
1567 filename, linenum, arg);
1569 options->ip_qos_interactive = value;
1570 options->ip_qos_bulk = value2;
1575 intptr = &options->request_tty;
1576 multistate_ptr = multistate_requesttty;
1577 goto parse_multistate;
1579 case oIgnoreUnknown:
1580 charptr = &options->ignored_unknown;
1583 case oProxyUseFdpass:
1584 intptr = &options->proxy_use_fdpass;
1587 case oCanonicalDomains:
1588 value = options->num_canonical_domains != 0;
1589 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1590 if (!valid_domain(arg, 1, &errstr)) {
1591 fatal("%s line %d: %s", filename, linenum,
1594 if (!*activep || value)
1596 if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1597 fatal("%s line %d: too many hostname suffixes.",
1599 options->canonical_domains[
1600 options->num_canonical_domains++] = xstrdup(arg);
1604 case oCanonicalizePermittedCNAMEs:
1605 value = options->num_permitted_cnames != 0;
1606 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1607 /* Either '*' for everything or 'list:list' */
1608 if (strcmp(arg, "*") == 0)
1612 if ((arg2 = strchr(arg, ':')) == NULL ||
1614 fatal("%s line %d: "
1615 "Invalid permitted CNAME \"%s\"",
1616 filename, linenum, arg);
1621 if (!*activep || value)
1623 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1624 fatal("%s line %d: too many permitted CNAMEs.",
1626 cname = options->permitted_cnames +
1627 options->num_permitted_cnames++;
1628 cname->source_list = xstrdup(arg);
1629 cname->target_list = xstrdup(arg2);
1633 case oCanonicalizeHostname:
1634 intptr = &options->canonicalize_hostname;
1635 multistate_ptr = multistate_canonicalizehostname;
1636 goto parse_multistate;
1638 case oCanonicalizeMaxDots:
1639 intptr = &options->canonicalize_max_dots;
1642 case oCanonicalizeFallbackLocal:
1643 intptr = &options->canonicalize_fallback_local;
1646 case oStreamLocalBindMask:
1648 if (!arg || *arg == '\0')
1649 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1650 /* Parse mode in octal format */
1651 value = strtol(arg, &endofnumber, 8);
1652 if (arg == endofnumber || value < 0 || value > 0777)
1653 fatal("%.200s line %d: Bad mask.", filename, linenum);
1654 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1657 case oStreamLocalBindUnlink:
1658 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1661 case oRevokedHostKeys:
1662 charptr = &options->revoked_host_keys;
1665 case oFingerprintHash:
1666 intptr = &options->fingerprint_hash;
1668 if (!arg || *arg == '\0')
1669 fatal("%.200s line %d: Missing argument.",
1671 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1672 fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1673 filename, linenum, arg);
1674 if (*activep && *intptr == -1)
1678 case oUpdateHostkeys:
1679 intptr = &options->update_hostkeys;
1680 multistate_ptr = multistate_yesnoask;
1681 goto parse_multistate;
1683 case oHostbasedKeyTypes:
1684 charptr = &options->hostbased_key_types;
1685 goto parse_keytypes;
1687 case oPubkeyAcceptedKeyTypes:
1688 charptr = &options->pubkey_key_types;
1689 goto parse_keytypes;
1691 case oAddKeysToAgent:
1692 intptr = &options->add_keys_to_agent;
1693 multistate_ptr = multistate_yesnoaskconfirm;
1694 goto parse_multistate;
1696 case oIdentityAgent:
1697 charptr = &options->identity_agent;
1701 debug("%s line %d: Deprecated option \"%s\"",
1702 filename, linenum, keyword);
1706 error("%s line %d: Unsupported option \"%s\"",
1707 filename, linenum, keyword);
1711 fatal("%s: Unimplemented opcode %d", __func__, opcode);
1714 /* Check that there is no garbage at end of line. */
1715 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1716 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1717 filename, linenum, arg);
1723 * Reads the config file and modifies the options accordingly. Options
1724 * should already be initialized before this call. This never returns if
1725 * there is an error. If the file does not exist, this returns 0.
1728 read_config_file(const char *filename, struct passwd *pw, const char *host,
1729 const char *original_host, Options *options, int flags)
1733 return read_config_file_depth(filename, pw, host, original_host,
1734 options, flags, &active, 0);
1737 #define READCONF_MAX_DEPTH 16
1739 read_config_file_depth(const char *filename, struct passwd *pw,
1740 const char *host, const char *original_host, Options *options,
1741 int flags, int *activep, int depth)
1745 size_t linesize = 0;
1747 int bad_options = 0;
1749 if (depth < 0 || depth > READCONF_MAX_DEPTH)
1750 fatal("Too many recursive configuration includes");
1752 if ((f = fopen(filename, "r")) == NULL)
1755 if (flags & SSHCONF_CHECKPERM) {
1758 if (fstat(fileno(f), &sb) == -1)
1759 fatal("fstat %s: %s", filename, strerror(errno));
1760 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1761 (sb.st_mode & 022) != 0))
1762 fatal("Bad owner or permissions on %s", filename);
1765 debug("Reading configuration data %.200s", filename);
1768 * Mark that we are now processing the options. This flag is turned
1769 * on/off by Host specifications.
1772 while (getline(&line, &linesize, f) != -1) {
1773 /* Update line number counter. */
1775 if (process_config_line_depth(options, pw, host, original_host,
1776 line, filename, linenum, activep, flags, depth) != 0)
1781 if (bad_options > 0)
1782 fatal("%s: terminating, %d bad configuration options",
1783 filename, bad_options);
1787 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1789 option_clear_or_none(const char *o)
1791 return o == NULL || strcasecmp(o, "none") == 0;
1795 * Initializes options to special values that indicate that they have not yet
1796 * been set. Read_config_file will only set options with this value. Options
1797 * are processed in the following order: command line, user config file,
1798 * system config file. Last, fill_default_options is called.
1802 initialize_options(Options * options)
1804 memset(options, 'X', sizeof(*options));
1805 options->forward_agent = -1;
1806 options->forward_x11 = -1;
1807 options->forward_x11_trusted = -1;
1808 options->forward_x11_timeout = -1;
1809 options->stdio_forward_host = NULL;
1810 options->stdio_forward_port = 0;
1811 options->clear_forwardings = -1;
1812 options->exit_on_forward_failure = -1;
1813 options->xauth_location = NULL;
1814 options->fwd_opts.gateway_ports = -1;
1815 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1816 options->fwd_opts.streamlocal_bind_unlink = -1;
1817 options->pubkey_authentication = -1;
1818 options->challenge_response_authentication = -1;
1819 options->gss_authentication = -1;
1820 options->gss_deleg_creds = -1;
1821 options->password_authentication = -1;
1822 options->kbd_interactive_authentication = -1;
1823 options->kbd_interactive_devices = NULL;
1824 options->hostbased_authentication = -1;
1825 options->batch_mode = -1;
1826 options->check_host_ip = -1;
1827 options->strict_host_key_checking = -1;
1828 options->compression = -1;
1829 options->tcp_keep_alive = -1;
1831 options->address_family = -1;
1832 options->connection_attempts = -1;
1833 options->connection_timeout = -1;
1834 options->number_of_password_prompts = -1;
1835 options->ciphers = NULL;
1836 options->macs = NULL;
1837 options->kex_algorithms = NULL;
1838 options->hostkeyalgorithms = NULL;
1839 options->num_identity_files = 0;
1840 options->num_certificate_files = 0;
1841 options->hostname = NULL;
1842 options->host_key_alias = NULL;
1843 options->proxy_command = NULL;
1844 options->jump_user = NULL;
1845 options->jump_host = NULL;
1846 options->jump_port = -1;
1847 options->jump_extra = NULL;
1848 options->user = NULL;
1849 options->escape_char = -1;
1850 options->num_system_hostfiles = 0;
1851 options->num_user_hostfiles = 0;
1852 options->local_forwards = NULL;
1853 options->num_local_forwards = 0;
1854 options->remote_forwards = NULL;
1855 options->num_remote_forwards = 0;
1856 options->log_facility = SYSLOG_FACILITY_NOT_SET;
1857 options->log_level = SYSLOG_LEVEL_NOT_SET;
1858 options->preferred_authentications = NULL;
1859 options->bind_address = NULL;
1860 options->bind_interface = NULL;
1861 options->pkcs11_provider = NULL;
1862 options->enable_ssh_keysign = - 1;
1863 options->no_host_authentication_for_localhost = - 1;
1864 options->identities_only = - 1;
1865 options->rekey_limit = - 1;
1866 options->rekey_interval = -1;
1867 options->verify_host_key_dns = -1;
1868 options->server_alive_interval = -1;
1869 options->server_alive_count_max = -1;
1870 options->send_env = NULL;
1871 options->num_send_env = 0;
1872 options->setenv = NULL;
1873 options->num_setenv = 0;
1874 options->control_path = NULL;
1875 options->control_master = -1;
1876 options->control_persist = -1;
1877 options->control_persist_timeout = 0;
1878 options->hash_known_hosts = -1;
1879 options->tun_open = -1;
1880 options->tun_local = -1;
1881 options->tun_remote = -1;
1882 options->local_command = NULL;
1883 options->permit_local_command = -1;
1884 options->remote_command = NULL;
1885 options->add_keys_to_agent = -1;
1886 options->identity_agent = NULL;
1887 options->visual_host_key = -1;
1888 options->ip_qos_interactive = -1;
1889 options->ip_qos_bulk = -1;
1890 options->request_tty = -1;
1891 options->proxy_use_fdpass = -1;
1892 options->ignored_unknown = NULL;
1893 options->num_canonical_domains = 0;
1894 options->num_permitted_cnames = 0;
1895 options->canonicalize_max_dots = -1;
1896 options->canonicalize_fallback_local = -1;
1897 options->canonicalize_hostname = -1;
1898 options->revoked_host_keys = NULL;
1899 options->fingerprint_hash = -1;
1900 options->update_hostkeys = -1;
1901 options->hostbased_key_types = NULL;
1902 options->pubkey_key_types = NULL;
1906 * A petite version of fill_default_options() that just fills the options
1907 * needed for hostname canonicalization to proceed.
1910 fill_default_options_for_canonicalization(Options *options)
1912 if (options->canonicalize_max_dots == -1)
1913 options->canonicalize_max_dots = 1;
1914 if (options->canonicalize_fallback_local == -1)
1915 options->canonicalize_fallback_local = 1;
1916 if (options->canonicalize_hostname == -1)
1917 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1921 * Called after processing other sources of option data, this fills those
1922 * options for which no value has been specified with their default values.
1925 fill_default_options(Options * options)
1927 char *all_cipher, *all_mac, *all_kex, *all_key;
1930 if (options->forward_agent == -1)
1931 options->forward_agent = 0;
1932 if (options->forward_x11 == -1)
1933 options->forward_x11 = 0;
1934 if (options->forward_x11_trusted == -1)
1935 options->forward_x11_trusted = 0;
1936 if (options->forward_x11_timeout == -1)
1937 options->forward_x11_timeout = 1200;
1939 * stdio forwarding (-W) changes the default for these but we defer
1940 * setting the values so they can be overridden.
1942 if (options->exit_on_forward_failure == -1)
1943 options->exit_on_forward_failure =
1944 options->stdio_forward_host != NULL ? 1 : 0;
1945 if (options->clear_forwardings == -1)
1946 options->clear_forwardings =
1947 options->stdio_forward_host != NULL ? 1 : 0;
1948 if (options->clear_forwardings == 1)
1949 clear_forwardings(options);
1951 if (options->xauth_location == NULL)
1952 options->xauth_location = _PATH_XAUTH;
1953 if (options->fwd_opts.gateway_ports == -1)
1954 options->fwd_opts.gateway_ports = 0;
1955 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1956 options->fwd_opts.streamlocal_bind_mask = 0177;
1957 if (options->fwd_opts.streamlocal_bind_unlink == -1)
1958 options->fwd_opts.streamlocal_bind_unlink = 0;
1959 if (options->pubkey_authentication == -1)
1960 options->pubkey_authentication = 1;
1961 if (options->challenge_response_authentication == -1)
1962 options->challenge_response_authentication = 1;
1963 if (options->gss_authentication == -1)
1964 options->gss_authentication = 0;
1965 if (options->gss_deleg_creds == -1)
1966 options->gss_deleg_creds = 0;
1967 if (options->password_authentication == -1)
1968 options->password_authentication = 1;
1969 if (options->kbd_interactive_authentication == -1)
1970 options->kbd_interactive_authentication = 1;
1971 if (options->hostbased_authentication == -1)
1972 options->hostbased_authentication = 0;
1973 if (options->batch_mode == -1)
1974 options->batch_mode = 0;
1975 if (options->check_host_ip == -1)
1976 options->check_host_ip = 1;
1977 if (options->strict_host_key_checking == -1)
1978 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
1979 if (options->compression == -1)
1980 options->compression = 0;
1981 if (options->tcp_keep_alive == -1)
1982 options->tcp_keep_alive = 1;
1983 if (options->port == -1)
1984 options->port = 0; /* Filled in ssh_connect. */
1985 if (options->address_family == -1)
1986 options->address_family = AF_UNSPEC;
1987 if (options->connection_attempts == -1)
1988 options->connection_attempts = 1;
1989 if (options->number_of_password_prompts == -1)
1990 options->number_of_password_prompts = 3;
1991 /* options->hostkeyalgorithms, default set in myproposals.h */
1992 if (options->add_keys_to_agent == -1)
1993 options->add_keys_to_agent = 0;
1994 if (options->num_identity_files == 0) {
1995 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
1996 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
1997 #ifdef OPENSSL_HAS_ECC
1998 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2000 add_identity_file(options, "~/",
2001 _PATH_SSH_CLIENT_ID_ED25519, 0);
2002 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2004 if (options->escape_char == -1)
2005 options->escape_char = '~';
2006 if (options->num_system_hostfiles == 0) {
2007 options->system_hostfiles[options->num_system_hostfiles++] =
2008 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2009 options->system_hostfiles[options->num_system_hostfiles++] =
2010 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2012 if (options->num_user_hostfiles == 0) {
2013 options->user_hostfiles[options->num_user_hostfiles++] =
2014 xstrdup(_PATH_SSH_USER_HOSTFILE);
2015 options->user_hostfiles[options->num_user_hostfiles++] =
2016 xstrdup(_PATH_SSH_USER_HOSTFILE2);
2018 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2019 options->log_level = SYSLOG_LEVEL_INFO;
2020 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2021 options->log_facility = SYSLOG_FACILITY_USER;
2022 if (options->no_host_authentication_for_localhost == - 1)
2023 options->no_host_authentication_for_localhost = 0;
2024 if (options->identities_only == -1)
2025 options->identities_only = 0;
2026 if (options->enable_ssh_keysign == -1)
2027 options->enable_ssh_keysign = 0;
2028 if (options->rekey_limit == -1)
2029 options->rekey_limit = 0;
2030 if (options->rekey_interval == -1)
2031 options->rekey_interval = 0;
2032 if (options->verify_host_key_dns == -1)
2033 options->verify_host_key_dns = 0;
2034 if (options->server_alive_interval == -1)
2035 options->server_alive_interval = 0;
2036 if (options->server_alive_count_max == -1)
2037 options->server_alive_count_max = 3;
2038 if (options->control_master == -1)
2039 options->control_master = 0;
2040 if (options->control_persist == -1) {
2041 options->control_persist = 0;
2042 options->control_persist_timeout = 0;
2044 if (options->hash_known_hosts == -1)
2045 options->hash_known_hosts = 0;
2046 if (options->tun_open == -1)
2047 options->tun_open = SSH_TUNMODE_NO;
2048 if (options->tun_local == -1)
2049 options->tun_local = SSH_TUNID_ANY;
2050 if (options->tun_remote == -1)
2051 options->tun_remote = SSH_TUNID_ANY;
2052 if (options->permit_local_command == -1)
2053 options->permit_local_command = 0;
2054 if (options->visual_host_key == -1)
2055 options->visual_host_key = 0;
2056 if (options->ip_qos_interactive == -1)
2057 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2058 if (options->ip_qos_bulk == -1)
2059 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2060 if (options->request_tty == -1)
2061 options->request_tty = REQUEST_TTY_AUTO;
2062 if (options->proxy_use_fdpass == -1)
2063 options->proxy_use_fdpass = 0;
2064 if (options->canonicalize_max_dots == -1)
2065 options->canonicalize_max_dots = 1;
2066 if (options->canonicalize_fallback_local == -1)
2067 options->canonicalize_fallback_local = 1;
2068 if (options->canonicalize_hostname == -1)
2069 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2070 if (options->fingerprint_hash == -1)
2071 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2072 if (options->update_hostkeys == -1)
2073 options->update_hostkeys = 0;
2075 /* Expand KEX name lists */
2076 all_cipher = cipher_alg_list(',', 0);
2077 all_mac = mac_alg_list(',');
2078 all_kex = kex_alg_list(',');
2079 all_key = sshkey_alg_list(0, 0, 1, ',');
2080 #define ASSEMBLE(what, defaults, all) \
2082 if ((r = kex_assemble_names(&options->what, \
2083 defaults, all)) != 0) \
2084 fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
2086 ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
2087 ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
2088 ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
2089 ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
2090 ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
2097 #define CLEAR_ON_NONE(v) \
2099 if (option_clear_or_none(v)) { \
2104 CLEAR_ON_NONE(options->local_command);
2105 CLEAR_ON_NONE(options->remote_command);
2106 CLEAR_ON_NONE(options->proxy_command);
2107 CLEAR_ON_NONE(options->control_path);
2108 CLEAR_ON_NONE(options->revoked_host_keys);
2109 if (options->jump_host != NULL &&
2110 strcmp(options->jump_host, "none") == 0 &&
2111 options->jump_port == 0 && options->jump_user == NULL) {
2112 free(options->jump_host);
2113 options->jump_host = NULL;
2115 /* options->identity_agent distinguishes NULL from 'none' */
2116 /* options->user will be set in the main program if appropriate */
2117 /* options->hostname will be set in the main program if appropriate */
2118 /* options->host_key_alias should not be set by default */
2119 /* options->preferred_authentications will be set in ssh */
2129 * parses the next field in a port forwarding specification.
2130 * sets fwd to the parsed field and advances p past the colon
2131 * or sets it to NULL at end of string.
2132 * returns 0 on success, else non-zero.
2135 parse_fwd_field(char **p, struct fwdarg *fwd)
2142 return -1; /* end of string */
2146 * A field escaped with square brackets is used literally.
2147 * XXX - allow ']' to be escaped via backslash?
2150 /* find matching ']' */
2151 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2155 /* no matching ']' or not at end of field. */
2156 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2158 /* NUL terminate the field and advance p past the colon */
2163 fwd->ispath = ispath;
2168 for (cp = *p; *cp != '\0'; cp++) {
2171 memmove(cp, cp + 1, strlen(cp + 1) + 1);
2185 fwd->ispath = ispath;
2192 * parses a string containing a port forwarding specification of the form:
2194 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2195 * listenpath:connectpath
2197 * [listenhost:]listenport
2198 * returns number of arguments parsed or zero on error
2201 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2203 struct fwdarg fwdargs[4];
2207 memset(fwd, 0, sizeof(*fwd));
2208 memset(fwdargs, 0, sizeof(fwdargs));
2210 cp = p = xstrdup(fwdspec);
2212 /* skip leading spaces */
2213 while (isspace((u_char)*cp))
2216 for (i = 0; i < 4; ++i) {
2217 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2221 /* Check for trailing garbage */
2222 if (cp != NULL && *cp != '\0') {
2223 i = 0; /* failure */
2228 if (fwdargs[0].ispath) {
2229 fwd->listen_path = xstrdup(fwdargs[0].arg);
2230 fwd->listen_port = PORT_STREAMLOCAL;
2232 fwd->listen_host = NULL;
2233 fwd->listen_port = a2port(fwdargs[0].arg);
2235 fwd->connect_host = xstrdup("socks");
2239 if (fwdargs[0].ispath && fwdargs[1].ispath) {
2240 fwd->listen_path = xstrdup(fwdargs[0].arg);
2241 fwd->listen_port = PORT_STREAMLOCAL;
2242 fwd->connect_path = xstrdup(fwdargs[1].arg);
2243 fwd->connect_port = PORT_STREAMLOCAL;
2244 } else if (fwdargs[1].ispath) {
2245 fwd->listen_host = NULL;
2246 fwd->listen_port = a2port(fwdargs[0].arg);
2247 fwd->connect_path = xstrdup(fwdargs[1].arg);
2248 fwd->connect_port = PORT_STREAMLOCAL;
2250 fwd->listen_host = xstrdup(fwdargs[0].arg);
2251 fwd->listen_port = a2port(fwdargs[1].arg);
2252 fwd->connect_host = xstrdup("socks");
2257 if (fwdargs[0].ispath) {
2258 fwd->listen_path = xstrdup(fwdargs[0].arg);
2259 fwd->listen_port = PORT_STREAMLOCAL;
2260 fwd->connect_host = xstrdup(fwdargs[1].arg);
2261 fwd->connect_port = a2port(fwdargs[2].arg);
2262 } else if (fwdargs[2].ispath) {
2263 fwd->listen_host = xstrdup(fwdargs[0].arg);
2264 fwd->listen_port = a2port(fwdargs[1].arg);
2265 fwd->connect_path = xstrdup(fwdargs[2].arg);
2266 fwd->connect_port = PORT_STREAMLOCAL;
2268 fwd->listen_host = NULL;
2269 fwd->listen_port = a2port(fwdargs[0].arg);
2270 fwd->connect_host = xstrdup(fwdargs[1].arg);
2271 fwd->connect_port = a2port(fwdargs[2].arg);
2276 fwd->listen_host = xstrdup(fwdargs[0].arg);
2277 fwd->listen_port = a2port(fwdargs[1].arg);
2278 fwd->connect_host = xstrdup(fwdargs[2].arg);
2279 fwd->connect_port = a2port(fwdargs[3].arg);
2282 i = 0; /* failure */
2288 if (!(i == 1 || i == 2))
2291 if (!(i == 3 || i == 4)) {
2292 if (fwd->connect_path == NULL &&
2293 fwd->listen_path == NULL)
2296 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2300 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2301 (!remotefwd && fwd->listen_port == 0))
2303 if (fwd->connect_host != NULL &&
2304 strlen(fwd->connect_host) >= NI_MAXHOST)
2306 /* XXX - if connecting to a remote socket, max sun len may not match this host */
2307 if (fwd->connect_path != NULL &&
2308 strlen(fwd->connect_path) >= PATH_MAX_SUN)
2310 if (fwd->listen_host != NULL &&
2311 strlen(fwd->listen_host) >= NI_MAXHOST)
2313 if (fwd->listen_path != NULL &&
2314 strlen(fwd->listen_path) >= PATH_MAX_SUN)
2320 free(fwd->connect_host);
2321 fwd->connect_host = NULL;
2322 free(fwd->connect_path);
2323 fwd->connect_path = NULL;
2324 free(fwd->listen_host);
2325 fwd->listen_host = NULL;
2326 free(fwd->listen_path);
2327 fwd->listen_path = NULL;
2332 parse_jump(const char *s, Options *o, int active)
2334 char *orig, *sdup, *cp;
2335 char *host = NULL, *user = NULL;
2336 int ret = -1, port = -1, first;
2338 active &= o->proxy_command == NULL && o->jump_host == NULL;
2340 orig = sdup = xstrdup(s);
2343 if (strcasecmp(s, "none") == 0)
2345 if ((cp = strrchr(sdup, ',')) == NULL)
2346 cp = sdup; /* last */
2351 /* First argument and configuration is active */
2352 if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
2353 parse_user_host_port(cp, &user, &host, &port) != 0)
2356 /* Subsequent argument or inactive configuration */
2357 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
2358 parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2361 first = 0; /* only check syntax for subsequent hosts */
2362 } while (cp != sdup);
2365 if (strcasecmp(s, "none") == 0) {
2366 o->jump_host = xstrdup("none");
2369 o->jump_user = user;
2370 o->jump_host = host;
2371 o->jump_port = port;
2372 o->proxy_command = xstrdup("none");
2374 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2375 o->jump_extra = xstrdup(s);
2376 o->jump_extra[cp - s] = '\0';
2389 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
2394 r = parse_uri("ssh", uri, userp, hostp, portp, &path);
2395 if (r == 0 && path != NULL)
2396 r = -1; /* path not allowed */
2400 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2402 fmt_multistate_int(int val, const struct multistate *m)
2406 for (i = 0; m[i].key != NULL; i++) {
2407 if (m[i].value == val)
2414 fmt_intarg(OpCodes code, int val)
2419 case oAddressFamily:
2420 return fmt_multistate_int(val, multistate_addressfamily);
2421 case oVerifyHostKeyDNS:
2422 case oUpdateHostkeys:
2423 return fmt_multistate_int(val, multistate_yesnoask);
2424 case oStrictHostKeyChecking:
2425 return fmt_multistate_int(val, multistate_strict_hostkey);
2426 case oControlMaster:
2427 return fmt_multistate_int(val, multistate_controlmaster);
2429 return fmt_multistate_int(val, multistate_tunnel);
2431 return fmt_multistate_int(val, multistate_requesttty);
2432 case oCanonicalizeHostname:
2433 return fmt_multistate_int(val, multistate_canonicalizehostname);
2434 case oAddKeysToAgent:
2435 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
2436 case oFingerprintHash:
2437 return ssh_digest_alg_name(val);
2451 lookup_opcode_name(OpCodes code)
2455 for (i = 0; keywords[i].name != NULL; i++)
2456 if (keywords[i].opcode == code)
2457 return(keywords[i].name);
2462 dump_cfg_int(OpCodes code, int val)
2464 printf("%s %d\n", lookup_opcode_name(code), val);
2468 dump_cfg_fmtint(OpCodes code, int val)
2470 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2474 dump_cfg_string(OpCodes code, const char *val)
2478 printf("%s %s\n", lookup_opcode_name(code), val);
2482 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2486 for (i = 0; i < count; i++)
2487 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2491 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2495 printf("%s", lookup_opcode_name(code));
2496 for (i = 0; i < count; i++)
2497 printf(" %s", vals[i]);
2502 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2504 const struct Forward *fwd;
2507 /* oDynamicForward */
2508 for (i = 0; i < count; i++) {
2510 if (code == oDynamicForward && fwd->connect_host != NULL &&
2511 strcmp(fwd->connect_host, "socks") != 0)
2513 if (code == oLocalForward && fwd->connect_host != NULL &&
2514 strcmp(fwd->connect_host, "socks") == 0)
2516 printf("%s", lookup_opcode_name(code));
2517 if (fwd->listen_port == PORT_STREAMLOCAL)
2518 printf(" %s", fwd->listen_path);
2519 else if (fwd->listen_host == NULL)
2520 printf(" %d", fwd->listen_port);
2523 fwd->listen_host, fwd->listen_port);
2525 if (code != oDynamicForward) {
2526 if (fwd->connect_port == PORT_STREAMLOCAL)
2527 printf(" %s", fwd->connect_path);
2528 else if (fwd->connect_host == NULL)
2529 printf(" %d", fwd->connect_port);
2532 fwd->connect_host, fwd->connect_port);
2540 dump_client_config(Options *o, const char *host)
2543 char buf[8], *all_key;
2545 /* This is normally prepared in ssh_kex2 */
2546 all_key = sshkey_alg_list(0, 0, 1, ',');
2547 if (kex_assemble_names( &o->hostkeyalgorithms,
2548 KEX_DEFAULT_PK_ALG, all_key) != 0)
2549 fatal("%s: kex_assemble_names failed", __func__);
2552 /* Most interesting options first: user, host, port */
2553 dump_cfg_string(oUser, o->user);
2554 dump_cfg_string(oHostName, host);
2555 dump_cfg_int(oPort, o->port);
2558 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
2559 dump_cfg_fmtint(oAddressFamily, o->address_family);
2560 dump_cfg_fmtint(oBatchMode, o->batch_mode);
2561 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2562 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2563 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2564 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2565 dump_cfg_fmtint(oCompression, o->compression);
2566 dump_cfg_fmtint(oControlMaster, o->control_master);
2567 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2568 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2569 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2570 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2571 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2572 dump_cfg_fmtint(oForwardX11, o->forward_x11);
2573 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2574 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2576 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2577 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2579 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2580 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2581 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2582 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2583 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2584 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2585 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2586 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2587 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2588 dump_cfg_fmtint(oRequestTTY, o->request_tty);
2589 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2590 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2591 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2592 dump_cfg_fmtint(oTunnel, o->tun_open);
2593 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2594 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2595 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2597 /* Integer options */
2598 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2599 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2600 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2601 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2602 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2603 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2605 /* String options */
2606 dump_cfg_string(oBindAddress, o->bind_address);
2607 dump_cfg_string(oBindInterface, o->bind_interface);
2608 dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2609 dump_cfg_string(oControlPath, o->control_path);
2610 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2611 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2612 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2613 dump_cfg_string(oIdentityAgent, o->identity_agent);
2614 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
2615 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2616 dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2617 dump_cfg_string(oLocalCommand, o->local_command);
2618 dump_cfg_string(oRemoteCommand, o->remote_command);
2619 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2620 dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2621 #ifdef ENABLE_PKCS11
2622 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2624 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2625 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2626 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2627 dump_cfg_string(oXAuthLocation, o->xauth_location);
2630 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2631 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2632 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2634 /* String array options */
2635 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2636 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2637 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
2638 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2639 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2640 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2641 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
2645 /* oConnectTimeout */
2646 if (o->connection_timeout == -1)
2647 printf("connecttimeout none\n");
2649 dump_cfg_int(oConnectTimeout, o->connection_timeout);
2652 printf("tunneldevice");
2653 if (o->tun_local == SSH_TUNID_ANY)
2656 printf(" %d", o->tun_local);
2657 if (o->tun_remote == SSH_TUNID_ANY)
2660 printf(":%d", o->tun_remote);
2663 /* oCanonicalizePermittedCNAMEs */
2664 if ( o->num_permitted_cnames > 0) {
2665 printf("canonicalizePermittedcnames");
2666 for (i = 0; i < o->num_permitted_cnames; i++) {
2667 printf(" %s:%s", o->permitted_cnames[i].source_list,
2668 o->permitted_cnames[i].target_list);
2673 /* oControlPersist */
2674 if (o->control_persist == 0 || o->control_persist_timeout == 0)
2675 dump_cfg_fmtint(oControlPersist, o->control_persist);
2677 dump_cfg_int(oControlPersist, o->control_persist_timeout);
2680 if (o->escape_char == SSH_ESCAPECHAR_NONE)
2681 printf("escapechar none\n");
2683 vis(buf, o->escape_char, VIS_WHITE, 0);
2684 printf("escapechar %s\n", buf);
2688 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2689 printf("%s\n", iptos2str(o->ip_qos_bulk));
2692 printf("rekeylimit %llu %d\n",
2693 (unsigned long long)o->rekey_limit, o->rekey_interval);
2695 /* oStreamLocalBindMask */
2696 printf("streamlocalbindmask 0%o\n",
2697 o->fwd_opts.streamlocal_bind_mask);
2700 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
2702 /* oProxyCommand / oProxyJump */
2703 if (o->jump_host == NULL)
2704 dump_cfg_string(oProxyCommand, o->proxy_command);
2706 /* Check for numeric addresses */
2707 i = strchr(o->jump_host, ':') != NULL ||
2708 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2709 snprintf(buf, sizeof(buf), "%d", o->jump_port);
2710 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2711 /* optional additional jump spec */
2712 o->jump_extra == NULL ? "" : o->jump_extra,
2713 o->jump_extra == NULL ? "" : ",",
2715 o->jump_user == NULL ? "" : o->jump_user,
2716 o->jump_user == NULL ? "" : "@",
2717 /* opening [ if hostname is numeric */
2719 /* mandatory hostname */
2721 /* closing ] if hostname is numeric */
2723 /* optional port number */
2724 o->jump_port <= 0 ? "" : ":",
2725 o->jump_port <= 0 ? "" : buf);