1 /* $OpenBSD: readconf.c,v 1.304 2019/03/01 02:08:50 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 *want_final_pass, 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,
140 int *want_final_pass, int depth);
142 /* Keyword tokens. */
146 oHost, oMatch, oInclude,
147 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
148 oGatewayPorts, oExitOnForwardFailure,
149 oPasswordAuthentication, oRSAAuthentication,
150 oChallengeResponseAuthentication, oXAuthLocation,
151 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
152 oCertificateFile, oAddKeysToAgent, oIdentityAgent,
153 oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
154 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
155 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
156 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
157 oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs,
158 oPubkeyAuthentication,
159 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
160 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
161 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
162 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
163 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
164 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
165 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
166 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
168 oTunnel, oTunnelDevice,
169 oLocalCommand, oPermitLocalCommand, oRemoteCommand,
171 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
172 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
173 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
174 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
175 oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
176 oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump,
177 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
180 /* Textual representations of the tokens. */
186 /* Deprecated options */
187 { "protocol", oIgnore }, /* NB. silently ignored */
188 { "cipher", oDeprecated },
189 { "fallbacktorsh", oDeprecated },
190 { "globalknownhostsfile2", oDeprecated },
191 { "rhostsauthentication", oDeprecated },
192 { "userknownhostsfile2", oDeprecated },
193 { "useroaming", oDeprecated },
194 { "usersh", oDeprecated },
195 { "useprivilegedport", oDeprecated },
197 /* Unsupported options */
198 { "afstokenpassing", oUnsupported },
199 { "kerberosauthentication", oUnsupported },
200 { "kerberostgtpassing", oUnsupported },
202 /* Sometimes-unsupported options */
204 { "gssapiauthentication", oGssAuthentication },
205 { "gssapidelegatecredentials", oGssDelegateCreds },
207 { "gssapiauthentication", oUnsupported },
208 { "gssapidelegatecredentials", oUnsupported },
211 { "pkcs11provider", oPKCS11Provider },
212 { "smartcarddevice", oPKCS11Provider },
214 { "smartcarddevice", oUnsupported },
215 { "pkcs11provider", oUnsupported },
217 { "rsaauthentication", oUnsupported },
218 { "rhostsrsaauthentication", oUnsupported },
219 { "compressionlevel", oUnsupported },
221 { "forwardagent", oForwardAgent },
222 { "forwardx11", oForwardX11 },
223 { "forwardx11trusted", oForwardX11Trusted },
224 { "forwardx11timeout", oForwardX11Timeout },
225 { "exitonforwardfailure", oExitOnForwardFailure },
226 { "xauthlocation", oXAuthLocation },
227 { "gatewayports", oGatewayPorts },
228 { "passwordauthentication", oPasswordAuthentication },
229 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
230 { "kbdinteractivedevices", oKbdInteractiveDevices },
231 { "pubkeyauthentication", oPubkeyAuthentication },
232 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
233 { "hostbasedauthentication", oHostbasedAuthentication },
234 { "challengeresponseauthentication", oChallengeResponseAuthentication },
235 { "skeyauthentication", oUnsupported },
236 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
237 { "identityfile", oIdentityFile },
238 { "identityfile2", oIdentityFile }, /* obsolete */
239 { "identitiesonly", oIdentitiesOnly },
240 { "certificatefile", oCertificateFile },
241 { "addkeystoagent", oAddKeysToAgent },
242 { "identityagent", oIdentityAgent },
243 { "hostname", oHostName },
244 { "hostkeyalias", oHostKeyAlias },
245 { "proxycommand", oProxyCommand },
247 { "ciphers", oCiphers },
249 { "remoteforward", oRemoteForward },
250 { "localforward", oLocalForward },
254 { "escapechar", oEscapeChar },
255 { "globalknownhostsfile", oGlobalKnownHostsFile },
256 { "userknownhostsfile", oUserKnownHostsFile },
257 { "connectionattempts", oConnectionAttempts },
258 { "batchmode", oBatchMode },
259 { "checkhostip", oCheckHostIP },
260 { "stricthostkeychecking", oStrictHostKeyChecking },
261 { "compression", oCompression },
262 { "tcpkeepalive", oTCPKeepAlive },
263 { "keepalive", oTCPKeepAlive }, /* obsolete */
264 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
265 { "syslogfacility", oLogFacility },
266 { "loglevel", oLogLevel },
267 { "dynamicforward", oDynamicForward },
268 { "preferredauthentications", oPreferredAuthentications },
269 { "hostkeyalgorithms", oHostKeyAlgorithms },
270 { "casignaturealgorithms", oCASignatureAlgorithms },
271 { "bindaddress", oBindAddress },
272 { "bindinterface", oBindInterface },
273 { "clearallforwardings", oClearAllForwardings },
274 { "enablesshkeysign", oEnableSSHKeysign },
275 { "verifyhostkeydns", oVerifyHostKeyDNS },
276 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
277 { "rekeylimit", oRekeyLimit },
278 { "connecttimeout", oConnectTimeout },
279 { "addressfamily", oAddressFamily },
280 { "serveraliveinterval", oServerAliveInterval },
281 { "serveralivecountmax", oServerAliveCountMax },
282 { "sendenv", oSendEnv },
283 { "setenv", oSetEnv },
284 { "controlpath", oControlPath },
285 { "controlmaster", oControlMaster },
286 { "controlpersist", oControlPersist },
287 { "hashknownhosts", oHashKnownHosts },
288 { "include", oInclude },
289 { "tunnel", oTunnel },
290 { "tunneldevice", oTunnelDevice },
291 { "localcommand", oLocalCommand },
292 { "permitlocalcommand", oPermitLocalCommand },
293 { "remotecommand", oRemoteCommand },
294 { "visualhostkey", oVisualHostKey },
295 { "kexalgorithms", oKexAlgorithms },
297 { "requesttty", oRequestTTY },
298 { "proxyusefdpass", oProxyUseFdpass },
299 { "canonicaldomains", oCanonicalDomains },
300 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
301 { "canonicalizehostname", oCanonicalizeHostname },
302 { "canonicalizemaxdots", oCanonicalizeMaxDots },
303 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
304 { "streamlocalbindmask", oStreamLocalBindMask },
305 { "streamlocalbindunlink", oStreamLocalBindUnlink },
306 { "revokedhostkeys", oRevokedHostKeys },
307 { "fingerprinthash", oFingerprintHash },
308 { "updatehostkeys", oUpdateHostkeys },
309 { "hostbasedkeytypes", oHostbasedKeyTypes },
310 { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
311 { "ignoreunknown", oIgnoreUnknown },
312 { "proxyjump", oProxyJump },
318 * Adds a local TCP/IP port forward to options. Never returns if there is an
323 add_local_forward(Options *options, const struct Forward *newfwd)
328 /* Don't add duplicates */
329 for (i = 0; i < options->num_local_forwards; i++) {
330 if (forward_equals(newfwd, options->local_forwards + i))
333 options->local_forwards = xreallocarray(options->local_forwards,
334 options->num_local_forwards + 1,
335 sizeof(*options->local_forwards));
336 fwd = &options->local_forwards[options->num_local_forwards++];
338 fwd->listen_host = newfwd->listen_host;
339 fwd->listen_port = newfwd->listen_port;
340 fwd->listen_path = newfwd->listen_path;
341 fwd->connect_host = newfwd->connect_host;
342 fwd->connect_port = newfwd->connect_port;
343 fwd->connect_path = newfwd->connect_path;
347 * Adds a remote TCP/IP port forward to options. Never returns if there is
352 add_remote_forward(Options *options, const struct Forward *newfwd)
357 /* Don't add duplicates */
358 for (i = 0; i < options->num_remote_forwards; i++) {
359 if (forward_equals(newfwd, options->remote_forwards + i))
362 options->remote_forwards = xreallocarray(options->remote_forwards,
363 options->num_remote_forwards + 1,
364 sizeof(*options->remote_forwards));
365 fwd = &options->remote_forwards[options->num_remote_forwards++];
367 fwd->listen_host = newfwd->listen_host;
368 fwd->listen_port = newfwd->listen_port;
369 fwd->listen_path = newfwd->listen_path;
370 fwd->connect_host = newfwd->connect_host;
371 fwd->connect_port = newfwd->connect_port;
372 fwd->connect_path = newfwd->connect_path;
373 fwd->handle = newfwd->handle;
374 fwd->allocated_port = 0;
378 clear_forwardings(Options *options)
382 for (i = 0; i < options->num_local_forwards; i++) {
383 free(options->local_forwards[i].listen_host);
384 free(options->local_forwards[i].listen_path);
385 free(options->local_forwards[i].connect_host);
386 free(options->local_forwards[i].connect_path);
388 if (options->num_local_forwards > 0) {
389 free(options->local_forwards);
390 options->local_forwards = NULL;
392 options->num_local_forwards = 0;
393 for (i = 0; i < options->num_remote_forwards; i++) {
394 free(options->remote_forwards[i].listen_host);
395 free(options->remote_forwards[i].listen_path);
396 free(options->remote_forwards[i].connect_host);
397 free(options->remote_forwards[i].connect_path);
399 if (options->num_remote_forwards > 0) {
400 free(options->remote_forwards);
401 options->remote_forwards = NULL;
403 options->num_remote_forwards = 0;
404 options->tun_open = SSH_TUNMODE_NO;
408 add_certificate_file(Options *options, const char *path, int userprovided)
412 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
413 fatal("Too many certificate files specified (max %d)",
414 SSH_MAX_CERTIFICATE_FILES);
416 /* Avoid registering duplicates */
417 for (i = 0; i < options->num_certificate_files; i++) {
418 if (options->certificate_file_userprovided[i] == userprovided &&
419 strcmp(options->certificate_files[i], path) == 0) {
420 debug2("%s: ignoring duplicate key %s", __func__, path);
425 options->certificate_file_userprovided[options->num_certificate_files] =
427 options->certificate_files[options->num_certificate_files++] =
432 add_identity_file(Options *options, const char *dir, const char *filename,
438 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
439 fatal("Too many identity files specified (max %d)",
440 SSH_MAX_IDENTITY_FILES);
442 if (dir == NULL) /* no dir, filename is absolute */
443 path = xstrdup(filename);
444 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
445 fatal("Identity file path %s too long", path);
447 /* Avoid registering duplicates */
448 for (i = 0; i < options->num_identity_files; i++) {
449 if (options->identity_file_userprovided[i] == userprovided &&
450 strcmp(options->identity_files[i], path) == 0) {
451 debug2("%s: ignoring duplicate key %s", __func__, path);
457 options->identity_file_userprovided[options->num_identity_files] =
459 options->identity_files[options->num_identity_files++] = path;
463 default_ssh_port(void)
469 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
470 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
476 * Execute a command in a shell.
477 * Return its exit status or -1 on abnormal exit.
480 execute_in_shell(const char *cmd)
486 if ((shell = getenv("SHELL")) == NULL)
487 shell = _PATH_BSHELL;
489 /* Need this to redirect subprocess stdin/out */
490 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
491 fatal("open(/dev/null): %s", strerror(errno));
493 debug("Executing command: '%.500s'", cmd);
495 /* Fork and execute the command. */
496 if ((pid = fork()) == 0) {
499 /* Redirect child stdin and stdout. Leave stderr */
500 if (dup2(devnull, STDIN_FILENO) == -1)
501 fatal("dup2: %s", strerror(errno));
502 if (dup2(devnull, STDOUT_FILENO) == -1)
503 fatal("dup2: %s", strerror(errno));
504 if (devnull > STDERR_FILENO)
506 closefrom(STDERR_FILENO + 1);
510 argv[2] = xstrdup(cmd);
513 execv(argv[0], argv);
514 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
515 /* Die with signal to make this error apparent to parent. */
516 signal(SIGTERM, SIG_DFL);
517 kill(getpid(), SIGTERM);
522 fatal("%s: fork: %.100s", __func__, strerror(errno));
526 while (waitpid(pid, &status, 0) == -1) {
527 if (errno != EINTR && errno != EAGAIN)
528 fatal("%s: waitpid: %s", __func__, strerror(errno));
530 if (!WIFEXITED(status)) {
531 error("command '%.100s' exited abnormally", cmd);
534 debug3("command returned status %d", WEXITSTATUS(status));
535 return WEXITSTATUS(status);
539 * Parse and execute a Match directive.
542 match_cfg_line(Options *options, char **condition, struct passwd *pw,
543 const char *host_arg, const char *original_host, int final_pass,
544 int *want_final_pass, const char *filename, int linenum)
546 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
548 int r, port, this_result, result = 1, attributes = 0, negate;
549 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
553 * Configuration is likely to be incomplete at this point so we
554 * must be prepared to use default values.
556 port = options->port <= 0 ? default_ssh_port() : options->port;
557 ruser = options->user == NULL ? pw->pw_name : options->user;
559 host = xstrdup(options->hostname);
560 } else if (options->hostname != NULL) {
561 /* NB. Please keep in sync with ssh.c:main() */
562 host = percent_expand(options->hostname,
563 "h", host_arg, (char *)NULL);
565 host = xstrdup(host_arg);
568 debug2("checking match for '%s' host %s originally %s",
569 cp, host, original_host);
570 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
573 if ((negate = attrib[0] == '!'))
575 /* criteria "all" and "canonical" have no argument */
576 if (strcasecmp(attrib, "all") == 0) {
577 if (attributes > 1 ||
578 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
579 error("%.200s line %d: '%s' cannot be combined "
580 "with other Match attributes",
581 filename, linenum, oattrib);
586 result = negate ? 0 : 1;
590 if (strcasecmp(attrib, "canonical") == 0 ||
591 strcasecmp(attrib, "final") == 0) {
593 * If the config requests "Match final" then remember
594 * this so we can perform a second pass later.
596 if (strcasecmp(attrib, "final") == 0 &&
597 want_final_pass != NULL)
598 *want_final_pass = 1;
599 r = !!final_pass; /* force bitmask member to boolean */
600 if (r == (negate ? 1 : 0))
601 this_result = result = 0;
602 debug3("%.200s line %d: %smatched '%s'",
604 this_result ? "" : "not ", oattrib);
607 /* All other criteria require an argument */
608 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
609 error("Missing Match criteria for %s", attrib);
613 if (strcasecmp(attrib, "host") == 0) {
614 criteria = xstrdup(host);
615 r = match_hostname(host, arg) == 1;
616 if (r == (negate ? 1 : 0))
617 this_result = result = 0;
618 } else if (strcasecmp(attrib, "originalhost") == 0) {
619 criteria = xstrdup(original_host);
620 r = match_hostname(original_host, arg) == 1;
621 if (r == (negate ? 1 : 0))
622 this_result = result = 0;
623 } else if (strcasecmp(attrib, "user") == 0) {
624 criteria = xstrdup(ruser);
625 r = match_pattern_list(ruser, arg, 0) == 1;
626 if (r == (negate ? 1 : 0))
627 this_result = result = 0;
628 } else if (strcasecmp(attrib, "localuser") == 0) {
629 criteria = xstrdup(pw->pw_name);
630 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
631 if (r == (negate ? 1 : 0))
632 this_result = result = 0;
633 } else if (strcasecmp(attrib, "exec") == 0) {
634 if (gethostname(thishost, sizeof(thishost)) == -1)
635 fatal("gethostname: %s", strerror(errno));
636 strlcpy(shorthost, thishost, sizeof(shorthost));
637 shorthost[strcspn(thishost, ".")] = '\0';
638 snprintf(portstr, sizeof(portstr), "%d", port);
639 snprintf(uidstr, sizeof(uidstr), "%llu",
640 (unsigned long long)pw->pw_uid);
642 cmd = percent_expand(arg,
654 /* skip execution if prior predicate failed */
655 debug3("%.200s line %d: skipped exec "
656 "\"%.100s\"", filename, linenum, cmd);
660 r = execute_in_shell(cmd);
662 fatal("%.200s line %d: match exec "
663 "'%.100s' error", filename,
666 criteria = xstrdup(cmd);
668 /* Force exit status to boolean */
670 if (r == (negate ? 1 : 0))
671 this_result = result = 0;
673 error("Unsupported Match attribute %s", attrib);
677 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
678 filename, linenum, this_result ? "": "not ",
682 if (attributes == 0) {
683 error("One or more attributes required for Match");
689 debug2("match %sfound", result ? "" : "not ");
695 /* Remove environment variable by pattern */
697 rm_env(Options *options, const char *arg, const char *filename, int linenum)
702 /* Remove an environment variable */
703 for (i = 0; i < options->num_send_env; ) {
704 cp = xstrdup(options->send_env[i]);
705 if (!match_pattern(cp, arg + 1)) {
710 debug3("%s line %d: removing environment %s",
711 filename, linenum, cp);
713 free(options->send_env[i]);
714 options->send_env[i] = NULL;
715 for (j = i; j < options->num_send_env - 1; j++) {
716 options->send_env[j] = options->send_env[j + 1];
717 options->send_env[j + 1] = NULL;
719 options->num_send_env--;
720 /* NB. don't increment i */
725 * Returns the number of the token pointed to by cp or oBadOption.
728 parse_token(const char *cp, const char *filename, int linenum,
729 const char *ignored_unknown)
733 for (i = 0; keywords[i].name; i++)
734 if (strcmp(cp, keywords[i].name) == 0)
735 return keywords[i].opcode;
736 if (ignored_unknown != NULL &&
737 match_pattern_list(cp, ignored_unknown, 1) == 1)
738 return oIgnoredUnknownOption;
739 error("%s: line %d: Bad configuration option: %s",
740 filename, linenum, cp);
744 /* Multistate option parsing */
749 static const struct multistate multistate_flag[] = {
756 static const struct multistate multistate_yesnoask[] = {
764 static const struct multistate multistate_strict_hostkey[] = {
765 { "true", SSH_STRICT_HOSTKEY_YES },
766 { "false", SSH_STRICT_HOSTKEY_OFF },
767 { "yes", SSH_STRICT_HOSTKEY_YES },
768 { "no", SSH_STRICT_HOSTKEY_OFF },
769 { "ask", SSH_STRICT_HOSTKEY_ASK },
770 { "off", SSH_STRICT_HOSTKEY_OFF },
771 { "accept-new", SSH_STRICT_HOSTKEY_NEW },
774 static const struct multistate multistate_yesnoaskconfirm[] = {
783 static const struct multistate multistate_addressfamily[] = {
785 { "inet6", AF_INET6 },
786 { "any", AF_UNSPEC },
789 static const struct multistate multistate_controlmaster[] = {
790 { "true", SSHCTL_MASTER_YES },
791 { "yes", SSHCTL_MASTER_YES },
792 { "false", SSHCTL_MASTER_NO },
793 { "no", SSHCTL_MASTER_NO },
794 { "auto", SSHCTL_MASTER_AUTO },
795 { "ask", SSHCTL_MASTER_ASK },
796 { "autoask", SSHCTL_MASTER_AUTO_ASK },
799 static const struct multistate multistate_tunnel[] = {
800 { "ethernet", SSH_TUNMODE_ETHERNET },
801 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
802 { "true", SSH_TUNMODE_DEFAULT },
803 { "yes", SSH_TUNMODE_DEFAULT },
804 { "false", SSH_TUNMODE_NO },
805 { "no", SSH_TUNMODE_NO },
808 static const struct multistate multistate_requesttty[] = {
809 { "true", REQUEST_TTY_YES },
810 { "yes", REQUEST_TTY_YES },
811 { "false", REQUEST_TTY_NO },
812 { "no", REQUEST_TTY_NO },
813 { "force", REQUEST_TTY_FORCE },
814 { "auto", REQUEST_TTY_AUTO },
817 static const struct multistate multistate_canonicalizehostname[] = {
818 { "true", SSH_CANONICALISE_YES },
819 { "false", SSH_CANONICALISE_NO },
820 { "yes", SSH_CANONICALISE_YES },
821 { "no", SSH_CANONICALISE_NO },
822 { "always", SSH_CANONICALISE_ALWAYS },
827 * Processes a single option line as used in the configuration files. This
828 * only sets those values that have not already been set.
831 process_config_line(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)
835 return process_config_line_depth(options, pw, host, original_host,
836 line, filename, linenum, activep, flags, NULL, 0);
839 #define WHITESPACE " \t\r\n"
841 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
842 const char *original_host, char *line, const char *filename,
843 int linenum, int *activep, int flags, int *want_final_pass, int depth)
845 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
846 char **cpptr, fwdarg[256];
847 u_int i, *uintptr, max_entries = 0;
848 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
849 int remotefwd, dynamicfwd;
850 LogLevel *log_level_ptr;
851 SyslogFacility *log_facility_ptr;
855 const struct multistate *multistate_ptr;
856 struct allowed_cname *cname;
860 if (activep == NULL) { /* We are processing a command line directive */
865 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
866 if ((len = strlen(line)) == 0)
868 for (len--; len > 0; len--) {
869 if (strchr(WHITESPACE "\f", line[len]) == NULL)
875 /* Get the keyword. (Each line is supposed to begin with a keyword). */
876 if ((keyword = strdelim(&s)) == NULL)
878 /* Ignore leading whitespace. */
879 if (*keyword == '\0')
880 keyword = strdelim(&s);
881 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
883 /* Match lowercase keyword */
886 opcode = parse_token(keyword, filename, linenum,
887 options->ignored_unknown);
891 /* don't panic, but count bad options */
895 case oIgnoredUnknownOption:
896 debug("%s line %d: Ignored unknown option \"%s\"",
897 filename, linenum, keyword);
899 case oConnectTimeout:
900 intptr = &options->connection_timeout;
903 if (!arg || *arg == '\0')
904 fatal("%s line %d: missing time value.",
906 if (strcmp(arg, "none") == 0)
908 else if ((value = convtime(arg)) == -1)
909 fatal("%s line %d: invalid time value.",
911 if (*activep && *intptr == -1)
916 intptr = &options->forward_agent;
918 multistate_ptr = multistate_flag;
921 if (!arg || *arg == '\0')
922 fatal("%s line %d: missing argument.",
925 for (i = 0; multistate_ptr[i].key != NULL; i++) {
926 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
927 value = multistate_ptr[i].value;
932 fatal("%s line %d: unsupported option \"%s\".",
933 filename, linenum, arg);
934 if (*activep && *intptr == -1)
939 intptr = &options->forward_x11;
942 case oForwardX11Trusted:
943 intptr = &options->forward_x11_trusted;
946 case oForwardX11Timeout:
947 intptr = &options->forward_x11_timeout;
951 intptr = &options->fwd_opts.gateway_ports;
954 case oExitOnForwardFailure:
955 intptr = &options->exit_on_forward_failure;
958 case oPasswordAuthentication:
959 intptr = &options->password_authentication;
962 case oKbdInteractiveAuthentication:
963 intptr = &options->kbd_interactive_authentication;
966 case oKbdInteractiveDevices:
967 charptr = &options->kbd_interactive_devices;
970 case oPubkeyAuthentication:
971 intptr = &options->pubkey_authentication;
974 case oHostbasedAuthentication:
975 intptr = &options->hostbased_authentication;
978 case oChallengeResponseAuthentication:
979 intptr = &options->challenge_response_authentication;
982 case oGssAuthentication:
983 intptr = &options->gss_authentication;
986 case oGssDelegateCreds:
987 intptr = &options->gss_deleg_creds;
991 intptr = &options->batch_mode;
995 intptr = &options->check_host_ip;
998 case oVerifyHostKeyDNS:
999 intptr = &options->verify_host_key_dns;
1000 multistate_ptr = multistate_yesnoask;
1001 goto parse_multistate;
1003 case oStrictHostKeyChecking:
1004 intptr = &options->strict_host_key_checking;
1005 multistate_ptr = multistate_strict_hostkey;
1006 goto parse_multistate;
1009 intptr = &options->compression;
1013 intptr = &options->tcp_keep_alive;
1016 case oNoHostAuthenticationForLocalhost:
1017 intptr = &options->no_host_authentication_for_localhost;
1020 case oNumberOfPasswordPrompts:
1021 intptr = &options->number_of_password_prompts;
1026 if (!arg || *arg == '\0')
1027 fatal("%.200s line %d: Missing argument.", filename,
1029 if (strcmp(arg, "default") == 0) {
1032 if (scan_scaled(arg, &val64) == -1)
1033 fatal("%.200s line %d: Bad number '%s': %s",
1034 filename, linenum, arg, strerror(errno));
1035 if (val64 != 0 && val64 < 16)
1036 fatal("%.200s line %d: RekeyLimit too small",
1039 if (*activep && options->rekey_limit == -1)
1040 options->rekey_limit = val64;
1041 if (s != NULL) { /* optional rekey interval present */
1042 if (strcmp(s, "none") == 0) {
1043 (void)strdelim(&s); /* discard */
1046 intptr = &options->rekey_interval;
1053 if (!arg || *arg == '\0')
1054 fatal("%.200s line %d: Missing argument.", filename, linenum);
1056 intptr = &options->num_identity_files;
1057 if (*intptr >= SSH_MAX_IDENTITY_FILES)
1058 fatal("%.200s line %d: Too many identity files specified (max %d).",
1059 filename, linenum, SSH_MAX_IDENTITY_FILES);
1060 add_identity_file(options, NULL,
1061 arg, flags & SSHCONF_USERCONF);
1065 case oCertificateFile:
1067 if (!arg || *arg == '\0')
1068 fatal("%.200s line %d: Missing argument.",
1071 intptr = &options->num_certificate_files;
1072 if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1073 fatal("%.200s line %d: Too many certificate "
1074 "files specified (max %d).",
1076 SSH_MAX_CERTIFICATE_FILES);
1078 add_certificate_file(options, arg,
1079 flags & SSHCONF_USERCONF);
1083 case oXAuthLocation:
1084 charptr=&options->xauth_location;
1088 charptr = &options->user;
1091 if (!arg || *arg == '\0')
1092 fatal("%.200s line %d: Missing argument.",
1094 if (*activep && *charptr == NULL)
1095 *charptr = xstrdup(arg);
1098 case oGlobalKnownHostsFile:
1099 cpptr = (char **)&options->system_hostfiles;
1100 uintptr = &options->num_system_hostfiles;
1101 max_entries = SSH_MAX_HOSTS_FILES;
1103 if (*activep && *uintptr == 0) {
1104 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1105 if ((*uintptr) >= max_entries)
1106 fatal("%s line %d: "
1107 "too many authorized keys files.",
1109 cpptr[(*uintptr)++] = xstrdup(arg);
1114 case oUserKnownHostsFile:
1115 cpptr = (char **)&options->user_hostfiles;
1116 uintptr = &options->num_user_hostfiles;
1117 max_entries = SSH_MAX_HOSTS_FILES;
1118 goto parse_char_array;
1121 charptr = &options->hostname;
1125 charptr = &options->host_key_alias;
1128 case oPreferredAuthentications:
1129 charptr = &options->preferred_authentications;
1133 charptr = &options->bind_address;
1136 case oBindInterface:
1137 charptr = &options->bind_interface;
1140 case oPKCS11Provider:
1141 charptr = &options->pkcs11_provider;
1145 charptr = &options->proxy_command;
1146 /* Ignore ProxyCommand if ProxyJump already specified */
1147 if (options->jump_host != NULL)
1148 charptr = &options->jump_host; /* Skip below */
1151 fatal("%.200s line %d: Missing argument.", filename, linenum);
1152 len = strspn(s, WHITESPACE "=");
1153 if (*activep && *charptr == NULL)
1154 *charptr = xstrdup(s + len);
1159 fatal("%.200s line %d: Missing argument.",
1162 len = strspn(s, WHITESPACE "=");
1163 if (parse_jump(s + len, options, *activep) == -1) {
1164 fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
1165 filename, linenum, s + len);
1171 if (!arg || *arg == '\0')
1172 fatal("%.200s line %d: Missing argument.",
1174 value = a2port(arg);
1176 fatal("%.200s line %d: Bad port '%s'.",
1177 filename, linenum, arg);
1178 if (*activep && options->port == -1)
1179 options->port = value;
1182 case oConnectionAttempts:
1183 intptr = &options->connection_attempts;
1186 if ((errstr = atoi_err(arg, &value)) != NULL)
1187 fatal("%s line %d: integer value %s.",
1188 filename, linenum, errstr);
1189 if (*activep && *intptr == -1)
1195 if (!arg || *arg == '\0')
1196 fatal("%.200s line %d: Missing argument.", filename, linenum);
1197 if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
1198 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1199 filename, linenum, arg ? arg : "<NONE>");
1200 if (*activep && options->ciphers == NULL)
1201 options->ciphers = xstrdup(arg);
1206 if (!arg || *arg == '\0')
1207 fatal("%.200s line %d: Missing argument.", filename, linenum);
1208 if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
1209 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1210 filename, linenum, arg ? arg : "<NONE>");
1211 if (*activep && options->macs == NULL)
1212 options->macs = xstrdup(arg);
1215 case oKexAlgorithms:
1217 if (!arg || *arg == '\0')
1218 fatal("%.200s line %d: Missing argument.",
1221 !kex_names_valid(*arg == '+' ? arg + 1 : arg))
1222 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1223 filename, linenum, arg ? arg : "<NONE>");
1224 if (*activep && options->kex_algorithms == NULL)
1225 options->kex_algorithms = xstrdup(arg);
1228 case oHostKeyAlgorithms:
1229 charptr = &options->hostkeyalgorithms;
1232 if (!arg || *arg == '\0')
1233 fatal("%.200s line %d: Missing argument.",
1236 !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1237 fatal("%s line %d: Bad key types '%s'.",
1238 filename, linenum, arg ? arg : "<NONE>");
1239 if (*activep && *charptr == NULL)
1240 *charptr = xstrdup(arg);
1243 case oCASignatureAlgorithms:
1244 charptr = &options->ca_sign_algorithms;
1245 goto parse_keytypes;
1248 log_level_ptr = &options->log_level;
1250 value = log_level_number(arg);
1251 if (value == SYSLOG_LEVEL_NOT_SET)
1252 fatal("%.200s line %d: unsupported log level '%s'",
1253 filename, linenum, arg ? arg : "<NONE>");
1254 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1255 *log_level_ptr = (LogLevel) value;
1259 log_facility_ptr = &options->log_facility;
1261 value = log_facility_number(arg);
1262 if (value == SYSLOG_FACILITY_NOT_SET)
1263 fatal("%.200s line %d: unsupported log facility '%s'",
1264 filename, linenum, arg ? arg : "<NONE>");
1265 if (*log_facility_ptr == -1)
1266 *log_facility_ptr = (SyslogFacility) value;
1270 case oRemoteForward:
1271 case oDynamicForward:
1273 if (arg == NULL || *arg == '\0')
1274 fatal("%.200s line %d: Missing port argument.",
1277 remotefwd = (opcode == oRemoteForward);
1278 dynamicfwd = (opcode == oDynamicForward);
1281 arg2 = strdelim(&s);
1282 if (arg2 == NULL || *arg2 == '\0') {
1286 fatal("%.200s line %d: Missing target "
1287 "argument.", filename, linenum);
1289 /* construct a string for parse_forward */
1290 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1295 strlcpy(fwdarg, arg, sizeof(fwdarg));
1297 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1298 fatal("%.200s line %d: Bad forwarding specification.",
1303 add_remote_forward(options, &fwd);
1305 add_local_forward(options, &fwd);
1310 case oClearAllForwardings:
1311 intptr = &options->clear_forwardings;
1316 fatal("Host directive not supported as a command-line "
1320 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1321 if ((flags & SSHCONF_NEVERMATCH) != 0)
1323 negated = *arg == '!';
1326 if (match_pattern(host, arg)) {
1328 debug("%.200s line %d: Skipping Host "
1329 "block because of negated match "
1330 "for %.100s", filename, linenum,
1336 arg2 = arg; /* logged below */
1341 debug("%.200s line %d: Applying options for %.100s",
1342 filename, linenum, arg2);
1343 /* Avoid garbage check below, as strdelim is done. */
1348 fatal("Host directive not supported as a command-line "
1350 value = match_cfg_line(options, &s, pw, host, original_host,
1351 flags & SSHCONF_FINAL, want_final_pass,
1354 fatal("%.200s line %d: Bad Match condition", filename,
1356 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1360 intptr = &options->escape_char;
1362 if (!arg || *arg == '\0')
1363 fatal("%.200s line %d: Missing argument.", filename, linenum);
1364 if (strcmp(arg, "none") == 0)
1365 value = SSH_ESCAPECHAR_NONE;
1366 else if (arg[1] == '\0')
1367 value = (u_char) arg[0];
1368 else if (arg[0] == '^' && arg[2] == 0 &&
1369 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1370 value = (u_char) arg[1] & 31;
1372 fatal("%.200s line %d: Bad escape character.",
1375 value = 0; /* Avoid compiler warning. */
1377 if (*activep && *intptr == -1)
1381 case oAddressFamily:
1382 intptr = &options->address_family;
1383 multistate_ptr = multistate_addressfamily;
1384 goto parse_multistate;
1386 case oEnableSSHKeysign:
1387 intptr = &options->enable_ssh_keysign;
1390 case oIdentitiesOnly:
1391 intptr = &options->identities_only;
1394 case oServerAliveInterval:
1395 intptr = &options->server_alive_interval;
1398 case oServerAliveCountMax:
1399 intptr = &options->server_alive_count_max;
1403 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1404 if (strchr(arg, '=') != NULL)
1405 fatal("%s line %d: Invalid environment name.",
1410 /* Removing an env var */
1411 rm_env(options, arg, filename, linenum);
1414 /* Adding an env var */
1415 if (options->num_send_env >= INT_MAX)
1416 fatal("%s line %d: too many send env.",
1418 options->send_env = xrecallocarray(
1419 options->send_env, options->num_send_env,
1420 options->num_send_env + 1,
1421 sizeof(*options->send_env));
1422 options->send_env[options->num_send_env++] =
1429 value = options->num_setenv;
1430 while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
1431 if (strchr(arg, '=') == NULL)
1432 fatal("%s line %d: Invalid SetEnv.",
1434 if (!*activep || value != 0)
1436 /* Adding a setenv var */
1437 if (options->num_setenv >= INT_MAX)
1438 fatal("%s line %d: too many SetEnv.",
1440 options->setenv = xrecallocarray(
1441 options->setenv, options->num_setenv,
1442 options->num_setenv + 1, sizeof(*options->setenv));
1443 options->setenv[options->num_setenv++] = xstrdup(arg);
1448 charptr = &options->control_path;
1451 case oControlMaster:
1452 intptr = &options->control_master;
1453 multistate_ptr = multistate_controlmaster;
1454 goto parse_multistate;
1456 case oControlPersist:
1457 /* no/false/yes/true, or a time spec */
1458 intptr = &options->control_persist;
1460 if (!arg || *arg == '\0')
1461 fatal("%.200s line %d: Missing ControlPersist"
1462 " argument.", filename, linenum);
1464 value2 = 0; /* timeout */
1465 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1467 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1469 else if ((value2 = convtime(arg)) >= 0)
1472 fatal("%.200s line %d: Bad ControlPersist argument.",
1474 if (*activep && *intptr == -1) {
1476 options->control_persist_timeout = value2;
1480 case oHashKnownHosts:
1481 intptr = &options->hash_known_hosts;
1485 intptr = &options->tun_open;
1486 multistate_ptr = multistate_tunnel;
1487 goto parse_multistate;
1491 if (!arg || *arg == '\0')
1492 fatal("%.200s line %d: Missing argument.", filename, linenum);
1493 value = a2tun(arg, &value2);
1494 if (value == SSH_TUNID_ERR)
1495 fatal("%.200s line %d: Bad tun device.", filename, linenum);
1497 options->tun_local = value;
1498 options->tun_remote = value2;
1503 charptr = &options->local_command;
1506 case oPermitLocalCommand:
1507 intptr = &options->permit_local_command;
1510 case oRemoteCommand:
1511 charptr = &options->remote_command;
1514 case oVisualHostKey:
1515 intptr = &options->visual_host_key;
1520 fatal("Include directive not supported as a "
1521 "command-line option");
1523 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1525 * Ensure all paths are anchored. User configuration
1526 * files may begin with '~/' but system configurations
1527 * must not. If the path is relative, then treat it
1528 * as living in ~/.ssh for user configurations or
1529 * /etc/ssh for system ones.
1531 if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
1532 fatal("%.200s line %d: bad include path %s.",
1533 filename, linenum, arg);
1534 if (!path_absolute(arg) && *arg != '~') {
1535 xasprintf(&arg2, "%s/%s",
1536 (flags & SSHCONF_USERCONF) ?
1537 "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1539 arg2 = xstrdup(arg);
1540 memset(&gl, 0, sizeof(gl));
1541 r = glob(arg2, GLOB_TILDE, NULL, &gl);
1542 if (r == GLOB_NOMATCH) {
1543 debug("%.200s line %d: include %s matched no "
1544 "files",filename, linenum, arg2);
1547 } else if (r != 0 || gl.gl_pathc < 0)
1548 fatal("%.200s line %d: glob failed for %s.",
1549 filename, linenum, arg2);
1552 for (i = 0; i < (u_int)gl.gl_pathc; i++) {
1553 debug3("%.200s line %d: Including file %s "
1554 "depth %d%s", filename, linenum,
1555 gl.gl_pathv[i], depth,
1556 oactive ? "" : " (parse only)");
1557 r = read_config_file_depth(gl.gl_pathv[i],
1558 pw, host, original_host, options,
1559 flags | SSHCONF_CHECKPERM |
1560 (oactive ? 0 : SSHCONF_NEVERMATCH),
1561 activep, want_final_pass, depth + 1);
1562 if (r != 1 && errno != ENOENT) {
1563 fatal("Can't open user config file "
1564 "%.100s: %.100s", gl.gl_pathv[i],
1568 * don't let Match in includes clobber the
1569 * containing file's Match state.
1583 if ((value = parse_ipqos(arg)) == -1)
1584 fatal("%s line %d: Bad IPQoS value: %s",
1585 filename, linenum, arg);
1589 else if ((value2 = parse_ipqos(arg)) == -1)
1590 fatal("%s line %d: Bad IPQoS value: %s",
1591 filename, linenum, arg);
1593 options->ip_qos_interactive = value;
1594 options->ip_qos_bulk = value2;
1599 intptr = &options->request_tty;
1600 multistate_ptr = multistate_requesttty;
1601 goto parse_multistate;
1603 case oIgnoreUnknown:
1604 charptr = &options->ignored_unknown;
1607 case oProxyUseFdpass:
1608 intptr = &options->proxy_use_fdpass;
1611 case oCanonicalDomains:
1612 value = options->num_canonical_domains != 0;
1613 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1614 if (!valid_domain(arg, 1, &errstr)) {
1615 fatal("%s line %d: %s", filename, linenum,
1618 if (!*activep || value)
1620 if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1621 fatal("%s line %d: too many hostname suffixes.",
1623 options->canonical_domains[
1624 options->num_canonical_domains++] = xstrdup(arg);
1628 case oCanonicalizePermittedCNAMEs:
1629 value = options->num_permitted_cnames != 0;
1630 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1631 /* Either '*' for everything or 'list:list' */
1632 if (strcmp(arg, "*") == 0)
1636 if ((arg2 = strchr(arg, ':')) == NULL ||
1638 fatal("%s line %d: "
1639 "Invalid permitted CNAME \"%s\"",
1640 filename, linenum, arg);
1645 if (!*activep || value)
1647 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1648 fatal("%s line %d: too many permitted CNAMEs.",
1650 cname = options->permitted_cnames +
1651 options->num_permitted_cnames++;
1652 cname->source_list = xstrdup(arg);
1653 cname->target_list = xstrdup(arg2);
1657 case oCanonicalizeHostname:
1658 intptr = &options->canonicalize_hostname;
1659 multistate_ptr = multistate_canonicalizehostname;
1660 goto parse_multistate;
1662 case oCanonicalizeMaxDots:
1663 intptr = &options->canonicalize_max_dots;
1666 case oCanonicalizeFallbackLocal:
1667 intptr = &options->canonicalize_fallback_local;
1670 case oStreamLocalBindMask:
1672 if (!arg || *arg == '\0')
1673 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1674 /* Parse mode in octal format */
1675 value = strtol(arg, &endofnumber, 8);
1676 if (arg == endofnumber || value < 0 || value > 0777)
1677 fatal("%.200s line %d: Bad mask.", filename, linenum);
1678 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1681 case oStreamLocalBindUnlink:
1682 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1685 case oRevokedHostKeys:
1686 charptr = &options->revoked_host_keys;
1689 case oFingerprintHash:
1690 intptr = &options->fingerprint_hash;
1692 if (!arg || *arg == '\0')
1693 fatal("%.200s line %d: Missing argument.",
1695 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1696 fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1697 filename, linenum, arg);
1698 if (*activep && *intptr == -1)
1702 case oUpdateHostkeys:
1703 intptr = &options->update_hostkeys;
1704 multistate_ptr = multistate_yesnoask;
1705 goto parse_multistate;
1707 case oHostbasedKeyTypes:
1708 charptr = &options->hostbased_key_types;
1709 goto parse_keytypes;
1711 case oPubkeyAcceptedKeyTypes:
1712 charptr = &options->pubkey_key_types;
1713 goto parse_keytypes;
1715 case oAddKeysToAgent:
1716 intptr = &options->add_keys_to_agent;
1717 multistate_ptr = multistate_yesnoaskconfirm;
1718 goto parse_multistate;
1720 case oIdentityAgent:
1721 charptr = &options->identity_agent;
1723 if (!arg || *arg == '\0')
1724 fatal("%.200s line %d: Missing argument.",
1726 /* Extra validation if the string represents an env var. */
1727 if (arg[0] == '$' && !valid_env_name(arg + 1)) {
1728 fatal("%.200s line %d: Invalid environment name %s.",
1729 filename, linenum, arg);
1731 if (*activep && *charptr == NULL)
1732 *charptr = xstrdup(arg);
1736 debug("%s line %d: Deprecated option \"%s\"",
1737 filename, linenum, keyword);
1741 error("%s line %d: Unsupported option \"%s\"",
1742 filename, linenum, keyword);
1746 fatal("%s: Unimplemented opcode %d", __func__, opcode);
1749 /* Check that there is no garbage at end of line. */
1750 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1751 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1752 filename, linenum, arg);
1758 * Reads the config file and modifies the options accordingly. Options
1759 * should already be initialized before this call. This never returns if
1760 * there is an error. If the file does not exist, this returns 0.
1763 read_config_file(const char *filename, struct passwd *pw, const char *host,
1764 const char *original_host, Options *options, int flags,
1765 int *want_final_pass)
1769 return read_config_file_depth(filename, pw, host, original_host,
1770 options, flags, &active, want_final_pass, 0);
1773 #define READCONF_MAX_DEPTH 16
1775 read_config_file_depth(const char *filename, struct passwd *pw,
1776 const char *host, const char *original_host, Options *options,
1777 int flags, int *activep, int *want_final_pass, int depth)
1781 size_t linesize = 0;
1783 int bad_options = 0;
1785 if (depth < 0 || depth > READCONF_MAX_DEPTH)
1786 fatal("Too many recursive configuration includes");
1788 if ((f = fopen(filename, "r")) == NULL)
1791 if (flags & SSHCONF_CHECKPERM) {
1794 if (fstat(fileno(f), &sb) == -1)
1795 fatal("fstat %s: %s", filename, strerror(errno));
1796 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1797 (sb.st_mode & 022) != 0))
1798 fatal("Bad owner or permissions on %s", filename);
1801 debug("Reading configuration data %.200s", filename);
1804 * Mark that we are now processing the options. This flag is turned
1805 * on/off by Host specifications.
1808 while (getline(&line, &linesize, f) != -1) {
1809 /* Update line number counter. */
1811 if (process_config_line_depth(options, pw, host, original_host,
1812 line, filename, linenum, activep, flags, want_final_pass,
1818 if (bad_options > 0)
1819 fatal("%s: terminating, %d bad configuration options",
1820 filename, bad_options);
1824 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1826 option_clear_or_none(const char *o)
1828 return o == NULL || strcasecmp(o, "none") == 0;
1832 * Initializes options to special values that indicate that they have not yet
1833 * been set. Read_config_file will only set options with this value. Options
1834 * are processed in the following order: command line, user config file,
1835 * system config file. Last, fill_default_options is called.
1839 initialize_options(Options * options)
1841 memset(options, 'X', sizeof(*options));
1842 options->forward_agent = -1;
1843 options->forward_x11 = -1;
1844 options->forward_x11_trusted = -1;
1845 options->forward_x11_timeout = -1;
1846 options->stdio_forward_host = NULL;
1847 options->stdio_forward_port = 0;
1848 options->clear_forwardings = -1;
1849 options->exit_on_forward_failure = -1;
1850 options->xauth_location = NULL;
1851 options->fwd_opts.gateway_ports = -1;
1852 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1853 options->fwd_opts.streamlocal_bind_unlink = -1;
1854 options->pubkey_authentication = -1;
1855 options->challenge_response_authentication = -1;
1856 options->gss_authentication = -1;
1857 options->gss_deleg_creds = -1;
1858 options->password_authentication = -1;
1859 options->kbd_interactive_authentication = -1;
1860 options->kbd_interactive_devices = NULL;
1861 options->hostbased_authentication = -1;
1862 options->batch_mode = -1;
1863 options->check_host_ip = -1;
1864 options->strict_host_key_checking = -1;
1865 options->compression = -1;
1866 options->tcp_keep_alive = -1;
1868 options->address_family = -1;
1869 options->connection_attempts = -1;
1870 options->connection_timeout = -1;
1871 options->number_of_password_prompts = -1;
1872 options->ciphers = NULL;
1873 options->macs = NULL;
1874 options->kex_algorithms = NULL;
1875 options->hostkeyalgorithms = NULL;
1876 options->ca_sign_algorithms = NULL;
1877 options->num_identity_files = 0;
1878 options->num_certificate_files = 0;
1879 options->hostname = NULL;
1880 options->host_key_alias = NULL;
1881 options->proxy_command = NULL;
1882 options->jump_user = NULL;
1883 options->jump_host = NULL;
1884 options->jump_port = -1;
1885 options->jump_extra = NULL;
1886 options->user = NULL;
1887 options->escape_char = -1;
1888 options->num_system_hostfiles = 0;
1889 options->num_user_hostfiles = 0;
1890 options->local_forwards = NULL;
1891 options->num_local_forwards = 0;
1892 options->remote_forwards = NULL;
1893 options->num_remote_forwards = 0;
1894 options->log_facility = SYSLOG_FACILITY_NOT_SET;
1895 options->log_level = SYSLOG_LEVEL_NOT_SET;
1896 options->preferred_authentications = NULL;
1897 options->bind_address = NULL;
1898 options->bind_interface = NULL;
1899 options->pkcs11_provider = NULL;
1900 options->enable_ssh_keysign = - 1;
1901 options->no_host_authentication_for_localhost = - 1;
1902 options->identities_only = - 1;
1903 options->rekey_limit = - 1;
1904 options->rekey_interval = -1;
1905 options->verify_host_key_dns = -1;
1906 options->server_alive_interval = -1;
1907 options->server_alive_count_max = -1;
1908 options->send_env = NULL;
1909 options->num_send_env = 0;
1910 options->setenv = NULL;
1911 options->num_setenv = 0;
1912 options->control_path = NULL;
1913 options->control_master = -1;
1914 options->control_persist = -1;
1915 options->control_persist_timeout = 0;
1916 options->hash_known_hosts = -1;
1917 options->tun_open = -1;
1918 options->tun_local = -1;
1919 options->tun_remote = -1;
1920 options->local_command = NULL;
1921 options->permit_local_command = -1;
1922 options->remote_command = NULL;
1923 options->add_keys_to_agent = -1;
1924 options->identity_agent = NULL;
1925 options->visual_host_key = -1;
1926 options->ip_qos_interactive = -1;
1927 options->ip_qos_bulk = -1;
1928 options->request_tty = -1;
1929 options->proxy_use_fdpass = -1;
1930 options->ignored_unknown = NULL;
1931 options->num_canonical_domains = 0;
1932 options->num_permitted_cnames = 0;
1933 options->canonicalize_max_dots = -1;
1934 options->canonicalize_fallback_local = -1;
1935 options->canonicalize_hostname = -1;
1936 options->revoked_host_keys = NULL;
1937 options->fingerprint_hash = -1;
1938 options->update_hostkeys = -1;
1939 options->hostbased_key_types = NULL;
1940 options->pubkey_key_types = NULL;
1944 * A petite version of fill_default_options() that just fills the options
1945 * needed for hostname canonicalization to proceed.
1948 fill_default_options_for_canonicalization(Options *options)
1950 if (options->canonicalize_max_dots == -1)
1951 options->canonicalize_max_dots = 1;
1952 if (options->canonicalize_fallback_local == -1)
1953 options->canonicalize_fallback_local = 1;
1954 if (options->canonicalize_hostname == -1)
1955 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1959 * Called after processing other sources of option data, this fills those
1960 * options for which no value has been specified with their default values.
1963 fill_default_options(Options * options)
1965 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
1968 if (options->forward_agent == -1)
1969 options->forward_agent = 0;
1970 if (options->forward_x11 == -1)
1971 options->forward_x11 = 0;
1972 if (options->forward_x11_trusted == -1)
1973 options->forward_x11_trusted = 0;
1974 if (options->forward_x11_timeout == -1)
1975 options->forward_x11_timeout = 1200;
1977 * stdio forwarding (-W) changes the default for these but we defer
1978 * setting the values so they can be overridden.
1980 if (options->exit_on_forward_failure == -1)
1981 options->exit_on_forward_failure =
1982 options->stdio_forward_host != NULL ? 1 : 0;
1983 if (options->clear_forwardings == -1)
1984 options->clear_forwardings =
1985 options->stdio_forward_host != NULL ? 1 : 0;
1986 if (options->clear_forwardings == 1)
1987 clear_forwardings(options);
1989 if (options->xauth_location == NULL)
1990 options->xauth_location = _PATH_XAUTH;
1991 if (options->fwd_opts.gateway_ports == -1)
1992 options->fwd_opts.gateway_ports = 0;
1993 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1994 options->fwd_opts.streamlocal_bind_mask = 0177;
1995 if (options->fwd_opts.streamlocal_bind_unlink == -1)
1996 options->fwd_opts.streamlocal_bind_unlink = 0;
1997 if (options->pubkey_authentication == -1)
1998 options->pubkey_authentication = 1;
1999 if (options->challenge_response_authentication == -1)
2000 options->challenge_response_authentication = 1;
2001 if (options->gss_authentication == -1)
2002 options->gss_authentication = 0;
2003 if (options->gss_deleg_creds == -1)
2004 options->gss_deleg_creds = 0;
2005 if (options->password_authentication == -1)
2006 options->password_authentication = 1;
2007 if (options->kbd_interactive_authentication == -1)
2008 options->kbd_interactive_authentication = 1;
2009 if (options->hostbased_authentication == -1)
2010 options->hostbased_authentication = 0;
2011 if (options->batch_mode == -1)
2012 options->batch_mode = 0;
2013 if (options->check_host_ip == -1)
2014 options->check_host_ip = 1;
2015 if (options->strict_host_key_checking == -1)
2016 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2017 if (options->compression == -1)
2018 options->compression = 0;
2019 if (options->tcp_keep_alive == -1)
2020 options->tcp_keep_alive = 1;
2021 if (options->port == -1)
2022 options->port = 0; /* Filled in ssh_connect. */
2023 if (options->address_family == -1)
2024 options->address_family = AF_UNSPEC;
2025 if (options->connection_attempts == -1)
2026 options->connection_attempts = 1;
2027 if (options->number_of_password_prompts == -1)
2028 options->number_of_password_prompts = 3;
2029 /* options->hostkeyalgorithms, default set in myproposals.h */
2030 if (options->add_keys_to_agent == -1)
2031 options->add_keys_to_agent = 0;
2032 if (options->num_identity_files == 0) {
2033 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2034 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2035 #ifdef OPENSSL_HAS_ECC
2036 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2038 add_identity_file(options, "~/",
2039 _PATH_SSH_CLIENT_ID_ED25519, 0);
2040 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2042 if (options->escape_char == -1)
2043 options->escape_char = '~';
2044 if (options->num_system_hostfiles == 0) {
2045 options->system_hostfiles[options->num_system_hostfiles++] =
2046 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2047 options->system_hostfiles[options->num_system_hostfiles++] =
2048 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2050 if (options->num_user_hostfiles == 0) {
2051 options->user_hostfiles[options->num_user_hostfiles++] =
2052 xstrdup(_PATH_SSH_USER_HOSTFILE);
2053 options->user_hostfiles[options->num_user_hostfiles++] =
2054 xstrdup(_PATH_SSH_USER_HOSTFILE2);
2056 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2057 options->log_level = SYSLOG_LEVEL_INFO;
2058 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2059 options->log_facility = SYSLOG_FACILITY_USER;
2060 if (options->no_host_authentication_for_localhost == - 1)
2061 options->no_host_authentication_for_localhost = 0;
2062 if (options->identities_only == -1)
2063 options->identities_only = 0;
2064 if (options->enable_ssh_keysign == -1)
2065 options->enable_ssh_keysign = 0;
2066 if (options->rekey_limit == -1)
2067 options->rekey_limit = 0;
2068 if (options->rekey_interval == -1)
2069 options->rekey_interval = 0;
2070 if (options->verify_host_key_dns == -1)
2071 options->verify_host_key_dns = 0;
2072 if (options->server_alive_interval == -1)
2073 options->server_alive_interval = 0;
2074 if (options->server_alive_count_max == -1)
2075 options->server_alive_count_max = 3;
2076 if (options->control_master == -1)
2077 options->control_master = 0;
2078 if (options->control_persist == -1) {
2079 options->control_persist = 0;
2080 options->control_persist_timeout = 0;
2082 if (options->hash_known_hosts == -1)
2083 options->hash_known_hosts = 0;
2084 if (options->tun_open == -1)
2085 options->tun_open = SSH_TUNMODE_NO;
2086 if (options->tun_local == -1)
2087 options->tun_local = SSH_TUNID_ANY;
2088 if (options->tun_remote == -1)
2089 options->tun_remote = SSH_TUNID_ANY;
2090 if (options->permit_local_command == -1)
2091 options->permit_local_command = 0;
2092 if (options->visual_host_key == -1)
2093 options->visual_host_key = 0;
2094 if (options->ip_qos_interactive == -1)
2095 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2096 if (options->ip_qos_bulk == -1)
2097 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2098 if (options->request_tty == -1)
2099 options->request_tty = REQUEST_TTY_AUTO;
2100 if (options->proxy_use_fdpass == -1)
2101 options->proxy_use_fdpass = 0;
2102 if (options->canonicalize_max_dots == -1)
2103 options->canonicalize_max_dots = 1;
2104 if (options->canonicalize_fallback_local == -1)
2105 options->canonicalize_fallback_local = 1;
2106 if (options->canonicalize_hostname == -1)
2107 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2108 if (options->fingerprint_hash == -1)
2109 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2110 if (options->update_hostkeys == -1)
2111 options->update_hostkeys = 0;
2113 /* Expand KEX name lists */
2114 all_cipher = cipher_alg_list(',', 0);
2115 all_mac = mac_alg_list(',');
2116 all_kex = kex_alg_list(',');
2117 all_key = sshkey_alg_list(0, 0, 1, ',');
2118 all_sig = sshkey_alg_list(0, 1, 1, ',');
2119 #define ASSEMBLE(what, defaults, all) \
2121 if ((r = kex_assemble_names(&options->what, \
2122 defaults, all)) != 0) \
2123 fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
2125 ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all_cipher);
2126 ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac);
2127 ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex);
2128 ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
2129 ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
2130 ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
2138 #define CLEAR_ON_NONE(v) \
2140 if (option_clear_or_none(v)) { \
2145 CLEAR_ON_NONE(options->local_command);
2146 CLEAR_ON_NONE(options->remote_command);
2147 CLEAR_ON_NONE(options->proxy_command);
2148 CLEAR_ON_NONE(options->control_path);
2149 CLEAR_ON_NONE(options->revoked_host_keys);
2150 CLEAR_ON_NONE(options->pkcs11_provider);
2151 if (options->jump_host != NULL &&
2152 strcmp(options->jump_host, "none") == 0 &&
2153 options->jump_port == 0 && options->jump_user == NULL) {
2154 free(options->jump_host);
2155 options->jump_host = NULL;
2157 /* options->identity_agent distinguishes NULL from 'none' */
2158 /* options->user will be set in the main program if appropriate */
2159 /* options->hostname will be set in the main program if appropriate */
2160 /* options->host_key_alias should not be set by default */
2161 /* options->preferred_authentications will be set in ssh */
2171 * parses the next field in a port forwarding specification.
2172 * sets fwd to the parsed field and advances p past the colon
2173 * or sets it to NULL at end of string.
2174 * returns 0 on success, else non-zero.
2177 parse_fwd_field(char **p, struct fwdarg *fwd)
2184 return -1; /* end of string */
2188 * A field escaped with square brackets is used literally.
2189 * XXX - allow ']' to be escaped via backslash?
2192 /* find matching ']' */
2193 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2197 /* no matching ']' or not at end of field. */
2198 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2200 /* NUL terminate the field and advance p past the colon */
2205 fwd->ispath = ispath;
2210 for (cp = *p; *cp != '\0'; cp++) {
2213 memmove(cp, cp + 1, strlen(cp + 1) + 1);
2227 fwd->ispath = ispath;
2234 * parses a string containing a port forwarding specification of the form:
2236 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2237 * listenpath:connectpath
2239 * [listenhost:]listenport
2240 * returns number of arguments parsed or zero on error
2243 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2245 struct fwdarg fwdargs[4];
2249 memset(fwd, 0, sizeof(*fwd));
2250 memset(fwdargs, 0, sizeof(fwdargs));
2252 cp = p = xstrdup(fwdspec);
2254 /* skip leading spaces */
2255 while (isspace((u_char)*cp))
2258 for (i = 0; i < 4; ++i) {
2259 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2263 /* Check for trailing garbage */
2264 if (cp != NULL && *cp != '\0') {
2265 i = 0; /* failure */
2270 if (fwdargs[0].ispath) {
2271 fwd->listen_path = xstrdup(fwdargs[0].arg);
2272 fwd->listen_port = PORT_STREAMLOCAL;
2274 fwd->listen_host = NULL;
2275 fwd->listen_port = a2port(fwdargs[0].arg);
2277 fwd->connect_host = xstrdup("socks");
2281 if (fwdargs[0].ispath && fwdargs[1].ispath) {
2282 fwd->listen_path = xstrdup(fwdargs[0].arg);
2283 fwd->listen_port = PORT_STREAMLOCAL;
2284 fwd->connect_path = xstrdup(fwdargs[1].arg);
2285 fwd->connect_port = PORT_STREAMLOCAL;
2286 } else if (fwdargs[1].ispath) {
2287 fwd->listen_host = NULL;
2288 fwd->listen_port = a2port(fwdargs[0].arg);
2289 fwd->connect_path = xstrdup(fwdargs[1].arg);
2290 fwd->connect_port = PORT_STREAMLOCAL;
2292 fwd->listen_host = xstrdup(fwdargs[0].arg);
2293 fwd->listen_port = a2port(fwdargs[1].arg);
2294 fwd->connect_host = xstrdup("socks");
2299 if (fwdargs[0].ispath) {
2300 fwd->listen_path = xstrdup(fwdargs[0].arg);
2301 fwd->listen_port = PORT_STREAMLOCAL;
2302 fwd->connect_host = xstrdup(fwdargs[1].arg);
2303 fwd->connect_port = a2port(fwdargs[2].arg);
2304 } else if (fwdargs[2].ispath) {
2305 fwd->listen_host = xstrdup(fwdargs[0].arg);
2306 fwd->listen_port = a2port(fwdargs[1].arg);
2307 fwd->connect_path = xstrdup(fwdargs[2].arg);
2308 fwd->connect_port = PORT_STREAMLOCAL;
2310 fwd->listen_host = NULL;
2311 fwd->listen_port = a2port(fwdargs[0].arg);
2312 fwd->connect_host = xstrdup(fwdargs[1].arg);
2313 fwd->connect_port = a2port(fwdargs[2].arg);
2318 fwd->listen_host = xstrdup(fwdargs[0].arg);
2319 fwd->listen_port = a2port(fwdargs[1].arg);
2320 fwd->connect_host = xstrdup(fwdargs[2].arg);
2321 fwd->connect_port = a2port(fwdargs[3].arg);
2324 i = 0; /* failure */
2330 if (!(i == 1 || i == 2))
2333 if (!(i == 3 || i == 4)) {
2334 if (fwd->connect_path == NULL &&
2335 fwd->listen_path == NULL)
2338 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2342 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2343 (!remotefwd && fwd->listen_port == 0))
2345 if (fwd->connect_host != NULL &&
2346 strlen(fwd->connect_host) >= NI_MAXHOST)
2348 /* XXX - if connecting to a remote socket, max sun len may not match this host */
2349 if (fwd->connect_path != NULL &&
2350 strlen(fwd->connect_path) >= PATH_MAX_SUN)
2352 if (fwd->listen_host != NULL &&
2353 strlen(fwd->listen_host) >= NI_MAXHOST)
2355 if (fwd->listen_path != NULL &&
2356 strlen(fwd->listen_path) >= PATH_MAX_SUN)
2362 free(fwd->connect_host);
2363 fwd->connect_host = NULL;
2364 free(fwd->connect_path);
2365 fwd->connect_path = NULL;
2366 free(fwd->listen_host);
2367 fwd->listen_host = NULL;
2368 free(fwd->listen_path);
2369 fwd->listen_path = NULL;
2374 parse_jump(const char *s, Options *o, int active)
2376 char *orig, *sdup, *cp;
2377 char *host = NULL, *user = NULL;
2378 int ret = -1, port = -1, first;
2380 active &= o->proxy_command == NULL && o->jump_host == NULL;
2382 orig = sdup = xstrdup(s);
2385 if (strcasecmp(s, "none") == 0)
2387 if ((cp = strrchr(sdup, ',')) == NULL)
2388 cp = sdup; /* last */
2393 /* First argument and configuration is active */
2394 if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
2395 parse_user_host_port(cp, &user, &host, &port) != 0)
2398 /* Subsequent argument or inactive configuration */
2399 if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
2400 parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2403 first = 0; /* only check syntax for subsequent hosts */
2404 } while (cp != sdup);
2407 if (strcasecmp(s, "none") == 0) {
2408 o->jump_host = xstrdup("none");
2411 o->jump_user = user;
2412 o->jump_host = host;
2413 o->jump_port = port;
2414 o->proxy_command = xstrdup("none");
2416 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2417 o->jump_extra = xstrdup(s);
2418 o->jump_extra[cp - s] = '\0';
2431 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
2436 r = parse_uri("ssh", uri, userp, hostp, portp, &path);
2437 if (r == 0 && path != NULL)
2438 r = -1; /* path not allowed */
2442 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2444 fmt_multistate_int(int val, const struct multistate *m)
2448 for (i = 0; m[i].key != NULL; i++) {
2449 if (m[i].value == val)
2456 fmt_intarg(OpCodes code, int val)
2461 case oAddressFamily:
2462 return fmt_multistate_int(val, multistate_addressfamily);
2463 case oVerifyHostKeyDNS:
2464 case oUpdateHostkeys:
2465 return fmt_multistate_int(val, multistate_yesnoask);
2466 case oStrictHostKeyChecking:
2467 return fmt_multistate_int(val, multistate_strict_hostkey);
2468 case oControlMaster:
2469 return fmt_multistate_int(val, multistate_controlmaster);
2471 return fmt_multistate_int(val, multistate_tunnel);
2473 return fmt_multistate_int(val, multistate_requesttty);
2474 case oCanonicalizeHostname:
2475 return fmt_multistate_int(val, multistate_canonicalizehostname);
2476 case oAddKeysToAgent:
2477 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
2478 case oFingerprintHash:
2479 return ssh_digest_alg_name(val);
2493 lookup_opcode_name(OpCodes code)
2497 for (i = 0; keywords[i].name != NULL; i++)
2498 if (keywords[i].opcode == code)
2499 return(keywords[i].name);
2504 dump_cfg_int(OpCodes code, int val)
2506 printf("%s %d\n", lookup_opcode_name(code), val);
2510 dump_cfg_fmtint(OpCodes code, int val)
2512 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2516 dump_cfg_string(OpCodes code, const char *val)
2520 printf("%s %s\n", lookup_opcode_name(code), val);
2524 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2528 for (i = 0; i < count; i++)
2529 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2533 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2537 printf("%s", lookup_opcode_name(code));
2538 for (i = 0; i < count; i++)
2539 printf(" %s", vals[i]);
2544 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2546 const struct Forward *fwd;
2549 /* oDynamicForward */
2550 for (i = 0; i < count; i++) {
2552 if (code == oDynamicForward && fwd->connect_host != NULL &&
2553 strcmp(fwd->connect_host, "socks") != 0)
2555 if (code == oLocalForward && fwd->connect_host != NULL &&
2556 strcmp(fwd->connect_host, "socks") == 0)
2558 printf("%s", lookup_opcode_name(code));
2559 if (fwd->listen_port == PORT_STREAMLOCAL)
2560 printf(" %s", fwd->listen_path);
2561 else if (fwd->listen_host == NULL)
2562 printf(" %d", fwd->listen_port);
2565 fwd->listen_host, fwd->listen_port);
2567 if (code != oDynamicForward) {
2568 if (fwd->connect_port == PORT_STREAMLOCAL)
2569 printf(" %s", fwd->connect_path);
2570 else if (fwd->connect_host == NULL)
2571 printf(" %d", fwd->connect_port);
2574 fwd->connect_host, fwd->connect_port);
2582 dump_client_config(Options *o, const char *host)
2585 char buf[8], *all_key;
2587 /* This is normally prepared in ssh_kex2 */
2588 all_key = sshkey_alg_list(0, 0, 1, ',');
2589 if (kex_assemble_names( &o->hostkeyalgorithms,
2590 KEX_DEFAULT_PK_ALG, all_key) != 0)
2591 fatal("%s: kex_assemble_names failed", __func__);
2594 /* Most interesting options first: user, host, port */
2595 dump_cfg_string(oUser, o->user);
2596 dump_cfg_string(oHostName, host);
2597 dump_cfg_int(oPort, o->port);
2600 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
2601 dump_cfg_fmtint(oAddressFamily, o->address_family);
2602 dump_cfg_fmtint(oBatchMode, o->batch_mode);
2603 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2604 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2605 dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2606 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2607 dump_cfg_fmtint(oCompression, o->compression);
2608 dump_cfg_fmtint(oControlMaster, o->control_master);
2609 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2610 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2611 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2612 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2613 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2614 dump_cfg_fmtint(oForwardX11, o->forward_x11);
2615 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2616 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2618 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2619 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2621 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2622 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2623 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2624 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2625 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2626 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2627 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2628 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2629 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2630 dump_cfg_fmtint(oRequestTTY, o->request_tty);
2631 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2632 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2633 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2634 dump_cfg_fmtint(oTunnel, o->tun_open);
2635 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2636 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2637 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2639 /* Integer options */
2640 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2641 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2642 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2643 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2644 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2645 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2647 /* String options */
2648 dump_cfg_string(oBindAddress, o->bind_address);
2649 dump_cfg_string(oBindInterface, o->bind_interface);
2650 dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2651 dump_cfg_string(oControlPath, o->control_path);
2652 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2653 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2654 dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2655 dump_cfg_string(oIdentityAgent, o->identity_agent);
2656 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
2657 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2658 dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2659 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms ? o->ca_sign_algorithms : SSH_ALLOWED_CA_SIGALGS);
2660 dump_cfg_string(oLocalCommand, o->local_command);
2661 dump_cfg_string(oRemoteCommand, o->remote_command);
2662 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2663 dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2664 #ifdef ENABLE_PKCS11
2665 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2667 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2668 dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2669 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2670 dump_cfg_string(oXAuthLocation, o->xauth_location);
2673 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2674 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2675 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2677 /* String array options */
2678 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2679 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2680 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
2681 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2682 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2683 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2684 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
2688 /* oConnectTimeout */
2689 if (o->connection_timeout == -1)
2690 printf("connecttimeout none\n");
2692 dump_cfg_int(oConnectTimeout, o->connection_timeout);
2695 printf("tunneldevice");
2696 if (o->tun_local == SSH_TUNID_ANY)
2699 printf(" %d", o->tun_local);
2700 if (o->tun_remote == SSH_TUNID_ANY)
2703 printf(":%d", o->tun_remote);
2706 /* oCanonicalizePermittedCNAMEs */
2707 if ( o->num_permitted_cnames > 0) {
2708 printf("canonicalizePermittedcnames");
2709 for (i = 0; i < o->num_permitted_cnames; i++) {
2710 printf(" %s:%s", o->permitted_cnames[i].source_list,
2711 o->permitted_cnames[i].target_list);
2716 /* oControlPersist */
2717 if (o->control_persist == 0 || o->control_persist_timeout == 0)
2718 dump_cfg_fmtint(oControlPersist, o->control_persist);
2720 dump_cfg_int(oControlPersist, o->control_persist_timeout);
2723 if (o->escape_char == SSH_ESCAPECHAR_NONE)
2724 printf("escapechar none\n");
2726 vis(buf, o->escape_char, VIS_WHITE, 0);
2727 printf("escapechar %s\n", buf);
2731 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2732 printf("%s\n", iptos2str(o->ip_qos_bulk));
2735 printf("rekeylimit %llu %d\n",
2736 (unsigned long long)o->rekey_limit, o->rekey_interval);
2738 /* oStreamLocalBindMask */
2739 printf("streamlocalbindmask 0%o\n",
2740 o->fwd_opts.streamlocal_bind_mask);
2743 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
2745 /* oProxyCommand / oProxyJump */
2746 if (o->jump_host == NULL)
2747 dump_cfg_string(oProxyCommand, o->proxy_command);
2749 /* Check for numeric addresses */
2750 i = strchr(o->jump_host, ':') != NULL ||
2751 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2752 snprintf(buf, sizeof(buf), "%d", o->jump_port);
2753 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2754 /* optional additional jump spec */
2755 o->jump_extra == NULL ? "" : o->jump_extra,
2756 o->jump_extra == NULL ? "" : ",",
2758 o->jump_user == NULL ? "" : o->jump_user,
2759 o->jump_user == NULL ? "" : "@",
2760 /* opening [ if hostname is numeric */
2762 /* mandatory hostname */
2764 /* closing ] if hostname is numeric */
2766 /* optional port number */
2767 o->jump_port <= 0 ? "" : ":",
2768 o->jump_port <= 0 ? "" : buf);