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