]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/readconf.c
zfs: merge openzfs/zfs@a382e2119
[FreeBSD/FreeBSD.git] / crypto / openssh / readconf.c
1 /* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 djm Exp $ */
2 /*
3  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5  *                    All rights reserved
6  * Functions for reading the configuration files.
7  *
8  * As far as I am concerned, the code I have written for this software
9  * can be used freely for any purpose.  Any derived versions of this
10  * software must be clearly marked as such, and if the derived work is
11  * incompatible with the protocol description in the RFC file, it must be
12  * called by a name other than "ssh" or "Secure Shell".
13  */
14
15 #include "includes.h"
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/socket.h>
20 #include <sys/wait.h>
21 #include <sys/un.h>
22
23 #include <net/if.h>
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 #ifdef HAVE_IFADDRS_H
33 # include <ifaddrs.h>
34 #endif
35 #include <limits.h>
36 #include <netdb.h>
37 #ifdef HAVE_PATHS_H
38 # include <paths.h>
39 #endif
40 #include <pwd.h>
41 #include <signal.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdarg.h>
45 #include <unistd.h>
46 #ifdef USE_SYSTEM_GLOB
47 # include <glob.h>
48 #else
49 # include "openbsd-compat/glob.h"
50 #endif
51 #ifdef HAVE_UTIL_H
52 #include <util.h>
53 #endif
54 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
55 # include <vis.h>
56 #endif
57
58 #include "xmalloc.h"
59 #include "ssh.h"
60 #include "ssherr.h"
61 #include "cipher.h"
62 #include "pathnames.h"
63 #include "log.h"
64 #include "sshkey.h"
65 #include "misc.h"
66 #include "readconf.h"
67 #include "match.h"
68 #include "kex.h"
69 #include "mac.h"
70 #include "uidswap.h"
71 #include "myproposal.h"
72 #include "digest.h"
73
74 /* Format of the configuration file:
75
76    # Configuration data is parsed as follows:
77    #  1. command line options
78    #  2. user-specific file
79    #  3. system-wide file
80    # Any configuration value is only changed the first time it is set.
81    # Thus, host-specific definitions should be at the beginning of the
82    # configuration file, and defaults at the end.
83
84    # Host-specific declarations.  These may override anything above.  A single
85    # host may match multiple declarations; these are processed in the order
86    # that they are given in.
87
88    Host *.ngs.fi ngs.fi
89      User foo
90
91    Host fake.com
92      Hostname another.host.name.real.org
93      User blaah
94      Port 34289
95      ForwardX11 no
96      ForwardAgent no
97
98    Host books.com
99      RemoteForward 9999 shadows.cs.hut.fi:9999
100      Ciphers 3des-cbc
101
102    Host fascist.blob.com
103      Port 23123
104      User tylonen
105      PasswordAuthentication no
106
107    Host puukko.hut.fi
108      User t35124p
109      ProxyCommand ssh-proxy %h %p
110
111    Host *.fr
112      PublicKeyAuthentication no
113
114    Host *.su
115      Ciphers aes128-ctr
116      PasswordAuthentication no
117
118    Host vpn.fake.com
119      Tunnel yes
120      TunnelDevice 3
121
122    # Defaults for various options
123    Host *
124      ForwardAgent no
125      ForwardX11 no
126      PasswordAuthentication 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 *want_final_pass, 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,
141     int *want_final_pass, int depth);
142
143 /* Keyword tokens. */
144
145 typedef enum {
146         oBadOption,
147         oHost, oMatch, oInclude, oTag,
148         oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
149         oGatewayPorts, oExitOnForwardFailure,
150         oPasswordAuthentication,
151         oXAuthLocation,
152         oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
153         oPermitRemoteOpen,
154         oCertificateFile, oAddKeysToAgent, oIdentityAgent,
155         oUser, oEscapeChar, oProxyCommand,
156         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
157         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
158         oTCPKeepAlive, oNumberOfPasswordPrompts,
159         oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
160         oPubkeyAuthentication,
161         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
162         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
163         oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
164         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
165         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
166         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
167         oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
168         oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
169         oHashKnownHosts,
170         oTunnel, oTunnelDevice,
171         oLocalCommand, oPermitLocalCommand, oRemoteCommand,
172         oVisualHostKey,
173         oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
174         oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
175         oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
176         oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
177         oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
178         oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
179         oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
180         oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
181         oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
182         oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
183 } OpCodes;
184
185 /* Textual representations of the tokens. */
186
187 static struct {
188         const char *name;
189         OpCodes opcode;
190 } keywords[] = {
191         /* Deprecated options */
192         { "protocol", oIgnore }, /* NB. silently ignored */
193         { "cipher", oDeprecated },
194         { "fallbacktorsh", oDeprecated },
195         { "globalknownhostsfile2", oDeprecated },
196         { "rhostsauthentication", oDeprecated },
197         { "userknownhostsfile2", oDeprecated },
198         { "useroaming", oDeprecated },
199         { "usersh", oDeprecated },
200         { "useprivilegedport", oDeprecated },
201
202         /* Unsupported options */
203         { "afstokenpassing", oUnsupported },
204         { "kerberosauthentication", oUnsupported },
205         { "kerberostgtpassing", oUnsupported },
206         { "rsaauthentication", oUnsupported },
207         { "rhostsrsaauthentication", oUnsupported },
208         { "compressionlevel", oUnsupported },
209
210         /* Sometimes-unsupported options */
211 #if defined(GSSAPI)
212         { "gssapiauthentication", oGssAuthentication },
213         { "gssapidelegatecredentials", oGssDelegateCreds },
214 # else
215         { "gssapiauthentication", oUnsupported },
216         { "gssapidelegatecredentials", oUnsupported },
217 #endif
218 #ifdef ENABLE_PKCS11
219         { "pkcs11provider", oPKCS11Provider },
220         { "smartcarddevice", oPKCS11Provider },
221 # else
222         { "smartcarddevice", oUnsupported },
223         { "pkcs11provider", oUnsupported },
224 #endif
225
226         { "forwardagent", oForwardAgent },
227         { "forwardx11", oForwardX11 },
228         { "forwardx11trusted", oForwardX11Trusted },
229         { "forwardx11timeout", oForwardX11Timeout },
230         { "exitonforwardfailure", oExitOnForwardFailure },
231         { "xauthlocation", oXAuthLocation },
232         { "gatewayports", oGatewayPorts },
233         { "passwordauthentication", oPasswordAuthentication },
234         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
235         { "kbdinteractivedevices", oKbdInteractiveDevices },
236         { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
237         { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
238         { "tisauthentication", oKbdInteractiveAuthentication },  /* alias */
239         { "pubkeyauthentication", oPubkeyAuthentication },
240         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
241         { "hostbasedauthentication", oHostbasedAuthentication },
242         { "identityfile", oIdentityFile },
243         { "identityfile2", oIdentityFile },                     /* obsolete */
244         { "identitiesonly", oIdentitiesOnly },
245         { "certificatefile", oCertificateFile },
246         { "addkeystoagent", oAddKeysToAgent },
247         { "identityagent", oIdentityAgent },
248         { "hostname", oHostname },
249         { "hostkeyalias", oHostKeyAlias },
250         { "proxycommand", oProxyCommand },
251         { "port", oPort },
252         { "ciphers", oCiphers },
253         { "macs", oMacs },
254         { "remoteforward", oRemoteForward },
255         { "localforward", oLocalForward },
256         { "permitremoteopen", oPermitRemoteOpen },
257         { "user", oUser },
258         { "host", oHost },
259         { "match", oMatch },
260         { "tag", oTag },
261         { "escapechar", oEscapeChar },
262         { "globalknownhostsfile", oGlobalKnownHostsFile },
263         { "userknownhostsfile", oUserKnownHostsFile },
264         { "connectionattempts", oConnectionAttempts },
265         { "batchmode", oBatchMode },
266         { "checkhostip", oCheckHostIP },
267         { "stricthostkeychecking", oStrictHostKeyChecking },
268         { "compression", oCompression },
269         { "tcpkeepalive", oTCPKeepAlive },
270         { "keepalive", oTCPKeepAlive },                         /* obsolete */
271         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
272         { "syslogfacility", oLogFacility },
273         { "loglevel", oLogLevel },
274         { "logverbose", oLogVerbose },
275         { "dynamicforward", oDynamicForward },
276         { "preferredauthentications", oPreferredAuthentications },
277         { "hostkeyalgorithms", oHostKeyAlgorithms },
278         { "casignaturealgorithms", oCASignatureAlgorithms },
279         { "bindaddress", oBindAddress },
280         { "bindinterface", oBindInterface },
281         { "clearallforwardings", oClearAllForwardings },
282         { "enablesshkeysign", oEnableSSHKeysign },
283         { "verifyhostkeydns", oVerifyHostKeyDNS },
284         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
285         { "rekeylimit", oRekeyLimit },
286         { "connecttimeout", oConnectTimeout },
287         { "addressfamily", oAddressFamily },
288         { "serveraliveinterval", oServerAliveInterval },
289         { "serveralivecountmax", oServerAliveCountMax },
290         { "sendenv", oSendEnv },
291         { "setenv", oSetEnv },
292         { "controlpath", oControlPath },
293         { "controlmaster", oControlMaster },
294         { "controlpersist", oControlPersist },
295         { "hashknownhosts", oHashKnownHosts },
296         { "include", oInclude },
297         { "tunnel", oTunnel },
298         { "tunneldevice", oTunnelDevice },
299         { "localcommand", oLocalCommand },
300         { "permitlocalcommand", oPermitLocalCommand },
301         { "remotecommand", oRemoteCommand },
302         { "visualhostkey", oVisualHostKey },
303         { "kexalgorithms", oKexAlgorithms },
304         { "ipqos", oIPQoS },
305         { "requesttty", oRequestTTY },
306         { "sessiontype", oSessionType },
307         { "stdinnull", oStdinNull },
308         { "forkafterauthentication", oForkAfterAuthentication },
309         { "proxyusefdpass", oProxyUseFdpass },
310         { "canonicaldomains", oCanonicalDomains },
311         { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
312         { "canonicalizehostname", oCanonicalizeHostname },
313         { "canonicalizemaxdots", oCanonicalizeMaxDots },
314         { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
315         { "streamlocalbindmask", oStreamLocalBindMask },
316         { "streamlocalbindunlink", oStreamLocalBindUnlink },
317         { "revokedhostkeys", oRevokedHostKeys },
318         { "fingerprinthash", oFingerprintHash },
319         { "updatehostkeys", oUpdateHostkeys },
320         { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
321         { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
322         { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
323         { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
324         { "ignoreunknown", oIgnoreUnknown },
325         { "proxyjump", oProxyJump },
326         { "securitykeyprovider", oSecurityKeyProvider },
327         { "knownhostscommand", oKnownHostsCommand },
328         { "requiredrsasize", oRequiredRSASize },
329         { "enableescapecommandline", oEnableEscapeCommandline },
330         { "obscurekeystroketiming", oObscureKeystrokeTiming },
331         { "channeltimeout", oChannelTimeout },
332
333         /* Client VersionAddendum - retired in bffe60ead024 */
334         { "versionaddendum", oDeprecated },
335
336         { NULL, oBadOption }
337 };
338
339 static const char *lookup_opcode_name(OpCodes code);
340
341 const char *
342 kex_default_pk_alg(void)
343 {
344         static char *pkalgs;
345
346         if (pkalgs == NULL) {
347                 char *all_key;
348
349                 all_key = sshkey_alg_list(0, 0, 1, ',');
350                 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
351                 free(all_key);
352         }
353         return pkalgs;
354 }
355
356 char *
357 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
358     const char *user, const char *jumphost)
359 {
360         struct ssh_digest_ctx *md;
361         u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
362
363         if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
364             ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
365             ssh_digest_update(md, host, strlen(host)) < 0 ||
366             ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
367             ssh_digest_update(md, user, strlen(user)) < 0 ||
368             ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 ||
369             ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
370                 fatal_f("mux digest failed");
371         ssh_digest_free(md);
372         return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
373 }
374
375 /*
376  * Adds a local TCP/IP port forward to options.  Never returns if there is an
377  * error.
378  */
379
380 void
381 add_local_forward(Options *options, const struct Forward *newfwd)
382 {
383         struct Forward *fwd;
384         int i;
385
386         /* Don't add duplicates */
387         for (i = 0; i < options->num_local_forwards; i++) {
388                 if (forward_equals(newfwd, options->local_forwards + i))
389                         return;
390         }
391         options->local_forwards = xreallocarray(options->local_forwards,
392             options->num_local_forwards + 1,
393             sizeof(*options->local_forwards));
394         fwd = &options->local_forwards[options->num_local_forwards++];
395
396         fwd->listen_host = newfwd->listen_host;
397         fwd->listen_port = newfwd->listen_port;
398         fwd->listen_path = newfwd->listen_path;
399         fwd->connect_host = newfwd->connect_host;
400         fwd->connect_port = newfwd->connect_port;
401         fwd->connect_path = newfwd->connect_path;
402 }
403
404 /*
405  * Adds a remote TCP/IP port forward to options.  Never returns if there is
406  * an error.
407  */
408
409 void
410 add_remote_forward(Options *options, const struct Forward *newfwd)
411 {
412         struct Forward *fwd;
413         int i;
414
415         /* Don't add duplicates */
416         for (i = 0; i < options->num_remote_forwards; i++) {
417                 if (forward_equals(newfwd, options->remote_forwards + i))
418                         return;
419         }
420         options->remote_forwards = xreallocarray(options->remote_forwards,
421             options->num_remote_forwards + 1,
422             sizeof(*options->remote_forwards));
423         fwd = &options->remote_forwards[options->num_remote_forwards++];
424
425         fwd->listen_host = newfwd->listen_host;
426         fwd->listen_port = newfwd->listen_port;
427         fwd->listen_path = newfwd->listen_path;
428         fwd->connect_host = newfwd->connect_host;
429         fwd->connect_port = newfwd->connect_port;
430         fwd->connect_path = newfwd->connect_path;
431         fwd->handle = newfwd->handle;
432         fwd->allocated_port = 0;
433 }
434
435 static void
436 clear_forwardings(Options *options)
437 {
438         int i;
439
440         for (i = 0; i < options->num_local_forwards; i++) {
441                 free(options->local_forwards[i].listen_host);
442                 free(options->local_forwards[i].listen_path);
443                 free(options->local_forwards[i].connect_host);
444                 free(options->local_forwards[i].connect_path);
445         }
446         if (options->num_local_forwards > 0) {
447                 free(options->local_forwards);
448                 options->local_forwards = NULL;
449         }
450         options->num_local_forwards = 0;
451         for (i = 0; i < options->num_remote_forwards; i++) {
452                 free(options->remote_forwards[i].listen_host);
453                 free(options->remote_forwards[i].listen_path);
454                 free(options->remote_forwards[i].connect_host);
455                 free(options->remote_forwards[i].connect_path);
456         }
457         if (options->num_remote_forwards > 0) {
458                 free(options->remote_forwards);
459                 options->remote_forwards = NULL;
460         }
461         options->num_remote_forwards = 0;
462         options->tun_open = SSH_TUNMODE_NO;
463 }
464
465 void
466 add_certificate_file(Options *options, const char *path, int userprovided)
467 {
468         int i;
469
470         if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
471                 fatal("Too many certificate files specified (max %d)",
472                     SSH_MAX_CERTIFICATE_FILES);
473
474         /* Avoid registering duplicates */
475         for (i = 0; i < options->num_certificate_files; i++) {
476                 if (options->certificate_file_userprovided[i] == userprovided &&
477                     strcmp(options->certificate_files[i], path) == 0) {
478                         debug2_f("ignoring duplicate key %s", path);
479                         return;
480                 }
481         }
482
483         options->certificate_file_userprovided[options->num_certificate_files] =
484             userprovided;
485         options->certificate_files[options->num_certificate_files++] =
486             xstrdup(path);
487 }
488
489 void
490 add_identity_file(Options *options, const char *dir, const char *filename,
491     int userprovided)
492 {
493         char *path;
494         int i;
495
496         if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
497                 fatal("Too many identity files specified (max %d)",
498                     SSH_MAX_IDENTITY_FILES);
499
500         if (dir == NULL) /* no dir, filename is absolute */
501                 path = xstrdup(filename);
502         else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
503                 fatal("Identity file path %s too long", path);
504
505         /* Avoid registering duplicates */
506         for (i = 0; i < options->num_identity_files; i++) {
507                 if (options->identity_file_userprovided[i] == userprovided &&
508                     strcmp(options->identity_files[i], path) == 0) {
509                         debug2_f("ignoring duplicate key %s", path);
510                         free(path);
511                         return;
512                 }
513         }
514
515         options->identity_file_userprovided[options->num_identity_files] =
516             userprovided;
517         options->identity_files[options->num_identity_files++] = path;
518 }
519
520 int
521 default_ssh_port(void)
522 {
523         static int port;
524         struct servent *sp;
525
526         if (port == 0) {
527                 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
528                 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
529         }
530         return port;
531 }
532
533 /*
534  * Execute a command in a shell.
535  * Return its exit status or -1 on abnormal exit.
536  */
537 static int
538 execute_in_shell(const char *cmd)
539 {
540         char *shell;
541         pid_t pid;
542         int status;
543
544         if ((shell = getenv("SHELL")) == NULL)
545                 shell = _PATH_BSHELL;
546
547         if (access(shell, X_OK) == -1) {
548                 fatal("Shell \"%s\" is not executable: %s",
549                     shell, strerror(errno));
550         }
551
552         debug("Executing command: '%.500s'", cmd);
553
554         /* Fork and execute the command. */
555         if ((pid = fork()) == 0) {
556                 char *argv[4];
557
558                 if (stdfd_devnull(1, 1, 0) == -1)
559                         fatal_f("stdfd_devnull failed");
560                 closefrom(STDERR_FILENO + 1);
561
562                 argv[0] = shell;
563                 argv[1] = "-c";
564                 argv[2] = xstrdup(cmd);
565                 argv[3] = NULL;
566
567                 execv(argv[0], argv);
568                 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
569                 /* Die with signal to make this error apparent to parent. */
570                 ssh_signal(SIGTERM, SIG_DFL);
571                 kill(getpid(), SIGTERM);
572                 _exit(1);
573         }
574         /* Parent. */
575         if (pid == -1)
576                 fatal_f("fork: %.100s", strerror(errno));
577
578         while (waitpid(pid, &status, 0) == -1) {
579                 if (errno != EINTR && errno != EAGAIN)
580                         fatal_f("waitpid: %s", strerror(errno));
581         }
582         if (!WIFEXITED(status)) {
583                 error("command '%.100s' exited abnormally", cmd);
584                 return -1;
585         }
586         debug3("command returned status %d", WEXITSTATUS(status));
587         return WEXITSTATUS(status);
588 }
589
590 /*
591  * Check whether a local network interface address appears in CIDR pattern-
592  * list 'addrlist'. Returns 1 if matched or 0 otherwise.
593  */
594 static int
595 check_match_ifaddrs(const char *addrlist)
596 {
597 #ifdef HAVE_IFADDRS_H
598         struct ifaddrs *ifa, *ifaddrs = NULL;
599         int r, found = 0;
600         char addr[NI_MAXHOST];
601         socklen_t salen;
602
603         if (getifaddrs(&ifaddrs) != 0) {
604                 error("match localnetwork: getifaddrs failed: %s",
605                     strerror(errno));
606                 return 0;
607         }
608         for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
609                 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
610                     (ifa->ifa_flags & IFF_UP) == 0)
611                         continue;
612                 switch (ifa->ifa_addr->sa_family) {
613                 case AF_INET:
614                         salen = sizeof(struct sockaddr_in);
615                         break;
616                 case AF_INET6:
617                         salen = sizeof(struct sockaddr_in6);
618                         break;
619 #ifdef AF_LINK
620                 case AF_LINK:
621                         /* ignore */
622                         continue;
623 #endif /* AF_LINK */
624                 default:
625                         debug2_f("interface %s: unsupported address family %d",
626                             ifa->ifa_name, ifa->ifa_addr->sa_family);
627                         continue;
628                 }
629                 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
630                     NULL, 0, NI_NUMERICHOST)) != 0) {
631                         debug2_f("interface %s getnameinfo failed: %s",
632                             ifa->ifa_name, gai_strerror(r));
633                         continue;
634                 }
635                 debug3_f("interface %s addr %s", ifa->ifa_name, addr);
636                 if (addr_match_cidr_list(addr, addrlist) == 1) {
637                         debug3_f("matched interface %s: address %s in %s",
638                             ifa->ifa_name, addr, addrlist);
639                         found = 1;
640                         break;
641                 }
642         }
643         freeifaddrs(ifaddrs);
644         return found;
645 #else /* HAVE_IFADDRS_H */
646         error("match localnetwork: not supported on this platform");
647         return 0;
648 #endif /* HAVE_IFADDRS_H */
649 }
650
651 /*
652  * Parse and execute a Match directive.
653  */
654 static int
655 match_cfg_line(Options *options, char **condition, struct passwd *pw,
656     const char *host_arg, const char *original_host, int final_pass,
657     int *want_final_pass, const char *filename, int linenum)
658 {
659         char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
660         const char *ruser;
661         int r, port, this_result, result = 1, attributes = 0, negate;
662         char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
663         char uidstr[32];
664
665         /*
666          * Configuration is likely to be incomplete at this point so we
667          * must be prepared to use default values.
668          */
669         port = options->port <= 0 ? default_ssh_port() : options->port;
670         ruser = options->user == NULL ? pw->pw_name : options->user;
671         if (final_pass) {
672                 host = xstrdup(options->hostname);
673         } else if (options->hostname != NULL) {
674                 /* NB. Please keep in sync with ssh.c:main() */
675                 host = percent_expand(options->hostname,
676                     "h", host_arg, (char *)NULL);
677         } else {
678                 host = xstrdup(host_arg);
679         }
680
681         debug2("checking match for '%s' host %s originally %s",
682             cp, host, original_host);
683         while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
684                 /* Terminate on comment */
685                 if (*attrib == '#') {
686                         cp = NULL; /* mark all arguments consumed */
687                         break;
688                 }
689                 arg = criteria = NULL;
690                 this_result = 1;
691                 if ((negate = (attrib[0] == '!')))
692                         attrib++;
693                 /* Criterion "all" has no argument and must appear alone */
694                 if (strcasecmp(attrib, "all") == 0) {
695                         if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
696                             *arg != '\0' && *arg != '#')) {
697                                 error("%.200s line %d: '%s' cannot be combined "
698                                     "with other Match attributes",
699                                     filename, linenum, oattrib);
700                                 result = -1;
701                                 goto out;
702                         }
703                         if (arg != NULL && *arg == '#')
704                                 cp = NULL; /* mark all arguments consumed */
705                         if (result)
706                                 result = negate ? 0 : 1;
707                         goto out;
708                 }
709                 attributes++;
710                 /* criteria "final" and "canonical" have no argument */
711                 if (strcasecmp(attrib, "canonical") == 0 ||
712                     strcasecmp(attrib, "final") == 0) {
713                         /*
714                          * If the config requests "Match final" then remember
715                          * this so we can perform a second pass later.
716                          */
717                         if (strcasecmp(attrib, "final") == 0 &&
718                             want_final_pass != NULL)
719                                 *want_final_pass = 1;
720                         r = !!final_pass;  /* force bitmask member to boolean */
721                         if (r == (negate ? 1 : 0))
722                                 this_result = result = 0;
723                         debug3("%.200s line %d: %smatched '%s'",
724                             filename, linenum,
725                             this_result ? "" : "not ", oattrib);
726                         continue;
727                 }
728                 /* All other criteria require an argument */
729                 if ((arg = strdelim(&cp)) == NULL ||
730                     *arg == '\0' || *arg == '#') {
731                         error("Missing Match criteria for %s", attrib);
732                         result = -1;
733                         goto out;
734                 }
735                 if (strcasecmp(attrib, "host") == 0) {
736                         criteria = xstrdup(host);
737                         r = match_hostname(host, arg) == 1;
738                         if (r == (negate ? 1 : 0))
739                                 this_result = result = 0;
740                 } else if (strcasecmp(attrib, "originalhost") == 0) {
741                         criteria = xstrdup(original_host);
742                         r = match_hostname(original_host, arg) == 1;
743                         if (r == (negate ? 1 : 0))
744                                 this_result = result = 0;
745                 } else if (strcasecmp(attrib, "user") == 0) {
746                         criteria = xstrdup(ruser);
747                         r = match_pattern_list(ruser, arg, 0) == 1;
748                         if (r == (negate ? 1 : 0))
749                                 this_result = result = 0;
750                 } else if (strcasecmp(attrib, "localuser") == 0) {
751                         criteria = xstrdup(pw->pw_name);
752                         r = match_pattern_list(pw->pw_name, arg, 0) == 1;
753                         if (r == (negate ? 1 : 0))
754                                 this_result = result = 0;
755                 } else if (strcasecmp(attrib, "localnetwork") == 0) {
756                         if (addr_match_cidr_list(NULL, arg) == -1) {
757                                 /* Error already printed */
758                                 result = -1;
759                                 goto out;
760                         }
761                         r = check_match_ifaddrs(arg) == 1;
762                         if (r == (negate ? 1 : 0))
763                                 this_result = result = 0;
764                 } else if (strcasecmp(attrib, "tagged") == 0) {
765                         criteria = xstrdup(options->tag == NULL ? "" :
766                             options->tag);
767                         r = match_pattern_list(criteria, arg, 0) == 1;
768                         if (r == (negate ? 1 : 0))
769                                 this_result = result = 0;
770                 } else if (strcasecmp(attrib, "exec") == 0) {
771                         char *conn_hash_hex, *keyalias, *jmphost;
772
773                         if (gethostname(thishost, sizeof(thishost)) == -1)
774                                 fatal("gethostname: %s", strerror(errno));
775                         jmphost = option_clear_or_none(options->jump_host) ?
776                             "" : options->jump_host;
777                         strlcpy(shorthost, thishost, sizeof(shorthost));
778                         shorthost[strcspn(thishost, ".")] = '\0';
779                         snprintf(portstr, sizeof(portstr), "%d", port);
780                         snprintf(uidstr, sizeof(uidstr), "%llu",
781                             (unsigned long long)pw->pw_uid);
782                         conn_hash_hex = ssh_connection_hash(thishost, host,
783                             portstr, ruser, jmphost);
784                         keyalias = options->host_key_alias ?
785                             options->host_key_alias : host;
786
787                         cmd = percent_expand(arg,
788                             "C", conn_hash_hex,
789                             "L", shorthost,
790                             "d", pw->pw_dir,
791                             "h", host,
792                             "k", keyalias,
793                             "l", thishost,
794                             "n", original_host,
795                             "p", portstr,
796                             "r", ruser,
797                             "u", pw->pw_name,
798                             "i", uidstr,
799                             "j", jmphost,
800                             (char *)NULL);
801                         free(conn_hash_hex);
802                         if (result != 1) {
803                                 /* skip execution if prior predicate failed */
804                                 debug3("%.200s line %d: skipped exec "
805                                     "\"%.100s\"", filename, linenum, cmd);
806                                 free(cmd);
807                                 continue;
808                         }
809                         r = execute_in_shell(cmd);
810                         if (r == -1) {
811                                 fatal("%.200s line %d: match exec "
812                                     "'%.100s' error", filename,
813                                     linenum, cmd);
814                         }
815                         criteria = xstrdup(cmd);
816                         free(cmd);
817                         /* Force exit status to boolean */
818                         r = r == 0;
819                         if (r == (negate ? 1 : 0))
820                                 this_result = result = 0;
821                 } else {
822                         error("Unsupported Match attribute %s", attrib);
823                         result = -1;
824                         goto out;
825                 }
826                 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
827                     filename, linenum, this_result ? "": "not ", oattrib,
828                     criteria == NULL ? "" : " \"",
829                     criteria == NULL ? "" : criteria,
830                     criteria == NULL ? "" : "\"");
831                 free(criteria);
832         }
833         if (attributes == 0) {
834                 error("One or more attributes required for Match");
835                 result = -1;
836                 goto out;
837         }
838  out:
839         if (result != -1)
840                 debug2("match %sfound", result ? "" : "not ");
841         *condition = cp;
842         free(host);
843         return result;
844 }
845
846 /* Remove environment variable by pattern */
847 static void
848 rm_env(Options *options, const char *arg, const char *filename, int linenum)
849 {
850         u_int i, j, onum_send_env = options->num_send_env;
851
852         /* Remove an environment variable */
853         for (i = 0; i < options->num_send_env; ) {
854                 if (!match_pattern(options->send_env[i], arg + 1)) {
855                         i++;
856                         continue;
857                 }
858                 debug3("%s line %d: removing environment %s",
859                     filename, linenum, options->send_env[i]);
860                 free(options->send_env[i]);
861                 options->send_env[i] = NULL;
862                 for (j = i; j < options->num_send_env - 1; j++) {
863                         options->send_env[j] = options->send_env[j + 1];
864                         options->send_env[j + 1] = NULL;
865                 }
866                 options->num_send_env--;
867                 /* NB. don't increment i */
868         }
869         if (onum_send_env != options->num_send_env) {
870                 options->send_env = xrecallocarray(options->send_env,
871                     onum_send_env, options->num_send_env,
872                     sizeof(*options->send_env));
873         }
874 }
875
876 /*
877  * Returns the number of the token pointed to by cp or oBadOption.
878  */
879 static OpCodes
880 parse_token(const char *cp, const char *filename, int linenum,
881     const char *ignored_unknown)
882 {
883         int i;
884
885         for (i = 0; keywords[i].name; i++)
886                 if (strcmp(cp, keywords[i].name) == 0)
887                         return keywords[i].opcode;
888         if (ignored_unknown != NULL &&
889             match_pattern_list(cp, ignored_unknown, 1) == 1)
890                 return oIgnoredUnknownOption;
891         error("%s: line %d: Bad configuration option: %s",
892             filename, linenum, cp);
893         return oBadOption;
894 }
895
896 /* Multistate option parsing */
897 struct multistate {
898         char *key;
899         int value;
900 };
901 static const struct multistate multistate_flag[] = {
902         { "true",                       1 },
903         { "false",                      0 },
904         { "yes",                        1 },
905         { "no",                         0 },
906         { NULL, -1 }
907 };
908 static const struct multistate multistate_yesnoask[] = {
909         { "true",                       1 },
910         { "false",                      0 },
911         { "yes",                        1 },
912         { "no",                         0 },
913         { "ask",                        2 },
914         { NULL, -1 }
915 };
916 static const struct multistate multistate_strict_hostkey[] = {
917         { "true",                       SSH_STRICT_HOSTKEY_YES },
918         { "false",                      SSH_STRICT_HOSTKEY_OFF },
919         { "yes",                        SSH_STRICT_HOSTKEY_YES },
920         { "no",                         SSH_STRICT_HOSTKEY_OFF },
921         { "ask",                        SSH_STRICT_HOSTKEY_ASK },
922         { "off",                        SSH_STRICT_HOSTKEY_OFF },
923         { "accept-new",                 SSH_STRICT_HOSTKEY_NEW },
924         { NULL, -1 }
925 };
926 static const struct multistate multistate_yesnoaskconfirm[] = {
927         { "true",                       1 },
928         { "false",                      0 },
929         { "yes",                        1 },
930         { "no",                         0 },
931         { "ask",                        2 },
932         { "confirm",                    3 },
933         { NULL, -1 }
934 };
935 static const struct multistate multistate_addressfamily[] = {
936         { "inet",                       AF_INET },
937         { "inet6",                      AF_INET6 },
938         { "any",                        AF_UNSPEC },
939         { NULL, -1 }
940 };
941 static const struct multistate multistate_controlmaster[] = {
942         { "true",                       SSHCTL_MASTER_YES },
943         { "yes",                        SSHCTL_MASTER_YES },
944         { "false",                      SSHCTL_MASTER_NO },
945         { "no",                         SSHCTL_MASTER_NO },
946         { "auto",                       SSHCTL_MASTER_AUTO },
947         { "ask",                        SSHCTL_MASTER_ASK },
948         { "autoask",                    SSHCTL_MASTER_AUTO_ASK },
949         { NULL, -1 }
950 };
951 static const struct multistate multistate_tunnel[] = {
952         { "ethernet",                   SSH_TUNMODE_ETHERNET },
953         { "point-to-point",             SSH_TUNMODE_POINTOPOINT },
954         { "true",                       SSH_TUNMODE_DEFAULT },
955         { "yes",                        SSH_TUNMODE_DEFAULT },
956         { "false",                      SSH_TUNMODE_NO },
957         { "no",                         SSH_TUNMODE_NO },
958         { NULL, -1 }
959 };
960 static const struct multistate multistate_requesttty[] = {
961         { "true",                       REQUEST_TTY_YES },
962         { "yes",                        REQUEST_TTY_YES },
963         { "false",                      REQUEST_TTY_NO },
964         { "no",                         REQUEST_TTY_NO },
965         { "force",                      REQUEST_TTY_FORCE },
966         { "auto",                       REQUEST_TTY_AUTO },
967         { NULL, -1 }
968 };
969 static const struct multistate multistate_sessiontype[] = {
970         { "none",                       SESSION_TYPE_NONE },
971         { "subsystem",                  SESSION_TYPE_SUBSYSTEM },
972         { "default",                    SESSION_TYPE_DEFAULT },
973         { NULL, -1 }
974 };
975 static const struct multistate multistate_canonicalizehostname[] = {
976         { "true",                       SSH_CANONICALISE_YES },
977         { "false",                      SSH_CANONICALISE_NO },
978         { "yes",                        SSH_CANONICALISE_YES },
979         { "no",                         SSH_CANONICALISE_NO },
980         { "always",                     SSH_CANONICALISE_ALWAYS },
981         { NULL, -1 }
982 };
983 static const struct multistate multistate_pubkey_auth[] = {
984         { "true",                       SSH_PUBKEY_AUTH_ALL },
985         { "false",                      SSH_PUBKEY_AUTH_NO },
986         { "yes",                        SSH_PUBKEY_AUTH_ALL },
987         { "no",                         SSH_PUBKEY_AUTH_NO },
988         { "unbound",                    SSH_PUBKEY_AUTH_UNBOUND },
989         { "host-bound",                 SSH_PUBKEY_AUTH_HBOUND },
990         { NULL, -1 }
991 };
992 static const struct multistate multistate_compression[] = {
993 #ifdef WITH_ZLIB
994         { "yes",                        COMP_ZLIB },
995 #endif
996         { "no",                         COMP_NONE },
997         { NULL, -1 }
998 };
999
1000 static int
1001 parse_multistate_value(const char *arg, const char *filename, int linenum,
1002     const struct multistate *multistate_ptr)
1003 {
1004         int i;
1005
1006         if (!arg || *arg == '\0') {
1007                 error("%s line %d: missing argument.", filename, linenum);
1008                 return -1;
1009         }
1010         for (i = 0; multistate_ptr[i].key != NULL; i++) {
1011                 if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1012                         return multistate_ptr[i].value;
1013         }
1014         return -1;
1015 }
1016
1017 /*
1018  * Processes a single option line as used in the configuration files. This
1019  * only sets those values that have not already been set.
1020  */
1021 int
1022 process_config_line(Options *options, struct passwd *pw, const char *host,
1023     const char *original_host, char *line, const char *filename,
1024     int linenum, int *activep, int flags)
1025 {
1026         return process_config_line_depth(options, pw, host, original_host,
1027             line, filename, linenum, activep, flags, NULL, 0);
1028 }
1029
1030 #define WHITESPACE " \t\r\n"
1031 static int
1032 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1033     const char *original_host, char *line, const char *filename,
1034     int linenum, int *activep, int flags, int *want_final_pass, int depth)
1035 {
1036         char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1037         char **cpptr, ***cppptr, fwdarg[256];
1038         u_int i, *uintptr, uvalue, max_entries = 0;
1039         int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1040         int remotefwd, dynamicfwd, ca_only = 0;
1041         LogLevel *log_level_ptr;
1042         SyslogFacility *log_facility_ptr;
1043         long long val64;
1044         size_t len;
1045         struct Forward fwd;
1046         const struct multistate *multistate_ptr;
1047         struct allowed_cname *cname;
1048         glob_t gl;
1049         const char *errstr;
1050         char **oav = NULL, **av;
1051         int oac = 0, ac;
1052         int ret = -1;
1053
1054         if (activep == NULL) { /* We are processing a command line directive */
1055                 cmdline = 1;
1056                 activep = &cmdline;
1057         }
1058
1059         /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1060         if ((len = strlen(line)) == 0)
1061                 return 0;
1062         for (len--; len > 0; len--) {
1063                 if (strchr(WHITESPACE "\f", line[len]) == NULL)
1064                         break;
1065                 line[len] = '\0';
1066         }
1067
1068         str = line;
1069         /* Get the keyword. (Each line is supposed to begin with a keyword). */
1070         if ((keyword = strdelim(&str)) == NULL)
1071                 return 0;
1072         /* Ignore leading whitespace. */
1073         if (*keyword == '\0')
1074                 keyword = strdelim(&str);
1075         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1076                 return 0;
1077         /* Match lowercase keyword */
1078         lowercase(keyword);
1079
1080         /* Prepare to parse remainder of line */
1081         if (str != NULL)
1082                 str += strspn(str, WHITESPACE);
1083         if (str == NULL || *str == '\0') {
1084                 error("%s line %d: no argument after keyword \"%s\"",
1085                     filename, linenum, keyword);
1086                 return -1;
1087         }
1088         opcode = parse_token(keyword, filename, linenum,
1089             options->ignored_unknown);
1090         if (argv_split(str, &oac, &oav, 1) != 0) {
1091                 error("%s line %d: invalid quotes", filename, linenum);
1092                 return -1;
1093         }
1094         ac = oac;
1095         av = oav;
1096
1097         switch (opcode) {
1098         case oBadOption:
1099                 /* don't panic, but count bad options */
1100                 goto out;
1101         case oIgnore:
1102                 argv_consume(&ac);
1103                 break;
1104         case oIgnoredUnknownOption:
1105                 debug("%s line %d: Ignored unknown option \"%s\"",
1106                     filename, linenum, keyword);
1107                 argv_consume(&ac);
1108                 break;
1109         case oConnectTimeout:
1110                 intptr = &options->connection_timeout;
1111 parse_time:
1112                 arg = argv_next(&ac, &av);
1113                 if (!arg || *arg == '\0') {
1114                         error("%s line %d: missing time value.",
1115                             filename, linenum);
1116                         goto out;
1117                 }
1118                 if (strcmp(arg, "none") == 0)
1119                         value = -1;
1120                 else if ((value = convtime(arg)) == -1) {
1121                         error("%s line %d: invalid time value.",
1122                             filename, linenum);
1123                         goto out;
1124                 }
1125                 if (*activep && *intptr == -1)
1126                         *intptr = value;
1127                 break;
1128
1129         case oForwardAgent:
1130                 intptr = &options->forward_agent;
1131
1132                 arg = argv_next(&ac, &av);
1133                 if (!arg || *arg == '\0') {
1134                         error("%s line %d: missing argument.",
1135                             filename, linenum);
1136                         goto out;
1137                 }
1138
1139                 value = -1;
1140                 multistate_ptr = multistate_flag;
1141                 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1142                         if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1143                                 value = multistate_ptr[i].value;
1144                                 break;
1145                         }
1146                 }
1147                 if (value != -1) {
1148                         if (*activep && *intptr == -1)
1149                                 *intptr = value;
1150                         break;
1151                 }
1152                 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1153                 if (*activep && *intptr == -1)
1154                         *intptr = 1;
1155
1156                 charptr = &options->forward_agent_sock_path;
1157                 goto parse_agent_path;
1158
1159         case oForwardX11:
1160                 intptr = &options->forward_x11;
1161  parse_flag:
1162                 multistate_ptr = multistate_flag;
1163  parse_multistate:
1164                 arg = argv_next(&ac, &av);
1165                 if ((value = parse_multistate_value(arg, filename, linenum,
1166                     multistate_ptr)) == -1) {
1167                         error("%s line %d: unsupported option \"%s\".",
1168                             filename, linenum, arg);
1169                         goto out;
1170                 }
1171                 if (*activep && *intptr == -1)
1172                         *intptr = value;
1173                 break;
1174
1175         case oForwardX11Trusted:
1176                 intptr = &options->forward_x11_trusted;
1177                 goto parse_flag;
1178
1179         case oForwardX11Timeout:
1180                 intptr = &options->forward_x11_timeout;
1181                 goto parse_time;
1182
1183         case oGatewayPorts:
1184                 intptr = &options->fwd_opts.gateway_ports;
1185                 goto parse_flag;
1186
1187         case oExitOnForwardFailure:
1188                 intptr = &options->exit_on_forward_failure;
1189                 goto parse_flag;
1190
1191         case oPasswordAuthentication:
1192                 intptr = &options->password_authentication;
1193                 goto parse_flag;
1194
1195         case oKbdInteractiveAuthentication:
1196                 intptr = &options->kbd_interactive_authentication;
1197                 goto parse_flag;
1198
1199         case oKbdInteractiveDevices:
1200                 charptr = &options->kbd_interactive_devices;
1201                 goto parse_string;
1202
1203         case oPubkeyAuthentication:
1204                 multistate_ptr = multistate_pubkey_auth;
1205                 intptr = &options->pubkey_authentication;
1206                 goto parse_multistate;
1207
1208         case oHostbasedAuthentication:
1209                 intptr = &options->hostbased_authentication;
1210                 goto parse_flag;
1211
1212         case oGssAuthentication:
1213                 intptr = &options->gss_authentication;
1214                 goto parse_flag;
1215
1216         case oGssDelegateCreds:
1217                 intptr = &options->gss_deleg_creds;
1218                 goto parse_flag;
1219
1220         case oBatchMode:
1221                 intptr = &options->batch_mode;
1222                 goto parse_flag;
1223
1224         case oCheckHostIP:
1225                 intptr = &options->check_host_ip;
1226                 goto parse_flag;
1227
1228         case oVerifyHostKeyDNS:
1229                 intptr = &options->verify_host_key_dns;
1230                 multistate_ptr = multistate_yesnoask;
1231                 goto parse_multistate;
1232
1233         case oStrictHostKeyChecking:
1234                 intptr = &options->strict_host_key_checking;
1235                 multistate_ptr = multistate_strict_hostkey;
1236                 goto parse_multistate;
1237
1238         case oCompression:
1239                 intptr = &options->compression;
1240                 multistate_ptr = multistate_compression;
1241                 goto parse_multistate;
1242
1243         case oTCPKeepAlive:
1244                 intptr = &options->tcp_keep_alive;
1245                 goto parse_flag;
1246
1247         case oNoHostAuthenticationForLocalhost:
1248                 intptr = &options->no_host_authentication_for_localhost;
1249                 goto parse_flag;
1250
1251         case oNumberOfPasswordPrompts:
1252                 intptr = &options->number_of_password_prompts;
1253                 goto parse_int;
1254
1255         case oRekeyLimit:
1256                 arg = argv_next(&ac, &av);
1257                 if (!arg || *arg == '\0') {
1258                         error("%.200s line %d: Missing argument.", filename,
1259                             linenum);
1260                         goto out;
1261                 }
1262                 if (strcmp(arg, "default") == 0) {
1263                         val64 = 0;
1264                 } else {
1265                         if (scan_scaled(arg, &val64) == -1) {
1266                                 error("%.200s line %d: Bad number '%s': %s",
1267                                     filename, linenum, arg, strerror(errno));
1268                                 goto out;
1269                         }
1270                         if (val64 != 0 && val64 < 16) {
1271                                 error("%.200s line %d: RekeyLimit too small",
1272                                     filename, linenum);
1273                                 goto out;
1274                         }
1275                 }
1276                 if (*activep && options->rekey_limit == -1)
1277                         options->rekey_limit = val64;
1278                 if (ac != 0) { /* optional rekey interval present */
1279                         if (strcmp(av[0], "none") == 0) {
1280                                 (void)argv_next(&ac, &av);      /* discard */
1281                                 break;
1282                         }
1283                         intptr = &options->rekey_interval;
1284                         goto parse_time;
1285                 }
1286                 break;
1287
1288         case oIdentityFile:
1289                 arg = argv_next(&ac, &av);
1290                 if (!arg || *arg == '\0') {
1291                         error("%.200s line %d: Missing argument.",
1292                             filename, linenum);
1293                         goto out;
1294                 }
1295                 if (*activep) {
1296                         intptr = &options->num_identity_files;
1297                         if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1298                                 error("%.200s line %d: Too many identity files "
1299                                     "specified (max %d).", filename, linenum,
1300                                     SSH_MAX_IDENTITY_FILES);
1301                                 goto out;
1302                         }
1303                         add_identity_file(options, NULL,
1304                             arg, flags & SSHCONF_USERCONF);
1305                 }
1306                 break;
1307
1308         case oCertificateFile:
1309                 arg = argv_next(&ac, &av);
1310                 if (!arg || *arg == '\0') {
1311                         error("%.200s line %d: Missing argument.",
1312                             filename, linenum);
1313                         goto out;
1314                 }
1315                 if (*activep) {
1316                         intptr = &options->num_certificate_files;
1317                         if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1318                                 error("%.200s line %d: Too many certificate "
1319                                     "files specified (max %d).",
1320                                     filename, linenum,
1321                                     SSH_MAX_CERTIFICATE_FILES);
1322                                 goto out;
1323                         }
1324                         add_certificate_file(options, arg,
1325                             flags & SSHCONF_USERCONF);
1326                 }
1327                 break;
1328
1329         case oXAuthLocation:
1330                 charptr=&options->xauth_location;
1331                 goto parse_string;
1332
1333         case oUser:
1334                 charptr = &options->user;
1335 parse_string:
1336                 arg = argv_next(&ac, &av);
1337                 if (!arg || *arg == '\0') {
1338                         error("%.200s line %d: Missing argument.",
1339                             filename, linenum);
1340                         goto out;
1341                 }
1342                 if (*activep && *charptr == NULL)
1343                         *charptr = xstrdup(arg);
1344                 break;
1345
1346         case oGlobalKnownHostsFile:
1347                 cpptr = (char **)&options->system_hostfiles;
1348                 uintptr = &options->num_system_hostfiles;
1349                 max_entries = SSH_MAX_HOSTS_FILES;
1350 parse_char_array:
1351                 i = 0;
1352                 value = *uintptr == 0; /* was array empty when we started? */
1353                 while ((arg = argv_next(&ac, &av)) != NULL) {
1354                         if (*arg == '\0') {
1355                                 error("%s line %d: keyword %s empty argument",
1356                                     filename, linenum, keyword);
1357                                 goto out;
1358                         }
1359                         /* Allow "none" only in first position */
1360                         if (strcasecmp(arg, "none") == 0) {
1361                                 if (i > 0 || ac > 0) {
1362                                         error("%s line %d: keyword %s \"none\" "
1363                                             "argument must appear alone.",
1364                                             filename, linenum, keyword);
1365                                         goto out;
1366                                 }
1367                         }
1368                         i++;
1369                         if (*activep && value) {
1370                                 if ((*uintptr) >= max_entries) {
1371                                         error("%s line %d: too many %s "
1372                                             "entries.", filename, linenum,
1373                                             keyword);
1374                                         goto out;
1375                                 }
1376                                 cpptr[(*uintptr)++] = xstrdup(arg);
1377                         }
1378                 }
1379                 break;
1380
1381         case oUserKnownHostsFile:
1382                 cpptr = (char **)&options->user_hostfiles;
1383                 uintptr = &options->num_user_hostfiles;
1384                 max_entries = SSH_MAX_HOSTS_FILES;
1385                 goto parse_char_array;
1386
1387         case oHostname:
1388                 charptr = &options->hostname;
1389                 goto parse_string;
1390
1391         case oTag:
1392                 charptr = &options->tag;
1393                 goto parse_string;
1394
1395         case oHostKeyAlias:
1396                 charptr = &options->host_key_alias;
1397                 goto parse_string;
1398
1399         case oPreferredAuthentications:
1400                 charptr = &options->preferred_authentications;
1401                 goto parse_string;
1402
1403         case oBindAddress:
1404                 charptr = &options->bind_address;
1405                 goto parse_string;
1406
1407         case oBindInterface:
1408                 charptr = &options->bind_interface;
1409                 goto parse_string;
1410
1411         case oPKCS11Provider:
1412                 charptr = &options->pkcs11_provider;
1413                 goto parse_string;
1414
1415         case oSecurityKeyProvider:
1416                 charptr = &options->sk_provider;
1417                 goto parse_string;
1418
1419         case oKnownHostsCommand:
1420                 charptr = &options->known_hosts_command;
1421                 goto parse_command;
1422
1423         case oProxyCommand:
1424                 charptr = &options->proxy_command;
1425                 /* Ignore ProxyCommand if ProxyJump already specified */
1426                 if (options->jump_host != NULL)
1427                         charptr = &options->jump_host; /* Skip below */
1428 parse_command:
1429                 if (str == NULL) {
1430                         error("%.200s line %d: Missing argument.",
1431                             filename, linenum);
1432                         goto out;
1433                 }
1434                 len = strspn(str, WHITESPACE "=");
1435                 if (*activep && *charptr == NULL)
1436                         *charptr = xstrdup(str + len);
1437                 argv_consume(&ac);
1438                 break;
1439
1440         case oProxyJump:
1441                 if (str == NULL) {
1442                         error("%.200s line %d: Missing argument.",
1443                             filename, linenum);
1444                         goto out;
1445                 }
1446                 len = strspn(str, WHITESPACE "=");
1447                 /* XXX use argv? */
1448                 if (parse_jump(str + len, options, *activep) == -1) {
1449                         error("%.200s line %d: Invalid ProxyJump \"%s\"",
1450                             filename, linenum, str + len);
1451                         goto out;
1452                 }
1453                 argv_consume(&ac);
1454                 break;
1455
1456         case oPort:
1457                 arg = argv_next(&ac, &av);
1458                 if (!arg || *arg == '\0') {
1459                         error("%.200s line %d: Missing argument.",
1460                             filename, linenum);
1461                         goto out;
1462                 }
1463                 value = a2port(arg);
1464                 if (value <= 0) {
1465                         error("%.200s line %d: Bad port '%s'.",
1466                             filename, linenum, arg);
1467                         goto out;
1468                 }
1469                 if (*activep && options->port == -1)
1470                         options->port = value;
1471                 break;
1472
1473         case oConnectionAttempts:
1474                 intptr = &options->connection_attempts;
1475 parse_int:
1476                 arg = argv_next(&ac, &av);
1477                 if ((errstr = atoi_err(arg, &value)) != NULL) {
1478                         error("%s line %d: integer value %s.",
1479                             filename, linenum, errstr);
1480                         goto out;
1481                 }
1482                 if (*activep && *intptr == -1)
1483                         *intptr = value;
1484                 break;
1485
1486         case oCiphers:
1487                 arg = argv_next(&ac, &av);
1488                 if (!arg || *arg == '\0') {
1489                         error("%.200s line %d: Missing argument.",
1490                             filename, linenum);
1491                         goto out;
1492                 }
1493                 if (*arg != '-' &&
1494                     !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1495                         error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1496                             filename, linenum, arg ? arg : "<NONE>");
1497                         goto out;
1498                 }
1499                 if (*activep && options->ciphers == NULL)
1500                         options->ciphers = xstrdup(arg);
1501                 break;
1502
1503         case oMacs:
1504                 arg = argv_next(&ac, &av);
1505                 if (!arg || *arg == '\0') {
1506                         error("%.200s line %d: Missing argument.",
1507                             filename, linenum);
1508                         goto out;
1509                 }
1510                 if (*arg != '-' &&
1511                     !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1512                         error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1513                             filename, linenum, arg ? arg : "<NONE>");
1514                         goto out;
1515                 }
1516                 if (*activep && options->macs == NULL)
1517                         options->macs = xstrdup(arg);
1518                 break;
1519
1520         case oKexAlgorithms:
1521                 arg = argv_next(&ac, &av);
1522                 if (!arg || *arg == '\0') {
1523                         error("%.200s line %d: Missing argument.",
1524                             filename, linenum);
1525                         goto out;
1526                 }
1527                 if (*arg != '-' &&
1528                     !kex_names_valid(*arg == '+' || *arg == '^' ?
1529                     arg + 1 : arg)) {
1530                         error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1531                             filename, linenum, arg ? arg : "<NONE>");
1532                         goto out;
1533                 }
1534                 if (*activep && options->kex_algorithms == NULL)
1535                         options->kex_algorithms = xstrdup(arg);
1536                 break;
1537
1538         case oHostKeyAlgorithms:
1539                 charptr = &options->hostkeyalgorithms;
1540                 ca_only = 0;
1541 parse_pubkey_algos:
1542                 arg = argv_next(&ac, &av);
1543                 if (!arg || *arg == '\0') {
1544                         error("%.200s line %d: Missing argument.",
1545                             filename, linenum);
1546                         goto out;
1547                 }
1548                 if (*arg != '-' &&
1549                     !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1550                     arg + 1 : arg, 1, ca_only)) {
1551                         error("%s line %d: Bad key types '%s'.",
1552                             filename, linenum, arg ? arg : "<NONE>");
1553                         goto out;
1554                 }
1555                 if (*activep && *charptr == NULL)
1556                         *charptr = xstrdup(arg);
1557                 break;
1558
1559         case oCASignatureAlgorithms:
1560                 charptr = &options->ca_sign_algorithms;
1561                 ca_only = 1;
1562                 goto parse_pubkey_algos;
1563
1564         case oLogLevel:
1565                 log_level_ptr = &options->log_level;
1566                 arg = argv_next(&ac, &av);
1567                 value = log_level_number(arg);
1568                 if (value == SYSLOG_LEVEL_NOT_SET) {
1569                         error("%.200s line %d: unsupported log level '%s'",
1570                             filename, linenum, arg ? arg : "<NONE>");
1571                         goto out;
1572                 }
1573                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1574                         *log_level_ptr = (LogLevel) value;
1575                 break;
1576
1577         case oLogFacility:
1578                 log_facility_ptr = &options->log_facility;
1579                 arg = argv_next(&ac, &av);
1580                 value = log_facility_number(arg);
1581                 if (value == SYSLOG_FACILITY_NOT_SET) {
1582                         error("%.200s line %d: unsupported log facility '%s'",
1583                             filename, linenum, arg ? arg : "<NONE>");
1584                         goto out;
1585                 }
1586                 if (*log_facility_ptr == -1)
1587                         *log_facility_ptr = (SyslogFacility) value;
1588                 break;
1589
1590         case oLogVerbose:
1591                 cppptr = &options->log_verbose;
1592                 uintptr = &options->num_log_verbose;
1593                 i = 0;
1594                 while ((arg = argv_next(&ac, &av)) != NULL) {
1595                         if (*arg == '\0') {
1596                                 error("%s line %d: keyword %s empty argument",
1597                                     filename, linenum, keyword);
1598                                 goto out;
1599                         }
1600                         /* Allow "none" only in first position */
1601                         if (strcasecmp(arg, "none") == 0) {
1602                                 if (i > 0 || ac > 0) {
1603                                         error("%s line %d: keyword %s \"none\" "
1604                                             "argument must appear alone.",
1605                                             filename, linenum, keyword);
1606                                         goto out;
1607                                 }
1608                         }
1609                         i++;
1610                         if (*activep && *uintptr == 0) {
1611                                 *cppptr = xrecallocarray(*cppptr, *uintptr,
1612                                     *uintptr + 1, sizeof(**cppptr));
1613                                 (*cppptr)[(*uintptr)++] = xstrdup(arg);
1614                         }
1615                 }
1616                 break;
1617
1618         case oLocalForward:
1619         case oRemoteForward:
1620         case oDynamicForward:
1621                 arg = argv_next(&ac, &av);
1622                 if (!arg || *arg == '\0') {
1623                         error("%.200s line %d: Missing argument.",
1624                             filename, linenum);
1625                         goto out;
1626                 }
1627
1628                 remotefwd = (opcode == oRemoteForward);
1629                 dynamicfwd = (opcode == oDynamicForward);
1630
1631                 if (!dynamicfwd) {
1632                         arg2 = argv_next(&ac, &av);
1633                         if (arg2 == NULL || *arg2 == '\0') {
1634                                 if (remotefwd)
1635                                         dynamicfwd = 1;
1636                                 else {
1637                                         error("%.200s line %d: Missing target "
1638                                             "argument.", filename, linenum);
1639                                         goto out;
1640                                 }
1641                         } else {
1642                                 /* construct a string for parse_forward */
1643                                 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1644                                     arg2);
1645                         }
1646                 }
1647                 if (dynamicfwd)
1648                         strlcpy(fwdarg, arg, sizeof(fwdarg));
1649
1650                 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1651                         error("%.200s line %d: Bad forwarding specification.",
1652                             filename, linenum);
1653                         goto out;
1654                 }
1655
1656                 if (*activep) {
1657                         if (remotefwd) {
1658                                 add_remote_forward(options, &fwd);
1659                         } else {
1660                                 add_local_forward(options, &fwd);
1661                         }
1662                 }
1663                 break;
1664
1665         case oPermitRemoteOpen:
1666                 uintptr = &options->num_permitted_remote_opens;
1667                 cppptr = &options->permitted_remote_opens;
1668                 uvalue = *uintptr;      /* modified later */
1669                 i = 0;
1670                 while ((arg = argv_next(&ac, &av)) != NULL) {
1671                         arg2 = xstrdup(arg);
1672                         /* Allow any/none only in first position */
1673                         if (strcasecmp(arg, "none") == 0 ||
1674                             strcasecmp(arg, "any") == 0) {
1675                                 if (i > 0 || ac > 0) {
1676                                         error("%s line %d: keyword %s \"%s\" "
1677                                             "argument must appear alone.",
1678                                             filename, linenum, keyword, arg);
1679                                         free(arg2);
1680                                         goto out;
1681                                 }
1682                         } else {
1683                                 p = hpdelim(&arg);
1684                                 if (p == NULL) {
1685                                         fatal("%s line %d: missing host in %s",
1686                                             filename, linenum,
1687                                             lookup_opcode_name(opcode));
1688                                 }
1689                                 p = cleanhostname(p);
1690                                 /*
1691                                  * don't want to use permitopen_port to avoid
1692                                  * dependency on channels.[ch] here.
1693                                  */
1694                                 if (arg == NULL || (strcmp(arg, "*") != 0 &&
1695                                     a2port(arg) <= 0)) {
1696                                         fatal("%s line %d: bad port number "
1697                                             "in %s", filename, linenum,
1698                                             lookup_opcode_name(opcode));
1699                                 }
1700                         }
1701                         if (*activep && uvalue == 0) {
1702                                 opt_array_append(filename, linenum,
1703                                     lookup_opcode_name(opcode),
1704                                     cppptr, uintptr, arg2);
1705                         }
1706                         free(arg2);
1707                         i++;
1708                 }
1709                 if (i == 0)
1710                         fatal("%s line %d: missing %s specification",
1711                             filename, linenum, lookup_opcode_name(opcode));
1712                 break;
1713
1714         case oClearAllForwardings:
1715                 intptr = &options->clear_forwardings;
1716                 goto parse_flag;
1717
1718         case oHost:
1719                 if (cmdline) {
1720                         error("Host directive not supported as a command-line "
1721                             "option");
1722                         goto out;
1723                 }
1724                 *activep = 0;
1725                 arg2 = NULL;
1726                 while ((arg = argv_next(&ac, &av)) != NULL) {
1727                         if (*arg == '\0') {
1728                                 error("%s line %d: keyword %s empty argument",
1729                                     filename, linenum, keyword);
1730                                 goto out;
1731                         }
1732                         if ((flags & SSHCONF_NEVERMATCH) != 0) {
1733                                 argv_consume(&ac);
1734                                 break;
1735                         }
1736                         negated = *arg == '!';
1737                         if (negated)
1738                                 arg++;
1739                         if (match_pattern(host, arg)) {
1740                                 if (negated) {
1741                                         debug("%.200s line %d: Skipping Host "
1742                                             "block because of negated match "
1743                                             "for %.100s", filename, linenum,
1744                                             arg);
1745                                         *activep = 0;
1746                                         argv_consume(&ac);
1747                                         break;
1748                                 }
1749                                 if (!*activep)
1750                                         arg2 = arg; /* logged below */
1751                                 *activep = 1;
1752                         }
1753                 }
1754                 if (*activep)
1755                         debug("%.200s line %d: Applying options for %.100s",
1756                             filename, linenum, arg2);
1757                 break;
1758
1759         case oMatch:
1760                 if (cmdline) {
1761                         error("Host directive not supported as a command-line "
1762                             "option");
1763                         goto out;
1764                 }
1765                 value = match_cfg_line(options, &str, pw, host, original_host,
1766                     flags & SSHCONF_FINAL, want_final_pass,
1767                     filename, linenum);
1768                 if (value < 0) {
1769                         error("%.200s line %d: Bad Match condition", filename,
1770                             linenum);
1771                         goto out;
1772                 }
1773                 *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1774                 /*
1775                  * If match_cfg_line() didn't consume all its arguments then
1776                  * arrange for the extra arguments check below to fail.
1777                  */
1778
1779                 if (str == NULL || *str == '\0')
1780                         argv_consume(&ac);
1781                 break;
1782
1783         case oEscapeChar:
1784                 intptr = &options->escape_char;
1785                 arg = argv_next(&ac, &av);
1786                 if (!arg || *arg == '\0') {
1787                         error("%.200s line %d: Missing argument.",
1788                             filename, linenum);
1789                         goto out;
1790                 }
1791                 if (strcmp(arg, "none") == 0)
1792                         value = SSH_ESCAPECHAR_NONE;
1793                 else if (arg[1] == '\0')
1794                         value = (u_char) arg[0];
1795                 else if (arg[0] == '^' && arg[2] == 0 &&
1796                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1797                         value = (u_char) arg[1] & 31;
1798                 else {
1799                         error("%.200s line %d: Bad escape character.",
1800                             filename, linenum);
1801                         goto out;
1802                 }
1803                 if (*activep && *intptr == -1)
1804                         *intptr = value;
1805                 break;
1806
1807         case oAddressFamily:
1808                 intptr = &options->address_family;
1809                 multistate_ptr = multistate_addressfamily;
1810                 goto parse_multistate;
1811
1812         case oEnableSSHKeysign:
1813                 intptr = &options->enable_ssh_keysign;
1814                 goto parse_flag;
1815
1816         case oIdentitiesOnly:
1817                 intptr = &options->identities_only;
1818                 goto parse_flag;
1819
1820         case oServerAliveInterval:
1821                 intptr = &options->server_alive_interval;
1822                 goto parse_time;
1823
1824         case oServerAliveCountMax:
1825                 intptr = &options->server_alive_count_max;
1826                 goto parse_int;
1827
1828         case oSendEnv:
1829                 while ((arg = argv_next(&ac, &av)) != NULL) {
1830                         if (*arg == '\0' || strchr(arg, '=') != NULL) {
1831                                 error("%s line %d: Invalid environment name.",
1832                                     filename, linenum);
1833                                 goto out;
1834                         }
1835                         if (!*activep)
1836                                 continue;
1837                         if (*arg == '-') {
1838                                 /* Removing an env var */
1839                                 rm_env(options, arg, filename, linenum);
1840                                 continue;
1841                         }
1842                         opt_array_append(filename, linenum,
1843                             lookup_opcode_name(opcode),
1844                             &options->send_env, &options->num_send_env, arg);
1845                 }
1846                 break;
1847
1848         case oSetEnv:
1849                 value = options->num_setenv;
1850                 while ((arg = argv_next(&ac, &av)) != NULL) {
1851                         if (strchr(arg, '=') == NULL) {
1852                                 error("%s line %d: Invalid SetEnv.",
1853                                     filename, linenum);
1854                                 goto out;
1855                         }
1856                         if (!*activep || value != 0)
1857                                 continue;
1858                         if (lookup_setenv_in_list(arg, options->setenv,
1859                             options->num_setenv) != NULL) {
1860                                 debug2("%s line %d: ignoring duplicate env "
1861                                     "name \"%.64s\"", filename, linenum, arg);
1862                                 continue;
1863                         }
1864                         opt_array_append(filename, linenum,
1865                             lookup_opcode_name(opcode),
1866                             &options->setenv, &options->num_setenv, arg);
1867                 }
1868                 break;
1869
1870         case oControlPath:
1871                 charptr = &options->control_path;
1872                 goto parse_string;
1873
1874         case oControlMaster:
1875                 intptr = &options->control_master;
1876                 multistate_ptr = multistate_controlmaster;
1877                 goto parse_multistate;
1878
1879         case oControlPersist:
1880                 /* no/false/yes/true, or a time spec */
1881                 intptr = &options->control_persist;
1882                 arg = argv_next(&ac, &av);
1883                 if (!arg || *arg == '\0') {
1884                         error("%.200s line %d: Missing ControlPersist"
1885                             " argument.", filename, linenum);
1886                         goto out;
1887                 }
1888                 value = 0;
1889                 value2 = 0;     /* timeout */
1890                 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1891                         value = 0;
1892                 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1893                         value = 1;
1894                 else if ((value2 = convtime(arg)) >= 0)
1895                         value = 1;
1896                 else {
1897                         error("%.200s line %d: Bad ControlPersist argument.",
1898                             filename, linenum);
1899                         goto out;
1900                 }
1901                 if (*activep && *intptr == -1) {
1902                         *intptr = value;
1903                         options->control_persist_timeout = value2;
1904                 }
1905                 break;
1906
1907         case oHashKnownHosts:
1908                 intptr = &options->hash_known_hosts;
1909                 goto parse_flag;
1910
1911         case oTunnel:
1912                 intptr = &options->tun_open;
1913                 multistate_ptr = multistate_tunnel;
1914                 goto parse_multistate;
1915
1916         case oTunnelDevice:
1917                 arg = argv_next(&ac, &av);
1918                 if (!arg || *arg == '\0') {
1919                         error("%.200s line %d: Missing argument.",
1920                             filename, linenum);
1921                         goto out;
1922                 }
1923                 value = a2tun(arg, &value2);
1924                 if (value == SSH_TUNID_ERR) {
1925                         error("%.200s line %d: Bad tun device.",
1926                             filename, linenum);
1927                         goto out;
1928                 }
1929                 if (*activep && options->tun_local == -1) {
1930                         options->tun_local = value;
1931                         options->tun_remote = value2;
1932                 }
1933                 break;
1934
1935         case oLocalCommand:
1936                 charptr = &options->local_command;
1937                 goto parse_command;
1938
1939         case oPermitLocalCommand:
1940                 intptr = &options->permit_local_command;
1941                 goto parse_flag;
1942
1943         case oRemoteCommand:
1944                 charptr = &options->remote_command;
1945                 goto parse_command;
1946
1947         case oVisualHostKey:
1948                 intptr = &options->visual_host_key;
1949                 goto parse_flag;
1950
1951         case oInclude:
1952                 if (cmdline) {
1953                         error("Include directive not supported as a "
1954                             "command-line option");
1955                         goto out;
1956                 }
1957                 value = 0;
1958                 while ((arg = argv_next(&ac, &av)) != NULL) {
1959                         if (*arg == '\0') {
1960                                 error("%s line %d: keyword %s empty argument",
1961                                     filename, linenum, keyword);
1962                                 goto out;
1963                         }
1964                         /*
1965                          * Ensure all paths are anchored. User configuration
1966                          * files may begin with '~/' but system configurations
1967                          * must not. If the path is relative, then treat it
1968                          * as living in ~/.ssh for user configurations or
1969                          * /etc/ssh for system ones.
1970                          */
1971                         if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1972                                 error("%.200s line %d: bad include path %s.",
1973                                     filename, linenum, arg);
1974                                 goto out;
1975                         }
1976                         if (!path_absolute(arg) && *arg != '~') {
1977                                 xasprintf(&arg2, "%s/%s",
1978                                     (flags & SSHCONF_USERCONF) ?
1979                                     "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1980                         } else
1981                                 arg2 = xstrdup(arg);
1982                         memset(&gl, 0, sizeof(gl));
1983                         r = glob(arg2, GLOB_TILDE, NULL, &gl);
1984                         if (r == GLOB_NOMATCH) {
1985                                 debug("%.200s line %d: include %s matched no "
1986                                     "files",filename, linenum, arg2);
1987                                 free(arg2);
1988                                 continue;
1989                         } else if (r != 0) {
1990                                 error("%.200s line %d: glob failed for %s.",
1991                                     filename, linenum, arg2);
1992                                 goto out;
1993                         }
1994                         free(arg2);
1995                         oactive = *activep;
1996                         for (i = 0; i < gl.gl_pathc; i++) {
1997                                 debug3("%.200s line %d: Including file %s "
1998                                     "depth %d%s", filename, linenum,
1999                                     gl.gl_pathv[i], depth,
2000                                     oactive ? "" : " (parse only)");
2001                                 r = read_config_file_depth(gl.gl_pathv[i],
2002                                     pw, host, original_host, options,
2003                                     flags | SSHCONF_CHECKPERM |
2004                                     (oactive ? 0 : SSHCONF_NEVERMATCH),
2005                                     activep, want_final_pass, depth + 1);
2006                                 if (r != 1 && errno != ENOENT) {
2007                                         error("Can't open user config file "
2008                                             "%.100s: %.100s", gl.gl_pathv[i],
2009                                             strerror(errno));
2010                                         globfree(&gl);
2011                                         goto out;
2012                                 }
2013                                 /*
2014                                  * don't let Match in includes clobber the
2015                                  * containing file's Match state.
2016                                  */
2017                                 *activep = oactive;
2018                                 if (r != 1)
2019                                         value = -1;
2020                         }
2021                         globfree(&gl);
2022                 }
2023                 if (value != 0)
2024                         ret = value;
2025                 break;
2026
2027         case oIPQoS:
2028                 arg = argv_next(&ac, &av);
2029                 if ((value = parse_ipqos(arg)) == -1) {
2030                         error("%s line %d: Bad IPQoS value: %s",
2031                             filename, linenum, arg);
2032                         goto out;
2033                 }
2034                 arg = argv_next(&ac, &av);
2035                 if (arg == NULL)
2036                         value2 = value;
2037                 else if ((value2 = parse_ipqos(arg)) == -1) {
2038                         error("%s line %d: Bad IPQoS value: %s",
2039                             filename, linenum, arg);
2040                         goto out;
2041                 }
2042                 if (*activep && options->ip_qos_interactive == -1) {
2043                         options->ip_qos_interactive = value;
2044                         options->ip_qos_bulk = value2;
2045                 }
2046                 break;
2047
2048         case oRequestTTY:
2049                 intptr = &options->request_tty;
2050                 multistate_ptr = multistate_requesttty;
2051                 goto parse_multistate;
2052
2053         case oSessionType:
2054                 intptr = &options->session_type;
2055                 multistate_ptr = multistate_sessiontype;
2056                 goto parse_multistate;
2057
2058         case oStdinNull:
2059                 intptr = &options->stdin_null;
2060                 goto parse_flag;
2061
2062         case oForkAfterAuthentication:
2063                 intptr = &options->fork_after_authentication;
2064                 goto parse_flag;
2065
2066         case oIgnoreUnknown:
2067                 charptr = &options->ignored_unknown;
2068                 goto parse_string;
2069
2070         case oProxyUseFdpass:
2071                 intptr = &options->proxy_use_fdpass;
2072                 goto parse_flag;
2073
2074         case oCanonicalDomains:
2075                 value = options->num_canonical_domains != 0;
2076                 i = 0;
2077                 while ((arg = argv_next(&ac, &av)) != NULL) {
2078                         if (*arg == '\0') {
2079                                 error("%s line %d: keyword %s empty argument",
2080                                     filename, linenum, keyword);
2081                                 goto out;
2082                         }
2083                         /* Allow "none" only in first position */
2084                         if (strcasecmp(arg, "none") == 0) {
2085                                 if (i > 0 || ac > 0) {
2086                                         error("%s line %d: keyword %s \"none\" "
2087                                             "argument must appear alone.",
2088                                             filename, linenum, keyword);
2089                                         goto out;
2090                                 }
2091                         }
2092                         i++;
2093                         if (!valid_domain(arg, 1, &errstr)) {
2094                                 error("%s line %d: %s", filename, linenum,
2095                                     errstr);
2096                                 goto out;
2097                         }
2098                         if (!*activep || value)
2099                                 continue;
2100                         if (options->num_canonical_domains >=
2101                             MAX_CANON_DOMAINS) {
2102                                 error("%s line %d: too many hostname suffixes.",
2103                                     filename, linenum);
2104                                 goto out;
2105                         }
2106                         options->canonical_domains[
2107                             options->num_canonical_domains++] = xstrdup(arg);
2108                 }
2109                 break;
2110
2111         case oCanonicalizePermittedCNAMEs:
2112                 value = options->num_permitted_cnames != 0;
2113                 i = 0;
2114                 while ((arg = argv_next(&ac, &av)) != NULL) {
2115                         /*
2116                          * Either 'none' (only in first position), '*' for
2117                          * everything or 'list:list'
2118                          */
2119                         if (strcasecmp(arg, "none") == 0) {
2120                                 if (i > 0 || ac > 0) {
2121                                         error("%s line %d: keyword %s \"none\" "
2122                                             "argument must appear alone.",
2123                                             filename, linenum, keyword);
2124                                         goto out;
2125                                 }
2126                                 arg2 = "";
2127                         } else if (strcmp(arg, "*") == 0) {
2128                                 arg2 = arg;
2129                         } else {
2130                                 lowercase(arg);
2131                                 if ((arg2 = strchr(arg, ':')) == NULL ||
2132                                     arg2[1] == '\0') {
2133                                         error("%s line %d: "
2134                                             "Invalid permitted CNAME \"%s\"",
2135                                             filename, linenum, arg);
2136                                         goto out;
2137                                 }
2138                                 *arg2 = '\0';
2139                                 arg2++;
2140                         }
2141                         i++;
2142                         if (!*activep || value)
2143                                 continue;
2144                         if (options->num_permitted_cnames >=
2145                             MAX_CANON_DOMAINS) {
2146                                 error("%s line %d: too many permitted CNAMEs.",
2147                                     filename, linenum);
2148                                 goto out;
2149                         }
2150                         cname = options->permitted_cnames +
2151                             options->num_permitted_cnames++;
2152                         cname->source_list = xstrdup(arg);
2153                         cname->target_list = xstrdup(arg2);
2154                 }
2155                 break;
2156
2157         case oCanonicalizeHostname:
2158                 intptr = &options->canonicalize_hostname;
2159                 multistate_ptr = multistate_canonicalizehostname;
2160                 goto parse_multistate;
2161
2162         case oCanonicalizeMaxDots:
2163                 intptr = &options->canonicalize_max_dots;
2164                 goto parse_int;
2165
2166         case oCanonicalizeFallbackLocal:
2167                 intptr = &options->canonicalize_fallback_local;
2168                 goto parse_flag;
2169
2170         case oStreamLocalBindMask:
2171                 arg = argv_next(&ac, &av);
2172                 if (!arg || *arg == '\0') {
2173                         error("%.200s line %d: Missing StreamLocalBindMask "
2174                             "argument.", filename, linenum);
2175                         goto out;
2176                 }
2177                 /* Parse mode in octal format */
2178                 value = strtol(arg, &endofnumber, 8);
2179                 if (arg == endofnumber || value < 0 || value > 0777) {
2180                         error("%.200s line %d: Bad mask.", filename, linenum);
2181                         goto out;
2182                 }
2183                 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2184                 break;
2185
2186         case oStreamLocalBindUnlink:
2187                 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2188                 goto parse_flag;
2189
2190         case oRevokedHostKeys:
2191                 charptr = &options->revoked_host_keys;
2192                 goto parse_string;
2193
2194         case oFingerprintHash:
2195                 intptr = &options->fingerprint_hash;
2196                 arg = argv_next(&ac, &av);
2197                 if (!arg || *arg == '\0') {
2198                         error("%.200s line %d: Missing argument.",
2199                             filename, linenum);
2200                         goto out;
2201                 }
2202                 if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2203                         error("%.200s line %d: Invalid hash algorithm \"%s\".",
2204                             filename, linenum, arg);
2205                         goto out;
2206                 }
2207                 if (*activep && *intptr == -1)
2208                         *intptr = value;
2209                 break;
2210
2211         case oUpdateHostkeys:
2212                 intptr = &options->update_hostkeys;
2213                 multistate_ptr = multistate_yesnoask;
2214                 goto parse_multistate;
2215
2216         case oHostbasedAcceptedAlgorithms:
2217                 charptr = &options->hostbased_accepted_algos;
2218                 ca_only = 0;
2219                 goto parse_pubkey_algos;
2220
2221         case oPubkeyAcceptedAlgorithms:
2222                 charptr = &options->pubkey_accepted_algos;
2223                 ca_only = 0;
2224                 goto parse_pubkey_algos;
2225
2226         case oAddKeysToAgent:
2227                 arg = argv_next(&ac, &av);
2228                 arg2 = argv_next(&ac, &av);
2229                 value = parse_multistate_value(arg, filename, linenum,
2230                     multistate_yesnoaskconfirm);
2231                 value2 = 0; /* unlimited lifespan by default */
2232                 if (value == 3 && arg2 != NULL) {
2233                         /* allow "AddKeysToAgent confirm 5m" */
2234                         if ((value2 = convtime(arg2)) == -1) {
2235                                 error("%s line %d: invalid time value.",
2236                                     filename, linenum);
2237                                 goto out;
2238                         }
2239                 } else if (value == -1 && arg2 == NULL) {
2240                         if ((value2 = convtime(arg)) == -1) {
2241                                 error("%s line %d: unsupported option",
2242                                     filename, linenum);
2243                                 goto out;
2244                         }
2245                         value = 1; /* yes */
2246                 } else if (value == -1 || arg2 != NULL) {
2247                         error("%s line %d: unsupported option",
2248                             filename, linenum);
2249                         goto out;
2250                 }
2251                 if (*activep && options->add_keys_to_agent == -1) {
2252                         options->add_keys_to_agent = value;
2253                         options->add_keys_to_agent_lifespan = value2;
2254                 }
2255                 break;
2256
2257         case oIdentityAgent:
2258                 charptr = &options->identity_agent;
2259                 arg = argv_next(&ac, &av);
2260                 if (!arg || *arg == '\0') {
2261                         error("%.200s line %d: Missing argument.",
2262                             filename, linenum);
2263                         goto out;
2264                 }
2265   parse_agent_path:
2266                 /* Extra validation if the string represents an env var. */
2267                 if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2268                         error("%.200s line %d: Invalid environment expansion "
2269                             "%s.", filename, linenum, arg);
2270                         goto out;
2271                 }
2272                 free(arg2);
2273                 /* check for legacy environment format */
2274                 if (arg[0] == '$' && arg[1] != '{' &&
2275                     !valid_env_name(arg + 1)) {
2276                         error("%.200s line %d: Invalid environment name %s.",
2277                             filename, linenum, arg);
2278                         goto out;
2279                 }
2280                 if (*activep && *charptr == NULL)
2281                         *charptr = xstrdup(arg);
2282                 break;
2283
2284         case oEnableEscapeCommandline:
2285                 intptr = &options->enable_escape_commandline;
2286                 goto parse_flag;
2287
2288         case oRequiredRSASize:
2289                 intptr = &options->required_rsa_size;
2290                 goto parse_int;
2291
2292         case oObscureKeystrokeTiming:
2293                 value = -1;
2294                 while ((arg = argv_next(&ac, &av)) != NULL) {
2295                         if (value != -1) {
2296                                 error("%s line %d: invalid arguments",
2297                                     filename, linenum);
2298                                 goto out;
2299                         }
2300                         if (strcmp(arg, "yes") == 0 ||
2301                             strcmp(arg, "true") == 0)
2302                                 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2303                         else if (strcmp(arg, "no") == 0 ||
2304                             strcmp(arg, "false") == 0)
2305                                 value = 0;
2306                         else if (strncmp(arg, "interval:", 9) == 0) {
2307                                 if ((errstr = atoi_err(arg + 9,
2308                                     &value)) != NULL) {
2309                                         error("%s line %d: integer value %s.",
2310                                             filename, linenum, errstr);
2311                                         goto out;
2312                                 }
2313                                 if (value <= 0 || value > 1000) {
2314                                         error("%s line %d: value out of range.",
2315                                             filename, linenum);
2316                                         goto out;
2317                                 }
2318                         } else {
2319                                 error("%s line %d: unsupported argument \"%s\"",
2320                                     filename, linenum, arg);
2321                                 goto out;
2322                         }
2323                 }
2324                 if (value == -1) {
2325                         error("%s line %d: missing argument",
2326                             filename, linenum);
2327                         goto out;
2328                 }
2329                 intptr = &options->obscure_keystroke_timing_interval;
2330                 if (*activep && *intptr == -1)
2331                         *intptr = value;
2332                 break;
2333
2334         case oChannelTimeout:
2335                 uvalue = options->num_channel_timeouts;
2336                 i = 0;
2337                 while ((arg = argv_next(&ac, &av)) != NULL) {
2338                         /* Allow "none" only in first position */
2339                         if (strcasecmp(arg, "none") == 0) {
2340                                 if (i > 0 || ac > 0) {
2341                                         error("%s line %d: keyword %s \"none\" "
2342                                             "argument must appear alone.",
2343                                             filename, linenum, keyword);
2344                                         goto out;
2345                                 }
2346                         } else if (parse_pattern_interval(arg,
2347                             NULL, NULL) != 0) {
2348                                 fatal("%s line %d: invalid channel timeout %s",
2349                                     filename, linenum, arg);
2350                         }
2351                         if (!*activep || uvalue != 0)
2352                                 continue;
2353                         opt_array_append(filename, linenum, keyword,
2354                             &options->channel_timeouts,
2355                             &options->num_channel_timeouts, arg);
2356                 }
2357                 break;
2358
2359         case oDeprecated:
2360                 debug("%s line %d: Deprecated option \"%s\"",
2361                     filename, linenum, keyword);
2362                 argv_consume(&ac);
2363                 break;
2364
2365         case oUnsupported:
2366                 error("%s line %d: Unsupported option \"%s\"",
2367                     filename, linenum, keyword);
2368                 argv_consume(&ac);
2369                 break;
2370
2371         default:
2372                 error("%s line %d: Unimplemented opcode %d",
2373                     filename, linenum, opcode);
2374                 goto out;
2375         }
2376
2377         /* Check that there is no garbage at end of line. */
2378         if (ac > 0) {
2379                 error("%.200s line %d: keyword %s extra arguments "
2380                     "at end of line", filename, linenum, keyword);
2381                 goto out;
2382         }
2383
2384         /* success */
2385         ret = 0;
2386  out:
2387         argv_free(oav, oac);
2388         return ret;
2389 }
2390
2391 /*
2392  * Reads the config file and modifies the options accordingly.  Options
2393  * should already be initialized before this call.  This never returns if
2394  * there is an error.  If the file does not exist, this returns 0.
2395  */
2396 int
2397 read_config_file(const char *filename, struct passwd *pw, const char *host,
2398     const char *original_host, Options *options, int flags,
2399     int *want_final_pass)
2400 {
2401         int active = 1;
2402
2403         return read_config_file_depth(filename, pw, host, original_host,
2404             options, flags, &active, want_final_pass, 0);
2405 }
2406
2407 #define READCONF_MAX_DEPTH      16
2408 static int
2409 read_config_file_depth(const char *filename, struct passwd *pw,
2410     const char *host, const char *original_host, Options *options,
2411     int flags, int *activep, int *want_final_pass, int depth)
2412 {
2413         FILE *f;
2414         char *line = NULL;
2415         size_t linesize = 0;
2416         int linenum;
2417         int bad_options = 0;
2418
2419         if (depth < 0 || depth > READCONF_MAX_DEPTH)
2420                 fatal("Too many recursive configuration includes");
2421
2422         if ((f = fopen(filename, "r")) == NULL)
2423                 return 0;
2424
2425         if (flags & SSHCONF_CHECKPERM) {
2426                 struct stat sb;
2427
2428                 if (fstat(fileno(f), &sb) == -1)
2429                         fatal("fstat %s: %s", filename, strerror(errno));
2430                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2431                     (sb.st_mode & 022) != 0))
2432                         fatal("Bad owner or permissions on %s", filename);
2433         }
2434
2435         debug("Reading configuration data %.200s", filename);
2436
2437         /*
2438          * Mark that we are now processing the options.  This flag is turned
2439          * on/off by Host specifications.
2440          */
2441         linenum = 0;
2442         while (getline(&line, &linesize, f) != -1) {
2443                 /* Update line number counter. */
2444                 linenum++;
2445                 /*
2446                  * Trim out comments and strip whitespace.
2447                  * NB - preserve newlines, they are needed to reproduce
2448                  * line numbers later for error messages.
2449                  */
2450                 if (process_config_line_depth(options, pw, host, original_host,
2451                     line, filename, linenum, activep, flags, want_final_pass,
2452                     depth) != 0)
2453                         bad_options++;
2454         }
2455         free(line);
2456         fclose(f);
2457         if (bad_options > 0)
2458                 fatal("%s: terminating, %d bad configuration options",
2459                     filename, bad_options);
2460         return 1;
2461 }
2462
2463 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2464 int
2465 option_clear_or_none(const char *o)
2466 {
2467         return o == NULL || strcasecmp(o, "none") == 0;
2468 }
2469
2470 /*
2471  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2472  * Allowed to be called on non-final configuration.
2473  */
2474 int
2475 config_has_permitted_cnames(Options *options)
2476 {
2477         if (options->num_permitted_cnames == 1 &&
2478             strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2479             strcmp(options->permitted_cnames[0].target_list, "") == 0)
2480                 return 0;
2481         return options->num_permitted_cnames > 0;
2482 }
2483
2484 /*
2485  * Initializes options to special values that indicate that they have not yet
2486  * been set.  Read_config_file will only set options with this value. Options
2487  * are processed in the following order: command line, user config file,
2488  * system config file.  Last, fill_default_options is called.
2489  */
2490
2491 void
2492 initialize_options(Options * options)
2493 {
2494         memset(options, 'X', sizeof(*options));
2495         options->host_arg = NULL;
2496         options->forward_agent = -1;
2497         options->forward_agent_sock_path = NULL;
2498         options->forward_x11 = -1;
2499         options->forward_x11_trusted = -1;
2500         options->forward_x11_timeout = -1;
2501         options->stdio_forward_host = NULL;
2502         options->stdio_forward_port = 0;
2503         options->clear_forwardings = -1;
2504         options->exit_on_forward_failure = -1;
2505         options->xauth_location = NULL;
2506         options->fwd_opts.gateway_ports = -1;
2507         options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2508         options->fwd_opts.streamlocal_bind_unlink = -1;
2509         options->pubkey_authentication = -1;
2510         options->gss_authentication = -1;
2511         options->gss_deleg_creds = -1;
2512         options->password_authentication = -1;
2513         options->kbd_interactive_authentication = -1;
2514         options->kbd_interactive_devices = NULL;
2515         options->hostbased_authentication = -1;
2516         options->batch_mode = -1;
2517         options->check_host_ip = -1;
2518         options->strict_host_key_checking = -1;
2519         options->compression = -1;
2520         options->tcp_keep_alive = -1;
2521         options->port = -1;
2522         options->address_family = -1;
2523         options->connection_attempts = -1;
2524         options->connection_timeout = -1;
2525         options->number_of_password_prompts = -1;
2526         options->ciphers = NULL;
2527         options->macs = NULL;
2528         options->kex_algorithms = NULL;
2529         options->hostkeyalgorithms = NULL;
2530         options->ca_sign_algorithms = NULL;
2531         options->num_identity_files = 0;
2532         memset(options->identity_keys, 0, sizeof(options->identity_keys));
2533         options->num_certificate_files = 0;
2534         memset(options->certificates, 0, sizeof(options->certificates));
2535         options->hostname = NULL;
2536         options->host_key_alias = NULL;
2537         options->proxy_command = NULL;
2538         options->jump_user = NULL;
2539         options->jump_host = NULL;
2540         options->jump_port = -1;
2541         options->jump_extra = NULL;
2542         options->user = NULL;
2543         options->escape_char = -1;
2544         options->num_system_hostfiles = 0;
2545         options->num_user_hostfiles = 0;
2546         options->local_forwards = NULL;
2547         options->num_local_forwards = 0;
2548         options->remote_forwards = NULL;
2549         options->num_remote_forwards = 0;
2550         options->permitted_remote_opens = NULL;
2551         options->num_permitted_remote_opens = 0;
2552         options->log_facility = SYSLOG_FACILITY_NOT_SET;
2553         options->log_level = SYSLOG_LEVEL_NOT_SET;
2554         options->num_log_verbose = 0;
2555         options->log_verbose = NULL;
2556         options->preferred_authentications = NULL;
2557         options->bind_address = NULL;
2558         options->bind_interface = NULL;
2559         options->pkcs11_provider = NULL;
2560         options->sk_provider = NULL;
2561         options->enable_ssh_keysign = - 1;
2562         options->no_host_authentication_for_localhost = - 1;
2563         options->identities_only = - 1;
2564         options->rekey_limit = - 1;
2565         options->rekey_interval = -1;
2566         options->verify_host_key_dns = -1;
2567         options->server_alive_interval = -1;
2568         options->server_alive_count_max = -1;
2569         options->send_env = NULL;
2570         options->num_send_env = 0;
2571         options->setenv = NULL;
2572         options->num_setenv = 0;
2573         options->control_path = NULL;
2574         options->control_master = -1;
2575         options->control_persist = -1;
2576         options->control_persist_timeout = 0;
2577         options->hash_known_hosts = -1;
2578         options->tun_open = -1;
2579         options->tun_local = -1;
2580         options->tun_remote = -1;
2581         options->local_command = NULL;
2582         options->permit_local_command = -1;
2583         options->remote_command = NULL;
2584         options->add_keys_to_agent = -1;
2585         options->add_keys_to_agent_lifespan = -1;
2586         options->identity_agent = NULL;
2587         options->visual_host_key = -1;
2588         options->ip_qos_interactive = -1;
2589         options->ip_qos_bulk = -1;
2590         options->request_tty = -1;
2591         options->session_type = -1;
2592         options->stdin_null = -1;
2593         options->fork_after_authentication = -1;
2594         options->proxy_use_fdpass = -1;
2595         options->ignored_unknown = NULL;
2596         options->num_canonical_domains = 0;
2597         options->num_permitted_cnames = 0;
2598         options->canonicalize_max_dots = -1;
2599         options->canonicalize_fallback_local = -1;
2600         options->canonicalize_hostname = -1;
2601         options->revoked_host_keys = NULL;
2602         options->fingerprint_hash = -1;
2603         options->update_hostkeys = -1;
2604         options->hostbased_accepted_algos = NULL;
2605         options->pubkey_accepted_algos = NULL;
2606         options->known_hosts_command = NULL;
2607         options->required_rsa_size = -1;
2608         options->enable_escape_commandline = -1;
2609         options->obscure_keystroke_timing_interval = -1;
2610         options->tag = NULL;
2611         options->channel_timeouts = NULL;
2612         options->num_channel_timeouts = 0;
2613 }
2614
2615 /*
2616  * A petite version of fill_default_options() that just fills the options
2617  * needed for hostname canonicalization to proceed.
2618  */
2619 void
2620 fill_default_options_for_canonicalization(Options *options)
2621 {
2622         if (options->canonicalize_max_dots == -1)
2623                 options->canonicalize_max_dots = 1;
2624         if (options->canonicalize_fallback_local == -1)
2625                 options->canonicalize_fallback_local = 1;
2626         if (options->canonicalize_hostname == -1)
2627                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2628 }
2629
2630 /*
2631  * Called after processing other sources of option data, this fills those
2632  * options for which no value has been specified with their default values.
2633  */
2634 int
2635 fill_default_options(Options * options)
2636 {
2637         char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2638         char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2639         int ret = 0, r;
2640
2641         if (options->forward_agent == -1)
2642                 options->forward_agent = 0;
2643         if (options->forward_x11 == -1)
2644                 options->forward_x11 = 0;
2645         if (options->forward_x11_trusted == -1)
2646                 options->forward_x11_trusted = 0;
2647         if (options->forward_x11_timeout == -1)
2648                 options->forward_x11_timeout = 1200;
2649         /*
2650          * stdio forwarding (-W) changes the default for these but we defer
2651          * setting the values so they can be overridden.
2652          */
2653         if (options->exit_on_forward_failure == -1)
2654                 options->exit_on_forward_failure =
2655                     options->stdio_forward_host != NULL ? 1 : 0;
2656         if (options->clear_forwardings == -1)
2657                 options->clear_forwardings =
2658                     options->stdio_forward_host != NULL ? 1 : 0;
2659         if (options->clear_forwardings == 1)
2660                 clear_forwardings(options);
2661
2662         if (options->xauth_location == NULL)
2663                 options->xauth_location = xstrdup(_PATH_XAUTH);
2664         if (options->fwd_opts.gateway_ports == -1)
2665                 options->fwd_opts.gateway_ports = 0;
2666         if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2667                 options->fwd_opts.streamlocal_bind_mask = 0177;
2668         if (options->fwd_opts.streamlocal_bind_unlink == -1)
2669                 options->fwd_opts.streamlocal_bind_unlink = 0;
2670         if (options->pubkey_authentication == -1)
2671                 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2672         if (options->gss_authentication == -1)
2673                 options->gss_authentication = 0;
2674         if (options->gss_deleg_creds == -1)
2675                 options->gss_deleg_creds = 0;
2676         if (options->password_authentication == -1)
2677                 options->password_authentication = 1;
2678         if (options->kbd_interactive_authentication == -1)
2679                 options->kbd_interactive_authentication = 1;
2680         if (options->hostbased_authentication == -1)
2681                 options->hostbased_authentication = 0;
2682         if (options->batch_mode == -1)
2683                 options->batch_mode = 0;
2684         if (options->check_host_ip == -1)
2685                 options->check_host_ip = 0;
2686         if (options->strict_host_key_checking == -1)
2687                 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2688         if (options->compression == -1)
2689                 options->compression = 0;
2690         if (options->tcp_keep_alive == -1)
2691                 options->tcp_keep_alive = 1;
2692         if (options->port == -1)
2693                 options->port = 0;      /* Filled in ssh_connect. */
2694         if (options->address_family == -1)
2695                 options->address_family = AF_UNSPEC;
2696         if (options->connection_attempts == -1)
2697                 options->connection_attempts = 1;
2698         if (options->number_of_password_prompts == -1)
2699                 options->number_of_password_prompts = 3;
2700         /* options->hostkeyalgorithms, default set in myproposals.h */
2701         if (options->add_keys_to_agent == -1) {
2702                 options->add_keys_to_agent = 0;
2703                 options->add_keys_to_agent_lifespan = 0;
2704         }
2705         if (options->num_identity_files == 0) {
2706                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2707 #ifdef OPENSSL_HAS_ECC
2708                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2709                 add_identity_file(options, "~/",
2710                     _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2711 #endif
2712                 add_identity_file(options, "~/",
2713                     _PATH_SSH_CLIENT_ID_ED25519, 0);
2714                 add_identity_file(options, "~/",
2715                     _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2716                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2717                 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2718         }
2719         if (options->escape_char == -1)
2720                 options->escape_char = '~';
2721         if (options->num_system_hostfiles == 0) {
2722                 options->system_hostfiles[options->num_system_hostfiles++] =
2723                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2724                 options->system_hostfiles[options->num_system_hostfiles++] =
2725                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2726         }
2727         if (options->update_hostkeys == -1) {
2728                 if (options->verify_host_key_dns <= 0 &&
2729                     (options->num_user_hostfiles == 0 ||
2730                     (options->num_user_hostfiles == 1 && strcmp(options->
2731                     user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2732                         options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2733                 else
2734                         options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2735         }
2736         if (options->num_user_hostfiles == 0) {
2737                 options->user_hostfiles[options->num_user_hostfiles++] =
2738                     xstrdup(_PATH_SSH_USER_HOSTFILE);
2739                 options->user_hostfiles[options->num_user_hostfiles++] =
2740                     xstrdup(_PATH_SSH_USER_HOSTFILE2);
2741         }
2742         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2743                 options->log_level = SYSLOG_LEVEL_INFO;
2744         if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2745                 options->log_facility = SYSLOG_FACILITY_USER;
2746         if (options->no_host_authentication_for_localhost == - 1)
2747                 options->no_host_authentication_for_localhost = 0;
2748         if (options->identities_only == -1)
2749                 options->identities_only = 0;
2750         if (options->enable_ssh_keysign == -1)
2751                 options->enable_ssh_keysign = 0;
2752         if (options->rekey_limit == -1)
2753                 options->rekey_limit = 0;
2754         if (options->rekey_interval == -1)
2755                 options->rekey_interval = 0;
2756         if (options->verify_host_key_dns == -1)
2757                 options->verify_host_key_dns = 0;
2758         if (options->server_alive_interval == -1)
2759                 options->server_alive_interval = 0;
2760         if (options->server_alive_count_max == -1)
2761                 options->server_alive_count_max = 3;
2762         if (options->control_master == -1)
2763                 options->control_master = 0;
2764         if (options->control_persist == -1) {
2765                 options->control_persist = 0;
2766                 options->control_persist_timeout = 0;
2767         }
2768         if (options->hash_known_hosts == -1)
2769                 options->hash_known_hosts = 0;
2770         if (options->tun_open == -1)
2771                 options->tun_open = SSH_TUNMODE_NO;
2772         if (options->tun_local == -1)
2773                 options->tun_local = SSH_TUNID_ANY;
2774         if (options->tun_remote == -1)
2775                 options->tun_remote = SSH_TUNID_ANY;
2776         if (options->permit_local_command == -1)
2777                 options->permit_local_command = 0;
2778         if (options->visual_host_key == -1)
2779                 options->visual_host_key = 0;
2780         if (options->ip_qos_interactive == -1)
2781                 options->ip_qos_interactive = IPTOS_DSCP_AF21;
2782         if (options->ip_qos_bulk == -1)
2783                 options->ip_qos_bulk = IPTOS_DSCP_CS1;
2784         if (options->request_tty == -1)
2785                 options->request_tty = REQUEST_TTY_AUTO;
2786         if (options->session_type == -1)
2787                 options->session_type = SESSION_TYPE_DEFAULT;
2788         if (options->stdin_null == -1)
2789                 options->stdin_null = 0;
2790         if (options->fork_after_authentication == -1)
2791                 options->fork_after_authentication = 0;
2792         if (options->proxy_use_fdpass == -1)
2793                 options->proxy_use_fdpass = 0;
2794         if (options->canonicalize_max_dots == -1)
2795                 options->canonicalize_max_dots = 1;
2796         if (options->canonicalize_fallback_local == -1)
2797                 options->canonicalize_fallback_local = 1;
2798         if (options->canonicalize_hostname == -1)
2799                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
2800         if (options->fingerprint_hash == -1)
2801                 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2802 #ifdef ENABLE_SK_INTERNAL
2803         if (options->sk_provider == NULL)
2804                 options->sk_provider = xstrdup("internal");
2805 #else
2806         if (options->sk_provider == NULL)
2807                 options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
2808 #endif
2809         if (options->required_rsa_size == -1)
2810                 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2811         if (options->enable_escape_commandline == -1)
2812                 options->enable_escape_commandline = 0;
2813         if (options->obscure_keystroke_timing_interval == -1) {
2814                 options->obscure_keystroke_timing_interval =
2815                     SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2816         }
2817
2818         /* Expand KEX name lists */
2819         all_cipher = cipher_alg_list(',', 0);
2820         all_mac = mac_alg_list(',');
2821         all_kex = kex_alg_list(',');
2822         all_key = sshkey_alg_list(0, 0, 1, ',');
2823         all_sig = sshkey_alg_list(0, 1, 1, ',');
2824         /* remove unsupported algos from default lists */
2825         def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2826         def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2827         def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2828         def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2829         def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2830 #define ASSEMBLE(what, defaults, all) \
2831         do { \
2832                 if ((r = kex_assemble_names(&options->what, \
2833                     defaults, all)) != 0) { \
2834                         error_fr(r, "%s", #what); \
2835                         goto fail; \
2836                 } \
2837         } while (0)
2838         ASSEMBLE(ciphers, def_cipher, all_cipher);
2839         ASSEMBLE(macs, def_mac, all_mac);
2840         ASSEMBLE(kex_algorithms, def_kex, all_kex);
2841         ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2842         ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2843         ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2844 #undef ASSEMBLE
2845
2846 #define CLEAR_ON_NONE(v) \
2847         do { \
2848                 if (option_clear_or_none(v)) { \
2849                         free(v); \
2850                         v = NULL; \
2851                 } \
2852         } while(0)
2853 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2854         do { \
2855                 if (options->nv == 1 && \
2856                     strcasecmp(options->v[0], none) == 0) { \
2857                         free(options->v[0]); \
2858                         free(options->v); \
2859                         options->v = NULL; \
2860                         options->nv = 0; \
2861                 } \
2862         } while (0)
2863         CLEAR_ON_NONE(options->local_command);
2864         CLEAR_ON_NONE(options->remote_command);
2865         CLEAR_ON_NONE(options->proxy_command);
2866         CLEAR_ON_NONE(options->control_path);
2867         CLEAR_ON_NONE(options->revoked_host_keys);
2868         CLEAR_ON_NONE(options->pkcs11_provider);
2869         CLEAR_ON_NONE(options->sk_provider);
2870         CLEAR_ON_NONE(options->known_hosts_command);
2871         CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2872 #undef CLEAR_ON_NONE
2873 #undef CLEAR_ON_NONE_ARRAY
2874         if (options->jump_host != NULL &&
2875             strcmp(options->jump_host, "none") == 0 &&
2876             options->jump_port == 0 && options->jump_user == NULL) {
2877                 free(options->jump_host);
2878                 options->jump_host = NULL;
2879         }
2880         if (options->num_permitted_cnames == 1 &&
2881             !config_has_permitted_cnames(options)) {
2882                 /* clean up CanonicalizePermittedCNAMEs=none */
2883                 free(options->permitted_cnames[0].source_list);
2884                 free(options->permitted_cnames[0].target_list);
2885                 memset(options->permitted_cnames, '\0',
2886                     sizeof(*options->permitted_cnames));
2887                 options->num_permitted_cnames = 0;
2888         }
2889         /* options->identity_agent distinguishes NULL from 'none' */
2890         /* options->user will be set in the main program if appropriate */
2891         /* options->hostname will be set in the main program if appropriate */
2892         /* options->host_key_alias should not be set by default */
2893         /* options->preferred_authentications will be set in ssh */
2894
2895         /* success */
2896         ret = 0;
2897  fail:
2898         free(all_cipher);
2899         free(all_mac);
2900         free(all_kex);
2901         free(all_key);
2902         free(all_sig);
2903         free(def_cipher);
2904         free(def_mac);
2905         free(def_kex);
2906         free(def_key);
2907         free(def_sig);
2908         return ret;
2909 }
2910
2911 void
2912 free_options(Options *o)
2913 {
2914         int i;
2915
2916         if (o == NULL)
2917                 return;
2918
2919 #define FREE_ARRAY(type, n, a) \
2920         do { \
2921                 type _i; \
2922                 for (_i = 0; _i < (n); _i++) \
2923                         free((a)[_i]); \
2924         } while (0)
2925
2926         free(o->forward_agent_sock_path);
2927         free(o->xauth_location);
2928         FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2929         free(o->log_verbose);
2930         free(o->ciphers);
2931         free(o->macs);
2932         free(o->hostkeyalgorithms);
2933         free(o->kex_algorithms);
2934         free(o->ca_sign_algorithms);
2935         free(o->hostname);
2936         free(o->host_key_alias);
2937         free(o->proxy_command);
2938         free(o->user);
2939         FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2940         FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2941         free(o->preferred_authentications);
2942         free(o->bind_address);
2943         free(o->bind_interface);
2944         free(o->pkcs11_provider);
2945         free(o->sk_provider);
2946         for (i = 0; i < o->num_identity_files; i++) {
2947                 free(o->identity_files[i]);
2948                 sshkey_free(o->identity_keys[i]);
2949         }
2950         for (i = 0; i < o->num_certificate_files; i++) {
2951                 free(o->certificate_files[i]);
2952                 sshkey_free(o->certificates[i]);
2953         }
2954         free(o->identity_agent);
2955         for (i = 0; i < o->num_local_forwards; i++) {
2956                 free(o->local_forwards[i].listen_host);
2957                 free(o->local_forwards[i].listen_path);
2958                 free(o->local_forwards[i].connect_host);
2959                 free(o->local_forwards[i].connect_path);
2960         }
2961         free(o->local_forwards);
2962         for (i = 0; i < o->num_remote_forwards; i++) {
2963                 free(o->remote_forwards[i].listen_host);
2964                 free(o->remote_forwards[i].listen_path);
2965                 free(o->remote_forwards[i].connect_host);
2966                 free(o->remote_forwards[i].connect_path);
2967         }
2968         free(o->remote_forwards);
2969         free(o->stdio_forward_host);
2970         FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2971         free(o->send_env);
2972         FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2973         free(o->setenv);
2974         free(o->control_path);
2975         free(o->local_command);
2976         free(o->remote_command);
2977         FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2978         for (i = 0; i < o->num_permitted_cnames; i++) {
2979                 free(o->permitted_cnames[i].source_list);
2980                 free(o->permitted_cnames[i].target_list);
2981         }
2982         free(o->revoked_host_keys);
2983         free(o->hostbased_accepted_algos);
2984         free(o->pubkey_accepted_algos);
2985         free(o->jump_user);
2986         free(o->jump_host);
2987         free(o->jump_extra);
2988         free(o->ignored_unknown);
2989         explicit_bzero(o, sizeof(*o));
2990 #undef FREE_ARRAY
2991 }
2992
2993 struct fwdarg {
2994         char *arg;
2995         int ispath;
2996 };
2997
2998 /*
2999  * parse_fwd_field
3000  * parses the next field in a port forwarding specification.
3001  * sets fwd to the parsed field and advances p past the colon
3002  * or sets it to NULL at end of string.
3003  * returns 0 on success, else non-zero.
3004  */
3005 static int
3006 parse_fwd_field(char **p, struct fwdarg *fwd)
3007 {
3008         char *ep, *cp = *p;
3009         int ispath = 0;
3010
3011         if (*cp == '\0') {
3012                 *p = NULL;
3013                 return -1;      /* end of string */
3014         }
3015
3016         /*
3017          * A field escaped with square brackets is used literally.
3018          * XXX - allow ']' to be escaped via backslash?
3019          */
3020         if (*cp == '[') {
3021                 /* find matching ']' */
3022                 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
3023                         if (*ep == '/')
3024                                 ispath = 1;
3025                 }
3026                 /* no matching ']' or not at end of field. */
3027                 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
3028                         return -1;
3029                 /* NUL terminate the field and advance p past the colon */
3030                 *ep++ = '\0';
3031                 if (*ep != '\0')
3032                         *ep++ = '\0';
3033                 fwd->arg = cp + 1;
3034                 fwd->ispath = ispath;
3035                 *p = ep;
3036                 return 0;
3037         }
3038
3039         for (cp = *p; *cp != '\0'; cp++) {
3040                 switch (*cp) {
3041                 case '\\':
3042                         memmove(cp, cp + 1, strlen(cp + 1) + 1);
3043                         if (*cp == '\0')
3044                                 return -1;
3045                         break;
3046                 case '/':
3047                         ispath = 1;
3048                         break;
3049                 case ':':
3050                         *cp++ = '\0';
3051                         goto done;
3052                 }
3053         }
3054 done:
3055         fwd->arg = *p;
3056         fwd->ispath = ispath;
3057         *p = cp;
3058         return 0;
3059 }
3060
3061 /*
3062  * parse_forward
3063  * parses a string containing a port forwarding specification of the form:
3064  *   dynamicfwd == 0
3065  *      [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3066  *      listenpath:connectpath
3067  *   dynamicfwd == 1
3068  *      [listenhost:]listenport
3069  * returns number of arguments parsed or zero on error
3070  */
3071 int
3072 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3073 {
3074         struct fwdarg fwdargs[4];
3075         char *p, *cp;
3076         int i, err;
3077
3078         memset(fwd, 0, sizeof(*fwd));
3079         memset(fwdargs, 0, sizeof(fwdargs));
3080
3081         /*
3082          * We expand environment variables before checking if we think they're
3083          * paths so that if ${VAR} expands to a fully qualified path it is
3084          * treated as a path.
3085          */
3086         cp = p = dollar_expand(&err, fwdspec);
3087         if (p == NULL || err)
3088                 return 0;
3089
3090         /* skip leading spaces */
3091         while (isspace((u_char)*cp))
3092                 cp++;
3093
3094         for (i = 0; i < 4; ++i) {
3095                 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3096                         break;
3097         }
3098
3099         /* Check for trailing garbage */
3100         if (cp != NULL && *cp != '\0') {
3101                 i = 0;  /* failure */
3102         }
3103
3104         switch (i) {
3105         case 1:
3106                 if (fwdargs[0].ispath) {
3107                         fwd->listen_path = xstrdup(fwdargs[0].arg);
3108                         fwd->listen_port = PORT_STREAMLOCAL;
3109                 } else {
3110                         fwd->listen_host = NULL;
3111                         fwd->listen_port = a2port(fwdargs[0].arg);
3112                 }
3113                 fwd->connect_host = xstrdup("socks");
3114                 break;
3115
3116         case 2:
3117                 if (fwdargs[0].ispath && fwdargs[1].ispath) {
3118                         fwd->listen_path = xstrdup(fwdargs[0].arg);
3119                         fwd->listen_port = PORT_STREAMLOCAL;
3120                         fwd->connect_path = xstrdup(fwdargs[1].arg);
3121                         fwd->connect_port = PORT_STREAMLOCAL;
3122                 } else if (fwdargs[1].ispath) {
3123                         fwd->listen_host = NULL;
3124                         fwd->listen_port = a2port(fwdargs[0].arg);
3125                         fwd->connect_path = xstrdup(fwdargs[1].arg);
3126                         fwd->connect_port = PORT_STREAMLOCAL;
3127                 } else {
3128                         fwd->listen_host = xstrdup(fwdargs[0].arg);
3129                         fwd->listen_port = a2port(fwdargs[1].arg);
3130                         fwd->connect_host = xstrdup("socks");
3131                 }
3132                 break;
3133
3134         case 3:
3135                 if (fwdargs[0].ispath) {
3136                         fwd->listen_path = xstrdup(fwdargs[0].arg);
3137                         fwd->listen_port = PORT_STREAMLOCAL;
3138                         fwd->connect_host = xstrdup(fwdargs[1].arg);
3139                         fwd->connect_port = a2port(fwdargs[2].arg);
3140                 } else if (fwdargs[2].ispath) {
3141                         fwd->listen_host = xstrdup(fwdargs[0].arg);
3142                         fwd->listen_port = a2port(fwdargs[1].arg);
3143                         fwd->connect_path = xstrdup(fwdargs[2].arg);
3144                         fwd->connect_port = PORT_STREAMLOCAL;
3145                 } else {
3146                         fwd->listen_host = NULL;
3147                         fwd->listen_port = a2port(fwdargs[0].arg);
3148                         fwd->connect_host = xstrdup(fwdargs[1].arg);
3149                         fwd->connect_port = a2port(fwdargs[2].arg);
3150                 }
3151                 break;
3152
3153         case 4:
3154                 fwd->listen_host = xstrdup(fwdargs[0].arg);
3155                 fwd->listen_port = a2port(fwdargs[1].arg);
3156                 fwd->connect_host = xstrdup(fwdargs[2].arg);
3157                 fwd->connect_port = a2port(fwdargs[3].arg);
3158                 break;
3159         default:
3160                 i = 0; /* failure */
3161         }
3162
3163         free(p);
3164
3165         if (dynamicfwd) {
3166                 if (!(i == 1 || i == 2))
3167                         goto fail_free;
3168         } else {
3169                 if (!(i == 3 || i == 4)) {
3170                         if (fwd->connect_path == NULL &&
3171                             fwd->listen_path == NULL)
3172                                 goto fail_free;
3173                 }
3174                 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3175                         goto fail_free;
3176         }
3177
3178         if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3179             (!remotefwd && fwd->listen_port == 0))
3180                 goto fail_free;
3181         if (fwd->connect_host != NULL &&
3182             strlen(fwd->connect_host) >= NI_MAXHOST)
3183                 goto fail_free;
3184         /*
3185          * XXX - if connecting to a remote socket, max sun len may not
3186          * match this host
3187          */
3188         if (fwd->connect_path != NULL &&
3189             strlen(fwd->connect_path) >= PATH_MAX_SUN)
3190                 goto fail_free;
3191         if (fwd->listen_host != NULL &&
3192             strlen(fwd->listen_host) >= NI_MAXHOST)
3193                 goto fail_free;
3194         if (fwd->listen_path != NULL &&
3195             strlen(fwd->listen_path) >= PATH_MAX_SUN)
3196                 goto fail_free;
3197
3198         return (i);
3199
3200  fail_free:
3201         free(fwd->connect_host);
3202         fwd->connect_host = NULL;
3203         free(fwd->connect_path);
3204         fwd->connect_path = NULL;
3205         free(fwd->listen_host);
3206         fwd->listen_host = NULL;
3207         free(fwd->listen_path);
3208         fwd->listen_path = NULL;
3209         return (0);
3210 }
3211
3212 int
3213 parse_jump(const char *s, Options *o, int active)
3214 {
3215         char *orig, *sdup, *cp;
3216         char *host = NULL, *user = NULL;
3217         int r, ret = -1, port = -1, first;
3218
3219         active &= o->proxy_command == NULL && o->jump_host == NULL;
3220
3221         orig = sdup = xstrdup(s);
3222
3223         /* Remove comment and trailing whitespace */
3224         if ((cp = strchr(orig, '#')) != NULL)
3225                 *cp = '\0';
3226         rtrim(orig);
3227
3228         first = active;
3229         do {
3230                 if (strcasecmp(s, "none") == 0)
3231                         break;
3232                 if ((cp = strrchr(sdup, ',')) == NULL)
3233                         cp = sdup; /* last */
3234                 else
3235                         *cp++ = '\0';
3236
3237                 if (first) {
3238                         /* First argument and configuration is active */
3239                         r = parse_ssh_uri(cp, &user, &host, &port);
3240                         if (r == -1 || (r == 1 &&
3241                             parse_user_host_port(cp, &user, &host, &port) != 0))
3242                                 goto out;
3243                 } else {
3244                         /* Subsequent argument or inactive configuration */
3245                         r = parse_ssh_uri(cp, NULL, NULL, NULL);
3246                         if (r == -1 || (r == 1 &&
3247                             parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3248                                 goto out;
3249                 }
3250                 first = 0; /* only check syntax for subsequent hosts */
3251         } while (cp != sdup);
3252         /* success */
3253         if (active) {
3254                 if (strcasecmp(s, "none") == 0) {
3255                         o->jump_host = xstrdup("none");
3256                         o->jump_port = 0;
3257                 } else {
3258                         o->jump_user = user;
3259                         o->jump_host = host;
3260                         o->jump_port = port;
3261                         o->proxy_command = xstrdup("none");
3262                         user = host = NULL;
3263                         if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3264                                 o->jump_extra = xstrdup(s);
3265                                 o->jump_extra[cp - s] = '\0';
3266                         }
3267                 }
3268         }
3269         ret = 0;
3270  out:
3271         free(orig);
3272         free(user);
3273         free(host);
3274         return ret;
3275 }
3276
3277 int
3278 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3279 {
3280         char *user = NULL, *host = NULL, *path = NULL;
3281         int r, port;
3282
3283         r = parse_uri("ssh", uri, &user, &host, &port, &path);
3284         if (r == 0 && path != NULL)
3285                 r = -1;         /* path not allowed */
3286         if (r == 0) {
3287                 if (userp != NULL) {
3288                         *userp = user;
3289                         user = NULL;
3290                 }
3291                 if (hostp != NULL) {
3292                         *hostp = host;
3293                         host = NULL;
3294                 }
3295                 if (portp != NULL)
3296                         *portp = port;
3297         }
3298         free(user);
3299         free(host);
3300         free(path);
3301         return r;
3302 }
3303
3304 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3305 static const char *
3306 fmt_multistate_int(int val, const struct multistate *m)
3307 {
3308         u_int i;
3309
3310         for (i = 0; m[i].key != NULL; i++) {
3311                 if (m[i].value == val)
3312                         return m[i].key;
3313         }
3314         return "UNKNOWN";
3315 }
3316
3317 static const char *
3318 fmt_intarg(OpCodes code, int val)
3319 {
3320         if (val == -1)
3321                 return "unset";
3322         switch (code) {
3323         case oAddressFamily:
3324                 return fmt_multistate_int(val, multistate_addressfamily);
3325         case oVerifyHostKeyDNS:
3326         case oUpdateHostkeys:
3327                 return fmt_multistate_int(val, multistate_yesnoask);
3328         case oStrictHostKeyChecking:
3329                 return fmt_multistate_int(val, multistate_strict_hostkey);
3330         case oControlMaster:
3331                 return fmt_multistate_int(val, multistate_controlmaster);
3332         case oTunnel:
3333                 return fmt_multistate_int(val, multistate_tunnel);
3334         case oRequestTTY:
3335                 return fmt_multistate_int(val, multistate_requesttty);
3336         case oSessionType:
3337                 return fmt_multistate_int(val, multistate_sessiontype);
3338         case oCanonicalizeHostname:
3339                 return fmt_multistate_int(val, multistate_canonicalizehostname);
3340         case oAddKeysToAgent:
3341                 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3342         case oPubkeyAuthentication:
3343                 return fmt_multistate_int(val, multistate_pubkey_auth);
3344         case oFingerprintHash:
3345                 return ssh_digest_alg_name(val);
3346         default:
3347                 switch (val) {
3348                 case 0:
3349                         return "no";
3350                 case 1:
3351                         return "yes";
3352                 default:
3353                         return "UNKNOWN";
3354                 }
3355         }
3356 }
3357
3358 static const char *
3359 lookup_opcode_name(OpCodes code)
3360 {
3361         u_int i;
3362
3363         for (i = 0; keywords[i].name != NULL; i++)
3364                 if (keywords[i].opcode == code)
3365                         return(keywords[i].name);
3366         return "UNKNOWN";
3367 }
3368
3369 static void
3370 dump_cfg_int(OpCodes code, int val)
3371 {
3372         if (code == oObscureKeystrokeTiming) {
3373                 if (val == 0) {
3374                         printf("%s no\n", lookup_opcode_name(code));
3375                         return;
3376                 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3377                         printf("%s yes\n", lookup_opcode_name(code));
3378                         return;
3379                 }
3380                 /* FALLTHROUGH */
3381         }
3382         printf("%s %d\n", lookup_opcode_name(code), val);
3383 }
3384
3385 static void
3386 dump_cfg_fmtint(OpCodes code, int val)
3387 {
3388         printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3389 }
3390
3391 static void
3392 dump_cfg_string(OpCodes code, const char *val)
3393 {
3394         if (val == NULL)
3395                 return;
3396         printf("%s %s\n", lookup_opcode_name(code), val);
3397 }
3398
3399 static void
3400 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3401 {
3402         u_int i;
3403
3404         for (i = 0; i < count; i++)
3405                 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3406 }
3407
3408 static void
3409 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3410 {
3411         u_int i;
3412
3413         printf("%s", lookup_opcode_name(code));
3414         if (count == 0)
3415                 printf(" none");
3416         for (i = 0; i < count; i++)
3417                 printf(" %s",  vals[i]);
3418         printf("\n");
3419 }
3420
3421 static void
3422 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3423 {
3424         const struct Forward *fwd;
3425         u_int i;
3426
3427         /* oDynamicForward */
3428         for (i = 0; i < count; i++) {
3429                 fwd = &fwds[i];
3430                 if (code == oDynamicForward && fwd->connect_host != NULL &&
3431                     strcmp(fwd->connect_host, "socks") != 0)
3432                         continue;
3433                 if (code == oLocalForward && fwd->connect_host != NULL &&
3434                     strcmp(fwd->connect_host, "socks") == 0)
3435                         continue;
3436                 printf("%s", lookup_opcode_name(code));
3437                 if (fwd->listen_port == PORT_STREAMLOCAL)
3438                         printf(" %s", fwd->listen_path);
3439                 else if (fwd->listen_host == NULL)
3440                         printf(" %d", fwd->listen_port);
3441                 else {
3442                         printf(" [%s]:%d",
3443                             fwd->listen_host, fwd->listen_port);
3444                 }
3445                 if (code != oDynamicForward) {
3446                         if (fwd->connect_port == PORT_STREAMLOCAL)
3447                                 printf(" %s", fwd->connect_path);
3448                         else if (fwd->connect_host == NULL)
3449                                 printf(" %d", fwd->connect_port);
3450                         else {
3451                                 printf(" [%s]:%d",
3452                                     fwd->connect_host, fwd->connect_port);
3453                         }
3454                 }
3455                 printf("\n");
3456         }
3457 }
3458
3459 void
3460 dump_client_config(Options *o, const char *host)
3461 {
3462         int i, r;
3463         char buf[8], *all_key;
3464
3465         /*
3466          * Expand HostKeyAlgorithms name lists. This isn't handled in
3467          * fill_default_options() like the other algorithm lists because
3468          * the host key algorithms are by default dynamically chosen based
3469          * on the host's keys found in known_hosts.
3470          */
3471         all_key = sshkey_alg_list(0, 0, 1, ',');
3472         if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3473             all_key)) != 0)
3474                 fatal_fr(r, "expand HostKeyAlgorithms");
3475         free(all_key);
3476
3477         /* Most interesting options first: user, host, port */
3478         dump_cfg_string(oHost, o->host_arg);
3479         dump_cfg_string(oUser, o->user);
3480         dump_cfg_string(oHostname, host);
3481         dump_cfg_int(oPort, o->port);
3482
3483         /* Flag options */
3484         dump_cfg_fmtint(oAddressFamily, o->address_family);
3485         dump_cfg_fmtint(oBatchMode, o->batch_mode);
3486         dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3487         dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3488         dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3489         dump_cfg_fmtint(oCompression, o->compression);
3490         dump_cfg_fmtint(oControlMaster, o->control_master);
3491         dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3492         dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3493         dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3494         dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3495         dump_cfg_fmtint(oForwardX11, o->forward_x11);
3496         dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3497         dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3498 #ifdef GSSAPI
3499         dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3500         dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3501 #endif /* GSSAPI */
3502         dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3503         dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3504         dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3505         dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3506         dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3507         dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3508         dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3509         dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3510         dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3511         dump_cfg_fmtint(oRequestTTY, o->request_tty);
3512         dump_cfg_fmtint(oSessionType, o->session_type);
3513         dump_cfg_fmtint(oStdinNull, o->stdin_null);
3514         dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3515         dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3516         dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3517         dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3518         dump_cfg_fmtint(oTunnel, o->tun_open);
3519         dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3520         dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3521         dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3522         dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3523
3524         /* Integer options */
3525         dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3526         dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3527         dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3528         dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3529         dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3530         dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3531         dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3532         dump_cfg_int(oObscureKeystrokeTiming,
3533             o->obscure_keystroke_timing_interval);
3534
3535         /* String options */
3536         dump_cfg_string(oBindAddress, o->bind_address);
3537         dump_cfg_string(oBindInterface, o->bind_interface);
3538         dump_cfg_string(oCiphers, o->ciphers);
3539         dump_cfg_string(oControlPath, o->control_path);
3540         dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3541         dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3542         dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3543         dump_cfg_string(oIdentityAgent, o->identity_agent);
3544         dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3545         dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3546         dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3547         dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3548         dump_cfg_string(oLocalCommand, o->local_command);
3549         dump_cfg_string(oRemoteCommand, o->remote_command);
3550         dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3551         dump_cfg_string(oMacs, o->macs);
3552 #ifdef ENABLE_PKCS11
3553         dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3554 #endif
3555         dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3556         dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3557         dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3558         dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3559         dump_cfg_string(oXAuthLocation, o->xauth_location);
3560         dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3561         dump_cfg_string(oTag, o->tag);
3562
3563         /* Forwards */
3564         dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3565         dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3566         dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3567
3568         /* String array options */
3569         dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3570         dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3571         dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3572         dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3573         dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3574         dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3575         dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3576         dump_cfg_strarray_oneline(oLogVerbose,
3577             o->num_log_verbose, o->log_verbose);
3578         dump_cfg_strarray_oneline(oChannelTimeout,
3579             o->num_channel_timeouts, o->channel_timeouts);
3580
3581         /* Special cases */
3582
3583         /* PermitRemoteOpen */
3584         if (o->num_permitted_remote_opens == 0)
3585                 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3586         else
3587                 dump_cfg_strarray_oneline(oPermitRemoteOpen,
3588                     o->num_permitted_remote_opens, o->permitted_remote_opens);
3589
3590         /* AddKeysToAgent */
3591         if (o->add_keys_to_agent_lifespan <= 0)
3592                 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3593         else {
3594                 printf("addkeystoagent%s %d\n",
3595                     o->add_keys_to_agent == 3 ? " confirm" : "",
3596                     o->add_keys_to_agent_lifespan);
3597         }
3598
3599         /* oForwardAgent */
3600         if (o->forward_agent_sock_path == NULL)
3601                 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3602         else
3603                 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3604
3605         /* oConnectTimeout */
3606         if (o->connection_timeout == -1)
3607                 printf("connecttimeout none\n");
3608         else
3609                 dump_cfg_int(oConnectTimeout, o->connection_timeout);
3610
3611         /* oTunnelDevice */
3612         printf("tunneldevice");
3613         if (o->tun_local == SSH_TUNID_ANY)
3614                 printf(" any");
3615         else
3616                 printf(" %d", o->tun_local);
3617         if (o->tun_remote == SSH_TUNID_ANY)
3618                 printf(":any");
3619         else
3620                 printf(":%d", o->tun_remote);
3621         printf("\n");
3622
3623         /* oCanonicalizePermittedCNAMEs */
3624         printf("canonicalizePermittedcnames");
3625         if (o->num_permitted_cnames == 0)
3626                 printf(" none");
3627         for (i = 0; i < o->num_permitted_cnames; i++) {
3628                 printf(" %s:%s", o->permitted_cnames[i].source_list,
3629                     o->permitted_cnames[i].target_list);
3630         }
3631         printf("\n");
3632
3633         /* oControlPersist */
3634         if (o->control_persist == 0 || o->control_persist_timeout == 0)
3635                 dump_cfg_fmtint(oControlPersist, o->control_persist);
3636         else
3637                 dump_cfg_int(oControlPersist, o->control_persist_timeout);
3638
3639         /* oEscapeChar */
3640         if (o->escape_char == SSH_ESCAPECHAR_NONE)
3641                 printf("escapechar none\n");
3642         else {
3643                 vis(buf, o->escape_char, VIS_WHITE, 0);
3644                 printf("escapechar %s\n", buf);
3645         }
3646
3647         /* oIPQoS */
3648         printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3649         printf("%s\n", iptos2str(o->ip_qos_bulk));
3650
3651         /* oRekeyLimit */
3652         printf("rekeylimit %llu %d\n",
3653             (unsigned long long)o->rekey_limit, o->rekey_interval);
3654
3655         /* oStreamLocalBindMask */
3656         printf("streamlocalbindmask 0%o\n",
3657             o->fwd_opts.streamlocal_bind_mask);
3658
3659         /* oLogFacility */
3660         printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3661
3662         /* oProxyCommand / oProxyJump */
3663         if (o->jump_host == NULL)
3664                 dump_cfg_string(oProxyCommand, o->proxy_command);
3665         else {
3666                 /* Check for numeric addresses */
3667                 i = strchr(o->jump_host, ':') != NULL ||
3668                     strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3669                 snprintf(buf, sizeof(buf), "%d", o->jump_port);
3670                 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3671                     /* optional additional jump spec */
3672                     o->jump_extra == NULL ? "" : o->jump_extra,
3673                     o->jump_extra == NULL ? "" : ",",
3674                     /* optional user */
3675                     o->jump_user == NULL ? "" : o->jump_user,
3676                     o->jump_user == NULL ? "" : "@",
3677                     /* opening [ if hostname is numeric */
3678                     i ? "[" : "",
3679                     /* mandatory hostname */
3680                     o->jump_host,
3681                     /* closing ] if hostname is numeric */
3682                     i ? "]" : "",
3683                     /* optional port number */
3684                     o->jump_port <= 0 ? "" : ":",
3685                     o->jump_port <= 0 ? "" : buf);
3686         }
3687 }