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