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