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