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