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