]> andersk Git - gssapi-openssh.git/blob - openssh/readconf.c
enable PAM user switching
[gssapi-openssh.git] / openssh / readconf.c
1 /* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 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         oVisualHostKey, oZeroKnowledgePasswordAuthentication,
136         oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
137         oHPNBufferSize,
138         oDeprecated, oUnsupported
139 } OpCodes;
140
141 /* Textual representations of the tokens. */
142
143 static struct {
144         const char *name;
145         OpCodes opcode;
146 } keywords[] = {
147         { "forwardagent", oForwardAgent },
148         { "forwardx11", oForwardX11 },
149         { "forwardx11trusted", oForwardX11Trusted },
150         { "exitonforwardfailure", oExitOnForwardFailure },
151         { "xauthlocation", oXAuthLocation },
152         { "gatewayports", oGatewayPorts },
153         { "useprivilegedport", oUsePrivilegedPort },
154         { "rhostsauthentication", oDeprecated },
155         { "passwordauthentication", oPasswordAuthentication },
156         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
157         { "kbdinteractivedevices", oKbdInteractiveDevices },
158         { "rsaauthentication", oRSAAuthentication },
159         { "pubkeyauthentication", oPubkeyAuthentication },
160         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
161         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
162         { "hostbasedauthentication", oHostbasedAuthentication },
163         { "challengeresponseauthentication", oChallengeResponseAuthentication },
164         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
165         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
166         { "kerberosauthentication", oUnsupported },
167         { "kerberostgtpassing", oUnsupported },
168         { "afstokenpassing", oUnsupported },
169 #if defined(GSSAPI)
170         { "gssapiauthentication", oGssAuthentication },
171         { "gssapikeyexchange", oGssKeyEx },
172         { "gssapidelegatecredentials", oGssDelegateCreds },
173         { "gssapitrustdns", oGssTrustDns },
174 #else
175         { "gssapiauthentication", oUnsupported },
176         { "gssapikeyexchange", oUnsupported },
177         { "gssapidelegatecredentials", oUnsupported },
178         { "gssapitrustdns", oUnsupported },
179 #endif
180         { "fallbacktorsh", oDeprecated },
181         { "usersh", oDeprecated },
182         { "identityfile", oIdentityFile },
183         { "identityfile2", oIdentityFile },                     /* obsolete */
184         { "identitiesonly", oIdentitiesOnly },
185         { "hostname", oHostName },
186         { "hostkeyalias", oHostKeyAlias },
187         { "proxycommand", oProxyCommand },
188         { "port", oPort },
189         { "cipher", oCipher },
190         { "ciphers", oCiphers },
191         { "macs", oMacs },
192         { "protocol", oProtocol },
193         { "remoteforward", oRemoteForward },
194         { "localforward", oLocalForward },
195         { "user", oUser },
196         { "host", oHost },
197         { "escapechar", oEscapeChar },
198         { "globalknownhostsfile", oGlobalKnownHostsFile },
199         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },    /* obsolete */
200         { "userknownhostsfile", oUserKnownHostsFile },
201         { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
202         { "connectionattempts", oConnectionAttempts },
203         { "batchmode", oBatchMode },
204         { "checkhostip", oCheckHostIP },
205         { "stricthostkeychecking", oStrictHostKeyChecking },
206         { "compression", oCompression },
207         { "compressionlevel", oCompressionLevel },
208         { "tcpkeepalive", oTCPKeepAlive },
209         { "keepalive", oTCPKeepAlive },                         /* obsolete */
210         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
211         { "loglevel", oLogLevel },
212         { "dynamicforward", oDynamicForward },
213         { "preferredauthentications", oPreferredAuthentications },
214         { "hostkeyalgorithms", oHostKeyAlgorithms },
215         { "bindaddress", oBindAddress },
216 #ifdef SMARTCARD
217         { "smartcarddevice", oSmartcardDevice },
218 #else
219         { "smartcarddevice", oUnsupported },
220 #endif
221         { "clearallforwardings", oClearAllForwardings },
222         { "enablesshkeysign", oEnableSSHKeysign },
223         { "verifyhostkeydns", oVerifyHostKeyDNS },
224         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
225         { "rekeylimit", oRekeyLimit },
226         { "connecttimeout", oConnectTimeout },
227         { "addressfamily", oAddressFamily },
228         { "serveraliveinterval", oServerAliveInterval },
229         { "serveralivecountmax", oServerAliveCountMax },
230         { "sendenv", oSendEnv },
231         { "controlpath", oControlPath },
232         { "controlmaster", oControlMaster },
233         { "hashknownhosts", oHashKnownHosts },
234         { "tunnel", oTunnel },
235         { "tunneldevice", oTunnelDevice },
236         { "localcommand", oLocalCommand },
237         { "permitlocalcommand", oPermitLocalCommand },
238         { "noneenabled", oNoneEnabled },
239         { "tcprcvbufpoll", oTcpRcvBufPoll },
240         { "tcprcvbuf", oTcpRcvBuf },
241         { "noneswitch", oNoneSwitch },
242         { "hpndisabled", oHPNDisabled },
243         { "hpnbuffersize", oHPNBufferSize },
244         { "visualhostkey", oVisualHostKey },
245         { "noneenabled", oNoneEnabled },
246         { "tcprcvbufpoll", oTcpRcvBufPoll },
247         { "tcprcvbuf", oTcpRcvBuf },
248         { "noneswitch", oNoneSwitch },
249         { "hpndisabled", oHPNDisabled },
250         { "hpnbuffersize", oHPNBufferSize },
251 #ifdef JPAKE
252         { "zeroknowledgepasswordauthentication",
253             oZeroKnowledgePasswordAuthentication },
254 #else
255         { "zeroknowledgepasswordauthentication", oUnsupported },
256 #endif
257         { NULL, oBadOption }
258 };
259
260 /*
261  * Adds a local TCP/IP port forward to options.  Never returns if there is an
262  * error.
263  */
264
265 void
266 add_local_forward(Options *options, const Forward *newfwd)
267 {
268         Forward *fwd;
269 #ifndef NO_IPPORT_RESERVED_CONCEPT
270         extern uid_t original_real_uid;
271         if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
272                 fatal("Privileged ports can only be forwarded by root.");
273 #endif
274         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
275                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
276         fwd = &options->local_forwards[options->num_local_forwards++];
277
278         fwd->listen_host = newfwd->listen_host;
279         fwd->listen_port = newfwd->listen_port;
280         fwd->connect_host = newfwd->connect_host;
281         fwd->connect_port = newfwd->connect_port;
282 }
283
284 /*
285  * Adds a remote TCP/IP port forward to options.  Never returns if there is
286  * an error.
287  */
288
289 void
290 add_remote_forward(Options *options, const Forward *newfwd)
291 {
292         Forward *fwd;
293         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
294                 fatal("Too many remote forwards (max %d).",
295                     SSH_MAX_FORWARDS_PER_DIRECTION);
296         fwd = &options->remote_forwards[options->num_remote_forwards++];
297
298         fwd->listen_host = newfwd->listen_host;
299         fwd->listen_port = newfwd->listen_port;
300         fwd->connect_host = newfwd->connect_host;
301         fwd->connect_port = newfwd->connect_port;
302 }
303
304 static void
305 clear_forwardings(Options *options)
306 {
307         int i;
308
309         for (i = 0; i < options->num_local_forwards; i++) {
310                 if (options->local_forwards[i].listen_host != NULL)
311                         xfree(options->local_forwards[i].listen_host);
312                 xfree(options->local_forwards[i].connect_host);
313         }
314         options->num_local_forwards = 0;
315         for (i = 0; i < options->num_remote_forwards; i++) {
316                 if (options->remote_forwards[i].listen_host != NULL)
317                         xfree(options->remote_forwards[i].listen_host);
318                 xfree(options->remote_forwards[i].connect_host);
319         }
320         options->num_remote_forwards = 0;
321         options->tun_open = SSH_TUNMODE_NO;
322 }
323
324 /*
325  * Returns the number of the token pointed to by cp or oBadOption.
326  */
327
328 static OpCodes
329 parse_token(const char *cp, const char *filename, int linenum)
330 {
331         u_int i;
332
333         for (i = 0; keywords[i].name; i++)
334                 if (strcasecmp(cp, keywords[i].name) == 0)
335                         return keywords[i].opcode;
336
337         error("%s: line %d: Bad configuration option: %s",
338             filename, linenum, cp);
339         return oBadOption;
340 }
341
342 /*
343  * Processes a single option line as used in the configuration files. This
344  * only sets those values that have not already been set.
345  */
346 #define WHITESPACE " \t\r\n"
347
348 int
349 process_config_line(Options *options, const char *host,
350                     char *line, const char *filename, int linenum,
351                     int *activep)
352 {
353         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
354         int opcode, *intptr, value, value2, scale;
355         LogLevel *log_level_ptr;
356         long long orig, val64;
357         size_t len;
358         Forward fwd;
359
360         /* Strip trailing whitespace */
361         for (len = strlen(line) - 1; len > 0; len--) {
362                 if (strchr(WHITESPACE, line[len]) == NULL)
363                         break;
364                 line[len] = '\0';
365         }
366
367         s = line;
368         /* Get the keyword. (Each line is supposed to begin with a keyword). */
369         if ((keyword = strdelim(&s)) == NULL)
370                 return 0;
371         /* Ignore leading whitespace. */
372         if (*keyword == '\0')
373                 keyword = strdelim(&s);
374         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
375                 return 0;
376
377         opcode = parse_token(keyword, filename, linenum);
378
379         switch (opcode) {
380         case oBadOption:
381                 /* don't panic, but count bad options */
382                 return -1;
383                 /* NOTREACHED */
384         case oConnectTimeout:
385                 intptr = &options->connection_timeout;
386 parse_time:
387                 arg = strdelim(&s);
388                 if (!arg || *arg == '\0')
389                         fatal("%s line %d: missing time value.",
390                             filename, linenum);
391                 if ((value = convtime(arg)) == -1)
392                         fatal("%s line %d: invalid time value.",
393                             filename, linenum);
394                 if (*activep && *intptr == -1)
395                         *intptr = value;
396                 break;
397
398         case oForwardAgent:
399                 intptr = &options->forward_agent;
400 parse_flag:
401                 arg = strdelim(&s);
402                 if (!arg || *arg == '\0')
403                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
404                 value = 0;      /* To avoid compiler warning... */
405                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
406                         value = 1;
407                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
408                         value = 0;
409                 else
410                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
411                 if (*activep && *intptr == -1)
412                         *intptr = value;
413                 break;
414
415         case oForwardX11:
416                 intptr = &options->forward_x11;
417                 goto parse_flag;
418
419         case oForwardX11Trusted:
420                 intptr = &options->forward_x11_trusted;
421                 goto parse_flag;
422
423         case oGatewayPorts:
424                 intptr = &options->gateway_ports;
425                 goto parse_flag;
426
427         case oExitOnForwardFailure:
428                 intptr = &options->exit_on_forward_failure;
429                 goto parse_flag;
430
431         case oUsePrivilegedPort:
432                 intptr = &options->use_privileged_port;
433                 goto parse_flag;
434
435         case oPasswordAuthentication:
436                 intptr = &options->password_authentication;
437                 goto parse_flag;
438
439         case oZeroKnowledgePasswordAuthentication:
440                 intptr = &options->zero_knowledge_password_authentication;
441                 goto parse_flag;
442
443         case oKbdInteractiveAuthentication:
444                 intptr = &options->kbd_interactive_authentication;
445                 goto parse_flag;
446
447         case oKbdInteractiveDevices:
448                 charptr = &options->kbd_interactive_devices;
449                 goto parse_string;
450
451         case oPubkeyAuthentication:
452                 intptr = &options->pubkey_authentication;
453                 goto parse_flag;
454
455         case oRSAAuthentication:
456                 intptr = &options->rsa_authentication;
457                 goto parse_flag;
458
459         case oRhostsRSAAuthentication:
460                 intptr = &options->rhosts_rsa_authentication;
461                 goto parse_flag;
462
463         case oHostbasedAuthentication:
464                 intptr = &options->hostbased_authentication;
465                 goto parse_flag;
466
467         case oChallengeResponseAuthentication:
468                 intptr = &options->challenge_response_authentication;
469                 goto parse_flag;
470
471         case oGssAuthentication:
472                 intptr = &options->gss_authentication;
473                 goto parse_flag;
474
475         case oGssKeyEx:
476                 intptr = &options->gss_keyex;
477                 goto parse_flag;
478
479         case oGssDelegateCreds:
480                 intptr = &options->gss_deleg_creds;
481                 goto parse_flag;
482
483         case oGssTrustDns:
484                 intptr = &options->gss_trust_dns;
485                 goto parse_flag;
486
487         case oBatchMode:
488                 intptr = &options->batch_mode;
489                 goto parse_flag;
490
491         case oCheckHostIP:
492                 intptr = &options->check_host_ip;
493                 goto parse_flag;
494
495         case oNoneEnabled:
496                 intptr = &options->none_enabled;
497                 goto parse_flag;
498  
499         /* we check to see if the command comes from the */
500         /* command line or not. If it does then enable it */
501         /* otherwise fail. NONE should never be a default configuration */
502         case oNoneSwitch:
503                 if(strcmp(filename,"command-line")==0)
504                 {               
505                     intptr = &options->none_switch;
506                     goto parse_flag;
507                 } else {
508                     error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
509                     error("Continuing...");
510                     debug("NoneSwitch directive found in %.200s.", filename);
511                     return 0;
512                 }
513
514         case oHPNDisabled:
515                 intptr = &options->hpn_disabled;
516                 goto parse_flag;
517
518         case oHPNBufferSize:
519                 intptr = &options->hpn_buffer_size;
520                 goto parse_int;
521
522         case oTcpRcvBufPoll:
523                 intptr = &options->tcp_rcv_buf_poll;
524                 goto parse_flag;
525
526         case oVerifyHostKeyDNS:
527                 intptr = &options->verify_host_key_dns;
528                 goto parse_yesnoask;
529
530         case oStrictHostKeyChecking:
531                 intptr = &options->strict_host_key_checking;
532 parse_yesnoask:
533                 arg = strdelim(&s);
534                 if (!arg || *arg == '\0')
535                         fatal("%.200s line %d: Missing yes/no/ask argument.",
536                             filename, linenum);
537                 value = 0;      /* To avoid compiler warning... */
538                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
539                         value = 1;
540                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
541                         value = 0;
542                 else if (strcmp(arg, "ask") == 0)
543                         value = 2;
544                 else
545                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
546                 if (*activep && *intptr == -1)
547                         *intptr = value;
548                 break;
549
550         case oCompression:
551                 intptr = &options->compression;
552                 goto parse_flag;
553
554         case oTCPKeepAlive:
555                 intptr = &options->tcp_keep_alive;
556                 goto parse_flag;
557
558         case oNoHostAuthenticationForLocalhost:
559                 intptr = &options->no_host_authentication_for_localhost;
560                 goto parse_flag;
561
562         case oNumberOfPasswordPrompts:
563                 intptr = &options->number_of_password_prompts;
564                 goto parse_int;
565
566         case oCompressionLevel:
567                 intptr = &options->compression_level;
568                 goto parse_int;
569
570         case oRekeyLimit:
571                 arg = strdelim(&s);
572                 if (!arg || *arg == '\0')
573                         fatal("%.200s line %d: Missing argument.", filename, linenum);
574                 if (arg[0] < '0' || arg[0] > '9')
575                         fatal("%.200s line %d: Bad number.", filename, linenum);
576                 orig = val64 = strtoll(arg, &endofnumber, 10);
577                 if (arg == endofnumber)
578                         fatal("%.200s line %d: Bad number.", filename, linenum);
579                 switch (toupper(*endofnumber)) {
580                 case '\0':
581                         scale = 1;
582                         break;
583                 case 'K':
584                         scale = 1<<10;
585                         break;
586                 case 'M':
587                         scale = 1<<20;
588                         break;
589                 case 'G':
590                         scale = 1<<30;
591                         break;
592                 default:
593                         fatal("%.200s line %d: Invalid RekeyLimit suffix",
594                             filename, linenum);
595                 }
596                 val64 *= scale;
597                 /* detect integer wrap and too-large limits */
598                 if ((val64 / scale) != orig || val64 > UINT_MAX)
599                         fatal("%.200s line %d: RekeyLimit too large",
600                             filename, linenum);
601                 if (val64 < 16)
602                         fatal("%.200s line %d: RekeyLimit too small",
603                             filename, linenum);
604                 if (*activep && options->rekey_limit == -1)
605                         options->rekey_limit = (u_int32_t)val64;
606                 break;
607
608         case oIdentityFile:
609                 arg = strdelim(&s);
610                 if (!arg || *arg == '\0')
611                         fatal("%.200s line %d: Missing argument.", filename, linenum);
612                 if (*activep) {
613                         intptr = &options->num_identity_files;
614                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
615                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
616                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
617                         charptr = &options->identity_files[*intptr];
618                         *charptr = xstrdup(arg);
619                         *intptr = *intptr + 1;
620                 }
621                 break;
622
623         case oXAuthLocation:
624                 charptr=&options->xauth_location;
625                 goto parse_string;
626
627         case oUser:
628                 charptr = &options->user;
629 parse_string:
630                 arg = strdelim(&s);
631                 if (!arg || *arg == '\0')
632                         fatal("%.200s line %d: Missing argument.", filename, linenum);
633                 if (*activep && *charptr == NULL)
634                         *charptr = xstrdup(arg);
635                 break;
636
637         case oGlobalKnownHostsFile:
638                 charptr = &options->system_hostfile;
639                 goto parse_string;
640
641         case oUserKnownHostsFile:
642                 charptr = &options->user_hostfile;
643                 goto parse_string;
644
645         case oGlobalKnownHostsFile2:
646                 charptr = &options->system_hostfile2;
647                 goto parse_string;
648
649         case oUserKnownHostsFile2:
650                 charptr = &options->user_hostfile2;
651                 goto parse_string;
652
653         case oHostName:
654                 charptr = &options->hostname;
655                 goto parse_string;
656
657         case oHostKeyAlias:
658                 charptr = &options->host_key_alias;
659                 goto parse_string;
660
661         case oPreferredAuthentications:
662                 charptr = &options->preferred_authentications;
663                 goto parse_string;
664
665         case oBindAddress:
666                 charptr = &options->bind_address;
667                 goto parse_string;
668
669         case oSmartcardDevice:
670                 charptr = &options->smartcard_device;
671                 goto parse_string;
672
673         case oProxyCommand:
674                 charptr = &options->proxy_command;
675 parse_command:
676                 if (s == NULL)
677                         fatal("%.200s line %d: Missing argument.", filename, linenum);
678                 len = strspn(s, WHITESPACE "=");
679                 if (*activep && *charptr == NULL)
680                         *charptr = xstrdup(s + len);
681                 return 0;
682
683         case oPort:
684                 intptr = &options->port;
685 parse_int:
686                 arg = strdelim(&s);
687                 if (!arg || *arg == '\0')
688                         fatal("%.200s line %d: Missing argument.", filename, linenum);
689                 if (arg[0] < '0' || arg[0] > '9')
690                         fatal("%.200s line %d: Bad number.", filename, linenum);
691
692                 /* Octal, decimal, or hex format? */
693                 value = strtol(arg, &endofnumber, 0);
694                 if (arg == endofnumber)
695                         fatal("%.200s line %d: Bad number.", filename, linenum);
696                 if (*activep && *intptr == -1)
697                         *intptr = value;
698                 break;
699
700         case oConnectionAttempts:
701                 intptr = &options->connection_attempts;
702                 goto parse_int;
703
704         case oTcpRcvBuf:
705                 intptr = &options->tcp_rcv_buf;
706                 goto parse_int;
707
708         case oCipher:
709                 intptr = &options->cipher;
710                 arg = strdelim(&s);
711                 if (!arg || *arg == '\0')
712                         fatal("%.200s line %d: Missing argument.", filename, linenum);
713                 value = cipher_number(arg);
714                 if (value == -1)
715                         fatal("%.200s line %d: Bad cipher '%s'.",
716                             filename, linenum, arg ? arg : "<NONE>");
717                 if (*activep && *intptr == -1)
718                         *intptr = value;
719                 break;
720
721         case oCiphers:
722                 arg = strdelim(&s);
723                 if (!arg || *arg == '\0')
724                         fatal("%.200s line %d: Missing argument.", filename, linenum);
725                 if (!ciphers_valid(arg))
726                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
727                             filename, linenum, arg ? arg : "<NONE>");
728                 if (*activep && options->ciphers == NULL)
729                         options->ciphers = xstrdup(arg);
730                 break;
731
732         case oMacs:
733                 arg = strdelim(&s);
734                 if (!arg || *arg == '\0')
735                         fatal("%.200s line %d: Missing argument.", filename, linenum);
736                 if (!mac_valid(arg))
737                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
738                             filename, linenum, arg ? arg : "<NONE>");
739                 if (*activep && options->macs == NULL)
740                         options->macs = xstrdup(arg);
741                 break;
742
743         case oHostKeyAlgorithms:
744                 arg = strdelim(&s);
745                 if (!arg || *arg == '\0')
746                         fatal("%.200s line %d: Missing argument.", filename, linenum);
747                 if (!key_names_valid2(arg))
748                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
749                             filename, linenum, arg ? arg : "<NONE>");
750                 if (*activep && options->hostkeyalgorithms == NULL)
751                         options->hostkeyalgorithms = xstrdup(arg);
752                 break;
753
754         case oProtocol:
755                 intptr = &options->protocol;
756                 arg = strdelim(&s);
757                 if (!arg || *arg == '\0')
758                         fatal("%.200s line %d: Missing argument.", filename, linenum);
759                 value = proto_spec(arg);
760                 if (value == SSH_PROTO_UNKNOWN)
761                         fatal("%.200s line %d: Bad protocol spec '%s'.",
762                             filename, linenum, arg ? arg : "<NONE>");
763                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
764                         *intptr = value;
765                 break;
766
767         case oLogLevel:
768                 log_level_ptr = &options->log_level;
769                 arg = strdelim(&s);
770                 value = log_level_number(arg);
771                 if (value == SYSLOG_LEVEL_NOT_SET)
772                         fatal("%.200s line %d: unsupported log level '%s'",
773                             filename, linenum, arg ? arg : "<NONE>");
774                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
775                         *log_level_ptr = (LogLevel) value;
776                 break;
777
778         case oLocalForward:
779         case oRemoteForward:
780         case oDynamicForward:
781                 arg = strdelim(&s);
782                 if (arg == NULL || *arg == '\0')
783                         fatal("%.200s line %d: Missing port argument.",
784                             filename, linenum);
785
786                 if (opcode == oLocalForward ||
787                     opcode == oRemoteForward) {
788                         arg2 = strdelim(&s);
789                         if (arg2 == NULL || *arg2 == '\0')
790                                 fatal("%.200s line %d: Missing target argument.",
791                                     filename, linenum);
792
793                         /* construct a string for parse_forward */
794                         snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
795                 } else if (opcode == oDynamicForward) {
796                         strlcpy(fwdarg, arg, sizeof(fwdarg));
797                 }
798
799                 if (parse_forward(&fwd, fwdarg,
800                     opcode == oDynamicForward ? 1 : 0,
801                     opcode == oRemoteForward ? 1 : 0) == 0)
802                         fatal("%.200s line %d: Bad forwarding specification.",
803                             filename, linenum);
804
805                 if (*activep) {
806                         if (opcode == oLocalForward ||
807                             opcode == oDynamicForward)
808                                 add_local_forward(options, &fwd);
809                         else if (opcode == oRemoteForward)
810                                 add_remote_forward(options, &fwd);
811                 }
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 oVisualHostKey:
976                 intptr = &options->visual_host_key;
977                 goto parse_flag;
978
979         case oDeprecated:
980                 debug("%s line %d: Deprecated option \"%s\"",
981                     filename, linenum, keyword);
982                 return 0;
983
984         case oUnsupported:
985                 error("%s line %d: Unsupported option \"%s\"",
986                     filename, linenum, keyword);
987                 return 0;
988
989         default:
990                 fatal("process_config_line: Unimplemented opcode %d", opcode);
991         }
992
993         /* Check that there is no garbage at end of line. */
994         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
995                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
996                     filename, linenum, arg);
997         }
998         return 0;
999 }
1000
1001
1002 /*
1003  * Reads the config file and modifies the options accordingly.  Options
1004  * should already be initialized before this call.  This never returns if
1005  * there is an error.  If the file does not exist, this returns 0.
1006  */
1007
1008 int
1009 read_config_file(const char *filename, const char *host, Options *options,
1010     int checkperm)
1011 {
1012         FILE *f;
1013         char line[1024];
1014         int active, linenum;
1015         int bad_options = 0;
1016
1017         if ((f = fopen(filename, "r")) == NULL)
1018                 return 0;
1019
1020         if (checkperm) {
1021                 struct stat sb;
1022
1023                 if (fstat(fileno(f), &sb) == -1)
1024                         fatal("fstat %s: %s", filename, strerror(errno));
1025                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1026                     (sb.st_mode & 022) != 0))
1027                         fatal("Bad owner or permissions on %s", filename);
1028         }
1029
1030         debug("Reading configuration data %.200s", filename);
1031
1032         /*
1033          * Mark that we are now processing the options.  This flag is turned
1034          * on/off by Host specifications.
1035          */
1036         active = 1;
1037         linenum = 0;
1038         while (fgets(line, sizeof(line), f)) {
1039                 /* Update line number counter. */
1040                 linenum++;
1041                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1042                         bad_options++;
1043         }
1044         fclose(f);
1045         if (bad_options > 0)
1046                 fatal("%s: terminating, %d bad configuration options",
1047                     filename, bad_options);
1048         return 1;
1049 }
1050
1051 /*
1052  * Initializes options to special values that indicate that they have not yet
1053  * been set.  Read_config_file will only set options with this value. Options
1054  * are processed in the following order: command line, user config file,
1055  * system config file.  Last, fill_default_options is called.
1056  */
1057
1058 void
1059 initialize_options(Options * options)
1060 {
1061         memset(options, 'X', sizeof(*options));
1062         options->forward_agent = -1;
1063         options->forward_x11 = -1;
1064         options->forward_x11_trusted = -1;
1065         options->exit_on_forward_failure = -1;
1066         options->xauth_location = NULL;
1067         options->gateway_ports = -1;
1068         options->use_privileged_port = -1;
1069         options->rsa_authentication = -1;
1070         options->pubkey_authentication = -1;
1071         options->challenge_response_authentication = -1;
1072         options->gss_authentication = -1;
1073         options->gss_keyex = -1;
1074         options->gss_deleg_creds = -1;
1075         options->gss_trust_dns = -1;
1076         options->password_authentication = -1;
1077         options->kbd_interactive_authentication = -1;
1078         options->kbd_interactive_devices = NULL;
1079         options->rhosts_rsa_authentication = -1;
1080         options->hostbased_authentication = -1;
1081         options->batch_mode = -1;
1082         options->check_host_ip = -1;
1083         options->strict_host_key_checking = -1;
1084         options->compression = -1;
1085         options->tcp_keep_alive = -1;
1086         options->compression_level = -1;
1087         options->port = -1;
1088         options->address_family = -1;
1089         options->connection_attempts = -1;
1090         options->connection_timeout = -1;
1091         options->number_of_password_prompts = -1;
1092         options->cipher = -1;
1093         options->ciphers = NULL;
1094         options->macs = NULL;
1095         options->hostkeyalgorithms = NULL;
1096         options->protocol = SSH_PROTO_UNKNOWN;
1097         options->num_identity_files = 0;
1098         options->hostname = NULL;
1099         options->host_key_alias = NULL;
1100         options->proxy_command = NULL;
1101         options->user = NULL;
1102         options->escape_char = -1;
1103         options->system_hostfile = NULL;
1104         options->user_hostfile = NULL;
1105         options->system_hostfile2 = NULL;
1106         options->user_hostfile2 = NULL;
1107         options->num_local_forwards = 0;
1108         options->num_remote_forwards = 0;
1109         options->clear_forwardings = -1;
1110         options->log_level = SYSLOG_LEVEL_NOT_SET;
1111         options->preferred_authentications = NULL;
1112         options->bind_address = NULL;
1113         options->smartcard_device = NULL;
1114         options->enable_ssh_keysign = - 1;
1115         options->no_host_authentication_for_localhost = - 1;
1116         options->identities_only = - 1;
1117         options->rekey_limit = - 1;
1118         options->verify_host_key_dns = -1;
1119         options->server_alive_interval = -1;
1120         options->server_alive_count_max = -1;
1121         options->num_send_env = 0;
1122         options->control_path = NULL;
1123         options->control_master = -1;
1124         options->hash_known_hosts = -1;
1125         options->tun_open = -1;
1126         options->tun_local = -1;
1127         options->tun_remote = -1;
1128         options->local_command = NULL;
1129         options->permit_local_command = -1;
1130         options->none_switch = -1;
1131         options->none_enabled = -1;
1132         options->hpn_disabled = -1;
1133         options->hpn_buffer_size = -1;
1134         options->tcp_rcv_buf_poll = -1;
1135         options->tcp_rcv_buf = -1;
1136         options->visual_host_key = -1;
1137         options->none_switch = -1;
1138         options->none_enabled = -1;
1139         options->hpn_disabled = -1;
1140         options->hpn_buffer_size = -1;
1141         options->tcp_rcv_buf_poll = -1;
1142         options->tcp_rcv_buf = -1;
1143         options->zero_knowledge_password_authentication = -1;
1144 }
1145
1146 /*
1147  * Called after processing other sources of option data, this fills those
1148  * options for which no value has been specified with their default values.
1149  */
1150
1151 void
1152 fill_default_options(Options * options)
1153 {
1154         int len;
1155
1156         if (options->forward_agent == -1)
1157                 options->forward_agent = 0;
1158         if (options->forward_x11 == -1)
1159                 options->forward_x11 = 0;
1160         if (options->forward_x11_trusted == -1)
1161                 options->forward_x11_trusted = 0;
1162         if (options->exit_on_forward_failure == -1)
1163                 options->exit_on_forward_failure = 0;
1164         if (options->xauth_location == NULL)
1165                 options->xauth_location = _PATH_XAUTH;
1166         if (options->gateway_ports == -1)
1167                 options->gateway_ports = 0;
1168         if (options->use_privileged_port == -1)
1169                 options->use_privileged_port = 0;
1170         if (options->rsa_authentication == -1)
1171                 options->rsa_authentication = 1;
1172         if (options->pubkey_authentication == -1)
1173                 options->pubkey_authentication = 1;
1174         if (options->challenge_response_authentication == -1)
1175                 options->challenge_response_authentication = 1;
1176         if (options->gss_authentication == -1)
1177                 options->gss_authentication = 1;
1178         if (options->gss_keyex == -1)
1179                 options->gss_keyex = 1;
1180         if (options->gss_deleg_creds == -1)
1181                 options->gss_deleg_creds = 1;
1182         if (options->gss_trust_dns == -1)
1183                 options->gss_trust_dns = 1;
1184         if (options->password_authentication == -1)
1185                 options->password_authentication = 1;
1186         if (options->kbd_interactive_authentication == -1)
1187                 options->kbd_interactive_authentication = 1;
1188         if (options->rhosts_rsa_authentication == -1)
1189                 options->rhosts_rsa_authentication = 0;
1190         if (options->hostbased_authentication == -1)
1191                 options->hostbased_authentication = 0;
1192         if (options->batch_mode == -1)
1193                 options->batch_mode = 0;
1194         if (options->check_host_ip == -1)
1195                 options->check_host_ip = 1;
1196         if (options->strict_host_key_checking == -1)
1197                 options->strict_host_key_checking = 2;  /* 2 is default */
1198         if (options->compression == -1)
1199                 options->compression = 0;
1200         if (options->tcp_keep_alive == -1)
1201                 options->tcp_keep_alive = 1;
1202         if (options->compression_level == -1)
1203                 options->compression_level = 6;
1204         if (options->port == -1)
1205                 options->port = 0;      /* Filled in ssh_connect. */
1206         if (options->address_family == -1)
1207                 options->address_family = AF_UNSPEC;
1208         if (options->connection_attempts == -1)
1209                 options->connection_attempts = 1;
1210         if (options->number_of_password_prompts == -1)
1211                 options->number_of_password_prompts = 3;
1212         /* Selected in ssh_login(). */
1213         if (options->cipher == -1)
1214                 options->cipher = SSH_CIPHER_NOT_SET;
1215         /* options->ciphers, default set in myproposals.h */
1216         /* options->macs, default set in myproposals.h */
1217         /* options->hostkeyalgorithms, default set in myproposals.h */
1218         if (options->protocol == SSH_PROTO_UNKNOWN)
1219                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1220         if (options->num_identity_files == 0) {
1221                 if (options->protocol & SSH_PROTO_1) {
1222                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1223                         options->identity_files[options->num_identity_files] =
1224                             xmalloc(len);
1225                         snprintf(options->identity_files[options->num_identity_files++],
1226                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1227                 }
1228                 if (options->protocol & SSH_PROTO_2) {
1229                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1230                         options->identity_files[options->num_identity_files] =
1231                             xmalloc(len);
1232                         snprintf(options->identity_files[options->num_identity_files++],
1233                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1234
1235                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1236                         options->identity_files[options->num_identity_files] =
1237                             xmalloc(len);
1238                         snprintf(options->identity_files[options->num_identity_files++],
1239                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1240                 }
1241         }
1242         if (options->escape_char == -1)
1243                 options->escape_char = '~';
1244         if (options->system_hostfile == NULL)
1245                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1246         if (options->user_hostfile == NULL)
1247                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1248         if (options->system_hostfile2 == NULL)
1249                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1250         if (options->user_hostfile2 == NULL)
1251                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1252         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1253                 options->log_level = SYSLOG_LEVEL_INFO;
1254         if (options->clear_forwardings == 1)
1255                 clear_forwardings(options);
1256         if (options->no_host_authentication_for_localhost == - 1)
1257                 options->no_host_authentication_for_localhost = 0;
1258         if (options->identities_only == -1)
1259                 options->identities_only = 0;
1260         if (options->enable_ssh_keysign == -1)
1261                 options->enable_ssh_keysign = 0;
1262         if (options->rekey_limit == -1)
1263                 options->rekey_limit = 0;
1264         if (options->verify_host_key_dns == -1)
1265                 options->verify_host_key_dns = 0;
1266         if (options->server_alive_interval == -1)
1267                 options->server_alive_interval = 0;
1268         if (options->server_alive_count_max == -1)
1269                 options->server_alive_count_max = 3;
1270         if (options->none_switch == -1)
1271                 options->none_switch = 0;
1272         if (options->hpn_disabled == -1)
1273                 options->hpn_disabled = 0;
1274         if (options->hpn_buffer_size > -1)
1275         {
1276           /* if a user tries to set the size to 0 set it to 1KB */
1277                 if (options->hpn_buffer_size == 0)
1278                 options->hpn_buffer_size = 1024;
1279                 /*limit the buffer to 64MB*/
1280                 if (options->hpn_buffer_size > 65536)
1281                 {
1282                         options->hpn_buffer_size = 65536*1024;
1283                         debug("User requested buffer larger than 64MB. Request reverted to 64MB");
1284                 }
1285                 debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
1286         }
1287         if (options->tcp_rcv_buf == 0)
1288                 options->tcp_rcv_buf = 1;
1289         if (options->tcp_rcv_buf > -1) 
1290                 options->tcp_rcv_buf *=1024;
1291         if (options->tcp_rcv_buf_poll == -1)
1292                 options->tcp_rcv_buf_poll = 1;
1293         if (options->control_master == -1)
1294                 options->control_master = 0;
1295         if (options->hash_known_hosts == -1)
1296                 options->hash_known_hosts = 0;
1297         if (options->tun_open == -1)
1298                 options->tun_open = SSH_TUNMODE_NO;
1299         if (options->tun_local == -1)
1300                 options->tun_local = SSH_TUNID_ANY;
1301         if (options->tun_remote == -1)
1302                 options->tun_remote = SSH_TUNID_ANY;
1303         if (options->permit_local_command == -1)
1304                 options->permit_local_command = 0;
1305         if (options->visual_host_key == -1)
1306                 options->visual_host_key = 0;
1307         if (options->zero_knowledge_password_authentication == -1)
1308                 options->zero_knowledge_password_authentication = 0;
1309         /* options->local_command should not be set by default */
1310         /* options->proxy_command should not be set by default */
1311         /* options->user will be set in the main program if appropriate */
1312         /* options->hostname will be set in the main program if appropriate */
1313         /* options->host_key_alias should not be set by default */
1314         /* options->preferred_authentications will be set in ssh */
1315 }
1316
1317 /*
1318  * parse_forward
1319  * parses a string containing a port forwarding specification of the form:
1320  *   dynamicfwd == 0
1321  *      [listenhost:]listenport:connecthost:connectport
1322  *   dynamicfwd == 1
1323  *      [listenhost:]listenport
1324  * returns number of arguments parsed or zero on error
1325  */
1326 int
1327 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1328 {
1329         int i;
1330         char *p, *cp, *fwdarg[4];
1331
1332         memset(fwd, '\0', sizeof(*fwd));
1333
1334         cp = p = xstrdup(fwdspec);
1335
1336         /* skip leading spaces */
1337         while (isspace(*cp))
1338                 cp++;
1339
1340         for (i = 0; i < 4; ++i)
1341                 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1342                         break;
1343
1344         /* Check for trailing garbage */
1345         if (cp != NULL)
1346                 i = 0;  /* failure */
1347
1348         switch (i) {
1349         case 1:
1350                 fwd->listen_host = NULL;
1351                 fwd->listen_port = a2port(fwdarg[0]);
1352                 fwd->connect_host = xstrdup("socks");
1353                 break;
1354
1355         case 2:
1356                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1357                 fwd->listen_port = a2port(fwdarg[1]);
1358                 fwd->connect_host = xstrdup("socks");
1359                 break;
1360
1361         case 3:
1362                 fwd->listen_host = NULL;
1363                 fwd->listen_port = a2port(fwdarg[0]);
1364                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1365                 fwd->connect_port = a2port(fwdarg[2]);
1366                 break;
1367
1368         case 4:
1369                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1370                 fwd->listen_port = a2port(fwdarg[1]);
1371                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1372                 fwd->connect_port = a2port(fwdarg[3]);
1373                 break;
1374         default:
1375                 i = 0; /* failure */
1376         }
1377
1378         xfree(p);
1379
1380         if (dynamicfwd) {
1381                 if (!(i == 1 || i == 2))
1382                         goto fail_free;
1383         } else {
1384                 if (!(i == 3 || i == 4))
1385                         goto fail_free;
1386                 if (fwd->connect_port <= 0)
1387                         goto fail_free;
1388         }
1389
1390         if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1391                 goto fail_free;
1392
1393         if (fwd->connect_host != NULL &&
1394             strlen(fwd->connect_host) >= NI_MAXHOST)
1395                 goto fail_free;
1396         if (fwd->listen_host != NULL &&
1397             strlen(fwd->listen_host) >= NI_MAXHOST)
1398                 goto fail_free;
1399
1400
1401         return (i);
1402
1403  fail_free:
1404         if (fwd->connect_host != NULL) {
1405                 xfree(fwd->connect_host);
1406                 fwd->connect_host = NULL;
1407         }
1408         if (fwd->listen_host != NULL) {
1409                 xfree(fwd->listen_host);
1410                 fwd->listen_host = NULL;
1411         }
1412         return (0);
1413 }
This page took 2.161946 seconds and 5 git commands to generate.