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