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