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