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