e26d952becb83800013a321c6c246ae78658be38
[dragonfly.git] / crypto / openssh / readconf.c
1 /* $OpenBSD: readconf.c,v 1.177 2009/06/27 09:35:06 andreas 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
21 #include <netinet/in.h>
22
23 #include <ctype.h>
24 #include <errno.h>
25 #include <netdb.h>
26 #include <signal.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "xmalloc.h"
33 #include "ssh.h"
34 #include "compat.h"
35 #include "cipher.h"
36 #include "pathnames.h"
37 #include "log.h"
38 #include "key.h"
39 #include "readconf.h"
40 #include "match.h"
41 #include "misc.h"
42 #include "buffer.h"
43 #include "kex.h"
44 #include "mac.h"
45 #include "uidswap.h"
46
47 /* Format of the configuration file:
48
49    # Configuration data is parsed as follows:
50    #  1. command line options
51    #  2. user-specific file
52    #  3. system-wide file
53    # Any configuration value is only changed the first time it is set.
54    # Thus, host-specific definitions should be at the beginning of the
55    # configuration file, and defaults at the end.
56
57    # Host-specific declarations.  These may override anything above.  A single
58    # host may match multiple declarations; these are processed in the order
59    # that they are given in.
60
61    Host *.ngs.fi ngs.fi
62      User foo
63
64    Host fake.com
65      HostName another.host.name.real.org
66      User blaah
67      Port 34289
68      ForwardX11 no
69      ForwardAgent no
70
71    Host books.com
72      RemoteForward 9999 shadows.cs.hut.fi:9999
73      Cipher 3des
74
75    Host fascist.blob.com
76      Port 23123
77      User tylonen
78      PasswordAuthentication no
79
80    Host puukko.hut.fi
81      User t35124p
82      ProxyCommand ssh-proxy %h %p
83
84    Host *.fr
85      PublicKeyAuthentication no
86
87    Host *.su
88      Cipher none
89      PasswordAuthentication no
90
91    Host vpn.fake.com
92      Tunnel yes
93      TunnelDevice 3
94
95    # Defaults for various options
96    Host *
97      ForwardAgent no
98      ForwardX11 no
99      PasswordAuthentication yes
100      RSAAuthentication yes
101      RhostsRSAAuthentication yes
102      StrictHostKeyChecking yes
103      TcpKeepAlive no
104      IdentityFile ~/.ssh/identity
105      Port 22
106      EscapeChar ~
107
108 */
109
110 /* Keyword tokens. */
111
112 typedef enum {
113         oBadOption,
114         oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
115         oExitOnForwardFailure,
116         oPasswordAuthentication, oRSAAuthentication,
117         oChallengeResponseAuthentication, oXAuthLocation,
118         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
119         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
120         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
121         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
122         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
123         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
124         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
125         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
126         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
127         oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
128         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
129         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
130         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
131         oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
132         oVersionAddendum,
133         oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
134         oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
135         oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
136         oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
137         oHPNBufferSize, oDeprecated, oUnsupported
138 } OpCodes;
139
140 /* Textual representations of the tokens. */
141
142 static struct {
143         const char *name;
144         OpCodes opcode;
145 } keywords[] = {
146         { "forwardagent", oForwardAgent },
147         { "forwardx11", oForwardX11 },
148         { "forwardx11trusted", oForwardX11Trusted },
149         { "exitonforwardfailure", oExitOnForwardFailure },
150         { "xauthlocation", oXAuthLocation },
151         { "gatewayports", oGatewayPorts },
152         { "useprivilegedport", oUsePrivilegedPort },
153         { "rhostsauthentication", oDeprecated },
154         { "passwordauthentication", oPasswordAuthentication },
155         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
156         { "kbdinteractivedevices", oKbdInteractiveDevices },
157         { "rsaauthentication", oRSAAuthentication },
158         { "pubkeyauthentication", oPubkeyAuthentication },
159         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
160         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
161         { "hostbasedauthentication", oHostbasedAuthentication },
162         { "challengeresponseauthentication", oChallengeResponseAuthentication },
163         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
164         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
165         { "kerberosauthentication", oUnsupported },
166         { "kerberostgtpassing", oUnsupported },
167         { "afstokenpassing", oUnsupported },
168 #if defined(GSSAPI)
169         { "gssapiauthentication", oGssAuthentication },
170         { "gssapidelegatecredentials", oGssDelegateCreds },
171 #else
172         { "gssapiauthentication", oUnsupported },
173         { "gssapidelegatecredentials", oUnsupported },
174 #endif
175         { "fallbacktorsh", oDeprecated },
176         { "usersh", oDeprecated },
177         { "identityfile", oIdentityFile },
178         { "identityfile2", oIdentityFile },                     /* obsolete */
179         { "identitiesonly", oIdentitiesOnly },
180         { "hostname", oHostName },
181         { "hostkeyalias", oHostKeyAlias },
182         { "proxycommand", oProxyCommand },
183         { "port", oPort },
184         { "cipher", oCipher },
185         { "ciphers", oCiphers },
186         { "macs", oMacs },
187         { "protocol", oProtocol },
188         { "remoteforward", oRemoteForward },
189         { "localforward", oLocalForward },
190         { "user", oUser },
191         { "host", oHost },
192         { "escapechar", oEscapeChar },
193         { "globalknownhostsfile", oGlobalKnownHostsFile },
194         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },    /* obsolete */
195         { "userknownhostsfile", oUserKnownHostsFile },
196         { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
197         { "connectionattempts", oConnectionAttempts },
198         { "batchmode", oBatchMode },
199         { "checkhostip", oCheckHostIP },
200         { "stricthostkeychecking", oStrictHostKeyChecking },
201         { "compression", oCompression },
202         { "compressionlevel", oCompressionLevel },
203         { "tcpkeepalive", oTCPKeepAlive },
204         { "keepalive", oTCPKeepAlive },                         /* obsolete */
205         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
206         { "loglevel", oLogLevel },
207         { "dynamicforward", oDynamicForward },
208         { "preferredauthentications", oPreferredAuthentications },
209         { "hostkeyalgorithms", oHostKeyAlgorithms },
210         { "bindaddress", oBindAddress },
211 #ifdef SMARTCARD
212         { "smartcarddevice", oSmartcardDevice },
213 #else
214         { "smartcarddevice", oUnsupported },
215 #endif
216         { "clearallforwardings", oClearAllForwardings },
217         { "enablesshkeysign", oEnableSSHKeysign },
218         { "verifyhostkeydns", oVerifyHostKeyDNS },
219         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
220         { "rekeylimit", oRekeyLimit },
221         { "connecttimeout", oConnectTimeout },
222         { "addressfamily", oAddressFamily },
223         { "serveraliveinterval", oServerAliveInterval },
224         { "serveralivecountmax", oServerAliveCountMax },
225         { "versionaddendum", oVersionAddendum },
226         { "sendenv", oSendEnv },
227         { "controlpath", oControlPath },
228         { "controlmaster", oControlMaster },
229         { "hashknownhosts", oHashKnownHosts },
230         { "tunnel", oTunnel },
231         { "tunneldevice", oTunnelDevice },
232         { "localcommand", oLocalCommand },
233         { "permitlocalcommand", oPermitLocalCommand },
234         { "visualhostkey", oVisualHostKey },
235         { "useroaming", oUseRoaming },
236 #ifdef JPAKE
237         { "zeroknowledgepasswordauthentication",
238             oZeroKnowledgePasswordAuthentication },
239 #else
240         { "zeroknowledgepasswordauthentication", oUnsupported },
241 #endif
242         { "noneenabled", oNoneEnabled },
243         { "tcprcvbufpoll", oTcpRcvBufPoll },
244         { "tcprcvbuf", oTcpRcvBuf },
245         { "noneswitch", oNoneSwitch },
246         { "hpndisabled", oHPNDisabled },
247         { "hpnbuffersize", oHPNBufferSize },
248
249         { NULL, oBadOption }
250 };
251
252 /*
253  * Adds a local TCP/IP port forward to options.  Never returns if there is an
254  * error.
255  */
256
257 void
258 add_local_forward(Options *options, const Forward *newfwd)
259 {
260         Forward *fwd;
261 #ifndef NO_IPPORT_RESERVED_CONCEPT
262         extern uid_t original_real_uid;
263         if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
264                 fatal("Privileged ports can only be forwarded by root.");
265 #endif
266         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
267                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
268         fwd = &options->local_forwards[options->num_local_forwards++];
269
270         fwd->listen_host = newfwd->listen_host;
271         fwd->listen_port = newfwd->listen_port;
272         fwd->connect_host = newfwd->connect_host;
273         fwd->connect_port = newfwd->connect_port;
274 }
275
276 /*
277  * Adds a remote TCP/IP port forward to options.  Never returns if there is
278  * an error.
279  */
280
281 void
282 add_remote_forward(Options *options, const Forward *newfwd)
283 {
284         Forward *fwd;
285         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
286                 fatal("Too many remote forwards (max %d).",
287                     SSH_MAX_FORWARDS_PER_DIRECTION);
288         fwd = &options->remote_forwards[options->num_remote_forwards++];
289
290         fwd->listen_host = newfwd->listen_host;
291         fwd->listen_port = newfwd->listen_port;
292         fwd->connect_host = newfwd->connect_host;
293         fwd->connect_port = newfwd->connect_port;
294 }
295
296 static void
297 clear_forwardings(Options *options)
298 {
299         int i;
300
301         for (i = 0; i < options->num_local_forwards; i++) {
302                 if (options->local_forwards[i].listen_host != NULL)
303                         xfree(options->local_forwards[i].listen_host);
304                 xfree(options->local_forwards[i].connect_host);
305         }
306         options->num_local_forwards = 0;
307         for (i = 0; i < options->num_remote_forwards; i++) {
308                 if (options->remote_forwards[i].listen_host != NULL)
309                         xfree(options->remote_forwards[i].listen_host);
310                 xfree(options->remote_forwards[i].connect_host);
311         }
312         options->num_remote_forwards = 0;
313         options->tun_open = SSH_TUNMODE_NO;
314 }
315
316 /*
317  * Returns the number of the token pointed to by cp or oBadOption.
318  */
319
320 static OpCodes
321 parse_token(const char *cp, const char *filename, int linenum)
322 {
323         u_int i;
324
325         for (i = 0; keywords[i].name; i++)
326                 if (strcasecmp(cp, keywords[i].name) == 0)
327                         return keywords[i].opcode;
328
329         error("%s: line %d: Bad configuration option: %s",
330             filename, linenum, cp);
331         return oBadOption;
332 }
333
334 /*
335  * Processes a single option line as used in the configuration files. This
336  * only sets those values that have not already been set.
337  */
338 #define WHITESPACE " \t\r\n"
339
340 int
341 process_config_line(Options *options, const char *host,
342                     char *line, const char *filename, int linenum,
343                     int *activep)
344 {
345         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
346         int opcode, *intptr, value, value2, scale;
347         LogLevel *log_level_ptr;
348         long long orig, val64;
349         size_t len;
350         Forward fwd;
351
352         /* Strip trailing whitespace */
353         for (len = strlen(line) - 1; len > 0; len--) {
354                 if (strchr(WHITESPACE, line[len]) == NULL)
355                         break;
356                 line[len] = '\0';
357         }
358
359         s = line;
360         /* Get the keyword. (Each line is supposed to begin with a keyword). */
361         if ((keyword = strdelim(&s)) == NULL)
362                 return 0;
363         /* Ignore leading whitespace. */
364         if (*keyword == '\0')
365                 keyword = strdelim(&s);
366         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
367                 return 0;
368
369         opcode = parse_token(keyword, filename, linenum);
370
371         switch (opcode) {
372         case oBadOption:
373                 /* don't panic, but count bad options */
374                 return -1;
375                 /* NOTREACHED */
376         case oConnectTimeout:
377                 intptr = &options->connection_timeout;
378 parse_time:
379                 arg = strdelim(&s);
380                 if (!arg || *arg == '\0')
381                         fatal("%s line %d: missing time value.",
382                             filename, linenum);
383                 if ((value = convtime(arg)) == -1)
384                         fatal("%s line %d: invalid time value.",
385                             filename, linenum);
386                 if (*activep && *intptr == -1)
387                         *intptr = value;
388                 break;
389
390         case oForwardAgent:
391                 intptr = &options->forward_agent;
392 parse_flag:
393                 arg = strdelim(&s);
394                 if (!arg || *arg == '\0')
395                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
396                 value = 0;      /* To avoid compiler warning... */
397                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
398                         value = 1;
399                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
400                         value = 0;
401                 else
402                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
403                 if (*activep && *intptr == -1)
404                         *intptr = value;
405                 break;
406
407         case oForwardX11:
408                 intptr = &options->forward_x11;
409                 goto parse_flag;
410
411         case oForwardX11Trusted:
412                 intptr = &options->forward_x11_trusted;
413                 goto parse_flag;
414
415         case oGatewayPorts:
416                 intptr = &options->gateway_ports;
417                 goto parse_flag;
418
419         case oExitOnForwardFailure:
420                 intptr = &options->exit_on_forward_failure;
421                 goto parse_flag;
422
423         case oUsePrivilegedPort:
424                 intptr = &options->use_privileged_port;
425                 goto parse_flag;
426
427         case oPasswordAuthentication:
428                 intptr = &options->password_authentication;
429                 goto parse_flag;
430
431         case oZeroKnowledgePasswordAuthentication:
432                 intptr = &options->zero_knowledge_password_authentication;
433                 goto parse_flag;
434
435         case oKbdInteractiveAuthentication:
436                 intptr = &options->kbd_interactive_authentication;
437                 goto parse_flag;
438
439         case oKbdInteractiveDevices:
440                 charptr = &options->kbd_interactive_devices;
441                 goto parse_string;
442
443         case oPubkeyAuthentication:
444                 intptr = &options->pubkey_authentication;
445                 goto parse_flag;
446
447         case oRSAAuthentication:
448                 intptr = &options->rsa_authentication;
449                 goto parse_flag;
450
451         case oRhostsRSAAuthentication:
452                 intptr = &options->rhosts_rsa_authentication;
453                 goto parse_flag;
454
455         case oHostbasedAuthentication:
456                 intptr = &options->hostbased_authentication;
457                 goto parse_flag;
458
459         case oChallengeResponseAuthentication:
460                 intptr = &options->challenge_response_authentication;
461                 goto parse_flag;
462
463         case oGssAuthentication:
464                 intptr = &options->gss_authentication;
465                 goto parse_flag;
466
467         case oGssDelegateCreds:
468                 intptr = &options->gss_deleg_creds;
469                 goto parse_flag;
470
471         case oBatchMode:
472                 intptr = &options->batch_mode;
473                 goto parse_flag;
474
475         case oCheckHostIP:
476                 intptr = &options->check_host_ip;
477                 goto parse_flag;
478
479         case oNoneEnabled:
480                 intptr = &options->none_enabled;
481                 goto parse_flag;
482
483         /* we check to see if the command comes from the */
484         /* command line or not. If it does then enable it */
485         /* otherwise fail. NONE should never be a default configuration */
486         case oNoneSwitch:
487                 if(strcmp(filename,"command-line")==0)
488                 {
489                     intptr = &options->none_switch;
490                     goto parse_flag;
491                 } else {
492                     error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
493                     error("Continuing...");
494                     debug("NoneSwitch directive found in %.200s.", filename);
495                     return 0;
496                 }
497
498         case oHPNDisabled:
499                 intptr = &options->hpn_disabled;
500                 goto parse_flag;
501
502         case oHPNBufferSize:
503                 intptr = &options->hpn_buffer_size;
504                 goto parse_int;
505
506         case oTcpRcvBufPoll:
507                 intptr = &options->tcp_rcv_buf_poll;
508                 goto parse_flag;
509
510         case oVerifyHostKeyDNS:
511                 intptr = &options->verify_host_key_dns;
512                 goto parse_yesnoask;
513
514         case oStrictHostKeyChecking:
515                 intptr = &options->strict_host_key_checking;
516 parse_yesnoask:
517                 arg = strdelim(&s);
518                 if (!arg || *arg == '\0')
519                         fatal("%.200s line %d: Missing yes/no/ask argument.",
520                             filename, linenum);
521                 value = 0;      /* To avoid compiler warning... */
522                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
523                         value = 1;
524                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
525                         value = 0;
526                 else if (strcmp(arg, "ask") == 0)
527                         value = 2;
528                 else
529                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
530                 if (*activep && *intptr == -1)
531                         *intptr = value;
532                 break;
533
534         case oCompression:
535                 intptr = &options->compression;
536                 goto parse_flag;
537
538         case oTCPKeepAlive:
539                 intptr = &options->tcp_keep_alive;
540                 goto parse_flag;
541
542         case oNoHostAuthenticationForLocalhost:
543                 intptr = &options->no_host_authentication_for_localhost;
544                 goto parse_flag;
545
546         case oNumberOfPasswordPrompts:
547                 intptr = &options->number_of_password_prompts;
548                 goto parse_int;
549
550         case oCompressionLevel:
551                 intptr = &options->compression_level;
552                 goto parse_int;
553
554         case oRekeyLimit:
555                 arg = strdelim(&s);
556                 if (!arg || *arg == '\0')
557                         fatal("%.200s line %d: Missing argument.", filename, linenum);
558                 if (arg[0] < '0' || arg[0] > '9')
559                         fatal("%.200s line %d: Bad number.", filename, linenum);
560                 orig = val64 = strtoll(arg, &endofnumber, 10);
561                 if (arg == endofnumber)
562                         fatal("%.200s line %d: Bad number.", filename, linenum);
563                 switch (toupper(*endofnumber)) {
564                 case '\0':
565                         scale = 1;
566                         break;
567                 case 'K':
568                         scale = 1<<10;
569                         break;
570                 case 'M':
571                         scale = 1<<20;
572                         break;
573                 case 'G':
574                         scale = 1<<30;
575                         break;
576                 default:
577                         fatal("%.200s line %d: Invalid RekeyLimit suffix",
578                             filename, linenum);
579                 }
580                 val64 *= scale;
581                 /* detect integer wrap and too-large limits */
582                 if ((val64 / scale) != orig || val64 > UINT_MAX)
583                         fatal("%.200s line %d: RekeyLimit too large",
584                             filename, linenum);
585                 if (val64 < 16)
586                         fatal("%.200s line %d: RekeyLimit too small",
587                             filename, linenum);
588                 if (*activep && options->rekey_limit == -1)
589                         options->rekey_limit = (u_int32_t)val64;
590                 break;
591
592         case oIdentityFile:
593                 arg = strdelim(&s);
594                 if (!arg || *arg == '\0')
595                         fatal("%.200s line %d: Missing argument.", filename, linenum);
596                 if (*activep) {
597                         intptr = &options->num_identity_files;
598                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
599                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
600                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
601                         charptr = &options->identity_files[*intptr];
602                         *charptr = xstrdup(arg);
603                         *intptr = *intptr + 1;
604                 }
605                 break;
606
607         case oXAuthLocation:
608                 charptr=&options->xauth_location;
609                 goto parse_string;
610
611         case oUser:
612                 charptr = &options->user;
613 parse_string:
614                 arg = strdelim(&s);
615                 if (!arg || *arg == '\0')
616                         fatal("%.200s line %d: Missing argument.", filename, linenum);
617                 if (*activep && *charptr == NULL)
618                         *charptr = xstrdup(arg);
619                 break;
620
621         case oGlobalKnownHostsFile:
622                 charptr = &options->system_hostfile;
623                 goto parse_string;
624
625         case oUserKnownHostsFile:
626                 charptr = &options->user_hostfile;
627                 goto parse_string;
628
629         case oGlobalKnownHostsFile2:
630                 charptr = &options->system_hostfile2;
631                 goto parse_string;
632
633         case oUserKnownHostsFile2:
634                 charptr = &options->user_hostfile2;
635                 goto parse_string;
636
637         case oHostName:
638                 charptr = &options->hostname;
639                 goto parse_string;
640
641         case oHostKeyAlias:
642                 charptr = &options->host_key_alias;
643                 goto parse_string;
644
645         case oPreferredAuthentications:
646                 charptr = &options->preferred_authentications;
647                 goto parse_string;
648
649         case oBindAddress:
650                 charptr = &options->bind_address;
651                 goto parse_string;
652
653         case oSmartcardDevice:
654                 charptr = &options->smartcard_device;
655                 goto parse_string;
656
657         case oProxyCommand:
658                 charptr = &options->proxy_command;
659 parse_command:
660                 if (s == NULL)
661                         fatal("%.200s line %d: Missing argument.", filename, linenum);
662                 len = strspn(s, WHITESPACE "=");
663                 if (*activep && *charptr == NULL)
664                         *charptr = xstrdup(s + len);
665                 return 0;
666
667         case oPort:
668                 intptr = &options->port;
669 parse_int:
670                 arg = strdelim(&s);
671                 if (!arg || *arg == '\0')
672                         fatal("%.200s line %d: Missing argument.", filename, linenum);
673                 if (arg[0] < '0' || arg[0] > '9')
674                         fatal("%.200s line %d: Bad number.", filename, linenum);
675
676                 /* Octal, decimal, or hex format? */
677                 value = strtol(arg, &endofnumber, 0);
678                 if (arg == endofnumber)
679                         fatal("%.200s line %d: Bad number.", filename, linenum);
680                 if (*activep && *intptr == -1)
681                         *intptr = value;
682                 break;
683
684         case oConnectionAttempts:
685                 intptr = &options->connection_attempts;
686                 goto parse_int;
687
688         case oTcpRcvBuf:
689                 intptr = &options->tcp_rcv_buf;
690                 goto parse_int;
691
692         case oCipher:
693                 intptr = &options->cipher;
694                 arg = strdelim(&s);
695                 if (!arg || *arg == '\0')
696                         fatal("%.200s line %d: Missing argument.", filename, linenum);
697                 value = cipher_number(arg);
698                 if (value == -1)
699                         fatal("%.200s line %d: Bad cipher '%s'.",
700                             filename, linenum, arg ? arg : "<NONE>");
701                 if (*activep && *intptr == -1)
702                         *intptr = value;
703                 break;
704
705         case oCiphers:
706                 arg = strdelim(&s);
707                 if (!arg || *arg == '\0')
708                         fatal("%.200s line %d: Missing argument.", filename, linenum);
709                 if (!ciphers_valid(arg))
710                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
711                             filename, linenum, arg ? arg : "<NONE>");
712                 if (*activep && options->ciphers == NULL)
713                         options->ciphers = xstrdup(arg);
714                 break;
715
716         case oMacs:
717                 arg = strdelim(&s);
718                 if (!arg || *arg == '\0')
719                         fatal("%.200s line %d: Missing argument.", filename, linenum);
720                 if (!mac_valid(arg))
721                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
722                             filename, linenum, arg ? arg : "<NONE>");
723                 if (*activep && options->macs == NULL)
724                         options->macs = xstrdup(arg);
725                 break;
726
727         case oHostKeyAlgorithms:
728                 arg = strdelim(&s);
729                 if (!arg || *arg == '\0')
730                         fatal("%.200s line %d: Missing argument.", filename, linenum);
731                 if (!key_names_valid2(arg))
732                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
733                             filename, linenum, arg ? arg : "<NONE>");
734                 if (*activep && options->hostkeyalgorithms == NULL)
735                         options->hostkeyalgorithms = xstrdup(arg);
736                 break;
737
738         case oProtocol:
739                 intptr = &options->protocol;
740                 arg = strdelim(&s);
741                 if (!arg || *arg == '\0')
742                         fatal("%.200s line %d: Missing argument.", filename, linenum);
743                 value = proto_spec(arg);
744                 if (value == SSH_PROTO_UNKNOWN)
745                         fatal("%.200s line %d: Bad protocol spec '%s'.",
746                             filename, linenum, arg ? arg : "<NONE>");
747                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
748                         *intptr = value;
749                 break;
750
751         case oLogLevel:
752                 log_level_ptr = &options->log_level;
753                 arg = strdelim(&s);
754                 value = log_level_number(arg);
755                 if (value == SYSLOG_LEVEL_NOT_SET)
756                         fatal("%.200s line %d: unsupported log level '%s'",
757                             filename, linenum, arg ? arg : "<NONE>");
758                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
759                         *log_level_ptr = (LogLevel) value;
760                 break;
761
762         case oLocalForward:
763         case oRemoteForward:
764         case oDynamicForward:
765                 arg = strdelim(&s);
766                 if (arg == NULL || *arg == '\0')
767                         fatal("%.200s line %d: Missing port argument.",
768                             filename, linenum);
769
770                 if (opcode == oLocalForward ||
771                     opcode == oRemoteForward) {
772                         arg2 = strdelim(&s);
773                         if (arg2 == NULL || *arg2 == '\0')
774                                 fatal("%.200s line %d: Missing target argument.",
775                                     filename, linenum);
776
777                         /* construct a string for parse_forward */
778                         snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
779                 } else if (opcode == oDynamicForward) {
780                         strlcpy(fwdarg, arg, sizeof(fwdarg));
781                 }
782
783                 if (parse_forward(&fwd, fwdarg,
784                     opcode == oDynamicForward ? 1 : 0,
785                     opcode == oRemoteForward ? 1 : 0) == 0)
786                         fatal("%.200s line %d: Bad forwarding specification.",
787                             filename, linenum);
788
789                 if (*activep) {
790                         if (opcode == oLocalForward ||
791                             opcode == oDynamicForward)
792                                 add_local_forward(options, &fwd);
793                         else if (opcode == oRemoteForward)
794                                 add_remote_forward(options, &fwd);
795                 }
796                 break;
797
798         case oClearAllForwardings:
799                 intptr = &options->clear_forwardings;
800                 goto parse_flag;
801
802         case oHost:
803                 *activep = 0;
804                 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
805                         if (match_pattern(host, arg)) {
806                                 debug("Applying options for %.100s", arg);
807                                 *activep = 1;
808                                 break;
809                         }
810                 /* Avoid garbage check below, as strdelim is done. */
811                 return 0;
812
813         case oEscapeChar:
814                 intptr = &options->escape_char;
815                 arg = strdelim(&s);
816                 if (!arg || *arg == '\0')
817                         fatal("%.200s line %d: Missing argument.", filename, linenum);
818                 if (arg[0] == '^' && arg[2] == 0 &&
819                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
820                         value = (u_char) arg[1] & 31;
821                 else if (strlen(arg) == 1)
822                         value = (u_char) arg[0];
823                 else if (strcmp(arg, "none") == 0)
824                         value = SSH_ESCAPECHAR_NONE;
825                 else {
826                         fatal("%.200s line %d: Bad escape character.",
827                             filename, linenum);
828                         /* NOTREACHED */
829                         value = 0;      /* Avoid compiler warning. */
830                 }
831                 if (*activep && *intptr == -1)
832                         *intptr = value;
833                 break;
834
835         case oAddressFamily:
836                 arg = strdelim(&s);
837                 if (!arg || *arg == '\0')
838                         fatal("%s line %d: missing address family.",
839                             filename, linenum);
840                 intptr = &options->address_family;
841                 if (strcasecmp(arg, "inet") == 0)
842                         value = AF_INET;
843                 else if (strcasecmp(arg, "inet6") == 0)
844                         value = AF_INET6;
845                 else if (strcasecmp(arg, "any") == 0)
846                         value = AF_UNSPEC;
847                 else
848                         fatal("Unsupported AddressFamily \"%s\"", arg);
849                 if (*activep && *intptr == -1)
850                         *intptr = value;
851                 break;
852
853         case oEnableSSHKeysign:
854                 intptr = &options->enable_ssh_keysign;
855                 goto parse_flag;
856
857         case oIdentitiesOnly:
858                 intptr = &options->identities_only;
859                 goto parse_flag;
860
861         case oServerAliveInterval:
862                 intptr = &options->server_alive_interval;
863                 goto parse_time;
864
865         case oServerAliveCountMax:
866                 intptr = &options->server_alive_count_max;
867                 goto parse_int;
868
869         case oVersionAddendum:
870                 ssh_version_set_addendum(strtok(s, "\n"));
871                 do {
872                         arg = strdelim(&s);
873                 } while (arg != NULL && *arg != '\0');
874                 break;
875
876         case oSendEnv:
877                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
878                         if (strchr(arg, '=') != NULL)
879                                 fatal("%s line %d: Invalid environment name.",
880                                     filename, linenum);
881                         if (!*activep)
882                                 continue;
883                         if (options->num_send_env >= MAX_SEND_ENV)
884                                 fatal("%s line %d: too many send env.",
885                                     filename, linenum);
886                         options->send_env[options->num_send_env++] =
887                             xstrdup(arg);
888                 }
889                 break;
890
891         case oControlPath:
892                 charptr = &options->control_path;
893                 goto parse_string;
894
895         case oControlMaster:
896                 intptr = &options->control_master;
897                 arg = strdelim(&s);
898                 if (!arg || *arg == '\0')
899                         fatal("%.200s line %d: Missing ControlMaster argument.",
900                             filename, linenum);
901                 value = 0;      /* To avoid compiler warning... */
902                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
903                         value = SSHCTL_MASTER_YES;
904                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
905                         value = SSHCTL_MASTER_NO;
906                 else if (strcmp(arg, "auto") == 0)
907                         value = SSHCTL_MASTER_AUTO;
908                 else if (strcmp(arg, "ask") == 0)
909                         value = SSHCTL_MASTER_ASK;
910                 else if (strcmp(arg, "autoask") == 0)
911                         value = SSHCTL_MASTER_AUTO_ASK;
912                 else
913                         fatal("%.200s line %d: Bad ControlMaster argument.",
914                             filename, linenum);
915                 if (*activep && *intptr == -1)
916                         *intptr = value;
917                 break;
918
919         case oHashKnownHosts:
920                 intptr = &options->hash_known_hosts;
921                 goto parse_flag;
922
923         case oTunnel:
924                 intptr = &options->tun_open;
925                 arg = strdelim(&s);
926                 if (!arg || *arg == '\0')
927                         fatal("%s line %d: Missing yes/point-to-point/"
928                             "ethernet/no argument.", filename, linenum);
929                 value = 0;      /* silence compiler */
930                 if (strcasecmp(arg, "ethernet") == 0)
931                         value = SSH_TUNMODE_ETHERNET;
932                 else if (strcasecmp(arg, "point-to-point") == 0)
933                         value = SSH_TUNMODE_POINTOPOINT;
934                 else if (strcasecmp(arg, "yes") == 0)
935                         value = SSH_TUNMODE_DEFAULT;
936                 else if (strcasecmp(arg, "no") == 0)
937                         value = SSH_TUNMODE_NO;
938                 else
939                         fatal("%s line %d: Bad yes/point-to-point/ethernet/"
940                             "no argument: %s", filename, linenum, arg);
941                 if (*activep)
942                         *intptr = value;
943                 break;
944
945         case oTunnelDevice:
946                 arg = strdelim(&s);
947                 if (!arg || *arg == '\0')
948                         fatal("%.200s line %d: Missing argument.", filename, linenum);
949                 value = a2tun(arg, &value2);
950                 if (value == SSH_TUNID_ERR)
951                         fatal("%.200s line %d: Bad tun device.", filename, linenum);
952                 if (*activep) {
953                         options->tun_local = value;
954                         options->tun_remote = value2;
955                 }
956                 break;
957
958         case oLocalCommand:
959                 charptr = &options->local_command;
960                 goto parse_command;
961
962         case oPermitLocalCommand:
963                 intptr = &options->permit_local_command;
964                 goto parse_flag;
965
966         case oVisualHostKey:
967                 intptr = &options->visual_host_key;
968                 goto parse_flag;
969
970         case oUseRoaming:
971                 intptr = &options->use_roaming;
972                 goto parse_flag;
973
974         case oDeprecated:
975                 debug("%s line %d: Deprecated option \"%s\"",
976                     filename, linenum, keyword);
977                 return 0;
978
979         case oUnsupported:
980                 error("%s line %d: Unsupported option \"%s\"",
981                     filename, linenum, keyword);
982                 return 0;
983
984         default:
985                 fatal("process_config_line: Unimplemented opcode %d", opcode);
986         }
987
988         /* Check that there is no garbage at end of line. */
989         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
990                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
991                     filename, linenum, arg);
992         }
993         return 0;
994 }
995
996
997 /*
998  * Reads the config file and modifies the options accordingly.  Options
999  * should already be initialized before this call.  This never returns if
1000  * there is an error.  If the file does not exist, this returns 0.
1001  */
1002
1003 int
1004 read_config_file(const char *filename, const char *host, Options *options,
1005     int checkperm)
1006 {
1007         FILE *f;
1008         char line[1024];
1009         int active, linenum;
1010         int bad_options = 0;
1011
1012         if ((f = fopen(filename, "r")) == NULL)
1013                 return 0;
1014
1015         if (checkperm) {
1016                 struct stat sb;
1017
1018                 if (fstat(fileno(f), &sb) == -1)
1019                         fatal("fstat %s: %s", filename, strerror(errno));
1020                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1021                     (sb.st_mode & 022) != 0))
1022                         fatal("Bad owner or permissions on %s", filename);
1023         }
1024
1025         debug("Reading configuration data %.200s", filename);
1026
1027         /*
1028          * Mark that we are now processing the options.  This flag is turned
1029          * on/off by Host specifications.
1030          */
1031         active = 1;
1032         linenum = 0;
1033         while (fgets(line, sizeof(line), f)) {
1034                 /* Update line number counter. */
1035                 linenum++;
1036                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1037                         bad_options++;
1038         }
1039         fclose(f);
1040         if (bad_options > 0)
1041                 fatal("%s: terminating, %d bad configuration options",
1042                     filename, bad_options);
1043         return 1;
1044 }
1045
1046 /*
1047  * Initializes options to special values that indicate that they have not yet
1048  * been set.  Read_config_file will only set options with this value. Options
1049  * are processed in the following order: command line, user config file,
1050  * system config file.  Last, fill_default_options is called.
1051  */
1052
1053 void
1054 initialize_options(Options * options)
1055 {
1056         memset(options, 'X', sizeof(*options));
1057         options->forward_agent = -1;
1058         options->forward_x11 = -1;
1059         options->forward_x11_trusted = -1;
1060         options->exit_on_forward_failure = -1;
1061         options->xauth_location = NULL;
1062         options->gateway_ports = -1;
1063         options->use_privileged_port = -1;
1064         options->rsa_authentication = -1;
1065         options->pubkey_authentication = -1;
1066         options->challenge_response_authentication = -1;
1067         options->gss_authentication = -1;
1068         options->gss_deleg_creds = -1;
1069         options->password_authentication = -1;
1070         options->kbd_interactive_authentication = -1;
1071         options->kbd_interactive_devices = NULL;
1072         options->rhosts_rsa_authentication = -1;
1073         options->hostbased_authentication = -1;
1074         options->batch_mode = -1;
1075         options->check_host_ip = -1;
1076         options->strict_host_key_checking = -1;
1077         options->compression = -1;
1078         options->tcp_keep_alive = -1;
1079         options->compression_level = -1;
1080         options->port = -1;
1081         options->address_family = -1;
1082         options->connection_attempts = -1;
1083         options->connection_timeout = -1;
1084         options->number_of_password_prompts = -1;
1085         options->cipher = -1;
1086         options->ciphers = NULL;
1087         options->macs = NULL;
1088         options->hostkeyalgorithms = NULL;
1089         options->protocol = SSH_PROTO_UNKNOWN;
1090         options->num_identity_files = 0;
1091         options->hostname = NULL;
1092         options->host_key_alias = NULL;
1093         options->proxy_command = NULL;
1094         options->user = NULL;
1095         options->escape_char = -1;
1096         options->system_hostfile = NULL;
1097         options->user_hostfile = NULL;
1098         options->system_hostfile2 = NULL;
1099         options->user_hostfile2 = NULL;
1100         options->num_local_forwards = 0;
1101         options->num_remote_forwards = 0;
1102         options->clear_forwardings = -1;
1103         options->log_level = SYSLOG_LEVEL_NOT_SET;
1104         options->preferred_authentications = NULL;
1105         options->bind_address = NULL;
1106         options->smartcard_device = NULL;
1107         options->enable_ssh_keysign = - 1;
1108         options->no_host_authentication_for_localhost = - 1;
1109         options->identities_only = - 1;
1110         options->rekey_limit = - 1;
1111         options->verify_host_key_dns = -1;
1112         options->server_alive_interval = -1;
1113         options->server_alive_count_max = -1;
1114         options->num_send_env = 0;
1115         options->control_path = NULL;
1116         options->control_master = -1;
1117         options->hash_known_hosts = -1;
1118         options->tun_open = -1;
1119         options->tun_local = -1;
1120         options->tun_remote = -1;
1121         options->local_command = NULL;
1122         options->permit_local_command = -1;
1123         options->use_roaming = -1;
1124         options->visual_host_key = -1;
1125         options->zero_knowledge_password_authentication = -1;
1126         options->none_switch = -1;
1127         options->none_enabled = -1;
1128         options->hpn_disabled = -1;
1129         options->hpn_buffer_size = -1;
1130         options->tcp_rcv_buf_poll = -1;
1131         options->tcp_rcv_buf = -1;
1132 }
1133
1134 /*
1135  * Called after processing other sources of option data, this fills those
1136  * options for which no value has been specified with their default values.
1137  */
1138
1139 void
1140 fill_default_options(Options * options)
1141 {
1142         int len;
1143
1144         if (options->forward_agent == -1)
1145                 options->forward_agent = 0;
1146         if (options->forward_x11 == -1)
1147                 options->forward_x11 = 0;
1148         if (options->forward_x11_trusted == -1)
1149                 options->forward_x11_trusted = 0;
1150         if (options->exit_on_forward_failure == -1)
1151                 options->exit_on_forward_failure = 0;
1152         if (options->xauth_location == NULL)
1153                 options->xauth_location = _PATH_XAUTH;
1154         if (options->gateway_ports == -1)
1155                 options->gateway_ports = 0;
1156         if (options->use_privileged_port == -1)
1157                 options->use_privileged_port = 0;
1158         if (options->rsa_authentication == -1)
1159                 options->rsa_authentication = 1;
1160         if (options->pubkey_authentication == -1)
1161                 options->pubkey_authentication = 1;
1162         if (options->challenge_response_authentication == -1)
1163                 options->challenge_response_authentication = 1;
1164         if (options->gss_authentication == -1)
1165                 options->gss_authentication = 0;
1166         if (options->gss_deleg_creds == -1)
1167                 options->gss_deleg_creds = 0;
1168         if (options->password_authentication == -1)
1169                 options->password_authentication = 1;
1170         if (options->kbd_interactive_authentication == -1)
1171                 options->kbd_interactive_authentication = 1;
1172         if (options->rhosts_rsa_authentication == -1)
1173                 options->rhosts_rsa_authentication = 0;
1174         if (options->hostbased_authentication == -1)
1175                 options->hostbased_authentication = 0;
1176         if (options->batch_mode == -1)
1177                 options->batch_mode = 0;
1178         if (options->check_host_ip == -1)
1179                 options->check_host_ip = 0;
1180         if (options->strict_host_key_checking == -1)
1181                 options->strict_host_key_checking = 2;  /* 2 is default */
1182         if (options->compression == -1)
1183                 options->compression = 0;
1184         if (options->tcp_keep_alive == -1)
1185                 options->tcp_keep_alive = 1;
1186         if (options->compression_level == -1)
1187                 options->compression_level = 6;
1188         if (options->port == -1)
1189                 options->port = 0;      /* Filled in ssh_connect. */
1190         if (options->address_family == -1)
1191                 options->address_family = AF_UNSPEC;
1192         if (options->connection_attempts == -1)
1193                 options->connection_attempts = 1;
1194         if (options->number_of_password_prompts == -1)
1195                 options->number_of_password_prompts = 3;
1196         /* Selected in ssh_login(). */
1197         if (options->cipher == -1)
1198                 options->cipher = SSH_CIPHER_NOT_SET;
1199         /* options->ciphers, default set in myproposals.h */
1200         /* options->macs, default set in myproposals.h */
1201         /* options->hostkeyalgorithms, default set in myproposals.h */
1202         if (options->protocol == SSH_PROTO_UNKNOWN)
1203                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1204         if (options->num_identity_files == 0) {
1205                 if (options->protocol & SSH_PROTO_1) {
1206                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1207                         options->identity_files[options->num_identity_files] =
1208                             xmalloc(len);
1209                         snprintf(options->identity_files[options->num_identity_files++],
1210                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1211                 }
1212                 if (options->protocol & SSH_PROTO_2) {
1213                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1214                         options->identity_files[options->num_identity_files] =
1215                             xmalloc(len);
1216                         snprintf(options->identity_files[options->num_identity_files++],
1217                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1218
1219                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1220                         options->identity_files[options->num_identity_files] =
1221                             xmalloc(len);
1222                         snprintf(options->identity_files[options->num_identity_files++],
1223                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1224                 }
1225         }
1226         if (options->escape_char == -1)
1227                 options->escape_char = '~';
1228         if (options->system_hostfile == NULL)
1229                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1230         if (options->user_hostfile == NULL)
1231                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1232         if (options->system_hostfile2 == NULL)
1233                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1234         if (options->user_hostfile2 == NULL)
1235                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1236         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1237                 options->log_level = SYSLOG_LEVEL_INFO;
1238         if (options->clear_forwardings == 1)
1239                 clear_forwardings(options);
1240         if (options->no_host_authentication_for_localhost == - 1)
1241                 options->no_host_authentication_for_localhost = 0;
1242         if (options->identities_only == -1)
1243                 options->identities_only = 0;
1244         if (options->enable_ssh_keysign == -1)
1245                 options->enable_ssh_keysign = 0;
1246         if (options->rekey_limit == -1)
1247                 options->rekey_limit = 0;
1248         if (options->verify_host_key_dns == -1)
1249                 options->verify_host_key_dns = 0;
1250         if (options->server_alive_interval == -1)
1251                 options->server_alive_interval = 0;
1252         if (options->server_alive_count_max == -1)
1253                 options->server_alive_count_max = 3;
1254         if (options->none_switch == -1)
1255                 options->none_switch = 0;
1256         if (options->hpn_disabled == -1)
1257                 options->hpn_disabled = 0;
1258         if (options->hpn_buffer_size > -1)
1259         {
1260           /* if a user tries to set the size to 0 set it to 1KB */
1261                 if (options->hpn_buffer_size == 0)
1262                 options->hpn_buffer_size = 1024;
1263                 /*limit the buffer to 64MB*/
1264                 if (options->hpn_buffer_size > 65536)
1265                 {
1266                         options->hpn_buffer_size = 65536*1024;
1267                         debug("User requested buffer larger than 64MB. Request reverted to 64MB");
1268                 }
1269                 debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
1270         }
1271         if (options->tcp_rcv_buf == 0)
1272                 options->tcp_rcv_buf = 1;
1273         if (options->tcp_rcv_buf > -1)
1274                 options->tcp_rcv_buf *=1024;
1275         if (options->tcp_rcv_buf_poll == -1)
1276                 options->tcp_rcv_buf_poll = 1;
1277         if (options->control_master == -1)
1278                 options->control_master = 0;
1279         if (options->hash_known_hosts == -1)
1280                 options->hash_known_hosts = 0;
1281         if (options->tun_open == -1)
1282                 options->tun_open = SSH_TUNMODE_NO;
1283         if (options->tun_local == -1)
1284                 options->tun_local = SSH_TUNID_ANY;
1285         if (options->tun_remote == -1)
1286                 options->tun_remote = SSH_TUNID_ANY;
1287         if (options->permit_local_command == -1)
1288                 options->permit_local_command = 0;
1289         if (options->use_roaming == -1)
1290                 options->use_roaming = 1;
1291         if (options->visual_host_key == -1)
1292                 options->visual_host_key = 0;
1293         if (options->zero_knowledge_password_authentication == -1)
1294                 options->zero_knowledge_password_authentication = 0;
1295         /* options->local_command should not be set by default */
1296         /* options->proxy_command should not be set by default */
1297         /* options->user will be set in the main program if appropriate */
1298         /* options->hostname will be set in the main program if appropriate */
1299         /* options->host_key_alias should not be set by default */
1300         /* options->preferred_authentications will be set in ssh */
1301 }
1302
1303 /*
1304  * parse_forward
1305  * parses a string containing a port forwarding specification of the form:
1306  *   dynamicfwd == 0
1307  *      [listenhost:]listenport:connecthost:connectport
1308  *   dynamicfwd == 1
1309  *      [listenhost:]listenport
1310  * returns number of arguments parsed or zero on error
1311  */
1312 int
1313 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1314 {
1315         int i;
1316         char *p, *cp, *fwdarg[4];
1317
1318         memset(fwd, '\0', sizeof(*fwd));
1319
1320         cp = p = xstrdup(fwdspec);
1321
1322         /* skip leading spaces */
1323         while (isspace(*cp))
1324                 cp++;
1325
1326         for (i = 0; i < 4; ++i)
1327                 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1328                         break;
1329
1330         /* Check for trailing garbage */
1331         if (cp != NULL)
1332                 i = 0;  /* failure */
1333
1334         switch (i) {
1335         case 1:
1336                 fwd->listen_host = NULL;
1337                 fwd->listen_port = a2port(fwdarg[0]);
1338                 fwd->connect_host = xstrdup("socks");
1339                 break;
1340
1341         case 2:
1342                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1343                 fwd->listen_port = a2port(fwdarg[1]);
1344                 fwd->connect_host = xstrdup("socks");
1345                 break;
1346
1347         case 3:
1348                 fwd->listen_host = NULL;
1349                 fwd->listen_port = a2port(fwdarg[0]);
1350                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1351                 fwd->connect_port = a2port(fwdarg[2]);
1352                 break;
1353
1354         case 4:
1355                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1356                 fwd->listen_port = a2port(fwdarg[1]);
1357                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1358                 fwd->connect_port = a2port(fwdarg[3]);
1359                 break;
1360         default:
1361                 i = 0; /* failure */
1362         }
1363
1364         xfree(p);
1365
1366         if (dynamicfwd) {
1367                 if (!(i == 1 || i == 2))
1368                         goto fail_free;
1369         } else {
1370                 if (!(i == 3 || i == 4))
1371                         goto fail_free;
1372                 if (fwd->connect_port <= 0)
1373                         goto fail_free;
1374         }
1375
1376         if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1377                 goto fail_free;
1378
1379         if (fwd->connect_host != NULL &&
1380             strlen(fwd->connect_host) >= NI_MAXHOST)
1381                 goto fail_free;
1382         if (fwd->listen_host != NULL &&
1383             strlen(fwd->listen_host) >= NI_MAXHOST)
1384                 goto fail_free;
1385
1386
1387         return (i);
1388
1389  fail_free:
1390         if (fwd->connect_host != NULL) {
1391                 xfree(fwd->connect_host);
1392                 fwd->connect_host = NULL;
1393         }
1394         if (fwd->listen_host != NULL) {
1395                 xfree(fwd->listen_host);
1396                 fwd->listen_host = NULL;
1397         }
1398         return (0);
1399 }