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