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