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