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