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