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