OSDN Git Service

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