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