- (dtucker) platform.c session.c] Move the USE_LIBIAF fragment into
[openssh-git.git] / readconf.c
blobda7efd19391ce6996c6761ba907fc7752585c52f
1 /* $OpenBSD: readconf.c,v 1.189 2010/09/22 05:01:29 djm 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"
46 /* Format of the configuration file:
48 # Configuration data is parsed as follows:
49 # 1. command line options
50 # 2. user-specific file
51 # 3. system-wide file
52 # Any configuration value is only changed the first time it is set.
53 # Thus, host-specific definitions should be at the beginning of the
54 # configuration file, and defaults at the end.
56 # Host-specific declarations. These may override anything above. A single
57 # host may match multiple declarations; these are processed in the order
58 # that they are given in.
60 Host *.ngs.fi ngs.fi
61 User foo
63 Host fake.com
64 HostName another.host.name.real.org
65 User blaah
66 Port 34289
67 ForwardX11 no
68 ForwardAgent no
70 Host books.com
71 RemoteForward 9999 shadows.cs.hut.fi:9999
72 Cipher 3des
74 Host fascist.blob.com
75 Port 23123
76 User tylonen
77 PasswordAuthentication no
79 Host puukko.hut.fi
80 User t35124p
81 ProxyCommand ssh-proxy %h %p
83 Host *.fr
84 PublicKeyAuthentication no
86 Host *.su
87 Cipher none
88 PasswordAuthentication no
90 Host vpn.fake.com
91 Tunnel yes
92 TunnelDevice 3
94 # Defaults for various options
95 Host *
96 ForwardAgent no
97 ForwardX11 no
98 PasswordAuthentication yes
99 RSAAuthentication yes
100 RhostsRSAAuthentication yes
101 StrictHostKeyChecking yes
102 TcpKeepAlive no
103 IdentityFile ~/.ssh/identity
104 Port 22
105 EscapeChar ~
109 /* Keyword tokens. */
111 typedef enum {
112 oBadOption,
113 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
114 oGatewayPorts, oExitOnForwardFailure,
115 oPasswordAuthentication, oRSAAuthentication,
116 oChallengeResponseAuthentication, oXAuthLocation,
117 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
118 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
119 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
120 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
121 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
122 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
123 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
124 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
125 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
126 oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
127 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
130 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
131 oSendEnv, oControlPath, oControlMaster, oControlPersist,
132 oHashKnownHosts,
133 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
134 oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
135 oKexAlgorithms,
136 oDeprecated, oUnsupported
137 } OpCodes;
139 /* Textual representations of the tokens. */
141 static struct {
142 const char *name;
143 OpCodes opcode;
144 } keywords[] = {
145 { "forwardagent", oForwardAgent },
146 { "forwardx11", oForwardX11 },
147 { "forwardx11trusted", oForwardX11Trusted },
148 { "forwardx11timeout", oForwardX11Timeout },
149 { "exitonforwardfailure", oExitOnForwardFailure },
150 { "xauthlocation", oXAuthLocation },
151 { "gatewayports", oGatewayPorts },
152 { "useprivilegedport", oUsePrivilegedPort },
153 { "rhostsauthentication", oDeprecated },
154 { "passwordauthentication", oPasswordAuthentication },
155 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
156 { "kbdinteractivedevices", oKbdInteractiveDevices },
157 { "rsaauthentication", oRSAAuthentication },
158 { "pubkeyauthentication", oPubkeyAuthentication },
159 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
160 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
161 { "hostbasedauthentication", oHostbasedAuthentication },
162 { "challengeresponseauthentication", oChallengeResponseAuthentication },
163 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
164 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
165 { "kerberosauthentication", oUnsupported },
166 { "kerberostgtpassing", oUnsupported },
167 { "afstokenpassing", oUnsupported },
168 #if defined(GSSAPI)
169 { "gssapiauthentication", oGssAuthentication },
170 { "gssapidelegatecredentials", oGssDelegateCreds },
171 #else
172 { "gssapiauthentication", oUnsupported },
173 { "gssapidelegatecredentials", oUnsupported },
174 #endif
175 { "fallbacktorsh", oDeprecated },
176 { "usersh", oDeprecated },
177 { "identityfile", oIdentityFile },
178 { "identityfile2", oIdentityFile }, /* obsolete */
179 { "identitiesonly", oIdentitiesOnly },
180 { "hostname", oHostName },
181 { "hostkeyalias", oHostKeyAlias },
182 { "proxycommand", oProxyCommand },
183 { "port", oPort },
184 { "cipher", oCipher },
185 { "ciphers", oCiphers },
186 { "macs", oMacs },
187 { "protocol", oProtocol },
188 { "remoteforward", oRemoteForward },
189 { "localforward", oLocalForward },
190 { "user", oUser },
191 { "host", oHost },
192 { "escapechar", oEscapeChar },
193 { "globalknownhostsfile", oGlobalKnownHostsFile },
194 { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */
195 { "userknownhostsfile", oUserKnownHostsFile },
196 { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
197 { "connectionattempts", oConnectionAttempts },
198 { "batchmode", oBatchMode },
199 { "checkhostip", oCheckHostIP },
200 { "stricthostkeychecking", oStrictHostKeyChecking },
201 { "compression", oCompression },
202 { "compressionlevel", oCompressionLevel },
203 { "tcpkeepalive", oTCPKeepAlive },
204 { "keepalive", oTCPKeepAlive }, /* obsolete */
205 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
206 { "loglevel", oLogLevel },
207 { "dynamicforward", oDynamicForward },
208 { "preferredauthentications", oPreferredAuthentications },
209 { "hostkeyalgorithms", oHostKeyAlgorithms },
210 { "bindaddress", oBindAddress },
211 #ifdef ENABLE_PKCS11
212 { "smartcarddevice", oPKCS11Provider },
213 { "pkcs11provider", oPKCS11Provider },
214 #else
215 { "smartcarddevice", oUnsupported },
216 { "pkcs11provider", oUnsupported },
217 #endif
218 { "clearallforwardings", oClearAllForwardings },
219 { "enablesshkeysign", oEnableSSHKeysign },
220 { "verifyhostkeydns", oVerifyHostKeyDNS },
221 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
222 { "rekeylimit", oRekeyLimit },
223 { "connecttimeout", oConnectTimeout },
224 { "addressfamily", oAddressFamily },
225 { "serveraliveinterval", oServerAliveInterval },
226 { "serveralivecountmax", oServerAliveCountMax },
227 { "sendenv", oSendEnv },
228 { "controlpath", oControlPath },
229 { "controlmaster", oControlMaster },
230 { "controlpersist", oControlPersist },
231 { "hashknownhosts", oHashKnownHosts },
232 { "tunnel", oTunnel },
233 { "tunneldevice", oTunnelDevice },
234 { "localcommand", oLocalCommand },
235 { "permitlocalcommand", oPermitLocalCommand },
236 { "visualhostkey", oVisualHostKey },
237 { "useroaming", oUseRoaming },
238 #ifdef JPAKE
239 { "zeroknowledgepasswordauthentication",
240 oZeroKnowledgePasswordAuthentication },
241 #else
242 { "zeroknowledgepasswordauthentication", oUnsupported },
243 #endif
244 { "kexalgorithms", oKexAlgorithms },
246 { NULL, oBadOption }
250 * Adds a local TCP/IP port forward to options. Never returns if there is an
251 * error.
254 void
255 add_local_forward(Options *options, const Forward *newfwd)
257 Forward *fwd;
258 #ifndef NO_IPPORT_RESERVED_CONCEPT
259 extern uid_t original_real_uid;
260 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
261 fatal("Privileged ports can only be forwarded by root.");
262 #endif
263 options->local_forwards = xrealloc(options->local_forwards,
264 options->num_local_forwards + 1,
265 sizeof(*options->local_forwards));
266 fwd = &options->local_forwards[options->num_local_forwards++];
268 fwd->listen_host = newfwd->listen_host;
269 fwd->listen_port = newfwd->listen_port;
270 fwd->connect_host = newfwd->connect_host;
271 fwd->connect_port = newfwd->connect_port;
275 * Adds a remote TCP/IP port forward to options. Never returns if there is
276 * an error.
279 void
280 add_remote_forward(Options *options, const Forward *newfwd)
282 Forward *fwd;
284 options->remote_forwards = xrealloc(options->remote_forwards,
285 options->num_remote_forwards + 1,
286 sizeof(*options->remote_forwards));
287 fwd = &options->remote_forwards[options->num_remote_forwards++];
289 fwd->listen_host = newfwd->listen_host;
290 fwd->listen_port = newfwd->listen_port;
291 fwd->connect_host = newfwd->connect_host;
292 fwd->connect_port = newfwd->connect_port;
293 fwd->allocated_port = 0;
296 static void
297 clear_forwardings(Options *options)
299 int i;
301 for (i = 0; i < options->num_local_forwards; i++) {
302 if (options->local_forwards[i].listen_host != NULL)
303 xfree(options->local_forwards[i].listen_host);
304 xfree(options->local_forwards[i].connect_host);
306 if (options->num_local_forwards > 0) {
307 xfree(options->local_forwards);
308 options->local_forwards = NULL;
310 options->num_local_forwards = 0;
311 for (i = 0; i < options->num_remote_forwards; i++) {
312 if (options->remote_forwards[i].listen_host != NULL)
313 xfree(options->remote_forwards[i].listen_host);
314 xfree(options->remote_forwards[i].connect_host);
316 if (options->num_remote_forwards > 0) {
317 xfree(options->remote_forwards);
318 options->remote_forwards = NULL;
320 options->num_remote_forwards = 0;
321 options->tun_open = SSH_TUNMODE_NO;
325 * Returns the number of the token pointed to by cp or oBadOption.
328 static OpCodes
329 parse_token(const char *cp, const char *filename, int linenum)
331 u_int i;
333 for (i = 0; keywords[i].name; i++)
334 if (strcasecmp(cp, keywords[i].name) == 0)
335 return keywords[i].opcode;
337 error("%s: line %d: Bad configuration option: %s",
338 filename, linenum, cp);
339 return oBadOption;
343 * Processes a single option line as used in the configuration files. This
344 * only sets those values that have not already been set.
346 #define WHITESPACE " \t\r\n"
349 process_config_line(Options *options, const char *host,
350 char *line, const char *filename, int linenum,
351 int *activep)
353 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
354 int opcode, *intptr, value, value2, scale;
355 LogLevel *log_level_ptr;
356 long long orig, val64;
357 size_t len;
358 Forward fwd;
360 /* Strip trailing whitespace */
361 for (len = strlen(line) - 1; len > 0; len--) {
362 if (strchr(WHITESPACE, line[len]) == NULL)
363 break;
364 line[len] = '\0';
367 s = line;
368 /* Get the keyword. (Each line is supposed to begin with a keyword). */
369 if ((keyword = strdelim(&s)) == NULL)
370 return 0;
371 /* Ignore leading whitespace. */
372 if (*keyword == '\0')
373 keyword = strdelim(&s);
374 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
375 return 0;
377 opcode = parse_token(keyword, filename, linenum);
379 switch (opcode) {
380 case oBadOption:
381 /* don't panic, but count bad options */
382 return -1;
383 /* NOTREACHED */
384 case oConnectTimeout:
385 intptr = &options->connection_timeout;
386 parse_time:
387 arg = strdelim(&s);
388 if (!arg || *arg == '\0')
389 fatal("%s line %d: missing time value.",
390 filename, linenum);
391 if ((value = convtime(arg)) == -1)
392 fatal("%s line %d: invalid time value.",
393 filename, linenum);
394 if (*activep && *intptr == -1)
395 *intptr = value;
396 break;
398 case oForwardAgent:
399 intptr = &options->forward_agent;
400 parse_flag:
401 arg = strdelim(&s);
402 if (!arg || *arg == '\0')
403 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
404 value = 0; /* To avoid compiler warning... */
405 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
406 value = 1;
407 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
408 value = 0;
409 else
410 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
411 if (*activep && *intptr == -1)
412 *intptr = value;
413 break;
415 case oForwardX11:
416 intptr = &options->forward_x11;
417 goto parse_flag;
419 case oForwardX11Trusted:
420 intptr = &options->forward_x11_trusted;
421 goto parse_flag;
423 case oForwardX11Timeout:
424 intptr = &options->forward_x11_timeout;
425 goto parse_time;
427 case oGatewayPorts:
428 intptr = &options->gateway_ports;
429 goto parse_flag;
431 case oExitOnForwardFailure:
432 intptr = &options->exit_on_forward_failure;
433 goto parse_flag;
435 case oUsePrivilegedPort:
436 intptr = &options->use_privileged_port;
437 goto parse_flag;
439 case oPasswordAuthentication:
440 intptr = &options->password_authentication;
441 goto parse_flag;
443 case oZeroKnowledgePasswordAuthentication:
444 intptr = &options->zero_knowledge_password_authentication;
445 goto parse_flag;
447 case oKbdInteractiveAuthentication:
448 intptr = &options->kbd_interactive_authentication;
449 goto parse_flag;
451 case oKbdInteractiveDevices:
452 charptr = &options->kbd_interactive_devices;
453 goto parse_string;
455 case oPubkeyAuthentication:
456 intptr = &options->pubkey_authentication;
457 goto parse_flag;
459 case oRSAAuthentication:
460 intptr = &options->rsa_authentication;
461 goto parse_flag;
463 case oRhostsRSAAuthentication:
464 intptr = &options->rhosts_rsa_authentication;
465 goto parse_flag;
467 case oHostbasedAuthentication:
468 intptr = &options->hostbased_authentication;
469 goto parse_flag;
471 case oChallengeResponseAuthentication:
472 intptr = &options->challenge_response_authentication;
473 goto parse_flag;
475 case oGssAuthentication:
476 intptr = &options->gss_authentication;
477 goto parse_flag;
479 case oGssDelegateCreds:
480 intptr = &options->gss_deleg_creds;
481 goto parse_flag;
483 case oBatchMode:
484 intptr = &options->batch_mode;
485 goto parse_flag;
487 case oCheckHostIP:
488 intptr = &options->check_host_ip;
489 goto parse_flag;
491 case oVerifyHostKeyDNS:
492 intptr = &options->verify_host_key_dns;
493 goto parse_yesnoask;
495 case oStrictHostKeyChecking:
496 intptr = &options->strict_host_key_checking;
497 parse_yesnoask:
498 arg = strdelim(&s);
499 if (!arg || *arg == '\0')
500 fatal("%.200s line %d: Missing yes/no/ask argument.",
501 filename, linenum);
502 value = 0; /* To avoid compiler warning... */
503 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
504 value = 1;
505 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
506 value = 0;
507 else if (strcmp(arg, "ask") == 0)
508 value = 2;
509 else
510 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
511 if (*activep && *intptr == -1)
512 *intptr = value;
513 break;
515 case oCompression:
516 intptr = &options->compression;
517 goto parse_flag;
519 case oTCPKeepAlive:
520 intptr = &options->tcp_keep_alive;
521 goto parse_flag;
523 case oNoHostAuthenticationForLocalhost:
524 intptr = &options->no_host_authentication_for_localhost;
525 goto parse_flag;
527 case oNumberOfPasswordPrompts:
528 intptr = &options->number_of_password_prompts;
529 goto parse_int;
531 case oCompressionLevel:
532 intptr = &options->compression_level;
533 goto parse_int;
535 case oRekeyLimit:
536 arg = strdelim(&s);
537 if (!arg || *arg == '\0')
538 fatal("%.200s line %d: Missing argument.", filename, linenum);
539 if (arg[0] < '0' || arg[0] > '9')
540 fatal("%.200s line %d: Bad number.", filename, linenum);
541 orig = val64 = strtoll(arg, &endofnumber, 10);
542 if (arg == endofnumber)
543 fatal("%.200s line %d: Bad number.", filename, linenum);
544 switch (toupper(*endofnumber)) {
545 case '\0':
546 scale = 1;
547 break;
548 case 'K':
549 scale = 1<<10;
550 break;
551 case 'M':
552 scale = 1<<20;
553 break;
554 case 'G':
555 scale = 1<<30;
556 break;
557 default:
558 fatal("%.200s line %d: Invalid RekeyLimit suffix",
559 filename, linenum);
561 val64 *= scale;
562 /* detect integer wrap and too-large limits */
563 if ((val64 / scale) != orig || val64 > UINT_MAX)
564 fatal("%.200s line %d: RekeyLimit too large",
565 filename, linenum);
566 if (val64 < 16)
567 fatal("%.200s line %d: RekeyLimit too small",
568 filename, linenum);
569 if (*activep && options->rekey_limit == -1)
570 options->rekey_limit = (u_int32_t)val64;
571 break;
573 case oIdentityFile:
574 arg = strdelim(&s);
575 if (!arg || *arg == '\0')
576 fatal("%.200s line %d: Missing argument.", filename, linenum);
577 if (*activep) {
578 intptr = &options->num_identity_files;
579 if (*intptr >= SSH_MAX_IDENTITY_FILES)
580 fatal("%.200s line %d: Too many identity files specified (max %d).",
581 filename, linenum, SSH_MAX_IDENTITY_FILES);
582 charptr = &options->identity_files[*intptr];
583 *charptr = xstrdup(arg);
584 *intptr = *intptr + 1;
586 break;
588 case oXAuthLocation:
589 charptr=&options->xauth_location;
590 goto parse_string;
592 case oUser:
593 charptr = &options->user;
594 parse_string:
595 arg = strdelim(&s);
596 if (!arg || *arg == '\0')
597 fatal("%.200s line %d: Missing argument.", filename, linenum);
598 if (*activep && *charptr == NULL)
599 *charptr = xstrdup(arg);
600 break;
602 case oGlobalKnownHostsFile:
603 charptr = &options->system_hostfile;
604 goto parse_string;
606 case oUserKnownHostsFile:
607 charptr = &options->user_hostfile;
608 goto parse_string;
610 case oGlobalKnownHostsFile2:
611 charptr = &options->system_hostfile2;
612 goto parse_string;
614 case oUserKnownHostsFile2:
615 charptr = &options->user_hostfile2;
616 goto parse_string;
618 case oHostName:
619 charptr = &options->hostname;
620 goto parse_string;
622 case oHostKeyAlias:
623 charptr = &options->host_key_alias;
624 goto parse_string;
626 case oPreferredAuthentications:
627 charptr = &options->preferred_authentications;
628 goto parse_string;
630 case oBindAddress:
631 charptr = &options->bind_address;
632 goto parse_string;
634 case oPKCS11Provider:
635 charptr = &options->pkcs11_provider;
636 goto parse_string;
638 case oProxyCommand:
639 charptr = &options->proxy_command;
640 parse_command:
641 if (s == NULL)
642 fatal("%.200s line %d: Missing argument.", filename, linenum);
643 len = strspn(s, WHITESPACE "=");
644 if (*activep && *charptr == NULL)
645 *charptr = xstrdup(s + len);
646 return 0;
648 case oPort:
649 intptr = &options->port;
650 parse_int:
651 arg = strdelim(&s);
652 if (!arg || *arg == '\0')
653 fatal("%.200s line %d: Missing argument.", filename, linenum);
654 if (arg[0] < '0' || arg[0] > '9')
655 fatal("%.200s line %d: Bad number.", filename, linenum);
657 /* Octal, decimal, or hex format? */
658 value = strtol(arg, &endofnumber, 0);
659 if (arg == endofnumber)
660 fatal("%.200s line %d: Bad number.", filename, linenum);
661 if (*activep && *intptr == -1)
662 *intptr = value;
663 break;
665 case oConnectionAttempts:
666 intptr = &options->connection_attempts;
667 goto parse_int;
669 case oCipher:
670 intptr = &options->cipher;
671 arg = strdelim(&s);
672 if (!arg || *arg == '\0')
673 fatal("%.200s line %d: Missing argument.", filename, linenum);
674 value = cipher_number(arg);
675 if (value == -1)
676 fatal("%.200s line %d: Bad cipher '%s'.",
677 filename, linenum, arg ? arg : "<NONE>");
678 if (*activep && *intptr == -1)
679 *intptr = value;
680 break;
682 case oCiphers:
683 arg = strdelim(&s);
684 if (!arg || *arg == '\0')
685 fatal("%.200s line %d: Missing argument.", filename, linenum);
686 if (!ciphers_valid(arg))
687 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
688 filename, linenum, arg ? arg : "<NONE>");
689 if (*activep && options->ciphers == NULL)
690 options->ciphers = xstrdup(arg);
691 break;
693 case oMacs:
694 arg = strdelim(&s);
695 if (!arg || *arg == '\0')
696 fatal("%.200s line %d: Missing argument.", filename, linenum);
697 if (!mac_valid(arg))
698 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
699 filename, linenum, arg ? arg : "<NONE>");
700 if (*activep && options->macs == NULL)
701 options->macs = xstrdup(arg);
702 break;
704 case oKexAlgorithms:
705 arg = strdelim(&s);
706 if (!arg || *arg == '\0')
707 fatal("%.200s line %d: Missing argument.",
708 filename, linenum);
709 if (!kex_names_valid(arg))
710 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
711 filename, linenum, arg ? arg : "<NONE>");
712 if (*activep && options->kex_algorithms == NULL)
713 options->kex_algorithms = xstrdup(arg);
714 break;
716 case oHostKeyAlgorithms:
717 arg = strdelim(&s);
718 if (!arg || *arg == '\0')
719 fatal("%.200s line %d: Missing argument.", filename, linenum);
720 if (!key_names_valid2(arg))
721 fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
722 filename, linenum, arg ? arg : "<NONE>");
723 if (*activep && options->hostkeyalgorithms == NULL)
724 options->hostkeyalgorithms = xstrdup(arg);
725 break;
727 case oProtocol:
728 intptr = &options->protocol;
729 arg = strdelim(&s);
730 if (!arg || *arg == '\0')
731 fatal("%.200s line %d: Missing argument.", filename, linenum);
732 value = proto_spec(arg);
733 if (value == SSH_PROTO_UNKNOWN)
734 fatal("%.200s line %d: Bad protocol spec '%s'.",
735 filename, linenum, arg ? arg : "<NONE>");
736 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
737 *intptr = value;
738 break;
740 case oLogLevel:
741 log_level_ptr = &options->log_level;
742 arg = strdelim(&s);
743 value = log_level_number(arg);
744 if (value == SYSLOG_LEVEL_NOT_SET)
745 fatal("%.200s line %d: unsupported log level '%s'",
746 filename, linenum, arg ? arg : "<NONE>");
747 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
748 *log_level_ptr = (LogLevel) value;
749 break;
751 case oLocalForward:
752 case oRemoteForward:
753 case oDynamicForward:
754 arg = strdelim(&s);
755 if (arg == NULL || *arg == '\0')
756 fatal("%.200s line %d: Missing port argument.",
757 filename, linenum);
759 if (opcode == oLocalForward ||
760 opcode == oRemoteForward) {
761 arg2 = strdelim(&s);
762 if (arg2 == NULL || *arg2 == '\0')
763 fatal("%.200s line %d: Missing target argument.",
764 filename, linenum);
766 /* construct a string for parse_forward */
767 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
768 } else if (opcode == oDynamicForward) {
769 strlcpy(fwdarg, arg, sizeof(fwdarg));
772 if (parse_forward(&fwd, fwdarg,
773 opcode == oDynamicForward ? 1 : 0,
774 opcode == oRemoteForward ? 1 : 0) == 0)
775 fatal("%.200s line %d: Bad forwarding specification.",
776 filename, linenum);
778 if (*activep) {
779 if (opcode == oLocalForward ||
780 opcode == oDynamicForward)
781 add_local_forward(options, &fwd);
782 else if (opcode == oRemoteForward)
783 add_remote_forward(options, &fwd);
785 break;
787 case oClearAllForwardings:
788 intptr = &options->clear_forwardings;
789 goto parse_flag;
791 case oHost:
792 *activep = 0;
793 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
794 if (match_pattern(host, arg)) {
795 debug("Applying options for %.100s", arg);
796 *activep = 1;
797 break;
799 /* Avoid garbage check below, as strdelim is done. */
800 return 0;
802 case oEscapeChar:
803 intptr = &options->escape_char;
804 arg = strdelim(&s);
805 if (!arg || *arg == '\0')
806 fatal("%.200s line %d: Missing argument.", filename, linenum);
807 if (arg[0] == '^' && arg[2] == 0 &&
808 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
809 value = (u_char) arg[1] & 31;
810 else if (strlen(arg) == 1)
811 value = (u_char) arg[0];
812 else if (strcmp(arg, "none") == 0)
813 value = SSH_ESCAPECHAR_NONE;
814 else {
815 fatal("%.200s line %d: Bad escape character.",
816 filename, linenum);
817 /* NOTREACHED */
818 value = 0; /* Avoid compiler warning. */
820 if (*activep && *intptr == -1)
821 *intptr = value;
822 break;
824 case oAddressFamily:
825 arg = strdelim(&s);
826 if (!arg || *arg == '\0')
827 fatal("%s line %d: missing address family.",
828 filename, linenum);
829 intptr = &options->address_family;
830 if (strcasecmp(arg, "inet") == 0)
831 value = AF_INET;
832 else if (strcasecmp(arg, "inet6") == 0)
833 value = AF_INET6;
834 else if (strcasecmp(arg, "any") == 0)
835 value = AF_UNSPEC;
836 else
837 fatal("Unsupported AddressFamily \"%s\"", arg);
838 if (*activep && *intptr == -1)
839 *intptr = value;
840 break;
842 case oEnableSSHKeysign:
843 intptr = &options->enable_ssh_keysign;
844 goto parse_flag;
846 case oIdentitiesOnly:
847 intptr = &options->identities_only;
848 goto parse_flag;
850 case oServerAliveInterval:
851 intptr = &options->server_alive_interval;
852 goto parse_time;
854 case oServerAliveCountMax:
855 intptr = &options->server_alive_count_max;
856 goto parse_int;
858 case oSendEnv:
859 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
860 if (strchr(arg, '=') != NULL)
861 fatal("%s line %d: Invalid environment name.",
862 filename, linenum);
863 if (!*activep)
864 continue;
865 if (options->num_send_env >= MAX_SEND_ENV)
866 fatal("%s line %d: too many send env.",
867 filename, linenum);
868 options->send_env[options->num_send_env++] =
869 xstrdup(arg);
871 break;
873 case oControlPath:
874 charptr = &options->control_path;
875 goto parse_string;
877 case oControlMaster:
878 intptr = &options->control_master;
879 arg = strdelim(&s);
880 if (!arg || *arg == '\0')
881 fatal("%.200s line %d: Missing ControlMaster argument.",
882 filename, linenum);
883 value = 0; /* To avoid compiler warning... */
884 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
885 value = SSHCTL_MASTER_YES;
886 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
887 value = SSHCTL_MASTER_NO;
888 else if (strcmp(arg, "auto") == 0)
889 value = SSHCTL_MASTER_AUTO;
890 else if (strcmp(arg, "ask") == 0)
891 value = SSHCTL_MASTER_ASK;
892 else if (strcmp(arg, "autoask") == 0)
893 value = SSHCTL_MASTER_AUTO_ASK;
894 else
895 fatal("%.200s line %d: Bad ControlMaster argument.",
896 filename, linenum);
897 if (*activep && *intptr == -1)
898 *intptr = value;
899 break;
901 case oControlPersist:
902 /* no/false/yes/true, or a time spec */
903 intptr = &options->control_persist;
904 arg = strdelim(&s);
905 if (!arg || *arg == '\0')
906 fatal("%.200s line %d: Missing ControlPersist"
907 " argument.", filename, linenum);
908 value = 0;
909 value2 = 0; /* timeout */
910 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
911 value = 0;
912 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
913 value = 1;
914 else if ((value2 = convtime(arg)) >= 0)
915 value = 1;
916 else
917 fatal("%.200s line %d: Bad ControlPersist argument.",
918 filename, linenum);
919 if (*activep && *intptr == -1) {
920 *intptr = value;
921 options->control_persist_timeout = value2;
923 break;
925 case oHashKnownHosts:
926 intptr = &options->hash_known_hosts;
927 goto parse_flag;
929 case oTunnel:
930 intptr = &options->tun_open;
931 arg = strdelim(&s);
932 if (!arg || *arg == '\0')
933 fatal("%s line %d: Missing yes/point-to-point/"
934 "ethernet/no argument.", filename, linenum);
935 value = 0; /* silence compiler */
936 if (strcasecmp(arg, "ethernet") == 0)
937 value = SSH_TUNMODE_ETHERNET;
938 else if (strcasecmp(arg, "point-to-point") == 0)
939 value = SSH_TUNMODE_POINTOPOINT;
940 else if (strcasecmp(arg, "yes") == 0)
941 value = SSH_TUNMODE_DEFAULT;
942 else if (strcasecmp(arg, "no") == 0)
943 value = SSH_TUNMODE_NO;
944 else
945 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
946 "no argument: %s", filename, linenum, arg);
947 if (*activep)
948 *intptr = value;
949 break;
951 case oTunnelDevice:
952 arg = strdelim(&s);
953 if (!arg || *arg == '\0')
954 fatal("%.200s line %d: Missing argument.", filename, linenum);
955 value = a2tun(arg, &value2);
956 if (value == SSH_TUNID_ERR)
957 fatal("%.200s line %d: Bad tun device.", filename, linenum);
958 if (*activep) {
959 options->tun_local = value;
960 options->tun_remote = value2;
962 break;
964 case oLocalCommand:
965 charptr = &options->local_command;
966 goto parse_command;
968 case oPermitLocalCommand:
969 intptr = &options->permit_local_command;
970 goto parse_flag;
972 case oVisualHostKey:
973 intptr = &options->visual_host_key;
974 goto parse_flag;
976 case oUseRoaming:
977 intptr = &options->use_roaming;
978 goto parse_flag;
980 case oDeprecated:
981 debug("%s line %d: Deprecated option \"%s\"",
982 filename, linenum, keyword);
983 return 0;
985 case oUnsupported:
986 error("%s line %d: Unsupported option \"%s\"",
987 filename, linenum, keyword);
988 return 0;
990 default:
991 fatal("process_config_line: Unimplemented opcode %d", opcode);
994 /* Check that there is no garbage at end of line. */
995 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
996 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
997 filename, linenum, arg);
999 return 0;
1004 * Reads the config file and modifies the options accordingly. Options
1005 * should already be initialized before this call. This never returns if
1006 * there is an error. If the file does not exist, this returns 0.
1010 read_config_file(const char *filename, const char *host, Options *options,
1011 int checkperm)
1013 FILE *f;
1014 char line[1024];
1015 int active, linenum;
1016 int bad_options = 0;
1018 if ((f = fopen(filename, "r")) == NULL)
1019 return 0;
1021 if (checkperm) {
1022 struct stat sb;
1024 if (fstat(fileno(f), &sb) == -1)
1025 fatal("fstat %s: %s", filename, strerror(errno));
1026 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1027 (sb.st_mode & 022) != 0))
1028 fatal("Bad owner or permissions on %s", filename);
1031 debug("Reading configuration data %.200s", filename);
1034 * Mark that we are now processing the options. This flag is turned
1035 * on/off by Host specifications.
1037 active = 1;
1038 linenum = 0;
1039 while (fgets(line, sizeof(line), f)) {
1040 /* Update line number counter. */
1041 linenum++;
1042 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1043 bad_options++;
1045 fclose(f);
1046 if (bad_options > 0)
1047 fatal("%s: terminating, %d bad configuration options",
1048 filename, bad_options);
1049 return 1;
1053 * Initializes options to special values that indicate that they have not yet
1054 * been set. Read_config_file will only set options with this value. Options
1055 * are processed in the following order: command line, user config file,
1056 * system config file. Last, fill_default_options is called.
1059 void
1060 initialize_options(Options * options)
1062 memset(options, 'X', sizeof(*options));
1063 options->forward_agent = -1;
1064 options->forward_x11 = -1;
1065 options->forward_x11_trusted = -1;
1066 options->forward_x11_timeout = -1;
1067 options->exit_on_forward_failure = -1;
1068 options->xauth_location = NULL;
1069 options->gateway_ports = -1;
1070 options->use_privileged_port = -1;
1071 options->rsa_authentication = -1;
1072 options->pubkey_authentication = -1;
1073 options->challenge_response_authentication = -1;
1074 options->gss_authentication = -1;
1075 options->gss_deleg_creds = -1;
1076 options->password_authentication = -1;
1077 options->kbd_interactive_authentication = -1;
1078 options->kbd_interactive_devices = NULL;
1079 options->rhosts_rsa_authentication = -1;
1080 options->hostbased_authentication = -1;
1081 options->batch_mode = -1;
1082 options->check_host_ip = -1;
1083 options->strict_host_key_checking = -1;
1084 options->compression = -1;
1085 options->tcp_keep_alive = -1;
1086 options->compression_level = -1;
1087 options->port = -1;
1088 options->address_family = -1;
1089 options->connection_attempts = -1;
1090 options->connection_timeout = -1;
1091 options->number_of_password_prompts = -1;
1092 options->cipher = -1;
1093 options->ciphers = NULL;
1094 options->macs = NULL;
1095 options->kex_algorithms = NULL;
1096 options->hostkeyalgorithms = NULL;
1097 options->protocol = SSH_PROTO_UNKNOWN;
1098 options->num_identity_files = 0;
1099 options->hostname = NULL;
1100 options->host_key_alias = NULL;
1101 options->proxy_command = NULL;
1102 options->user = NULL;
1103 options->escape_char = -1;
1104 options->system_hostfile = NULL;
1105 options->user_hostfile = NULL;
1106 options->system_hostfile2 = NULL;
1107 options->user_hostfile2 = NULL;
1108 options->local_forwards = NULL;
1109 options->num_local_forwards = 0;
1110 options->remote_forwards = NULL;
1111 options->num_remote_forwards = 0;
1112 options->clear_forwardings = -1;
1113 options->log_level = SYSLOG_LEVEL_NOT_SET;
1114 options->preferred_authentications = NULL;
1115 options->bind_address = NULL;
1116 options->pkcs11_provider = NULL;
1117 options->enable_ssh_keysign = - 1;
1118 options->no_host_authentication_for_localhost = - 1;
1119 options->identities_only = - 1;
1120 options->rekey_limit = - 1;
1121 options->verify_host_key_dns = -1;
1122 options->server_alive_interval = -1;
1123 options->server_alive_count_max = -1;
1124 options->num_send_env = 0;
1125 options->control_path = NULL;
1126 options->control_master = -1;
1127 options->control_persist = -1;
1128 options->control_persist_timeout = 0;
1129 options->hash_known_hosts = -1;
1130 options->tun_open = -1;
1131 options->tun_local = -1;
1132 options->tun_remote = -1;
1133 options->local_command = NULL;
1134 options->permit_local_command = -1;
1135 options->use_roaming = -1;
1136 options->visual_host_key = -1;
1137 options->zero_knowledge_password_authentication = -1;
1141 * Called after processing other sources of option data, this fills those
1142 * options for which no value has been specified with their default values.
1145 void
1146 fill_default_options(Options * options)
1148 int len;
1150 if (options->forward_agent == -1)
1151 options->forward_agent = 0;
1152 if (options->forward_x11 == -1)
1153 options->forward_x11 = 0;
1154 if (options->forward_x11_trusted == -1)
1155 options->forward_x11_trusted = 0;
1156 if (options->forward_x11_timeout == -1)
1157 options->forward_x11_timeout = 1200;
1158 if (options->exit_on_forward_failure == -1)
1159 options->exit_on_forward_failure = 0;
1160 if (options->xauth_location == NULL)
1161 options->xauth_location = _PATH_XAUTH;
1162 if (options->gateway_ports == -1)
1163 options->gateway_ports = 0;
1164 if (options->use_privileged_port == -1)
1165 options->use_privileged_port = 0;
1166 if (options->rsa_authentication == -1)
1167 options->rsa_authentication = 1;
1168 if (options->pubkey_authentication == -1)
1169 options->pubkey_authentication = 1;
1170 if (options->challenge_response_authentication == -1)
1171 options->challenge_response_authentication = 1;
1172 if (options->gss_authentication == -1)
1173 options->gss_authentication = 0;
1174 if (options->gss_deleg_creds == -1)
1175 options->gss_deleg_creds = 0;
1176 if (options->password_authentication == -1)
1177 options->password_authentication = 1;
1178 if (options->kbd_interactive_authentication == -1)
1179 options->kbd_interactive_authentication = 1;
1180 if (options->rhosts_rsa_authentication == -1)
1181 options->rhosts_rsa_authentication = 0;
1182 if (options->hostbased_authentication == -1)
1183 options->hostbased_authentication = 0;
1184 if (options->batch_mode == -1)
1185 options->batch_mode = 0;
1186 if (options->check_host_ip == -1)
1187 options->check_host_ip = 1;
1188 if (options->strict_host_key_checking == -1)
1189 options->strict_host_key_checking = 2; /* 2 is default */
1190 if (options->compression == -1)
1191 options->compression = 0;
1192 if (options->tcp_keep_alive == -1)
1193 options->tcp_keep_alive = 1;
1194 if (options->compression_level == -1)
1195 options->compression_level = 6;
1196 if (options->port == -1)
1197 options->port = 0; /* Filled in ssh_connect. */
1198 if (options->address_family == -1)
1199 options->address_family = AF_UNSPEC;
1200 if (options->connection_attempts == -1)
1201 options->connection_attempts = 1;
1202 if (options->number_of_password_prompts == -1)
1203 options->number_of_password_prompts = 3;
1204 /* Selected in ssh_login(). */
1205 if (options->cipher == -1)
1206 options->cipher = SSH_CIPHER_NOT_SET;
1207 /* options->ciphers, default set in myproposals.h */
1208 /* options->macs, default set in myproposals.h */
1209 /* options->kex_algorithms, default set in myproposals.h */
1210 /* options->hostkeyalgorithms, default set in myproposals.h */
1211 if (options->protocol == SSH_PROTO_UNKNOWN)
1212 options->protocol = SSH_PROTO_2;
1213 if (options->num_identity_files == 0) {
1214 if (options->protocol & SSH_PROTO_1) {
1215 len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1216 options->identity_files[options->num_identity_files] =
1217 xmalloc(len);
1218 snprintf(options->identity_files[options->num_identity_files++],
1219 len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1221 if (options->protocol & SSH_PROTO_2) {
1222 len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1223 options->identity_files[options->num_identity_files] =
1224 xmalloc(len);
1225 snprintf(options->identity_files[options->num_identity_files++],
1226 len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1228 len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1229 options->identity_files[options->num_identity_files] =
1230 xmalloc(len);
1231 snprintf(options->identity_files[options->num_identity_files++],
1232 len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1233 #ifdef OPENSSL_HAS_ECC
1234 len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
1235 options->identity_files[options->num_identity_files] =
1236 xmalloc(len);
1237 snprintf(options->identity_files[options->num_identity_files++],
1238 len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
1239 #endif
1242 if (options->escape_char == -1)
1243 options->escape_char = '~';
1244 if (options->system_hostfile == NULL)
1245 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1246 if (options->user_hostfile == NULL)
1247 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1248 if (options->system_hostfile2 == NULL)
1249 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1250 if (options->user_hostfile2 == NULL)
1251 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1252 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1253 options->log_level = SYSLOG_LEVEL_INFO;
1254 if (options->clear_forwardings == 1)
1255 clear_forwardings(options);
1256 if (options->no_host_authentication_for_localhost == - 1)
1257 options->no_host_authentication_for_localhost = 0;
1258 if (options->identities_only == -1)
1259 options->identities_only = 0;
1260 if (options->enable_ssh_keysign == -1)
1261 options->enable_ssh_keysign = 0;
1262 if (options->rekey_limit == -1)
1263 options->rekey_limit = 0;
1264 if (options->verify_host_key_dns == -1)
1265 options->verify_host_key_dns = 0;
1266 if (options->server_alive_interval == -1)
1267 options->server_alive_interval = 0;
1268 if (options->server_alive_count_max == -1)
1269 options->server_alive_count_max = 3;
1270 if (options->control_master == -1)
1271 options->control_master = 0;
1272 if (options->control_persist == -1) {
1273 options->control_persist = 0;
1274 options->control_persist_timeout = 0;
1276 if (options->hash_known_hosts == -1)
1277 options->hash_known_hosts = 0;
1278 if (options->tun_open == -1)
1279 options->tun_open = SSH_TUNMODE_NO;
1280 if (options->tun_local == -1)
1281 options->tun_local = SSH_TUNID_ANY;
1282 if (options->tun_remote == -1)
1283 options->tun_remote = SSH_TUNID_ANY;
1284 if (options->permit_local_command == -1)
1285 options->permit_local_command = 0;
1286 if (options->use_roaming == -1)
1287 options->use_roaming = 1;
1288 if (options->visual_host_key == -1)
1289 options->visual_host_key = 0;
1290 if (options->zero_knowledge_password_authentication == -1)
1291 options->zero_knowledge_password_authentication = 0;
1292 /* options->local_command should not be set by default */
1293 /* options->proxy_command should not be set by default */
1294 /* options->user will be set in the main program if appropriate */
1295 /* options->hostname will be set in the main program if appropriate */
1296 /* options->host_key_alias should not be set by default */
1297 /* options->preferred_authentications will be set in ssh */
1301 * parse_forward
1302 * parses a string containing a port forwarding specification of the form:
1303 * dynamicfwd == 0
1304 * [listenhost:]listenport:connecthost:connectport
1305 * dynamicfwd == 1
1306 * [listenhost:]listenport
1307 * returns number of arguments parsed or zero on error
1310 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1312 int i;
1313 char *p, *cp, *fwdarg[4];
1315 memset(fwd, '\0', sizeof(*fwd));
1317 cp = p = xstrdup(fwdspec);
1319 /* skip leading spaces */
1320 while (isspace(*cp))
1321 cp++;
1323 for (i = 0; i < 4; ++i)
1324 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1325 break;
1327 /* Check for trailing garbage */
1328 if (cp != NULL)
1329 i = 0; /* failure */
1331 switch (i) {
1332 case 1:
1333 fwd->listen_host = NULL;
1334 fwd->listen_port = a2port(fwdarg[0]);
1335 fwd->connect_host = xstrdup("socks");
1336 break;
1338 case 2:
1339 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1340 fwd->listen_port = a2port(fwdarg[1]);
1341 fwd->connect_host = xstrdup("socks");
1342 break;
1344 case 3:
1345 fwd->listen_host = NULL;
1346 fwd->listen_port = a2port(fwdarg[0]);
1347 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1348 fwd->connect_port = a2port(fwdarg[2]);
1349 break;
1351 case 4:
1352 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1353 fwd->listen_port = a2port(fwdarg[1]);
1354 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1355 fwd->connect_port = a2port(fwdarg[3]);
1356 break;
1357 default:
1358 i = 0; /* failure */
1361 xfree(p);
1363 if (dynamicfwd) {
1364 if (!(i == 1 || i == 2))
1365 goto fail_free;
1366 } else {
1367 if (!(i == 3 || i == 4))
1368 goto fail_free;
1369 if (fwd->connect_port <= 0)
1370 goto fail_free;
1373 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1374 goto fail_free;
1376 if (fwd->connect_host != NULL &&
1377 strlen(fwd->connect_host) >= NI_MAXHOST)
1378 goto fail_free;
1379 if (fwd->listen_host != NULL &&
1380 strlen(fwd->listen_host) >= NI_MAXHOST)
1381 goto fail_free;
1384 return (i);
1386 fail_free:
1387 if (fwd->connect_host != NULL) {
1388 xfree(fwd->connect_host);
1389 fwd->connect_host = NULL;
1391 if (fwd->listen_host != NULL) {
1392 xfree(fwd->listen_host);
1393 fwd->listen_host = NULL;
1395 return (0);