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