OSDN Git Service

Make the sshd directory configurable am: 3337c7067d
[android-x86/external-openssh.git] / readconf.c
1 /* $OpenBSD: readconf.c,v 1.232 2015/02/16 22:13:32 djm Exp $ */
2 /*
3  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5  *                    All rights reserved
6  * Functions for reading the configuration files.
7  *
8  * As far as I am concerned, the code I have written for this software
9  * can be used freely for any purpose.  Any derived versions of this
10  * software must be clearly marked as such, and if the derived work is
11  * incompatible with the protocol description in the RFC file, it must be
12  * called by a name other than "ssh" or "Secure Shell".
13  */
14
15 #include "includes.h"
16
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         oIgnoredUnknownOption, oDeprecated, oUnsupported
161 } OpCodes;
162
163 /* Textual representations of the tokens. */
164
165 static struct {
166         const char *name;
167         OpCodes opcode;
168 } keywords[] = {
169         { "forwardagent", oForwardAgent },
170         { "forwardx11", oForwardX11 },
171         { "forwardx11trusted", oForwardX11Trusted },
172         { "forwardx11timeout", oForwardX11Timeout },
173         { "exitonforwardfailure", oExitOnForwardFailure },
174         { "xauthlocation", oXAuthLocation },
175         { "gatewayports", oGatewayPorts },
176         { "useprivilegedport", oUsePrivilegedPort },
177         { "rhostsauthentication", oDeprecated },
178         { "passwordauthentication", oPasswordAuthentication },
179         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
180         { "kbdinteractivedevices", oKbdInteractiveDevices },
181         { "rsaauthentication", oRSAAuthentication },
182         { "pubkeyauthentication", oPubkeyAuthentication },
183         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
184         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
185         { "hostbasedauthentication", oHostbasedAuthentication },
186         { "challengeresponseauthentication", oChallengeResponseAuthentication },
187         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
188         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
189         { "kerberosauthentication", oUnsupported },
190         { "kerberostgtpassing", oUnsupported },
191         { "afstokenpassing", oUnsupported },
192 #if defined(GSSAPI)
193         { "gssapiauthentication", oGssAuthentication },
194         { "gssapidelegatecredentials", oGssDelegateCreds },
195 #else
196         { "gssapiauthentication", oUnsupported },
197         { "gssapidelegatecredentials", oUnsupported },
198 #endif
199         { "fallbacktorsh", oDeprecated },
200         { "usersh", oDeprecated },
201         { "identityfile", oIdentityFile },
202         { "identityfile2", oIdentityFile },                     /* obsolete */
203         { "identitiesonly", oIdentitiesOnly },
204         { "hostname", oHostName },
205         { "hostkeyalias", oHostKeyAlias },
206         { "proxycommand", oProxyCommand },
207         { "port", oPort },
208         { "cipher", oCipher },
209         { "ciphers", oCiphers },
210         { "macs", oMacs },
211         { "protocol", oProtocol },
212         { "remoteforward", oRemoteForward },
213         { "localforward", oLocalForward },
214         { "user", oUser },
215         { "host", oHost },
216         { "match", oMatch },
217         { "escapechar", oEscapeChar },
218         { "globalknownhostsfile", oGlobalKnownHostsFile },
219         { "globalknownhostsfile2", oDeprecated },
220         { "userknownhostsfile", oUserKnownHostsFile },
221         { "userknownhostsfile2", oDeprecated },
222         { "connectionattempts", oConnectionAttempts },
223         { "batchmode", oBatchMode },
224         { "checkhostip", oCheckHostIP },
225         { "stricthostkeychecking", oStrictHostKeyChecking },
226         { "compression", oCompression },
227         { "compressionlevel", oCompressionLevel },
228         { "tcpkeepalive", oTCPKeepAlive },
229         { "keepalive", oTCPKeepAlive },                         /* obsolete */
230         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
231         { "loglevel", oLogLevel },
232         { "dynamicforward", oDynamicForward },
233         { "preferredauthentications", oPreferredAuthentications },
234         { "hostkeyalgorithms", oHostKeyAlgorithms },
235         { "bindaddress", oBindAddress },
236 #ifdef ENABLE_PKCS11
237         { "smartcarddevice", oPKCS11Provider },
238         { "pkcs11provider", oPKCS11Provider },
239 #else
240         { "smartcarddevice", oUnsupported },
241         { "pkcs11provider", oUnsupported },
242 #endif
243         { "clearallforwardings", oClearAllForwardings },
244         { "enablesshkeysign", oEnableSSHKeysign },
245         { "verifyhostkeydns", oVerifyHostKeyDNS },
246         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
247         { "rekeylimit", oRekeyLimit },
248         { "connecttimeout", oConnectTimeout },
249         { "addressfamily", oAddressFamily },
250         { "serveraliveinterval", oServerAliveInterval },
251         { "serveralivecountmax", oServerAliveCountMax },
252         { "sendenv", oSendEnv },
253         { "controlpath", oControlPath },
254         { "controlmaster", oControlMaster },
255         { "controlpersist", oControlPersist },
256         { "hashknownhosts", oHashKnownHosts },
257         { "tunnel", oTunnel },
258         { "tunneldevice", oTunnelDevice },
259         { "localcommand", oLocalCommand },
260         { "permitlocalcommand", oPermitLocalCommand },
261         { "visualhostkey", oVisualHostKey },
262         { "useroaming", oUseRoaming },
263         { "kexalgorithms", oKexAlgorithms },
264         { "ipqos", oIPQoS },
265         { "requesttty", oRequestTTY },
266         { "proxyusefdpass", oProxyUseFdpass },
267         { "canonicaldomains", oCanonicalDomains },
268         { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
269         { "canonicalizehostname", oCanonicalizeHostname },
270         { "canonicalizemaxdots", oCanonicalizeMaxDots },
271         { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
272         { "streamlocalbindmask", oStreamLocalBindMask },
273         { "streamlocalbindunlink", oStreamLocalBindUnlink },
274         { "revokedhostkeys", oRevokedHostKeys },
275         { "fingerprinthash", oFingerprintHash },
276         { "updatehostkeys", oUpdateHostkeys },
277         { "hostbasedkeytypes", oHostbasedKeyTypes },
278         { "ignoreunknown", oIgnoreUnknown },
279
280         { NULL, oBadOption }
281 };
282
283 /*
284  * Adds a local TCP/IP port forward to options.  Never returns if there is an
285  * error.
286  */
287
288 void
289 add_local_forward(Options *options, const struct Forward *newfwd)
290 {
291         struct Forward *fwd;
292 #ifndef NO_IPPORT_RESERVED_CONCEPT
293         extern uid_t original_real_uid;
294         if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
295             newfwd->listen_path == NULL)
296                 fatal("Privileged ports can only be forwarded by root.");
297 #endif
298         options->local_forwards = xrealloc(options->local_forwards,
299             options->num_local_forwards + 1,
300             sizeof(*options->local_forwards));
301         fwd = &options->local_forwards[options->num_local_forwards++];
302
303         fwd->listen_host = newfwd->listen_host;
304         fwd->listen_port = newfwd->listen_port;
305         fwd->listen_path = newfwd->listen_path;
306         fwd->connect_host = newfwd->connect_host;
307         fwd->connect_port = newfwd->connect_port;
308         fwd->connect_path = newfwd->connect_path;
309 }
310
311 /*
312  * Adds a remote TCP/IP port forward to options.  Never returns if there is
313  * an error.
314  */
315
316 void
317 add_remote_forward(Options *options, const struct Forward *newfwd)
318 {
319         struct Forward *fwd;
320
321         options->remote_forwards = xrealloc(options->remote_forwards,
322             options->num_remote_forwards + 1,
323             sizeof(*options->remote_forwards));
324         fwd = &options->remote_forwards[options->num_remote_forwards++];
325
326         fwd->listen_host = newfwd->listen_host;
327         fwd->listen_port = newfwd->listen_port;
328         fwd->listen_path = newfwd->listen_path;
329         fwd->connect_host = newfwd->connect_host;
330         fwd->connect_port = newfwd->connect_port;
331         fwd->connect_path = newfwd->connect_path;
332         fwd->handle = newfwd->handle;
333         fwd->allocated_port = 0;
334 }
335
336 static void
337 clear_forwardings(Options *options)
338 {
339         int i;
340
341         for (i = 0; i < options->num_local_forwards; i++) {
342                 free(options->local_forwards[i].listen_host);
343                 free(options->local_forwards[i].listen_path);
344                 free(options->local_forwards[i].connect_host);
345                 free(options->local_forwards[i].connect_path);
346         }
347         if (options->num_local_forwards > 0) {
348                 free(options->local_forwards);
349                 options->local_forwards = NULL;
350         }
351         options->num_local_forwards = 0;
352         for (i = 0; i < options->num_remote_forwards; i++) {
353                 free(options->remote_forwards[i].listen_host);
354                 free(options->remote_forwards[i].listen_path);
355                 free(options->remote_forwards[i].connect_host);
356                 free(options->remote_forwards[i].connect_path);
357         }
358         if (options->num_remote_forwards > 0) {
359                 free(options->remote_forwards);
360                 options->remote_forwards = NULL;
361         }
362         options->num_remote_forwards = 0;
363         options->tun_open = SSH_TUNMODE_NO;
364 }
365
366 void
367 add_identity_file(Options *options, const char *dir, const char *filename,
368     int userprovided)
369 {
370         char *path;
371         int i;
372
373         if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
374                 fatal("Too many identity files specified (max %d)",
375                     SSH_MAX_IDENTITY_FILES);
376
377         if (dir == NULL) /* no dir, filename is absolute */
378                 path = xstrdup(filename);
379         else
380                 (void)xasprintf(&path, "%.100s%.100s", dir, filename);
381
382         /* Avoid registering duplicates */
383         for (i = 0; i < options->num_identity_files; i++) {
384                 if (options->identity_file_userprovided[i] == userprovided &&
385                     strcmp(options->identity_files[i], path) == 0) {
386                         debug2("%s: ignoring duplicate key %s", __func__, path);
387                         free(path);
388                         return;
389                 }
390         }
391
392         options->identity_file_userprovided[options->num_identity_files] =
393             userprovided;
394         options->identity_files[options->num_identity_files++] = path;
395 }
396
397 int
398 default_ssh_port(void)
399 {
400         static int port;
401         struct servent *sp;
402
403         if (port == 0) {
404                 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
405                 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
406         }
407         return port;
408 }
409
410 /*
411  * Execute a command in a shell.
412  * Return its exit status or -1 on abnormal exit.
413  */
414 static int
415 execute_in_shell(const char *cmd)
416 {
417         char *shell, *command_string;
418         pid_t pid;
419         int devnull, status;
420         extern uid_t original_real_uid;
421
422         if ((shell = getenv("SHELL")) == NULL)
423                 shell = _PATH_BSHELL;
424
425         /*
426          * Use "exec" to avoid "sh -c" processes on some platforms
427          * (e.g. Solaris)
428          */
429         xasprintf(&command_string, "exec %s", cmd);
430
431         /* Need this to redirect subprocess stdin/out */
432         if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
433                 fatal("open(/dev/null): %s", strerror(errno));
434
435         debug("Executing command: '%.500s'", cmd);
436
437         /* Fork and execute the command. */
438         if ((pid = fork()) == 0) {
439                 char *argv[4];
440
441                 /* Child.  Permanently give up superuser privileges. */
442                 permanently_drop_suid(original_real_uid);
443
444                 /* Redirect child stdin and stdout. Leave stderr */
445                 if (dup2(devnull, STDIN_FILENO) == -1)
446                         fatal("dup2: %s", strerror(errno));
447                 if (dup2(devnull, STDOUT_FILENO) == -1)
448                         fatal("dup2: %s", strerror(errno));
449                 if (devnull > STDERR_FILENO)
450                         close(devnull);
451                 closefrom(STDERR_FILENO + 1);
452
453                 argv[0] = shell;
454                 argv[1] = "-c";
455                 argv[2] = command_string;
456                 argv[3] = NULL;
457
458                 execv(argv[0], argv);
459                 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
460                 /* Die with signal to make this error apparent to parent. */
461                 signal(SIGTERM, SIG_DFL);
462                 kill(getpid(), SIGTERM);
463                 _exit(1);
464         }
465         /* Parent. */
466         if (pid < 0)
467                 fatal("%s: fork: %.100s", __func__, strerror(errno));
468
469         close(devnull);
470         free(command_string);
471
472         while (waitpid(pid, &status, 0) == -1) {
473                 if (errno != EINTR && errno != EAGAIN)
474                         fatal("%s: waitpid: %s", __func__, strerror(errno));
475         }
476         if (!WIFEXITED(status)) {
477                 error("command '%.100s' exited abnormally", cmd);
478                 return -1;
479         }
480         debug3("command returned status %d", WEXITSTATUS(status));
481         return WEXITSTATUS(status);
482 }
483
484 /*
485  * Parse and execute a Match directive.
486  */
487 static int
488 match_cfg_line(Options *options, char **condition, struct passwd *pw,
489     const char *host_arg, const char *original_host, int post_canon,
490     const char *filename, int linenum)
491 {
492         char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
493         const char *ruser;
494         int r, port, this_result, result = 1, attributes = 0, negate;
495         size_t len;
496         char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
497
498         /*
499          * Configuration is likely to be incomplete at this point so we
500          * must be prepared to use default values.
501          */
502         port = options->port <= 0 ? default_ssh_port() : options->port;
503         ruser = options->user == NULL ? pw->pw_name : options->user;
504         if (options->hostname != NULL) {
505                 /* NB. Please keep in sync with ssh.c:main() */
506                 host = percent_expand(options->hostname,
507                     "h", host_arg, (char *)NULL);
508         } else
509                 host = xstrdup(host_arg);
510
511         debug2("checking match for '%s' host %s originally %s",
512             cp, host, original_host);
513         while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
514                 criteria = NULL;
515                 this_result = 1;
516                 if ((negate = attrib[0] == '!'))
517                         attrib++;
518                 /* criteria "all" and "canonical" have no argument */
519                 if (strcasecmp(attrib, "all") == 0) {
520                         if (attributes > 1 ||
521                             ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
522                                 error("%.200s line %d: '%s' cannot be combined "
523                                     "with other Match attributes",
524                                     filename, linenum, oattrib);
525                                 result = -1;
526                                 goto out;
527                         }
528                         if (result)
529                                 result = negate ? 0 : 1;
530                         goto out;
531                 }
532                 attributes++;
533                 if (strcasecmp(attrib, "canonical") == 0) {
534                         r = !!post_canon;  /* force bitmask member to boolean */
535                         if (r == (negate ? 1 : 0))
536                                 this_result = result = 0;
537                         debug3("%.200s line %d: %smatched '%s'",
538                             filename, linenum,
539                             this_result ? "" : "not ", oattrib);
540                         continue;
541                 }
542                 /* All other criteria require an argument */
543                 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
544                         error("Missing Match criteria for %s", attrib);
545                         result = -1;
546                         goto out;
547                 }
548                 len = strlen(arg);
549                 if (strcasecmp(attrib, "host") == 0) {
550                         criteria = xstrdup(host);
551                         r = match_hostname(host, arg, len) == 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, len) == 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, len, 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, len, 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 && match_pattern_list(cp, ignored_unknown,
669             strlen(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         for (len = strlen(line) - 1; len > 0; len--) {
767                 if (strchr(WHITESPACE, line[len]) == NULL)
768                         break;
769                 line[len] = '\0';
770         }
771
772         s = line;
773         /* Get the keyword. (Each line is supposed to begin with a keyword). */
774         if ((keyword = strdelim(&s)) == NULL)
775                 return 0;
776         /* Ignore leading whitespace. */
777         if (*keyword == '\0')
778                 keyword = strdelim(&s);
779         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
780                 return 0;
781         /* Match lowercase keyword */
782         lowercase(keyword);
783
784         opcode = parse_token(keyword, filename, linenum,
785             options->ignored_unknown);
786
787         switch (opcode) {
788         case oBadOption:
789                 /* don't panic, but count bad options */
790                 return -1;
791                 /* NOTREACHED */
792         case oIgnoredUnknownOption:
793                 debug("%s line %d: Ignored unknown option \"%s\"",
794                     filename, linenum, keyword);
795                 return 0;
796         case oConnectTimeout:
797                 intptr = &options->connection_timeout;
798 parse_time:
799                 arg = strdelim(&s);
800                 if (!arg || *arg == '\0')
801                         fatal("%s line %d: missing time value.",
802                             filename, linenum);
803                 if (strcmp(arg, "none") == 0)
804                         value = -1;
805                 else if ((value = convtime(arg)) == -1)
806                         fatal("%s line %d: invalid time value.",
807                             filename, linenum);
808                 if (*activep && *intptr == -1)
809                         *intptr = value;
810                 break;
811
812         case oForwardAgent:
813                 intptr = &options->forward_agent;
814  parse_flag:
815                 multistate_ptr = multistate_flag;
816  parse_multistate:
817                 arg = strdelim(&s);
818                 if (!arg || *arg == '\0')
819                         fatal("%s line %d: missing argument.",
820                             filename, linenum);
821                 value = -1;
822                 for (i = 0; multistate_ptr[i].key != NULL; i++) {
823                         if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
824                                 value = multistate_ptr[i].value;
825                                 break;
826                         }
827                 }
828                 if (value == -1)
829                         fatal("%s line %d: unsupported option \"%s\".",
830                             filename, linenum, arg);
831                 if (*activep && *intptr == -1)
832                         *intptr = value;
833                 break;
834
835         case oForwardX11:
836                 intptr = &options->forward_x11;
837                 goto parse_flag;
838
839         case oForwardX11Trusted:
840                 intptr = &options->forward_x11_trusted;
841                 goto parse_flag;
842
843         case oForwardX11Timeout:
844                 intptr = &options->forward_x11_timeout;
845                 goto parse_time;
846
847         case oGatewayPorts:
848                 intptr = &options->fwd_opts.gateway_ports;
849                 goto parse_flag;
850
851         case oExitOnForwardFailure:
852                 intptr = &options->exit_on_forward_failure;
853                 goto parse_flag;
854
855         case oUsePrivilegedPort:
856                 intptr = &options->use_privileged_port;
857                 goto parse_flag;
858
859         case oPasswordAuthentication:
860                 intptr = &options->password_authentication;
861                 goto parse_flag;
862
863         case oKbdInteractiveAuthentication:
864                 intptr = &options->kbd_interactive_authentication;
865                 goto parse_flag;
866
867         case oKbdInteractiveDevices:
868                 charptr = &options->kbd_interactive_devices;
869                 goto parse_string;
870
871         case oPubkeyAuthentication:
872                 intptr = &options->pubkey_authentication;
873                 goto parse_flag;
874
875         case oRSAAuthentication:
876                 intptr = &options->rsa_authentication;
877                 goto parse_flag;
878
879         case oRhostsRSAAuthentication:
880                 intptr = &options->rhosts_rsa_authentication;
881                 goto parse_flag;
882
883         case oHostbasedAuthentication:
884                 intptr = &options->hostbased_authentication;
885                 goto parse_flag;
886
887         case oChallengeResponseAuthentication:
888                 intptr = &options->challenge_response_authentication;
889                 goto parse_flag;
890
891         case oGssAuthentication:
892                 intptr = &options->gss_authentication;
893                 goto parse_flag;
894
895         case oGssDelegateCreds:
896                 intptr = &options->gss_deleg_creds;
897                 goto parse_flag;
898
899         case oBatchMode:
900                 intptr = &options->batch_mode;
901                 goto parse_flag;
902
903         case oCheckHostIP:
904                 intptr = &options->check_host_ip;
905                 goto parse_flag;
906
907         case oVerifyHostKeyDNS:
908                 intptr = &options->verify_host_key_dns;
909                 multistate_ptr = multistate_yesnoask;
910                 goto parse_multistate;
911
912         case oStrictHostKeyChecking:
913                 intptr = &options->strict_host_key_checking;
914                 multistate_ptr = multistate_yesnoask;
915                 goto parse_multistate;
916
917         case oCompression:
918                 intptr = &options->compression;
919                 goto parse_flag;
920
921         case oTCPKeepAlive:
922                 intptr = &options->tcp_keep_alive;
923                 goto parse_flag;
924
925         case oNoHostAuthenticationForLocalhost:
926                 intptr = &options->no_host_authentication_for_localhost;
927                 goto parse_flag;
928
929         case oNumberOfPasswordPrompts:
930                 intptr = &options->number_of_password_prompts;
931                 goto parse_int;
932
933         case oCompressionLevel:
934                 intptr = &options->compression_level;
935                 goto parse_int;
936
937         case oRekeyLimit:
938                 arg = strdelim(&s);
939                 if (!arg || *arg == '\0')
940                         fatal("%.200s line %d: Missing argument.", filename,
941                             linenum);
942                 if (strcmp(arg, "default") == 0) {
943                         val64 = 0;
944                 } else {
945                         if (scan_scaled(arg, &val64) == -1)
946                                 fatal("%.200s line %d: Bad number '%s': %s",
947                                     filename, linenum, arg, strerror(errno));
948                         /* check for too-large or too-small limits */
949                         if (val64 > UINT_MAX)
950                                 fatal("%.200s line %d: RekeyLimit too large",
951                                     filename, linenum);
952                         if (val64 != 0 && val64 < 16)
953                                 fatal("%.200s line %d: RekeyLimit too small",
954                                     filename, linenum);
955                 }
956                 if (*activep && options->rekey_limit == -1)
957                         options->rekey_limit = (u_int32_t)val64;
958                 if (s != NULL) { /* optional rekey interval present */
959                         if (strcmp(s, "none") == 0) {
960                                 (void)strdelim(&s);     /* discard */
961                                 break;
962                         }
963                         intptr = &options->rekey_interval;
964                         goto parse_time;
965                 }
966                 break;
967
968         case oIdentityFile:
969                 arg = strdelim(&s);
970                 if (!arg || *arg == '\0')
971                         fatal("%.200s line %d: Missing argument.", filename, linenum);
972                 if (*activep) {
973                         intptr = &options->num_identity_files;
974                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
975                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
976                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
977                         add_identity_file(options, NULL,
978                             arg, flags & SSHCONF_USERCONF);
979                 }
980                 break;
981
982         case oXAuthLocation:
983                 charptr=&options->xauth_location;
984                 goto parse_string;
985
986         case oUser:
987                 charptr = &options->user;
988 parse_string:
989                 arg = strdelim(&s);
990                 if (!arg || *arg == '\0')
991                         fatal("%.200s line %d: Missing argument.",
992                             filename, linenum);
993                 if (*activep && *charptr == NULL)
994                         *charptr = xstrdup(arg);
995                 break;
996
997         case oGlobalKnownHostsFile:
998                 cpptr = (char **)&options->system_hostfiles;
999                 uintptr = &options->num_system_hostfiles;
1000                 max_entries = SSH_MAX_HOSTS_FILES;
1001 parse_char_array:
1002                 if (*activep && *uintptr == 0) {
1003                         while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1004                                 if ((*uintptr) >= max_entries)
1005                                         fatal("%s line %d: "
1006                                             "too many authorized keys files.",
1007                                             filename, linenum);
1008                                 cpptr[(*uintptr)++] = xstrdup(arg);
1009                         }
1010                 }
1011                 return 0;
1012
1013         case oUserKnownHostsFile:
1014                 cpptr = (char **)&options->user_hostfiles;
1015                 uintptr = &options->num_user_hostfiles;
1016                 max_entries = SSH_MAX_HOSTS_FILES;
1017                 goto parse_char_array;
1018
1019         case oHostName:
1020                 charptr = &options->hostname;
1021                 goto parse_string;
1022
1023         case oHostKeyAlias:
1024                 charptr = &options->host_key_alias;
1025                 goto parse_string;
1026
1027         case oPreferredAuthentications:
1028                 charptr = &options->preferred_authentications;
1029                 goto parse_string;
1030
1031         case oBindAddress:
1032                 charptr = &options->bind_address;
1033                 goto parse_string;
1034
1035         case oPKCS11Provider:
1036                 charptr = &options->pkcs11_provider;
1037                 goto parse_string;
1038
1039         case oProxyCommand:
1040                 charptr = &options->proxy_command;
1041 parse_command:
1042                 if (s == NULL)
1043                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1044                 len = strspn(s, WHITESPACE "=");
1045                 if (*activep && *charptr == NULL)
1046                         *charptr = xstrdup(s + len);
1047                 return 0;
1048
1049         case oPort:
1050                 intptr = &options->port;
1051 parse_int:
1052                 arg = strdelim(&s);
1053                 if (!arg || *arg == '\0')
1054                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1055                 if (arg[0] < '0' || arg[0] > '9')
1056                         fatal("%.200s line %d: Bad number.", filename, linenum);
1057
1058                 /* Octal, decimal, or hex format? */
1059                 value = strtol(arg, &endofnumber, 0);
1060                 if (arg == endofnumber)
1061                         fatal("%.200s line %d: Bad number.", filename, linenum);
1062                 if (*activep && *intptr == -1)
1063                         *intptr = value;
1064                 break;
1065
1066         case oConnectionAttempts:
1067                 intptr = &options->connection_attempts;
1068                 goto parse_int;
1069
1070         case oCipher:
1071                 intptr = &options->cipher;
1072                 arg = strdelim(&s);
1073                 if (!arg || *arg == '\0')
1074                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1075                 value = cipher_number(arg);
1076                 if (value == -1)
1077                         fatal("%.200s line %d: Bad cipher '%s'.",
1078                             filename, linenum, arg ? arg : "<NONE>");
1079                 if (*activep && *intptr == -1)
1080                         *intptr = value;
1081                 break;
1082
1083         case oCiphers:
1084                 arg = strdelim(&s);
1085                 if (!arg || *arg == '\0')
1086                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1087                 if (!ciphers_valid(arg))
1088                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1089                             filename, linenum, arg ? arg : "<NONE>");
1090                 if (*activep && options->ciphers == NULL)
1091                         options->ciphers = xstrdup(arg);
1092                 break;
1093
1094         case oMacs:
1095                 arg = strdelim(&s);
1096                 if (!arg || *arg == '\0')
1097                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1098                 if (!mac_valid(arg))
1099                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1100                             filename, linenum, arg ? arg : "<NONE>");
1101                 if (*activep && options->macs == NULL)
1102                         options->macs = xstrdup(arg);
1103                 break;
1104
1105         case oKexAlgorithms:
1106                 arg = strdelim(&s);
1107                 if (!arg || *arg == '\0')
1108                         fatal("%.200s line %d: Missing argument.",
1109                             filename, linenum);
1110                 if (!kex_names_valid(arg))
1111                         fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1112                             filename, linenum, arg ? arg : "<NONE>");
1113                 if (*activep && options->kex_algorithms == NULL)
1114                         options->kex_algorithms = xstrdup(arg);
1115                 break;
1116
1117         case oHostKeyAlgorithms:
1118                 arg = strdelim(&s);
1119                 if (!arg || *arg == '\0')
1120                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1121                 if (!sshkey_names_valid2(arg, 1))
1122                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
1123                             filename, linenum, arg ? arg : "<NONE>");
1124                 if (*activep && options->hostkeyalgorithms == NULL)
1125                         options->hostkeyalgorithms = xstrdup(arg);
1126                 break;
1127
1128         case oProtocol:
1129                 intptr = &options->protocol;
1130                 arg = strdelim(&s);
1131                 if (!arg || *arg == '\0')
1132                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1133                 value = proto_spec(arg);
1134                 if (value == SSH_PROTO_UNKNOWN)
1135                         fatal("%.200s line %d: Bad protocol spec '%s'.",
1136                             filename, linenum, arg ? arg : "<NONE>");
1137                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
1138                         *intptr = value;
1139                 break;
1140
1141         case oLogLevel:
1142                 log_level_ptr = &options->log_level;
1143                 arg = strdelim(&s);
1144                 value = log_level_number(arg);
1145                 if (value == SYSLOG_LEVEL_NOT_SET)
1146                         fatal("%.200s line %d: unsupported log level '%s'",
1147                             filename, linenum, arg ? arg : "<NONE>");
1148                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1149                         *log_level_ptr = (LogLevel) value;
1150                 break;
1151
1152         case oLocalForward:
1153         case oRemoteForward:
1154         case oDynamicForward:
1155                 arg = strdelim(&s);
1156                 if (arg == NULL || *arg == '\0')
1157                         fatal("%.200s line %d: Missing port argument.",
1158                             filename, linenum);
1159
1160                 if (opcode == oLocalForward ||
1161                     opcode == oRemoteForward) {
1162                         arg2 = strdelim(&s);
1163                         if (arg2 == NULL || *arg2 == '\0')
1164                                 fatal("%.200s line %d: Missing target argument.",
1165                                     filename, linenum);
1166
1167                         /* construct a string for parse_forward */
1168                         snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
1169                 } else if (opcode == oDynamicForward) {
1170                         strlcpy(fwdarg, arg, sizeof(fwdarg));
1171                 }
1172
1173                 if (parse_forward(&fwd, fwdarg,
1174                     opcode == oDynamicForward ? 1 : 0,
1175                     opcode == oRemoteForward ? 1 : 0) == 0)
1176                         fatal("%.200s line %d: Bad forwarding specification.",
1177                             filename, linenum);
1178
1179                 if (*activep) {
1180                         if (opcode == oLocalForward ||
1181                             opcode == oDynamicForward)
1182                                 add_local_forward(options, &fwd);
1183                         else if (opcode == oRemoteForward)
1184                                 add_remote_forward(options, &fwd);
1185                 }
1186                 break;
1187
1188         case oClearAllForwardings:
1189                 intptr = &options->clear_forwardings;
1190                 goto parse_flag;
1191
1192         case oHost:
1193                 if (cmdline)
1194                         fatal("Host directive not supported as a command-line "
1195                             "option");
1196                 *activep = 0;
1197                 arg2 = NULL;
1198                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1199                         negated = *arg == '!';
1200                         if (negated)
1201                                 arg++;
1202                         if (match_pattern(host, arg)) {
1203                                 if (negated) {
1204                                         debug("%.200s line %d: Skipping Host "
1205                                             "block because of negated match "
1206                                             "for %.100s", filename, linenum,
1207                                             arg);
1208                                         *activep = 0;
1209                                         break;
1210                                 }
1211                                 if (!*activep)
1212                                         arg2 = arg; /* logged below */
1213                                 *activep = 1;
1214                         }
1215                 }
1216                 if (*activep)
1217                         debug("%.200s line %d: Applying options for %.100s",
1218                             filename, linenum, arg2);
1219                 /* Avoid garbage check below, as strdelim is done. */
1220                 return 0;
1221
1222         case oMatch:
1223                 if (cmdline)
1224                         fatal("Host directive not supported as a command-line "
1225                             "option");
1226                 value = match_cfg_line(options, &s, pw, host, original_host,
1227                     flags & SSHCONF_POSTCANON, filename, linenum);
1228                 if (value < 0)
1229                         fatal("%.200s line %d: Bad Match condition", filename,
1230                             linenum);
1231                 *activep = value;
1232                 break;
1233
1234         case oEscapeChar:
1235                 intptr = &options->escape_char;
1236                 arg = strdelim(&s);
1237                 if (!arg || *arg == '\0')
1238                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1239                 if (arg[0] == '^' && arg[2] == 0 &&
1240                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1241                         value = (u_char) arg[1] & 31;
1242                 else if (strlen(arg) == 1)
1243                         value = (u_char) arg[0];
1244                 else if (strcmp(arg, "none") == 0)
1245                         value = SSH_ESCAPECHAR_NONE;
1246                 else {
1247                         fatal("%.200s line %d: Bad escape character.",
1248                             filename, linenum);
1249                         /* NOTREACHED */
1250                         value = 0;      /* Avoid compiler warning. */
1251                 }
1252                 if (*activep && *intptr == -1)
1253                         *intptr = value;
1254                 break;
1255
1256         case oAddressFamily:
1257                 intptr = &options->address_family;
1258                 multistate_ptr = multistate_addressfamily;
1259                 goto parse_multistate;
1260
1261         case oEnableSSHKeysign:
1262                 intptr = &options->enable_ssh_keysign;
1263                 goto parse_flag;
1264
1265         case oIdentitiesOnly:
1266                 intptr = &options->identities_only;
1267                 goto parse_flag;
1268
1269         case oServerAliveInterval:
1270                 intptr = &options->server_alive_interval;
1271                 goto parse_time;
1272
1273         case oServerAliveCountMax:
1274                 intptr = &options->server_alive_count_max;
1275                 goto parse_int;
1276
1277         case oSendEnv:
1278                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1279                         if (strchr(arg, '=') != NULL)
1280                                 fatal("%s line %d: Invalid environment name.",
1281                                     filename, linenum);
1282                         if (!*activep)
1283                                 continue;
1284                         if (options->num_send_env >= MAX_SEND_ENV)
1285                                 fatal("%s line %d: too many send env.",
1286                                     filename, linenum);
1287                         options->send_env[options->num_send_env++] =
1288                             xstrdup(arg);
1289                 }
1290                 break;
1291
1292         case oControlPath:
1293                 charptr = &options->control_path;
1294                 goto parse_string;
1295
1296         case oControlMaster:
1297                 intptr = &options->control_master;
1298                 multistate_ptr = multistate_controlmaster;
1299                 goto parse_multistate;
1300
1301         case oControlPersist:
1302                 /* no/false/yes/true, or a time spec */
1303                 intptr = &options->control_persist;
1304                 arg = strdelim(&s);
1305                 if (!arg || *arg == '\0')
1306                         fatal("%.200s line %d: Missing ControlPersist"
1307                             " argument.", filename, linenum);
1308                 value = 0;
1309                 value2 = 0;     /* timeout */
1310                 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1311                         value = 0;
1312                 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1313                         value = 1;
1314                 else if ((value2 = convtime(arg)) >= 0)
1315                         value = 1;
1316                 else
1317                         fatal("%.200s line %d: Bad ControlPersist argument.",
1318                             filename, linenum);
1319                 if (*activep && *intptr == -1) {
1320                         *intptr = value;
1321                         options->control_persist_timeout = value2;
1322                 }
1323                 break;
1324
1325         case oHashKnownHosts:
1326                 intptr = &options->hash_known_hosts;
1327                 goto parse_flag;
1328
1329         case oTunnel:
1330                 intptr = &options->tun_open;
1331                 multistate_ptr = multistate_tunnel;
1332                 goto parse_multistate;
1333
1334         case oTunnelDevice:
1335                 arg = strdelim(&s);
1336                 if (!arg || *arg == '\0')
1337                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1338                 value = a2tun(arg, &value2);
1339                 if (value == SSH_TUNID_ERR)
1340                         fatal("%.200s line %d: Bad tun device.", filename, linenum);
1341                 if (*activep) {
1342                         options->tun_local = value;
1343                         options->tun_remote = value2;
1344                 }
1345                 break;
1346
1347         case oLocalCommand:
1348                 charptr = &options->local_command;
1349                 goto parse_command;
1350
1351         case oPermitLocalCommand:
1352                 intptr = &options->permit_local_command;
1353                 goto parse_flag;
1354
1355         case oVisualHostKey:
1356                 intptr = &options->visual_host_key;
1357                 goto parse_flag;
1358
1359         case oIPQoS:
1360                 arg = strdelim(&s);
1361                 if ((value = parse_ipqos(arg)) == -1)
1362                         fatal("%s line %d: Bad IPQoS value: %s",
1363                             filename, linenum, arg);
1364                 arg = strdelim(&s);
1365                 if (arg == NULL)
1366                         value2 = value;
1367                 else if ((value2 = parse_ipqos(arg)) == -1)
1368                         fatal("%s line %d: Bad IPQoS value: %s",
1369                             filename, linenum, arg);
1370                 if (*activep) {
1371                         options->ip_qos_interactive = value;
1372                         options->ip_qos_bulk = value2;
1373                 }
1374                 break;
1375
1376         case oUseRoaming:
1377                 intptr = &options->use_roaming;
1378                 goto parse_flag;
1379
1380         case oRequestTTY:
1381                 intptr = &options->request_tty;
1382                 multistate_ptr = multistate_requesttty;
1383                 goto parse_multistate;
1384
1385         case oIgnoreUnknown:
1386                 charptr = &options->ignored_unknown;
1387                 goto parse_string;
1388
1389         case oProxyUseFdpass:
1390                 intptr = &options->proxy_use_fdpass;
1391                 goto parse_flag;
1392
1393         case oCanonicalDomains:
1394                 value = options->num_canonical_domains != 0;
1395                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1396                         valid_domain(arg, filename, linenum);
1397                         if (!*activep || value)
1398                                 continue;
1399                         if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1400                                 fatal("%s line %d: too many hostname suffixes.",
1401                                     filename, linenum);
1402                         options->canonical_domains[
1403                             options->num_canonical_domains++] = xstrdup(arg);
1404                 }
1405                 break;
1406
1407         case oCanonicalizePermittedCNAMEs:
1408                 value = options->num_permitted_cnames != 0;
1409                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1410                         /* Either '*' for everything or 'list:list' */
1411                         if (strcmp(arg, "*") == 0)
1412                                 arg2 = arg;
1413                         else {
1414                                 lowercase(arg);
1415                                 if ((arg2 = strchr(arg, ':')) == NULL ||
1416                                     arg2[1] == '\0') {
1417                                         fatal("%s line %d: "
1418                                             "Invalid permitted CNAME \"%s\"",
1419                                             filename, linenum, arg);
1420                                 }
1421                                 *arg2 = '\0';
1422                                 arg2++;
1423                         }
1424                         if (!*activep || value)
1425                                 continue;
1426                         if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1427                                 fatal("%s line %d: too many permitted CNAMEs.",
1428                                     filename, linenum);
1429                         cname = options->permitted_cnames +
1430                             options->num_permitted_cnames++;
1431                         cname->source_list = xstrdup(arg);
1432                         cname->target_list = xstrdup(arg2);
1433                 }
1434                 break;
1435
1436         case oCanonicalizeHostname:
1437                 intptr = &options->canonicalize_hostname;
1438                 multistate_ptr = multistate_canonicalizehostname;
1439                 goto parse_multistate;
1440
1441         case oCanonicalizeMaxDots:
1442                 intptr = &options->canonicalize_max_dots;
1443                 goto parse_int;
1444
1445         case oCanonicalizeFallbackLocal:
1446                 intptr = &options->canonicalize_fallback_local;
1447                 goto parse_flag;
1448
1449         case oStreamLocalBindMask:
1450                 arg = strdelim(&s);
1451                 if (!arg || *arg == '\0')
1452                         fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1453                 /* Parse mode in octal format */
1454                 value = strtol(arg, &endofnumber, 8);
1455                 if (arg == endofnumber || value < 0 || value > 0777)
1456                         fatal("%.200s line %d: Bad mask.", filename, linenum);
1457                 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1458                 break;
1459
1460         case oStreamLocalBindUnlink:
1461                 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1462                 goto parse_flag;
1463
1464         case oRevokedHostKeys:
1465                 charptr = &options->revoked_host_keys;
1466                 goto parse_string;
1467
1468         case oFingerprintHash:
1469                 intptr = &options->fingerprint_hash;
1470                 arg = strdelim(&s);
1471                 if (!arg || *arg == '\0')
1472                         fatal("%.200s line %d: Missing argument.",
1473                             filename, linenum);
1474                 if ((value = ssh_digest_alg_by_name(arg)) == -1)
1475                         fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1476                             filename, linenum, arg);
1477                 if (*activep && *intptr == -1)
1478                         *intptr = value;
1479                 break;
1480
1481         case oUpdateHostkeys:
1482                 intptr = &options->update_hostkeys;
1483                 multistate_ptr = multistate_yesnoask;
1484                 goto parse_multistate;
1485
1486         case oHostbasedKeyTypes:
1487                 charptr = &options->hostbased_key_types;
1488                 arg = strdelim(&s);
1489                 if (!arg || *arg == '\0')
1490                         fatal("%.200s line %d: Missing argument.",
1491                             filename, linenum);
1492                 if (!sshkey_names_valid2(arg, 1))
1493                         fatal("%s line %d: Bad key types '%s'.",
1494                                 filename, linenum, arg ? arg : "<NONE>");
1495                 if (*activep && *charptr == NULL)
1496                         *charptr = xstrdup(arg);
1497                 break;
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 }
1680
1681 /*
1682  * A petite version of fill_default_options() that just fills the options
1683  * needed for hostname canonicalization to proceed.
1684  */
1685 void
1686 fill_default_options_for_canonicalization(Options *options)
1687 {
1688         if (options->canonicalize_max_dots == -1)
1689                 options->canonicalize_max_dots = 1;
1690         if (options->canonicalize_fallback_local == -1)
1691                 options->canonicalize_fallback_local = 1;
1692         if (options->canonicalize_hostname == -1)
1693                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1694 }
1695
1696 /*
1697  * Called after processing other sources of option data, this fills those
1698  * options for which no value has been specified with their default values.
1699  */
1700 void
1701 fill_default_options(Options * options)
1702 {
1703         if (options->forward_agent == -1)
1704                 options->forward_agent = 0;
1705         if (options->forward_x11 == -1)
1706                 options->forward_x11 = 0;
1707         if (options->forward_x11_trusted == -1)
1708                 options->forward_x11_trusted = 0;
1709         if (options->forward_x11_timeout == -1)
1710                 options->forward_x11_timeout = 1200;
1711         if (options->exit_on_forward_failure == -1)
1712                 options->exit_on_forward_failure = 0;
1713         if (options->xauth_location == NULL)
1714                 options->xauth_location = _PATH_XAUTH;
1715         if (options->fwd_opts.gateway_ports == -1)
1716                 options->fwd_opts.gateway_ports = 0;
1717         if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1718                 options->fwd_opts.streamlocal_bind_mask = 0177;
1719         if (options->fwd_opts.streamlocal_bind_unlink == -1)
1720                 options->fwd_opts.streamlocal_bind_unlink = 0;
1721         if (options->use_privileged_port == -1)
1722                 options->use_privileged_port = 0;
1723         if (options->rsa_authentication == -1)
1724                 options->rsa_authentication = 1;
1725         if (options->pubkey_authentication == -1)
1726                 options->pubkey_authentication = 1;
1727         if (options->challenge_response_authentication == -1)
1728                 options->challenge_response_authentication = 1;
1729         if (options->gss_authentication == -1)
1730                 options->gss_authentication = 0;
1731         if (options->gss_deleg_creds == -1)
1732                 options->gss_deleg_creds = 0;
1733         if (options->password_authentication == -1)
1734                 options->password_authentication = 1;
1735         if (options->kbd_interactive_authentication == -1)
1736                 options->kbd_interactive_authentication = 1;
1737         if (options->rhosts_rsa_authentication == -1)
1738                 options->rhosts_rsa_authentication = 0;
1739         if (options->hostbased_authentication == -1)
1740                 options->hostbased_authentication = 0;
1741         if (options->batch_mode == -1)
1742                 options->batch_mode = 0;
1743         if (options->check_host_ip == -1)
1744                 options->check_host_ip = 1;
1745         if (options->strict_host_key_checking == -1)
1746                 options->strict_host_key_checking = 2;  /* 2 is default */
1747         if (options->compression == -1)
1748                 options->compression = 0;
1749         if (options->tcp_keep_alive == -1)
1750                 options->tcp_keep_alive = 1;
1751         if (options->compression_level == -1)
1752                 options->compression_level = 6;
1753         if (options->port == -1)
1754                 options->port = 0;      /* Filled in ssh_connect. */
1755         if (options->address_family == -1)
1756                 options->address_family = AF_UNSPEC;
1757         if (options->connection_attempts == -1)
1758                 options->connection_attempts = 1;
1759         if (options->number_of_password_prompts == -1)
1760                 options->number_of_password_prompts = 3;
1761         /* Selected in ssh_login(). */
1762         if (options->cipher == -1)
1763                 options->cipher = SSH_CIPHER_NOT_SET;
1764         /* options->ciphers, default set in myproposals.h */
1765         /* options->macs, default set in myproposals.h */
1766         /* options->kex_algorithms, default set in myproposals.h */
1767         /* options->hostkeyalgorithms, default set in myproposals.h */
1768         if (options->protocol == SSH_PROTO_UNKNOWN)
1769                 options->protocol = SSH_PROTO_2;
1770         if (options->num_identity_files == 0) {
1771                 if (options->protocol & SSH_PROTO_1) {
1772                         add_identity_file(options, "~/",
1773                             _PATH_SSH_CLIENT_IDENTITY, 0);
1774                 }
1775                 if (options->protocol & SSH_PROTO_2) {
1776                         add_identity_file(options, "~/",
1777                             _PATH_SSH_CLIENT_ID_RSA, 0);
1778                         add_identity_file(options, "~/",
1779                             _PATH_SSH_CLIENT_ID_DSA, 0);
1780 #ifdef OPENSSL_HAS_ECC
1781                         add_identity_file(options, "~/",
1782                             _PATH_SSH_CLIENT_ID_ECDSA, 0);
1783 #endif
1784                         add_identity_file(options, "~/",
1785                             _PATH_SSH_CLIENT_ID_ED25519, 0);
1786                 }
1787         }
1788         if (options->escape_char == -1)
1789                 options->escape_char = '~';
1790         if (options->num_system_hostfiles == 0) {
1791                 options->system_hostfiles[options->num_system_hostfiles++] =
1792                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1793                 options->system_hostfiles[options->num_system_hostfiles++] =
1794                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1795         }
1796         if (options->num_user_hostfiles == 0) {
1797                 options->user_hostfiles[options->num_user_hostfiles++] =
1798                     xstrdup(_PATH_SSH_USER_HOSTFILE);
1799                 options->user_hostfiles[options->num_user_hostfiles++] =
1800                     xstrdup(_PATH_SSH_USER_HOSTFILE2);
1801         }
1802         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1803                 options->log_level = SYSLOG_LEVEL_INFO;
1804         if (options->clear_forwardings == 1)
1805                 clear_forwardings(options);
1806         if (options->no_host_authentication_for_localhost == - 1)
1807                 options->no_host_authentication_for_localhost = 0;
1808         if (options->identities_only == -1)
1809                 options->identities_only = 0;
1810         if (options->enable_ssh_keysign == -1)
1811                 options->enable_ssh_keysign = 0;
1812         if (options->rekey_limit == -1)
1813                 options->rekey_limit = 0;
1814         if (options->rekey_interval == -1)
1815                 options->rekey_interval = 0;
1816         if (options->verify_host_key_dns == -1)
1817                 options->verify_host_key_dns = 0;
1818         if (options->server_alive_interval == -1)
1819                 options->server_alive_interval = 0;
1820         if (options->server_alive_count_max == -1)
1821                 options->server_alive_count_max = 3;
1822         if (options->control_master == -1)
1823                 options->control_master = 0;
1824         if (options->control_persist == -1) {
1825                 options->control_persist = 0;
1826                 options->control_persist_timeout = 0;
1827         }
1828         if (options->hash_known_hosts == -1)
1829                 options->hash_known_hosts = 0;
1830         if (options->tun_open == -1)
1831                 options->tun_open = SSH_TUNMODE_NO;
1832         if (options->tun_local == -1)
1833                 options->tun_local = SSH_TUNID_ANY;
1834         if (options->tun_remote == -1)
1835                 options->tun_remote = SSH_TUNID_ANY;
1836         if (options->permit_local_command == -1)
1837                 options->permit_local_command = 0;
1838         options->use_roaming = 0;
1839         if (options->visual_host_key == -1)
1840                 options->visual_host_key = 0;
1841         if (options->ip_qos_interactive == -1)
1842                 options->ip_qos_interactive = IPTOS_LOWDELAY;
1843         if (options->ip_qos_bulk == -1)
1844                 options->ip_qos_bulk = IPTOS_THROUGHPUT;
1845         if (options->request_tty == -1)
1846                 options->request_tty = REQUEST_TTY_AUTO;
1847         if (options->proxy_use_fdpass == -1)
1848                 options->proxy_use_fdpass = 0;
1849         if (options->canonicalize_max_dots == -1)
1850                 options->canonicalize_max_dots = 1;
1851         if (options->canonicalize_fallback_local == -1)
1852                 options->canonicalize_fallback_local = 1;
1853         if (options->canonicalize_hostname == -1)
1854                 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1855         if (options->fingerprint_hash == -1)
1856                 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
1857         if (options->update_hostkeys == -1)
1858                 options->update_hostkeys = 0;
1859         if (options->hostbased_key_types == NULL)
1860                 options->hostbased_key_types = xstrdup("*");
1861
1862 #define CLEAR_ON_NONE(v) \
1863         do { \
1864                 if (option_clear_or_none(v)) { \
1865                         free(v); \
1866                         v = NULL; \
1867                 } \
1868         } while(0)
1869         CLEAR_ON_NONE(options->local_command);
1870         CLEAR_ON_NONE(options->proxy_command);
1871         CLEAR_ON_NONE(options->control_path);
1872         CLEAR_ON_NONE(options->revoked_host_keys);
1873         /* options->user will be set in the main program if appropriate */
1874         /* options->hostname will be set in the main program if appropriate */
1875         /* options->host_key_alias should not be set by default */
1876         /* options->preferred_authentications will be set in ssh */
1877 }
1878
1879 struct fwdarg {
1880         char *arg;
1881         int ispath;
1882 };
1883
1884 /*
1885  * parse_fwd_field
1886  * parses the next field in a port forwarding specification.
1887  * sets fwd to the parsed field and advances p past the colon
1888  * or sets it to NULL at end of string.
1889  * returns 0 on success, else non-zero.
1890  */
1891 static int
1892 parse_fwd_field(char **p, struct fwdarg *fwd)
1893 {
1894         char *ep, *cp = *p;
1895         int ispath = 0;
1896
1897         if (*cp == '\0') {
1898                 *p = NULL;
1899                 return -1;      /* end of string */
1900         }
1901
1902         /*
1903          * A field escaped with square brackets is used literally.
1904          * XXX - allow ']' to be escaped via backslash?
1905          */
1906         if (*cp == '[') {
1907                 /* find matching ']' */
1908                 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1909                         if (*ep == '/')
1910                                 ispath = 1;
1911                 }
1912                 /* no matching ']' or not at end of field. */
1913                 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1914                         return -1;
1915                 /* NUL terminate the field and advance p past the colon */
1916                 *ep++ = '\0';
1917                 if (*ep != '\0')
1918                         *ep++ = '\0';
1919                 fwd->arg = cp + 1;
1920                 fwd->ispath = ispath;
1921                 *p = ep;
1922                 return 0;
1923         }
1924
1925         for (cp = *p; *cp != '\0'; cp++) {
1926                 switch (*cp) {
1927                 case '\\':
1928                         memmove(cp, cp + 1, strlen(cp + 1) + 1);
1929                         cp++;
1930                         break;
1931                 case '/':
1932                         ispath = 1;
1933                         break;
1934                 case ':':
1935                         *cp++ = '\0';
1936                         goto done;
1937                 }
1938         }
1939 done:
1940         fwd->arg = *p;
1941         fwd->ispath = ispath;
1942         *p = cp;
1943         return 0;
1944 }
1945
1946 /*
1947  * parse_forward
1948  * parses a string containing a port forwarding specification of the form:
1949  *   dynamicfwd == 0
1950  *      [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
1951  *      listenpath:connectpath
1952  *   dynamicfwd == 1
1953  *      [listenhost:]listenport
1954  * returns number of arguments parsed or zero on error
1955  */
1956 int
1957 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1958 {
1959         struct fwdarg fwdargs[4];
1960         char *p, *cp;
1961         int i;
1962
1963         memset(fwd, 0, sizeof(*fwd));
1964         memset(fwdargs, 0, sizeof(fwdargs));
1965
1966         cp = p = xstrdup(fwdspec);
1967
1968         /* skip leading spaces */
1969         while (isspace((u_char)*cp))
1970                 cp++;
1971
1972         for (i = 0; i < 4; ++i) {
1973                 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
1974                         break;
1975         }
1976
1977         /* Check for trailing garbage */
1978         if (cp != NULL && *cp != '\0') {
1979                 i = 0;  /* failure */
1980         }
1981
1982         switch (i) {
1983         case 1:
1984                 if (fwdargs[0].ispath) {
1985                         fwd->listen_path = xstrdup(fwdargs[0].arg);
1986                         fwd->listen_port = PORT_STREAMLOCAL;
1987                 } else {
1988                         fwd->listen_host = NULL;
1989                         fwd->listen_port = a2port(fwdargs[0].arg);
1990                 }
1991                 fwd->connect_host = xstrdup("socks");
1992                 break;
1993
1994         case 2:
1995                 if (fwdargs[0].ispath && fwdargs[1].ispath) {
1996                         fwd->listen_path = xstrdup(fwdargs[0].arg);
1997                         fwd->listen_port = PORT_STREAMLOCAL;
1998                         fwd->connect_path = xstrdup(fwdargs[1].arg);
1999                         fwd->connect_port = PORT_STREAMLOCAL;
2000                 } else if (fwdargs[1].ispath) {
2001                         fwd->listen_host = NULL;
2002                         fwd->listen_port = a2port(fwdargs[0].arg);
2003                         fwd->connect_path = xstrdup(fwdargs[1].arg);
2004                         fwd->connect_port = PORT_STREAMLOCAL;
2005                 } else {
2006                         fwd->listen_host = xstrdup(fwdargs[0].arg);
2007                         fwd->listen_port = a2port(fwdargs[1].arg);
2008                         fwd->connect_host = xstrdup("socks");
2009                 }
2010                 break;
2011
2012         case 3:
2013                 if (fwdargs[0].ispath) {
2014                         fwd->listen_path = xstrdup(fwdargs[0].arg);
2015                         fwd->listen_port = PORT_STREAMLOCAL;
2016                         fwd->connect_host = xstrdup(fwdargs[1].arg);
2017                         fwd->connect_port = a2port(fwdargs[2].arg);
2018                 } else if (fwdargs[2].ispath) {
2019                         fwd->listen_host = xstrdup(fwdargs[0].arg);
2020                         fwd->listen_port = a2port(fwdargs[1].arg);
2021                         fwd->connect_path = xstrdup(fwdargs[2].arg);
2022                         fwd->connect_port = PORT_STREAMLOCAL;
2023                 } else {
2024                         fwd->listen_host = NULL;
2025                         fwd->listen_port = a2port(fwdargs[0].arg);
2026                         fwd->connect_host = xstrdup(fwdargs[1].arg);
2027                         fwd->connect_port = a2port(fwdargs[2].arg);
2028                 }
2029                 break;
2030
2031         case 4:
2032                 fwd->listen_host = xstrdup(fwdargs[0].arg);
2033                 fwd->listen_port = a2port(fwdargs[1].arg);
2034                 fwd->connect_host = xstrdup(fwdargs[2].arg);
2035                 fwd->connect_port = a2port(fwdargs[3].arg);
2036                 break;
2037         default:
2038                 i = 0; /* failure */
2039         }
2040
2041         free(p);
2042
2043         if (dynamicfwd) {
2044                 if (!(i == 1 || i == 2))
2045                         goto fail_free;
2046         } else {
2047                 if (!(i == 3 || i == 4)) {
2048                         if (fwd->connect_path == NULL &&
2049                             fwd->listen_path == NULL)
2050                                 goto fail_free;
2051                 }
2052                 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2053                         goto fail_free;
2054         }
2055
2056         if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2057             (!remotefwd && fwd->listen_port == 0))
2058                 goto fail_free;
2059         if (fwd->connect_host != NULL &&
2060             strlen(fwd->connect_host) >= NI_MAXHOST)
2061                 goto fail_free;
2062         /* XXX - if connecting to a remote socket, max sun len may not match this host */
2063         if (fwd->connect_path != NULL &&
2064             strlen(fwd->connect_path) >= PATH_MAX_SUN)
2065                 goto fail_free;
2066         if (fwd->listen_host != NULL &&
2067             strlen(fwd->listen_host) >= NI_MAXHOST)
2068                 goto fail_free;
2069         if (fwd->listen_path != NULL &&
2070             strlen(fwd->listen_path) >= PATH_MAX_SUN)
2071                 goto fail_free;
2072
2073         return (i);
2074
2075  fail_free:
2076         free(fwd->connect_host);
2077         fwd->connect_host = NULL;
2078         free(fwd->connect_path);
2079         fwd->connect_path = NULL;
2080         free(fwd->listen_host);
2081         fwd->listen_host = NULL;
2082         free(fwd->listen_path);
2083         fwd->listen_path = NULL;
2084         return (0);
2085 }
2086
2087 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2088 static const char *
2089 fmt_multistate_int(int val, const struct multistate *m)
2090 {
2091         u_int i;
2092
2093         for (i = 0; m[i].key != NULL; i++) {
2094                 if (m[i].value == val)
2095                         return m[i].key;
2096         }
2097         return "UNKNOWN";
2098 }
2099
2100 static const char *
2101 fmt_intarg(OpCodes code, int val)
2102 {
2103         if (val == -1)
2104                 return "unset";
2105         switch (code) {
2106         case oAddressFamily:
2107                 return fmt_multistate_int(val, multistate_addressfamily);
2108         case oVerifyHostKeyDNS:
2109         case oStrictHostKeyChecking:
2110         case oUpdateHostkeys:
2111                 return fmt_multistate_int(val, multistate_yesnoask);
2112         case oControlMaster:
2113                 return fmt_multistate_int(val, multistate_controlmaster);
2114         case oTunnel:
2115                 return fmt_multistate_int(val, multistate_tunnel);
2116         case oRequestTTY:
2117                 return fmt_multistate_int(val, multistate_requesttty);
2118         case oCanonicalizeHostname:
2119                 return fmt_multistate_int(val, multistate_canonicalizehostname);
2120         case oFingerprintHash:
2121                 return ssh_digest_alg_name(val);
2122         case oProtocol:
2123                 switch (val) {
2124                 case SSH_PROTO_1:
2125                         return "1";
2126                 case SSH_PROTO_2:
2127                         return "2";
2128                 case (SSH_PROTO_1|SSH_PROTO_2):
2129                         return "2,1";
2130                 default:
2131                         return "UNKNOWN";
2132                 }
2133         default:
2134                 switch (val) {
2135                 case 0:
2136                         return "no";
2137                 case 1:
2138                         return "yes";
2139                 default:
2140                         return "UNKNOWN";
2141                 }
2142         }
2143 }
2144
2145 static const char *
2146 lookup_opcode_name(OpCodes code)
2147 {
2148         u_int i;
2149
2150         for (i = 0; keywords[i].name != NULL; i++)
2151                 if (keywords[i].opcode == code)
2152                         return(keywords[i].name);
2153         return "UNKNOWN";
2154 }
2155
2156 static void
2157 dump_cfg_int(OpCodes code, int val)
2158 {
2159         printf("%s %d\n", lookup_opcode_name(code), val);
2160 }
2161
2162 static void
2163 dump_cfg_fmtint(OpCodes code, int val)
2164 {
2165         printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2166 }
2167
2168 static void
2169 dump_cfg_string(OpCodes code, const char *val)
2170 {
2171         if (val == NULL)
2172                 return;
2173         printf("%s %s\n", lookup_opcode_name(code), val);
2174 }
2175
2176 static void
2177 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2178 {
2179         u_int i;
2180
2181         for (i = 0; i < count; i++)
2182                 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2183 }
2184
2185 static void
2186 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2187 {
2188         u_int i;
2189
2190         printf("%s", lookup_opcode_name(code));
2191         for (i = 0; i < count; i++)
2192                 printf(" %s",  vals[i]);
2193         printf("\n");
2194 }
2195
2196 static void
2197 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2198 {
2199         const struct Forward *fwd;
2200         u_int i;
2201
2202         /* oDynamicForward */
2203         for (i = 0; i < count; i++) {
2204                 fwd = &fwds[i];
2205                 if (code == oDynamicForward &&
2206                     strcmp(fwd->connect_host, "socks") != 0)
2207                         continue;
2208                 if (code == oLocalForward &&
2209                     strcmp(fwd->connect_host, "socks") == 0)
2210                         continue;
2211                 printf("%s", lookup_opcode_name(code));
2212                 if (fwd->listen_port == PORT_STREAMLOCAL)
2213                         printf(" %s", fwd->listen_path);
2214                 else if (fwd->listen_host == NULL)
2215                         printf(" %d", fwd->listen_port);
2216                 else {
2217                         printf(" [%s]:%d",
2218                             fwd->listen_host, fwd->listen_port);
2219                 }
2220                 if (code != oDynamicForward) {
2221                         if (fwd->connect_port == PORT_STREAMLOCAL)
2222                                 printf(" %s", fwd->connect_path);
2223                         else if (fwd->connect_host == NULL)
2224                                 printf(" %d", fwd->connect_port);
2225                         else {
2226                                 printf(" [%s]:%d",
2227                                     fwd->connect_host, fwd->connect_port);
2228                         }
2229                 }
2230                 printf("\n");
2231         }
2232 }
2233
2234 void
2235 dump_client_config(Options *o, const char *host)
2236 {
2237         int i;
2238         char vbuf[5];
2239
2240         /* Most interesting options first: user, host, port */
2241         dump_cfg_string(oUser, o->user);
2242         dump_cfg_string(oHostName, host);
2243         dump_cfg_int(oPort, o->port);
2244
2245         /* Flag options */
2246         dump_cfg_fmtint(oAddressFamily, o->address_family);
2247         dump_cfg_fmtint(oBatchMode, o->batch_mode);
2248         dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2249         dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2250         dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2251         dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2252         dump_cfg_fmtint(oCompression, o->compression);
2253         dump_cfg_fmtint(oControlMaster, o->control_master);
2254         dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2255         dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2256         dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2257         dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2258         dump_cfg_fmtint(oForwardX11, o->forward_x11);
2259         dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2260         dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2261 #ifdef GSSAPI
2262         dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2263         dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2264 #endif /* GSSAPI */
2265         dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2266         dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2267         dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2268         dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2269         dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2270         dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2271         dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2272         dump_cfg_fmtint(oProtocol, o->protocol);
2273         dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2274         dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2275         dump_cfg_fmtint(oRequestTTY, o->request_tty);
2276         dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
2277         dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
2278         dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2279         dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2280         dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2281         dump_cfg_fmtint(oTunnel, o->tun_open);
2282         dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
2283         dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2284         dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2285         dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2286
2287         /* Integer options */
2288         dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2289         dump_cfg_int(oCompressionLevel, o->compression_level);
2290         dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2291         dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2292         dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2293         dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2294         dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2295
2296         /* String options */
2297         dump_cfg_string(oBindAddress, o->bind_address);
2298         dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2299         dump_cfg_string(oControlPath, o->control_path);
2300         dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
2301         dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2302         dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2303         dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2304         dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2305         dump_cfg_string(oLocalCommand, o->local_command);
2306         dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2307         dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2308         dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2309         dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2310         dump_cfg_string(oProxyCommand, o->proxy_command);
2311         dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2312         dump_cfg_string(oXAuthLocation, o->xauth_location);
2313
2314         /* Forwards */
2315         dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2316         dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2317         dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2318
2319         /* String array options */
2320         dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2321         dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2322         dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2323         dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2324         dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2325
2326         /* Special cases */
2327
2328         /* oConnectTimeout */
2329         if (o->connection_timeout == -1)
2330                 printf("connecttimeout none\n");
2331         else
2332                 dump_cfg_int(oConnectTimeout, o->connection_timeout);
2333
2334         /* oTunnelDevice */
2335         printf("tunneldevice");
2336         if (o->tun_local == SSH_TUNID_ANY)
2337                 printf(" any");
2338         else
2339                 printf(" %d", o->tun_local);
2340         if (o->tun_remote == SSH_TUNID_ANY)
2341                 printf(":any");
2342         else
2343                 printf(":%d", o->tun_remote);
2344         printf("\n");
2345
2346         /* oCanonicalizePermittedCNAMEs */
2347         if ( o->num_permitted_cnames > 0) {
2348                 printf("canonicalizePermittedcnames");
2349                 for (i = 0; i < o->num_permitted_cnames; i++) {
2350                         printf(" %s:%s", o->permitted_cnames[i].source_list,
2351                             o->permitted_cnames[i].target_list);
2352                 }
2353                 printf("\n");
2354         }
2355
2356         /* oCipher */
2357         if (o->cipher != SSH_CIPHER_NOT_SET)
2358                 printf("Cipher %s\n", cipher_name(o->cipher));
2359
2360         /* oControlPersist */
2361         if (o->control_persist == 0 || o->control_persist_timeout == 0)
2362                 dump_cfg_fmtint(oControlPersist, o->control_persist);
2363         else
2364                 dump_cfg_int(oControlPersist, o->control_persist_timeout);
2365
2366         /* oEscapeChar */
2367         if (o->escape_char == SSH_ESCAPECHAR_NONE)
2368                 printf("escapechar none\n");
2369         else {
2370                 vis(vbuf, o->escape_char, VIS_WHITE, 0);
2371                 printf("escapechar %s\n", vbuf);
2372         }
2373
2374         /* oIPQoS */
2375         printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2376         printf("%s\n", iptos2str(o->ip_qos_bulk));
2377
2378         /* oRekeyLimit */
2379         printf("rekeylimit %lld %d\n",
2380             (long long)o->rekey_limit, o->rekey_interval);
2381
2382         /* oStreamLocalBindMask */
2383         printf("streamlocalbindmask 0%o\n",
2384             o->fwd_opts.streamlocal_bind_mask);
2385 }