1 /* $OpenBSD: readconf.c,v 1.393 2024/11/27 16:07:08 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
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".
17 #include <sys/types.h>
19 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <arpa/inet.h>
46 #ifdef USE_SYSTEM_GLOB
49 # include "openbsd-compat/glob.h"
54 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
62 #include "pathnames.h"
71 #include "myproposal.h"
74 /* Format of the configuration file:
76 # Configuration data is parsed as follows:
77 # 1. command line options
78 # 2. user-specific file
80 # Any configuration value is only changed the first time it is set.
81 # Thus, host-specific definitions should be at the beginning of the
82 # configuration file, and defaults at the end.
84 # Host-specific declarations. These may override anything above. A single
85 # host may match multiple declarations; these are processed in the order
86 # that they are given in.
92 Hostname another.host.name.real.org
99 RemoteForward 9999 shadows.cs.hut.fi:9999
102 Host fascist.blob.com
105 PasswordAuthentication no
109 ProxyCommand ssh-proxy %h %p
112 PublicKeyAuthentication no
116 PasswordAuthentication no
122 # Defaults for various options
126 PasswordAuthentication yes
127 StrictHostKeyChecking yes
129 IdentityFile ~/.ssh/identity
135 static int read_config_file_depth(const char *filename
, struct passwd
*pw
,
136 const char *host
, const char *original_host
, Options
*options
,
137 int flags
, int *activep
, int *want_final_pass
, int depth
);
138 static int process_config_line_depth(Options
*options
, struct passwd
*pw
,
139 const char *host
, const char *original_host
, char *line
,
140 const char *filename
, int linenum
, int *activep
, int flags
,
141 int *want_final_pass
, int depth
);
143 /* Keyword tokens. */
147 oHost
, oMatch
, oInclude
, oTag
,
148 oForwardAgent
, oForwardX11
, oForwardX11Trusted
, oForwardX11Timeout
,
149 oGatewayPorts
, oExitOnForwardFailure
,
150 oPasswordAuthentication
,
152 oIdentityFile
, oHostname
, oPort
, oRemoteForward
, oLocalForward
,
154 oCertificateFile
, oAddKeysToAgent
, oIdentityAgent
,
155 oUser
, oEscapeChar
, oProxyCommand
,
156 oGlobalKnownHostsFile
, oUserKnownHostsFile
, oConnectionAttempts
,
157 oBatchMode
, oCheckHostIP
, oStrictHostKeyChecking
, oCompression
,
158 oTCPKeepAlive
, oNumberOfPasswordPrompts
,
159 oLogFacility
, oLogLevel
, oLogVerbose
, oCiphers
, oMacs
,
160 oPubkeyAuthentication
,
161 oKbdInteractiveAuthentication
, oKbdInteractiveDevices
, oHostKeyAlias
,
162 oDynamicForward
, oPreferredAuthentications
, oHostbasedAuthentication
,
163 oHostKeyAlgorithms
, oBindAddress
, oBindInterface
, oPKCS11Provider
,
164 oClearAllForwardings
, oNoHostAuthenticationForLocalhost
,
165 oEnableSSHKeysign
, oRekeyLimit
, oVerifyHostKeyDNS
, oConnectTimeout
,
166 oAddressFamily
, oGssAuthentication
, oGssDelegateCreds
,
167 oServerAliveInterval
, oServerAliveCountMax
, oIdentitiesOnly
,
168 oSendEnv
, oSetEnv
, oControlPath
, oControlMaster
, oControlPersist
,
170 oTunnel
, oTunnelDevice
,
171 oLocalCommand
, oPermitLocalCommand
, oRemoteCommand
,
173 oKexAlgorithms
, oIPQoS
, oRequestTTY
, oSessionType
, oStdinNull
,
174 oForkAfterAuthentication
, oIgnoreUnknown
, oProxyUseFdpass
,
175 oCanonicalDomains
, oCanonicalizeHostname
, oCanonicalizeMaxDots
,
176 oCanonicalizeFallbackLocal
, oCanonicalizePermittedCNAMEs
,
177 oStreamLocalBindMask
, oStreamLocalBindUnlink
, oRevokedHostKeys
,
178 oFingerprintHash
, oUpdateHostkeys
, oHostbasedAcceptedAlgorithms
,
179 oPubkeyAcceptedAlgorithms
, oCASignatureAlgorithms
, oProxyJump
,
180 oSecurityKeyProvider
, oKnownHostsCommand
, oRequiredRSASize
,
181 oEnableEscapeCommandline
, oObscureKeystrokeTiming
, oChannelTimeout
,
182 oIgnore
, oIgnoredUnknownOption
, oDeprecated
, oUnsupported
185 /* Textual representations of the tokens. */
191 /* Deprecated options */
192 { "protocol", oIgnore
}, /* NB. silently ignored */
193 { "cipher", oDeprecated
},
194 { "fallbacktorsh", oDeprecated
},
195 { "globalknownhostsfile2", oDeprecated
},
196 { "rhostsauthentication", oDeprecated
},
197 { "userknownhostsfile2", oDeprecated
},
198 { "useroaming", oDeprecated
},
199 { "usersh", oDeprecated
},
200 { "useprivilegedport", oDeprecated
},
202 /* Unsupported options */
203 { "afstokenpassing", oUnsupported
},
204 { "kerberosauthentication", oUnsupported
},
205 { "kerberostgtpassing", oUnsupported
},
206 { "rsaauthentication", oUnsupported
},
207 { "rhostsrsaauthentication", oUnsupported
},
208 { "compressionlevel", oUnsupported
},
210 /* Sometimes-unsupported options */
212 { "gssapiauthentication", oGssAuthentication
},
213 { "gssapidelegatecredentials", oGssDelegateCreds
},
215 { "gssapiauthentication", oUnsupported
},
216 { "gssapidelegatecredentials", oUnsupported
},
219 { "pkcs11provider", oPKCS11Provider
},
220 { "smartcarddevice", oPKCS11Provider
},
222 { "smartcarddevice", oUnsupported
},
223 { "pkcs11provider", oUnsupported
},
226 { "forwardagent", oForwardAgent
},
227 { "forwardx11", oForwardX11
},
228 { "forwardx11trusted", oForwardX11Trusted
},
229 { "forwardx11timeout", oForwardX11Timeout
},
230 { "exitonforwardfailure", oExitOnForwardFailure
},
231 { "xauthlocation", oXAuthLocation
},
232 { "gatewayports", oGatewayPorts
},
233 { "passwordauthentication", oPasswordAuthentication
},
234 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication
},
235 { "kbdinteractivedevices", oKbdInteractiveDevices
},
236 { "challengeresponseauthentication", oKbdInteractiveAuthentication
}, /* alias */
237 { "skeyauthentication", oKbdInteractiveAuthentication
}, /* alias */
238 { "tisauthentication", oKbdInteractiveAuthentication
}, /* alias */
239 { "pubkeyauthentication", oPubkeyAuthentication
},
240 { "dsaauthentication", oPubkeyAuthentication
}, /* alias */
241 { "hostbasedauthentication", oHostbasedAuthentication
},
242 { "identityfile", oIdentityFile
},
243 { "identityfile2", oIdentityFile
}, /* obsolete */
244 { "identitiesonly", oIdentitiesOnly
},
245 { "certificatefile", oCertificateFile
},
246 { "addkeystoagent", oAddKeysToAgent
},
247 { "identityagent", oIdentityAgent
},
248 { "hostname", oHostname
},
249 { "hostkeyalias", oHostKeyAlias
},
250 { "proxycommand", oProxyCommand
},
252 { "ciphers", oCiphers
},
254 { "remoteforward", oRemoteForward
},
255 { "localforward", oLocalForward
},
256 { "permitremoteopen", oPermitRemoteOpen
},
261 { "escapechar", oEscapeChar
},
262 { "globalknownhostsfile", oGlobalKnownHostsFile
},
263 { "userknownhostsfile", oUserKnownHostsFile
},
264 { "connectionattempts", oConnectionAttempts
},
265 { "batchmode", oBatchMode
},
266 { "checkhostip", oCheckHostIP
},
267 { "stricthostkeychecking", oStrictHostKeyChecking
},
268 { "compression", oCompression
},
269 { "tcpkeepalive", oTCPKeepAlive
},
270 { "keepalive", oTCPKeepAlive
}, /* obsolete */
271 { "numberofpasswordprompts", oNumberOfPasswordPrompts
},
272 { "syslogfacility", oLogFacility
},
273 { "loglevel", oLogLevel
},
274 { "logverbose", oLogVerbose
},
275 { "dynamicforward", oDynamicForward
},
276 { "preferredauthentications", oPreferredAuthentications
},
277 { "hostkeyalgorithms", oHostKeyAlgorithms
},
278 { "casignaturealgorithms", oCASignatureAlgorithms
},
279 { "bindaddress", oBindAddress
},
280 { "bindinterface", oBindInterface
},
281 { "clearallforwardings", oClearAllForwardings
},
282 { "enablesshkeysign", oEnableSSHKeysign
},
283 { "verifyhostkeydns", oVerifyHostKeyDNS
},
284 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost
},
285 { "rekeylimit", oRekeyLimit
},
286 { "connecttimeout", oConnectTimeout
},
287 { "addressfamily", oAddressFamily
},
288 { "serveraliveinterval", oServerAliveInterval
},
289 { "serveralivecountmax", oServerAliveCountMax
},
290 { "sendenv", oSendEnv
},
291 { "setenv", oSetEnv
},
292 { "controlpath", oControlPath
},
293 { "controlmaster", oControlMaster
},
294 { "controlpersist", oControlPersist
},
295 { "hashknownhosts", oHashKnownHosts
},
296 { "include", oInclude
},
297 { "tunnel", oTunnel
},
298 { "tunneldevice", oTunnelDevice
},
299 { "localcommand", oLocalCommand
},
300 { "permitlocalcommand", oPermitLocalCommand
},
301 { "remotecommand", oRemoteCommand
},
302 { "visualhostkey", oVisualHostKey
},
303 { "kexalgorithms", oKexAlgorithms
},
305 { "requesttty", oRequestTTY
},
306 { "sessiontype", oSessionType
},
307 { "stdinnull", oStdinNull
},
308 { "forkafterauthentication", oForkAfterAuthentication
},
309 { "proxyusefdpass", oProxyUseFdpass
},
310 { "canonicaldomains", oCanonicalDomains
},
311 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal
},
312 { "canonicalizehostname", oCanonicalizeHostname
},
313 { "canonicalizemaxdots", oCanonicalizeMaxDots
},
314 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs
},
315 { "streamlocalbindmask", oStreamLocalBindMask
},
316 { "streamlocalbindunlink", oStreamLocalBindUnlink
},
317 { "revokedhostkeys", oRevokedHostKeys
},
318 { "fingerprinthash", oFingerprintHash
},
319 { "updatehostkeys", oUpdateHostkeys
},
320 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms
},
321 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms
}, /* obsolete */
322 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms
},
323 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms
}, /* obsolete */
324 { "ignoreunknown", oIgnoreUnknown
},
325 { "proxyjump", oProxyJump
},
326 { "securitykeyprovider", oSecurityKeyProvider
},
327 { "knownhostscommand", oKnownHostsCommand
},
328 { "requiredrsasize", oRequiredRSASize
},
329 { "enableescapecommandline", oEnableEscapeCommandline
},
330 { "obscurekeystroketiming", oObscureKeystrokeTiming
},
331 { "channeltimeout", oChannelTimeout
},
336 static const char *lookup_opcode_name(OpCodes code
);
339 kex_default_pk_alg(void)
343 if (pkalgs
== NULL
) {
346 all_key
= sshkey_alg_list(0, 0, 1, ',');
347 pkalgs
= match_filter_allowlist(KEX_DEFAULT_PK_ALG
, all_key
);
354 ssh_connection_hash(const char *thishost
, const char *host
, const char *portstr
,
355 const char *user
, const char *jumphost
)
357 struct ssh_digest_ctx
*md
;
358 u_char conn_hash
[SSH_DIGEST_MAX_LENGTH
];
360 if ((md
= ssh_digest_start(SSH_DIGEST_SHA1
)) == NULL
||
361 ssh_digest_update(md
, thishost
, strlen(thishost
)) < 0 ||
362 ssh_digest_update(md
, host
, strlen(host
)) < 0 ||
363 ssh_digest_update(md
, portstr
, strlen(portstr
)) < 0 ||
364 ssh_digest_update(md
, user
, strlen(user
)) < 0 ||
365 ssh_digest_update(md
, jumphost
, strlen(jumphost
)) < 0 ||
366 ssh_digest_final(md
, conn_hash
, sizeof(conn_hash
)) < 0)
367 fatal_f("mux digest failed");
369 return tohex(conn_hash
, ssh_digest_bytes(SSH_DIGEST_SHA1
));
373 * Adds a local TCP/IP port forward to options. Never returns if there is an
378 add_local_forward(Options
*options
, const struct Forward
*newfwd
)
383 /* Don't add duplicates */
384 for (i
= 0; i
< options
->num_local_forwards
; i
++) {
385 if (forward_equals(newfwd
, options
->local_forwards
+ i
))
388 options
->local_forwards
= xreallocarray(options
->local_forwards
,
389 options
->num_local_forwards
+ 1,
390 sizeof(*options
->local_forwards
));
391 fwd
= &options
->local_forwards
[options
->num_local_forwards
++];
393 fwd
->listen_host
= newfwd
->listen_host
;
394 fwd
->listen_port
= newfwd
->listen_port
;
395 fwd
->listen_path
= newfwd
->listen_path
;
396 fwd
->connect_host
= newfwd
->connect_host
;
397 fwd
->connect_port
= newfwd
->connect_port
;
398 fwd
->connect_path
= newfwd
->connect_path
;
402 * Adds a remote TCP/IP port forward to options. Never returns if there is
407 add_remote_forward(Options
*options
, const struct Forward
*newfwd
)
412 /* Don't add duplicates */
413 for (i
= 0; i
< options
->num_remote_forwards
; i
++) {
414 if (forward_equals(newfwd
, options
->remote_forwards
+ i
))
417 options
->remote_forwards
= xreallocarray(options
->remote_forwards
,
418 options
->num_remote_forwards
+ 1,
419 sizeof(*options
->remote_forwards
));
420 fwd
= &options
->remote_forwards
[options
->num_remote_forwards
++];
422 fwd
->listen_host
= newfwd
->listen_host
;
423 fwd
->listen_port
= newfwd
->listen_port
;
424 fwd
->listen_path
= newfwd
->listen_path
;
425 fwd
->connect_host
= newfwd
->connect_host
;
426 fwd
->connect_port
= newfwd
->connect_port
;
427 fwd
->connect_path
= newfwd
->connect_path
;
428 fwd
->handle
= newfwd
->handle
;
429 fwd
->allocated_port
= 0;
433 clear_forwardings(Options
*options
)
437 for (i
= 0; i
< options
->num_local_forwards
; i
++) {
438 free(options
->local_forwards
[i
].listen_host
);
439 free(options
->local_forwards
[i
].listen_path
);
440 free(options
->local_forwards
[i
].connect_host
);
441 free(options
->local_forwards
[i
].connect_path
);
443 if (options
->num_local_forwards
> 0) {
444 free(options
->local_forwards
);
445 options
->local_forwards
= NULL
;
447 options
->num_local_forwards
= 0;
448 for (i
= 0; i
< options
->num_remote_forwards
; i
++) {
449 free(options
->remote_forwards
[i
].listen_host
);
450 free(options
->remote_forwards
[i
].listen_path
);
451 free(options
->remote_forwards
[i
].connect_host
);
452 free(options
->remote_forwards
[i
].connect_path
);
454 if (options
->num_remote_forwards
> 0) {
455 free(options
->remote_forwards
);
456 options
->remote_forwards
= NULL
;
458 options
->num_remote_forwards
= 0;
459 options
->tun_open
= SSH_TUNMODE_NO
;
463 add_certificate_file(Options
*options
, const char *path
, int userprovided
)
467 if (options
->num_certificate_files
>= SSH_MAX_CERTIFICATE_FILES
)
468 fatal("Too many certificate files specified (max %d)",
469 SSH_MAX_CERTIFICATE_FILES
);
471 /* Avoid registering duplicates */
472 for (i
= 0; i
< options
->num_certificate_files
; i
++) {
473 if (options
->certificate_file_userprovided
[i
] == userprovided
&&
474 strcmp(options
->certificate_files
[i
], path
) == 0) {
475 debug2_f("ignoring duplicate key %s", path
);
480 options
->certificate_file_userprovided
[options
->num_certificate_files
] =
482 options
->certificate_files
[options
->num_certificate_files
++] =
487 add_identity_file(Options
*options
, const char *dir
, const char *filename
,
493 if (options
->num_identity_files
>= SSH_MAX_IDENTITY_FILES
)
494 fatal("Too many identity files specified (max %d)",
495 SSH_MAX_IDENTITY_FILES
);
497 if (dir
== NULL
) /* no dir, filename is absolute */
498 path
= xstrdup(filename
);
499 else if (xasprintf(&path
, "%s%s", dir
, filename
) >= PATH_MAX
)
500 fatal("Identity file path %s too long", path
);
502 /* Avoid registering duplicates */
503 for (i
= 0; i
< options
->num_identity_files
; i
++) {
504 if (options
->identity_file_userprovided
[i
] == userprovided
&&
505 strcmp(options
->identity_files
[i
], path
) == 0) {
506 debug2_f("ignoring duplicate key %s", path
);
512 options
->identity_file_userprovided
[options
->num_identity_files
] =
514 options
->identity_files
[options
->num_identity_files
++] = path
;
518 default_ssh_port(void)
524 sp
= getservbyname(SSH_SERVICE_NAME
, "tcp");
525 port
= sp
? ntohs(sp
->s_port
) : SSH_DEFAULT_PORT
;
531 * Execute a command in a shell.
532 * Return its exit status or -1 on abnormal exit.
535 execute_in_shell(const char *cmd
)
541 if ((shell
= getenv("SHELL")) == NULL
)
542 shell
= _PATH_BSHELL
;
544 if (access(shell
, X_OK
) == -1) {
545 fatal("Shell \"%s\" is not executable: %s",
546 shell
, strerror(errno
));
549 debug("Executing command: '%.500s'", cmd
);
551 /* Fork and execute the command. */
552 if ((pid
= fork()) == 0) {
555 if (stdfd_devnull(1, 1, 0) == -1)
556 fatal_f("stdfd_devnull failed");
557 closefrom(STDERR_FILENO
+ 1);
561 argv
[2] = xstrdup(cmd
);
564 execv(argv
[0], argv
);
565 error("Unable to execute '%.100s': %s", cmd
, strerror(errno
));
566 /* Die with signal to make this error apparent to parent. */
567 ssh_signal(SIGTERM
, SIG_DFL
);
568 kill(getpid(), SIGTERM
);
573 fatal_f("fork: %.100s", strerror(errno
));
575 while (waitpid(pid
, &status
, 0) == -1) {
576 if (errno
!= EINTR
&& errno
!= EAGAIN
)
577 fatal_f("waitpid: %s", strerror(errno
));
579 if (!WIFEXITED(status
)) {
580 error("command '%.100s' exited abnormally", cmd
);
583 debug3("command returned status %d", WEXITSTATUS(status
));
584 return WEXITSTATUS(status
);
588 * Check whether a local network interface address appears in CIDR pattern-
589 * list 'addrlist'. Returns 1 if matched or 0 otherwise.
592 check_match_ifaddrs(const char *addrlist
)
594 #ifdef HAVE_IFADDRS_H
595 struct ifaddrs
*ifa
, *ifaddrs
= NULL
;
597 char addr
[NI_MAXHOST
];
600 if (getifaddrs(&ifaddrs
) != 0) {
601 error("match localnetwork: getifaddrs failed: %s",
605 for (ifa
= ifaddrs
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
606 if (ifa
->ifa_addr
== NULL
|| ifa
->ifa_name
== NULL
||
607 (ifa
->ifa_flags
& IFF_UP
) == 0)
609 switch (ifa
->ifa_addr
->sa_family
) {
611 salen
= sizeof(struct sockaddr_in
);
614 salen
= sizeof(struct sockaddr_in6
);
622 debug2_f("interface %s: unsupported address family %d",
623 ifa
->ifa_name
, ifa
->ifa_addr
->sa_family
);
626 if ((r
= getnameinfo(ifa
->ifa_addr
, salen
, addr
, sizeof(addr
),
627 NULL
, 0, NI_NUMERICHOST
)) != 0) {
628 debug2_f("interface %s getnameinfo failed: %s",
629 ifa
->ifa_name
, gai_strerror(r
));
632 debug3_f("interface %s addr %s", ifa
->ifa_name
, addr
);
633 if (addr_match_cidr_list(addr
, addrlist
) == 1) {
634 debug3_f("matched interface %s: address %s in %s",
635 ifa
->ifa_name
, addr
, addrlist
);
640 freeifaddrs(ifaddrs
);
642 #else /* HAVE_IFADDRS_H */
643 error("match localnetwork: not supported on this platform");
645 #endif /* HAVE_IFADDRS_H */
649 * Expand a "match exec" command or an Include path, caller must free returned
653 expand_match_exec_or_include_path(const char *path
, Options
*options
,
654 struct passwd
*pw
, const char *host_arg
, const char *original_host
,
655 int final_pass
, int is_include_path
)
657 char thishost
[NI_MAXHOST
], shorthost
[NI_MAXHOST
], portstr
[NI_MAXSERV
];
658 char uidstr
[32], *conn_hash_hex
, *keyalias
, *jmphost
, *ruser
;
662 port
= options
->port
<= 0 ? default_ssh_port() : options
->port
;
663 ruser
= options
->user
== NULL
? pw
->pw_name
: options
->user
;
665 host
= xstrdup(options
->hostname
);
666 } else if (options
->hostname
!= NULL
) {
667 /* NB. Please keep in sync with ssh.c:main() */
668 host
= percent_expand(options
->hostname
,
669 "h", host_arg
, (char *)NULL
);
671 host
= xstrdup(host_arg
);
673 if (gethostname(thishost
, sizeof(thishost
)) == -1)
674 fatal("gethostname: %s", strerror(errno
));
675 jmphost
= option_clear_or_none(options
->jump_host
) ?
676 "" : options
->jump_host
;
677 strlcpy(shorthost
, thishost
, sizeof(shorthost
));
678 shorthost
[strcspn(thishost
, ".")] = '\0';
679 snprintf(portstr
, sizeof(portstr
), "%d", port
);
680 snprintf(uidstr
, sizeof(uidstr
), "%llu",
681 (unsigned long long)pw
->pw_uid
);
682 conn_hash_hex
= ssh_connection_hash(thishost
, host
,
683 portstr
, ruser
, jmphost
);
684 keyalias
= options
->host_key_alias
? options
->host_key_alias
: host
;
686 ret
= (is_include_path
? percent_dollar_expand
: percent_expand
)(path
,
706 * Parse and execute a Match directive.
709 match_cfg_line(Options
*options
, const char *full_line
, int *acp
, char ***avp
,
710 struct passwd
*pw
, const char *host_arg
, const char *original_host
,
711 int final_pass
, int *want_final_pass
, const char *filename
, int linenum
)
713 char *arg
, *oattrib
= NULL
, *attrib
= NULL
, *cmd
, *host
, *criteria
;
715 int r
, this_result
, result
= 1, attributes
= 0, negate
;
718 * Configuration is likely to be incomplete at this point so we
719 * must be prepared to use default values.
721 ruser
= options
->user
== NULL
? pw
->pw_name
: options
->user
;
723 host
= xstrdup(options
->hostname
);
724 } else if (options
->hostname
!= NULL
) {
725 /* NB. Please keep in sync with ssh.c:main() */
726 host
= percent_expand(options
->hostname
,
727 "h", host_arg
, (char *)NULL
);
729 host
= xstrdup(host_arg
);
732 debug2("checking match for '%s' host %s originally %s",
733 full_line
, host
, original_host
);
734 while ((attrib
= argv_next(acp
, avp
)) != NULL
) {
735 attrib
= oattrib
= xstrdup(attrib
);
736 /* Terminate on comment */
737 if (*attrib
== '#') {
741 arg
= criteria
= NULL
;
743 if ((negate
= (attrib
[0] == '!')))
745 /* Criterion "all" has no argument and must appear alone */
746 if (strcasecmp(attrib
, "all") == 0) {
747 if (attributes
> 1 ||
748 ((arg
= argv_next(acp
, avp
)) != NULL
&&
749 *arg
!= '\0' && *arg
!= '#')) {
750 error("%.200s line %d: '%s' cannot be combined "
751 "with other Match attributes",
752 filename
, linenum
, oattrib
);
756 if (arg
!= NULL
&& *arg
== '#')
757 argv_consume(acp
); /* consume remaining args */
759 result
= negate
? 0 : 1;
763 /* criteria "final" and "canonical" have no argument */
764 if (strcasecmp(attrib
, "canonical") == 0 ||
765 strcasecmp(attrib
, "final") == 0) {
767 * If the config requests "Match final" then remember
768 * this so we can perform a second pass later.
770 if (strcasecmp(attrib
, "final") == 0 &&
771 want_final_pass
!= NULL
)
772 *want_final_pass
= 1;
773 r
= !!final_pass
; /* force bitmask member to boolean */
774 if (r
== (negate
? 1 : 0))
775 this_result
= result
= 0;
776 debug3("%.200s line %d: %smatched '%s'",
778 this_result
? "" : "not ", oattrib
);
782 /* Keep this list in sync with below */
783 if (strprefix(attrib
, "host=", 1) != NULL
||
784 strprefix(attrib
, "originalhost=", 1) != NULL
||
785 strprefix(attrib
, "user=", 1) != NULL
||
786 strprefix(attrib
, "localuser=", 1) != NULL
||
787 strprefix(attrib
, "localnetwork=", 1) != NULL
||
788 strprefix(attrib
, "tagged=", 1) != NULL
||
789 strprefix(attrib
, "exec=", 1) != NULL
) {
790 arg
= strchr(attrib
, '=');
793 arg
= argv_next(acp
, avp
);
796 /* All other criteria require an argument */
797 if (arg
== NULL
|| *arg
== '\0' || *arg
== '#') {
798 error("Missing Match criteria for %s", attrib
);
802 if (strcasecmp(attrib
, "host") == 0) {
803 criteria
= xstrdup(host
);
804 r
= match_hostname(host
, arg
) == 1;
805 if (r
== (negate
? 1 : 0))
806 this_result
= result
= 0;
807 } else if (strcasecmp(attrib
, "originalhost") == 0) {
808 criteria
= xstrdup(original_host
);
809 r
= match_hostname(original_host
, arg
) == 1;
810 if (r
== (negate
? 1 : 0))
811 this_result
= result
= 0;
812 } else if (strcasecmp(attrib
, "user") == 0) {
813 criteria
= xstrdup(ruser
);
814 r
= match_pattern_list(ruser
, arg
, 0) == 1;
815 if (r
== (negate
? 1 : 0))
816 this_result
= result
= 0;
817 } else if (strcasecmp(attrib
, "localuser") == 0) {
818 criteria
= xstrdup(pw
->pw_name
);
819 r
= match_pattern_list(pw
->pw_name
, arg
, 0) == 1;
820 if (r
== (negate
? 1 : 0))
821 this_result
= result
= 0;
822 } else if (strcasecmp(attrib
, "localnetwork") == 0) {
823 if (addr_match_cidr_list(NULL
, arg
) == -1) {
824 /* Error already printed */
828 r
= check_match_ifaddrs(arg
) == 1;
829 if (r
== (negate
? 1 : 0))
830 this_result
= result
= 0;
831 } else if (strcasecmp(attrib
, "tagged") == 0) {
832 criteria
= xstrdup(options
->tag
== NULL
? "" :
834 r
= match_pattern_list(criteria
, arg
, 0) == 1;
835 if (r
== (negate
? 1 : 0))
836 this_result
= result
= 0;
837 } else if (strcasecmp(attrib
, "exec") == 0) {
838 if ((cmd
= expand_match_exec_or_include_path(arg
,
839 options
, pw
, host_arg
, original_host
,
840 final_pass
, 0)) == NULL
) {
841 fatal("%.200s line %d: failed to expand match "
842 "exec '%.100s'", filename
, linenum
, arg
);
845 /* skip execution if prior predicate failed */
846 debug3("%.200s line %d: skipped exec "
847 "\"%.100s\"", filename
, linenum
, cmd
);
851 r
= execute_in_shell(cmd
);
853 fatal("%.200s line %d: match exec "
854 "'%.100s' error", filename
,
857 criteria
= xstrdup(cmd
);
859 /* Force exit status to boolean */
861 if (r
== (negate
? 1 : 0))
862 this_result
= result
= 0;
864 error("Unsupported Match attribute %s", attrib
);
868 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
869 filename
, linenum
, this_result
? "": "not ", oattrib
,
870 criteria
== NULL
? "" : " \"",
871 criteria
== NULL
? "" : criteria
,
872 criteria
== NULL
? "" : "\"");
875 oattrib
= attrib
= NULL
;
877 if (attributes
== 0) {
878 error("One or more attributes required for Match");
884 debug2("match %sfound", result
? "" : "not ");
890 /* Remove environment variable by pattern */
892 rm_env(Options
*options
, const char *arg
, const char *filename
, int linenum
)
894 u_int i
, j
, onum_send_env
= options
->num_send_env
;
896 /* Remove an environment variable */
897 for (i
= 0; i
< options
->num_send_env
; ) {
898 if (!match_pattern(options
->send_env
[i
], arg
+ 1)) {
902 debug3("%s line %d: removing environment %s",
903 filename
, linenum
, options
->send_env
[i
]);
904 free(options
->send_env
[i
]);
905 options
->send_env
[i
] = NULL
;
906 for (j
= i
; j
< options
->num_send_env
- 1; j
++) {
907 options
->send_env
[j
] = options
->send_env
[j
+ 1];
908 options
->send_env
[j
+ 1] = NULL
;
910 options
->num_send_env
--;
911 /* NB. don't increment i */
913 if (onum_send_env
!= options
->num_send_env
) {
914 options
->send_env
= xrecallocarray(options
->send_env
,
915 onum_send_env
, options
->num_send_env
,
916 sizeof(*options
->send_env
));
921 * Returns the number of the token pointed to by cp or oBadOption.
924 parse_token(const char *cp
, const char *filename
, int linenum
,
925 const char *ignored_unknown
)
929 for (i
= 0; keywords
[i
].name
; i
++)
930 if (strcmp(cp
, keywords
[i
].name
) == 0)
931 return keywords
[i
].opcode
;
932 if (ignored_unknown
!= NULL
&&
933 match_pattern_list(cp
, ignored_unknown
, 1) == 1)
934 return oIgnoredUnknownOption
;
935 error("%s: line %d: Bad configuration option: %s",
936 filename
, linenum
, cp
);
941 free_canon_cnames(struct allowed_cname
*cnames
, u_int n
)
945 if (cnames
== NULL
|| n
== 0)
947 for (i
= 0; i
< n
; i
++) {
948 free(cnames
[i
].source_list
);
949 free(cnames
[i
].target_list
);
954 /* Multistate option parsing */
959 static const struct multistate multistate_flag
[] = {
966 static const struct multistate multistate_yesnoask
[] = {
974 static const struct multistate multistate_strict_hostkey
[] = {
975 { "true", SSH_STRICT_HOSTKEY_YES
},
976 { "false", SSH_STRICT_HOSTKEY_OFF
},
977 { "yes", SSH_STRICT_HOSTKEY_YES
},
978 { "no", SSH_STRICT_HOSTKEY_OFF
},
979 { "ask", SSH_STRICT_HOSTKEY_ASK
},
980 { "off", SSH_STRICT_HOSTKEY_OFF
},
981 { "accept-new", SSH_STRICT_HOSTKEY_NEW
},
984 static const struct multistate multistate_yesnoaskconfirm
[] = {
993 static const struct multistate multistate_addressfamily
[] = {
995 { "inet6", AF_INET6
},
996 { "any", AF_UNSPEC
},
999 static const struct multistate multistate_controlmaster
[] = {
1000 { "true", SSHCTL_MASTER_YES
},
1001 { "yes", SSHCTL_MASTER_YES
},
1002 { "false", SSHCTL_MASTER_NO
},
1003 { "no", SSHCTL_MASTER_NO
},
1004 { "auto", SSHCTL_MASTER_AUTO
},
1005 { "ask", SSHCTL_MASTER_ASK
},
1006 { "autoask", SSHCTL_MASTER_AUTO_ASK
},
1009 static const struct multistate multistate_tunnel
[] = {
1010 { "ethernet", SSH_TUNMODE_ETHERNET
},
1011 { "point-to-point", SSH_TUNMODE_POINTOPOINT
},
1012 { "true", SSH_TUNMODE_DEFAULT
},
1013 { "yes", SSH_TUNMODE_DEFAULT
},
1014 { "false", SSH_TUNMODE_NO
},
1015 { "no", SSH_TUNMODE_NO
},
1018 static const struct multistate multistate_requesttty
[] = {
1019 { "true", REQUEST_TTY_YES
},
1020 { "yes", REQUEST_TTY_YES
},
1021 { "false", REQUEST_TTY_NO
},
1022 { "no", REQUEST_TTY_NO
},
1023 { "force", REQUEST_TTY_FORCE
},
1024 { "auto", REQUEST_TTY_AUTO
},
1027 static const struct multistate multistate_sessiontype
[] = {
1028 { "none", SESSION_TYPE_NONE
},
1029 { "subsystem", SESSION_TYPE_SUBSYSTEM
},
1030 { "default", SESSION_TYPE_DEFAULT
},
1033 static const struct multistate multistate_canonicalizehostname
[] = {
1034 { "true", SSH_CANONICALISE_YES
},
1035 { "false", SSH_CANONICALISE_NO
},
1036 { "yes", SSH_CANONICALISE_YES
},
1037 { "no", SSH_CANONICALISE_NO
},
1038 { "always", SSH_CANONICALISE_ALWAYS
},
1041 static const struct multistate multistate_pubkey_auth
[] = {
1042 { "true", SSH_PUBKEY_AUTH_ALL
},
1043 { "false", SSH_PUBKEY_AUTH_NO
},
1044 { "yes", SSH_PUBKEY_AUTH_ALL
},
1045 { "no", SSH_PUBKEY_AUTH_NO
},
1046 { "unbound", SSH_PUBKEY_AUTH_UNBOUND
},
1047 { "host-bound", SSH_PUBKEY_AUTH_HBOUND
},
1050 static const struct multistate multistate_compression
[] = {
1052 { "yes", COMP_DELAYED
},
1054 { "no", COMP_NONE
},
1059 parse_multistate_value(const char *arg
, const char *filename
, int linenum
,
1060 const struct multistate
*multistate_ptr
)
1064 if (!arg
|| *arg
== '\0') {
1065 error("%s line %d: missing argument.", filename
, linenum
);
1068 for (i
= 0; multistate_ptr
[i
].key
!= NULL
; i
++) {
1069 if (strcasecmp(arg
, multistate_ptr
[i
].key
) == 0)
1070 return multistate_ptr
[i
].value
;
1076 * Processes a single option line as used in the configuration files. This
1077 * only sets those values that have not already been set.
1080 process_config_line(Options
*options
, struct passwd
*pw
, const char *host
,
1081 const char *original_host
, char *line
, const char *filename
,
1082 int linenum
, int *activep
, int flags
)
1084 return process_config_line_depth(options
, pw
, host
, original_host
,
1085 line
, filename
, linenum
, activep
, flags
, NULL
, 0);
1088 #define WHITESPACE " \t\r\n"
1090 process_config_line_depth(Options
*options
, struct passwd
*pw
, const char *host
,
1091 const char *original_host
, char *line
, const char *filename
,
1092 int linenum
, int *activep
, int flags
, int *want_final_pass
, int depth
)
1094 char *str
, **charptr
, *endofnumber
, *keyword
, *arg
, *arg2
, *p
;
1095 char **cpptr
, ***cppptr
, fwdarg
[256];
1096 u_int i
, *uintptr
, max_entries
= 0;
1097 int r
, oactive
, negated
, opcode
, *intptr
, value
, value2
, cmdline
= 0;
1098 int remotefwd
, dynamicfwd
, ca_only
= 0, found
= 0;
1099 LogLevel
*log_level_ptr
;
1100 SyslogFacility
*log_facility_ptr
;
1104 const struct multistate
*multistate_ptr
;
1107 char **oav
= NULL
, **av
;
1110 struct allowed_cname
*cnames
= NULL
;
1112 char **strs
= NULL
; /* string array arguments; freed implicitly */
1115 if (activep
== NULL
) { /* We are processing a command line directive */
1120 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1121 if ((len
= strlen(line
)) == 0)
1123 for (len
--; len
> 0; len
--) {
1124 if (strchr(WHITESPACE
"\f", line
[len
]) == NULL
)
1130 /* Get the keyword. (Each line is supposed to begin with a keyword). */
1131 if ((keyword
= strdelim(&str
)) == NULL
)
1133 /* Ignore leading whitespace. */
1134 if (*keyword
== '\0')
1135 keyword
= strdelim(&str
);
1136 if (keyword
== NULL
|| !*keyword
|| *keyword
== '\n' || *keyword
== '#')
1138 /* Match lowercase keyword */
1141 /* Prepare to parse remainder of line */
1143 str
+= strspn(str
, WHITESPACE
);
1144 if (str
== NULL
|| *str
== '\0') {
1145 error("%s line %d: no argument after keyword \"%s\"",
1146 filename
, linenum
, keyword
);
1149 opcode
= parse_token(keyword
, filename
, linenum
,
1150 options
->ignored_unknown
);
1151 if (argv_split(str
, &oac
, &oav
, 1) != 0) {
1152 error("%s line %d: invalid quotes", filename
, linenum
);
1160 /* don't panic, but count bad options */
1165 case oIgnoredUnknownOption
:
1166 debug("%s line %d: Ignored unknown option \"%s\"",
1167 filename
, linenum
, keyword
);
1170 case oConnectTimeout
:
1171 intptr
= &options
->connection_timeout
;
1173 arg
= argv_next(&ac
, &av
);
1174 if (!arg
|| *arg
== '\0') {
1175 error("%s line %d: missing time value.",
1179 if (strcmp(arg
, "none") == 0)
1181 else if ((value
= convtime(arg
)) == -1) {
1182 error("%s line %d: invalid time value.",
1186 if (*activep
&& *intptr
== -1)
1191 intptr
= &options
->forward_agent
;
1193 arg
= argv_next(&ac
, &av
);
1194 if (!arg
|| *arg
== '\0') {
1195 error("%s line %d: missing argument.",
1201 multistate_ptr
= multistate_flag
;
1202 for (i
= 0; multistate_ptr
[i
].key
!= NULL
; i
++) {
1203 if (strcasecmp(arg
, multistate_ptr
[i
].key
) == 0) {
1204 value
= multistate_ptr
[i
].value
;
1209 if (*activep
&& *intptr
== -1)
1213 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1214 if (*activep
&& *intptr
== -1)
1217 charptr
= &options
->forward_agent_sock_path
;
1218 goto parse_agent_path
;
1221 intptr
= &options
->forward_x11
;
1223 multistate_ptr
= multistate_flag
;
1225 arg
= argv_next(&ac
, &av
);
1226 if ((value
= parse_multistate_value(arg
, filename
, linenum
,
1227 multistate_ptr
)) == -1) {
1228 error("%s line %d: unsupported option \"%s\".",
1229 filename
, linenum
, arg
);
1232 if (*activep
&& *intptr
== -1)
1236 case oForwardX11Trusted
:
1237 intptr
= &options
->forward_x11_trusted
;
1240 case oForwardX11Timeout
:
1241 intptr
= &options
->forward_x11_timeout
;
1245 intptr
= &options
->fwd_opts
.gateway_ports
;
1248 case oExitOnForwardFailure
:
1249 intptr
= &options
->exit_on_forward_failure
;
1252 case oPasswordAuthentication
:
1253 intptr
= &options
->password_authentication
;
1256 case oKbdInteractiveAuthentication
:
1257 intptr
= &options
->kbd_interactive_authentication
;
1260 case oKbdInteractiveDevices
:
1261 charptr
= &options
->kbd_interactive_devices
;
1264 case oPubkeyAuthentication
:
1265 multistate_ptr
= multistate_pubkey_auth
;
1266 intptr
= &options
->pubkey_authentication
;
1267 goto parse_multistate
;
1269 case oHostbasedAuthentication
:
1270 intptr
= &options
->hostbased_authentication
;
1273 case oGssAuthentication
:
1274 intptr
= &options
->gss_authentication
;
1277 case oGssDelegateCreds
:
1278 intptr
= &options
->gss_deleg_creds
;
1282 intptr
= &options
->batch_mode
;
1286 intptr
= &options
->check_host_ip
;
1289 case oVerifyHostKeyDNS
:
1290 intptr
= &options
->verify_host_key_dns
;
1291 multistate_ptr
= multistate_yesnoask
;
1292 goto parse_multistate
;
1294 case oStrictHostKeyChecking
:
1295 intptr
= &options
->strict_host_key_checking
;
1296 multistate_ptr
= multistate_strict_hostkey
;
1297 goto parse_multistate
;
1300 intptr
= &options
->compression
;
1301 multistate_ptr
= multistate_compression
;
1302 goto parse_multistate
;
1305 intptr
= &options
->tcp_keep_alive
;
1308 case oNoHostAuthenticationForLocalhost
:
1309 intptr
= &options
->no_host_authentication_for_localhost
;
1312 case oNumberOfPasswordPrompts
:
1313 intptr
= &options
->number_of_password_prompts
;
1317 arg
= argv_next(&ac
, &av
);
1318 if (!arg
|| *arg
== '\0') {
1319 error("%.200s line %d: Missing argument.", filename
,
1323 if (strcmp(arg
, "default") == 0) {
1326 if (scan_scaled(arg
, &val64
) == -1) {
1327 error("%.200s line %d: Bad number '%s': %s",
1328 filename
, linenum
, arg
, strerror(errno
));
1331 if (val64
!= 0 && val64
< 16) {
1332 error("%.200s line %d: RekeyLimit too small",
1337 if (*activep
&& options
->rekey_limit
== -1)
1338 options
->rekey_limit
= val64
;
1339 if (ac
!= 0) { /* optional rekey interval present */
1340 if (strcmp(av
[0], "none") == 0) {
1341 (void)argv_next(&ac
, &av
); /* discard */
1344 intptr
= &options
->rekey_interval
;
1350 arg
= argv_next(&ac
, &av
);
1351 if (!arg
|| *arg
== '\0') {
1352 error("%.200s line %d: Missing argument.",
1357 intptr
= &options
->num_identity_files
;
1358 if (*intptr
>= SSH_MAX_IDENTITY_FILES
) {
1359 error("%.200s line %d: Too many identity files "
1360 "specified (max %d).", filename
, linenum
,
1361 SSH_MAX_IDENTITY_FILES
);
1364 add_identity_file(options
, NULL
,
1365 arg
, flags
& SSHCONF_USERCONF
);
1369 case oCertificateFile
:
1370 arg
= argv_next(&ac
, &av
);
1371 if (!arg
|| *arg
== '\0') {
1372 error("%.200s line %d: Missing argument.",
1377 intptr
= &options
->num_certificate_files
;
1378 if (*intptr
>= SSH_MAX_CERTIFICATE_FILES
) {
1379 error("%.200s line %d: Too many certificate "
1380 "files specified (max %d).",
1382 SSH_MAX_CERTIFICATE_FILES
);
1385 add_certificate_file(options
, arg
,
1386 flags
& SSHCONF_USERCONF
);
1390 case oXAuthLocation
:
1391 charptr
=&options
->xauth_location
;
1395 charptr
= &options
->user
;
1397 arg
= argv_next(&ac
, &av
);
1398 if (!arg
|| *arg
== '\0') {
1399 error("%.200s line %d: Missing argument.",
1403 if (*activep
&& *charptr
== NULL
)
1404 *charptr
= xstrdup(arg
);
1407 case oGlobalKnownHostsFile
:
1408 cpptr
= (char **)&options
->system_hostfiles
;
1409 uintptr
= &options
->num_system_hostfiles
;
1410 max_entries
= SSH_MAX_HOSTS_FILES
;
1413 value
= *uintptr
== 0; /* was array empty when we started? */
1414 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1416 error("%s line %d: keyword %s empty argument",
1417 filename
, linenum
, keyword
);
1420 /* Allow "none" only in first position */
1421 if (strcasecmp(arg
, "none") == 0) {
1422 if (i
> 0 || ac
> 0) {
1423 error("%s line %d: keyword %s \"none\" "
1424 "argument must appear alone.",
1425 filename
, linenum
, keyword
);
1430 if (*activep
&& value
) {
1431 if ((*uintptr
) >= max_entries
) {
1432 error("%s line %d: too many %s "
1433 "entries.", filename
, linenum
,
1437 cpptr
[(*uintptr
)++] = xstrdup(arg
);
1442 case oUserKnownHostsFile
:
1443 cpptr
= (char **)&options
->user_hostfiles
;
1444 uintptr
= &options
->num_user_hostfiles
;
1445 max_entries
= SSH_MAX_HOSTS_FILES
;
1446 goto parse_char_array
;
1449 charptr
= &options
->hostname
;
1453 charptr
= &options
->tag
;
1457 charptr
= &options
->host_key_alias
;
1460 case oPreferredAuthentications
:
1461 charptr
= &options
->preferred_authentications
;
1465 charptr
= &options
->bind_address
;
1468 case oBindInterface
:
1469 charptr
= &options
->bind_interface
;
1472 case oPKCS11Provider
:
1473 charptr
= &options
->pkcs11_provider
;
1476 case oSecurityKeyProvider
:
1477 charptr
= &options
->sk_provider
;
1480 case oKnownHostsCommand
:
1481 charptr
= &options
->known_hosts_command
;
1485 charptr
= &options
->proxy_command
;
1486 /* Ignore ProxyCommand if ProxyJump already specified */
1487 if (options
->jump_host
!= NULL
)
1488 charptr
= &options
->jump_host
; /* Skip below */
1491 error("%.200s line %d: Missing argument.",
1495 len
= strspn(str
, WHITESPACE
"=");
1496 if (*activep
&& *charptr
== NULL
)
1497 *charptr
= xstrdup(str
+ len
);
1503 error("%.200s line %d: Missing argument.",
1507 len
= strspn(str
, WHITESPACE
"=");
1509 if (parse_jump(str
+ len
, options
, *activep
) == -1) {
1510 error("%.200s line %d: Invalid ProxyJump \"%s\"",
1511 filename
, linenum
, str
+ len
);
1518 arg
= argv_next(&ac
, &av
);
1519 if (!arg
|| *arg
== '\0') {
1520 error("%.200s line %d: Missing argument.",
1524 value
= a2port(arg
);
1526 error("%.200s line %d: Bad port '%s'.",
1527 filename
, linenum
, arg
);
1530 if (*activep
&& options
->port
== -1)
1531 options
->port
= value
;
1534 case oConnectionAttempts
:
1535 intptr
= &options
->connection_attempts
;
1537 arg
= argv_next(&ac
, &av
);
1538 if ((errstr
= atoi_err(arg
, &value
)) != NULL
) {
1539 error("%s line %d: integer value %s.",
1540 filename
, linenum
, errstr
);
1543 if (*activep
&& *intptr
== -1)
1548 arg
= argv_next(&ac
, &av
);
1549 if (!arg
|| *arg
== '\0') {
1550 error("%.200s line %d: Missing argument.",
1555 !ciphers_valid(*arg
== '+' || *arg
== '^' ? arg
+ 1 : arg
)){
1556 error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1557 filename
, linenum
, arg
? arg
: "<NONE>");
1560 if (*activep
&& options
->ciphers
== NULL
)
1561 options
->ciphers
= xstrdup(arg
);
1565 arg
= argv_next(&ac
, &av
);
1566 if (!arg
|| *arg
== '\0') {
1567 error("%.200s line %d: Missing argument.",
1572 !mac_valid(*arg
== '+' || *arg
== '^' ? arg
+ 1 : arg
)) {
1573 error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1574 filename
, linenum
, arg
? arg
: "<NONE>");
1577 if (*activep
&& options
->macs
== NULL
)
1578 options
->macs
= xstrdup(arg
);
1581 case oKexAlgorithms
:
1582 arg
= argv_next(&ac
, &av
);
1583 if (!arg
|| *arg
== '\0') {
1584 error("%.200s line %d: Missing argument.",
1589 !kex_names_valid(*arg
== '+' || *arg
== '^' ?
1591 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1592 filename
, linenum
, arg
? arg
: "<NONE>");
1595 if (*activep
&& options
->kex_algorithms
== NULL
)
1596 options
->kex_algorithms
= xstrdup(arg
);
1599 case oHostKeyAlgorithms
:
1600 charptr
= &options
->hostkeyalgorithms
;
1603 arg
= argv_next(&ac
, &av
);
1604 if (!arg
|| *arg
== '\0') {
1605 error("%.200s line %d: Missing argument.",
1610 !sshkey_names_valid2(*arg
== '+' || *arg
== '^' ?
1611 arg
+ 1 : arg
, 1, ca_only
)) {
1612 error("%s line %d: Bad key types '%s'.",
1613 filename
, linenum
, arg
? arg
: "<NONE>");
1616 if (*activep
&& *charptr
== NULL
)
1617 *charptr
= xstrdup(arg
);
1620 case oCASignatureAlgorithms
:
1621 charptr
= &options
->ca_sign_algorithms
;
1623 goto parse_pubkey_algos
;
1626 log_level_ptr
= &options
->log_level
;
1627 arg
= argv_next(&ac
, &av
);
1628 value
= log_level_number(arg
);
1629 if (value
== SYSLOG_LEVEL_NOT_SET
) {
1630 error("%.200s line %d: unsupported log level '%s'",
1631 filename
, linenum
, arg
? arg
: "<NONE>");
1634 if (*activep
&& *log_level_ptr
== SYSLOG_LEVEL_NOT_SET
)
1635 *log_level_ptr
= (LogLevel
) value
;
1639 log_facility_ptr
= &options
->log_facility
;
1640 arg
= argv_next(&ac
, &av
);
1641 value
= log_facility_number(arg
);
1642 if (value
== SYSLOG_FACILITY_NOT_SET
) {
1643 error("%.200s line %d: unsupported log facility '%s'",
1644 filename
, linenum
, arg
? arg
: "<NONE>");
1647 if (*log_facility_ptr
== -1)
1648 *log_facility_ptr
= (SyslogFacility
) value
;
1652 cppptr
= &options
->log_verbose
;
1653 uintptr
= &options
->num_log_verbose
;
1655 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1657 error("%s line %d: keyword %s empty argument",
1658 filename
, linenum
, keyword
);
1661 /* Allow "none" only in first position */
1662 if (strcasecmp(arg
, "none") == 0) {
1663 if (i
> 0 || ac
> 0) {
1664 error("%s line %d: keyword %s \"none\" "
1665 "argument must appear alone.",
1666 filename
, linenum
, keyword
);
1671 if (*activep
&& *uintptr
== 0) {
1672 *cppptr
= xrecallocarray(*cppptr
, *uintptr
,
1673 *uintptr
+ 1, sizeof(**cppptr
));
1674 (*cppptr
)[(*uintptr
)++] = xstrdup(arg
);
1680 case oRemoteForward
:
1681 case oDynamicForward
:
1682 arg
= argv_next(&ac
, &av
);
1683 if (!arg
|| *arg
== '\0') {
1684 error("%.200s line %d: Missing argument.",
1689 remotefwd
= (opcode
== oRemoteForward
);
1690 dynamicfwd
= (opcode
== oDynamicForward
);
1693 arg2
= argv_next(&ac
, &av
);
1694 if (arg2
== NULL
|| *arg2
== '\0') {
1698 error("%.200s line %d: Missing target "
1699 "argument.", filename
, linenum
);
1703 /* construct a string for parse_forward */
1704 snprintf(fwdarg
, sizeof(fwdarg
), "%s:%s", arg
,
1709 strlcpy(fwdarg
, arg
, sizeof(fwdarg
));
1711 if (parse_forward(&fwd
, fwdarg
, dynamicfwd
, remotefwd
) == 0) {
1712 error("%.200s line %d: Bad forwarding specification.",
1719 add_remote_forward(options
, &fwd
);
1721 add_local_forward(options
, &fwd
);
1726 case oPermitRemoteOpen
:
1727 uintptr
= &options
->num_permitted_remote_opens
;
1728 cppptr
= &options
->permitted_remote_opens
;
1729 found
= *uintptr
== 0;
1730 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1731 arg2
= xstrdup(arg
);
1732 /* Allow any/none only in first position */
1733 if (strcasecmp(arg
, "none") == 0 ||
1734 strcasecmp(arg
, "any") == 0) {
1735 if (nstrs
> 0 || ac
> 0) {
1736 error("%s line %d: keyword %s \"%s\" "
1737 "argument must appear alone.",
1738 filename
, linenum
, keyword
, arg
);
1745 fatal("%s line %d: missing host in %s",
1747 lookup_opcode_name(opcode
));
1749 p
= cleanhostname(p
);
1751 * don't want to use permitopen_port to avoid
1752 * dependency on channels.[ch] here.
1754 if (arg
== NULL
|| (strcmp(arg
, "*") != 0 &&
1755 a2port(arg
) <= 0)) {
1756 fatal("%s line %d: bad port number "
1757 "in %s", filename
, linenum
,
1758 lookup_opcode_name(opcode
));
1761 opt_array_append(filename
, linenum
,
1762 lookup_opcode_name(opcode
),
1763 &strs
, &nstrs
, arg2
);
1767 fatal("%s line %d: missing %s specification",
1768 filename
, linenum
, lookup_opcode_name(opcode
));
1769 if (found
&& *activep
) {
1772 strs
= NULL
; /* transferred */
1777 case oClearAllForwardings
:
1778 intptr
= &options
->clear_forwardings
;
1783 error("Host directive not supported as a command-line "
1789 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1791 error("%s line %d: keyword %s empty argument",
1792 filename
, linenum
, keyword
);
1795 if ((flags
& SSHCONF_NEVERMATCH
) != 0) {
1799 negated
= *arg
== '!';
1802 if (match_pattern(host
, arg
)) {
1804 debug("%.200s line %d: Skipping Host "
1805 "block because of negated match "
1806 "for %.100s", filename
, linenum
,
1813 arg2
= arg
; /* logged below */
1818 debug("%.200s line %d: Applying options for %.100s",
1819 filename
, linenum
, arg2
);
1824 error("Host directive not supported as a command-line "
1828 value
= match_cfg_line(options
, str
, &ac
, &av
, pw
, host
,
1829 original_host
, flags
& SSHCONF_FINAL
, want_final_pass
,
1832 error("%.200s line %d: Bad Match condition", filename
,
1836 *activep
= (flags
& SSHCONF_NEVERMATCH
) ? 0 : value
;
1840 intptr
= &options
->escape_char
;
1841 arg
= argv_next(&ac
, &av
);
1842 if (!arg
|| *arg
== '\0') {
1843 error("%.200s line %d: Missing argument.",
1847 if (strcmp(arg
, "none") == 0)
1848 value
= SSH_ESCAPECHAR_NONE
;
1849 else if (arg
[1] == '\0')
1850 value
= (u_char
) arg
[0];
1851 else if (arg
[0] == '^' && arg
[2] == 0 &&
1852 (u_char
) arg
[1] >= 64 && (u_char
) arg
[1] < 128)
1853 value
= (u_char
) arg
[1] & 31;
1855 error("%.200s line %d: Bad escape character.",
1859 if (*activep
&& *intptr
== -1)
1863 case oAddressFamily
:
1864 intptr
= &options
->address_family
;
1865 multistate_ptr
= multistate_addressfamily
;
1866 goto parse_multistate
;
1868 case oEnableSSHKeysign
:
1869 intptr
= &options
->enable_ssh_keysign
;
1872 case oIdentitiesOnly
:
1873 intptr
= &options
->identities_only
;
1876 case oServerAliveInterval
:
1877 intptr
= &options
->server_alive_interval
;
1880 case oServerAliveCountMax
:
1881 intptr
= &options
->server_alive_count_max
;
1885 /* XXX appends to list; doesn't respect first-match-wins */
1886 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1887 if (*arg
== '\0' || strchr(arg
, '=') != NULL
) {
1888 error("%s line %d: Invalid environment name.",
1896 /* Removing an env var */
1897 rm_env(options
, arg
, filename
, linenum
);
1900 opt_array_append(filename
, linenum
,
1901 lookup_opcode_name(opcode
),
1902 &options
->send_env
, &options
->num_send_env
, arg
);
1905 fatal("%s line %d: no %s specified",
1906 filename
, linenum
, keyword
);
1911 found
= options
->num_setenv
== 0;
1912 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
1913 if (strchr(arg
, '=') == NULL
) {
1914 error("%s line %d: Invalid SetEnv.",
1918 if (lookup_setenv_in_list(arg
, strs
, nstrs
) != NULL
) {
1919 debug2("%s line %d: ignoring duplicate env "
1920 "name \"%.64s\"", filename
, linenum
, arg
);
1923 opt_array_append(filename
, linenum
,
1924 lookup_opcode_name(opcode
),
1925 &strs
, &nstrs
, arg
);
1928 fatal("%s line %d: no %s specified",
1929 filename
, linenum
, keyword
);
1931 if (found
&& *activep
) {
1932 options
->setenv
= strs
;
1933 options
->num_setenv
= nstrs
;
1934 strs
= NULL
; /* transferred */
1940 charptr
= &options
->control_path
;
1943 case oControlMaster
:
1944 intptr
= &options
->control_master
;
1945 multistate_ptr
= multistate_controlmaster
;
1946 goto parse_multistate
;
1948 case oControlPersist
:
1949 /* no/false/yes/true, or a time spec */
1950 intptr
= &options
->control_persist
;
1951 arg
= argv_next(&ac
, &av
);
1952 if (!arg
|| *arg
== '\0') {
1953 error("%.200s line %d: Missing ControlPersist"
1954 " argument.", filename
, linenum
);
1958 value2
= 0; /* timeout */
1959 if (strcmp(arg
, "no") == 0 || strcmp(arg
, "false") == 0)
1961 else if (strcmp(arg
, "yes") == 0 || strcmp(arg
, "true") == 0)
1963 else if ((value2
= convtime(arg
)) >= 0)
1966 error("%.200s line %d: Bad ControlPersist argument.",
1970 if (*activep
&& *intptr
== -1) {
1972 options
->control_persist_timeout
= value2
;
1976 case oHashKnownHosts
:
1977 intptr
= &options
->hash_known_hosts
;
1981 intptr
= &options
->tun_open
;
1982 multistate_ptr
= multistate_tunnel
;
1983 goto parse_multistate
;
1986 arg
= argv_next(&ac
, &av
);
1987 if (!arg
|| *arg
== '\0') {
1988 error("%.200s line %d: Missing argument.",
1992 value
= a2tun(arg
, &value2
);
1993 if (value
== SSH_TUNID_ERR
) {
1994 error("%.200s line %d: Bad tun device.",
1998 if (*activep
&& options
->tun_local
== -1) {
1999 options
->tun_local
= value
;
2000 options
->tun_remote
= value2
;
2005 charptr
= &options
->local_command
;
2008 case oPermitLocalCommand
:
2009 intptr
= &options
->permit_local_command
;
2012 case oRemoteCommand
:
2013 charptr
= &options
->remote_command
;
2016 case oVisualHostKey
:
2017 intptr
= &options
->visual_host_key
;
2022 error("Include directive not supported as a "
2023 "command-line option");
2027 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
2029 error("%s line %d: keyword %s empty argument",
2030 filename
, linenum
, keyword
);
2033 /* Expand %tokens and environment variables */
2034 if ((p
= expand_match_exec_or_include_path(arg
,
2035 options
, pw
, host
, original_host
,
2036 flags
& SSHCONF_FINAL
, 1)) == NULL
) {
2037 error("%.200s line %d: Unable to expand user "
2038 "config file '%.100s'",
2039 filename
, linenum
, arg
);
2043 * Ensure all paths are anchored. User configuration
2044 * files may begin with '~/' but system configurations
2045 * must not. If the path is relative, then treat it
2046 * as living in ~/.ssh for user configurations or
2047 * /etc/ssh for system ones.
2049 if (*p
== '~' && (flags
& SSHCONF_USERCONF
) == 0) {
2050 error("%.200s line %d: bad include path %s.",
2051 filename
, linenum
, p
);
2054 if (!path_absolute(p
) && *p
!= '~') {
2055 xasprintf(&arg2
, "%s/%s",
2056 (flags
& SSHCONF_USERCONF
) ?
2057 "~/" _PATH_SSH_USER_DIR
: SSHDIR
, p
);
2062 memset(&gl
, 0, sizeof(gl
));
2063 r
= glob(arg2
, GLOB_TILDE
, NULL
, &gl
);
2064 if (r
== GLOB_NOMATCH
) {
2065 debug("%.200s line %d: include %s matched no "
2066 "files",filename
, linenum
, arg2
);
2069 } else if (r
!= 0) {
2070 error("%.200s line %d: glob failed for %s.",
2071 filename
, linenum
, arg2
);
2076 for (i
= 0; i
< gl
.gl_pathc
; i
++) {
2077 debug3("%.200s line %d: Including file %s "
2078 "depth %d%s", filename
, linenum
,
2079 gl
.gl_pathv
[i
], depth
,
2080 oactive
? "" : " (parse only)");
2081 r
= read_config_file_depth(gl
.gl_pathv
[i
],
2082 pw
, host
, original_host
, options
,
2083 flags
| SSHCONF_CHECKPERM
|
2084 (oactive
? 0 : SSHCONF_NEVERMATCH
),
2085 activep
, want_final_pass
, depth
+ 1);
2086 if (r
!= 1 && errno
!= ENOENT
) {
2087 error("%.200s line %d: Can't open user "
2088 "config file %.100s: %.100s",
2089 filename
, linenum
, gl
.gl_pathv
[i
],
2095 * don't let Match in includes clobber the
2096 * containing file's Match state.
2109 arg
= argv_next(&ac
, &av
);
2110 if ((value
= parse_ipqos(arg
)) == -1) {
2111 error("%s line %d: Bad IPQoS value: %s",
2112 filename
, linenum
, arg
);
2115 arg
= argv_next(&ac
, &av
);
2118 else if ((value2
= parse_ipqos(arg
)) == -1) {
2119 error("%s line %d: Bad IPQoS value: %s",
2120 filename
, linenum
, arg
);
2123 if (*activep
&& options
->ip_qos_interactive
== -1) {
2124 options
->ip_qos_interactive
= value
;
2125 options
->ip_qos_bulk
= value2
;
2130 intptr
= &options
->request_tty
;
2131 multistate_ptr
= multistate_requesttty
;
2132 goto parse_multistate
;
2135 intptr
= &options
->session_type
;
2136 multistate_ptr
= multistate_sessiontype
;
2137 goto parse_multistate
;
2140 intptr
= &options
->stdin_null
;
2143 case oForkAfterAuthentication
:
2144 intptr
= &options
->fork_after_authentication
;
2147 case oIgnoreUnknown
:
2148 charptr
= &options
->ignored_unknown
;
2151 case oProxyUseFdpass
:
2152 intptr
= &options
->proxy_use_fdpass
;
2155 case oCanonicalDomains
:
2156 found
= options
->num_canonical_domains
== 0;
2157 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
2158 /* Allow "none" only in first position */
2159 if (strcasecmp(arg
, "none") == 0) {
2160 if (nstrs
> 0 || ac
> 0) {
2161 error("%s line %d: keyword %s \"none\" "
2162 "argument must appear alone.",
2163 filename
, linenum
, keyword
);
2167 if (!valid_domain(arg
, 1, &errstr
)) {
2168 error("%s line %d: %s", filename
, linenum
,
2172 opt_array_append(filename
, linenum
, keyword
,
2173 &strs
, &nstrs
, arg
);
2176 fatal("%s line %d: no %s specified",
2177 filename
, linenum
, keyword
);
2179 if (found
&& *activep
) {
2180 options
->canonical_domains
= strs
;
2181 options
->num_canonical_domains
= nstrs
;
2182 strs
= NULL
; /* transferred */
2187 case oCanonicalizePermittedCNAMEs
:
2188 found
= options
->num_permitted_cnames
== 0;
2189 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
2191 * Either 'none' (only in first position), '*' for
2192 * everything or 'list:list'
2194 if (strcasecmp(arg
, "none") == 0) {
2195 if (ncnames
> 0 || ac
> 0) {
2196 error("%s line %d: keyword %s \"none\" "
2197 "argument must appear alone.",
2198 filename
, linenum
, keyword
);
2202 } else if (strcmp(arg
, "*") == 0) {
2206 if ((arg2
= strchr(arg
, ':')) == NULL
||
2208 error("%s line %d: "
2209 "Invalid permitted CNAME \"%s\"",
2210 filename
, linenum
, arg
);
2216 cnames
= xrecallocarray(cnames
, ncnames
, ncnames
+ 1,
2218 cnames
[ncnames
].source_list
= xstrdup(arg
);
2219 cnames
[ncnames
].target_list
= xstrdup(arg2
);
2223 fatal("%s line %d: no %s specified",
2224 filename
, linenum
, keyword
);
2226 if (found
&& *activep
) {
2227 options
->permitted_cnames
= cnames
;
2228 options
->num_permitted_cnames
= ncnames
;
2229 cnames
= NULL
; /* transferred */
2232 /* un-transferred cnames is cleaned up before exit */
2235 case oCanonicalizeHostname
:
2236 intptr
= &options
->canonicalize_hostname
;
2237 multistate_ptr
= multistate_canonicalizehostname
;
2238 goto parse_multistate
;
2240 case oCanonicalizeMaxDots
:
2241 intptr
= &options
->canonicalize_max_dots
;
2244 case oCanonicalizeFallbackLocal
:
2245 intptr
= &options
->canonicalize_fallback_local
;
2248 case oStreamLocalBindMask
:
2249 arg
= argv_next(&ac
, &av
);
2250 if (!arg
|| *arg
== '\0') {
2251 error("%.200s line %d: Missing StreamLocalBindMask "
2252 "argument.", filename
, linenum
);
2255 /* Parse mode in octal format */
2256 value
= strtol(arg
, &endofnumber
, 8);
2257 if (arg
== endofnumber
|| value
< 0 || value
> 0777) {
2258 error("%.200s line %d: Bad mask.", filename
, linenum
);
2261 options
->fwd_opts
.streamlocal_bind_mask
= (mode_t
)value
;
2264 case oStreamLocalBindUnlink
:
2265 intptr
= &options
->fwd_opts
.streamlocal_bind_unlink
;
2268 case oRevokedHostKeys
:
2269 charptr
= &options
->revoked_host_keys
;
2272 case oFingerprintHash
:
2273 intptr
= &options
->fingerprint_hash
;
2274 arg
= argv_next(&ac
, &av
);
2275 if (!arg
|| *arg
== '\0') {
2276 error("%.200s line %d: Missing argument.",
2280 if ((value
= ssh_digest_alg_by_name(arg
)) == -1) {
2281 error("%.200s line %d: Invalid hash algorithm \"%s\".",
2282 filename
, linenum
, arg
);
2285 if (*activep
&& *intptr
== -1)
2289 case oUpdateHostkeys
:
2290 intptr
= &options
->update_hostkeys
;
2291 multistate_ptr
= multistate_yesnoask
;
2292 goto parse_multistate
;
2294 case oHostbasedAcceptedAlgorithms
:
2295 charptr
= &options
->hostbased_accepted_algos
;
2297 goto parse_pubkey_algos
;
2299 case oPubkeyAcceptedAlgorithms
:
2300 charptr
= &options
->pubkey_accepted_algos
;
2302 goto parse_pubkey_algos
;
2304 case oAddKeysToAgent
:
2305 arg
= argv_next(&ac
, &av
);
2306 arg2
= argv_next(&ac
, &av
);
2307 value
= parse_multistate_value(arg
, filename
, linenum
,
2308 multistate_yesnoaskconfirm
);
2309 value2
= 0; /* unlimited lifespan by default */
2310 if (value
== 3 && arg2
!= NULL
) {
2311 /* allow "AddKeysToAgent confirm 5m" */
2312 if ((value2
= convtime(arg2
)) == -1) {
2313 error("%s line %d: invalid time value.",
2317 } else if (value
== -1 && arg2
== NULL
) {
2318 if ((value2
= convtime(arg
)) == -1) {
2319 error("%s line %d: unsupported option",
2323 value
= 1; /* yes */
2324 } else if (value
== -1 || arg2
!= NULL
) {
2325 error("%s line %d: unsupported option",
2329 if (*activep
&& options
->add_keys_to_agent
== -1) {
2330 options
->add_keys_to_agent
= value
;
2331 options
->add_keys_to_agent_lifespan
= value2
;
2335 case oIdentityAgent
:
2336 charptr
= &options
->identity_agent
;
2337 arg
= argv_next(&ac
, &av
);
2338 if (!arg
|| *arg
== '\0') {
2339 error("%.200s line %d: Missing argument.",
2344 /* Extra validation if the string represents an env var. */
2345 if ((arg2
= dollar_expand(&r
, arg
)) == NULL
|| r
) {
2346 error("%.200s line %d: Invalid environment expansion "
2347 "%s.", filename
, linenum
, arg
);
2351 /* check for legacy environment format */
2352 if (arg
[0] == '$' && arg
[1] != '{' &&
2353 !valid_env_name(arg
+ 1)) {
2354 error("%.200s line %d: Invalid environment name %s.",
2355 filename
, linenum
, arg
);
2358 if (*activep
&& *charptr
== NULL
)
2359 *charptr
= xstrdup(arg
);
2362 case oEnableEscapeCommandline
:
2363 intptr
= &options
->enable_escape_commandline
;
2366 case oRequiredRSASize
:
2367 intptr
= &options
->required_rsa_size
;
2370 case oObscureKeystrokeTiming
:
2372 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
2374 error("%s line %d: invalid arguments",
2378 if (strcmp(arg
, "yes") == 0 ||
2379 strcmp(arg
, "true") == 0)
2380 value
= SSH_KEYSTROKE_DEFAULT_INTERVAL_MS
;
2381 else if (strcmp(arg
, "no") == 0 ||
2382 strcmp(arg
, "false") == 0)
2384 else if (strncmp(arg
, "interval:", 9) == 0) {
2385 if ((errstr
= atoi_err(arg
+ 9,
2387 error("%s line %d: integer value %s.",
2388 filename
, linenum
, errstr
);
2391 if (value
<= 0 || value
> 1000) {
2392 error("%s line %d: value out of range.",
2397 error("%s line %d: unsupported argument \"%s\"",
2398 filename
, linenum
, arg
);
2403 error("%s line %d: missing argument",
2407 intptr
= &options
->obscure_keystroke_timing_interval
;
2408 if (*activep
&& *intptr
== -1)
2412 case oChannelTimeout
:
2413 found
= options
->num_channel_timeouts
== 0;
2414 while ((arg
= argv_next(&ac
, &av
)) != NULL
) {
2415 /* Allow "none" only in first position */
2416 if (strcasecmp(arg
, "none") == 0) {
2417 if (nstrs
> 0 || ac
> 0) {
2418 error("%s line %d: keyword %s \"none\" "
2419 "argument must appear alone.",
2420 filename
, linenum
, keyword
);
2423 } else if (parse_pattern_interval(arg
,
2425 fatal("%s line %d: invalid channel timeout %s",
2426 filename
, linenum
, arg
);
2428 opt_array_append(filename
, linenum
, keyword
,
2429 &strs
, &nstrs
, arg
);
2432 fatal("%s line %d: no %s specified",
2433 filename
, linenum
, keyword
);
2435 if (found
&& *activep
) {
2436 options
->channel_timeouts
= strs
;
2437 options
->num_channel_timeouts
= nstrs
;
2438 strs
= NULL
; /* transferred */
2444 debug("%s line %d: Deprecated option \"%s\"",
2445 filename
, linenum
, keyword
);
2450 error("%s line %d: Unsupported option \"%s\"",
2451 filename
, linenum
, keyword
);
2456 error("%s line %d: Unimplemented opcode %d",
2457 filename
, linenum
, opcode
);
2461 /* Check that there is no garbage at end of line. */
2463 error("%.200s line %d: keyword %s extra arguments "
2464 "at end of line", filename
, linenum
, keyword
);
2471 free_canon_cnames(cnames
, ncnames
);
2472 opt_array_free2(strs
, NULL
, nstrs
);
2473 argv_free(oav
, oac
);
2478 * Reads the config file and modifies the options accordingly. Options
2479 * should already be initialized before this call. This never returns if
2480 * there is an error. If the file does not exist, this returns 0.
2483 read_config_file(const char *filename
, struct passwd
*pw
, const char *host
,
2484 const char *original_host
, Options
*options
, int flags
,
2485 int *want_final_pass
)
2489 return read_config_file_depth(filename
, pw
, host
, original_host
,
2490 options
, flags
, &active
, want_final_pass
, 0);
2493 #define READCONF_MAX_DEPTH 16
2495 read_config_file_depth(const char *filename
, struct passwd
*pw
,
2496 const char *host
, const char *original_host
, Options
*options
,
2497 int flags
, int *activep
, int *want_final_pass
, int depth
)
2501 size_t linesize
= 0;
2503 int bad_options
= 0;
2505 if (depth
< 0 || depth
> READCONF_MAX_DEPTH
)
2506 fatal("Too many recursive configuration includes");
2508 if ((f
= fopen(filename
, "r")) == NULL
)
2511 if (flags
& SSHCONF_CHECKPERM
) {
2514 if (fstat(fileno(f
), &sb
) == -1)
2515 fatal("fstat %s: %s", filename
, strerror(errno
));
2516 if (((sb
.st_uid
!= 0 && sb
.st_uid
!= getuid()) ||
2517 (sb
.st_mode
& 022) != 0))
2518 fatal("Bad owner or permissions on %s", filename
);
2521 debug("Reading configuration data %.200s", filename
);
2524 * Mark that we are now processing the options. This flag is turned
2525 * on/off by Host specifications.
2528 while (getline(&line
, &linesize
, f
) != -1) {
2529 /* Update line number counter. */
2532 * Trim out comments and strip whitespace.
2533 * NB - preserve newlines, they are needed to reproduce
2534 * line numbers later for error messages.
2536 if (process_config_line_depth(options
, pw
, host
, original_host
,
2537 line
, filename
, linenum
, activep
, flags
, want_final_pass
,
2543 if (bad_options
> 0)
2544 fatal("%s: terminating, %d bad configuration options",
2545 filename
, bad_options
);
2549 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2551 option_clear_or_none(const char *o
)
2553 return o
== NULL
|| strcasecmp(o
, "none") == 0;
2557 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2558 * Allowed to be called on non-final configuration.
2561 config_has_permitted_cnames(Options
*options
)
2563 if (options
->num_permitted_cnames
== 1 &&
2564 strcasecmp(options
->permitted_cnames
[0].source_list
, "none") == 0 &&
2565 strcmp(options
->permitted_cnames
[0].target_list
, "") == 0)
2567 return options
->num_permitted_cnames
> 0;
2571 * Initializes options to special values that indicate that they have not yet
2572 * been set. Read_config_file will only set options with this value. Options
2573 * are processed in the following order: command line, user config file,
2574 * system config file. Last, fill_default_options is called.
2578 initialize_options(Options
* options
)
2580 memset(options
, 'X', sizeof(*options
));
2581 options
->host_arg
= NULL
;
2582 options
->forward_agent
= -1;
2583 options
->forward_agent_sock_path
= NULL
;
2584 options
->forward_x11
= -1;
2585 options
->forward_x11_trusted
= -1;
2586 options
->forward_x11_timeout
= -1;
2587 options
->stdio_forward_host
= NULL
;
2588 options
->stdio_forward_port
= 0;
2589 options
->clear_forwardings
= -1;
2590 options
->exit_on_forward_failure
= -1;
2591 options
->xauth_location
= NULL
;
2592 options
->fwd_opts
.gateway_ports
= -1;
2593 options
->fwd_opts
.streamlocal_bind_mask
= (mode_t
)-1;
2594 options
->fwd_opts
.streamlocal_bind_unlink
= -1;
2595 options
->pubkey_authentication
= -1;
2596 options
->gss_authentication
= -1;
2597 options
->gss_deleg_creds
= -1;
2598 options
->password_authentication
= -1;
2599 options
->kbd_interactive_authentication
= -1;
2600 options
->kbd_interactive_devices
= NULL
;
2601 options
->hostbased_authentication
= -1;
2602 options
->batch_mode
= -1;
2603 options
->check_host_ip
= -1;
2604 options
->strict_host_key_checking
= -1;
2605 options
->compression
= -1;
2606 options
->tcp_keep_alive
= -1;
2608 options
->address_family
= -1;
2609 options
->connection_attempts
= -1;
2610 options
->connection_timeout
= -1;
2611 options
->number_of_password_prompts
= -1;
2612 options
->ciphers
= NULL
;
2613 options
->macs
= NULL
;
2614 options
->kex_algorithms
= NULL
;
2615 options
->hostkeyalgorithms
= NULL
;
2616 options
->ca_sign_algorithms
= NULL
;
2617 options
->num_identity_files
= 0;
2618 memset(options
->identity_keys
, 0, sizeof(options
->identity_keys
));
2619 options
->num_certificate_files
= 0;
2620 memset(options
->certificates
, 0, sizeof(options
->certificates
));
2621 options
->hostname
= NULL
;
2622 options
->host_key_alias
= NULL
;
2623 options
->proxy_command
= NULL
;
2624 options
->jump_user
= NULL
;
2625 options
->jump_host
= NULL
;
2626 options
->jump_port
= -1;
2627 options
->jump_extra
= NULL
;
2628 options
->user
= NULL
;
2629 options
->escape_char
= -1;
2630 options
->num_system_hostfiles
= 0;
2631 options
->num_user_hostfiles
= 0;
2632 options
->local_forwards
= NULL
;
2633 options
->num_local_forwards
= 0;
2634 options
->remote_forwards
= NULL
;
2635 options
->num_remote_forwards
= 0;
2636 options
->permitted_remote_opens
= NULL
;
2637 options
->num_permitted_remote_opens
= 0;
2638 options
->log_facility
= SYSLOG_FACILITY_NOT_SET
;
2639 options
->log_level
= SYSLOG_LEVEL_NOT_SET
;
2640 options
->num_log_verbose
= 0;
2641 options
->log_verbose
= NULL
;
2642 options
->preferred_authentications
= NULL
;
2643 options
->bind_address
= NULL
;
2644 options
->bind_interface
= NULL
;
2645 options
->pkcs11_provider
= NULL
;
2646 options
->sk_provider
= NULL
;
2647 options
->enable_ssh_keysign
= - 1;
2648 options
->no_host_authentication_for_localhost
= - 1;
2649 options
->identities_only
= - 1;
2650 options
->rekey_limit
= - 1;
2651 options
->rekey_interval
= -1;
2652 options
->verify_host_key_dns
= -1;
2653 options
->server_alive_interval
= -1;
2654 options
->server_alive_count_max
= -1;
2655 options
->send_env
= NULL
;
2656 options
->num_send_env
= 0;
2657 options
->setenv
= NULL
;
2658 options
->num_setenv
= 0;
2659 options
->control_path
= NULL
;
2660 options
->control_master
= -1;
2661 options
->control_persist
= -1;
2662 options
->control_persist_timeout
= 0;
2663 options
->hash_known_hosts
= -1;
2664 options
->tun_open
= -1;
2665 options
->tun_local
= -1;
2666 options
->tun_remote
= -1;
2667 options
->local_command
= NULL
;
2668 options
->permit_local_command
= -1;
2669 options
->remote_command
= NULL
;
2670 options
->add_keys_to_agent
= -1;
2671 options
->add_keys_to_agent_lifespan
= -1;
2672 options
->identity_agent
= NULL
;
2673 options
->visual_host_key
= -1;
2674 options
->ip_qos_interactive
= -1;
2675 options
->ip_qos_bulk
= -1;
2676 options
->request_tty
= -1;
2677 options
->session_type
= -1;
2678 options
->stdin_null
= -1;
2679 options
->fork_after_authentication
= -1;
2680 options
->proxy_use_fdpass
= -1;
2681 options
->ignored_unknown
= NULL
;
2682 options
->num_canonical_domains
= 0;
2683 options
->num_permitted_cnames
= 0;
2684 options
->canonicalize_max_dots
= -1;
2685 options
->canonicalize_fallback_local
= -1;
2686 options
->canonicalize_hostname
= -1;
2687 options
->revoked_host_keys
= NULL
;
2688 options
->fingerprint_hash
= -1;
2689 options
->update_hostkeys
= -1;
2690 options
->hostbased_accepted_algos
= NULL
;
2691 options
->pubkey_accepted_algos
= NULL
;
2692 options
->known_hosts_command
= NULL
;
2693 options
->required_rsa_size
= -1;
2694 options
->enable_escape_commandline
= -1;
2695 options
->obscure_keystroke_timing_interval
= -1;
2696 options
->tag
= NULL
;
2697 options
->channel_timeouts
= NULL
;
2698 options
->num_channel_timeouts
= 0;
2702 * A petite version of fill_default_options() that just fills the options
2703 * needed for hostname canonicalization to proceed.
2706 fill_default_options_for_canonicalization(Options
*options
)
2708 if (options
->canonicalize_max_dots
== -1)
2709 options
->canonicalize_max_dots
= 1;
2710 if (options
->canonicalize_fallback_local
== -1)
2711 options
->canonicalize_fallback_local
= 1;
2712 if (options
->canonicalize_hostname
== -1)
2713 options
->canonicalize_hostname
= SSH_CANONICALISE_NO
;
2717 * Called after processing other sources of option data, this fills those
2718 * options for which no value has been specified with their default values.
2721 fill_default_options(Options
* options
)
2723 char *all_cipher
, *all_mac
, *all_kex
, *all_key
, *all_sig
;
2724 char *def_cipher
, *def_mac
, *def_kex
, *def_key
, *def_sig
;
2727 if (options
->forward_agent
== -1)
2728 options
->forward_agent
= 0;
2729 if (options
->forward_x11
== -1)
2730 options
->forward_x11
= 0;
2731 if (options
->forward_x11_trusted
== -1)
2732 options
->forward_x11_trusted
= 0;
2733 if (options
->forward_x11_timeout
== -1)
2734 options
->forward_x11_timeout
= 1200;
2736 * stdio forwarding (-W) changes the default for these but we defer
2737 * setting the values so they can be overridden.
2739 if (options
->exit_on_forward_failure
== -1)
2740 options
->exit_on_forward_failure
=
2741 options
->stdio_forward_host
!= NULL
? 1 : 0;
2742 if (options
->clear_forwardings
== -1)
2743 options
->clear_forwardings
=
2744 options
->stdio_forward_host
!= NULL
? 1 : 0;
2745 if (options
->clear_forwardings
== 1)
2746 clear_forwardings(options
);
2748 if (options
->xauth_location
== NULL
)
2749 options
->xauth_location
= xstrdup(_PATH_XAUTH
);
2750 if (options
->fwd_opts
.gateway_ports
== -1)
2751 options
->fwd_opts
.gateway_ports
= 0;
2752 if (options
->fwd_opts
.streamlocal_bind_mask
== (mode_t
)-1)
2753 options
->fwd_opts
.streamlocal_bind_mask
= 0177;
2754 if (options
->fwd_opts
.streamlocal_bind_unlink
== -1)
2755 options
->fwd_opts
.streamlocal_bind_unlink
= 0;
2756 if (options
->pubkey_authentication
== -1)
2757 options
->pubkey_authentication
= SSH_PUBKEY_AUTH_ALL
;
2758 if (options
->gss_authentication
== -1)
2759 options
->gss_authentication
= 0;
2760 if (options
->gss_deleg_creds
== -1)
2761 options
->gss_deleg_creds
= 0;
2762 if (options
->password_authentication
== -1)
2763 options
->password_authentication
= 1;
2764 if (options
->kbd_interactive_authentication
== -1)
2765 options
->kbd_interactive_authentication
= 1;
2766 if (options
->hostbased_authentication
== -1)
2767 options
->hostbased_authentication
= 0;
2768 if (options
->batch_mode
== -1)
2769 options
->batch_mode
= 0;
2770 if (options
->check_host_ip
== -1)
2771 options
->check_host_ip
= 0;
2772 if (options
->strict_host_key_checking
== -1)
2773 options
->strict_host_key_checking
= SSH_STRICT_HOSTKEY_ASK
;
2774 if (options
->compression
== -1)
2775 options
->compression
= 0;
2776 if (options
->tcp_keep_alive
== -1)
2777 options
->tcp_keep_alive
= 1;
2778 if (options
->port
== -1)
2779 options
->port
= 0; /* Filled in ssh_connect. */
2780 if (options
->address_family
== -1)
2781 options
->address_family
= AF_UNSPEC
;
2782 if (options
->connection_attempts
== -1)
2783 options
->connection_attempts
= 1;
2784 if (options
->number_of_password_prompts
== -1)
2785 options
->number_of_password_prompts
= 3;
2786 /* options->hostkeyalgorithms, default set in myproposals.h */
2787 if (options
->add_keys_to_agent
== -1) {
2788 options
->add_keys_to_agent
= 0;
2789 options
->add_keys_to_agent_lifespan
= 0;
2791 if (options
->num_identity_files
== 0) {
2792 add_identity_file(options
, "~/", _PATH_SSH_CLIENT_ID_RSA
, 0);
2793 #ifdef OPENSSL_HAS_ECC
2794 add_identity_file(options
, "~/", _PATH_SSH_CLIENT_ID_ECDSA
, 0);
2795 add_identity_file(options
, "~/",
2796 _PATH_SSH_CLIENT_ID_ECDSA_SK
, 0);
2798 add_identity_file(options
, "~/",
2799 _PATH_SSH_CLIENT_ID_ED25519
, 0);
2800 add_identity_file(options
, "~/",
2801 _PATH_SSH_CLIENT_ID_ED25519_SK
, 0);
2802 add_identity_file(options
, "~/", _PATH_SSH_CLIENT_ID_XMSS
, 0);
2804 add_identity_file(options
, "~/", _PATH_SSH_CLIENT_ID_DSA
, 0);
2807 if (options
->escape_char
== -1)
2808 options
->escape_char
= '~';
2809 if (options
->num_system_hostfiles
== 0) {
2810 options
->system_hostfiles
[options
->num_system_hostfiles
++] =
2811 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE
);
2812 options
->system_hostfiles
[options
->num_system_hostfiles
++] =
2813 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2
);
2815 if (options
->update_hostkeys
== -1) {
2816 if (options
->verify_host_key_dns
<= 0 &&
2817 (options
->num_user_hostfiles
== 0 ||
2818 (options
->num_user_hostfiles
== 1 && strcmp(options
->
2819 user_hostfiles
[0], _PATH_SSH_USER_HOSTFILE
) == 0)))
2820 options
->update_hostkeys
= SSH_UPDATE_HOSTKEYS_YES
;
2822 options
->update_hostkeys
= SSH_UPDATE_HOSTKEYS_NO
;
2824 if (options
->num_user_hostfiles
== 0) {
2825 options
->user_hostfiles
[options
->num_user_hostfiles
++] =
2826 xstrdup(_PATH_SSH_USER_HOSTFILE
);
2827 options
->user_hostfiles
[options
->num_user_hostfiles
++] =
2828 xstrdup(_PATH_SSH_USER_HOSTFILE2
);
2830 if (options
->log_level
== SYSLOG_LEVEL_NOT_SET
)
2831 options
->log_level
= SYSLOG_LEVEL_INFO
;
2832 if (options
->log_facility
== SYSLOG_FACILITY_NOT_SET
)
2833 options
->log_facility
= SYSLOG_FACILITY_USER
;
2834 if (options
->no_host_authentication_for_localhost
== - 1)
2835 options
->no_host_authentication_for_localhost
= 0;
2836 if (options
->identities_only
== -1)
2837 options
->identities_only
= 0;
2838 if (options
->enable_ssh_keysign
== -1)
2839 options
->enable_ssh_keysign
= 0;
2840 if (options
->rekey_limit
== -1)
2841 options
->rekey_limit
= 0;
2842 if (options
->rekey_interval
== -1)
2843 options
->rekey_interval
= 0;
2844 if (options
->verify_host_key_dns
== -1)
2845 options
->verify_host_key_dns
= 0;
2846 if (options
->server_alive_interval
== -1)
2847 options
->server_alive_interval
= 0;
2848 if (options
->server_alive_count_max
== -1)
2849 options
->server_alive_count_max
= 3;
2850 if (options
->control_master
== -1)
2851 options
->control_master
= 0;
2852 if (options
->control_persist
== -1) {
2853 options
->control_persist
= 0;
2854 options
->control_persist_timeout
= 0;
2856 if (options
->hash_known_hosts
== -1)
2857 options
->hash_known_hosts
= 0;
2858 if (options
->tun_open
== -1)
2859 options
->tun_open
= SSH_TUNMODE_NO
;
2860 if (options
->tun_local
== -1)
2861 options
->tun_local
= SSH_TUNID_ANY
;
2862 if (options
->tun_remote
== -1)
2863 options
->tun_remote
= SSH_TUNID_ANY
;
2864 if (options
->permit_local_command
== -1)
2865 options
->permit_local_command
= 0;
2866 if (options
->visual_host_key
== -1)
2867 options
->visual_host_key
= 0;
2868 if (options
->ip_qos_interactive
== -1)
2869 options
->ip_qos_interactive
= IPTOS_DSCP_AF21
;
2870 if (options
->ip_qos_bulk
== -1)
2871 options
->ip_qos_bulk
= IPTOS_DSCP_CS1
;
2872 if (options
->request_tty
== -1)
2873 options
->request_tty
= REQUEST_TTY_AUTO
;
2874 if (options
->session_type
== -1)
2875 options
->session_type
= SESSION_TYPE_DEFAULT
;
2876 if (options
->stdin_null
== -1)
2877 options
->stdin_null
= 0;
2878 if (options
->fork_after_authentication
== -1)
2879 options
->fork_after_authentication
= 0;
2880 if (options
->proxy_use_fdpass
== -1)
2881 options
->proxy_use_fdpass
= 0;
2882 if (options
->canonicalize_max_dots
== -1)
2883 options
->canonicalize_max_dots
= 1;
2884 if (options
->canonicalize_fallback_local
== -1)
2885 options
->canonicalize_fallback_local
= 1;
2886 if (options
->canonicalize_hostname
== -1)
2887 options
->canonicalize_hostname
= SSH_CANONICALISE_NO
;
2888 if (options
->fingerprint_hash
== -1)
2889 options
->fingerprint_hash
= SSH_FP_HASH_DEFAULT
;
2890 #ifdef ENABLE_SK_INTERNAL
2891 if (options
->sk_provider
== NULL
)
2892 options
->sk_provider
= xstrdup("internal");
2894 if (options
->sk_provider
== NULL
)
2895 options
->sk_provider
= xstrdup("$SSH_SK_PROVIDER");
2897 if (options
->required_rsa_size
== -1)
2898 options
->required_rsa_size
= SSH_RSA_MINIMUM_MODULUS_SIZE
;
2899 if (options
->enable_escape_commandline
== -1)
2900 options
->enable_escape_commandline
= 0;
2901 if (options
->obscure_keystroke_timing_interval
== -1) {
2902 options
->obscure_keystroke_timing_interval
=
2903 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS
;
2906 /* Expand KEX name lists */
2907 all_cipher
= cipher_alg_list(',', 0);
2908 all_mac
= mac_alg_list(',');
2909 all_kex
= kex_alg_list(',');
2910 all_key
= sshkey_alg_list(0, 0, 1, ',');
2911 all_sig
= sshkey_alg_list(0, 1, 1, ',');
2912 /* remove unsupported algos from default lists */
2913 def_cipher
= match_filter_allowlist(KEX_CLIENT_ENCRYPT
, all_cipher
);
2914 def_mac
= match_filter_allowlist(KEX_CLIENT_MAC
, all_mac
);
2915 def_kex
= match_filter_allowlist(KEX_CLIENT_KEX
, all_kex
);
2916 def_key
= match_filter_allowlist(KEX_DEFAULT_PK_ALG
, all_key
);
2917 def_sig
= match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS
, all_sig
);
2918 #define ASSEMBLE(what, defaults, all) \
2920 if ((r = kex_assemble_names(&options->what, \
2921 defaults, all)) != 0) { \
2922 error_fr(r, "%s", #what); \
2926 ASSEMBLE(ciphers
, def_cipher
, all_cipher
);
2927 ASSEMBLE(macs
, def_mac
, all_mac
);
2928 ASSEMBLE(kex_algorithms
, def_kex
, all_kex
);
2929 ASSEMBLE(hostbased_accepted_algos
, def_key
, all_key
);
2930 ASSEMBLE(pubkey_accepted_algos
, def_key
, all_key
);
2931 ASSEMBLE(ca_sign_algorithms
, def_sig
, all_sig
);
2934 #define CLEAR_ON_NONE(v) \
2936 if (option_clear_or_none(v)) { \
2941 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2943 if (options->nv == 1 && \
2944 strcasecmp(options->v[0], none) == 0) { \
2945 free(options->v[0]); \
2947 options->v = NULL; \
2951 CLEAR_ON_NONE(options
->local_command
);
2952 CLEAR_ON_NONE(options
->remote_command
);
2953 CLEAR_ON_NONE(options
->proxy_command
);
2954 CLEAR_ON_NONE(options
->control_path
);
2955 CLEAR_ON_NONE(options
->revoked_host_keys
);
2956 CLEAR_ON_NONE(options
->pkcs11_provider
);
2957 CLEAR_ON_NONE(options
->sk_provider
);
2958 CLEAR_ON_NONE(options
->known_hosts_command
);
2959 CLEAR_ON_NONE_ARRAY(channel_timeouts
, num_channel_timeouts
, "none");
2960 #undef CLEAR_ON_NONE
2961 #undef CLEAR_ON_NONE_ARRAY
2962 if (options
->jump_host
!= NULL
&&
2963 strcmp(options
->jump_host
, "none") == 0 &&
2964 options
->jump_port
== 0 && options
->jump_user
== NULL
) {
2965 free(options
->jump_host
);
2966 options
->jump_host
= NULL
;
2968 if (options
->num_permitted_cnames
== 1 &&
2969 !config_has_permitted_cnames(options
)) {
2970 /* clean up CanonicalizePermittedCNAMEs=none */
2971 free(options
->permitted_cnames
[0].source_list
);
2972 free(options
->permitted_cnames
[0].target_list
);
2973 memset(options
->permitted_cnames
, '\0',
2974 sizeof(*options
->permitted_cnames
));
2975 options
->num_permitted_cnames
= 0;
2977 /* options->identity_agent distinguishes NULL from 'none' */
2978 /* options->user will be set in the main program if appropriate */
2979 /* options->hostname will be set in the main program if appropriate */
2980 /* options->host_key_alias should not be set by default */
2981 /* options->preferred_authentications will be set in ssh */
3000 free_options(Options
*o
)
3007 #define FREE_ARRAY(type, n, a) \
3010 for (_i = 0; _i < (n); _i++) \
3014 free(o
->forward_agent_sock_path
);
3015 free(o
->xauth_location
);
3016 FREE_ARRAY(u_int
, o
->num_log_verbose
, o
->log_verbose
);
3017 free(o
->log_verbose
);
3020 free(o
->hostkeyalgorithms
);
3021 free(o
->kex_algorithms
);
3022 free(o
->ca_sign_algorithms
);
3024 free(o
->host_key_alias
);
3025 free(o
->proxy_command
);
3027 FREE_ARRAY(u_int
, o
->num_system_hostfiles
, o
->system_hostfiles
);
3028 FREE_ARRAY(u_int
, o
->num_user_hostfiles
, o
->user_hostfiles
);
3029 free(o
->preferred_authentications
);
3030 free(o
->bind_address
);
3031 free(o
->bind_interface
);
3032 free(o
->pkcs11_provider
);
3033 free(o
->sk_provider
);
3034 for (i
= 0; i
< o
->num_identity_files
; i
++) {
3035 free(o
->identity_files
[i
]);
3036 sshkey_free(o
->identity_keys
[i
]);
3038 for (i
= 0; i
< o
->num_certificate_files
; i
++) {
3039 free(o
->certificate_files
[i
]);
3040 sshkey_free(o
->certificates
[i
]);
3042 free(o
->identity_agent
);
3043 for (i
= 0; i
< o
->num_local_forwards
; i
++) {
3044 free(o
->local_forwards
[i
].listen_host
);
3045 free(o
->local_forwards
[i
].listen_path
);
3046 free(o
->local_forwards
[i
].connect_host
);
3047 free(o
->local_forwards
[i
].connect_path
);
3049 free(o
->local_forwards
);
3050 for (i
= 0; i
< o
->num_remote_forwards
; i
++) {
3051 free(o
->remote_forwards
[i
].listen_host
);
3052 free(o
->remote_forwards
[i
].listen_path
);
3053 free(o
->remote_forwards
[i
].connect_host
);
3054 free(o
->remote_forwards
[i
].connect_path
);
3056 free(o
->remote_forwards
);
3057 free(o
->stdio_forward_host
);
3058 FREE_ARRAY(u_int
, o
->num_send_env
, o
->send_env
);
3060 FREE_ARRAY(u_int
, o
->num_setenv
, o
->setenv
);
3062 free(o
->control_path
);
3063 free(o
->local_command
);
3064 free(o
->remote_command
);
3065 FREE_ARRAY(int, o
->num_canonical_domains
, o
->canonical_domains
);
3066 for (i
= 0; i
< o
->num_permitted_cnames
; i
++) {
3067 free(o
->permitted_cnames
[i
].source_list
);
3068 free(o
->permitted_cnames
[i
].target_list
);
3070 free(o
->revoked_host_keys
);
3071 free(o
->hostbased_accepted_algos
);
3072 free(o
->pubkey_accepted_algos
);
3075 free(o
->jump_extra
);
3076 free(o
->ignored_unknown
);
3077 explicit_bzero(o
, sizeof(*o
));
3088 * parses the next field in a port forwarding specification.
3089 * sets fwd to the parsed field and advances p past the colon
3090 * or sets it to NULL at end of string.
3091 * returns 0 on success, else non-zero.
3094 parse_fwd_field(char **p
, struct fwdarg
*fwd
)
3101 return -1; /* end of string */
3105 * A field escaped with square brackets is used literally.
3106 * XXX - allow ']' to be escaped via backslash?
3109 /* find matching ']' */
3110 for (ep
= cp
+ 1; *ep
!= ']' && *ep
!= '\0'; ep
++) {
3114 /* no matching ']' or not at end of field. */
3115 if (ep
[0] != ']' || (ep
[1] != ':' && ep
[1] != '\0'))
3117 /* NUL terminate the field and advance p past the colon */
3122 fwd
->ispath
= ispath
;
3127 for (cp
= *p
; *cp
!= '\0'; cp
++) {
3130 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
3144 fwd
->ispath
= ispath
;
3151 * parses a string containing a port forwarding specification of the form:
3153 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3154 * listenpath:connectpath
3156 * [listenhost:]listenport
3157 * returns number of arguments parsed or zero on error
3160 parse_forward(struct Forward
*fwd
, const char *fwdspec
, int dynamicfwd
, int remotefwd
)
3162 struct fwdarg fwdargs
[4];
3166 memset(fwd
, 0, sizeof(*fwd
));
3167 memset(fwdargs
, 0, sizeof(fwdargs
));
3170 * We expand environment variables before checking if we think they're
3171 * paths so that if ${VAR} expands to a fully qualified path it is
3172 * treated as a path.
3174 cp
= p
= dollar_expand(&err
, fwdspec
);
3175 if (p
== NULL
|| err
)
3178 /* skip leading spaces */
3179 while (isspace((u_char
)*cp
))
3182 for (i
= 0; i
< 4; ++i
) {
3183 if (parse_fwd_field(&cp
, &fwdargs
[i
]) != 0)
3187 /* Check for trailing garbage */
3188 if (cp
!= NULL
&& *cp
!= '\0') {
3189 i
= 0; /* failure */
3194 if (fwdargs
[0].ispath
) {
3195 fwd
->listen_path
= xstrdup(fwdargs
[0].arg
);
3196 fwd
->listen_port
= PORT_STREAMLOCAL
;
3198 fwd
->listen_host
= NULL
;
3199 fwd
->listen_port
= a2port(fwdargs
[0].arg
);
3201 fwd
->connect_host
= xstrdup("socks");
3205 if (fwdargs
[0].ispath
&& fwdargs
[1].ispath
) {
3206 fwd
->listen_path
= xstrdup(fwdargs
[0].arg
);
3207 fwd
->listen_port
= PORT_STREAMLOCAL
;
3208 fwd
->connect_path
= xstrdup(fwdargs
[1].arg
);
3209 fwd
->connect_port
= PORT_STREAMLOCAL
;
3210 } else if (fwdargs
[1].ispath
) {
3211 fwd
->listen_host
= NULL
;
3212 fwd
->listen_port
= a2port(fwdargs
[0].arg
);
3213 fwd
->connect_path
= xstrdup(fwdargs
[1].arg
);
3214 fwd
->connect_port
= PORT_STREAMLOCAL
;
3216 fwd
->listen_host
= xstrdup(fwdargs
[0].arg
);
3217 fwd
->listen_port
= a2port(fwdargs
[1].arg
);
3218 fwd
->connect_host
= xstrdup("socks");
3223 if (fwdargs
[0].ispath
) {
3224 fwd
->listen_path
= xstrdup(fwdargs
[0].arg
);
3225 fwd
->listen_port
= PORT_STREAMLOCAL
;
3226 fwd
->connect_host
= xstrdup(fwdargs
[1].arg
);
3227 fwd
->connect_port
= a2port(fwdargs
[2].arg
);
3228 } else if (fwdargs
[2].ispath
) {
3229 fwd
->listen_host
= xstrdup(fwdargs
[0].arg
);
3230 fwd
->listen_port
= a2port(fwdargs
[1].arg
);
3231 fwd
->connect_path
= xstrdup(fwdargs
[2].arg
);
3232 fwd
->connect_port
= PORT_STREAMLOCAL
;
3234 fwd
->listen_host
= NULL
;
3235 fwd
->listen_port
= a2port(fwdargs
[0].arg
);
3236 fwd
->connect_host
= xstrdup(fwdargs
[1].arg
);
3237 fwd
->connect_port
= a2port(fwdargs
[2].arg
);
3242 fwd
->listen_host
= xstrdup(fwdargs
[0].arg
);
3243 fwd
->listen_port
= a2port(fwdargs
[1].arg
);
3244 fwd
->connect_host
= xstrdup(fwdargs
[2].arg
);
3245 fwd
->connect_port
= a2port(fwdargs
[3].arg
);
3248 i
= 0; /* failure */
3254 if (!(i
== 1 || i
== 2))
3257 if (!(i
== 3 || i
== 4)) {
3258 if (fwd
->connect_path
== NULL
&&
3259 fwd
->listen_path
== NULL
)
3262 if (fwd
->connect_port
<= 0 && fwd
->connect_path
== NULL
)
3266 if ((fwd
->listen_port
< 0 && fwd
->listen_path
== NULL
) ||
3267 (!remotefwd
&& fwd
->listen_port
== 0))
3269 if (fwd
->connect_host
!= NULL
&&
3270 strlen(fwd
->connect_host
) >= NI_MAXHOST
)
3273 * XXX - if connecting to a remote socket, max sun len may not
3276 if (fwd
->connect_path
!= NULL
&&
3277 strlen(fwd
->connect_path
) >= PATH_MAX_SUN
)
3279 if (fwd
->listen_host
!= NULL
&&
3280 strlen(fwd
->listen_host
) >= NI_MAXHOST
)
3282 if (fwd
->listen_path
!= NULL
&&
3283 strlen(fwd
->listen_path
) >= PATH_MAX_SUN
)
3289 free(fwd
->connect_host
);
3290 fwd
->connect_host
= NULL
;
3291 free(fwd
->connect_path
);
3292 fwd
->connect_path
= NULL
;
3293 free(fwd
->listen_host
);
3294 fwd
->listen_host
= NULL
;
3295 free(fwd
->listen_path
);
3296 fwd
->listen_path
= NULL
;
3301 parse_jump(const char *s
, Options
*o
, int active
)
3303 char *orig
, *sdup
, *cp
;
3304 char *host
= NULL
, *user
= NULL
;
3305 int r
, ret
= -1, port
= -1, first
;
3307 active
&= o
->proxy_command
== NULL
&& o
->jump_host
== NULL
;
3309 orig
= sdup
= xstrdup(s
);
3311 /* Remove comment and trailing whitespace */
3312 if ((cp
= strchr(orig
, '#')) != NULL
)
3318 if (strcasecmp(s
, "none") == 0)
3320 if ((cp
= strrchr(sdup
, ',')) == NULL
)
3321 cp
= sdup
; /* last */
3326 /* First argument and configuration is active */
3327 r
= parse_ssh_uri(cp
, &user
, &host
, &port
);
3328 if (r
== -1 || (r
== 1 &&
3329 parse_user_host_port(cp
, &user
, &host
, &port
) != 0))
3332 /* Subsequent argument or inactive configuration */
3333 r
= parse_ssh_uri(cp
, NULL
, NULL
, NULL
);
3334 if (r
== -1 || (r
== 1 &&
3335 parse_user_host_port(cp
, NULL
, NULL
, NULL
) != 0))
3338 first
= 0; /* only check syntax for subsequent hosts */
3339 } while (cp
!= sdup
);
3342 if (strcasecmp(s
, "none") == 0) {
3343 o
->jump_host
= xstrdup("none");
3346 o
->jump_user
= user
;
3347 o
->jump_host
= host
;
3348 o
->jump_port
= port
;
3349 o
->proxy_command
= xstrdup("none");
3351 if ((cp
= strrchr(s
, ',')) != NULL
&& cp
!= s
) {
3352 o
->jump_extra
= xstrdup(s
);
3353 o
->jump_extra
[cp
- s
] = '\0';
3366 parse_ssh_uri(const char *uri
, char **userp
, char **hostp
, int *portp
)
3368 char *user
= NULL
, *host
= NULL
, *path
= NULL
;
3371 r
= parse_uri("ssh", uri
, &user
, &host
, &port
, &path
);
3372 if (r
== 0 && path
!= NULL
)
3373 r
= -1; /* path not allowed */
3375 if (userp
!= NULL
) {
3379 if (hostp
!= NULL
) {
3392 /* XXX the following is a near-verbatim copy from servconf.c; refactor */
3394 fmt_multistate_int(int val
, const struct multistate
*m
)
3398 for (i
= 0; m
[i
].key
!= NULL
; i
++) {
3399 if (m
[i
].value
== val
)
3406 fmt_intarg(OpCodes code
, int val
)
3411 case oAddressFamily
:
3412 return fmt_multistate_int(val
, multistate_addressfamily
);
3414 return fmt_multistate_int(val
, multistate_compression
);
3415 case oVerifyHostKeyDNS
:
3416 case oUpdateHostkeys
:
3417 return fmt_multistate_int(val
, multistate_yesnoask
);
3418 case oStrictHostKeyChecking
:
3419 return fmt_multistate_int(val
, multistate_strict_hostkey
);
3420 case oControlMaster
:
3421 return fmt_multistate_int(val
, multistate_controlmaster
);
3423 return fmt_multistate_int(val
, multistate_tunnel
);
3425 return fmt_multistate_int(val
, multistate_requesttty
);
3427 return fmt_multistate_int(val
, multistate_sessiontype
);
3428 case oCanonicalizeHostname
:
3429 return fmt_multistate_int(val
, multistate_canonicalizehostname
);
3430 case oAddKeysToAgent
:
3431 return fmt_multistate_int(val
, multistate_yesnoaskconfirm
);
3432 case oPubkeyAuthentication
:
3433 return fmt_multistate_int(val
, multistate_pubkey_auth
);
3434 case oFingerprintHash
:
3435 return ssh_digest_alg_name(val
);
3449 lookup_opcode_name(OpCodes code
)
3453 for (i
= 0; keywords
[i
].name
!= NULL
; i
++)
3454 if (keywords
[i
].opcode
== code
)
3455 return(keywords
[i
].name
);
3460 dump_cfg_int(OpCodes code
, int val
)
3462 if (code
== oObscureKeystrokeTiming
) {
3464 printf("%s no\n", lookup_opcode_name(code
));
3466 } else if (val
== SSH_KEYSTROKE_DEFAULT_INTERVAL_MS
) {
3467 printf("%s yes\n", lookup_opcode_name(code
));
3472 printf("%s %d\n", lookup_opcode_name(code
), val
);
3476 dump_cfg_fmtint(OpCodes code
, int val
)
3478 printf("%s %s\n", lookup_opcode_name(code
), fmt_intarg(code
, val
));
3482 dump_cfg_string(OpCodes code
, const char *val
)
3486 printf("%s %s\n", lookup_opcode_name(code
), val
);
3490 dump_cfg_strarray(OpCodes code
, u_int count
, char **vals
)
3494 for (i
= 0; i
< count
; i
++)
3495 printf("%s %s\n", lookup_opcode_name(code
), vals
[i
]);
3499 dump_cfg_strarray_oneline(OpCodes code
, u_int count
, char **vals
)
3503 printf("%s", lookup_opcode_name(code
));
3506 for (i
= 0; i
< count
; i
++)
3507 printf(" %s", vals
[i
]);
3512 dump_cfg_forwards(OpCodes code
, u_int count
, const struct Forward
*fwds
)
3514 const struct Forward
*fwd
;
3517 /* oDynamicForward */
3518 for (i
= 0; i
< count
; i
++) {
3520 if (code
== oDynamicForward
&& fwd
->connect_host
!= NULL
&&
3521 strcmp(fwd
->connect_host
, "socks") != 0)
3523 if (code
== oLocalForward
&& fwd
->connect_host
!= NULL
&&
3524 strcmp(fwd
->connect_host
, "socks") == 0)
3526 printf("%s", lookup_opcode_name(code
));
3527 if (fwd
->listen_port
== PORT_STREAMLOCAL
)
3528 printf(" %s", fwd
->listen_path
);
3529 else if (fwd
->listen_host
== NULL
)
3530 printf(" %d", fwd
->listen_port
);
3533 fwd
->listen_host
, fwd
->listen_port
);
3535 if (code
!= oDynamicForward
) {
3536 if (fwd
->connect_port
== PORT_STREAMLOCAL
)
3537 printf(" %s", fwd
->connect_path
);
3538 else if (fwd
->connect_host
== NULL
)
3539 printf(" %d", fwd
->connect_port
);
3542 fwd
->connect_host
, fwd
->connect_port
);
3550 dump_client_config(Options
*o
, const char *host
)
3553 char buf
[8], *all_key
;
3556 * Expand HostKeyAlgorithms name lists. This isn't handled in
3557 * fill_default_options() like the other algorithm lists because
3558 * the host key algorithms are by default dynamically chosen based
3559 * on the host's keys found in known_hosts.
3561 all_key
= sshkey_alg_list(0, 0, 1, ',');
3562 if ((r
= kex_assemble_names(&o
->hostkeyalgorithms
, kex_default_pk_alg(),
3564 fatal_fr(r
, "expand HostKeyAlgorithms");
3567 /* Most interesting options first: user, host, port */
3568 dump_cfg_string(oHost
, o
->host_arg
);
3569 dump_cfg_string(oUser
, o
->user
);
3570 dump_cfg_string(oHostname
, host
);
3571 dump_cfg_int(oPort
, o
->port
);
3574 dump_cfg_fmtint(oAddressFamily
, o
->address_family
);
3575 dump_cfg_fmtint(oBatchMode
, o
->batch_mode
);
3576 dump_cfg_fmtint(oCanonicalizeFallbackLocal
, o
->canonicalize_fallback_local
);
3577 dump_cfg_fmtint(oCanonicalizeHostname
, o
->canonicalize_hostname
);
3578 dump_cfg_fmtint(oCheckHostIP
, o
->check_host_ip
);
3579 dump_cfg_fmtint(oCompression
, o
->compression
);
3580 dump_cfg_fmtint(oControlMaster
, o
->control_master
);
3581 dump_cfg_fmtint(oEnableSSHKeysign
, o
->enable_ssh_keysign
);
3582 dump_cfg_fmtint(oClearAllForwardings
, o
->clear_forwardings
);
3583 dump_cfg_fmtint(oExitOnForwardFailure
, o
->exit_on_forward_failure
);
3584 dump_cfg_fmtint(oFingerprintHash
, o
->fingerprint_hash
);
3585 dump_cfg_fmtint(oForwardX11
, o
->forward_x11
);
3586 dump_cfg_fmtint(oForwardX11Trusted
, o
->forward_x11_trusted
);
3587 dump_cfg_fmtint(oGatewayPorts
, o
->fwd_opts
.gateway_ports
);
3589 dump_cfg_fmtint(oGssAuthentication
, o
->gss_authentication
);
3590 dump_cfg_fmtint(oGssDelegateCreds
, o
->gss_deleg_creds
);
3592 dump_cfg_fmtint(oHashKnownHosts
, o
->hash_known_hosts
);
3593 dump_cfg_fmtint(oHostbasedAuthentication
, o
->hostbased_authentication
);
3594 dump_cfg_fmtint(oIdentitiesOnly
, o
->identities_only
);
3595 dump_cfg_fmtint(oKbdInteractiveAuthentication
, o
->kbd_interactive_authentication
);
3596 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost
, o
->no_host_authentication_for_localhost
);
3597 dump_cfg_fmtint(oPasswordAuthentication
, o
->password_authentication
);
3598 dump_cfg_fmtint(oPermitLocalCommand
, o
->permit_local_command
);
3599 dump_cfg_fmtint(oProxyUseFdpass
, o
->proxy_use_fdpass
);
3600 dump_cfg_fmtint(oPubkeyAuthentication
, o
->pubkey_authentication
);
3601 dump_cfg_fmtint(oRequestTTY
, o
->request_tty
);
3602 dump_cfg_fmtint(oSessionType
, o
->session_type
);
3603 dump_cfg_fmtint(oStdinNull
, o
->stdin_null
);
3604 dump_cfg_fmtint(oForkAfterAuthentication
, o
->fork_after_authentication
);
3605 dump_cfg_fmtint(oStreamLocalBindUnlink
, o
->fwd_opts
.streamlocal_bind_unlink
);
3606 dump_cfg_fmtint(oStrictHostKeyChecking
, o
->strict_host_key_checking
);
3607 dump_cfg_fmtint(oTCPKeepAlive
, o
->tcp_keep_alive
);
3608 dump_cfg_fmtint(oTunnel
, o
->tun_open
);
3609 dump_cfg_fmtint(oVerifyHostKeyDNS
, o
->verify_host_key_dns
);
3610 dump_cfg_fmtint(oVisualHostKey
, o
->visual_host_key
);
3611 dump_cfg_fmtint(oUpdateHostkeys
, o
->update_hostkeys
);
3612 dump_cfg_fmtint(oEnableEscapeCommandline
, o
->enable_escape_commandline
);
3614 /* Integer options */
3615 dump_cfg_int(oCanonicalizeMaxDots
, o
->canonicalize_max_dots
);
3616 dump_cfg_int(oConnectionAttempts
, o
->connection_attempts
);
3617 dump_cfg_int(oForwardX11Timeout
, o
->forward_x11_timeout
);
3618 dump_cfg_int(oNumberOfPasswordPrompts
, o
->number_of_password_prompts
);
3619 dump_cfg_int(oServerAliveCountMax
, o
->server_alive_count_max
);
3620 dump_cfg_int(oServerAliveInterval
, o
->server_alive_interval
);
3621 dump_cfg_int(oRequiredRSASize
, o
->required_rsa_size
);
3622 dump_cfg_int(oObscureKeystrokeTiming
,
3623 o
->obscure_keystroke_timing_interval
);
3625 /* String options */
3626 dump_cfg_string(oBindAddress
, o
->bind_address
);
3627 dump_cfg_string(oBindInterface
, o
->bind_interface
);
3628 dump_cfg_string(oCiphers
, o
->ciphers
);
3629 dump_cfg_string(oControlPath
, o
->control_path
);
3630 dump_cfg_string(oHostKeyAlgorithms
, o
->hostkeyalgorithms
);
3631 dump_cfg_string(oHostKeyAlias
, o
->host_key_alias
);
3632 dump_cfg_string(oHostbasedAcceptedAlgorithms
, o
->hostbased_accepted_algos
);
3633 dump_cfg_string(oIdentityAgent
, o
->identity_agent
);
3634 dump_cfg_string(oIgnoreUnknown
, o
->ignored_unknown
);
3635 dump_cfg_string(oKbdInteractiveDevices
, o
->kbd_interactive_devices
);
3636 dump_cfg_string(oKexAlgorithms
, o
->kex_algorithms
);
3637 dump_cfg_string(oCASignatureAlgorithms
, o
->ca_sign_algorithms
);
3638 dump_cfg_string(oLocalCommand
, o
->local_command
);
3639 dump_cfg_string(oRemoteCommand
, o
->remote_command
);
3640 dump_cfg_string(oLogLevel
, log_level_name(o
->log_level
));
3641 dump_cfg_string(oMacs
, o
->macs
);
3642 #ifdef ENABLE_PKCS11
3643 dump_cfg_string(oPKCS11Provider
, o
->pkcs11_provider
);
3645 dump_cfg_string(oSecurityKeyProvider
, o
->sk_provider
);
3646 dump_cfg_string(oPreferredAuthentications
, o
->preferred_authentications
);
3647 dump_cfg_string(oPubkeyAcceptedAlgorithms
, o
->pubkey_accepted_algos
);
3648 dump_cfg_string(oRevokedHostKeys
, o
->revoked_host_keys
);
3649 dump_cfg_string(oXAuthLocation
, o
->xauth_location
);
3650 dump_cfg_string(oKnownHostsCommand
, o
->known_hosts_command
);
3651 dump_cfg_string(oTag
, o
->tag
);
3654 dump_cfg_forwards(oDynamicForward
, o
->num_local_forwards
, o
->local_forwards
);
3655 dump_cfg_forwards(oLocalForward
, o
->num_local_forwards
, o
->local_forwards
);
3656 dump_cfg_forwards(oRemoteForward
, o
->num_remote_forwards
, o
->remote_forwards
);
3658 /* String array options */
3659 dump_cfg_strarray(oIdentityFile
, o
->num_identity_files
, o
->identity_files
);
3660 dump_cfg_strarray_oneline(oCanonicalDomains
, o
->num_canonical_domains
, o
->canonical_domains
);
3661 dump_cfg_strarray(oCertificateFile
, o
->num_certificate_files
, o
->certificate_files
);
3662 dump_cfg_strarray_oneline(oGlobalKnownHostsFile
, o
->num_system_hostfiles
, o
->system_hostfiles
);
3663 dump_cfg_strarray_oneline(oUserKnownHostsFile
, o
->num_user_hostfiles
, o
->user_hostfiles
);
3664 dump_cfg_strarray(oSendEnv
, o
->num_send_env
, o
->send_env
);
3665 dump_cfg_strarray(oSetEnv
, o
->num_setenv
, o
->setenv
);
3666 dump_cfg_strarray_oneline(oLogVerbose
,
3667 o
->num_log_verbose
, o
->log_verbose
);
3668 dump_cfg_strarray_oneline(oChannelTimeout
,
3669 o
->num_channel_timeouts
, o
->channel_timeouts
);
3673 /* PermitRemoteOpen */
3674 if (o
->num_permitted_remote_opens
== 0)
3675 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen
));
3677 dump_cfg_strarray_oneline(oPermitRemoteOpen
,
3678 o
->num_permitted_remote_opens
, o
->permitted_remote_opens
);
3680 /* AddKeysToAgent */
3681 if (o
->add_keys_to_agent_lifespan
<= 0)
3682 dump_cfg_fmtint(oAddKeysToAgent
, o
->add_keys_to_agent
);
3684 printf("addkeystoagent%s %d\n",
3685 o
->add_keys_to_agent
== 3 ? " confirm" : "",
3686 o
->add_keys_to_agent_lifespan
);
3690 if (o
->forward_agent_sock_path
== NULL
)
3691 dump_cfg_fmtint(oForwardAgent
, o
->forward_agent
);
3693 dump_cfg_string(oForwardAgent
, o
->forward_agent_sock_path
);
3695 /* oConnectTimeout */
3696 if (o
->connection_timeout
== -1)
3697 printf("connecttimeout none\n");
3699 dump_cfg_int(oConnectTimeout
, o
->connection_timeout
);
3702 printf("tunneldevice");
3703 if (o
->tun_local
== SSH_TUNID_ANY
)
3706 printf(" %d", o
->tun_local
);
3707 if (o
->tun_remote
== SSH_TUNID_ANY
)
3710 printf(":%d", o
->tun_remote
);
3713 /* oCanonicalizePermittedCNAMEs */
3714 printf("canonicalizePermittedcnames");
3715 if (o
->num_permitted_cnames
== 0)
3717 for (i
= 0; i
< o
->num_permitted_cnames
; i
++) {
3718 printf(" %s:%s", o
->permitted_cnames
[i
].source_list
,
3719 o
->permitted_cnames
[i
].target_list
);
3723 /* oControlPersist */
3724 if (o
->control_persist
== 0 || o
->control_persist_timeout
== 0)
3725 dump_cfg_fmtint(oControlPersist
, o
->control_persist
);
3727 dump_cfg_int(oControlPersist
, o
->control_persist_timeout
);
3730 if (o
->escape_char
== SSH_ESCAPECHAR_NONE
)
3731 printf("escapechar none\n");
3733 vis(buf
, o
->escape_char
, VIS_WHITE
, 0);
3734 printf("escapechar %s\n", buf
);
3738 printf("ipqos %s ", iptos2str(o
->ip_qos_interactive
));
3739 printf("%s\n", iptos2str(o
->ip_qos_bulk
));
3742 printf("rekeylimit %llu %d\n",
3743 (unsigned long long)o
->rekey_limit
, o
->rekey_interval
);
3745 /* oStreamLocalBindMask */
3746 printf("streamlocalbindmask 0%o\n",
3747 o
->fwd_opts
.streamlocal_bind_mask
);
3750 printf("syslogfacility %s\n", log_facility_name(o
->log_facility
));
3752 /* oProxyCommand / oProxyJump */
3753 if (o
->jump_host
== NULL
)
3754 dump_cfg_string(oProxyCommand
, o
->proxy_command
);
3756 /* Check for numeric addresses */
3757 i
= strchr(o
->jump_host
, ':') != NULL
||
3758 strspn(o
->jump_host
, "1234567890.") == strlen(o
->jump_host
);
3759 snprintf(buf
, sizeof(buf
), "%d", o
->jump_port
);
3760 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3761 /* optional additional jump spec */
3762 o
->jump_extra
== NULL
? "" : o
->jump_extra
,
3763 o
->jump_extra
== NULL
? "" : ",",
3765 o
->jump_user
== NULL
? "" : o
->jump_user
,
3766 o
->jump_user
== NULL
? "" : "@",
3767 /* opening [ if hostname is numeric */
3769 /* mandatory hostname */
3771 /* closing ] if hostname is numeric */
3773 /* optional port number */
3774 o
->jump_port
<= 0 ? "" : ":",
3775 o
->jump_port
<= 0 ? "" : buf
);