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