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