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