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