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