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