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