]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - crypto/openssh/readconf.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / crypto / openssh / 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 __RCSID("$FreeBSD$");
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/sysctl.h>
22
23 #include <netinet/in.h>
24
25 #include <ctype.h>
26 #include <errno.h>
27 #include <netdb.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include "xmalloc.h"
35 #include "ssh.h"
36 #include "compat.h"
37 #include "cipher.h"
38 #include "pathnames.h"
39 #include "log.h"
40 #include "key.h"
41 #include "readconf.h"
42 #include "match.h"
43 #include "misc.h"
44 #include "buffer.h"
45 #include "kex.h"
46 #include "mac.h"
47
48 /* Format of the configuration file:
49
50    # Configuration data is parsed as follows:
51    #  1. command line options
52    #  2. user-specific file
53    #  3. system-wide file
54    # Any configuration value is only changed the first time it is set.
55    # Thus, host-specific definitions should be at the beginning of the
56    # configuration file, and defaults at the end.
57
58    # Host-specific declarations.  These may override anything above.  A single
59    # host may match multiple declarations; these are processed in the order
60    # that they are given in.
61
62    Host *.ngs.fi ngs.fi
63      User foo
64
65    Host fake.com
66      HostName another.host.name.real.org
67      User blaah
68      Port 34289
69      ForwardX11 no
70      ForwardAgent no
71
72    Host books.com
73      RemoteForward 9999 shadows.cs.hut.fi:9999
74      Cipher 3des
75
76    Host fascist.blob.com
77      Port 23123
78      User tylonen
79      PasswordAuthentication no
80
81    Host puukko.hut.fi
82      User t35124p
83      ProxyCommand ssh-proxy %h %p
84
85    Host *.fr
86      PublicKeyAuthentication no
87
88    Host *.su
89      Cipher none
90      PasswordAuthentication no
91
92    Host vpn.fake.com
93      Tunnel yes
94      TunnelDevice 3
95
96    # Defaults for various options
97    Host *
98      ForwardAgent no
99      ForwardX11 no
100      PasswordAuthentication yes
101      RSAAuthentication yes
102      RhostsRSAAuthentication yes
103      StrictHostKeyChecking yes
104      TcpKeepAlive no
105      IdentityFile ~/.ssh/identity
106      Port 22
107      EscapeChar ~
108
109 */
110
111 /* Keyword tokens. */
112
113 typedef enum {
114         oBadOption,
115         oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
116         oExitOnForwardFailure,
117         oPasswordAuthentication, oRSAAuthentication,
118         oChallengeResponseAuthentication, oXAuthLocation,
119         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
120         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
121         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
122         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
123         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
124         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
125         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
126         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
127         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
128         oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
129         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
130         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
131         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
132         oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
133         oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
134         oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
135         oVisualHostKey,
136         oVersionAddendum,
137         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 },                     /* alias */
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         { "userknownhostsfile", oUserKnownHostsFile },          /* obsolete */
195         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
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         { "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         { "versionaddendum", oVersionAddendum },
235         { NULL, oBadOption }
236 };
237
238 /*
239  * Adds a local TCP/IP port forward to options.  Never returns if there is an
240  * error.
241  */
242
243 void
244 add_local_forward(Options *options, const Forward *newfwd)
245 {
246         Forward *fwd;
247 #ifndef NO_IPPORT_RESERVED_CONCEPT
248         extern uid_t original_real_uid;
249         int ipport_reserved;
250 #ifdef __FreeBSD__
251         size_t len_ipport_reserved = sizeof(ipport_reserved);
252
253         if (sysctlbyname("net.inet.ip.portrange.reservedhigh",
254             &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0)
255                 ipport_reserved = IPPORT_RESERVED;
256         else
257                 ipport_reserved++;
258 #else
259         ipport_reserved = IPPORT_RESERVED;
260 #endif
261         if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
262                 fatal("Privileged ports can only be forwarded by root.");
263 #endif
264         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
265                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
266         fwd = &options->local_forwards[options->num_local_forwards++];
267
268         fwd->listen_host = (newfwd->listen_host == NULL) ?
269             NULL : xstrdup(newfwd->listen_host);
270         fwd->listen_port = newfwd->listen_port;
271         fwd->connect_host = xstrdup(newfwd->connect_host);
272         fwd->connect_port = newfwd->connect_port;
273 }
274
275 /*
276  * Adds a remote TCP/IP port forward to options.  Never returns if there is
277  * an error.
278  */
279
280 void
281 add_remote_forward(Options *options, const Forward *newfwd)
282 {
283         Forward *fwd;
284         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
285                 fatal("Too many remote forwards (max %d).",
286                     SSH_MAX_FORWARDS_PER_DIRECTION);
287         fwd = &options->remote_forwards[options->num_remote_forwards++];
288
289         fwd->listen_host = (newfwd->listen_host == NULL) ?
290             NULL : xstrdup(newfwd->listen_host);
291         fwd->listen_port = newfwd->listen_port;
292         fwd->connect_host = xstrdup(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 oKbdInteractiveAuthentication:
432                 intptr = &options->kbd_interactive_authentication;
433                 goto parse_flag;
434
435         case oKbdInteractiveDevices:
436                 charptr = &options->kbd_interactive_devices;
437                 goto parse_string;
438
439         case oPubkeyAuthentication:
440                 intptr = &options->pubkey_authentication;
441                 goto parse_flag;
442
443         case oRSAAuthentication:
444                 intptr = &options->rsa_authentication;
445                 goto parse_flag;
446
447         case oRhostsRSAAuthentication:
448                 intptr = &options->rhosts_rsa_authentication;
449                 goto parse_flag;
450
451         case oHostbasedAuthentication:
452                 intptr = &options->hostbased_authentication;
453                 goto parse_flag;
454
455         case oChallengeResponseAuthentication:
456                 intptr = &options->challenge_response_authentication;
457                 goto parse_flag;
458
459         case oGssAuthentication:
460                 intptr = &options->gss_authentication;
461                 goto parse_flag;
462
463         case oGssDelegateCreds:
464                 intptr = &options->gss_deleg_creds;
465                 goto parse_flag;
466
467         case oBatchMode:
468                 intptr = &options->batch_mode;
469                 goto parse_flag;
470
471         case oCheckHostIP:
472                 intptr = &options->check_host_ip;
473                 goto parse_flag;
474
475         case oVerifyHostKeyDNS:
476                 intptr = &options->verify_host_key_dns;
477                 goto parse_yesnoask;
478
479         case oStrictHostKeyChecking:
480                 intptr = &options->strict_host_key_checking;
481 parse_yesnoask:
482                 arg = strdelim(&s);
483                 if (!arg || *arg == '\0')
484                         fatal("%.200s line %d: Missing yes/no/ask argument.",
485                             filename, linenum);
486                 value = 0;      /* To avoid compiler warning... */
487                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
488                         value = 1;
489                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
490                         value = 0;
491                 else if (strcmp(arg, "ask") == 0)
492                         value = 2;
493                 else
494                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
495                 if (*activep && *intptr == -1)
496                         *intptr = value;
497                 break;
498
499         case oCompression:
500                 intptr = &options->compression;
501                 goto parse_flag;
502
503         case oTCPKeepAlive:
504                 intptr = &options->tcp_keep_alive;
505                 goto parse_flag;
506
507         case oNoHostAuthenticationForLocalhost:
508                 intptr = &options->no_host_authentication_for_localhost;
509                 goto parse_flag;
510
511         case oNumberOfPasswordPrompts:
512                 intptr = &options->number_of_password_prompts;
513                 goto parse_int;
514
515         case oCompressionLevel:
516                 intptr = &options->compression_level;
517                 goto parse_int;
518
519         case oRekeyLimit:
520                 arg = strdelim(&s);
521                 if (!arg || *arg == '\0')
522                         fatal("%.200s line %d: Missing argument.", filename, linenum);
523                 if (arg[0] < '0' || arg[0] > '9')
524                         fatal("%.200s line %d: Bad number.", filename, linenum);
525                 orig = val64 = strtoll(arg, &endofnumber, 10);
526                 if (arg == endofnumber)
527                         fatal("%.200s line %d: Bad number.", filename, linenum);
528                 switch (toupper(*endofnumber)) {
529                 case '\0':
530                         scale = 1;
531                         break;
532                 case 'K':
533                         scale = 1<<10;
534                         break;
535                 case 'M':
536                         scale = 1<<20;
537                         break;
538                 case 'G':
539                         scale = 1<<30;
540                         break;
541                 default:
542                         fatal("%.200s line %d: Invalid RekeyLimit suffix",
543                             filename, linenum);
544                 }
545                 val64 *= scale;
546                 /* detect integer wrap and too-large limits */
547                 if ((val64 / scale) != orig || val64 > UINT_MAX)
548                         fatal("%.200s line %d: RekeyLimit too large",
549                             filename, linenum);
550                 if (val64 < 16)
551                         fatal("%.200s line %d: RekeyLimit too small",
552                             filename, linenum);
553                 if (*activep && options->rekey_limit == -1)
554                         options->rekey_limit = (u_int32_t)val64;
555                 break;
556
557         case oIdentityFile:
558                 arg = strdelim(&s);
559                 if (!arg || *arg == '\0')
560                         fatal("%.200s line %d: Missing argument.", filename, linenum);
561                 if (*activep) {
562                         intptr = &options->num_identity_files;
563                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
564                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
565                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
566                         charptr = &options->identity_files[*intptr];
567                         *charptr = xstrdup(arg);
568                         *intptr = *intptr + 1;
569                 }
570                 break;
571
572         case oXAuthLocation:
573                 charptr=&options->xauth_location;
574                 goto parse_string;
575
576         case oUser:
577                 charptr = &options->user;
578 parse_string:
579                 arg = strdelim(&s);
580                 if (!arg || *arg == '\0')
581                         fatal("%.200s line %d: Missing argument.", filename, linenum);
582                 if (*activep && *charptr == NULL)
583                         *charptr = xstrdup(arg);
584                 break;
585
586         case oGlobalKnownHostsFile:
587                 charptr = &options->system_hostfile;
588                 goto parse_string;
589
590         case oUserKnownHostsFile:
591                 charptr = &options->user_hostfile;
592                 goto parse_string;
593
594         case oGlobalKnownHostsFile2:
595                 charptr = &options->system_hostfile2;
596                 goto parse_string;
597
598         case oUserKnownHostsFile2:
599                 charptr = &options->user_hostfile2;
600                 goto parse_string;
601
602         case oHostName:
603                 charptr = &options->hostname;
604                 goto parse_string;
605
606         case oHostKeyAlias:
607                 charptr = &options->host_key_alias;
608                 goto parse_string;
609
610         case oPreferredAuthentications:
611                 charptr = &options->preferred_authentications;
612                 goto parse_string;
613
614         case oBindAddress:
615                 charptr = &options->bind_address;
616                 goto parse_string;
617
618         case oSmartcardDevice:
619                 charptr = &options->smartcard_device;
620                 goto parse_string;
621
622         case oProxyCommand:
623                 charptr = &options->proxy_command;
624 parse_command:
625                 if (s == NULL)
626                         fatal("%.200s line %d: Missing argument.", filename, linenum);
627                 len = strspn(s, WHITESPACE "=");
628                 if (*activep && *charptr == NULL)
629                         *charptr = xstrdup(s + len);
630                 return 0;
631
632         case oPort:
633                 intptr = &options->port;
634 parse_int:
635                 arg = strdelim(&s);
636                 if (!arg || *arg == '\0')
637                         fatal("%.200s line %d: Missing argument.", filename, linenum);
638                 if (arg[0] < '0' || arg[0] > '9')
639                         fatal("%.200s line %d: Bad number.", filename, linenum);
640
641                 /* Octal, decimal, or hex format? */
642                 value = strtol(arg, &endofnumber, 0);
643                 if (arg == endofnumber)
644                         fatal("%.200s line %d: Bad number.", filename, linenum);
645                 if (*activep && *intptr == -1)
646                         *intptr = value;
647                 break;
648
649         case oConnectionAttempts:
650                 intptr = &options->connection_attempts;
651                 goto parse_int;
652
653         case oCipher:
654                 intptr = &options->cipher;
655                 arg = strdelim(&s);
656                 if (!arg || *arg == '\0')
657                         fatal("%.200s line %d: Missing argument.", filename, linenum);
658                 value = cipher_number(arg);
659                 if (value == -1)
660                         fatal("%.200s line %d: Bad cipher '%s'.",
661                             filename, linenum, arg ? arg : "<NONE>");
662                 if (*activep && *intptr == -1)
663                         *intptr = value;
664                 break;
665
666         case oCiphers:
667                 arg = strdelim(&s);
668                 if (!arg || *arg == '\0')
669                         fatal("%.200s line %d: Missing argument.", filename, linenum);
670                 if (!ciphers_valid(arg))
671                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
672                             filename, linenum, arg ? arg : "<NONE>");
673                 if (*activep && options->ciphers == NULL)
674                         options->ciphers = xstrdup(arg);
675                 break;
676
677         case oMacs:
678                 arg = strdelim(&s);
679                 if (!arg || *arg == '\0')
680                         fatal("%.200s line %d: Missing argument.", filename, linenum);
681                 if (!mac_valid(arg))
682                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
683                             filename, linenum, arg ? arg : "<NONE>");
684                 if (*activep && options->macs == NULL)
685                         options->macs = xstrdup(arg);
686                 break;
687
688         case oHostKeyAlgorithms:
689                 arg = strdelim(&s);
690                 if (!arg || *arg == '\0')
691                         fatal("%.200s line %d: Missing argument.", filename, linenum);
692                 if (!key_names_valid2(arg))
693                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
694                             filename, linenum, arg ? arg : "<NONE>");
695                 if (*activep && options->hostkeyalgorithms == NULL)
696                         options->hostkeyalgorithms = xstrdup(arg);
697                 break;
698
699         case oProtocol:
700                 intptr = &options->protocol;
701                 arg = strdelim(&s);
702                 if (!arg || *arg == '\0')
703                         fatal("%.200s line %d: Missing argument.", filename, linenum);
704                 value = proto_spec(arg);
705                 if (value == SSH_PROTO_UNKNOWN)
706                         fatal("%.200s line %d: Bad protocol spec '%s'.",
707                             filename, linenum, arg ? arg : "<NONE>");
708                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
709                         *intptr = value;
710                 break;
711
712         case oLogLevel:
713                 log_level_ptr = &options->log_level;
714                 arg = strdelim(&s);
715                 value = log_level_number(arg);
716                 if (value == SYSLOG_LEVEL_NOT_SET)
717                         fatal("%.200s line %d: unsupported log level '%s'",
718                             filename, linenum, arg ? arg : "<NONE>");
719                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
720                         *log_level_ptr = (LogLevel) value;
721                 break;
722
723         case oLocalForward:
724         case oRemoteForward:
725                 arg = strdelim(&s);
726                 if (arg == NULL || *arg == '\0')
727                         fatal("%.200s line %d: Missing port argument.",
728                             filename, linenum);
729                 arg2 = strdelim(&s);
730                 if (arg2 == NULL || *arg2 == '\0')
731                         fatal("%.200s line %d: Missing target argument.",
732                             filename, linenum);
733
734                 /* construct a string for parse_forward */
735                 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
736
737                 if (parse_forward(&fwd, fwdarg) == 0)
738                         fatal("%.200s line %d: Bad forwarding specification.",
739                             filename, linenum);
740
741                 if (*activep) {
742                         if (opcode == oLocalForward)
743                                 add_local_forward(options, &fwd);
744                         else if (opcode == oRemoteForward)
745                                 add_remote_forward(options, &fwd);
746                 }
747                 break;
748
749         case oDynamicForward:
750                 arg = strdelim(&s);
751                 if (!arg || *arg == '\0')
752                         fatal("%.200s line %d: Missing port argument.",
753                             filename, linenum);
754                 memset(&fwd, '\0', sizeof(fwd));
755                 fwd.connect_host = "socks";
756                 fwd.listen_host = hpdelim(&arg);
757                 if (fwd.listen_host == NULL ||
758                     strlen(fwd.listen_host) >= NI_MAXHOST)
759                         fatal("%.200s line %d: Bad forwarding specification.",
760                             filename, linenum);
761                 if (arg) {
762                         fwd.listen_port = a2port(arg);
763                         fwd.listen_host = cleanhostname(fwd.listen_host);
764                 } else {
765                         fwd.listen_port = a2port(fwd.listen_host);
766                         fwd.listen_host = NULL;
767                 }
768                 if (fwd.listen_port == 0)
769                         fatal("%.200s line %d: Badly formatted port number.",
770                             filename, linenum);
771                 if (*activep)
772                         add_local_forward(options, &fwd);
773                 break;
774
775         case oClearAllForwardings:
776                 intptr = &options->clear_forwardings;
777                 goto parse_flag;
778
779         case oHost:
780                 *activep = 0;
781                 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
782                         if (match_pattern(host, arg)) {
783                                 debug("Applying options for %.100s", arg);
784                                 *activep = 1;
785                                 break;
786                         }
787                 /* Avoid garbage check below, as strdelim is done. */
788                 return 0;
789
790         case oEscapeChar:
791                 intptr = &options->escape_char;
792                 arg = strdelim(&s);
793                 if (!arg || *arg == '\0')
794                         fatal("%.200s line %d: Missing argument.", filename, linenum);
795                 if (arg[0] == '^' && arg[2] == 0 &&
796                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
797                         value = (u_char) arg[1] & 31;
798                 else if (strlen(arg) == 1)
799                         value = (u_char) arg[0];
800                 else if (strcmp(arg, "none") == 0)
801                         value = SSH_ESCAPECHAR_NONE;
802                 else {
803                         fatal("%.200s line %d: Bad escape character.",
804                             filename, linenum);
805                         /* NOTREACHED */
806                         value = 0;      /* Avoid compiler warning. */
807                 }
808                 if (*activep && *intptr == -1)
809                         *intptr = value;
810                 break;
811
812         case oAddressFamily:
813                 arg = strdelim(&s);
814                 if (!arg || *arg == '\0')
815                         fatal("%s line %d: missing address family.",
816                             filename, linenum);
817                 intptr = &options->address_family;
818                 if (strcasecmp(arg, "inet") == 0)
819                         value = AF_INET;
820                 else if (strcasecmp(arg, "inet6") == 0)
821                         value = AF_INET6;
822                 else if (strcasecmp(arg, "any") == 0)
823                         value = AF_UNSPEC;
824                 else
825                         fatal("Unsupported AddressFamily \"%s\"", arg);
826                 if (*activep && *intptr == -1)
827                         *intptr = value;
828                 break;
829
830         case oEnableSSHKeysign:
831                 intptr = &options->enable_ssh_keysign;
832                 goto parse_flag;
833
834         case oIdentitiesOnly:
835                 intptr = &options->identities_only;
836                 goto parse_flag;
837
838         case oServerAliveInterval:
839                 intptr = &options->server_alive_interval;
840                 goto parse_time;
841
842         case oServerAliveCountMax:
843                 intptr = &options->server_alive_count_max;
844                 goto parse_int;
845
846         case oSendEnv:
847                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
848                         if (strchr(arg, '=') != NULL)
849                                 fatal("%s line %d: Invalid environment name.",
850                                     filename, linenum);
851                         if (!*activep)
852                                 continue;
853                         if (options->num_send_env >= MAX_SEND_ENV)
854                                 fatal("%s line %d: too many send env.",
855                                     filename, linenum);
856                         options->send_env[options->num_send_env++] =
857                             xstrdup(arg);
858                 }
859                 break;
860
861         case oControlPath:
862                 charptr = &options->control_path;
863                 goto parse_string;
864
865         case oControlMaster:
866                 intptr = &options->control_master;
867                 arg = strdelim(&s);
868                 if (!arg || *arg == '\0')
869                         fatal("%.200s line %d: Missing ControlMaster argument.",
870                             filename, linenum);
871                 value = 0;      /* To avoid compiler warning... */
872                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
873                         value = SSHCTL_MASTER_YES;
874                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
875                         value = SSHCTL_MASTER_NO;
876                 else if (strcmp(arg, "auto") == 0)
877                         value = SSHCTL_MASTER_AUTO;
878                 else if (strcmp(arg, "ask") == 0)
879                         value = SSHCTL_MASTER_ASK;
880                 else if (strcmp(arg, "autoask") == 0)
881                         value = SSHCTL_MASTER_AUTO_ASK;
882                 else
883                         fatal("%.200s line %d: Bad ControlMaster argument.",
884                             filename, linenum);
885                 if (*activep && *intptr == -1)
886                         *intptr = value;
887                 break;
888
889         case oHashKnownHosts:
890                 intptr = &options->hash_known_hosts;
891                 goto parse_flag;
892
893         case oTunnel:
894                 intptr = &options->tun_open;
895                 arg = strdelim(&s);
896                 if (!arg || *arg == '\0')
897                         fatal("%s line %d: Missing yes/point-to-point/"
898                             "ethernet/no argument.", filename, linenum);
899                 value = 0;      /* silence compiler */
900                 if (strcasecmp(arg, "ethernet") == 0)
901                         value = SSH_TUNMODE_ETHERNET;
902                 else if (strcasecmp(arg, "point-to-point") == 0)
903                         value = SSH_TUNMODE_POINTOPOINT;
904                 else if (strcasecmp(arg, "yes") == 0)
905                         value = SSH_TUNMODE_DEFAULT;
906                 else if (strcasecmp(arg, "no") == 0)
907                         value = SSH_TUNMODE_NO;
908                 else
909                         fatal("%s line %d: Bad yes/point-to-point/ethernet/"
910                             "no argument: %s", filename, linenum, arg);
911                 if (*activep)
912                         *intptr = value;
913                 break;
914
915         case oTunnelDevice:
916                 arg = strdelim(&s);
917                 if (!arg || *arg == '\0')
918                         fatal("%.200s line %d: Missing argument.", filename, linenum);
919                 value = a2tun(arg, &value2);
920                 if (value == SSH_TUNID_ERR)
921                         fatal("%.200s line %d: Bad tun device.", filename, linenum);
922                 if (*activep) {
923                         options->tun_local = value;
924                         options->tun_remote = value2;
925                 }
926                 break;
927
928         case oLocalCommand:
929                 charptr = &options->local_command;
930                 goto parse_command;
931
932         case oPermitLocalCommand:
933                 intptr = &options->permit_local_command;
934                 goto parse_flag;
935
936         case oVisualHostKey:
937                 intptr = &options->visual_host_key;
938                 goto parse_flag;
939
940         case oVersionAddendum:
941                 ssh_version_set_addendum(strtok(s, "\n"));
942                 do {
943                         arg = strdelim(&s);
944                 } while (arg != NULL && *arg != '\0');
945                 break;
946
947         case oDeprecated:
948                 debug("%s line %d: Deprecated option \"%s\"",
949                     filename, linenum, keyword);
950                 return 0;
951
952         case oUnsupported:
953                 error("%s line %d: Unsupported option \"%s\"",
954                     filename, linenum, keyword);
955                 return 0;
956
957         default:
958                 fatal("process_config_line: Unimplemented opcode %d", opcode);
959         }
960
961         /* Check that there is no garbage at end of line. */
962         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
963                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
964                     filename, linenum, arg);
965         }
966         return 0;
967 }
968
969
970 /*
971  * Reads the config file and modifies the options accordingly.  Options
972  * should already be initialized before this call.  This never returns if
973  * there is an error.  If the file does not exist, this returns 0.
974  */
975
976 int
977 read_config_file(const char *filename, const char *host, Options *options,
978     int checkperm)
979 {
980         FILE *f;
981         char line[1024];
982         int active, linenum;
983         int bad_options = 0;
984
985         /* Open the file. */
986         if ((f = fopen(filename, "r")) == NULL)
987                 return 0;
988
989         if (checkperm) {
990                 struct stat sb;
991
992                 if (fstat(fileno(f), &sb) == -1)
993                         fatal("fstat %s: %s", filename, strerror(errno));
994                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
995                     (sb.st_mode & 022) != 0))
996                         fatal("Bad owner or permissions on %s", filename);
997         }
998
999         debug("Reading configuration data %.200s", filename);
1000
1001         /*
1002          * Mark that we are now processing the options.  This flag is turned
1003          * on/off by Host specifications.
1004          */
1005         active = 1;
1006         linenum = 0;
1007         while (fgets(line, sizeof(line), f)) {
1008                 /* Update line number counter. */
1009                 linenum++;
1010                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1011                         bad_options++;
1012         }
1013         fclose(f);
1014         if (bad_options > 0)
1015                 fatal("%s: terminating, %d bad configuration options",
1016                     filename, bad_options);
1017         return 1;
1018 }
1019
1020 /*
1021  * Initializes options to special values that indicate that they have not yet
1022  * been set.  Read_config_file will only set options with this value. Options
1023  * are processed in the following order: command line, user config file,
1024  * system config file.  Last, fill_default_options is called.
1025  */
1026
1027 void
1028 initialize_options(Options * options)
1029 {
1030         memset(options, 'X', sizeof(*options));
1031         options->forward_agent = -1;
1032         options->forward_x11 = -1;
1033         options->forward_x11_trusted = -1;
1034         options->exit_on_forward_failure = -1;
1035         options->xauth_location = NULL;
1036         options->gateway_ports = -1;
1037         options->use_privileged_port = -1;
1038         options->rsa_authentication = -1;
1039         options->pubkey_authentication = -1;
1040         options->challenge_response_authentication = -1;
1041         options->gss_authentication = -1;
1042         options->gss_deleg_creds = -1;
1043         options->password_authentication = -1;
1044         options->kbd_interactive_authentication = -1;
1045         options->kbd_interactive_devices = NULL;
1046         options->rhosts_rsa_authentication = -1;
1047         options->hostbased_authentication = -1;
1048         options->batch_mode = -1;
1049         options->check_host_ip = -1;
1050         options->strict_host_key_checking = -1;
1051         options->compression = -1;
1052         options->tcp_keep_alive = -1;
1053         options->compression_level = -1;
1054         options->port = -1;
1055         options->address_family = -1;
1056         options->connection_attempts = -1;
1057         options->connection_timeout = -1;
1058         options->number_of_password_prompts = -1;
1059         options->cipher = -1;
1060         options->ciphers = NULL;
1061         options->macs = NULL;
1062         options->hostkeyalgorithms = NULL;
1063         options->protocol = SSH_PROTO_UNKNOWN;
1064         options->num_identity_files = 0;
1065         options->hostname = NULL;
1066         options->host_key_alias = NULL;
1067         options->proxy_command = NULL;
1068         options->user = NULL;
1069         options->escape_char = -1;
1070         options->system_hostfile = NULL;
1071         options->user_hostfile = NULL;
1072         options->system_hostfile2 = NULL;
1073         options->user_hostfile2 = NULL;
1074         options->num_local_forwards = 0;
1075         options->num_remote_forwards = 0;
1076         options->clear_forwardings = -1;
1077         options->log_level = SYSLOG_LEVEL_NOT_SET;
1078         options->preferred_authentications = NULL;
1079         options->bind_address = NULL;
1080         options->smartcard_device = NULL;
1081         options->enable_ssh_keysign = - 1;
1082         options->no_host_authentication_for_localhost = - 1;
1083         options->identities_only = - 1;
1084         options->rekey_limit = - 1;
1085         options->verify_host_key_dns = -1;
1086         options->server_alive_interval = -1;
1087         options->server_alive_count_max = -1;
1088         options->num_send_env = 0;
1089         options->control_path = NULL;
1090         options->control_master = -1;
1091         options->hash_known_hosts = -1;
1092         options->tun_open = -1;
1093         options->tun_local = -1;
1094         options->tun_remote = -1;
1095         options->local_command = NULL;
1096         options->permit_local_command = -1;
1097         options->visual_host_key = -1;
1098 }
1099
1100 /*
1101  * Called after processing other sources of option data, this fills those
1102  * options for which no value has been specified with their default values.
1103  */
1104
1105 void
1106 fill_default_options(Options * options)
1107 {
1108         int len;
1109
1110         if (options->forward_agent == -1)
1111                 options->forward_agent = 0;
1112         if (options->forward_x11 == -1)
1113                 options->forward_x11 = 0;
1114         if (options->forward_x11_trusted == -1)
1115                 options->forward_x11_trusted = 0;
1116         if (options->exit_on_forward_failure == -1)
1117                 options->exit_on_forward_failure = 0;
1118         if (options->xauth_location == NULL)
1119                 options->xauth_location = _PATH_XAUTH;
1120         if (options->gateway_ports == -1)
1121                 options->gateway_ports = 0;
1122         if (options->use_privileged_port == -1)
1123                 options->use_privileged_port = 0;
1124         if (options->rsa_authentication == -1)
1125                 options->rsa_authentication = 1;
1126         if (options->pubkey_authentication == -1)
1127                 options->pubkey_authentication = 1;
1128         if (options->challenge_response_authentication == -1)
1129                 options->challenge_response_authentication = 1;
1130         if (options->gss_authentication == -1)
1131                 options->gss_authentication = 0;
1132         if (options->gss_deleg_creds == -1)
1133                 options->gss_deleg_creds = 0;
1134         if (options->password_authentication == -1)
1135                 options->password_authentication = 1;
1136         if (options->kbd_interactive_authentication == -1)
1137                 options->kbd_interactive_authentication = 1;
1138         if (options->rhosts_rsa_authentication == -1)
1139                 options->rhosts_rsa_authentication = 0;
1140         if (options->hostbased_authentication == -1)
1141                 options->hostbased_authentication = 0;
1142         if (options->batch_mode == -1)
1143                 options->batch_mode = 0;
1144         if (options->check_host_ip == -1)
1145                 options->check_host_ip = 0;
1146         if (options->strict_host_key_checking == -1)
1147                 options->strict_host_key_checking = 2;  /* 2 is default */
1148         if (options->compression == -1)
1149                 options->compression = 0;
1150         if (options->tcp_keep_alive == -1)
1151                 options->tcp_keep_alive = 1;
1152         if (options->compression_level == -1)
1153                 options->compression_level = 6;
1154         if (options->port == -1)
1155                 options->port = 0;      /* Filled in ssh_connect. */
1156         if (options->address_family == -1)
1157                 options->address_family = AF_UNSPEC;
1158         if (options->connection_attempts == -1)
1159                 options->connection_attempts = 1;
1160         if (options->number_of_password_prompts == -1)
1161                 options->number_of_password_prompts = 3;
1162         /* Selected in ssh_login(). */
1163         if (options->cipher == -1)
1164                 options->cipher = SSH_CIPHER_NOT_SET;
1165         /* options->ciphers, default set in myproposals.h */
1166         /* options->macs, default set in myproposals.h */
1167         /* options->hostkeyalgorithms, default set in myproposals.h */
1168         if (options->protocol == SSH_PROTO_UNKNOWN)
1169                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1170         if (options->num_identity_files == 0) {
1171                 if (options->protocol & SSH_PROTO_1) {
1172                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 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_IDENTITY);
1177                 }
1178                 if (options->protocol & SSH_PROTO_2) {
1179                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1180                         options->identity_files[options->num_identity_files] =
1181                             xmalloc(len);
1182                         snprintf(options->identity_files[options->num_identity_files++],
1183                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1184
1185                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1186                         options->identity_files[options->num_identity_files] =
1187                             xmalloc(len);
1188                         snprintf(options->identity_files[options->num_identity_files++],
1189                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1190                 }
1191         }
1192         if (options->escape_char == -1)
1193                 options->escape_char = '~';
1194         if (options->system_hostfile == NULL)
1195                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1196         if (options->user_hostfile == NULL)
1197                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1198         if (options->system_hostfile2 == NULL)
1199                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1200         if (options->user_hostfile2 == NULL)
1201                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1202         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1203                 options->log_level = SYSLOG_LEVEL_INFO;
1204         if (options->clear_forwardings == 1)
1205                 clear_forwardings(options);
1206         if (options->no_host_authentication_for_localhost == - 1)
1207                 options->no_host_authentication_for_localhost = 0;
1208         if (options->identities_only == -1)
1209                 options->identities_only = 0;
1210         if (options->enable_ssh_keysign == -1)
1211                 options->enable_ssh_keysign = 0;
1212         if (options->rekey_limit == -1)
1213                 options->rekey_limit = 0;
1214         if (options->verify_host_key_dns == -1)
1215                 options->verify_host_key_dns = 0;
1216         if (options->server_alive_interval == -1)
1217                 options->server_alive_interval = 0;
1218         if (options->server_alive_count_max == -1)
1219                 options->server_alive_count_max = 3;
1220         if (options->control_master == -1)
1221                 options->control_master = 0;
1222         if (options->hash_known_hosts == -1)
1223                 options->hash_known_hosts = 0;
1224         if (options->tun_open == -1)
1225                 options->tun_open = SSH_TUNMODE_NO;
1226         if (options->tun_local == -1)
1227                 options->tun_local = SSH_TUNID_ANY;
1228         if (options->tun_remote == -1)
1229                 options->tun_remote = SSH_TUNID_ANY;
1230         if (options->permit_local_command == -1)
1231                 options->permit_local_command = 0;
1232         if (options->visual_host_key == -1)
1233                 options->visual_host_key = 0;
1234         /* options->local_command should not be set by default */
1235         /* options->proxy_command should not be set by default */
1236         /* options->user will be set in the main program if appropriate */
1237         /* options->hostname will be set in the main program if appropriate */
1238         /* options->host_key_alias should not be set by default */
1239         /* options->preferred_authentications will be set in ssh */
1240 }
1241
1242 /*
1243  * parse_forward
1244  * parses a string containing a port forwarding specification of the form:
1245  *      [listenhost:]listenport:connecthost:connectport
1246  * returns number of arguments parsed or zero on error
1247  */
1248 int
1249 parse_forward(Forward *fwd, const char *fwdspec)
1250 {
1251         int i;
1252         char *p, *cp, *fwdarg[4];
1253
1254         memset(fwd, '\0', sizeof(*fwd));
1255
1256         cp = p = xstrdup(fwdspec);
1257
1258         /* skip leading spaces */
1259         while (isspace(*cp))
1260                 cp++;
1261
1262         for (i = 0; i < 4; ++i)
1263                 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1264                         break;
1265
1266         /* Check for trailing garbage in 4-arg case*/
1267         if (cp != NULL)
1268                 i = 0;  /* failure */
1269
1270         switch (i) {
1271         case 3:
1272                 fwd->listen_host = NULL;
1273                 fwd->listen_port = a2port(fwdarg[0]);
1274                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1275                 fwd->connect_port = a2port(fwdarg[2]);
1276                 break;
1277
1278         case 4:
1279                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1280                 fwd->listen_port = a2port(fwdarg[1]);
1281                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1282                 fwd->connect_port = a2port(fwdarg[3]);
1283                 break;
1284         default:
1285                 i = 0; /* failure */
1286         }
1287
1288         xfree(p);
1289
1290         if (fwd->listen_port == 0 || fwd->connect_port == 0)
1291                 goto fail_free;
1292
1293         if (fwd->connect_host != NULL &&
1294             strlen(fwd->connect_host) >= NI_MAXHOST)
1295                 goto fail_free;
1296
1297         return (i);
1298
1299  fail_free:
1300         if (fwd->connect_host != NULL)
1301                 xfree(fwd->connect_host);
1302         if (fwd->listen_host != NULL)
1303                 xfree(fwd->listen_host);
1304         return (0);
1305 }