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