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