]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/readconf.c
MFV r337218: 7261 nvlist code should enforce name length limit
[FreeBSD/FreeBSD.git] / crypto / openssh / readconf.c
1 /* $OpenBSD: readconf.c,v 1.283 2018/02/23 15:58:37 markus Exp $ */
2 /*
3  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5  *                    All rights reserved
6  * Functions for reading the configuration files.
7  *
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".
13  */
14
15 #include "includes.h"
16 __RCSID("$FreeBSD$");
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <sys/un.h>
23
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <arpa/inet.h>
28
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #include <netdb.h>
34 #ifdef HAVE_PATHS_H
35 # include <paths.h>
36 #endif
37 #include <pwd.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #ifdef USE_SYSTEM_GLOB
44 # include <glob.h>
45 #else
46 # include "openbsd-compat/glob.h"
47 #endif
48 #ifdef HAVE_UTIL_H
49 #include <util.h>
50 #endif
51 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
52 # include <vis.h>
53 #endif
54
55 #include "xmalloc.h"
56 #include "ssh.h"
57 #include "compat.h"
58 #include "cipher.h"
59 #include "pathnames.h"
60 #include "log.h"
61 #include "sshkey.h"
62 #include "misc.h"
63 #include "readconf.h"
64 #include "match.h"
65 #include "kex.h"
66 #include "mac.h"
67 #include "uidswap.h"
68 #include "myproposal.h"
69 #include "digest.h"
70 #include "version.h"
71
72 /* Format of the configuration file:
73
74    # Configuration data is parsed as follows:
75    #  1. command line options
76    #  2. user-specific file
77    #  3. system-wide file
78    # Any configuration value is only changed the first time it is set.
79    # Thus, host-specific definitions should be at the beginning of the
80    # configuration file, and defaults at the end.
81
82    # Host-specific declarations.  These may override anything above.  A single
83    # host may match multiple declarations; these are processed in the order
84    # that they are given in.
85
86    Host *.ngs.fi ngs.fi
87      User foo
88
89    Host fake.com
90      HostName another.host.name.real.org
91      User blaah
92      Port 34289
93      ForwardX11 no
94      ForwardAgent no
95
96    Host books.com
97      RemoteForward 9999 shadows.cs.hut.fi:9999
98      Ciphers 3des-cbc
99
100    Host fascist.blob.com
101      Port 23123
102      User tylonen
103      PasswordAuthentication no
104
105    Host puukko.hut.fi
106      User t35124p
107      ProxyCommand ssh-proxy %h %p
108
109    Host *.fr
110      PublicKeyAuthentication no
111
112    Host *.su
113      Ciphers aes128-ctr
114      PasswordAuthentication no
115
116    Host vpn.fake.com
117      Tunnel yes
118      TunnelDevice 3
119
120    # Defaults for various options
121    Host *
122      ForwardAgent no
123      ForwardX11 no
124      PasswordAuthentication yes
125      RSAAuthentication yes
126      RhostsRSAAuthentication yes
127      StrictHostKeyChecking yes
128      TcpKeepAlive no
129      IdentityFile ~/.ssh/identity
130      Port 22
131      EscapeChar ~
132
133 */
134
135 static int read_config_file_depth(const char *filename, struct passwd *pw,
136     const char *host, const char *original_host, Options *options,
137     int flags, int *activep, int depth);
138 static int process_config_line_depth(Options *options, struct passwd *pw,
139     const char *host, const char *original_host, char *line,
140     const char *filename, int linenum, int *activep, int flags, int depth);
141
142 /* Keyword tokens. */
143
144 typedef enum {
145         oBadOption,
146         oVersionAddendum,
147         oHost, oMatch, oInclude,
148         oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
149         oGatewayPorts, oExitOnForwardFailure,
150         oPasswordAuthentication, oRSAAuthentication,
151         oChallengeResponseAuthentication, oXAuthLocation,
152         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
153         oCertificateFile, oAddKeysToAgent, oIdentityAgent,
154         oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
155         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
156         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
157         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
158         oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs,
159         oPubkeyAuthentication,
160         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
161         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
162         oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
163         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
164         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
165         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
166         oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
167         oSendEnv, oControlPath, oControlMaster, oControlPersist,
168         oHashKnownHosts,
169         oTunnel, oTunnelDevice,
170         oLocalCommand, oPermitLocalCommand, oRemoteCommand,
171         oVisualHostKey,
172         oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
173         oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
174         oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
175         oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
176         oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
177         oPubkeyAcceptedKeyTypes, oProxyJump,
178         oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
179 } OpCodes;
180
181 /* Textual representations of the tokens. */
182
183 static struct {
184         const char *name;
185         OpCodes opcode;
186 } keywords[] = {
187         /* Deprecated options */
188         { "protocol", oIgnore }, /* NB. silently ignored */
189         { "cipher", oDeprecated },
190         { "fallbacktorsh", oDeprecated },
191         { "globalknownhostsfile2", oDeprecated },
192         { "rhostsauthentication", oDeprecated },
193         { "userknownhostsfile2", oDeprecated },
194         { "useroaming", oDeprecated },
195         { "usersh", oDeprecated },
196
197         /* Unsupported options */
198         { "afstokenpassing", oUnsupported },
199         { "kerberosauthentication", oUnsupported },
200         { "kerberostgtpassing", oUnsupported },
201
202         /* Sometimes-unsupported options */
203 #if defined(GSSAPI)
204         { "gssapiauthentication", oGssAuthentication },
205         { "gssapidelegatecredentials", oGssDelegateCreds },
206 # else
207         { "gssapiauthentication", oUnsupported },
208         { "gssapidelegatecredentials", oUnsupported },
209 #endif
210 #ifdef ENABLE_PKCS11
211         { "smartcarddevice", oPKCS11Provider },
212         { "pkcs11provider", oPKCS11Provider },
213 # else
214         { "smartcarddevice", oUnsupported },
215         { "pkcs11provider", oUnsupported },
216 #endif
217         { "rsaauthentication", oUnsupported },
218         { "rhostsrsaauthentication", oUnsupported },
219         { "compressionlevel", oUnsupported },
220
221         { "forwardagent", oForwardAgent },
222         { "forwardx11", oForwardX11 },
223         { "forwardx11trusted", oForwardX11Trusted },
224         { "forwardx11timeout", oForwardX11Timeout },
225         { "exitonforwardfailure", oExitOnForwardFailure },
226         { "xauthlocation", oXAuthLocation },
227         { "gatewayports", oGatewayPorts },
228         { "useprivilegedport", oUsePrivilegedPort },
229         { "passwordauthentication", oPasswordAuthentication },
230         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
231         { "kbdinteractivedevices", oKbdInteractiveDevices },
232         { "pubkeyauthentication", oPubkeyAuthentication },
233         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
234         { "hostbasedauthentication", oHostbasedAuthentication },
235         { "challengeresponseauthentication", oChallengeResponseAuthentication },
236         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
237         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
238         { "identityfile", oIdentityFile },
239         { "identityfile2", oIdentityFile },                     /* obsolete */
240         { "identitiesonly", oIdentitiesOnly },
241         { "certificatefile", oCertificateFile },
242         { "addkeystoagent", oAddKeysToAgent },
243         { "identityagent", oIdentityAgent },
244         { "hostname", oHostName },
245         { "hostkeyalias", oHostKeyAlias },
246         { "proxycommand", oProxyCommand },
247         { "port", oPort },
248         { "ciphers", oCiphers },
249         { "macs", oMacs },
250         { "remoteforward", oRemoteForward },
251         { "localforward", oLocalForward },
252         { "user", oUser },
253         { "host", oHost },
254         { "match", oMatch },
255         { "escapechar", oEscapeChar },
256         { "globalknownhostsfile", oGlobalKnownHostsFile },
257         { "userknownhostsfile", oUserKnownHostsFile },
258         { "connectionattempts", oConnectionAttempts },
259         { "batchmode", oBatchMode },
260         { "checkhostip", oCheckHostIP },
261         { "stricthostkeychecking", oStrictHostKeyChecking },
262         { "compression", oCompression },
263         { "tcpkeepalive", oTCPKeepAlive },
264         { "keepalive", oTCPKeepAlive },                         /* obsolete */
265         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
266         { "syslogfacility", oLogFacility },
267         { "loglevel", oLogLevel },
268         { "dynamicforward", oDynamicForward },
269         { "preferredauthentications", oPreferredAuthentications },
270         { "hostkeyalgorithms", oHostKeyAlgorithms },
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         { "controlpath", oControlPath },
284         { "controlmaster", oControlMaster },
285         { "controlpersist", oControlPersist },
286         { "hashknownhosts", oHashKnownHosts },
287         { "include", oInclude },
288         { "tunnel", oTunnel },
289         { "tunneldevice", oTunnelDevice },
290         { "localcommand", oLocalCommand },
291         { "permitlocalcommand", oPermitLocalCommand },
292         { "remotecommand", oRemoteCommand },
293         { "visualhostkey", oVisualHostKey },
294         { "kexalgorithms", oKexAlgorithms },
295         { "ipqos", oIPQoS },
296         { "requesttty", oRequestTTY },
297         { "proxyusefdpass", oProxyUseFdpass },
298         { "canonicaldomains", oCanonicalDomains },
299         { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
300         { "canonicalizehostname", oCanonicalizeHostname },
301         { "canonicalizemaxdots", oCanonicalizeMaxDots },
302         { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
303         { "streamlocalbindmask", oStreamLocalBindMask },
304         { "streamlocalbindunlink", oStreamLocalBindUnlink },
305         { "revokedhostkeys", oRevokedHostKeys },
306         { "fingerprinthash", oFingerprintHash },
307         { "updatehostkeys", oUpdateHostkeys },
308         { "hostbasedkeytypes", oHostbasedKeyTypes },
309         { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
310         { "ignoreunknown", oIgnoreUnknown },
311         { "proxyjump", oProxyJump },
312
313         { "hpndisabled", oDeprecated },
314         { "hpnbuffersize", oDeprecated },
315         { "tcprcvbufpoll", oDeprecated },
316         { "tcprcvbuf", oDeprecated },
317         { "noneenabled", oUnsupported },
318         { "noneswitch", oUnsupported },
319         { "versionaddendum", oVersionAddendum },
320
321         { NULL, oBadOption }
322 };
323
324 /*
325  * Adds a local TCP/IP port forward to options.  Never returns if there is an
326  * error.
327  */
328
329 void
330 add_local_forward(Options *options, const struct Forward *newfwd)
331 {
332         struct Forward *fwd;
333         extern uid_t original_real_uid;
334         int i, ipport_reserved;
335
336         if (!bind_permitted(newfwd->listen_port, original_real_uid) &&
337             newfwd->listen_path == NULL)
338                 fatal("Privileged ports can only be forwarded by root.");
339         /* Don't add duplicates */
340         for (i = 0; i < options->num_local_forwards; i++) {
341                 if (forward_equals(newfwd, options->local_forwards + i))
342                         return;
343         }
344         options->local_forwards = xreallocarray(options->local_forwards,
345             options->num_local_forwards + 1,
346             sizeof(*options->local_forwards));
347         fwd = &options->local_forwards[options->num_local_forwards++];
348
349         fwd->listen_host = newfwd->listen_host;
350         fwd->listen_port = newfwd->listen_port;
351         fwd->listen_path = newfwd->listen_path;
352         fwd->connect_host = newfwd->connect_host;
353         fwd->connect_port = newfwd->connect_port;
354         fwd->connect_path = newfwd->connect_path;
355 }
356
357 /*
358  * Adds a remote TCP/IP port forward to options.  Never returns if there is
359  * an error.
360  */
361
362 void
363 add_remote_forward(Options *options, const struct Forward *newfwd)
364 {
365         struct Forward *fwd;
366         int i;
367
368         /* Don't add duplicates */
369         for (i = 0; i < options->num_remote_forwards; i++) {
370                 if (forward_equals(newfwd, options->remote_forwards + i))
371                         return;
372         }
373         options->remote_forwards = xreallocarray(options->remote_forwards,
374             options->num_remote_forwards + 1,
375             sizeof(*options->remote_forwards));
376         fwd = &options->remote_forwards[options->num_remote_forwards++];
377
378         fwd->listen_host = newfwd->listen_host;
379         fwd->listen_port = newfwd->listen_port;
380         fwd->listen_path = newfwd->listen_path;
381         fwd->connect_host = newfwd->connect_host;
382         fwd->connect_port = newfwd->connect_port;
383         fwd->connect_path = newfwd->connect_path;
384         fwd->handle = newfwd->handle;
385         fwd->allocated_port = 0;
386 }
387
388 static void
389 clear_forwardings(Options *options)
390 {
391         int i;
392
393         for (i = 0; i < options->num_local_forwards; i++) {
394                 free(options->local_forwards[i].listen_host);
395                 free(options->local_forwards[i].listen_path);
396                 free(options->local_forwards[i].connect_host);
397                 free(options->local_forwards[i].connect_path);
398         }
399         if (options->num_local_forwards > 0) {
400                 free(options->local_forwards);
401                 options->local_forwards = NULL;
402         }
403         options->num_local_forwards = 0;
404         for (i = 0; i < options->num_remote_forwards; i++) {
405                 free(options->remote_forwards[i].listen_host);
406                 free(options->remote_forwards[i].listen_path);
407                 free(options->remote_forwards[i].connect_host);
408                 free(options->remote_forwards[i].connect_path);
409         }
410         if (options->num_remote_forwards > 0) {
411                 free(options->remote_forwards);
412                 options->remote_forwards = NULL;
413         }
414         options->num_remote_forwards = 0;
415         options->tun_open = SSH_TUNMODE_NO;
416 }
417
418 void
419 add_certificate_file(Options *options, const char *path, int userprovided)
420 {
421         int i;
422
423         if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
424                 fatal("Too many certificate files specified (max %d)",
425                     SSH_MAX_CERTIFICATE_FILES);
426
427         /* Avoid registering duplicates */
428         for (i = 0; i < options->num_certificate_files; i++) {
429                 if (options->certificate_file_userprovided[i] == userprovided &&
430                     strcmp(options->certificate_files[i], path) == 0) {
431                         debug2("%s: ignoring duplicate key %s", __func__, path);
432                         return;
433                 }
434         }
435
436         options->certificate_file_userprovided[options->num_certificate_files] =
437             userprovided;
438         options->certificate_files[options->num_certificate_files++] =
439             xstrdup(path);
440 }
441
442 void
443 add_identity_file(Options *options, const char *dir, const char *filename,
444     int userprovided)
445 {
446         char *path;
447         int i;
448
449         if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
450                 fatal("Too many identity files specified (max %d)",
451                     SSH_MAX_IDENTITY_FILES);
452
453         if (dir == NULL) /* no dir, filename is absolute */
454                 path = xstrdup(filename);
455         else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
456                 fatal("Identity file path %s too long", path);
457
458         /* Avoid registering duplicates */
459         for (i = 0; i < options->num_identity_files; i++) {
460                 if (options->identity_file_userprovided[i] == userprovided &&
461                     strcmp(options->identity_files[i], path) == 0) {
462                         debug2("%s: ignoring duplicate key %s", __func__, path);
463                         free(path);
464                         return;
465                 }
466         }
467
468         options->identity_file_userprovided[options->num_identity_files] =
469             userprovided;
470         options->identity_files[options->num_identity_files++] = path;
471 }
472
473 int
474 default_ssh_port(void)
475 {
476         static int port;
477         struct servent *sp;
478
479         if (port == 0) {
480                 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
481                 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
482         }
483         return port;
484 }
485
486 /*
487  * Execute a command in a shell.
488  * Return its exit status or -1 on abnormal exit.
489  */
490 static int
491 execute_in_shell(const char *cmd)
492 {
493         char *shell;
494         pid_t pid;
495         int devnull, status;
496         extern uid_t original_real_uid;
497
498         if ((shell = getenv("SHELL")) == NULL)
499                 shell = _PATH_BSHELL;
500
501         /* Need this to redirect subprocess stdin/out */
502         if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
503                 fatal("open(/dev/null): %s", strerror(errno));
504
505         debug("Executing command: '%.500s'", cmd);
506
507         /* Fork and execute the command. */
508         if ((pid = fork()) == 0) {
509                 char *argv[4];
510
511                 /* Child.  Permanently give up superuser privileges. */
512                 permanently_drop_suid(original_real_uid);
513
514                 /* Redirect child stdin and stdout. Leave stderr */
515                 if (dup2(devnull, STDIN_FILENO) == -1)
516                         fatal("dup2: %s", strerror(errno));
517                 if (dup2(devnull, STDOUT_FILENO) == -1)
518                         fatal("dup2: %s", strerror(errno));
519                 if (devnull > STDERR_FILENO)
520                         close(devnull);
521                 closefrom(STDERR_FILENO + 1);
522
523                 argv[0] = shell;
524                 argv[1] = "-c";
525                 argv[2] = xstrdup(cmd);
526                 argv[3] = NULL;
527
528                 execv(argv[0], argv);
529                 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
530                 /* Die with signal to make this error apparent to parent. */
531                 signal(SIGTERM, SIG_DFL);
532                 kill(getpid(), SIGTERM);
533                 _exit(1);
534         }
535         /* Parent. */
536         if (pid < 0)
537                 fatal("%s: fork: %.100s", __func__, strerror(errno));
538
539         close(devnull);
540
541         while (waitpid(pid, &status, 0) == -1) {
542                 if (errno != EINTR && errno != EAGAIN)
543                         fatal("%s: waitpid: %s", __func__, strerror(errno));
544         }
545         if (!WIFEXITED(status)) {
546                 error("command '%.100s' exited abnormally", cmd);
547                 return -1;
548         }
549         debug3("command returned status %d", WEXITSTATUS(status));
550         return WEXITSTATUS(status);
551 }
552
553 /*
554  * Parse and execute a Match directive.
555  */
556 static int
557 match_cfg_line(Options *options, char **condition, struct passwd *pw,
558     const char *host_arg, const char *original_host, int post_canon,
559     const char *filename, int linenum)
560 {
561         char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
562         const char *ruser;
563         int r, port, this_result, result = 1, attributes = 0, negate;
564         char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
565
566         /*
567          * Configuration is likely to be incomplete at this point so we
568          * must be prepared to use default values.
569          */
570         port = options->port <= 0 ? default_ssh_port() : options->port;
571         ruser = options->user == NULL ? pw->pw_name : options->user;
572         if (post_canon) {
573                 host = xstrdup(options->hostname);
574         } else if (options->hostname != NULL) {
575                 /* NB. Please keep in sync with ssh.c:main() */
576                 host = percent_expand(options->hostname,
577                     "h", host_arg, (char *)NULL);
578         } else {
579                 host = xstrdup(host_arg);
580         }
581
582         debug2("checking match for '%s' host %s originally %s",
583             cp, host, original_host);
584         while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
585                 criteria = NULL;
586                 this_result = 1;
587                 if ((negate = attrib[0] == '!'))
588                         attrib++;
589                 /* criteria "all" and "canonical" have no argument */
590                 if (strcasecmp(attrib, "all") == 0) {
591                         if (attributes > 1 ||
592                             ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
593                                 error("%.200s line %d: '%s' cannot be combined "
594                                     "with other Match attributes",
595                                     filename, linenum, oattrib);
596                                 result = -1;
597                                 goto out;
598                         }
599                         if (result)
600                                 result = negate ? 0 : 1;
601                         goto out;
602                 }
603                 attributes++;
604                 if (strcasecmp(attrib, "canonical") == 0) {
605                         r = !!post_canon;  /* force bitmask member to boolean */
606                         if (r == (negate ? 1 : 0))
607                                 this_result = result = 0;
608                         debug3("%.200s line %d: %smatched '%s'",
609                             filename, linenum,
610                             this_result ? "" : "not ", oattrib);
611                         continue;
612                 }
613                 /* All other criteria require an argument */
614                 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
615                         error("Missing Match criteria for %s", attrib);
616                         result = -1;
617                         goto out;
618                 }
619                 if (strcasecmp(attrib, "host") == 0) {
620                         criteria = xstrdup(host);
621                         r = match_hostname(host, arg) == 1;
622                         if (r == (negate ? 1 : 0))
623                                 this_result = result = 0;
624                 } else if (strcasecmp(attrib, "originalhost") == 0) {
625                         criteria = xstrdup(original_host);
626                         r = match_hostname(original_host, arg) == 1;
627                         if (r == (negate ? 1 : 0))
628                                 this_result = result = 0;
629                 } else if (strcasecmp(attrib, "user") == 0) {
630                         criteria = xstrdup(ruser);
631                         r = match_pattern_list(ruser, arg, 0) == 1;
632                         if (r == (negate ? 1 : 0))
633                                 this_result = result = 0;
634                 } else if (strcasecmp(attrib, "localuser") == 0) {
635                         criteria = xstrdup(pw->pw_name);
636                         r = match_pattern_list(pw->pw_name, arg, 0) == 1;
637                         if (r == (negate ? 1 : 0))
638                                 this_result = result = 0;
639                 } else if (strcasecmp(attrib, "exec") == 0) {
640                         if (gethostname(thishost, sizeof(thishost)) == -1)
641                                 fatal("gethostname: %s", strerror(errno));
642                         strlcpy(shorthost, thishost, sizeof(shorthost));
643                         shorthost[strcspn(thishost, ".")] = '\0';
644                         snprintf(portstr, sizeof(portstr), "%d", port);
645
646                         cmd = percent_expand(arg,
647                             "L", shorthost,
648                             "d", pw->pw_dir,
649                             "h", host,
650                             "l", thishost,
651                             "n", original_host,
652                             "p", portstr,
653                             "r", ruser,
654                             "u", pw->pw_name,
655                             (char *)NULL);
656                         if (result != 1) {
657                                 /* skip execution if prior predicate failed */
658                                 debug3("%.200s line %d: skipped exec "
659                                     "\"%.100s\"", filename, linenum, cmd);
660                                 free(cmd);
661                                 continue;
662                         }
663                         r = execute_in_shell(cmd);
664                         if (r == -1) {
665                                 fatal("%.200s line %d: match exec "
666                                     "'%.100s' error", filename,
667                                     linenum, cmd);
668                         }
669                         criteria = xstrdup(cmd);
670                         free(cmd);
671                         /* Force exit status to boolean */
672                         r = r == 0;
673                         if (r == (negate ? 1 : 0))
674                                 this_result = result = 0;
675                 } else {
676                         error("Unsupported Match attribute %s", attrib);
677                         result = -1;
678                         goto out;
679                 }
680                 debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
681                     filename, linenum, this_result ? "": "not ",
682                     oattrib, criteria);
683                 free(criteria);
684         }
685         if (attributes == 0) {
686                 error("One or more attributes required for Match");
687                 result = -1;
688                 goto out;
689         }
690  out:
691         if (result != -1)
692                 debug2("match %sfound", result ? "" : "not ");
693         *condition = cp;
694         free(host);
695         return result;
696 }
697
698 /*
699  * Returns the number of the token pointed to by cp or oBadOption.
700  */
701 static OpCodes
702 parse_token(const char *cp, const char *filename, int linenum,
703     const char *ignored_unknown)
704 {
705         int i;
706
707         for (i = 0; keywords[i].name; i++)
708                 if (strcmp(cp, keywords[i].name) == 0)
709                         return keywords[i].opcode;
710         if (ignored_unknown != NULL &&
711             match_pattern_list(cp, ignored_unknown, 1) == 1)
712                 return oIgnoredUnknownOption;
713         error("%s: line %d: Bad configuration option: %s",
714             filename, linenum, cp);
715         return oBadOption;
716 }
717
718 /* Multistate option parsing */
719 struct multistate {
720         char *key;
721         int value;
722 };
723 static const struct multistate multistate_flag[] = {
724         { "true",                       1 },
725         { "false",                      0 },
726         { "yes",                        1 },
727         { "no",                         0 },
728         { NULL, -1 }
729 };
730 static const struct multistate multistate_yesnoask[] = {
731         { "true",                       1 },
732         { "false",                      0 },
733         { "yes",                        1 },
734         { "no",                         0 },
735         { "ask",                        2 },
736         { NULL, -1 }
737 };
738 static const struct multistate multistate_strict_hostkey[] = {
739         { "true",                       SSH_STRICT_HOSTKEY_YES },
740         { "false",                      SSH_STRICT_HOSTKEY_OFF },
741         { "yes",                        SSH_STRICT_HOSTKEY_YES },
742         { "no",                         SSH_STRICT_HOSTKEY_OFF },
743         { "ask",                        SSH_STRICT_HOSTKEY_ASK },
744         { "off",                        SSH_STRICT_HOSTKEY_OFF },
745         { "accept-new",                 SSH_STRICT_HOSTKEY_NEW },
746         { NULL, -1 }
747 };
748 static const struct multistate multistate_yesnoaskconfirm[] = {
749         { "true",                       1 },
750         { "false",                      0 },
751         { "yes",                        1 },
752         { "no",                         0 },
753         { "ask",                        2 },
754         { "confirm",                    3 },
755         { NULL, -1 }
756 };
757 static const struct multistate multistate_addressfamily[] = {
758         { "inet",                       AF_INET },
759         { "inet6",                      AF_INET6 },
760         { "any",                        AF_UNSPEC },
761         { NULL, -1 }
762 };
763 static const struct multistate multistate_controlmaster[] = {
764         { "true",                       SSHCTL_MASTER_YES },
765         { "yes",                        SSHCTL_MASTER_YES },
766         { "false",                      SSHCTL_MASTER_NO },
767         { "no",                         SSHCTL_MASTER_NO },
768         { "auto",                       SSHCTL_MASTER_AUTO },
769         { "ask",                        SSHCTL_MASTER_ASK },
770         { "autoask",                    SSHCTL_MASTER_AUTO_ASK },
771         { NULL, -1 }
772 };
773 static const struct multistate multistate_tunnel[] = {
774         { "ethernet",                   SSH_TUNMODE_ETHERNET },
775         { "point-to-point",             SSH_TUNMODE_POINTOPOINT },
776         { "true",                       SSH_TUNMODE_DEFAULT },
777         { "yes",                        SSH_TUNMODE_DEFAULT },
778         { "false",                      SSH_TUNMODE_NO },
779         { "no",                         SSH_TUNMODE_NO },
780         { NULL, -1 }
781 };
782 static const struct multistate multistate_requesttty[] = {
783         { "true",                       REQUEST_TTY_YES },
784         { "yes",                        REQUEST_TTY_YES },
785         { "false",                      REQUEST_TTY_NO },
786         { "no",                         REQUEST_TTY_NO },
787         { "force",                      REQUEST_TTY_FORCE },
788         { "auto",                       REQUEST_TTY_AUTO },
789         { NULL, -1 }
790 };
791 static const struct multistate multistate_canonicalizehostname[] = {
792         { "true",                       SSH_CANONICALISE_YES },
793         { "false",                      SSH_CANONICALISE_NO },
794         { "yes",                        SSH_CANONICALISE_YES },
795         { "no",                         SSH_CANONICALISE_NO },
796         { "always",                     SSH_CANONICALISE_ALWAYS },
797         { NULL, -1 }
798 };
799
800 /*
801  * Processes a single option line as used in the configuration files. This
802  * only sets those values that have not already been set.
803  */
804 int
805 process_config_line(Options *options, struct passwd *pw, const char *host,
806     const char *original_host, char *line, const char *filename,
807     int linenum, int *activep, int flags)
808 {
809         return process_config_line_depth(options, pw, host, original_host,
810             line, filename, linenum, activep, flags, 0);
811 }
812
813 #define WHITESPACE " \t\r\n"
814 static int
815 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
816     const char *original_host, char *line, const char *filename,
817     int linenum, int *activep, int flags, int depth)
818 {
819         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
820         char **cpptr, fwdarg[256];
821         u_int i, *uintptr, max_entries = 0;
822         int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
823         int remotefwd, dynamicfwd;
824         LogLevel *log_level_ptr;
825         SyslogFacility *log_facility_ptr;
826         long long val64;
827         size_t len;
828         struct Forward fwd;
829         const struct multistate *multistate_ptr;
830         struct allowed_cname *cname;
831         glob_t gl;
832         const char *errstr;
833
834         if (activep == NULL) { /* We are processing a command line directive */
835                 cmdline = 1;
836                 activep = &cmdline;
837         }
838
839         /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
840         if ((len = strlen(line)) == 0)
841                 return 0;
842         for (len--; len > 0; len--) {
843                 if (strchr(WHITESPACE "\f", line[len]) == NULL)
844                         break;
845                 line[len] = '\0';
846         }
847
848         s = line;
849         /* Get the keyword. (Each line is supposed to begin with a keyword). */
850         if ((keyword = strdelim(&s)) == NULL)
851                 return 0;
852         /* Ignore leading whitespace. */
853         if (*keyword == '\0')
854                 keyword = strdelim(&s);
855         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
856                 return 0;
857         /* Match lowercase keyword */
858         lowercase(keyword);
859
860         opcode = parse_token(keyword, filename, linenum,
861             options->ignored_unknown);
862
863         switch (opcode) {
864         case oBadOption:
865                 /* don't panic, but count bad options */
866                 return -1;
867         case oIgnore:
868                 return 0;
869         case oIgnoredUnknownOption:
870                 debug("%s line %d: Ignored unknown option \"%s\"",
871                     filename, linenum, keyword);
872                 return 0;
873         case oConnectTimeout:
874                 intptr = &options->connection_timeout;
875 parse_time:
876                 arg = strdelim(&s);
877                 if (!arg || *arg == '\0')
878                         fatal("%s line %d: missing time value.",
879                             filename, linenum);
880                 if (strcmp(arg, "none") == 0)
881                         value = -1;
882                 else if ((value = convtime(arg)) == -1)
883                         fatal("%s line %d: invalid time value.",
884                             filename, linenum);
885                 if (*activep && *intptr == -1)
886                         *intptr = value;
887                 break;
888
889         case oForwardAgent:
890                 intptr = &options->forward_agent;
891  parse_flag:
892                 multistate_ptr = multistate_flag;
893  parse_multistate:
894                 arg = strdelim(&s);
895                 if (!arg || *arg == '\0')
896                         fatal("%s line %d: missing argument.",
897                             filename, linenum);
898                 value = -1;
899                 for (i = 0; multistate_ptr[i].key != NULL; i++) {
900                         if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
901                                 value = multistate_ptr[i].value;
902                                 break;
903                         }
904                 }
905                 if (value == -1)
906                         fatal("%s line %d: unsupported option \"%s\".",
907                             filename, linenum, arg);
908                 if (*activep && *intptr == -1)
909                         *intptr = value;
910                 break;
911
912         case oForwardX11:
913                 intptr = &options->forward_x11;
914                 goto parse_flag;
915
916         case oForwardX11Trusted:
917                 intptr = &options->forward_x11_trusted;
918                 goto parse_flag;
919
920         case oForwardX11Timeout:
921                 intptr = &options->forward_x11_timeout;
922                 goto parse_time;
923
924         case oGatewayPorts:
925                 intptr = &options->fwd_opts.gateway_ports;
926                 goto parse_flag;
927
928         case oExitOnForwardFailure:
929                 intptr = &options->exit_on_forward_failure;
930                 goto parse_flag;
931
932         case oUsePrivilegedPort:
933                 intptr = &options->use_privileged_port;
934                 goto parse_flag;
935
936         case oPasswordAuthentication:
937                 intptr = &options->password_authentication;
938                 goto parse_flag;
939
940         case oKbdInteractiveAuthentication:
941                 intptr = &options->kbd_interactive_authentication;
942                 goto parse_flag;
943
944         case oKbdInteractiveDevices:
945                 charptr = &options->kbd_interactive_devices;
946                 goto parse_string;
947
948         case oPubkeyAuthentication:
949                 intptr = &options->pubkey_authentication;
950                 goto parse_flag;
951
952         case oHostbasedAuthentication:
953                 intptr = &options->hostbased_authentication;
954                 goto parse_flag;
955
956         case oChallengeResponseAuthentication:
957                 intptr = &options->challenge_response_authentication;
958                 goto parse_flag;
959
960         case oGssAuthentication:
961                 intptr = &options->gss_authentication;
962                 goto parse_flag;
963
964         case oGssDelegateCreds:
965                 intptr = &options->gss_deleg_creds;
966                 goto parse_flag;
967
968         case oBatchMode:
969                 intptr = &options->batch_mode;
970                 goto parse_flag;
971
972         case oCheckHostIP:
973                 intptr = &options->check_host_ip;
974                 goto parse_flag;
975
976         case oVerifyHostKeyDNS:
977                 intptr = &options->verify_host_key_dns;
978                 multistate_ptr = multistate_yesnoask;
979                 goto parse_multistate;
980
981         case oStrictHostKeyChecking:
982                 intptr = &options->strict_host_key_checking;
983                 multistate_ptr = multistate_strict_hostkey;
984                 goto parse_multistate;
985
986         case oCompression:
987                 intptr = &options->compression;
988                 goto parse_flag;
989
990         case oTCPKeepAlive:
991                 intptr = &options->tcp_keep_alive;
992                 goto parse_flag;
993
994         case oNoHostAuthenticationForLocalhost:
995                 intptr = &options->no_host_authentication_for_localhost;
996                 goto parse_flag;
997
998         case oNumberOfPasswordPrompts:
999                 intptr = &options->number_of_password_prompts;
1000                 goto parse_int;
1001
1002         case oRekeyLimit:
1003                 arg = strdelim(&s);
1004                 if (!arg || *arg == '\0')
1005                         fatal("%.200s line %d: Missing argument.", filename,
1006                             linenum);
1007                 if (strcmp(arg, "default") == 0) {
1008                         val64 = 0;
1009                 } else {
1010                         if (scan_scaled(arg, &val64) == -1)
1011                                 fatal("%.200s line %d: Bad number '%s': %s",
1012                                     filename, linenum, arg, strerror(errno));
1013                         if (val64 != 0 && val64 < 16)
1014                                 fatal("%.200s line %d: RekeyLimit too small",
1015                                     filename, linenum);
1016                 }
1017                 if (*activep && options->rekey_limit == -1)
1018                         options->rekey_limit = val64;
1019                 if (s != NULL) { /* optional rekey interval present */
1020                         if (strcmp(s, "none") == 0) {
1021                                 (void)strdelim(&s);     /* discard */
1022                                 break;
1023                         }
1024                         intptr = &options->rekey_interval;
1025                         goto parse_time;
1026                 }
1027                 break;
1028
1029         case oIdentityFile:
1030                 arg = strdelim(&s);
1031                 if (!arg || *arg == '\0')
1032                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1033                 if (*activep) {
1034                         intptr = &options->num_identity_files;
1035                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
1036                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
1037                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
1038                         add_identity_file(options, NULL,
1039                             arg, flags & SSHCONF_USERCONF);
1040                 }
1041                 break;
1042
1043         case oCertificateFile:
1044                 arg = strdelim(&s);
1045                 if (!arg || *arg == '\0')
1046                         fatal("%.200s line %d: Missing argument.",
1047                             filename, linenum);
1048                 if (*activep) {
1049                         intptr = &options->num_certificate_files;
1050                         if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1051                                 fatal("%.200s line %d: Too many certificate "
1052                                     "files specified (max %d).",
1053                                     filename, linenum,
1054                                     SSH_MAX_CERTIFICATE_FILES);
1055                         }
1056                         add_certificate_file(options, arg,
1057                             flags & SSHCONF_USERCONF);
1058                 }
1059                 break;
1060
1061         case oXAuthLocation:
1062                 charptr=&options->xauth_location;
1063                 goto parse_string;
1064
1065         case oUser:
1066                 charptr = &options->user;
1067 parse_string:
1068                 arg = strdelim(&s);
1069                 if (!arg || *arg == '\0')
1070                         fatal("%.200s line %d: Missing argument.",
1071                             filename, linenum);
1072                 if (*activep && *charptr == NULL)
1073                         *charptr = xstrdup(arg);
1074                 break;
1075
1076         case oGlobalKnownHostsFile:
1077                 cpptr = (char **)&options->system_hostfiles;
1078                 uintptr = &options->num_system_hostfiles;
1079                 max_entries = SSH_MAX_HOSTS_FILES;
1080 parse_char_array:
1081                 if (*activep && *uintptr == 0) {
1082                         while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1083                                 if ((*uintptr) >= max_entries)
1084                                         fatal("%s line %d: "
1085                                             "too many authorized keys files.",
1086                                             filename, linenum);
1087                                 cpptr[(*uintptr)++] = xstrdup(arg);
1088                         }
1089                 }
1090                 return 0;
1091
1092         case oUserKnownHostsFile:
1093                 cpptr = (char **)&options->user_hostfiles;
1094                 uintptr = &options->num_user_hostfiles;
1095                 max_entries = SSH_MAX_HOSTS_FILES;
1096                 goto parse_char_array;
1097
1098         case oHostName:
1099                 charptr = &options->hostname;
1100                 goto parse_string;
1101
1102         case oHostKeyAlias:
1103                 charptr = &options->host_key_alias;
1104                 goto parse_string;
1105
1106         case oPreferredAuthentications:
1107                 charptr = &options->preferred_authentications;
1108                 goto parse_string;
1109
1110         case oBindAddress:
1111                 charptr = &options->bind_address;
1112                 goto parse_string;
1113
1114         case oBindInterface:
1115                 charptr = &options->bind_interface;
1116                 goto parse_string;
1117
1118         case oPKCS11Provider:
1119                 charptr = &options->pkcs11_provider;
1120                 goto parse_string;
1121
1122         case oProxyCommand:
1123                 charptr = &options->proxy_command;
1124                 /* Ignore ProxyCommand if ProxyJump already specified */
1125                 if (options->jump_host != NULL)
1126                         charptr = &options->jump_host; /* Skip below */
1127 parse_command:
1128                 if (s == NULL)
1129                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1130                 len = strspn(s, WHITESPACE "=");
1131                 if (*activep && *charptr == NULL)
1132                         *charptr = xstrdup(s + len);
1133                 return 0;
1134
1135         case oProxyJump:
1136                 if (s == NULL) {
1137                         fatal("%.200s line %d: Missing argument.",
1138                             filename, linenum);
1139                 }
1140                 len = strspn(s, WHITESPACE "=");
1141                 if (parse_jump(s + len, options, *activep) == -1) {
1142                         fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
1143                             filename, linenum, s + len);
1144                 }
1145                 return 0;
1146
1147         case oPort:
1148                 intptr = &options->port;
1149 parse_int:
1150                 arg = strdelim(&s);
1151                 if ((errstr = atoi_err(arg, &value)) != NULL)
1152                         fatal("%s line %d: integer value %s.",
1153                             filename, linenum, errstr);
1154                 if (*activep && *intptr == -1)
1155                         *intptr = value;
1156                 break;
1157
1158         case oConnectionAttempts:
1159                 intptr = &options->connection_attempts;
1160                 goto parse_int;
1161
1162         case oCiphers:
1163                 arg = strdelim(&s);
1164                 if (!arg || *arg == '\0')
1165                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1166                 if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
1167                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1168                             filename, linenum, arg ? arg : "<NONE>");
1169                 if (*activep && options->ciphers == NULL)
1170                         options->ciphers = xstrdup(arg);
1171                 break;
1172
1173         case oMacs:
1174                 arg = strdelim(&s);
1175                 if (!arg || *arg == '\0')
1176                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1177                 if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
1178                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1179                             filename, linenum, arg ? arg : "<NONE>");
1180                 if (*activep && options->macs == NULL)
1181                         options->macs = xstrdup(arg);
1182                 break;
1183
1184         case oKexAlgorithms:
1185                 arg = strdelim(&s);
1186                 if (!arg || *arg == '\0')
1187                         fatal("%.200s line %d: Missing argument.",
1188                             filename, linenum);
1189                 if (*arg != '-' &&
1190                     !kex_names_valid(*arg == '+' ? arg + 1 : arg))
1191                         fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1192                             filename, linenum, arg ? arg : "<NONE>");
1193                 if (*activep && options->kex_algorithms == NULL)
1194                         options->kex_algorithms = xstrdup(arg);
1195                 break;
1196
1197         case oHostKeyAlgorithms:
1198                 charptr = &options->hostkeyalgorithms;
1199 parse_keytypes:
1200                 arg = strdelim(&s);
1201                 if (!arg || *arg == '\0')
1202                         fatal("%.200s line %d: Missing argument.",
1203                             filename, linenum);
1204                 if (*arg != '-' &&
1205                     !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1206                         fatal("%s line %d: Bad key types '%s'.",
1207                                 filename, linenum, arg ? arg : "<NONE>");
1208                 if (*activep && *charptr == NULL)
1209                         *charptr = xstrdup(arg);
1210                 break;
1211
1212         case oLogLevel:
1213                 log_level_ptr = &options->log_level;
1214                 arg = strdelim(&s);
1215                 value = log_level_number(arg);
1216                 if (value == SYSLOG_LEVEL_NOT_SET)
1217                         fatal("%.200s line %d: unsupported log level '%s'",
1218                             filename, linenum, arg ? arg : "<NONE>");
1219                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1220                         *log_level_ptr = (LogLevel) value;
1221                 break;
1222
1223         case oLogFacility:
1224                 log_facility_ptr = &options->log_facility;
1225                 arg = strdelim(&s);
1226                 value = log_facility_number(arg);
1227                 if (value == SYSLOG_FACILITY_NOT_SET)
1228                         fatal("%.200s line %d: unsupported log facility '%s'",
1229                             filename, linenum, arg ? arg : "<NONE>");
1230                 if (*log_facility_ptr == -1)
1231                         *log_facility_ptr = (SyslogFacility) value;
1232                 break;
1233
1234         case oLocalForward:
1235         case oRemoteForward:
1236         case oDynamicForward:
1237                 arg = strdelim(&s);
1238                 if (arg == NULL || *arg == '\0')
1239                         fatal("%.200s line %d: Missing port argument.",
1240                             filename, linenum);
1241
1242                 remotefwd = (opcode == oRemoteForward);
1243                 dynamicfwd = (opcode == oDynamicForward);
1244
1245                 if (!dynamicfwd) {
1246                         arg2 = strdelim(&s);
1247                         if (arg2 == NULL || *arg2 == '\0') {
1248                                 if (remotefwd)
1249                                         dynamicfwd = 1;
1250                                 else
1251                                         fatal("%.200s line %d: Missing target "
1252                                             "argument.", filename, linenum);
1253                         } else {
1254                                 /* construct a string for parse_forward */
1255                                 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1256                                     arg2);
1257                         }
1258                 }
1259                 if (dynamicfwd)
1260                         strlcpy(fwdarg, arg, sizeof(fwdarg));
1261
1262                 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1263                         fatal("%.200s line %d: Bad forwarding specification.",
1264                             filename, linenum);
1265
1266                 if (*activep) {
1267                         if (remotefwd) {
1268                                 add_remote_forward(options, &fwd);
1269                         } else {
1270                                 add_local_forward(options, &fwd);
1271                         }
1272                 }
1273                 break;
1274
1275         case oClearAllForwardings:
1276                 intptr = &options->clear_forwardings;
1277                 goto parse_flag;
1278
1279         case oHost:
1280                 if (cmdline)
1281                         fatal("Host directive not supported as a command-line "
1282                             "option");
1283                 *activep = 0;
1284                 arg2 = NULL;
1285                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1286                         if ((flags & SSHCONF_NEVERMATCH) != 0)
1287                                 break;
1288                         negated = *arg == '!';
1289                         if (negated)
1290                                 arg++;
1291                         if (match_pattern(host, arg)) {
1292                                 if (negated) {
1293                                         debug("%.200s line %d: Skipping Host "
1294                                             "block because of negated match "
1295                                             "for %.100s", filename, linenum,
1296                                             arg);
1297                                         *activep = 0;
1298                                         break;
1299                                 }
1300                                 if (!*activep)
1301                                         arg2 = arg; /* logged below */
1302                                 *activep = 1;
1303                         }
1304                 }
1305                 if (*activep)
1306                         debug("%.200s line %d: Applying options for %.100s",
1307                             filename, linenum, arg2);
1308                 /* Avoid garbage check below, as strdelim is done. */
1309                 return 0;
1310
1311         case oMatch:
1312                 if (cmdline)
1313                         fatal("Host directive not supported as a command-line "
1314                             "option");
1315                 value = match_cfg_line(options, &s, pw, host, original_host,
1316                     flags & SSHCONF_POSTCANON, filename, linenum);
1317                 if (value < 0)
1318                         fatal("%.200s line %d: Bad Match condition", filename,
1319                             linenum);
1320                 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1321                 break;
1322
1323         case oEscapeChar:
1324                 intptr = &options->escape_char;
1325                 arg = strdelim(&s);
1326                 if (!arg || *arg == '\0')
1327                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1328                 if (strcmp(arg, "none") == 0)
1329                         value = SSH_ESCAPECHAR_NONE;
1330                 else if (arg[1] == '\0')
1331                         value = (u_char) arg[0];
1332                 else if (arg[0] == '^' && arg[2] == 0 &&
1333                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1334                         value = (u_char) arg[1] & 31;
1335                 else {
1336                         fatal("%.200s line %d: Bad escape character.",
1337                             filename, linenum);
1338                         /* NOTREACHED */
1339                         value = 0;      /* Avoid compiler warning. */
1340                 }
1341                 if (*activep && *intptr == -1)
1342                         *intptr = value;
1343                 break;
1344
1345         case oAddressFamily:
1346                 intptr = &options->address_family;
1347                 multistate_ptr = multistate_addressfamily;
1348                 goto parse_multistate;
1349
1350         case oEnableSSHKeysign:
1351                 intptr = &options->enable_ssh_keysign;
1352                 goto parse_flag;
1353
1354         case oIdentitiesOnly:
1355                 intptr = &options->identities_only;
1356                 goto parse_flag;
1357
1358         case oServerAliveInterval:
1359                 intptr = &options->server_alive_interval;
1360                 goto parse_time;
1361
1362         case oServerAliveCountMax:
1363                 intptr = &options->server_alive_count_max;
1364                 goto parse_int;
1365
1366         case oSendEnv:
1367                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1368                         if (strchr(arg, '=') != NULL)
1369                                 fatal("%s line %d: Invalid environment name.",
1370                                     filename, linenum);
1371                         if (!*activep)
1372                                 continue;
1373                         if (options->num_send_env >= MAX_SEND_ENV)
1374                                 fatal("%s line %d: too many send env.",
1375                                     filename, linenum);
1376                         options->send_env[options->num_send_env++] =
1377                             xstrdup(arg);
1378                 }
1379                 break;
1380
1381         case oControlPath:
1382                 charptr = &options->control_path;
1383                 goto parse_string;
1384
1385         case oControlMaster:
1386                 intptr = &options->control_master;
1387                 multistate_ptr = multistate_controlmaster;
1388                 goto parse_multistate;
1389
1390         case oControlPersist:
1391                 /* no/false/yes/true, or a time spec */
1392                 intptr = &options->control_persist;
1393                 arg = strdelim(&s);
1394                 if (!arg || *arg == '\0')
1395                         fatal("%.200s line %d: Missing ControlPersist"
1396                             " argument.", filename, linenum);
1397                 value = 0;
1398                 value2 = 0;     /* timeout */
1399                 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1400                         value = 0;
1401                 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1402                         value = 1;
1403                 else if ((value2 = convtime(arg)) >= 0)
1404                         value = 1;
1405                 else
1406                         fatal("%.200s line %d: Bad ControlPersist argument.",
1407                             filename, linenum);
1408                 if (*activep && *intptr == -1) {
1409                         *intptr = value;
1410                         options->control_persist_timeout = value2;
1411                 }
1412                 break;
1413
1414         case oHashKnownHosts:
1415                 intptr = &options->hash_known_hosts;
1416                 goto parse_flag;
1417
1418         case oTunnel:
1419                 intptr = &options->tun_open;
1420                 multistate_ptr = multistate_tunnel;
1421                 goto parse_multistate;
1422
1423         case oTunnelDevice:
1424                 arg = strdelim(&s);
1425                 if (!arg || *arg == '\0')
1426                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1427                 value = a2tun(arg, &value2);
1428                 if (value == SSH_TUNID_ERR)
1429                         fatal("%.200s line %d: Bad tun device.", filename, linenum);
1430                 if (*activep) {
1431                         options->tun_local = value;
1432                         options->tun_remote = value2;
1433                 }
1434                 break;
1435
1436         case oLocalCommand:
1437                 charptr = &options->local_command;
1438                 goto parse_command;
1439
1440         case oPermitLocalCommand:
1441                 intptr = &options->permit_local_command;
1442                 goto parse_flag;
1443
1444         case oRemoteCommand:
1445                 charptr = &options->remote_command;
1446                 goto parse_command;
1447
1448         case oVisualHostKey:
1449                 intptr = &options->visual_host_key;
1450                 goto parse_flag;
1451
1452         case oInclude:
1453                 if (cmdline)
1454                         fatal("Include directive not supported as a "
1455                             "command-line option");
1456                 value = 0;
1457                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1458                         /*
1459                          * Ensure all paths are anchored. User configuration
1460                          * files may begin with '~/' but system configurations
1461                          * must not. If the path is relative, then treat it
1462                          * as living in ~/.ssh for user configurations or
1463                          * /etc/ssh for system ones.
1464                          */
1465                         if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
1466                                 fatal("%.200s line %d: bad include path %s.",
1467                                     filename, linenum, arg);
1468                         if (*arg != '/' && *arg != '~') {
1469                                 xasprintf(&arg2, "%s/%s",
1470                                     (flags & SSHCONF_USERCONF) ?
1471                                     "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1472                         } else
1473                                 arg2 = xstrdup(arg);
1474                         memset(&gl, 0, sizeof(gl));
1475                         r = glob(arg2, GLOB_TILDE, NULL, &gl);
1476                         if (r == GLOB_NOMATCH) {
1477                                 debug("%.200s line %d: include %s matched no "
1478                                     "files",filename, linenum, arg2);
1479                                 free(arg2);
1480                                 continue;
1481                         } else if (r != 0 || gl.gl_pathc < 0)
1482                                 fatal("%.200s line %d: glob failed for %s.",
1483                                     filename, linenum, arg2);
1484                         free(arg2);
1485                         oactive = *activep;
1486                         for (i = 0; i < (u_int)gl.gl_pathc; i++) {
1487                                 debug3("%.200s line %d: Including file %s "
1488                                     "depth %d%s", filename, linenum,
1489                                     gl.gl_pathv[i], depth,
1490                                     oactive ? "" : " (parse only)");
1491                                 r = read_config_file_depth(gl.gl_pathv[i],
1492                                     pw, host, original_host, options,
1493                                     flags | SSHCONF_CHECKPERM |
1494                                     (oactive ? 0 : SSHCONF_NEVERMATCH),
1495                                     activep, depth + 1);
1496                                 if (r != 1 && errno != ENOENT) {
1497                                         fatal("Can't open user config file "
1498                                             "%.100s: %.100s", gl.gl_pathv[i],
1499                                             strerror(errno));
1500                                 }
1501                                 /*
1502                                  * don't let Match in includes clobber the
1503                                  * containing file's Match state.
1504                                  */
1505                                 *activep = oactive;
1506                                 if (r != 1)
1507                                         value = -1;
1508                         }
1509                         globfree(&gl);
1510                 }
1511                 if (value != 0)
1512                         return value;
1513                 break;
1514
1515         case oIPQoS:
1516                 arg = strdelim(&s);
1517                 if ((value = parse_ipqos(arg)) == -1)
1518                         fatal("%s line %d: Bad IPQoS value: %s",
1519                             filename, linenum, arg);
1520                 arg = strdelim(&s);
1521                 if (arg == NULL)
1522                         value2 = value;
1523                 else if ((value2 = parse_ipqos(arg)) == -1)
1524                         fatal("%s line %d: Bad IPQoS value: %s",
1525                             filename, linenum, arg);
1526                 if (*activep) {
1527                         options->ip_qos_interactive = value;
1528                         options->ip_qos_bulk = value2;
1529                 }
1530                 break;
1531
1532         case oRequestTTY:
1533                 intptr = &options->request_tty;
1534                 multistate_ptr = multistate_requesttty;
1535                 goto parse_multistate;
1536
1537         case oVersionAddendum:
1538                 if (s == NULL)
1539                         fatal("%.200s line %d: Missing argument.", filename,
1540                             linenum);
1541                 len = strspn(s, WHITESPACE);
1542                 if (*activep && options->version_addendum == NULL) {
1543                         if (strcasecmp(s + len, "none") == 0)
1544                                 options->version_addendum = xstrdup("");
1545                         else if (strchr(s + len, '\r') != NULL)
1546                                 fatal("%.200s line %d: Invalid argument",
1547                                     filename, linenum);
1548                         else
1549                                 options->version_addendum = xstrdup(s + len);
1550                 }
1551                 return 0;
1552
1553         case oIgnoreUnknown:
1554                 charptr = &options->ignored_unknown;
1555                 goto parse_string;
1556
1557         case oProxyUseFdpass:
1558                 intptr = &options->proxy_use_fdpass;
1559                 goto parse_flag;
1560
1561         case oCanonicalDomains:
1562                 value = options->num_canonical_domains != 0;
1563                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1564                         if (!valid_domain(arg, 1, &errstr)) {
1565                                 fatal("%s line %d: %s", filename, linenum,
1566                                     errstr);
1567                         }
1568                         if (!*activep || value)
1569                                 continue;
1570                         if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1571                                 fatal("%s line %d: too many hostname suffixes.",
1572                                     filename, linenum);
1573                         options->canonical_domains[
1574                             options->num_canonical_domains++] = xstrdup(arg);
1575                 }
1576                 break;
1577
1578         case oCanonicalizePermittedCNAMEs:
1579                 value = options->num_permitted_cnames != 0;
1580                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1581                         /* Either '*' for everything or 'list:list' */
1582                         if (strcmp(arg, "*") == 0)
1583                                 arg2 = arg;
1584                         else {
1585                                 lowercase(arg);
1586                                 if ((arg2 = strchr(arg, ':')) == NULL ||
1587                                     arg2[1] == '\0') {
1588                                         fatal("%s line %d: "
1589                                             "Invalid permitted CNAME \"%s\"",
1590                                             filename, linenum, arg);
1591                                 }
1592                                 *arg2 = '\0';
1593                                 arg2++;
1594                         }
1595                         if (!*activep || value)
1596                                 continue;
1597                         if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1598                                 fatal("%s line %d: too many permitted CNAMEs.",
1599                                     filename, linenum);
1600                         cname = options->permitted_cnames +
1601                             options->num_permitted_cnames++;
1602                         cname->source_list = xstrdup(arg);
1603                         cname->target_list = xstrdup(arg2);
1604                 }
1605                 break;
1606
1607         case oCanonicalizeHostname:
1608                 intptr = &options->canonicalize_hostname;
1609                 multistate_ptr = multistate_canonicalizehostname;
1610                 goto parse_multistate;
1611
1612         case oCanonicalizeMaxDots:
1613                 intptr = &options->canonicalize_max_dots;
1614                 goto parse_int;
1615
1616         case oCanonicalizeFallbackLocal:
1617                 intptr = &options->canonicalize_fallback_local;
1618                 goto parse_flag;
1619
1620         case oStreamLocalBindMask:
1621                 arg = strdelim(&s);
1622                 if (!arg || *arg == '\0')
1623                         fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1624                 /* Parse mode in octal format */
1625                 value = strtol(arg, &endofnumber, 8);
1626                 if (arg == endofnumber || value < 0 || value > 0777)
1627                         fatal("%.200s line %d: Bad mask.", filename, linenum);
1628                 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1629                 break;
1630
1631         case oStreamLocalBindUnlink:
1632                 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1633                 goto parse_flag;
1634
1635         case oRevokedHostKeys:
1636                 charptr = &options->revoked_host_keys;
1637                 goto parse_string;
1638
1639         case oFingerprintHash:
1640                 intptr = &options->fingerprint_hash;
1641                 arg = strdelim(&s);
1642                 if (!arg || *arg == '\0')
1643                         fatal("%.200s line %d: Missing argument.",
1644                             filename, linenum);
1645                 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1646                         fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1647                             filename, linenum, arg);
1648                 if (*activep && *intptr == -1)
1649                         *intptr = value;
1650                 break;
1651
1652         case oUpdateHostkeys:
1653                 intptr = &options->update_hostkeys;
1654                 multistate_ptr = multistate_yesnoask;
1655                 goto parse_multistate;
1656
1657         case oHostbasedKeyTypes:
1658                 charptr = &options->hostbased_key_types;
1659                 goto parse_keytypes;
1660
1661         case oPubkeyAcceptedKeyTypes:
1662                 charptr = &options->pubkey_key_types;
1663                 goto parse_keytypes;
1664
1665         case oAddKeysToAgent:
1666                 intptr = &options->add_keys_to_agent;
1667                 multistate_ptr = multistate_yesnoaskconfirm;
1668                 goto parse_multistate;
1669
1670         case oIdentityAgent:
1671                 charptr = &options->identity_agent;
1672                 goto parse_string;
1673
1674         case oDeprecated:
1675                 debug("%s line %d: Deprecated option \"%s\"",
1676                     filename, linenum, keyword);
1677                 return 0;
1678
1679         case oUnsupported:
1680                 error("%s line %d: Unsupported option \"%s\"",
1681                     filename, linenum, keyword);
1682                 return 0;
1683
1684         default:
1685                 fatal("%s: Unimplemented opcode %d", __func__, opcode);
1686         }
1687
1688         /* Check that there is no garbage at end of line. */
1689         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1690                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1691                     filename, linenum, arg);
1692         }
1693         return 0;
1694 }
1695
1696 /*
1697  * Reads the config file and modifies the options accordingly.  Options
1698  * should already be initialized before this call.  This never returns if
1699  * there is an error.  If the file does not exist, this returns 0.
1700  */
1701 int
1702 read_config_file(const char *filename, struct passwd *pw, const char *host,
1703     const char *original_host, Options *options, int flags)
1704 {
1705         int active = 1;
1706
1707         return read_config_file_depth(filename, pw, host, original_host,
1708             options, flags, &active, 0);
1709 }
1710
1711 #define READCONF_MAX_DEPTH      16
1712 static int
1713 read_config_file_depth(const char *filename, struct passwd *pw,
1714     const char *host, const char *original_host, Options *options,
1715     int flags, int *activep, int depth)
1716 {
1717         FILE *f;
1718         char line[4096];
1719         int linenum;
1720         int bad_options = 0;
1721
1722         if (depth < 0 || depth > READCONF_MAX_DEPTH)
1723                 fatal("Too many recursive configuration includes");
1724
1725         if ((f = fopen(filename, "r")) == NULL)
1726                 return 0;
1727
1728         if (flags & SSHCONF_CHECKPERM) {
1729                 struct stat sb;
1730
1731                 if (fstat(fileno(f), &sb) == -1)
1732                         fatal("fstat %s: %s", filename, strerror(errno));
1733                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1734                     (sb.st_mode & 022) != 0))
1735                         fatal("Bad owner or permissions on %s", filename);
1736         }
1737
1738         debug("Reading configuration data %.200s", filename);
1739
1740         /*
1741          * Mark that we are now processing the options.  This flag is turned
1742          * on/off by Host specifications.
1743          */
1744         linenum = 0;
1745         while (fgets(line, sizeof(line), f)) {
1746                 /* Update line number counter. */
1747                 linenum++;
1748                 if (strlen(line) == sizeof(line) - 1)
1749                         fatal("%s line %d too long", filename, linenum);
1750                 if (process_config_line_depth(options, pw, host, original_host,
1751                     line, filename, linenum, activep, flags, depth) != 0)
1752                         bad_options++;
1753         }
1754         fclose(f);
1755         if (bad_options > 0)
1756                 fatal("%s: terminating, %d bad configuration options",
1757                     filename, bad_options);
1758         return 1;
1759 }
1760
1761 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1762 int
1763 option_clear_or_none(const char *o)
1764 {
1765         return o == NULL || strcasecmp(o, "none") == 0;
1766 }
1767
1768 /*
1769  * Initializes options to special values that indicate that they have not yet
1770  * been set.  Read_config_file will only set options with this value. Options
1771  * are processed in the following order: command line, user config file,
1772  * system config file.  Last, fill_default_options is called.
1773  */
1774
1775 void
1776 initialize_options(Options * options)
1777 {
1778         memset(options, 'X', sizeof(*options));
1779         options->version_addendum = NULL;
1780         options->forward_agent = -1;
1781         options->forward_x11 = -1;
1782         options->forward_x11_trusted = -1;
1783         options->forward_x11_timeout = -1;
1784         options->stdio_forward_host = NULL;
1785         options->stdio_forward_port = 0;
1786         options->clear_forwardings = -1;
1787         options->exit_on_forward_failure = -1;
1788         options->xauth_location = NULL;
1789         options->fwd_opts.gateway_ports = -1;
1790         options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1791         options->fwd_opts.streamlocal_bind_unlink = -1;
1792         options->use_privileged_port = -1;
1793         options->pubkey_authentication = -1;
1794         options->challenge_response_authentication = -1;
1795         options->gss_authentication = -1;
1796         options->gss_deleg_creds = -1;
1797         options->password_authentication = -1;
1798         options->kbd_interactive_authentication = -1;
1799         options->kbd_interactive_devices = NULL;
1800         options->hostbased_authentication = -1;
1801         options->batch_mode = -1;
1802         options->check_host_ip = -1;
1803         options->strict_host_key_checking = -1;
1804         options->compression = -1;
1805         options->tcp_keep_alive = -1;
1806         options->port = -1;
1807         options->address_family = -1;
1808         options->connection_attempts = -1;
1809         options->connection_timeout = -1;
1810         options->number_of_password_prompts = -1;
1811         options->ciphers = NULL;
1812         options->macs = NULL;
1813         options->kex_algorithms = NULL;
1814         options->hostkeyalgorithms = NULL;
1815         options->num_identity_files = 0;
1816         options->num_certificate_files = 0;
1817         options->hostname = NULL;
1818         options->host_key_alias = NULL;
1819         options->proxy_command = NULL;
1820         options->jump_user = NULL;
1821         options->jump_host = NULL;
1822         options->jump_port = -1;
1823         options->jump_extra = NULL;
1824         options->user = NULL;
1825         options->escape_char = -1;
1826         options->num_system_hostfiles = 0;
1827         options->num_user_hostfiles = 0;
1828         options->local_forwards = NULL;
1829         options->num_local_forwards = 0;
1830         options->remote_forwards = NULL;
1831         options->num_remote_forwards = 0;
1832         options->log_facility = SYSLOG_FACILITY_NOT_SET;
1833         options->log_level = SYSLOG_LEVEL_NOT_SET;
1834         options->preferred_authentications = NULL;
1835         options->bind_address = NULL;
1836         options->bind_interface = NULL;
1837         options->pkcs11_provider = NULL;
1838         options->enable_ssh_keysign = - 1;
1839         options->no_host_authentication_for_localhost = - 1;
1840         options->identities_only = - 1;
1841         options->rekey_limit = - 1;
1842         options->rekey_interval = -1;
1843         options->verify_host_key_dns = -1;
1844         options->server_alive_interval = -1;
1845         options->server_alive_count_max = -1;
1846         options->num_send_env = 0;
1847         options->control_path = NULL;
1848         options->control_master = -1;
1849         options->control_persist = -1;
1850         options->control_persist_timeout = 0;
1851         options->hash_known_hosts = -1;
1852         options->tun_open = -1;
1853         options->tun_local = -1;
1854         options->tun_remote = -1;
1855         options->local_command = NULL;
1856         options->permit_local_command = -1;
1857         options->remote_command = NULL;
1858         options->add_keys_to_agent = -1;
1859         options->identity_agent = NULL;
1860         options->visual_host_key = -1;
1861         options->ip_qos_interactive = -1;
1862         options->ip_qos_bulk = -1;
1863         options->request_tty = -1;
1864         options->proxy_use_fdpass = -1;
1865         options->ignored_unknown = NULL;
1866         options->num_canonical_domains = 0;
1867         options->num_permitted_cnames = 0;
1868         options->canonicalize_max_dots = -1;
1869         options->canonicalize_fallback_local = -1;
1870         options->canonicalize_hostname = -1;
1871         options->revoked_host_keys = NULL;
1872         options->fingerprint_hash = -1;
1873         options->update_hostkeys = -1;
1874         options->hostbased_key_types = NULL;
1875         options->pubkey_key_types = NULL;
1876 }
1877
1878 /*
1879  * A petite version of fill_default_options() that just fills the options
1880  * needed for hostname canonicalization to proceed.
1881  */
1882 void
1883 fill_default_options_for_canonicalization(Options *options)
1884 {
1885         if (options->canonicalize_max_dots == -1)
1886                 options->canonicalize_max_dots = 1;
1887         if (options->canonicalize_fallback_local == -1)
1888                 options->canonicalize_fallback_local = 1;
1889         if (options->canonicalize_hostname == -1)
1890                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1891 }
1892
1893 /*
1894  * Called after processing other sources of option data, this fills those
1895  * options for which no value has been specified with their default values.
1896  */
1897 void
1898 fill_default_options(Options * options)
1899 {
1900         if (options->forward_agent == -1)
1901                 options->forward_agent = 0;
1902         if (options->forward_x11 == -1)
1903                 options->forward_x11 = 0;
1904         if (options->forward_x11_trusted == -1)
1905                 options->forward_x11_trusted = 0;
1906         if (options->forward_x11_timeout == -1)
1907                 options->forward_x11_timeout = 1200;
1908         /*
1909          * stdio forwarding (-W) changes the default for these but we defer
1910          * setting the values so they can be overridden.
1911          */
1912         if (options->exit_on_forward_failure == -1)
1913                 options->exit_on_forward_failure =
1914                     options->stdio_forward_host != NULL ? 1 : 0;
1915         if (options->clear_forwardings == -1)
1916                 options->clear_forwardings =
1917                     options->stdio_forward_host != NULL ? 1 : 0;
1918         if (options->clear_forwardings == 1)
1919                 clear_forwardings(options);
1920
1921         if (options->xauth_location == NULL)
1922                 options->xauth_location = _PATH_XAUTH;
1923         if (options->fwd_opts.gateway_ports == -1)
1924                 options->fwd_opts.gateway_ports = 0;
1925         if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1926                 options->fwd_opts.streamlocal_bind_mask = 0177;
1927         if (options->fwd_opts.streamlocal_bind_unlink == -1)
1928                 options->fwd_opts.streamlocal_bind_unlink = 0;
1929         if (options->use_privileged_port == -1)
1930                 options->use_privileged_port = 0;
1931         if (options->pubkey_authentication == -1)
1932                 options->pubkey_authentication = 1;
1933         if (options->challenge_response_authentication == -1)
1934                 options->challenge_response_authentication = 1;
1935         if (options->gss_authentication == -1)
1936                 options->gss_authentication = 0;
1937         if (options->gss_deleg_creds == -1)
1938                 options->gss_deleg_creds = 0;
1939         if (options->password_authentication == -1)
1940                 options->password_authentication = 1;
1941         if (options->kbd_interactive_authentication == -1)
1942                 options->kbd_interactive_authentication = 1;
1943         if (options->hostbased_authentication == -1)
1944                 options->hostbased_authentication = 0;
1945         if (options->batch_mode == -1)
1946                 options->batch_mode = 0;
1947         if (options->check_host_ip == -1)
1948                 options->check_host_ip = 0;
1949         if (options->strict_host_key_checking == -1)
1950                 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
1951         if (options->compression == -1)
1952                 options->compression = 0;
1953         if (options->tcp_keep_alive == -1)
1954                 options->tcp_keep_alive = 1;
1955         if (options->port == -1)
1956                 options->port = 0;      /* Filled in ssh_connect. */
1957         if (options->address_family == -1)
1958                 options->address_family = AF_UNSPEC;
1959         if (options->connection_attempts == -1)
1960                 options->connection_attempts = 1;
1961         if (options->number_of_password_prompts == -1)
1962                 options->number_of_password_prompts = 3;
1963         /* options->hostkeyalgorithms, default set in myproposals.h */
1964         if (options->add_keys_to_agent == -1)
1965                 options->add_keys_to_agent = 0;
1966         if (options->num_identity_files == 0) {
1967                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
1968                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
1969 #ifdef OPENSSL_HAS_ECC
1970                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
1971 #endif
1972                 add_identity_file(options, "~/",
1973                     _PATH_SSH_CLIENT_ID_ED25519, 0);
1974                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
1975         }
1976         if (options->escape_char == -1)
1977                 options->escape_char = '~';
1978         if (options->num_system_hostfiles == 0) {
1979                 options->system_hostfiles[options->num_system_hostfiles++] =
1980                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1981                 options->system_hostfiles[options->num_system_hostfiles++] =
1982                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1983         }
1984         if (options->num_user_hostfiles == 0) {
1985                 options->user_hostfiles[options->num_user_hostfiles++] =
1986                     xstrdup(_PATH_SSH_USER_HOSTFILE);
1987                 options->user_hostfiles[options->num_user_hostfiles++] =
1988                     xstrdup(_PATH_SSH_USER_HOSTFILE2);
1989         }
1990         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1991                 options->log_level = SYSLOG_LEVEL_INFO;
1992         if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
1993                 options->log_facility = SYSLOG_FACILITY_USER;
1994         if (options->no_host_authentication_for_localhost == - 1)
1995                 options->no_host_authentication_for_localhost = 0;
1996         if (options->identities_only == -1)
1997                 options->identities_only = 0;
1998         if (options->enable_ssh_keysign == -1)
1999                 options->enable_ssh_keysign = 0;
2000         if (options->rekey_limit == -1)
2001                 options->rekey_limit = 0;
2002         if (options->rekey_interval == -1)
2003                 options->rekey_interval = 0;
2004 #if HAVE_LDNS
2005         if (options->verify_host_key_dns == -1)
2006                 /* automatically trust a verified SSHFP record */
2007                 options->verify_host_key_dns = 1;
2008 #else
2009         if (options->verify_host_key_dns == -1)
2010                 options->verify_host_key_dns = 0;
2011 #endif
2012         if (options->server_alive_interval == -1)
2013                 options->server_alive_interval = 0;
2014         if (options->server_alive_count_max == -1)
2015                 options->server_alive_count_max = 3;
2016         if (options->control_master == -1)
2017                 options->control_master = 0;
2018         if (options->control_persist == -1) {
2019                 options->control_persist = 0;
2020                 options->control_persist_timeout = 0;
2021         }
2022         if (options->hash_known_hosts == -1)
2023                 options->hash_known_hosts = 0;
2024         if (options->tun_open == -1)
2025                 options->tun_open = SSH_TUNMODE_NO;
2026         if (options->tun_local == -1)
2027                 options->tun_local = SSH_TUNID_ANY;
2028         if (options->tun_remote == -1)
2029                 options->tun_remote = SSH_TUNID_ANY;
2030         if (options->permit_local_command == -1)
2031                 options->permit_local_command = 0;
2032         if (options->visual_host_key == -1)
2033                 options->visual_host_key = 0;
2034         if (options->ip_qos_interactive == -1)
2035                 options->ip_qos_interactive = IPTOS_LOWDELAY;
2036         if (options->ip_qos_bulk == -1)
2037                 options->ip_qos_bulk = IPTOS_THROUGHPUT;
2038         if (options->request_tty == -1)
2039                 options->request_tty = REQUEST_TTY_AUTO;
2040         if (options->proxy_use_fdpass == -1)
2041                 options->proxy_use_fdpass = 0;
2042         if (options->canonicalize_max_dots == -1)
2043                 options->canonicalize_max_dots = 1;
2044         if (options->canonicalize_fallback_local == -1)
2045                 options->canonicalize_fallback_local = 1;
2046         if (options->canonicalize_hostname == -1)
2047                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2048         if (options->fingerprint_hash == -1)
2049                 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2050         if (options->update_hostkeys == -1)
2051                 options->update_hostkeys = 0;
2052         if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 ||
2053             kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 ||
2054             kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 ||
2055             kex_assemble_names(KEX_DEFAULT_PK_ALG,
2056             &options->hostbased_key_types) != 0 ||
2057             kex_assemble_names(KEX_DEFAULT_PK_ALG,
2058             &options->pubkey_key_types) != 0)
2059                 fatal("%s: kex_assemble_names failed", __func__);
2060
2061 #define CLEAR_ON_NONE(v) \
2062         do { \
2063                 if (option_clear_or_none(v)) { \
2064                         free(v); \
2065                         v = NULL; \
2066                 } \
2067         } while(0)
2068         CLEAR_ON_NONE(options->local_command);
2069         CLEAR_ON_NONE(options->remote_command);
2070         CLEAR_ON_NONE(options->proxy_command);
2071         CLEAR_ON_NONE(options->control_path);
2072         CLEAR_ON_NONE(options->revoked_host_keys);
2073         /* options->identity_agent distinguishes NULL from 'none' */
2074         /* options->user will be set in the main program if appropriate */
2075         /* options->hostname will be set in the main program if appropriate */
2076         /* options->host_key_alias should not be set by default */
2077         /* options->preferred_authentications will be set in ssh */
2078         if (options->version_addendum == NULL)
2079                 options->version_addendum = xstrdup(SSH_VERSION_FREEBSD);
2080 }
2081
2082 struct fwdarg {
2083         char *arg;
2084         int ispath;
2085 };
2086
2087 /*
2088  * parse_fwd_field
2089  * parses the next field in a port forwarding specification.
2090  * sets fwd to the parsed field and advances p past the colon
2091  * or sets it to NULL at end of string.
2092  * returns 0 on success, else non-zero.
2093  */
2094 static int
2095 parse_fwd_field(char **p, struct fwdarg *fwd)
2096 {
2097         char *ep, *cp = *p;
2098         int ispath = 0;
2099
2100         if (*cp == '\0') {
2101                 *p = NULL;
2102                 return -1;      /* end of string */
2103         }
2104
2105         /*
2106          * A field escaped with square brackets is used literally.
2107          * XXX - allow ']' to be escaped via backslash?
2108          */
2109         if (*cp == '[') {
2110                 /* find matching ']' */
2111                 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2112                         if (*ep == '/')
2113                                 ispath = 1;
2114                 }
2115                 /* no matching ']' or not at end of field. */
2116                 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2117                         return -1;
2118                 /* NUL terminate the field and advance p past the colon */
2119                 *ep++ = '\0';
2120                 if (*ep != '\0')
2121                         *ep++ = '\0';
2122                 fwd->arg = cp + 1;
2123                 fwd->ispath = ispath;
2124                 *p = ep;
2125                 return 0;
2126         }
2127
2128         for (cp = *p; *cp != '\0'; cp++) {
2129                 switch (*cp) {
2130                 case '\\':
2131                         memmove(cp, cp + 1, strlen(cp + 1) + 1);
2132                         if (*cp == '\0')
2133                                 return -1;
2134                         break;
2135                 case '/':
2136                         ispath = 1;
2137                         break;
2138                 case ':':
2139                         *cp++ = '\0';
2140                         goto done;
2141                 }
2142         }
2143 done:
2144         fwd->arg = *p;
2145         fwd->ispath = ispath;
2146         *p = cp;
2147         return 0;
2148 }
2149
2150 /*
2151  * parse_forward
2152  * parses a string containing a port forwarding specification of the form:
2153  *   dynamicfwd == 0
2154  *      [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2155  *      listenpath:connectpath
2156  *   dynamicfwd == 1
2157  *      [listenhost:]listenport
2158  * returns number of arguments parsed or zero on error
2159  */
2160 int
2161 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2162 {
2163         struct fwdarg fwdargs[4];
2164         char *p, *cp;
2165         int i;
2166
2167         memset(fwd, 0, sizeof(*fwd));
2168         memset(fwdargs, 0, sizeof(fwdargs));
2169
2170         cp = p = xstrdup(fwdspec);
2171
2172         /* skip leading spaces */
2173         while (isspace((u_char)*cp))
2174                 cp++;
2175
2176         for (i = 0; i < 4; ++i) {
2177                 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2178                         break;
2179         }
2180
2181         /* Check for trailing garbage */
2182         if (cp != NULL && *cp != '\0') {
2183                 i = 0;  /* failure */
2184         }
2185
2186         switch (i) {
2187         case 1:
2188                 if (fwdargs[0].ispath) {
2189                         fwd->listen_path = xstrdup(fwdargs[0].arg);
2190                         fwd->listen_port = PORT_STREAMLOCAL;
2191                 } else {
2192                         fwd->listen_host = NULL;
2193                         fwd->listen_port = a2port(fwdargs[0].arg);
2194                 }
2195                 fwd->connect_host = xstrdup("socks");
2196                 break;
2197
2198         case 2:
2199                 if (fwdargs[0].ispath && fwdargs[1].ispath) {
2200                         fwd->listen_path = xstrdup(fwdargs[0].arg);
2201                         fwd->listen_port = PORT_STREAMLOCAL;
2202                         fwd->connect_path = xstrdup(fwdargs[1].arg);
2203                         fwd->connect_port = PORT_STREAMLOCAL;
2204                 } else if (fwdargs[1].ispath) {
2205                         fwd->listen_host = NULL;
2206                         fwd->listen_port = a2port(fwdargs[0].arg);
2207                         fwd->connect_path = xstrdup(fwdargs[1].arg);
2208                         fwd->connect_port = PORT_STREAMLOCAL;
2209                 } else {
2210                         fwd->listen_host = xstrdup(fwdargs[0].arg);
2211                         fwd->listen_port = a2port(fwdargs[1].arg);
2212                         fwd->connect_host = xstrdup("socks");
2213                 }
2214                 break;
2215
2216         case 3:
2217                 if (fwdargs[0].ispath) {
2218                         fwd->listen_path = xstrdup(fwdargs[0].arg);
2219                         fwd->listen_port = PORT_STREAMLOCAL;
2220                         fwd->connect_host = xstrdup(fwdargs[1].arg);
2221                         fwd->connect_port = a2port(fwdargs[2].arg);
2222                 } else if (fwdargs[2].ispath) {
2223                         fwd->listen_host = xstrdup(fwdargs[0].arg);
2224                         fwd->listen_port = a2port(fwdargs[1].arg);
2225                         fwd->connect_path = xstrdup(fwdargs[2].arg);
2226                         fwd->connect_port = PORT_STREAMLOCAL;
2227                 } else {
2228                         fwd->listen_host = NULL;
2229                         fwd->listen_port = a2port(fwdargs[0].arg);
2230                         fwd->connect_host = xstrdup(fwdargs[1].arg);
2231                         fwd->connect_port = a2port(fwdargs[2].arg);
2232                 }
2233                 break;
2234
2235         case 4:
2236                 fwd->listen_host = xstrdup(fwdargs[0].arg);
2237                 fwd->listen_port = a2port(fwdargs[1].arg);
2238                 fwd->connect_host = xstrdup(fwdargs[2].arg);
2239                 fwd->connect_port = a2port(fwdargs[3].arg);
2240                 break;
2241         default:
2242                 i = 0; /* failure */
2243         }
2244
2245         free(p);
2246
2247         if (dynamicfwd) {
2248                 if (!(i == 1 || i == 2))
2249                         goto fail_free;
2250         } else {
2251                 if (!(i == 3 || i == 4)) {
2252                         if (fwd->connect_path == NULL &&
2253                             fwd->listen_path == NULL)
2254                                 goto fail_free;
2255                 }
2256                 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2257                         goto fail_free;
2258         }
2259
2260         if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2261             (!remotefwd && fwd->listen_port == 0))
2262                 goto fail_free;
2263         if (fwd->connect_host != NULL &&
2264             strlen(fwd->connect_host) >= NI_MAXHOST)
2265                 goto fail_free;
2266         /* XXX - if connecting to a remote socket, max sun len may not match this host */
2267         if (fwd->connect_path != NULL &&
2268             strlen(fwd->connect_path) >= PATH_MAX_SUN)
2269                 goto fail_free;
2270         if (fwd->listen_host != NULL &&
2271             strlen(fwd->listen_host) >= NI_MAXHOST)
2272                 goto fail_free;
2273         if (fwd->listen_path != NULL &&
2274             strlen(fwd->listen_path) >= PATH_MAX_SUN)
2275                 goto fail_free;
2276
2277         return (i);
2278
2279  fail_free:
2280         free(fwd->connect_host);
2281         fwd->connect_host = NULL;
2282         free(fwd->connect_path);
2283         fwd->connect_path = NULL;
2284         free(fwd->listen_host);
2285         fwd->listen_host = NULL;
2286         free(fwd->listen_path);
2287         fwd->listen_path = NULL;
2288         return (0);
2289 }
2290
2291 int
2292 parse_jump(const char *s, Options *o, int active)
2293 {
2294         char *orig, *sdup, *cp;
2295         char *host = NULL, *user = NULL;
2296         int ret = -1, port = -1, first;
2297
2298         active &= o->proxy_command == NULL && o->jump_host == NULL;
2299
2300         orig = sdup = xstrdup(s);
2301         first = active;
2302         do {
2303                 if ((cp = strrchr(sdup, ',')) == NULL)
2304                         cp = sdup; /* last */
2305                 else
2306                         *cp++ = '\0';
2307
2308                 if (first) {
2309                         /* First argument and configuration is active */
2310                         if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
2311                             parse_user_host_port(cp, &user, &host, &port) != 0)
2312                                 goto out;
2313                 } else {
2314                         /* Subsequent argument or inactive configuration */
2315                         if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
2316                             parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2317                                 goto out;
2318                 }
2319                 first = 0; /* only check syntax for subsequent hosts */
2320         } while (cp != sdup);
2321         /* success */
2322         if (active) {
2323                 o->jump_user = user;
2324                 o->jump_host = host;
2325                 o->jump_port = port;
2326                 o->proxy_command = xstrdup("none");
2327                 user = host = NULL;
2328                 if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2329                         o->jump_extra = xstrdup(s);
2330                         o->jump_extra[cp - s] = '\0';
2331                 }
2332         }
2333         ret = 0;
2334  out:
2335         free(orig);
2336         free(user);
2337         free(host);
2338         return ret;
2339 }
2340
2341 int
2342 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
2343 {
2344         char *path;
2345         int r;
2346
2347         r = parse_uri("ssh", uri, userp, hostp, portp, &path);
2348         if (r == 0 && path != NULL)
2349                 r = -1;         /* path not allowed */
2350         return r;
2351 }
2352
2353 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2354 static const char *
2355 fmt_multistate_int(int val, const struct multistate *m)
2356 {
2357         u_int i;
2358
2359         for (i = 0; m[i].key != NULL; i++) {
2360                 if (m[i].value == val)
2361                         return m[i].key;
2362         }
2363         return "UNKNOWN";
2364 }
2365
2366 static const char *
2367 fmt_intarg(OpCodes code, int val)
2368 {
2369         if (val == -1)
2370                 return "unset";
2371         switch (code) {
2372         case oAddressFamily:
2373                 return fmt_multistate_int(val, multistate_addressfamily);
2374         case oVerifyHostKeyDNS:
2375         case oUpdateHostkeys:
2376                 return fmt_multistate_int(val, multistate_yesnoask);
2377         case oStrictHostKeyChecking:
2378                 return fmt_multistate_int(val, multistate_strict_hostkey);
2379         case oControlMaster:
2380                 return fmt_multistate_int(val, multistate_controlmaster);
2381         case oTunnel:
2382                 return fmt_multistate_int(val, multistate_tunnel);
2383         case oRequestTTY:
2384                 return fmt_multistate_int(val, multistate_requesttty);
2385         case oCanonicalizeHostname:
2386                 return fmt_multistate_int(val, multistate_canonicalizehostname);
2387         case oFingerprintHash:
2388                 return ssh_digest_alg_name(val);
2389         default:
2390                 switch (val) {
2391                 case 0:
2392                         return "no";
2393                 case 1:
2394                         return "yes";
2395                 default:
2396                         return "UNKNOWN";
2397                 }
2398         }
2399 }
2400
2401 static const char *
2402 lookup_opcode_name(OpCodes code)
2403 {
2404         u_int i;
2405
2406         for (i = 0; keywords[i].name != NULL; i++)
2407                 if (keywords[i].opcode == code)
2408                         return(keywords[i].name);
2409         return "UNKNOWN";
2410 }
2411
2412 static void
2413 dump_cfg_int(OpCodes code, int val)
2414 {
2415         printf("%s %d\n", lookup_opcode_name(code), val);
2416 }
2417
2418 static void
2419 dump_cfg_fmtint(OpCodes code, int val)
2420 {
2421         printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2422 }
2423
2424 static void
2425 dump_cfg_string(OpCodes code, const char *val)
2426 {
2427         if (val == NULL)
2428                 return;
2429         printf("%s %s\n", lookup_opcode_name(code), val);
2430 }
2431
2432 static void
2433 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2434 {
2435         u_int i;
2436
2437         for (i = 0; i < count; i++)
2438                 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2439 }
2440
2441 static void
2442 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2443 {
2444         u_int i;
2445
2446         printf("%s", lookup_opcode_name(code));
2447         for (i = 0; i < count; i++)
2448                 printf(" %s",  vals[i]);
2449         printf("\n");
2450 }
2451
2452 static void
2453 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2454 {
2455         const struct Forward *fwd;
2456         u_int i;
2457
2458         /* oDynamicForward */
2459         for (i = 0; i < count; i++) {
2460                 fwd = &fwds[i];
2461                 if (code == oDynamicForward && fwd->connect_host != NULL &&
2462                     strcmp(fwd->connect_host, "socks") != 0)
2463                         continue;
2464                 if (code == oLocalForward && fwd->connect_host != NULL &&
2465                     strcmp(fwd->connect_host, "socks") == 0)
2466                         continue;
2467                 printf("%s", lookup_opcode_name(code));
2468                 if (fwd->listen_port == PORT_STREAMLOCAL)
2469                         printf(" %s", fwd->listen_path);
2470                 else if (fwd->listen_host == NULL)
2471                         printf(" %d", fwd->listen_port);
2472                 else {
2473                         printf(" [%s]:%d",
2474                             fwd->listen_host, fwd->listen_port);
2475                 }
2476                 if (code != oDynamicForward) {
2477                         if (fwd->connect_port == PORT_STREAMLOCAL)
2478                                 printf(" %s", fwd->connect_path);
2479                         else if (fwd->connect_host == NULL)
2480                                 printf(" %d", fwd->connect_port);
2481                         else {
2482                                 printf(" [%s]:%d",
2483                                     fwd->connect_host, fwd->connect_port);
2484                         }
2485                 }
2486                 printf("\n");
2487         }
2488 }
2489
2490 void
2491 dump_client_config(Options *o, const char *host)
2492 {
2493         int i;
2494         char buf[8];
2495
2496         /* This is normally prepared in ssh_kex2 */
2497         if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0)
2498                 fatal("%s: kex_assemble_names failed", __func__);
2499
2500         /* Most interesting options first: user, host, port */
2501         dump_cfg_string(oUser, o->user);
2502         dump_cfg_string(oHostName, host);
2503         dump_cfg_int(oPort, o->port);
2504
2505         /* Flag options */
2506         dump_cfg_fmtint(oAddressFamily, o->address_family);
2507         dump_cfg_fmtint(oBatchMode, o->batch_mode);
2508         dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2509         dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2510         dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2511         dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2512         dump_cfg_fmtint(oCompression, o->compression);
2513         dump_cfg_fmtint(oControlMaster, o->control_master);
2514         dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2515         dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2516         dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2517         dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2518         dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2519         dump_cfg_fmtint(oForwardX11, o->forward_x11);
2520         dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2521         dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2522 #ifdef GSSAPI
2523         dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2524         dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2525 #endif /* GSSAPI */
2526         dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2527         dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2528         dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2529         dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2530         dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2531         dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2532         dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2533         dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2534         dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2535         dump_cfg_fmtint(oRequestTTY, o->request_tty);
2536         dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2537         dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2538         dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2539         dump_cfg_fmtint(oTunnel, o->tun_open);
2540         dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
2541         dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2542         dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2543         dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2544
2545         /* Integer options */
2546         dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2547         dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2548         dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2549         dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2550         dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2551         dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2552
2553         /* String options */
2554         dump_cfg_string(oBindAddress, o->bind_address);
2555         dump_cfg_string(oBindInterface, o->bind_interface);
2556         dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2557         dump_cfg_string(oControlPath, o->control_path);
2558         dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2559         dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2560         dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2561         dump_cfg_string(oIdentityAgent, o->identity_agent);
2562         dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2563         dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2564         dump_cfg_string(oLocalCommand, o->local_command);
2565         dump_cfg_string(oRemoteCommand, o->remote_command);
2566         dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2567         dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2568 #ifdef ENABLE_PKCS11
2569         dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2570 #endif
2571         dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2572         dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2573         dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2574         dump_cfg_string(oXAuthLocation, o->xauth_location);
2575
2576         /* Forwards */
2577         dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2578         dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2579         dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2580
2581         /* String array options */
2582         dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2583         dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2584         dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2585         dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2586         dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2587
2588         /* Special cases */
2589
2590         /* oConnectTimeout */
2591         if (o->connection_timeout == -1)
2592                 printf("connecttimeout none\n");
2593         else
2594                 dump_cfg_int(oConnectTimeout, o->connection_timeout);
2595
2596         /* oTunnelDevice */
2597         printf("tunneldevice");
2598         if (o->tun_local == SSH_TUNID_ANY)
2599                 printf(" any");
2600         else
2601                 printf(" %d", o->tun_local);
2602         if (o->tun_remote == SSH_TUNID_ANY)
2603                 printf(":any");
2604         else
2605                 printf(":%d", o->tun_remote);
2606         printf("\n");
2607
2608         /* oCanonicalizePermittedCNAMEs */
2609         if ( o->num_permitted_cnames > 0) {
2610                 printf("canonicalizePermittedcnames");
2611                 for (i = 0; i < o->num_permitted_cnames; i++) {
2612                         printf(" %s:%s", o->permitted_cnames[i].source_list,
2613                             o->permitted_cnames[i].target_list);
2614                 }
2615                 printf("\n");
2616         }
2617
2618         /* oControlPersist */
2619         if (o->control_persist == 0 || o->control_persist_timeout == 0)
2620                 dump_cfg_fmtint(oControlPersist, o->control_persist);
2621         else
2622                 dump_cfg_int(oControlPersist, o->control_persist_timeout);
2623
2624         /* oEscapeChar */
2625         if (o->escape_char == SSH_ESCAPECHAR_NONE)
2626                 printf("escapechar none\n");
2627         else {
2628                 vis(buf, o->escape_char, VIS_WHITE, 0);
2629                 printf("escapechar %s\n", buf);
2630         }
2631
2632         /* oIPQoS */
2633         printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2634         printf("%s\n", iptos2str(o->ip_qos_bulk));
2635
2636         /* oRekeyLimit */
2637         printf("rekeylimit %llu %d\n",
2638             (unsigned long long)o->rekey_limit, o->rekey_interval);
2639
2640         /* oStreamLocalBindMask */
2641         printf("streamlocalbindmask 0%o\n",
2642             o->fwd_opts.streamlocal_bind_mask);
2643
2644         /* oProxyCommand / oProxyJump */
2645         if (o->jump_host == NULL)
2646                 dump_cfg_string(oProxyCommand, o->proxy_command);
2647         else {
2648                 /* Check for numeric addresses */
2649                 i = strchr(o->jump_host, ':') != NULL ||
2650                     strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2651                 snprintf(buf, sizeof(buf), "%d", o->jump_port);
2652                 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2653                     /* optional additional jump spec */
2654                     o->jump_extra == NULL ? "" : o->jump_extra,
2655                     o->jump_extra == NULL ? "" : ",",
2656                     /* optional user */
2657                     o->jump_user == NULL ? "" : o->jump_user,
2658                     o->jump_user == NULL ? "" : "@",
2659                     /* opening [ if hostname is numeric */
2660                     i ? "[" : "",
2661                     /* mandatory hostname */
2662                     o->jump_host,
2663                     /* closing ] if hostname is numeric */
2664                     i ? "]" : "",
2665                     /* optional port number */
2666                     o->jump_port <= 0 ? "" : ":",
2667                     o->jump_port <= 0 ? "" : buf);
2668         }
2669 }