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