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