readconf.c revision 1.37 1 1.36 kim /* $NetBSD: readconf.c,v 1.37 2021/09/27 17:03:13 christos Exp $ */
2 1.37 christos /* $OpenBSD: readconf.c,v 1.363 2021/09/16 05:36:03 djm Exp $ */
3 1.32 christos
4 1.1 christos /*
5 1.1 christos * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
6 1.1 christos * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
7 1.1 christos * All rights reserved
8 1.1 christos * Functions for reading the configuration files.
9 1.1 christos *
10 1.1 christos * As far as I am concerned, the code I have written for this software
11 1.1 christos * can be used freely for any purpose. Any derived versions of this
12 1.1 christos * software must be clearly marked as such, and if the derived work is
13 1.1 christos * incompatible with the protocol description in the RFC file, it must be
14 1.1 christos * called by a name other than "ssh" or "Secure Shell".
15 1.1 christos */
16 1.1 christos
17 1.2 christos #include "includes.h"
18 1.36 kim __RCSID("$NetBSD: readconf.c,v 1.37 2021/09/27 17:03:13 christos Exp $");
19 1.1 christos #include <sys/types.h>
20 1.1 christos #include <sys/stat.h>
21 1.1 christos #include <sys/socket.h>
22 1.12 christos #include <sys/wait.h>
23 1.12 christos #include <sys/un.h>
24 1.1 christos
25 1.1 christos #include <netinet/in.h>
26 1.5 christos #include <netinet/ip.h>
27 1.1 christos
28 1.1 christos #include <ctype.h>
29 1.1 christos #include <errno.h>
30 1.12 christos #include <fcntl.h>
31 1.19 christos #include <glob.h>
32 1.1 christos #include <netdb.h>
33 1.12 christos #include <paths.h>
34 1.12 christos #include <pwd.h>
35 1.1 christos #include <signal.h>
36 1.1 christos #include <stdio.h>
37 1.1 christos #include <string.h>
38 1.29 christos #include <stdarg.h>
39 1.1 christos #include <unistd.h>
40 1.2 christos #include <limits.h>
41 1.11 christos #include <util.h>
42 1.13 christos #include <vis.h>
43 1.1 christos
44 1.1 christos #include "xmalloc.h"
45 1.1 christos #include "ssh.h"
46 1.25 christos #include "ssherr.h"
47 1.1 christos #include "compat.h"
48 1.1 christos #include "cipher.h"
49 1.1 christos #include "pathnames.h"
50 1.1 christos #include "log.h"
51 1.13 christos #include "sshkey.h"
52 1.12 christos #include "misc.h"
53 1.1 christos #include "readconf.h"
54 1.1 christos #include "match.h"
55 1.1 christos #include "kex.h"
56 1.1 christos #include "mac.h"
57 1.11 christos #include "fmt_scaled.h"
58 1.12 christos #include "uidswap.h"
59 1.13 christos #include "myproposal.h"
60 1.13 christos #include "digest.h"
61 1.1 christos
62 1.1 christos /* Format of the configuration file:
63 1.1 christos
64 1.1 christos # Configuration data is parsed as follows:
65 1.1 christos # 1. command line options
66 1.1 christos # 2. user-specific file
67 1.1 christos # 3. system-wide file
68 1.1 christos # Any configuration value is only changed the first time it is set.
69 1.1 christos # Thus, host-specific definitions should be at the beginning of the
70 1.1 christos # configuration file, and defaults at the end.
71 1.1 christos
72 1.1 christos # Host-specific declarations. These may override anything above. A single
73 1.1 christos # host may match multiple declarations; these are processed in the order
74 1.1 christos # that they are given in.
75 1.1 christos
76 1.1 christos Host *.ngs.fi ngs.fi
77 1.1 christos User foo
78 1.1 christos
79 1.1 christos Host fake.com
80 1.28 christos Hostname another.host.name.real.org
81 1.1 christos User blaah
82 1.1 christos Port 34289
83 1.1 christos ForwardX11 no
84 1.1 christos ForwardAgent no
85 1.1 christos
86 1.1 christos Host books.com
87 1.1 christos RemoteForward 9999 shadows.cs.hut.fi:9999
88 1.21 christos Ciphers 3des-cbc
89 1.1 christos
90 1.1 christos Host fascist.blob.com
91 1.1 christos Port 23123
92 1.1 christos User tylonen
93 1.1 christos PasswordAuthentication no
94 1.1 christos
95 1.1 christos Host puukko.hut.fi
96 1.1 christos User t35124p
97 1.1 christos ProxyCommand ssh-proxy %h %p
98 1.1 christos
99 1.1 christos Host *.fr
100 1.1 christos PublicKeyAuthentication no
101 1.1 christos
102 1.1 christos Host *.su
103 1.21 christos Ciphers aes128-ctr
104 1.1 christos PasswordAuthentication no
105 1.1 christos
106 1.1 christos Host vpn.fake.com
107 1.1 christos Tunnel yes
108 1.1 christos TunnelDevice 3
109 1.1 christos
110 1.1 christos # Defaults for various options
111 1.1 christos Host *
112 1.1 christos ForwardAgent no
113 1.1 christos ForwardX11 no
114 1.1 christos PasswordAuthentication yes
115 1.1 christos StrictHostKeyChecking yes
116 1.1 christos TcpKeepAlive no
117 1.1 christos IdentityFile ~/.ssh/identity
118 1.1 christos Port 22
119 1.1 christos EscapeChar ~
120 1.1 christos
121 1.1 christos */
122 1.1 christos
123 1.19 christos static int read_config_file_depth(const char *filename, struct passwd *pw,
124 1.19 christos const char *host, const char *original_host, Options *options,
125 1.27 christos int flags, int *activep, int *want_final_pass, int depth);
126 1.19 christos static int process_config_line_depth(Options *options, struct passwd *pw,
127 1.19 christos const char *host, const char *original_host, char *line,
128 1.27 christos const char *filename, int linenum, int *activep, int flags,
129 1.27 christos int *want_final_pass, int depth);
130 1.19 christos
131 1.1 christos /* Keyword tokens. */
132 1.1 christos
133 1.1 christos typedef enum {
134 1.1 christos oBadOption,
135 1.19 christos oHost, oMatch, oInclude,
136 1.4 adam oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
137 1.4 adam oGatewayPorts, oExitOnForwardFailure,
138 1.29 christos oPasswordAuthentication,
139 1.35 christos oXAuthLocation,
140 1.2 christos #if defined(KRB4) || defined(KRB5)
141 1.2 christos oKerberosAuthentication,
142 1.2 christos #endif
143 1.2 christos #if defined(AFS) || defined(KRB5)
144 1.2 christos oKerberosTgtPassing,
145 1.2 christos #endif
146 1.2 christos #ifdef AFS
147 1.2 christos oAFSTokenPassing,
148 1.2 christos #endif
149 1.29 christos oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
150 1.33 christos oPermitRemoteOpen,
151 1.19 christos oCertificateFile, oAddKeysToAgent, oIdentityAgent,
152 1.29 christos oUser, oEscapeChar, oProxyCommand,
153 1.1 christos oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
154 1.1 christos oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
155 1.29 christos oTCPKeepAlive, oNumberOfPasswordPrompts,
156 1.33 christos oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
157 1.13 christos oPubkeyAuthentication,
158 1.1 christos oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
159 1.1 christos oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
160 1.23 christos oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
161 1.1 christos oClearAllForwardings, oNoHostAuthenticationForLocalhost,
162 1.1 christos oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
163 1.1 christos oAddressFamily, oGssAuthentication, oGssDelegateCreds,
164 1.1 christos oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
165 1.25 christos oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
166 1.4 adam oHashKnownHosts,
167 1.22 christos oTunnel, oTunnelDevice,
168 1.22 christos oLocalCommand, oPermitLocalCommand, oRemoteCommand,
169 1.17 christos oVisualHostKey,
170 1.35 christos oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
171 1.35 christos oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
172 1.12 christos oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
173 1.12 christos oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
174 1.13 christos oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
175 1.33 christos oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
176 1.33 christos oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
177 1.33 christos oSecurityKeyProvider, oKnownHostsCommand,
178 1.2 christos oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
179 1.2 christos oHPNBufferSize,
180 1.7 tls oSendVersionFirst,
181 1.22 christos oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
182 1.1 christos } OpCodes;
183 1.1 christos
184 1.1 christos /* Textual representations of the tokens. */
185 1.1 christos
186 1.1 christos static struct {
187 1.1 christos const char *name;
188 1.1 christos OpCodes opcode;
189 1.1 christos } keywords[] = {
190 1.21 christos /* Deprecated options */
191 1.22 christos { "protocol", oIgnore }, /* NB. silently ignored */
192 1.22 christos { "cipher", oDeprecated },
193 1.21 christos { "fallbacktorsh", oDeprecated },
194 1.21 christos { "globalknownhostsfile2", oDeprecated },
195 1.21 christos { "rhostsauthentication", oDeprecated },
196 1.21 christos { "userknownhostsfile2", oDeprecated },
197 1.21 christos { "useroaming", oDeprecated },
198 1.21 christos { "usersh", oDeprecated },
199 1.25 christos { "useprivilegedport", oDeprecated },
200 1.21 christos
201 1.21 christos /* Unsupported options */
202 1.30 kim #ifdef AFS
203 1.30 kim { "afstokenpassing", oAFSTokenPassing },
204 1.30 kim #else
205 1.21 christos { "afstokenpassing", oUnsupported },
206 1.30 kim #endif
207 1.30 kim #if defined(KRB4) || defined(KRB5)
208 1.30 kim { "kerberosauthentication", oKerberosAuthentication },
209 1.30 kim #else
210 1.21 christos { "kerberosauthentication", oUnsupported },
211 1.30 kim #endif
212 1.30 kim #if defined(AFS) || defined(KRB5)
213 1.30 kim { "kerberostgtpassing", oKerberosTgtPassing },
214 1.30 kim { "kerberos5tgtpassing", oKerberosTgtPassing }, /* alias */
215 1.30 kim { "kerberos4tgtpassing", oKerberosTgtPassing }, /* alias */
216 1.30 kim #else
217 1.21 christos { "kerberostgtpassing", oUnsupported },
218 1.30 kim { "kerberos5tgtpassing", oUnsupported },
219 1.30 kim { "kerberos4tgtpassing", oUnsupported },
220 1.30 kim #endif
221 1.29 christos { "rsaauthentication", oUnsupported },
222 1.29 christos { "rhostsrsaauthentication", oUnsupported },
223 1.29 christos { "compressionlevel", oUnsupported },
224 1.21 christos
225 1.21 christos /* Sometimes-unsupported options */
226 1.21 christos #if defined(GSSAPI)
227 1.21 christos { "gssapiauthentication", oGssAuthentication },
228 1.21 christos { "gssapidelegatecredentials", oGssDelegateCreds },
229 1.21 christos # else
230 1.21 christos { "gssapiauthentication", oUnsupported },
231 1.21 christos { "gssapidelegatecredentials", oUnsupported },
232 1.21 christos #endif
233 1.21 christos #ifdef ENABLE_PKCS11
234 1.27 christos { "pkcs11provider", oPKCS11Provider },
235 1.21 christos { "smartcarddevice", oPKCS11Provider },
236 1.21 christos # else
237 1.21 christos { "smartcarddevice", oUnsupported },
238 1.21 christos { "pkcs11provider", oUnsupported },
239 1.21 christos #endif
240 1.21 christos
241 1.1 christos { "forwardagent", oForwardAgent },
242 1.1 christos { "forwardx11", oForwardX11 },
243 1.1 christos { "forwardx11trusted", oForwardX11Trusted },
244 1.4 adam { "forwardx11timeout", oForwardX11Timeout },
245 1.1 christos { "exitonforwardfailure", oExitOnForwardFailure },
246 1.1 christos { "xauthlocation", oXAuthLocation },
247 1.1 christos { "gatewayports", oGatewayPorts },
248 1.1 christos { "passwordauthentication", oPasswordAuthentication },
249 1.1 christos { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
250 1.1 christos { "kbdinteractivedevices", oKbdInteractiveDevices },
251 1.36 kim { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
252 1.36 kim { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
253 1.36 kim { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */
254 1.1 christos { "pubkeyauthentication", oPubkeyAuthentication },
255 1.1 christos { "dsaauthentication", oPubkeyAuthentication }, /* alias */
256 1.1 christos { "hostbasedauthentication", oHostbasedAuthentication },
257 1.1 christos #if defined(GSSAPI)
258 1.1 christos { "gssapiauthentication", oGssAuthentication },
259 1.1 christos { "gssapidelegatecredentials", oGssDelegateCreds },
260 1.1 christos #else
261 1.1 christos { "gssapiauthentication", oUnsupported },
262 1.1 christos { "gssapidelegatecredentials", oUnsupported },
263 1.1 christos #endif
264 1.1 christos { "identityfile", oIdentityFile },
265 1.1 christos { "identityfile2", oIdentityFile }, /* obsolete */
266 1.1 christos { "identitiesonly", oIdentitiesOnly },
267 1.18 christos { "certificatefile", oCertificateFile },
268 1.18 christos { "addkeystoagent", oAddKeysToAgent },
269 1.19 christos { "identityagent", oIdentityAgent },
270 1.28 christos { "hostname", oHostname },
271 1.1 christos { "hostkeyalias", oHostKeyAlias },
272 1.1 christos { "proxycommand", oProxyCommand },
273 1.1 christos { "port", oPort },
274 1.1 christos { "ciphers", oCiphers },
275 1.1 christos { "macs", oMacs },
276 1.1 christos { "remoteforward", oRemoteForward },
277 1.1 christos { "localforward", oLocalForward },
278 1.33 christos { "permitremoteopen", oPermitRemoteOpen },
279 1.1 christos { "user", oUser },
280 1.1 christos { "host", oHost },
281 1.12 christos { "match", oMatch },
282 1.1 christos { "escapechar", oEscapeChar },
283 1.1 christos { "globalknownhostsfile", oGlobalKnownHostsFile },
284 1.1 christos { "userknownhostsfile", oUserKnownHostsFile },
285 1.1 christos { "connectionattempts", oConnectionAttempts },
286 1.1 christos { "batchmode", oBatchMode },
287 1.1 christos { "checkhostip", oCheckHostIP },
288 1.1 christos { "stricthostkeychecking", oStrictHostKeyChecking },
289 1.1 christos { "compression", oCompression },
290 1.1 christos { "tcpkeepalive", oTCPKeepAlive },
291 1.1 christos { "keepalive", oTCPKeepAlive }, /* obsolete */
292 1.1 christos { "numberofpasswordprompts", oNumberOfPasswordPrompts },
293 1.22 christos { "syslogfacility", oLogFacility },
294 1.1 christos { "loglevel", oLogLevel },
295 1.33 christos { "logverbose", oLogVerbose },
296 1.1 christos { "dynamicforward", oDynamicForward },
297 1.1 christos { "preferredauthentications", oPreferredAuthentications },
298 1.1 christos { "hostkeyalgorithms", oHostKeyAlgorithms },
299 1.27 christos { "casignaturealgorithms", oCASignatureAlgorithms },
300 1.1 christos { "bindaddress", oBindAddress },
301 1.23 christos { "bindinterface", oBindInterface },
302 1.1 christos { "clearallforwardings", oClearAllForwardings },
303 1.1 christos { "enablesshkeysign", oEnableSSHKeysign },
304 1.1 christos { "verifyhostkeydns", oVerifyHostKeyDNS },
305 1.1 christos { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
306 1.1 christos { "rekeylimit", oRekeyLimit },
307 1.1 christos { "connecttimeout", oConnectTimeout },
308 1.1 christos { "addressfamily", oAddressFamily },
309 1.1 christos { "serveraliveinterval", oServerAliveInterval },
310 1.1 christos { "serveralivecountmax", oServerAliveCountMax },
311 1.1 christos { "sendenv", oSendEnv },
312 1.25 christos { "setenv", oSetEnv },
313 1.1 christos { "controlpath", oControlPath },
314 1.1 christos { "controlmaster", oControlMaster },
315 1.4 adam { "controlpersist", oControlPersist },
316 1.1 christos { "hashknownhosts", oHashKnownHosts },
317 1.19 christos { "include", oInclude },
318 1.1 christos { "tunnel", oTunnel },
319 1.1 christos { "tunneldevice", oTunnelDevice },
320 1.1 christos { "localcommand", oLocalCommand },
321 1.1 christos { "permitlocalcommand", oPermitLocalCommand },
322 1.22 christos { "remotecommand", oRemoteCommand },
323 1.1 christos { "visualhostkey", oVisualHostKey },
324 1.5 christos { "kexalgorithms", oKexAlgorithms },
325 1.5 christos { "ipqos", oIPQoS },
326 1.6 christos { "requesttty", oRequestTTY },
327 1.35 christos { "sessiontype", oSessionType },
328 1.35 christos { "stdinnull", oStdinNull },
329 1.35 christos { "forkafterauthentication", oForkAfterAuthentication },
330 1.12 christos { "proxyusefdpass", oProxyUseFdpass },
331 1.12 christos { "canonicaldomains", oCanonicalDomains },
332 1.12 christos { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
333 1.12 christos { "canonicalizehostname", oCanonicalizeHostname },
334 1.12 christos { "canonicalizemaxdots", oCanonicalizeMaxDots },
335 1.12 christos { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
336 1.12 christos { "streamlocalbindmask", oStreamLocalBindMask },
337 1.12 christos { "streamlocalbindunlink", oStreamLocalBindUnlink },
338 1.13 christos { "revokedhostkeys", oRevokedHostKeys },
339 1.13 christos { "fingerprinthash", oFingerprintHash },
340 1.13 christos { "updatehostkeys", oUpdateHostkeys },
341 1.35 christos { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
342 1.33 christos { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
343 1.33 christos { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
344 1.33 christos { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
345 1.19 christos { "proxyjump", oProxyJump },
346 1.2 christos { "noneenabled", oNoneEnabled },
347 1.2 christos { "tcprcvbufpoll", oTcpRcvBufPoll },
348 1.2 christos { "tcprcvbuf", oTcpRcvBuf },
349 1.2 christos { "noneswitch", oNoneSwitch },
350 1.2 christos { "hpndisabled", oHPNDisabled },
351 1.2 christos { "hpnbuffersize", oHPNBufferSize },
352 1.7 tls { "sendversionfirst", oSendVersionFirst },
353 1.12 christos { "ignoreunknown", oIgnoreUnknown },
354 1.29 christos { "proxyjump", oProxyJump },
355 1.29 christos { "securitykeyprovider", oSecurityKeyProvider },
356 1.33 christos { "knownhostscommand", oKnownHostsCommand },
357 1.19 christos
358 1.1 christos { NULL, oBadOption }
359 1.1 christos };
360 1.1 christos
361 1.33 christos static const char *lookup_opcode_name(OpCodes code);
362 1.29 christos
363 1.29 christos const char *
364 1.29 christos kex_default_pk_alg(void)
365 1.29 christos {
366 1.33 christos static char *pkalgs;
367 1.33 christos
368 1.33 christos if (pkalgs == NULL) {
369 1.33 christos char *all_key;
370 1.33 christos
371 1.33 christos all_key = sshkey_alg_list(0, 0, 1, ',');
372 1.33 christos pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
373 1.33 christos free(all_key);
374 1.33 christos }
375 1.33 christos return pkalgs;
376 1.29 christos }
377 1.29 christos
378 1.31 christos char *
379 1.31 christos ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
380 1.31 christos const char *user)
381 1.31 christos {
382 1.31 christos struct ssh_digest_ctx *md;
383 1.31 christos u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
384 1.31 christos
385 1.31 christos if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
386 1.31 christos ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
387 1.31 christos ssh_digest_update(md, host, strlen(host)) < 0 ||
388 1.31 christos ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
389 1.31 christos ssh_digest_update(md, user, strlen(user)) < 0 ||
390 1.31 christos ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
391 1.33 christos fatal_f("mux digest failed");
392 1.31 christos ssh_digest_free(md);
393 1.31 christos return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
394 1.31 christos }
395 1.31 christos
396 1.1 christos /*
397 1.1 christos * Adds a local TCP/IP port forward to options. Never returns if there is an
398 1.1 christos * error.
399 1.1 christos */
400 1.1 christos
401 1.1 christos void
402 1.12 christos add_local_forward(Options *options, const struct Forward *newfwd)
403 1.1 christos {
404 1.12 christos struct Forward *fwd;
405 1.19 christos int i;
406 1.4 adam
407 1.19 christos /* Don't add duplicates */
408 1.19 christos for (i = 0; i < options->num_local_forwards; i++) {
409 1.19 christos if (forward_equals(newfwd, options->local_forwards + i))
410 1.19 christos return;
411 1.19 christos }
412 1.14 christos options->local_forwards = xreallocarray(options->local_forwards,
413 1.4 adam options->num_local_forwards + 1,
414 1.4 adam sizeof(*options->local_forwards));
415 1.1 christos fwd = &options->local_forwards[options->num_local_forwards++];
416 1.1 christos
417 1.1 christos fwd->listen_host = newfwd->listen_host;
418 1.1 christos fwd->listen_port = newfwd->listen_port;
419 1.12 christos fwd->listen_path = newfwd->listen_path;
420 1.1 christos fwd->connect_host = newfwd->connect_host;
421 1.1 christos fwd->connect_port = newfwd->connect_port;
422 1.12 christos fwd->connect_path = newfwd->connect_path;
423 1.1 christos }
424 1.1 christos
425 1.1 christos /*
426 1.1 christos * Adds a remote TCP/IP port forward to options. Never returns if there is
427 1.1 christos * an error.
428 1.1 christos */
429 1.1 christos
430 1.1 christos void
431 1.12 christos add_remote_forward(Options *options, const struct Forward *newfwd)
432 1.1 christos {
433 1.12 christos struct Forward *fwd;
434 1.19 christos int i;
435 1.4 adam
436 1.19 christos /* Don't add duplicates */
437 1.19 christos for (i = 0; i < options->num_remote_forwards; i++) {
438 1.19 christos if (forward_equals(newfwd, options->remote_forwards + i))
439 1.19 christos return;
440 1.19 christos }
441 1.14 christos options->remote_forwards = xreallocarray(options->remote_forwards,
442 1.4 adam options->num_remote_forwards + 1,
443 1.4 adam sizeof(*options->remote_forwards));
444 1.1 christos fwd = &options->remote_forwards[options->num_remote_forwards++];
445 1.1 christos
446 1.1 christos fwd->listen_host = newfwd->listen_host;
447 1.1 christos fwd->listen_port = newfwd->listen_port;
448 1.12 christos fwd->listen_path = newfwd->listen_path;
449 1.1 christos fwd->connect_host = newfwd->connect_host;
450 1.1 christos fwd->connect_port = newfwd->connect_port;
451 1.12 christos fwd->connect_path = newfwd->connect_path;
452 1.8 christos fwd->handle = newfwd->handle;
453 1.4 adam fwd->allocated_port = 0;
454 1.1 christos }
455 1.1 christos
456 1.1 christos static void
457 1.1 christos clear_forwardings(Options *options)
458 1.1 christos {
459 1.1 christos int i;
460 1.1 christos
461 1.1 christos for (i = 0; i < options->num_local_forwards; i++) {
462 1.11 christos free(options->local_forwards[i].listen_host);
463 1.12 christos free(options->local_forwards[i].listen_path);
464 1.11 christos free(options->local_forwards[i].connect_host);
465 1.12 christos free(options->local_forwards[i].connect_path);
466 1.1 christos }
467 1.4 adam if (options->num_local_forwards > 0) {
468 1.11 christos free(options->local_forwards);
469 1.4 adam options->local_forwards = NULL;
470 1.4 adam }
471 1.1 christos options->num_local_forwards = 0;
472 1.1 christos for (i = 0; i < options->num_remote_forwards; i++) {
473 1.11 christos free(options->remote_forwards[i].listen_host);
474 1.12 christos free(options->remote_forwards[i].listen_path);
475 1.11 christos free(options->remote_forwards[i].connect_host);
476 1.12 christos free(options->remote_forwards[i].connect_path);
477 1.1 christos }
478 1.4 adam if (options->num_remote_forwards > 0) {
479 1.11 christos free(options->remote_forwards);
480 1.4 adam options->remote_forwards = NULL;
481 1.4 adam }
482 1.1 christos options->num_remote_forwards = 0;
483 1.1 christos options->tun_open = SSH_TUNMODE_NO;
484 1.1 christos }
485 1.1 christos
486 1.9 mlelstv void
487 1.18 christos add_certificate_file(Options *options, const char *path, int userprovided)
488 1.18 christos {
489 1.18 christos int i;
490 1.18 christos
491 1.18 christos if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
492 1.18 christos fatal("Too many certificate files specified (max %d)",
493 1.18 christos SSH_MAX_CERTIFICATE_FILES);
494 1.18 christos
495 1.18 christos /* Avoid registering duplicates */
496 1.18 christos for (i = 0; i < options->num_certificate_files; i++) {
497 1.18 christos if (options->certificate_file_userprovided[i] == userprovided &&
498 1.18 christos strcmp(options->certificate_files[i], path) == 0) {
499 1.33 christos debug2_f("ignoring duplicate key %s", path);
500 1.18 christos return;
501 1.18 christos }
502 1.18 christos }
503 1.18 christos
504 1.18 christos options->certificate_file_userprovided[options->num_certificate_files] =
505 1.18 christos userprovided;
506 1.18 christos options->certificate_files[options->num_certificate_files++] =
507 1.18 christos xstrdup(path);
508 1.18 christos }
509 1.18 christos
510 1.18 christos void
511 1.9 mlelstv add_identity_file(Options *options, const char *dir, const char *filename,
512 1.9 mlelstv int userprovided)
513 1.9 mlelstv {
514 1.9 mlelstv char *path;
515 1.12 christos int i;
516 1.9 mlelstv
517 1.9 mlelstv if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
518 1.9 mlelstv fatal("Too many identity files specified (max %d)",
519 1.9 mlelstv SSH_MAX_IDENTITY_FILES);
520 1.9 mlelstv
521 1.9 mlelstv if (dir == NULL) /* no dir, filename is absolute */
522 1.9 mlelstv path = xstrdup(filename);
523 1.22 christos else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
524 1.22 christos fatal("Identity file path %s too long", path);
525 1.9 mlelstv
526 1.12 christos /* Avoid registering duplicates */
527 1.12 christos for (i = 0; i < options->num_identity_files; i++) {
528 1.12 christos if (options->identity_file_userprovided[i] == userprovided &&
529 1.12 christos strcmp(options->identity_files[i], path) == 0) {
530 1.33 christos debug2_f("ignoring duplicate key %s", path);
531 1.12 christos free(path);
532 1.12 christos return;
533 1.12 christos }
534 1.12 christos }
535 1.12 christos
536 1.9 mlelstv options->identity_file_userprovided[options->num_identity_files] =
537 1.9 mlelstv userprovided;
538 1.9 mlelstv options->identity_files[options->num_identity_files++] = path;
539 1.9 mlelstv }
540 1.9 mlelstv
541 1.12 christos int
542 1.12 christos default_ssh_port(void)
543 1.12 christos {
544 1.12 christos static int port;
545 1.12 christos struct servent *sp;
546 1.12 christos
547 1.12 christos if (port == 0) {
548 1.12 christos sp = getservbyname(SSH_SERVICE_NAME, "tcp");
549 1.12 christos port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
550 1.12 christos }
551 1.12 christos return port;
552 1.12 christos }
553 1.12 christos
554 1.12 christos /*
555 1.12 christos * Execute a command in a shell.
556 1.12 christos * Return its exit status or -1 on abnormal exit.
557 1.12 christos */
558 1.12 christos static int
559 1.12 christos execute_in_shell(const char *cmd)
560 1.12 christos {
561 1.12 christos const char *shell;
562 1.12 christos pid_t pid;
563 1.33 christos int status;
564 1.12 christos
565 1.12 christos if ((shell = getenv("SHELL")) == NULL)
566 1.12 christos shell = _PATH_BSHELL;
567 1.12 christos
568 1.28 christos if (access(shell, X_OK) == -1) {
569 1.28 christos fatal("Shell \"%s\" is not executable: %s",
570 1.28 christos shell, strerror(errno));
571 1.28 christos }
572 1.28 christos
573 1.12 christos debug("Executing command: '%.500s'", cmd);
574 1.12 christos
575 1.12 christos /* Fork and execute the command. */
576 1.12 christos if ((pid = fork()) == 0) {
577 1.12 christos char *argv[4];
578 1.12 christos
579 1.33 christos if (stdfd_devnull(1, 1, 0) == -1)
580 1.33 christos fatal_f("stdfd_devnull failed");
581 1.33 christos closefrom(STDERR_FILENO + 1);
582 1.12 christos
583 1.12 christos argv[0] = __UNCONST(shell);
584 1.12 christos argv[1] = __UNCONST("-c");
585 1.18 christos argv[2] = xstrdup(cmd);
586 1.12 christos argv[3] = NULL;
587 1.12 christos
588 1.12 christos execv(argv[0], argv);
589 1.12 christos error("Unable to execute '%.100s': %s", cmd, strerror(errno));
590 1.12 christos /* Die with signal to make this error apparent to parent. */
591 1.29 christos ssh_signal(SIGTERM, SIG_DFL);
592 1.12 christos kill(getpid(), SIGTERM);
593 1.12 christos _exit(1);
594 1.12 christos }
595 1.12 christos /* Parent. */
596 1.28 christos if (pid == -1)
597 1.33 christos fatal_f("fork: %.100s", strerror(errno));
598 1.12 christos
599 1.12 christos while (waitpid(pid, &status, 0) == -1) {
600 1.12 christos if (errno != EINTR && errno != EAGAIN)
601 1.33 christos fatal_f("waitpid: %s", strerror(errno));
602 1.12 christos }
603 1.12 christos if (!WIFEXITED(status)) {
604 1.12 christos error("command '%.100s' exited abnormally", cmd);
605 1.12 christos return -1;
606 1.13 christos }
607 1.12 christos debug3("command returned status %d", WEXITSTATUS(status));
608 1.12 christos return WEXITSTATUS(status);
609 1.12 christos }
610 1.12 christos
611 1.12 christos /*
612 1.12 christos * Parse and execute a Match directive.
613 1.12 christos */
614 1.12 christos static int
615 1.12 christos match_cfg_line(Options *options, char **condition, struct passwd *pw,
616 1.27 christos const char *host_arg, const char *original_host, int final_pass,
617 1.27 christos int *want_final_pass, const char *filename, int linenum)
618 1.12 christos {
619 1.13 christos char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
620 1.12 christos const char *ruser;
621 1.13 christos int r, port, this_result, result = 1, attributes = 0, negate;
622 1.12 christos char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
623 1.25 christos char uidstr[32];
624 1.12 christos
625 1.12 christos /*
626 1.12 christos * Configuration is likely to be incomplete at this point so we
627 1.12 christos * must be prepared to use default values.
628 1.12 christos */
629 1.12 christos port = options->port <= 0 ? default_ssh_port() : options->port;
630 1.12 christos ruser = options->user == NULL ? pw->pw_name : options->user;
631 1.27 christos if (final_pass) {
632 1.18 christos host = xstrdup(options->hostname);
633 1.18 christos } else if (options->hostname != NULL) {
634 1.12 christos /* NB. Please keep in sync with ssh.c:main() */
635 1.12 christos host = percent_expand(options->hostname,
636 1.12 christos "h", host_arg, (char *)NULL);
637 1.18 christos } else {
638 1.12 christos host = xstrdup(host_arg);
639 1.18 christos }
640 1.12 christos
641 1.13 christos debug2("checking match for '%s' host %s originally %s",
642 1.13 christos cp, host, original_host);
643 1.13 christos while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
644 1.35 christos /* Terminate on comment */
645 1.35 christos if (*attrib == '#') {
646 1.35 christos cp = NULL; /* mark all arguments consumed */
647 1.35 christos break;
648 1.35 christos }
649 1.35 christos arg = criteria = NULL;
650 1.13 christos this_result = 1;
651 1.13 christos if ((negate = attrib[0] == '!'))
652 1.13 christos attrib++;
653 1.35 christos /* Criterion "all" has no argument and must appear alone */
654 1.12 christos if (strcasecmp(attrib, "all") == 0) {
655 1.35 christos if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
656 1.35 christos *arg != '\0' && *arg != '#')) {
657 1.13 christos error("%.200s line %d: '%s' cannot be combined "
658 1.13 christos "with other Match attributes",
659 1.13 christos filename, linenum, oattrib);
660 1.12 christos result = -1;
661 1.12 christos goto out;
662 1.12 christos }
663 1.35 christos if (arg != NULL && *arg == '#')
664 1.35 christos cp = NULL; /* mark all arguments consumed */
665 1.13 christos if (result)
666 1.13 christos result = negate ? 0 : 1;
667 1.12 christos goto out;
668 1.12 christos }
669 1.13 christos attributes++;
670 1.35 christos /* criteria "final" and "canonical" have no argument */
671 1.27 christos if (strcasecmp(attrib, "canonical") == 0 ||
672 1.27 christos strcasecmp(attrib, "final") == 0) {
673 1.27 christos /*
674 1.27 christos * If the config requests "Match final" then remember
675 1.27 christos * this so we can perform a second pass later.
676 1.27 christos */
677 1.27 christos if (strcasecmp(attrib, "final") == 0 &&
678 1.27 christos want_final_pass != NULL)
679 1.27 christos *want_final_pass = 1;
680 1.27 christos r = !!final_pass; /* force bitmask member to boolean */
681 1.13 christos if (r == (negate ? 1 : 0))
682 1.13 christos this_result = result = 0;
683 1.13 christos debug3("%.200s line %d: %smatched '%s'",
684 1.13 christos filename, linenum,
685 1.13 christos this_result ? "" : "not ", oattrib);
686 1.13 christos continue;
687 1.13 christos }
688 1.13 christos /* All other criteria require an argument */
689 1.35 christos if ((arg = strdelim(&cp)) == NULL ||
690 1.35 christos *arg == '\0' || *arg == '#') {
691 1.12 christos error("Missing Match criteria for %s", attrib);
692 1.12 christos result = -1;
693 1.12 christos goto out;
694 1.12 christos }
695 1.12 christos if (strcasecmp(attrib, "host") == 0) {
696 1.13 christos criteria = xstrdup(host);
697 1.14 christos r = match_hostname(host, arg) == 1;
698 1.13 christos if (r == (negate ? 1 : 0))
699 1.13 christos this_result = result = 0;
700 1.12 christos } else if (strcasecmp(attrib, "originalhost") == 0) {
701 1.13 christos criteria = xstrdup(original_host);
702 1.14 christos r = match_hostname(original_host, arg) == 1;
703 1.13 christos if (r == (negate ? 1 : 0))
704 1.13 christos this_result = result = 0;
705 1.12 christos } else if (strcasecmp(attrib, "user") == 0) {
706 1.13 christos criteria = xstrdup(ruser);
707 1.14 christos r = match_pattern_list(ruser, arg, 0) == 1;
708 1.13 christos if (r == (negate ? 1 : 0))
709 1.13 christos this_result = result = 0;
710 1.12 christos } else if (strcasecmp(attrib, "localuser") == 0) {
711 1.13 christos criteria = xstrdup(pw->pw_name);
712 1.14 christos r = match_pattern_list(pw->pw_name, arg, 0) == 1;
713 1.13 christos if (r == (negate ? 1 : 0))
714 1.13 christos this_result = result = 0;
715 1.12 christos } else if (strcasecmp(attrib, "exec") == 0) {
716 1.32 christos char *conn_hash_hex, *keyalias;
717 1.31 christos
718 1.12 christos if (gethostname(thishost, sizeof(thishost)) == -1)
719 1.12 christos fatal("gethostname: %s", strerror(errno));
720 1.12 christos strlcpy(shorthost, thishost, sizeof(shorthost));
721 1.12 christos shorthost[strcspn(thishost, ".")] = '\0';
722 1.12 christos snprintf(portstr, sizeof(portstr), "%d", port);
723 1.25 christos snprintf(uidstr, sizeof(uidstr), "%llu",
724 1.25 christos (unsigned long long)pw->pw_uid);
725 1.31 christos conn_hash_hex = ssh_connection_hash(thishost, host,
726 1.34 christos portstr, ruser);
727 1.32 christos keyalias = options->host_key_alias ?
728 1.32 christos options->host_key_alias : host;
729 1.12 christos
730 1.12 christos cmd = percent_expand(arg,
731 1.31 christos "C", conn_hash_hex,
732 1.12 christos "L", shorthost,
733 1.12 christos "d", pw->pw_dir,
734 1.12 christos "h", host,
735 1.32 christos "k", keyalias,
736 1.12 christos "l", thishost,
737 1.13 christos "n", original_host,
738 1.12 christos "p", portstr,
739 1.12 christos "r", ruser,
740 1.12 christos "u", pw->pw_name,
741 1.25 christos "i", uidstr,
742 1.12 christos (char *)NULL);
743 1.31 christos free(conn_hash_hex);
744 1.12 christos if (result != 1) {
745 1.12 christos /* skip execution if prior predicate failed */
746 1.13 christos debug3("%.200s line %d: skipped exec "
747 1.13 christos "\"%.100s\"", filename, linenum, cmd);
748 1.13 christos free(cmd);
749 1.13 christos continue;
750 1.13 christos }
751 1.13 christos r = execute_in_shell(cmd);
752 1.13 christos if (r == -1) {
753 1.13 christos fatal("%.200s line %d: match exec "
754 1.13 christos "'%.100s' error", filename,
755 1.13 christos linenum, cmd);
756 1.12 christos }
757 1.13 christos criteria = xstrdup(cmd);
758 1.12 christos free(cmd);
759 1.13 christos /* Force exit status to boolean */
760 1.13 christos r = r == 0;
761 1.13 christos if (r == (negate ? 1 : 0))
762 1.13 christos this_result = result = 0;
763 1.12 christos } else {
764 1.12 christos error("Unsupported Match attribute %s", attrib);
765 1.12 christos result = -1;
766 1.12 christos goto out;
767 1.12 christos }
768 1.13 christos debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
769 1.13 christos filename, linenum, this_result ? "": "not ",
770 1.13 christos oattrib, criteria);
771 1.13 christos free(criteria);
772 1.12 christos }
773 1.12 christos if (attributes == 0) {
774 1.12 christos error("One or more attributes required for Match");
775 1.12 christos result = -1;
776 1.12 christos goto out;
777 1.12 christos }
778 1.13 christos out:
779 1.13 christos if (result != -1)
780 1.13 christos debug2("match %sfound", result ? "" : "not ");
781 1.12 christos *condition = cp;
782 1.12 christos free(host);
783 1.12 christos return result;
784 1.12 christos }
785 1.12 christos
786 1.25 christos /* Remove environment variable by pattern */
787 1.25 christos static void
788 1.25 christos rm_env(Options *options, const char *arg, const char *filename, int linenum)
789 1.25 christos {
790 1.32 christos int i, j, onum_send_env = options->num_send_env;
791 1.25 christos char *cp;
792 1.25 christos
793 1.25 christos /* Remove an environment variable */
794 1.25 christos for (i = 0; i < options->num_send_env; ) {
795 1.25 christos cp = xstrdup(options->send_env[i]);
796 1.25 christos if (!match_pattern(cp, arg + 1)) {
797 1.25 christos free(cp);
798 1.25 christos i++;
799 1.25 christos continue;
800 1.25 christos }
801 1.25 christos debug3("%s line %d: removing environment %s",
802 1.25 christos filename, linenum, cp);
803 1.25 christos free(cp);
804 1.25 christos free(options->send_env[i]);
805 1.25 christos options->send_env[i] = NULL;
806 1.25 christos for (j = i; j < options->num_send_env - 1; j++) {
807 1.25 christos options->send_env[j] = options->send_env[j + 1];
808 1.25 christos options->send_env[j + 1] = NULL;
809 1.25 christos }
810 1.25 christos options->num_send_env--;
811 1.25 christos /* NB. don't increment i */
812 1.25 christos }
813 1.32 christos if (onum_send_env != options->num_send_env) {
814 1.32 christos options->send_env = xrecallocarray(options->send_env,
815 1.32 christos onum_send_env, options->num_send_env,
816 1.32 christos sizeof(*options->send_env));
817 1.32 christos }
818 1.25 christos }
819 1.25 christos
820 1.1 christos /*
821 1.1 christos * Returns the number of the token pointed to by cp or oBadOption.
822 1.1 christos */
823 1.1 christos static OpCodes
824 1.11 christos parse_token(const char *cp, const char *filename, int linenum,
825 1.11 christos const char *ignored_unknown)
826 1.1 christos {
827 1.11 christos int i;
828 1.1 christos
829 1.1 christos for (i = 0; keywords[i].name; i++)
830 1.11 christos if (strcmp(cp, keywords[i].name) == 0)
831 1.1 christos return keywords[i].opcode;
832 1.14 christos if (ignored_unknown != NULL &&
833 1.14 christos match_pattern_list(cp, ignored_unknown, 1) == 1)
834 1.11 christos return oIgnoredUnknownOption;
835 1.1 christos error("%s: line %d: Bad configuration option: %s",
836 1.1 christos filename, linenum, cp);
837 1.1 christos return oBadOption;
838 1.1 christos }
839 1.1 christos
840 1.12 christos /* Multistate option parsing */
841 1.12 christos struct multistate {
842 1.12 christos const char *key;
843 1.12 christos int value;
844 1.12 christos };
845 1.12 christos static const struct multistate multistate_flag[] = {
846 1.12 christos { "true", 1 },
847 1.12 christos { "false", 0 },
848 1.12 christos { "yes", 1 },
849 1.12 christos { "no", 0 },
850 1.12 christos { NULL, -1 }
851 1.12 christos };
852 1.12 christos static const struct multistate multistate_yesnoask[] = {
853 1.12 christos { "true", 1 },
854 1.12 christos { "false", 0 },
855 1.12 christos { "yes", 1 },
856 1.12 christos { "no", 0 },
857 1.12 christos { "ask", 2 },
858 1.12 christos { NULL, -1 }
859 1.12 christos };
860 1.22 christos static const struct multistate multistate_strict_hostkey[] = {
861 1.22 christos { "true", SSH_STRICT_HOSTKEY_YES },
862 1.22 christos { "false", SSH_STRICT_HOSTKEY_OFF },
863 1.22 christos { "yes", SSH_STRICT_HOSTKEY_YES },
864 1.22 christos { "no", SSH_STRICT_HOSTKEY_OFF },
865 1.22 christos { "ask", SSH_STRICT_HOSTKEY_ASK },
866 1.22 christos { "off", SSH_STRICT_HOSTKEY_OFF },
867 1.22 christos { "accept-new", SSH_STRICT_HOSTKEY_NEW },
868 1.22 christos { NULL, -1 }
869 1.22 christos };
870 1.18 christos static const struct multistate multistate_yesnoaskconfirm[] = {
871 1.18 christos { "true", 1 },
872 1.18 christos { "false", 0 },
873 1.18 christos { "yes", 1 },
874 1.18 christos { "no", 0 },
875 1.18 christos { "ask", 2 },
876 1.18 christos { "confirm", 3 },
877 1.18 christos { NULL, -1 }
878 1.18 christos };
879 1.12 christos static const struct multistate multistate_addressfamily[] = {
880 1.12 christos { "inet", AF_INET },
881 1.12 christos { "inet6", AF_INET6 },
882 1.12 christos { "any", AF_UNSPEC },
883 1.12 christos { NULL, -1 }
884 1.12 christos };
885 1.12 christos static const struct multistate multistate_controlmaster[] = {
886 1.12 christos { "true", SSHCTL_MASTER_YES },
887 1.12 christos { "yes", SSHCTL_MASTER_YES },
888 1.12 christos { "false", SSHCTL_MASTER_NO },
889 1.12 christos { "no", SSHCTL_MASTER_NO },
890 1.12 christos { "auto", SSHCTL_MASTER_AUTO },
891 1.12 christos { "ask", SSHCTL_MASTER_ASK },
892 1.12 christos { "autoask", SSHCTL_MASTER_AUTO_ASK },
893 1.12 christos { NULL, -1 }
894 1.12 christos };
895 1.12 christos static const struct multistate multistate_tunnel[] = {
896 1.12 christos { "ethernet", SSH_TUNMODE_ETHERNET },
897 1.12 christos { "point-to-point", SSH_TUNMODE_POINTOPOINT },
898 1.12 christos { "true", SSH_TUNMODE_DEFAULT },
899 1.12 christos { "yes", SSH_TUNMODE_DEFAULT },
900 1.12 christos { "false", SSH_TUNMODE_NO },
901 1.12 christos { "no", SSH_TUNMODE_NO },
902 1.12 christos { NULL, -1 }
903 1.12 christos };
904 1.12 christos static const struct multistate multistate_requesttty[] = {
905 1.12 christos { "true", REQUEST_TTY_YES },
906 1.12 christos { "yes", REQUEST_TTY_YES },
907 1.12 christos { "false", REQUEST_TTY_NO },
908 1.12 christos { "no", REQUEST_TTY_NO },
909 1.12 christos { "force", REQUEST_TTY_FORCE },
910 1.12 christos { "auto", REQUEST_TTY_AUTO },
911 1.12 christos { NULL, -1 }
912 1.12 christos };
913 1.35 christos static const struct multistate multistate_sessiontype[] = {
914 1.35 christos { "none", SESSION_TYPE_NONE },
915 1.35 christos { "subsystem", SESSION_TYPE_SUBSYSTEM },
916 1.35 christos { "default", SESSION_TYPE_DEFAULT },
917 1.35 christos { NULL, -1 }
918 1.35 christos };
919 1.12 christos static const struct multistate multistate_canonicalizehostname[] = {
920 1.12 christos { "true", SSH_CANONICALISE_YES },
921 1.12 christos { "false", SSH_CANONICALISE_NO },
922 1.12 christos { "yes", SSH_CANONICALISE_YES },
923 1.12 christos { "no", SSH_CANONICALISE_NO },
924 1.12 christos { "always", SSH_CANONICALISE_ALWAYS },
925 1.12 christos { NULL, -1 }
926 1.12 christos };
927 1.29 christos static const struct multistate multistate_compression[] = {
928 1.29 christos #ifdef WITH_ZLIB
929 1.29 christos { "yes", COMP_ZLIB },
930 1.29 christos #endif
931 1.29 christos { "no", COMP_NONE },
932 1.29 christos { NULL, -1 }
933 1.29 christos };
934 1.12 christos
935 1.32 christos static int
936 1.32 christos parse_multistate_value(const char *arg, const char *filename, int linenum,
937 1.32 christos const struct multistate *multistate_ptr)
938 1.32 christos {
939 1.32 christos int i;
940 1.32 christos
941 1.33 christos if (!arg || *arg == '\0') {
942 1.33 christos error("%s line %d: missing argument.", filename, linenum);
943 1.33 christos return -1;
944 1.33 christos }
945 1.32 christos for (i = 0; multistate_ptr[i].key != NULL; i++) {
946 1.32 christos if (strcasecmp(arg, multistate_ptr[i].key) == 0)
947 1.32 christos return multistate_ptr[i].value;
948 1.32 christos }
949 1.32 christos return -1;
950 1.32 christos }
951 1.32 christos
952 1.1 christos /*
953 1.1 christos * Processes a single option line as used in the configuration files. This
954 1.1 christos * only sets those values that have not already been set.
955 1.1 christos */
956 1.1 christos int
957 1.12 christos process_config_line(Options *options, struct passwd *pw, const char *host,
958 1.13 christos const char *original_host, char *line, const char *filename,
959 1.13 christos int linenum, int *activep, int flags)
960 1.1 christos {
961 1.19 christos return process_config_line_depth(options, pw, host, original_host,
962 1.27 christos line, filename, linenum, activep, flags, NULL, 0);
963 1.19 christos }
964 1.19 christos
965 1.19 christos #define WHITESPACE " \t\r\n"
966 1.19 christos static int
967 1.19 christos process_config_line_depth(Options *options, struct passwd *pw, const char *host,
968 1.19 christos const char *original_host, char *line, const char *filename,
969 1.27 christos int linenum, int *activep, int flags, int *want_final_pass, int depth)
970 1.19 christos {
971 1.35 christos char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
972 1.33 christos char **cpptr, ***cppptr, fwdarg[256];
973 1.33 christos u_int i, *uintptr, uvalue, max_entries = 0;
974 1.19 christos int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
975 1.22 christos int remotefwd, dynamicfwd;
976 1.1 christos LogLevel *log_level_ptr;
977 1.22 christos SyslogFacility *log_facility_ptr;
978 1.11 christos long long val64;
979 1.1 christos size_t len;
980 1.12 christos struct Forward fwd;
981 1.12 christos const struct multistate *multistate_ptr;
982 1.12 christos struct allowed_cname *cname;
983 1.19 christos glob_t gl;
984 1.23 christos const char *errstr;
985 1.35 christos char **oav = NULL, **av;
986 1.35 christos int oac = 0, ac;
987 1.35 christos int ret = -1;
988 1.12 christos
989 1.12 christos if (activep == NULL) { /* We are processing a command line directive */
990 1.12 christos cmdline = 1;
991 1.12 christos activep = &cmdline;
992 1.12 christos }
993 1.1 christos
994 1.21 christos /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
995 1.14 christos if ((len = strlen(line)) == 0)
996 1.14 christos return 0;
997 1.14 christos for (len--; len > 0; len--) {
998 1.21 christos if (strchr(WHITESPACE "\f", line[len]) == NULL)
999 1.1 christos break;
1000 1.1 christos line[len] = '\0';
1001 1.1 christos }
1002 1.1 christos
1003 1.35 christos str = line;
1004 1.1 christos /* Get the keyword. (Each line is supposed to begin with a keyword). */
1005 1.35 christos if ((keyword = strdelim(&str)) == NULL)
1006 1.1 christos return 0;
1007 1.1 christos /* Ignore leading whitespace. */
1008 1.1 christos if (*keyword == '\0')
1009 1.35 christos keyword = strdelim(&str);
1010 1.1 christos if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1011 1.1 christos return 0;
1012 1.11 christos /* Match lowercase keyword */
1013 1.12 christos lowercase(keyword);
1014 1.1 christos
1015 1.35 christos /* Prepare to parse remainder of line */
1016 1.35 christos if (str != NULL)
1017 1.35 christos str += strspn(str, WHITESPACE);
1018 1.35 christos if (str == NULL || *str == '\0') {
1019 1.35 christos error("%s line %d: no argument after keyword \"%s\"",
1020 1.35 christos filename, linenum, keyword);
1021 1.35 christos return -1;
1022 1.35 christos }
1023 1.11 christos opcode = parse_token(keyword, filename, linenum,
1024 1.11 christos options->ignored_unknown);
1025 1.35 christos if (argv_split(str, &oac, &oav, 1) != 0) {
1026 1.35 christos error("%s line %d: invalid quotes", filename, linenum);
1027 1.35 christos return -1;
1028 1.35 christos }
1029 1.35 christos ac = oac;
1030 1.35 christos av = oav;
1031 1.1 christos
1032 1.1 christos switch (opcode) {
1033 1.1 christos case oBadOption:
1034 1.1 christos /* don't panic, but count bad options */
1035 1.35 christos goto out;
1036 1.22 christos case oIgnore:
1037 1.35 christos argv_consume(&ac);
1038 1.35 christos break;
1039 1.11 christos case oIgnoredUnknownOption:
1040 1.11 christos debug("%s line %d: Ignored unknown option \"%s\"",
1041 1.11 christos filename, linenum, keyword);
1042 1.35 christos argv_consume(&ac);
1043 1.35 christos break;
1044 1.1 christos case oConnectTimeout:
1045 1.1 christos intptr = &options->connection_timeout;
1046 1.1 christos parse_time:
1047 1.35 christos arg = argv_next(&ac, &av);
1048 1.33 christos if (!arg || *arg == '\0') {
1049 1.33 christos error("%s line %d: missing time value.",
1050 1.1 christos filename, linenum);
1051 1.35 christos goto out;
1052 1.33 christos }
1053 1.13 christos if (strcmp(arg, "none") == 0)
1054 1.13 christos value = -1;
1055 1.33 christos else if ((value = convtime(arg)) == -1) {
1056 1.33 christos error("%s line %d: invalid time value.",
1057 1.1 christos filename, linenum);
1058 1.35 christos goto out;
1059 1.33 christos }
1060 1.1 christos if (*activep && *intptr == -1)
1061 1.1 christos *intptr = value;
1062 1.1 christos break;
1063 1.1 christos
1064 1.1 christos case oForwardAgent:
1065 1.1 christos intptr = &options->forward_agent;
1066 1.29 christos
1067 1.35 christos arg = argv_next(&ac, &av);
1068 1.33 christos if (!arg || *arg == '\0') {
1069 1.33 christos error("%s line %d: missing argument.",
1070 1.29 christos filename, linenum);
1071 1.35 christos goto out;
1072 1.33 christos }
1073 1.29 christos
1074 1.29 christos value = -1;
1075 1.29 christos multistate_ptr = multistate_flag;
1076 1.29 christos for (i = 0; multistate_ptr[i].key != NULL; i++) {
1077 1.29 christos if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1078 1.29 christos value = multistate_ptr[i].value;
1079 1.29 christos break;
1080 1.29 christos }
1081 1.29 christos }
1082 1.29 christos if (value != -1) {
1083 1.29 christos if (*activep && *intptr == -1)
1084 1.29 christos *intptr = value;
1085 1.29 christos break;
1086 1.29 christos }
1087 1.29 christos /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1088 1.29 christos if (*activep && *intptr == -1)
1089 1.29 christos *intptr = 1;
1090 1.29 christos
1091 1.29 christos charptr = &options->forward_agent_sock_path;
1092 1.29 christos goto parse_agent_path;
1093 1.29 christos
1094 1.29 christos case oForwardX11:
1095 1.29 christos intptr = &options->forward_x11;
1096 1.12 christos parse_flag:
1097 1.12 christos multistate_ptr = multistate_flag;
1098 1.12 christos parse_multistate:
1099 1.35 christos arg = argv_next(&ac, &av);
1100 1.32 christos if ((value = parse_multistate_value(arg, filename, linenum,
1101 1.34 christos multistate_ptr)) == -1) {
1102 1.33 christos error("%s line %d: unsupported option \"%s\".",
1103 1.12 christos filename, linenum, arg);
1104 1.35 christos goto out;
1105 1.32 christos }
1106 1.1 christos if (*activep && *intptr == -1)
1107 1.1 christos *intptr = value;
1108 1.1 christos break;
1109 1.1 christos
1110 1.1 christos case oForwardX11Trusted:
1111 1.1 christos intptr = &options->forward_x11_trusted;
1112 1.1 christos goto parse_flag;
1113 1.13 christos
1114 1.4 adam case oForwardX11Timeout:
1115 1.4 adam intptr = &options->forward_x11_timeout;
1116 1.4 adam goto parse_time;
1117 1.1 christos
1118 1.1 christos case oGatewayPorts:
1119 1.12 christos intptr = &options->fwd_opts.gateway_ports;
1120 1.1 christos goto parse_flag;
1121 1.1 christos
1122 1.1 christos case oExitOnForwardFailure:
1123 1.1 christos intptr = &options->exit_on_forward_failure;
1124 1.1 christos goto parse_flag;
1125 1.1 christos
1126 1.1 christos case oPasswordAuthentication:
1127 1.1 christos intptr = &options->password_authentication;
1128 1.1 christos goto parse_flag;
1129 1.1 christos
1130 1.1 christos case oKbdInteractiveAuthentication:
1131 1.1 christos intptr = &options->kbd_interactive_authentication;
1132 1.1 christos goto parse_flag;
1133 1.1 christos
1134 1.1 christos case oKbdInteractiveDevices:
1135 1.1 christos charptr = &options->kbd_interactive_devices;
1136 1.1 christos goto parse_string;
1137 1.1 christos
1138 1.1 christos case oPubkeyAuthentication:
1139 1.1 christos intptr = &options->pubkey_authentication;
1140 1.1 christos goto parse_flag;
1141 1.1 christos
1142 1.1 christos case oHostbasedAuthentication:
1143 1.1 christos intptr = &options->hostbased_authentication;
1144 1.1 christos goto parse_flag;
1145 1.1 christos
1146 1.2 christos #if defined(KRB4) || defined(KRB5)
1147 1.2 christos case oKerberosAuthentication:
1148 1.2 christos intptr = &options->kerberos_authentication;
1149 1.2 christos goto parse_flag;
1150 1.2 christos #endif
1151 1.2 christos #if defined(AFS) || defined(KRB5)
1152 1.2 christos case oKerberosTgtPassing:
1153 1.2 christos intptr = &options->kerberos_tgt_passing;
1154 1.2 christos goto parse_flag;
1155 1.2 christos #endif
1156 1.2 christos
1157 1.1 christos case oGssAuthentication:
1158 1.1 christos intptr = &options->gss_authentication;
1159 1.1 christos goto parse_flag;
1160 1.1 christos
1161 1.2 christos #ifdef AFS
1162 1.2 christos case oAFSTokenPassing:
1163 1.2 christos intptr = &options->afs_token_passing;
1164 1.2 christos goto parse_flag;
1165 1.2 christos #endif
1166 1.2 christos
1167 1.1 christos case oGssDelegateCreds:
1168 1.1 christos intptr = &options->gss_deleg_creds;
1169 1.1 christos goto parse_flag;
1170 1.1 christos
1171 1.1 christos case oBatchMode:
1172 1.1 christos intptr = &options->batch_mode;
1173 1.1 christos goto parse_flag;
1174 1.1 christos
1175 1.1 christos case oCheckHostIP:
1176 1.1 christos intptr = &options->check_host_ip;
1177 1.1 christos goto parse_flag;
1178 1.1 christos
1179 1.2 christos case oNoneEnabled:
1180 1.2 christos intptr = &options->none_enabled;
1181 1.2 christos goto parse_flag;
1182 1.2 christos
1183 1.2 christos /* we check to see if the command comes from the */
1184 1.2 christos /* command line or not. If it does then enable it */
1185 1.2 christos /* otherwise fail. NONE should never be a default configuration */
1186 1.2 christos case oNoneSwitch:
1187 1.2 christos if(strcmp(filename,"command-line")==0)
1188 1.2 christos {
1189 1.2 christos intptr = &options->none_switch;
1190 1.2 christos goto parse_flag;
1191 1.2 christos } else {
1192 1.2 christos error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
1193 1.2 christos error("Continuing...");
1194 1.2 christos debug("NoneSwitch directive found in %.200s.", filename);
1195 1.2 christos return 0;
1196 1.2 christos }
1197 1.2 christos
1198 1.2 christos case oHPNDisabled:
1199 1.2 christos intptr = &options->hpn_disabled;
1200 1.2 christos goto parse_flag;
1201 1.2 christos
1202 1.2 christos case oHPNBufferSize:
1203 1.2 christos intptr = &options->hpn_buffer_size;
1204 1.2 christos goto parse_int;
1205 1.2 christos
1206 1.2 christos case oTcpRcvBufPoll:
1207 1.2 christos intptr = &options->tcp_rcv_buf_poll;
1208 1.2 christos goto parse_flag;
1209 1.2 christos
1210 1.1 christos case oVerifyHostKeyDNS:
1211 1.1 christos intptr = &options->verify_host_key_dns;
1212 1.12 christos multistate_ptr = multistate_yesnoask;
1213 1.12 christos goto parse_multistate;
1214 1.1 christos
1215 1.1 christos case oStrictHostKeyChecking:
1216 1.1 christos intptr = &options->strict_host_key_checking;
1217 1.22 christos multistate_ptr = multistate_strict_hostkey;
1218 1.12 christos goto parse_multistate;
1219 1.1 christos
1220 1.1 christos case oCompression:
1221 1.1 christos intptr = &options->compression;
1222 1.29 christos multistate_ptr = multistate_compression;
1223 1.29 christos goto parse_multistate;
1224 1.1 christos
1225 1.1 christos case oTCPKeepAlive:
1226 1.1 christos intptr = &options->tcp_keep_alive;
1227 1.1 christos goto parse_flag;
1228 1.1 christos
1229 1.1 christos case oNoHostAuthenticationForLocalhost:
1230 1.1 christos intptr = &options->no_host_authentication_for_localhost;
1231 1.1 christos goto parse_flag;
1232 1.1 christos
1233 1.1 christos case oNumberOfPasswordPrompts:
1234 1.1 christos intptr = &options->number_of_password_prompts;
1235 1.1 christos goto parse_int;
1236 1.1 christos
1237 1.1 christos case oRekeyLimit:
1238 1.35 christos arg = argv_next(&ac, &av);
1239 1.33 christos if (!arg || *arg == '\0') {
1240 1.33 christos error("%.200s line %d: Missing argument.", filename,
1241 1.11 christos linenum);
1242 1.35 christos goto out;
1243 1.33 christos }
1244 1.11 christos if (strcmp(arg, "default") == 0) {
1245 1.11 christos val64 = 0;
1246 1.11 christos } else {
1247 1.33 christos if (scan_scaled(arg, &val64) == -1) {
1248 1.33 christos error("%.200s line %d: Bad number '%s': %s",
1249 1.11 christos filename, linenum, arg, strerror(errno));
1250 1.35 christos goto out;
1251 1.33 christos }
1252 1.33 christos if (val64 != 0 && val64 < 16) {
1253 1.33 christos error("%.200s line %d: RekeyLimit too small",
1254 1.11 christos filename, linenum);
1255 1.35 christos goto out;
1256 1.33 christos }
1257 1.1 christos }
1258 1.1 christos if (*activep && options->rekey_limit == -1)
1259 1.18 christos options->rekey_limit = val64;
1260 1.35 christos if (ac != 0) { /* optional rekey interval present */
1261 1.35 christos if (strcmp(av[0], "none") == 0) {
1262 1.35 christos (void)argv_next(&ac, &av); /* discard */
1263 1.11 christos break;
1264 1.11 christos }
1265 1.11 christos intptr = &options->rekey_interval;
1266 1.11 christos goto parse_time;
1267 1.11 christos }
1268 1.1 christos break;
1269 1.1 christos
1270 1.1 christos case oIdentityFile:
1271 1.35 christos arg = argv_next(&ac, &av);
1272 1.33 christos if (!arg || *arg == '\0') {
1273 1.33 christos error("%.200s line %d: Missing argument.",
1274 1.33 christos filename, linenum);
1275 1.35 christos goto out;
1276 1.33 christos }
1277 1.1 christos if (*activep) {
1278 1.1 christos intptr = &options->num_identity_files;
1279 1.33 christos if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1280 1.33 christos error("%.200s line %d: Too many identity files "
1281 1.33 christos "specified (max %d).", filename, linenum,
1282 1.33 christos SSH_MAX_IDENTITY_FILES);
1283 1.35 christos goto out;
1284 1.33 christos }
1285 1.13 christos add_identity_file(options, NULL,
1286 1.13 christos arg, flags & SSHCONF_USERCONF);
1287 1.1 christos }
1288 1.1 christos break;
1289 1.1 christos
1290 1.18 christos case oCertificateFile:
1291 1.35 christos arg = argv_next(&ac, &av);
1292 1.33 christos if (!arg || *arg == '\0') {
1293 1.33 christos error("%.200s line %d: Missing argument.",
1294 1.18 christos filename, linenum);
1295 1.35 christos goto out;
1296 1.33 christos }
1297 1.18 christos if (*activep) {
1298 1.18 christos intptr = &options->num_certificate_files;
1299 1.18 christos if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1300 1.33 christos error("%.200s line %d: Too many certificate "
1301 1.18 christos "files specified (max %d).",
1302 1.18 christos filename, linenum,
1303 1.18 christos SSH_MAX_CERTIFICATE_FILES);
1304 1.35 christos goto out;
1305 1.18 christos }
1306 1.18 christos add_certificate_file(options, arg,
1307 1.18 christos flags & SSHCONF_USERCONF);
1308 1.18 christos }
1309 1.18 christos break;
1310 1.18 christos
1311 1.1 christos case oXAuthLocation:
1312 1.1 christos charptr=&options->xauth_location;
1313 1.1 christos goto parse_string;
1314 1.1 christos
1315 1.1 christos case oUser:
1316 1.1 christos charptr = &options->user;
1317 1.1 christos parse_string:
1318 1.35 christos arg = argv_next(&ac, &av);
1319 1.33 christos if (!arg || *arg == '\0') {
1320 1.33 christos error("%.200s line %d: Missing argument.",
1321 1.6 christos filename, linenum);
1322 1.35 christos goto out;
1323 1.33 christos }
1324 1.1 christos if (*activep && *charptr == NULL)
1325 1.1 christos *charptr = xstrdup(arg);
1326 1.1 christos break;
1327 1.1 christos
1328 1.1 christos case oGlobalKnownHostsFile:
1329 1.6 christos cpptr = (char **)&options->system_hostfiles;
1330 1.6 christos uintptr = &options->num_system_hostfiles;
1331 1.6 christos max_entries = SSH_MAX_HOSTS_FILES;
1332 1.6 christos parse_char_array:
1333 1.35 christos i = 0;
1334 1.35 christos value = *uintptr == 0; /* was array empty when we started? */
1335 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1336 1.35 christos if (*arg == '\0') {
1337 1.35 christos error("%s line %d: keyword %s empty argument",
1338 1.35 christos filename, linenum, keyword);
1339 1.35 christos goto out;
1340 1.35 christos }
1341 1.35 christos /* Allow "none" only in first position */
1342 1.35 christos if (strcasecmp(arg, "none") == 0) {
1343 1.35 christos if (i > 0 || ac > 0) {
1344 1.35 christos error("%s line %d: keyword %s \"none\" "
1345 1.35 christos "argument must appear alone.",
1346 1.35 christos filename, linenum, keyword);
1347 1.35 christos goto out;
1348 1.35 christos }
1349 1.35 christos }
1350 1.35 christos i++;
1351 1.35 christos if (*activep && value) {
1352 1.33 christos if ((*uintptr) >= max_entries) {
1353 1.35 christos error("%s line %d: too many %s "
1354 1.35 christos "entries.", filename, linenum,
1355 1.35 christos keyword);
1356 1.35 christos goto out;
1357 1.33 christos }
1358 1.6 christos cpptr[(*uintptr)++] = xstrdup(arg);
1359 1.6 christos }
1360 1.6 christos }
1361 1.35 christos break;
1362 1.1 christos
1363 1.1 christos case oUserKnownHostsFile:
1364 1.6 christos cpptr = (char **)&options->user_hostfiles;
1365 1.6 christos uintptr = &options->num_user_hostfiles;
1366 1.6 christos max_entries = SSH_MAX_HOSTS_FILES;
1367 1.6 christos goto parse_char_array;
1368 1.1 christos
1369 1.28 christos case oHostname:
1370 1.1 christos charptr = &options->hostname;
1371 1.1 christos goto parse_string;
1372 1.1 christos
1373 1.1 christos case oHostKeyAlias:
1374 1.1 christos charptr = &options->host_key_alias;
1375 1.1 christos goto parse_string;
1376 1.1 christos
1377 1.1 christos case oPreferredAuthentications:
1378 1.1 christos charptr = &options->preferred_authentications;
1379 1.1 christos goto parse_string;
1380 1.1 christos
1381 1.1 christos case oBindAddress:
1382 1.1 christos charptr = &options->bind_address;
1383 1.1 christos goto parse_string;
1384 1.1 christos
1385 1.23 christos case oBindInterface:
1386 1.23 christos charptr = &options->bind_interface;
1387 1.23 christos goto parse_string;
1388 1.23 christos
1389 1.4 adam case oPKCS11Provider:
1390 1.4 adam charptr = &options->pkcs11_provider;
1391 1.1 christos goto parse_string;
1392 1.1 christos
1393 1.29 christos case oSecurityKeyProvider:
1394 1.29 christos charptr = &options->sk_provider;
1395 1.29 christos goto parse_string;
1396 1.29 christos
1397 1.33 christos case oKnownHostsCommand:
1398 1.33 christos charptr = &options->known_hosts_command;
1399 1.33 christos goto parse_command;
1400 1.33 christos
1401 1.1 christos case oProxyCommand:
1402 1.1 christos charptr = &options->proxy_command;
1403 1.19 christos /* Ignore ProxyCommand if ProxyJump already specified */
1404 1.19 christos if (options->jump_host != NULL)
1405 1.19 christos charptr = &options->jump_host; /* Skip below */
1406 1.1 christos parse_command:
1407 1.35 christos if (str == NULL) {
1408 1.33 christos error("%.200s line %d: Missing argument.",
1409 1.33 christos filename, linenum);
1410 1.35 christos goto out;
1411 1.33 christos }
1412 1.35 christos len = strspn(str, WHITESPACE "=");
1413 1.1 christos if (*activep && *charptr == NULL)
1414 1.35 christos *charptr = xstrdup(str + len);
1415 1.35 christos argv_consume(&ac);
1416 1.35 christos break;
1417 1.1 christos
1418 1.19 christos case oProxyJump:
1419 1.35 christos if (str == NULL) {
1420 1.33 christos error("%.200s line %d: Missing argument.",
1421 1.19 christos filename, linenum);
1422 1.35 christos goto out;
1423 1.19 christos }
1424 1.35 christos len = strspn(str, WHITESPACE "=");
1425 1.35 christos /* XXX use argv? */
1426 1.35 christos if (parse_jump(str + len, options, *activep) == -1) {
1427 1.33 christos error("%.200s line %d: Invalid ProxyJump \"%s\"",
1428 1.35 christos filename, linenum, str + len);
1429 1.35 christos goto out;
1430 1.19 christos }
1431 1.35 christos argv_consume(&ac);
1432 1.35 christos break;
1433 1.19 christos
1434 1.1 christos case oPort:
1435 1.35 christos arg = argv_next(&ac, &av);
1436 1.33 christos if (!arg || *arg == '\0') {
1437 1.33 christos error("%.200s line %d: Missing argument.",
1438 1.27 christos filename, linenum);
1439 1.35 christos goto out;
1440 1.33 christos }
1441 1.27 christos value = a2port(arg);
1442 1.33 christos if (value <= 0) {
1443 1.33 christos error("%.200s line %d: Bad port '%s'.",
1444 1.27 christos filename, linenum, arg);
1445 1.35 christos goto out;
1446 1.33 christos }
1447 1.27 christos if (*activep && options->port == -1)
1448 1.27 christos options->port = value;
1449 1.27 christos break;
1450 1.27 christos
1451 1.27 christos case oConnectionAttempts:
1452 1.27 christos intptr = &options->connection_attempts;
1453 1.1 christos parse_int:
1454 1.35 christos arg = argv_next(&ac, &av);
1455 1.33 christos if ((errstr = atoi_err(arg, &value)) != NULL) {
1456 1.33 christos error("%s line %d: integer value %s.",
1457 1.23 christos filename, linenum, errstr);
1458 1.35 christos goto out;
1459 1.33 christos }
1460 1.1 christos if (*activep && *intptr == -1)
1461 1.1 christos *intptr = value;
1462 1.1 christos break;
1463 1.1 christos
1464 1.2 christos case oTcpRcvBuf:
1465 1.2 christos intptr = &options->tcp_rcv_buf;
1466 1.2 christos goto parse_int;
1467 1.2 christos
1468 1.1 christos case oCiphers:
1469 1.35 christos arg = argv_next(&ac, &av);
1470 1.33 christos if (!arg || *arg == '\0') {
1471 1.33 christos error("%.200s line %d: Missing argument.",
1472 1.33 christos filename, linenum);
1473 1.35 christos goto out;
1474 1.33 christos }
1475 1.28 christos if (*arg != '-' &&
1476 1.33 christos !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1477 1.33 christos error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1478 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1479 1.35 christos goto out;
1480 1.33 christos }
1481 1.1 christos if (*activep && options->ciphers == NULL)
1482 1.1 christos options->ciphers = xstrdup(arg);
1483 1.1 christos break;
1484 1.1 christos
1485 1.1 christos case oMacs:
1486 1.35 christos arg = argv_next(&ac, &av);
1487 1.33 christos if (!arg || *arg == '\0') {
1488 1.33 christos error("%.200s line %d: Missing argument.",
1489 1.33 christos filename, linenum);
1490 1.35 christos goto out;
1491 1.33 christos }
1492 1.28 christos if (*arg != '-' &&
1493 1.33 christos !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1494 1.33 christos error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1495 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1496 1.35 christos goto out;
1497 1.33 christos }
1498 1.1 christos if (*activep && options->macs == NULL)
1499 1.1 christos options->macs = xstrdup(arg);
1500 1.1 christos break;
1501 1.1 christos
1502 1.5 christos case oKexAlgorithms:
1503 1.35 christos arg = argv_next(&ac, &av);
1504 1.33 christos if (!arg || *arg == '\0') {
1505 1.33 christos error("%.200s line %d: Missing argument.",
1506 1.5 christos filename, linenum);
1507 1.35 christos goto out;
1508 1.33 christos }
1509 1.21 christos if (*arg != '-' &&
1510 1.28 christos !kex_names_valid(*arg == '+' || *arg == '^' ?
1511 1.33 christos arg + 1 : arg)) {
1512 1.33 christos error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1513 1.5 christos filename, linenum, arg ? arg : "<NONE>");
1514 1.35 christos goto out;
1515 1.33 christos }
1516 1.5 christos if (*activep && options->kex_algorithms == NULL)
1517 1.5 christos options->kex_algorithms = xstrdup(arg);
1518 1.5 christos break;
1519 1.5 christos
1520 1.1 christos case oHostKeyAlgorithms:
1521 1.16 christos charptr = &options->hostkeyalgorithms;
1522 1.33 christos parse_pubkey_algos:
1523 1.35 christos arg = argv_next(&ac, &av);
1524 1.33 christos if (!arg || *arg == '\0') {
1525 1.33 christos error("%.200s line %d: Missing argument.",
1526 1.16 christos filename, linenum);
1527 1.35 christos goto out;
1528 1.33 christos }
1529 1.21 christos if (*arg != '-' &&
1530 1.28 christos !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1531 1.33 christos arg + 1 : arg, 1)) {
1532 1.33 christos error("%s line %d: Bad key types '%s'.",
1533 1.33 christos filename, linenum, arg ? arg : "<NONE>");
1534 1.35 christos goto out;
1535 1.33 christos }
1536 1.16 christos if (*activep && *charptr == NULL)
1537 1.16 christos *charptr = xstrdup(arg);
1538 1.1 christos break;
1539 1.1 christos
1540 1.27 christos case oCASignatureAlgorithms:
1541 1.27 christos charptr = &options->ca_sign_algorithms;
1542 1.33 christos goto parse_pubkey_algos;
1543 1.27 christos
1544 1.1 christos case oLogLevel:
1545 1.1 christos log_level_ptr = &options->log_level;
1546 1.35 christos arg = argv_next(&ac, &av);
1547 1.1 christos value = log_level_number(arg);
1548 1.33 christos if (value == SYSLOG_LEVEL_NOT_SET) {
1549 1.33 christos error("%.200s line %d: unsupported log level '%s'",
1550 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1551 1.35 christos goto out;
1552 1.33 christos }
1553 1.1 christos if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1554 1.1 christos *log_level_ptr = (LogLevel) value;
1555 1.1 christos break;
1556 1.1 christos
1557 1.22 christos case oLogFacility:
1558 1.22 christos log_facility_ptr = &options->log_facility;
1559 1.35 christos arg = argv_next(&ac, &av);
1560 1.22 christos value = log_facility_number(arg);
1561 1.33 christos if (value == SYSLOG_FACILITY_NOT_SET) {
1562 1.33 christos error("%.200s line %d: unsupported log facility '%s'",
1563 1.22 christos filename, linenum, arg ? arg : "<NONE>");
1564 1.35 christos goto out;
1565 1.33 christos }
1566 1.22 christos if (*log_facility_ptr == -1)
1567 1.22 christos *log_facility_ptr = (SyslogFacility) value;
1568 1.22 christos break;
1569 1.22 christos
1570 1.33 christos case oLogVerbose:
1571 1.33 christos cppptr = &options->log_verbose;
1572 1.33 christos uintptr = &options->num_log_verbose;
1573 1.35 christos i = 0;
1574 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1575 1.35 christos if (*arg == '\0') {
1576 1.35 christos error("%s line %d: keyword %s empty argument",
1577 1.35 christos filename, linenum, keyword);
1578 1.35 christos goto out;
1579 1.35 christos }
1580 1.35 christos /* Allow "none" only in first position */
1581 1.35 christos if (strcasecmp(arg, "none") == 0) {
1582 1.35 christos if (i > 0 || ac > 0) {
1583 1.35 christos error("%s line %d: keyword %s \"none\" "
1584 1.35 christos "argument must appear alone.",
1585 1.35 christos filename, linenum, keyword);
1586 1.35 christos goto out;
1587 1.35 christos }
1588 1.35 christos }
1589 1.35 christos i++;
1590 1.35 christos if (*activep && *uintptr == 0) {
1591 1.33 christos *cppptr = xrecallocarray(*cppptr, *uintptr,
1592 1.33 christos *uintptr + 1, sizeof(**cppptr));
1593 1.33 christos (*cppptr)[(*uintptr)++] = xstrdup(arg);
1594 1.33 christos }
1595 1.33 christos }
1596 1.35 christos break;
1597 1.33 christos
1598 1.1 christos case oLocalForward:
1599 1.1 christos case oRemoteForward:
1600 1.1 christos case oDynamicForward:
1601 1.35 christos arg = argv_next(&ac, &av);
1602 1.33 christos if (!arg || *arg == '\0') {
1603 1.33 christos error("%.200s line %d: Missing argument.",
1604 1.1 christos filename, linenum);
1605 1.35 christos goto out;
1606 1.33 christos }
1607 1.1 christos
1608 1.22 christos remotefwd = (opcode == oRemoteForward);
1609 1.22 christos dynamicfwd = (opcode == oDynamicForward);
1610 1.22 christos
1611 1.22 christos if (!dynamicfwd) {
1612 1.35 christos arg2 = argv_next(&ac, &av);
1613 1.22 christos if (arg2 == NULL || *arg2 == '\0') {
1614 1.22 christos if (remotefwd)
1615 1.22 christos dynamicfwd = 1;
1616 1.33 christos else {
1617 1.33 christos error("%.200s line %d: Missing target "
1618 1.22 christos "argument.", filename, linenum);
1619 1.35 christos goto out;
1620 1.33 christos }
1621 1.22 christos } else {
1622 1.22 christos /* construct a string for parse_forward */
1623 1.22 christos snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1624 1.22 christos arg2);
1625 1.22 christos }
1626 1.22 christos }
1627 1.22 christos if (dynamicfwd)
1628 1.1 christos strlcpy(fwdarg, arg, sizeof(fwdarg));
1629 1.1 christos
1630 1.33 christos if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1631 1.33 christos error("%.200s line %d: Bad forwarding specification.",
1632 1.1 christos filename, linenum);
1633 1.35 christos goto out;
1634 1.33 christos }
1635 1.1 christos
1636 1.1 christos if (*activep) {
1637 1.22 christos if (remotefwd) {
1638 1.22 christos add_remote_forward(options, &fwd);
1639 1.22 christos } else {
1640 1.1 christos add_local_forward(options, &fwd);
1641 1.22 christos }
1642 1.1 christos }
1643 1.1 christos break;
1644 1.1 christos
1645 1.33 christos case oPermitRemoteOpen:
1646 1.33 christos uintptr = &options->num_permitted_remote_opens;
1647 1.33 christos cppptr = &options->permitted_remote_opens;
1648 1.35 christos arg = argv_next(&ac, &av);
1649 1.33 christos if (!arg || *arg == '\0')
1650 1.33 christos fatal("%s line %d: missing %s specification",
1651 1.33 christos filename, linenum, lookup_opcode_name(opcode));
1652 1.33 christos uvalue = *uintptr; /* modified later */
1653 1.33 christos if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
1654 1.33 christos if (*activep && uvalue == 0) {
1655 1.33 christos *uintptr = 1;
1656 1.33 christos *cppptr = xcalloc(1, sizeof(**cppptr));
1657 1.33 christos (*cppptr)[0] = xstrdup(arg);
1658 1.33 christos }
1659 1.33 christos break;
1660 1.33 christos }
1661 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1662 1.33 christos arg2 = xstrdup(arg);
1663 1.33 christos ch = '\0';
1664 1.33 christos p = hpdelim2(&arg, &ch);
1665 1.33 christos if (p == NULL || ch == '/') {
1666 1.33 christos fatal("%s line %d: missing host in %s",
1667 1.33 christos filename, linenum,
1668 1.33 christos lookup_opcode_name(opcode));
1669 1.33 christos }
1670 1.33 christos p = cleanhostname(p);
1671 1.33 christos /*
1672 1.33 christos * don't want to use permitopen_port to avoid
1673 1.33 christos * dependency on channels.[ch] here.
1674 1.33 christos */
1675 1.33 christos if (arg == NULL ||
1676 1.33 christos (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
1677 1.33 christos fatal("%s line %d: bad port number in %s",
1678 1.33 christos filename, linenum,
1679 1.33 christos lookup_opcode_name(opcode));
1680 1.33 christos }
1681 1.33 christos if (*activep && uvalue == 0) {
1682 1.33 christos opt_array_append(filename, linenum,
1683 1.33 christos lookup_opcode_name(opcode),
1684 1.33 christos cppptr, uintptr, arg2);
1685 1.33 christos }
1686 1.33 christos free(arg2);
1687 1.33 christos }
1688 1.33 christos break;
1689 1.33 christos
1690 1.1 christos case oClearAllForwardings:
1691 1.1 christos intptr = &options->clear_forwardings;
1692 1.1 christos goto parse_flag;
1693 1.1 christos
1694 1.1 christos case oHost:
1695 1.33 christos if (cmdline) {
1696 1.33 christos error("Host directive not supported as a command-line "
1697 1.12 christos "option");
1698 1.35 christos goto out;
1699 1.33 christos }
1700 1.1 christos *activep = 0;
1701 1.6 christos arg2 = NULL;
1702 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1703 1.35 christos if (*arg == '\0') {
1704 1.35 christos error("%s line %d: keyword %s empty argument",
1705 1.35 christos filename, linenum, keyword);
1706 1.35 christos goto out;
1707 1.35 christos }
1708 1.35 christos if ((flags & SSHCONF_NEVERMATCH) != 0) {
1709 1.35 christos argv_consume(&ac);
1710 1.19 christos break;
1711 1.35 christos }
1712 1.6 christos negated = *arg == '!';
1713 1.6 christos if (negated)
1714 1.6 christos arg++;
1715 1.1 christos if (match_pattern(host, arg)) {
1716 1.6 christos if (negated) {
1717 1.6 christos debug("%.200s line %d: Skipping Host "
1718 1.6 christos "block because of negated match "
1719 1.6 christos "for %.100s", filename, linenum,
1720 1.6 christos arg);
1721 1.6 christos *activep = 0;
1722 1.35 christos argv_consume(&ac);
1723 1.6 christos break;
1724 1.6 christos }
1725 1.6 christos if (!*activep)
1726 1.6 christos arg2 = arg; /* logged below */
1727 1.1 christos *activep = 1;
1728 1.1 christos }
1729 1.6 christos }
1730 1.6 christos if (*activep)
1731 1.6 christos debug("%.200s line %d: Applying options for %.100s",
1732 1.6 christos filename, linenum, arg2);
1733 1.35 christos break;
1734 1.1 christos
1735 1.12 christos case oMatch:
1736 1.33 christos if (cmdline) {
1737 1.33 christos error("Host directive not supported as a command-line "
1738 1.12 christos "option");
1739 1.35 christos goto out;
1740 1.33 christos }
1741 1.35 christos value = match_cfg_line(options, &str, pw, host, original_host,
1742 1.27 christos flags & SSHCONF_FINAL, want_final_pass,
1743 1.27 christos filename, linenum);
1744 1.33 christos if (value < 0) {
1745 1.33 christos error("%.200s line %d: Bad Match condition", filename,
1746 1.12 christos linenum);
1747 1.35 christos goto out;
1748 1.33 christos }
1749 1.19 christos *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1750 1.35 christos /*
1751 1.35 christos * If match_cfg_line() didn't consume all its arguments then
1752 1.35 christos * arrange for the extra arguments check below to fail.
1753 1.35 christos */
1754 1.35 christos
1755 1.35 christos if (str == NULL || *str == '\0')
1756 1.35 christos argv_consume(&ac);
1757 1.12 christos break;
1758 1.12 christos
1759 1.1 christos case oEscapeChar:
1760 1.1 christos intptr = &options->escape_char;
1761 1.35 christos arg = argv_next(&ac, &av);
1762 1.33 christos if (!arg || *arg == '\0') {
1763 1.33 christos error("%.200s line %d: Missing argument.",
1764 1.33 christos filename, linenum);
1765 1.35 christos goto out;
1766 1.33 christos }
1767 1.14 christos if (strcmp(arg, "none") == 0)
1768 1.14 christos value = SSH_ESCAPECHAR_NONE;
1769 1.14 christos else if (arg[1] == '\0')
1770 1.14 christos value = (u_char) arg[0];
1771 1.14 christos else if (arg[0] == '^' && arg[2] == 0 &&
1772 1.1 christos (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1773 1.1 christos value = (u_char) arg[1] & 31;
1774 1.1 christos else {
1775 1.33 christos error("%.200s line %d: Bad escape character.",
1776 1.1 christos filename, linenum);
1777 1.35 christos goto out;
1778 1.1 christos }
1779 1.1 christos if (*activep && *intptr == -1)
1780 1.1 christos *intptr = value;
1781 1.1 christos break;
1782 1.1 christos
1783 1.1 christos case oAddressFamily:
1784 1.1 christos intptr = &options->address_family;
1785 1.12 christos multistate_ptr = multistate_addressfamily;
1786 1.12 christos goto parse_multistate;
1787 1.1 christos
1788 1.1 christos case oEnableSSHKeysign:
1789 1.1 christos intptr = &options->enable_ssh_keysign;
1790 1.1 christos goto parse_flag;
1791 1.1 christos
1792 1.1 christos case oIdentitiesOnly:
1793 1.1 christos intptr = &options->identities_only;
1794 1.1 christos goto parse_flag;
1795 1.1 christos
1796 1.1 christos case oServerAliveInterval:
1797 1.1 christos intptr = &options->server_alive_interval;
1798 1.1 christos goto parse_time;
1799 1.1 christos
1800 1.1 christos case oServerAliveCountMax:
1801 1.1 christos intptr = &options->server_alive_count_max;
1802 1.1 christos goto parse_int;
1803 1.1 christos
1804 1.1 christos case oSendEnv:
1805 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1806 1.35 christos if (*arg == '\0' || strchr(arg, '=') != NULL) {
1807 1.33 christos error("%s line %d: Invalid environment name.",
1808 1.1 christos filename, linenum);
1809 1.35 christos goto out;
1810 1.33 christos }
1811 1.1 christos if (!*activep)
1812 1.1 christos continue;
1813 1.25 christos if (*arg == '-') {
1814 1.25 christos /* Removing an env var */
1815 1.25 christos rm_env(options, arg, filename, linenum);
1816 1.25 christos continue;
1817 1.25 christos } else {
1818 1.25 christos /* Adding an env var */
1819 1.33 christos if (options->num_send_env >= INT_MAX) {
1820 1.33 christos error("%s line %d: too many send env.",
1821 1.25 christos filename, linenum);
1822 1.35 christos goto out;
1823 1.33 christos }
1824 1.25 christos options->send_env = xrecallocarray(
1825 1.25 christos options->send_env, options->num_send_env,
1826 1.25 christos options->num_send_env + 1,
1827 1.25 christos sizeof(*options->send_env));
1828 1.25 christos options->send_env[options->num_send_env++] =
1829 1.25 christos xstrdup(arg);
1830 1.25 christos }
1831 1.25 christos }
1832 1.25 christos break;
1833 1.25 christos
1834 1.25 christos case oSetEnv:
1835 1.25 christos value = options->num_setenv;
1836 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1837 1.33 christos if (strchr(arg, '=') == NULL) {
1838 1.33 christos error("%s line %d: Invalid SetEnv.",
1839 1.25 christos filename, linenum);
1840 1.35 christos goto out;
1841 1.33 christos }
1842 1.25 christos if (!*activep || value != 0)
1843 1.25 christos continue;
1844 1.25 christos /* Adding a setenv var */
1845 1.33 christos if (options->num_setenv >= INT_MAX) {
1846 1.33 christos error("%s line %d: too many SetEnv.",
1847 1.1 christos filename, linenum);
1848 1.35 christos goto out;
1849 1.33 christos }
1850 1.25 christos options->setenv = xrecallocarray(
1851 1.25 christos options->setenv, options->num_setenv,
1852 1.25 christos options->num_setenv + 1, sizeof(*options->setenv));
1853 1.25 christos options->setenv[options->num_setenv++] = xstrdup(arg);
1854 1.1 christos }
1855 1.1 christos break;
1856 1.1 christos
1857 1.1 christos case oControlPath:
1858 1.1 christos charptr = &options->control_path;
1859 1.1 christos goto parse_string;
1860 1.1 christos
1861 1.1 christos case oControlMaster:
1862 1.1 christos intptr = &options->control_master;
1863 1.12 christos multistate_ptr = multistate_controlmaster;
1864 1.12 christos goto parse_multistate;
1865 1.1 christos
1866 1.4 adam case oControlPersist:
1867 1.4 adam /* no/false/yes/true, or a time spec */
1868 1.4 adam intptr = &options->control_persist;
1869 1.35 christos arg = argv_next(&ac, &av);
1870 1.33 christos if (!arg || *arg == '\0') {
1871 1.33 christos error("%.200s line %d: Missing ControlPersist"
1872 1.4 adam " argument.", filename, linenum);
1873 1.35 christos goto out;
1874 1.33 christos }
1875 1.4 adam value = 0;
1876 1.4 adam value2 = 0; /* timeout */
1877 1.4 adam if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1878 1.4 adam value = 0;
1879 1.4 adam else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1880 1.4 adam value = 1;
1881 1.4 adam else if ((value2 = convtime(arg)) >= 0)
1882 1.4 adam value = 1;
1883 1.33 christos else {
1884 1.33 christos error("%.200s line %d: Bad ControlPersist argument.",
1885 1.4 adam filename, linenum);
1886 1.35 christos goto out;
1887 1.33 christos }
1888 1.4 adam if (*activep && *intptr == -1) {
1889 1.4 adam *intptr = value;
1890 1.4 adam options->control_persist_timeout = value2;
1891 1.4 adam }
1892 1.4 adam break;
1893 1.4 adam
1894 1.1 christos case oHashKnownHosts:
1895 1.1 christos intptr = &options->hash_known_hosts;
1896 1.1 christos goto parse_flag;
1897 1.1 christos
1898 1.1 christos case oTunnel:
1899 1.1 christos intptr = &options->tun_open;
1900 1.12 christos multistate_ptr = multistate_tunnel;
1901 1.12 christos goto parse_multistate;
1902 1.1 christos
1903 1.1 christos case oTunnelDevice:
1904 1.35 christos arg = argv_next(&ac, &av);
1905 1.33 christos if (!arg || *arg == '\0') {
1906 1.33 christos error("%.200s line %d: Missing argument.",
1907 1.33 christos filename, linenum);
1908 1.35 christos goto out;
1909 1.33 christos }
1910 1.1 christos value = a2tun(arg, &value2);
1911 1.33 christos if (value == SSH_TUNID_ERR) {
1912 1.33 christos error("%.200s line %d: Bad tun device.",
1913 1.33 christos filename, linenum);
1914 1.35 christos goto out;
1915 1.33 christos }
1916 1.35 christos if (*activep && options->tun_local == -1) {
1917 1.1 christos options->tun_local = value;
1918 1.1 christos options->tun_remote = value2;
1919 1.1 christos }
1920 1.1 christos break;
1921 1.1 christos
1922 1.1 christos case oLocalCommand:
1923 1.1 christos charptr = &options->local_command;
1924 1.1 christos goto parse_command;
1925 1.1 christos
1926 1.1 christos case oPermitLocalCommand:
1927 1.1 christos intptr = &options->permit_local_command;
1928 1.1 christos goto parse_flag;
1929 1.1 christos
1930 1.22 christos case oRemoteCommand:
1931 1.22 christos charptr = &options->remote_command;
1932 1.22 christos goto parse_command;
1933 1.22 christos
1934 1.1 christos case oVisualHostKey:
1935 1.1 christos intptr = &options->visual_host_key;
1936 1.1 christos goto parse_flag;
1937 1.1 christos
1938 1.19 christos case oInclude:
1939 1.33 christos if (cmdline) {
1940 1.33 christos error("Include directive not supported as a "
1941 1.19 christos "command-line option");
1942 1.35 christos goto out;
1943 1.33 christos }
1944 1.19 christos value = 0;
1945 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
1946 1.35 christos if (*arg == '\0') {
1947 1.35 christos error("%s line %d: keyword %s empty argument",
1948 1.35 christos filename, linenum, keyword);
1949 1.35 christos goto out;
1950 1.35 christos }
1951 1.19 christos /*
1952 1.19 christos * Ensure all paths are anchored. User configuration
1953 1.19 christos * files may begin with '~/' but system configurations
1954 1.19 christos * must not. If the path is relative, then treat it
1955 1.19 christos * as living in ~/.ssh for user configurations or
1956 1.19 christos * /etc/ssh for system ones.
1957 1.19 christos */
1958 1.33 christos if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1959 1.33 christos error("%.200s line %d: bad include path %s.",
1960 1.19 christos filename, linenum, arg);
1961 1.35 christos goto out;
1962 1.33 christos }
1963 1.27 christos if (!path_absolute(arg) && *arg != '~') {
1964 1.19 christos xasprintf(&arg2, "%s/%s",
1965 1.19 christos (flags & SSHCONF_USERCONF) ?
1966 1.19 christos "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1967 1.19 christos } else
1968 1.19 christos arg2 = xstrdup(arg);
1969 1.19 christos memset(&gl, 0, sizeof(gl));
1970 1.19 christos r = glob(arg2, GLOB_TILDE | GLOB_LIMIT, NULL, &gl);
1971 1.19 christos if (r == GLOB_NOMATCH) {
1972 1.19 christos debug("%.200s line %d: include %s matched no "
1973 1.19 christos "files",filename, linenum, arg2);
1974 1.21 christos free(arg2);
1975 1.19 christos continue;
1976 1.33 christos } else if (r != 0) {
1977 1.33 christos error("%.200s line %d: glob failed for %s.",
1978 1.19 christos filename, linenum, arg2);
1979 1.35 christos goto out;
1980 1.33 christos }
1981 1.19 christos free(arg2);
1982 1.19 christos oactive = *activep;
1983 1.29 christos for (i = 0; i < gl.gl_pathc; i++) {
1984 1.19 christos debug3("%.200s line %d: Including file %s "
1985 1.19 christos "depth %d%s", filename, linenum,
1986 1.19 christos gl.gl_pathv[i], depth,
1987 1.19 christos oactive ? "" : " (parse only)");
1988 1.19 christos r = read_config_file_depth(gl.gl_pathv[i],
1989 1.19 christos pw, host, original_host, options,
1990 1.19 christos flags | SSHCONF_CHECKPERM |
1991 1.19 christos (oactive ? 0 : SSHCONF_NEVERMATCH),
1992 1.27 christos activep, want_final_pass, depth + 1);
1993 1.21 christos if (r != 1 && errno != ENOENT) {
1994 1.33 christos error("Can't open user config file "
1995 1.21 christos "%.100s: %.100s", gl.gl_pathv[i],
1996 1.21 christos strerror(errno));
1997 1.33 christos globfree(&gl);
1998 1.35 christos goto out;
1999 1.21 christos }
2000 1.19 christos /*
2001 1.19 christos * don't let Match in includes clobber the
2002 1.19 christos * containing file's Match state.
2003 1.19 christos */
2004 1.19 christos *activep = oactive;
2005 1.19 christos if (r != 1)
2006 1.19 christos value = -1;
2007 1.19 christos }
2008 1.19 christos globfree(&gl);
2009 1.19 christos }
2010 1.19 christos if (value != 0)
2011 1.35 christos ret = value;
2012 1.19 christos break;
2013 1.19 christos
2014 1.5 christos case oIPQoS:
2015 1.35 christos arg = argv_next(&ac, &av);
2016 1.33 christos if ((value = parse_ipqos(arg)) == -1) {
2017 1.33 christos error("%s line %d: Bad IPQoS value: %s",
2018 1.5 christos filename, linenum, arg);
2019 1.35 christos goto out;
2020 1.33 christos }
2021 1.35 christos arg = argv_next(&ac, &av);
2022 1.5 christos if (arg == NULL)
2023 1.5 christos value2 = value;
2024 1.33 christos else if ((value2 = parse_ipqos(arg)) == -1) {
2025 1.33 christos error("%s line %d: Bad IPQoS value: %s",
2026 1.5 christos filename, linenum, arg);
2027 1.35 christos goto out;
2028 1.33 christos }
2029 1.35 christos if (*activep && options->ip_qos_interactive == -1) {
2030 1.5 christos options->ip_qos_interactive = value;
2031 1.5 christos options->ip_qos_bulk = value2;
2032 1.5 christos }
2033 1.5 christos break;
2034 1.5 christos
2035 1.6 christos case oRequestTTY:
2036 1.6 christos intptr = &options->request_tty;
2037 1.12 christos multistate_ptr = multistate_requesttty;
2038 1.12 christos goto parse_multistate;
2039 1.6 christos
2040 1.7 tls case oSendVersionFirst:
2041 1.7 tls intptr = &options->send_version_first;
2042 1.7 tls goto parse_flag;
2043 1.7 tls
2044 1.35 christos case oSessionType:
2045 1.35 christos intptr = &options->session_type;
2046 1.35 christos multistate_ptr = multistate_sessiontype;
2047 1.35 christos goto parse_multistate;
2048 1.35 christos
2049 1.35 christos case oStdinNull:
2050 1.35 christos intptr = &options->stdin_null;
2051 1.35 christos goto parse_flag;
2052 1.35 christos
2053 1.35 christos case oForkAfterAuthentication:
2054 1.35 christos intptr = &options->fork_after_authentication;
2055 1.35 christos goto parse_flag;
2056 1.35 christos
2057 1.11 christos case oIgnoreUnknown:
2058 1.11 christos charptr = &options->ignored_unknown;
2059 1.11 christos goto parse_string;
2060 1.11 christos
2061 1.12 christos case oProxyUseFdpass:
2062 1.12 christos intptr = &options->proxy_use_fdpass;
2063 1.12 christos goto parse_flag;
2064 1.12 christos
2065 1.12 christos case oCanonicalDomains:
2066 1.12 christos value = options->num_canonical_domains != 0;
2067 1.35 christos i = 0;
2068 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
2069 1.35 christos if (*arg == '\0') {
2070 1.35 christos error("%s line %d: keyword %s empty argument",
2071 1.35 christos filename, linenum, keyword);
2072 1.35 christos goto out;
2073 1.35 christos }
2074 1.35 christos /* Allow "none" only in first position */
2075 1.35 christos if (strcasecmp(arg, "none") == 0) {
2076 1.35 christos if (i > 0 || ac > 0) {
2077 1.35 christos error("%s line %d: keyword %s \"none\" "
2078 1.35 christos "argument must appear alone.",
2079 1.35 christos filename, linenum, keyword);
2080 1.35 christos goto out;
2081 1.35 christos }
2082 1.35 christos }
2083 1.35 christos i++;
2084 1.23 christos if (!valid_domain(arg, 1, &errstr)) {
2085 1.33 christos error("%s line %d: %s", filename, linenum,
2086 1.23 christos errstr);
2087 1.35 christos goto out;
2088 1.23 christos }
2089 1.12 christos if (!*activep || value)
2090 1.12 christos continue;
2091 1.33 christos if (options->num_canonical_domains >=
2092 1.33 christos MAX_CANON_DOMAINS) {
2093 1.33 christos error("%s line %d: too many hostname suffixes.",
2094 1.12 christos filename, linenum);
2095 1.35 christos goto out;
2096 1.33 christos }
2097 1.12 christos options->canonical_domains[
2098 1.12 christos options->num_canonical_domains++] = xstrdup(arg);
2099 1.12 christos }
2100 1.12 christos break;
2101 1.12 christos
2102 1.12 christos case oCanonicalizePermittedCNAMEs:
2103 1.12 christos value = options->num_permitted_cnames != 0;
2104 1.37 christos i = 0;
2105 1.35 christos while ((arg = argv_next(&ac, &av)) != NULL) {
2106 1.37 christos char empty[] = "";
2107 1.37 christos /*
2108 1.37 christos * Either 'none' (only in first position), '*' for
2109 1.37 christos * everything or 'list:list'
2110 1.37 christos */
2111 1.37 christos if (strcasecmp(arg, "none") == 0) {
2112 1.37 christos if (i > 0 || ac > 0) {
2113 1.37 christos error("%s line %d: keyword %s \"none\" "
2114 1.37 christos "argument must appear alone.",
2115 1.37 christos filename, linenum, keyword);
2116 1.37 christos goto out;
2117 1.37 christos }
2118 1.37 christos arg2 = empty;
2119 1.37 christos } else if (strcmp(arg, "*") == 0) {
2120 1.12 christos arg2 = arg;
2121 1.37 christos } else {
2122 1.12 christos lowercase(arg);
2123 1.12 christos if ((arg2 = strchr(arg, ':')) == NULL ||
2124 1.12 christos arg2[1] == '\0') {
2125 1.33 christos error("%s line %d: "
2126 1.12 christos "Invalid permitted CNAME \"%s\"",
2127 1.12 christos filename, linenum, arg);
2128 1.35 christos goto out;
2129 1.12 christos }
2130 1.12 christos *arg2 = '\0';
2131 1.12 christos arg2++;
2132 1.12 christos }
2133 1.37 christos i++;
2134 1.12 christos if (!*activep || value)
2135 1.12 christos continue;
2136 1.33 christos if (options->num_permitted_cnames >=
2137 1.33 christos MAX_CANON_DOMAINS) {
2138 1.33 christos error("%s line %d: too many permitted CNAMEs.",
2139 1.12 christos filename, linenum);
2140 1.35 christos goto out;
2141 1.33 christos }
2142 1.12 christos cname = options->permitted_cnames +
2143 1.12 christos options->num_permitted_cnames++;
2144 1.12 christos cname->source_list = xstrdup(arg);
2145 1.12 christos cname->target_list = xstrdup(arg2);
2146 1.12 christos }
2147 1.12 christos break;
2148 1.12 christos
2149 1.12 christos case oCanonicalizeHostname:
2150 1.12 christos intptr = &options->canonicalize_hostname;
2151 1.12 christos multistate_ptr = multistate_canonicalizehostname;
2152 1.12 christos goto parse_multistate;
2153 1.12 christos
2154 1.12 christos case oCanonicalizeMaxDots:
2155 1.12 christos intptr = &options->canonicalize_max_dots;
2156 1.12 christos goto parse_int;
2157 1.12 christos
2158 1.12 christos case oCanonicalizeFallbackLocal:
2159 1.12 christos intptr = &options->canonicalize_fallback_local;
2160 1.12 christos goto parse_flag;
2161 1.12 christos
2162 1.12 christos case oStreamLocalBindMask:
2163 1.35 christos arg = argv_next(&ac, &av);
2164 1.33 christos if (!arg || *arg == '\0') {
2165 1.33 christos error("%.200s line %d: Missing StreamLocalBindMask "
2166 1.33 christos "argument.", filename, linenum);
2167 1.35 christos goto out;
2168 1.33 christos }
2169 1.12 christos /* Parse mode in octal format */
2170 1.12 christos value = strtol(arg, &endofnumber, 8);
2171 1.33 christos if (arg == endofnumber || value < 0 || value > 0777) {
2172 1.33 christos error("%.200s line %d: Bad mask.", filename, linenum);
2173 1.35 christos goto out;
2174 1.33 christos }
2175 1.12 christos options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2176 1.12 christos break;
2177 1.12 christos
2178 1.12 christos case oStreamLocalBindUnlink:
2179 1.12 christos intptr = &options->fwd_opts.streamlocal_bind_unlink;
2180 1.12 christos goto parse_flag;
2181 1.12 christos
2182 1.13 christos case oRevokedHostKeys:
2183 1.13 christos charptr = &options->revoked_host_keys;
2184 1.13 christos goto parse_string;
2185 1.13 christos
2186 1.13 christos case oFingerprintHash:
2187 1.13 christos intptr = &options->fingerprint_hash;
2188 1.35 christos arg = argv_next(&ac, &av);
2189 1.33 christos if (!arg || *arg == '\0') {
2190 1.33 christos error("%.200s line %d: Missing argument.",
2191 1.13 christos filename, linenum);
2192 1.35 christos goto out;
2193 1.33 christos }
2194 1.33 christos if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2195 1.33 christos error("%.200s line %d: Invalid hash algorithm \"%s\".",
2196 1.13 christos filename, linenum, arg);
2197 1.35 christos goto out;
2198 1.33 christos }
2199 1.13 christos if (*activep && *intptr == -1)
2200 1.13 christos *intptr = value;
2201 1.13 christos break;
2202 1.13 christos
2203 1.13 christos case oUpdateHostkeys:
2204 1.13 christos intptr = &options->update_hostkeys;
2205 1.13 christos multistate_ptr = multistate_yesnoask;
2206 1.13 christos goto parse_multistate;
2207 1.13 christos
2208 1.33 christos case oHostbasedAcceptedAlgorithms:
2209 1.33 christos charptr = &options->hostbased_accepted_algos;
2210 1.33 christos goto parse_pubkey_algos;
2211 1.33 christos
2212 1.33 christos case oPubkeyAcceptedAlgorithms:
2213 1.33 christos charptr = &options->pubkey_accepted_algos;
2214 1.33 christos goto parse_pubkey_algos;
2215 1.13 christos
2216 1.18 christos case oAddKeysToAgent:
2217 1.35 christos arg = argv_next(&ac, &av);
2218 1.35 christos arg2 = argv_next(&ac, &av);
2219 1.32 christos value = parse_multistate_value(arg, filename, linenum,
2220 1.34 christos multistate_yesnoaskconfirm);
2221 1.32 christos value2 = 0; /* unlimited lifespan by default */
2222 1.32 christos if (value == 3 && arg2 != NULL) {
2223 1.32 christos /* allow "AddKeysToAgent confirm 5m" */
2224 1.33 christos if ((value2 = convtime(arg2)) == -1 ||
2225 1.33 christos value2 > INT_MAX) {
2226 1.33 christos error("%s line %d: invalid time value.",
2227 1.32 christos filename, linenum);
2228 1.35 christos goto out;
2229 1.33 christos }
2230 1.32 christos } else if (value == -1 && arg2 == NULL) {
2231 1.33 christos if ((value2 = convtime(arg)) == -1 ||
2232 1.33 christos value2 > INT_MAX) {
2233 1.33 christos error("%s line %d: unsupported option",
2234 1.32 christos filename, linenum);
2235 1.35 christos goto out;
2236 1.33 christos }
2237 1.32 christos value = 1; /* yes */
2238 1.32 christos } else if (value == -1 || arg2 != NULL) {
2239 1.33 christos error("%s line %d: unsupported option",
2240 1.32 christos filename, linenum);
2241 1.35 christos goto out;
2242 1.32 christos }
2243 1.32 christos if (*activep && options->add_keys_to_agent == -1) {
2244 1.32 christos options->add_keys_to_agent = value;
2245 1.32 christos options->add_keys_to_agent_lifespan = value2;
2246 1.32 christos }
2247 1.32 christos break;
2248 1.18 christos
2249 1.19 christos case oIdentityAgent:
2250 1.19 christos charptr = &options->identity_agent;
2251 1.35 christos arg = argv_next(&ac, &av);
2252 1.33 christos if (!arg || *arg == '\0') {
2253 1.33 christos error("%.200s line %d: Missing argument.",
2254 1.27 christos filename, linenum);
2255 1.35 christos goto out;
2256 1.33 christos }
2257 1.29 christos parse_agent_path:
2258 1.27 christos /* Extra validation if the string represents an env var. */
2259 1.33 christos if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2260 1.33 christos error("%.200s line %d: Invalid environment expansion "
2261 1.32 christos "%s.", filename, linenum, arg);
2262 1.35 christos goto out;
2263 1.33 christos }
2264 1.32 christos free(arg2);
2265 1.32 christos /* check for legacy environment format */
2266 1.33 christos if (arg[0] == '$' && arg[1] != '{' &&
2267 1.33 christos !valid_env_name(arg + 1)) {
2268 1.33 christos error("%.200s line %d: Invalid environment name %s.",
2269 1.27 christos filename, linenum, arg);
2270 1.35 christos goto out;
2271 1.27 christos }
2272 1.27 christos if (*activep && *charptr == NULL)
2273 1.27 christos *charptr = xstrdup(arg);
2274 1.27 christos break;
2275 1.19 christos
2276 1.1 christos case oDeprecated:
2277 1.1 christos debug("%s line %d: Deprecated option \"%s\"",
2278 1.1 christos filename, linenum, keyword);
2279 1.35 christos argv_consume(&ac);
2280 1.35 christos break;
2281 1.1 christos
2282 1.1 christos case oUnsupported:
2283 1.1 christos error("%s line %d: Unsupported option \"%s\"",
2284 1.1 christos filename, linenum, keyword);
2285 1.35 christos argv_consume(&ac);
2286 1.35 christos break;
2287 1.1 christos
2288 1.1 christos default:
2289 1.33 christos error("%s line %d: Unimplemented opcode %d",
2290 1.33 christos filename, linenum, opcode);
2291 1.35 christos goto out;
2292 1.1 christos }
2293 1.1 christos
2294 1.1 christos /* Check that there is no garbage at end of line. */
2295 1.35 christos if (ac > 0) {
2296 1.35 christos error("%.200s line %d: keyword %s extra arguments "
2297 1.35 christos "at end of line", filename, linenum, keyword);
2298 1.35 christos goto out;
2299 1.1 christos }
2300 1.35 christos
2301 1.35 christos /* success */
2302 1.35 christos ret = 0;
2303 1.35 christos out:
2304 1.35 christos argv_free(oav, oac);
2305 1.35 christos return ret;
2306 1.1 christos }
2307 1.1 christos
2308 1.1 christos /*
2309 1.1 christos * Reads the config file and modifies the options accordingly. Options
2310 1.1 christos * should already be initialized before this call. This never returns if
2311 1.1 christos * there is an error. If the file does not exist, this returns 0.
2312 1.1 christos */
2313 1.1 christos int
2314 1.12 christos read_config_file(const char *filename, struct passwd *pw, const char *host,
2315 1.27 christos const char *original_host, Options *options, int flags,
2316 1.27 christos int *want_final_pass)
2317 1.1 christos {
2318 1.19 christos int active = 1;
2319 1.19 christos
2320 1.19 christos return read_config_file_depth(filename, pw, host, original_host,
2321 1.27 christos options, flags, &active, want_final_pass, 0);
2322 1.19 christos }
2323 1.19 christos
2324 1.19 christos #define READCONF_MAX_DEPTH 16
2325 1.19 christos static int
2326 1.19 christos read_config_file_depth(const char *filename, struct passwd *pw,
2327 1.19 christos const char *host, const char *original_host, Options *options,
2328 1.27 christos int flags, int *activep, int *want_final_pass, int depth)
2329 1.19 christos {
2330 1.1 christos FILE *f;
2331 1.35 christos char *line = NULL;
2332 1.25 christos size_t linesize = 0;
2333 1.19 christos int linenum;
2334 1.1 christos int bad_options = 0;
2335 1.1 christos
2336 1.19 christos if (depth < 0 || depth > READCONF_MAX_DEPTH)
2337 1.19 christos fatal("Too many recursive configuration includes");
2338 1.19 christos
2339 1.1 christos if ((f = fopen(filename, "r")) == NULL)
2340 1.1 christos return 0;
2341 1.1 christos
2342 1.9 mlelstv if (flags & SSHCONF_CHECKPERM) {
2343 1.1 christos struct stat sb;
2344 1.1 christos
2345 1.1 christos if (fstat(fileno(f), &sb) == -1)
2346 1.1 christos fatal("fstat %s: %s", filename, strerror(errno));
2347 1.1 christos if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2348 1.1 christos (sb.st_mode & 022) != 0))
2349 1.1 christos fatal("Bad owner or permissions on %s", filename);
2350 1.1 christos }
2351 1.1 christos
2352 1.1 christos debug("Reading configuration data %.200s", filename);
2353 1.1 christos
2354 1.1 christos /*
2355 1.1 christos * Mark that we are now processing the options. This flag is turned
2356 1.1 christos * on/off by Host specifications.
2357 1.1 christos */
2358 1.1 christos linenum = 0;
2359 1.25 christos while (getline(&line, &linesize, f) != -1) {
2360 1.1 christos /* Update line number counter. */
2361 1.1 christos linenum++;
2362 1.33 christos /*
2363 1.33 christos * Trim out comments and strip whitespace.
2364 1.33 christos * NB - preserve newlines, they are needed to reproduce
2365 1.33 christos * line numbers later for error messages.
2366 1.33 christos */
2367 1.19 christos if (process_config_line_depth(options, pw, host, original_host,
2368 1.27 christos line, filename, linenum, activep, flags, want_final_pass,
2369 1.27 christos depth) != 0)
2370 1.1 christos bad_options++;
2371 1.1 christos }
2372 1.25 christos free(line);
2373 1.1 christos fclose(f);
2374 1.1 christos if (bad_options > 0)
2375 1.1 christos fatal("%s: terminating, %d bad configuration options",
2376 1.1 christos filename, bad_options);
2377 1.1 christos return 1;
2378 1.1 christos }
2379 1.1 christos
2380 1.12 christos /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2381 1.12 christos int
2382 1.12 christos option_clear_or_none(const char *o)
2383 1.12 christos {
2384 1.12 christos return o == NULL || strcasecmp(o, "none") == 0;
2385 1.12 christos }
2386 1.12 christos
2387 1.1 christos /*
2388 1.37 christos * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2389 1.37 christos * Allowed to be called on non-final configuration.
2390 1.37 christos */
2391 1.37 christos int
2392 1.37 christos config_has_permitted_cnames(Options *options)
2393 1.37 christos {
2394 1.37 christos if (options->num_permitted_cnames == 1 &&
2395 1.37 christos strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2396 1.37 christos strcmp(options->permitted_cnames[0].target_list, "") == 0)
2397 1.37 christos return 0;
2398 1.37 christos return options->num_permitted_cnames > 0;
2399 1.37 christos }
2400 1.37 christos
2401 1.37 christos /*
2402 1.1 christos * Initializes options to special values that indicate that they have not yet
2403 1.1 christos * been set. Read_config_file will only set options with this value. Options
2404 1.1 christos * are processed in the following order: command line, user config file,
2405 1.1 christos * system config file. Last, fill_default_options is called.
2406 1.1 christos */
2407 1.1 christos
2408 1.1 christos void
2409 1.1 christos initialize_options(Options * options)
2410 1.1 christos {
2411 1.1 christos memset(options, 'X', sizeof(*options));
2412 1.1 christos options->forward_agent = -1;
2413 1.29 christos options->forward_agent_sock_path = NULL;
2414 1.1 christos options->forward_x11 = -1;
2415 1.1 christos options->forward_x11_trusted = -1;
2416 1.4 adam options->forward_x11_timeout = -1;
2417 1.19 christos options->stdio_forward_host = NULL;
2418 1.19 christos options->stdio_forward_port = 0;
2419 1.19 christos options->clear_forwardings = -1;
2420 1.1 christos options->exit_on_forward_failure = -1;
2421 1.1 christos options->xauth_location = NULL;
2422 1.12 christos options->fwd_opts.gateway_ports = -1;
2423 1.12 christos options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2424 1.12 christos options->fwd_opts.streamlocal_bind_unlink = -1;
2425 1.1 christos options->pubkey_authentication = -1;
2426 1.2 christos #if defined(KRB4) || defined(KRB5)
2427 1.2 christos options->kerberos_authentication = -1;
2428 1.2 christos #endif
2429 1.2 christos #if defined(AFS) || defined(KRB5)
2430 1.2 christos options->kerberos_tgt_passing = -1;
2431 1.2 christos #endif
2432 1.2 christos #ifdef AFS
2433 1.2 christos options->afs_token_passing = -1;
2434 1.2 christos #endif
2435 1.1 christos options->gss_authentication = -1;
2436 1.1 christos options->gss_deleg_creds = -1;
2437 1.1 christos options->password_authentication = -1;
2438 1.1 christos options->kbd_interactive_authentication = -1;
2439 1.1 christos options->kbd_interactive_devices = NULL;
2440 1.1 christos options->hostbased_authentication = -1;
2441 1.1 christos options->batch_mode = -1;
2442 1.1 christos options->check_host_ip = -1;
2443 1.1 christos options->strict_host_key_checking = -1;
2444 1.1 christos options->compression = -1;
2445 1.1 christos options->tcp_keep_alive = -1;
2446 1.1 christos options->port = -1;
2447 1.1 christos options->address_family = -1;
2448 1.1 christos options->connection_attempts = -1;
2449 1.1 christos options->connection_timeout = -1;
2450 1.1 christos options->number_of_password_prompts = -1;
2451 1.1 christos options->ciphers = NULL;
2452 1.1 christos options->macs = NULL;
2453 1.5 christos options->kex_algorithms = NULL;
2454 1.1 christos options->hostkeyalgorithms = NULL;
2455 1.27 christos options->ca_sign_algorithms = NULL;
2456 1.1 christos options->num_identity_files = 0;
2457 1.33 christos memset(options->identity_keys, 0, sizeof(options->identity_keys));
2458 1.18 christos options->num_certificate_files = 0;
2459 1.33 christos memset(options->certificates, 0, sizeof(options->certificates));
2460 1.1 christos options->hostname = NULL;
2461 1.1 christos options->host_key_alias = NULL;
2462 1.1 christos options->proxy_command = NULL;
2463 1.19 christos options->jump_user = NULL;
2464 1.19 christos options->jump_host = NULL;
2465 1.19 christos options->jump_port = -1;
2466 1.19 christos options->jump_extra = NULL;
2467 1.1 christos options->user = NULL;
2468 1.1 christos options->escape_char = -1;
2469 1.6 christos options->num_system_hostfiles = 0;
2470 1.6 christos options->num_user_hostfiles = 0;
2471 1.4 adam options->local_forwards = NULL;
2472 1.1 christos options->num_local_forwards = 0;
2473 1.4 adam options->remote_forwards = NULL;
2474 1.1 christos options->num_remote_forwards = 0;
2475 1.33 christos options->permitted_remote_opens = NULL;
2476 1.33 christos options->num_permitted_remote_opens = 0;
2477 1.22 christos options->log_facility = SYSLOG_FACILITY_NOT_SET;
2478 1.1 christos options->log_level = SYSLOG_LEVEL_NOT_SET;
2479 1.33 christos options->num_log_verbose = 0;
2480 1.33 christos options->log_verbose = NULL;
2481 1.1 christos options->preferred_authentications = NULL;
2482 1.1 christos options->bind_address = NULL;
2483 1.23 christos options->bind_interface = NULL;
2484 1.4 adam options->pkcs11_provider = NULL;
2485 1.29 christos options->sk_provider = NULL;
2486 1.1 christos options->enable_ssh_keysign = - 1;
2487 1.1 christos options->no_host_authentication_for_localhost = - 1;
2488 1.1 christos options->identities_only = - 1;
2489 1.1 christos options->rekey_limit = - 1;
2490 1.11 christos options->rekey_interval = -1;
2491 1.1 christos options->verify_host_key_dns = -1;
2492 1.1 christos options->server_alive_interval = -1;
2493 1.1 christos options->server_alive_count_max = -1;
2494 1.25 christos options->send_env = NULL;
2495 1.1 christos options->num_send_env = 0;
2496 1.25 christos options->setenv = NULL;
2497 1.25 christos options->num_setenv = 0;
2498 1.1 christos options->control_path = NULL;
2499 1.1 christos options->control_master = -1;
2500 1.4 adam options->control_persist = -1;
2501 1.4 adam options->control_persist_timeout = 0;
2502 1.1 christos options->hash_known_hosts = -1;
2503 1.1 christos options->tun_open = -1;
2504 1.1 christos options->tun_local = -1;
2505 1.1 christos options->tun_remote = -1;
2506 1.1 christos options->local_command = NULL;
2507 1.1 christos options->permit_local_command = -1;
2508 1.22 christos options->remote_command = NULL;
2509 1.18 christos options->add_keys_to_agent = -1;
2510 1.32 christos options->add_keys_to_agent_lifespan = -1;
2511 1.19 christos options->identity_agent = NULL;
2512 1.1 christos options->visual_host_key = -1;
2513 1.5 christos options->ip_qos_interactive = -1;
2514 1.5 christos options->ip_qos_bulk = -1;
2515 1.6 christos options->request_tty = -1;
2516 1.35 christos options->session_type = -1;
2517 1.35 christos options->stdin_null = -1;
2518 1.35 christos options->fork_after_authentication = -1;
2519 1.12 christos options->proxy_use_fdpass = -1;
2520 1.11 christos options->ignored_unknown = NULL;
2521 1.12 christos options->num_canonical_domains = 0;
2522 1.12 christos options->num_permitted_cnames = 0;
2523 1.12 christos options->canonicalize_max_dots = -1;
2524 1.12 christos options->canonicalize_fallback_local = -1;
2525 1.12 christos options->canonicalize_hostname = -1;
2526 1.13 christos options->revoked_host_keys = NULL;
2527 1.13 christos options->fingerprint_hash = -1;
2528 1.13 christos options->update_hostkeys = -1;
2529 1.33 christos options->hostbased_accepted_algos = NULL;
2530 1.33 christos options->pubkey_accepted_algos = NULL;
2531 1.33 christos options->known_hosts_command = NULL;
2532 1.2 christos options->none_switch = -1;
2533 1.2 christos options->none_enabled = -1;
2534 1.2 christos options->hpn_disabled = -1;
2535 1.2 christos options->hpn_buffer_size = -1;
2536 1.2 christos options->tcp_rcv_buf_poll = -1;
2537 1.2 christos options->tcp_rcv_buf = -1;
2538 1.7 tls options->send_version_first = -1;
2539 1.1 christos }
2540 1.1 christos
2541 1.1 christos /*
2542 1.12 christos * A petite version of fill_default_options() that just fills the options
2543 1.12 christos * needed for hostname canonicalization to proceed.
2544 1.12 christos */
2545 1.12 christos void
2546 1.12 christos fill_default_options_for_canonicalization(Options *options)
2547 1.12 christos {
2548 1.12 christos if (options->canonicalize_max_dots == -1)
2549 1.12 christos options->canonicalize_max_dots = 1;
2550 1.12 christos if (options->canonicalize_fallback_local == -1)
2551 1.12 christos options->canonicalize_fallback_local = 1;
2552 1.12 christos if (options->canonicalize_hostname == -1)
2553 1.12 christos options->canonicalize_hostname = SSH_CANONICALISE_NO;
2554 1.12 christos }
2555 1.12 christos
2556 1.12 christos /*
2557 1.1 christos * Called after processing other sources of option data, this fills those
2558 1.1 christos * options for which no value has been specified with their default values.
2559 1.1 christos */
2560 1.33 christos int
2561 1.1 christos fill_default_options(Options * options)
2562 1.1 christos {
2563 1.27 christos char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2564 1.29 christos char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2565 1.33 christos int ret = 0, r;
2566 1.25 christos
2567 1.1 christos if (options->forward_agent == -1)
2568 1.1 christos options->forward_agent = 0;
2569 1.1 christos if (options->forward_x11 == -1)
2570 1.1 christos options->forward_x11 = 0;
2571 1.1 christos if (options->forward_x11_trusted == -1)
2572 1.1 christos options->forward_x11_trusted = 0;
2573 1.4 adam if (options->forward_x11_timeout == -1)
2574 1.4 adam options->forward_x11_timeout = 1200;
2575 1.19 christos /*
2576 1.19 christos * stdio forwarding (-W) changes the default for these but we defer
2577 1.19 christos * setting the values so they can be overridden.
2578 1.19 christos */
2579 1.1 christos if (options->exit_on_forward_failure == -1)
2580 1.19 christos options->exit_on_forward_failure =
2581 1.19 christos options->stdio_forward_host != NULL ? 1 : 0;
2582 1.19 christos if (options->clear_forwardings == -1)
2583 1.19 christos options->clear_forwardings =
2584 1.19 christos options->stdio_forward_host != NULL ? 1 : 0;
2585 1.19 christos if (options->clear_forwardings == 1)
2586 1.19 christos clear_forwardings(options);
2587 1.19 christos
2588 1.1 christos if (options->xauth_location == NULL)
2589 1.33 christos options->xauth_location = xstrdup(_PATH_XAUTH);
2590 1.12 christos if (options->fwd_opts.gateway_ports == -1)
2591 1.12 christos options->fwd_opts.gateway_ports = 0;
2592 1.12 christos if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2593 1.12 christos options->fwd_opts.streamlocal_bind_mask = 0177;
2594 1.12 christos if (options->fwd_opts.streamlocal_bind_unlink == -1)
2595 1.12 christos options->fwd_opts.streamlocal_bind_unlink = 0;
2596 1.1 christos if (options->pubkey_authentication == -1)
2597 1.1 christos options->pubkey_authentication = 1;
2598 1.2 christos #if defined(KRB4) || defined(KRB5)
2599 1.2 christos if (options->kerberos_authentication == -1)
2600 1.2 christos options->kerberos_authentication = 1;
2601 1.2 christos #endif
2602 1.2 christos #if defined(AFS) || defined(KRB5)
2603 1.2 christos if (options->kerberos_tgt_passing == -1)
2604 1.2 christos options->kerberos_tgt_passing = 1;
2605 1.2 christos #endif
2606 1.2 christos #ifdef AFS
2607 1.2 christos if (options->afs_token_passing == -1)
2608 1.2 christos options->afs_token_passing = 1;
2609 1.2 christos #endif
2610 1.1 christos if (options->gss_authentication == -1)
2611 1.1 christos options->gss_authentication = 0;
2612 1.1 christos if (options->gss_deleg_creds == -1)
2613 1.1 christos options->gss_deleg_creds = 0;
2614 1.1 christos if (options->password_authentication == -1)
2615 1.1 christos options->password_authentication = 1;
2616 1.1 christos if (options->kbd_interactive_authentication == -1)
2617 1.1 christos options->kbd_interactive_authentication = 1;
2618 1.1 christos if (options->hostbased_authentication == -1)
2619 1.1 christos options->hostbased_authentication = 0;
2620 1.1 christos if (options->batch_mode == -1)
2621 1.1 christos options->batch_mode = 0;
2622 1.1 christos if (options->check_host_ip == -1)
2623 1.33 christos options->check_host_ip = 0;
2624 1.1 christos if (options->strict_host_key_checking == -1)
2625 1.22 christos options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2626 1.1 christos if (options->compression == -1)
2627 1.1 christos options->compression = 0;
2628 1.1 christos if (options->tcp_keep_alive == -1)
2629 1.1 christos options->tcp_keep_alive = 1;
2630 1.1 christos if (options->port == -1)
2631 1.1 christos options->port = 0; /* Filled in ssh_connect. */
2632 1.1 christos if (options->address_family == -1)
2633 1.1 christos options->address_family = AF_UNSPEC;
2634 1.1 christos if (options->connection_attempts == -1)
2635 1.1 christos options->connection_attempts = 1;
2636 1.1 christos if (options->number_of_password_prompts == -1)
2637 1.1 christos options->number_of_password_prompts = 3;
2638 1.1 christos /* options->hostkeyalgorithms, default set in myproposals.h */
2639 1.32 christos if (options->add_keys_to_agent == -1) {
2640 1.18 christos options->add_keys_to_agent = 0;
2641 1.32 christos options->add_keys_to_agent_lifespan = 0;
2642 1.32 christos }
2643 1.1 christos if (options->num_identity_files == 0) {
2644 1.22 christos add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2645 1.22 christos add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2646 1.22 christos add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2647 1.22 christos add_identity_file(options, "~/",
2648 1.29 christos _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2649 1.29 christos add_identity_file(options, "~/",
2650 1.22 christos _PATH_SSH_CLIENT_ID_ED25519, 0);
2651 1.29 christos add_identity_file(options, "~/",
2652 1.29 christos _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2653 1.23 christos add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2654 1.1 christos }
2655 1.1 christos if (options->escape_char == -1)
2656 1.1 christos options->escape_char = '~';
2657 1.6 christos if (options->num_system_hostfiles == 0) {
2658 1.6 christos options->system_hostfiles[options->num_system_hostfiles++] =
2659 1.6 christos xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2660 1.6 christos options->system_hostfiles[options->num_system_hostfiles++] =
2661 1.6 christos xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2662 1.6 christos }
2663 1.33 christos if (options->update_hostkeys == -1) {
2664 1.33 christos if (options->verify_host_key_dns <= 0 &&
2665 1.33 christos (options->num_user_hostfiles == 0 ||
2666 1.33 christos (options->num_user_hostfiles == 1 && strcmp(options->
2667 1.33 christos user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2668 1.33 christos options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2669 1.33 christos else
2670 1.29 christos options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2671 1.33 christos }
2672 1.6 christos if (options->num_user_hostfiles == 0) {
2673 1.6 christos options->user_hostfiles[options->num_user_hostfiles++] =
2674 1.6 christos xstrdup(_PATH_SSH_USER_HOSTFILE);
2675 1.6 christos options->user_hostfiles[options->num_user_hostfiles++] =
2676 1.6 christos xstrdup(_PATH_SSH_USER_HOSTFILE2);
2677 1.6 christos }
2678 1.1 christos if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2679 1.1 christos options->log_level = SYSLOG_LEVEL_INFO;
2680 1.22 christos if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2681 1.22 christos options->log_facility = SYSLOG_FACILITY_USER;
2682 1.1 christos if (options->no_host_authentication_for_localhost == - 1)
2683 1.1 christos options->no_host_authentication_for_localhost = 0;
2684 1.1 christos if (options->identities_only == -1)
2685 1.1 christos options->identities_only = 0;
2686 1.1 christos if (options->enable_ssh_keysign == -1)
2687 1.1 christos options->enable_ssh_keysign = 0;
2688 1.1 christos if (options->rekey_limit == -1)
2689 1.1 christos options->rekey_limit = 0;
2690 1.11 christos if (options->rekey_interval == -1)
2691 1.11 christos options->rekey_interval = 0;
2692 1.1 christos if (options->verify_host_key_dns == -1)
2693 1.1 christos options->verify_host_key_dns = 0;
2694 1.1 christos if (options->server_alive_interval == -1)
2695 1.1 christos options->server_alive_interval = 0;
2696 1.1 christos if (options->server_alive_count_max == -1)
2697 1.1 christos options->server_alive_count_max = 3;
2698 1.2 christos if (options->none_switch == -1)
2699 1.2 christos options->none_switch = 0;
2700 1.2 christos if (options->hpn_disabled == -1)
2701 1.2 christos options->hpn_disabled = 0;
2702 1.2 christos if (options->hpn_buffer_size > -1)
2703 1.2 christos {
2704 1.2 christos /* if a user tries to set the size to 0 set it to 1KB */
2705 1.2 christos if (options->hpn_buffer_size == 0)
2706 1.2 christos options->hpn_buffer_size = 1024;
2707 1.2 christos /*limit the buffer to 64MB*/
2708 1.2 christos if (options->hpn_buffer_size > 65536)
2709 1.2 christos {
2710 1.2 christos options->hpn_buffer_size = 65536*1024;
2711 1.2 christos debug("User requested buffer larger than 64MB. Request reverted to 64MB");
2712 1.2 christos }
2713 1.2 christos debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
2714 1.2 christos }
2715 1.2 christos if (options->tcp_rcv_buf == 0)
2716 1.2 christos options->tcp_rcv_buf = 1;
2717 1.2 christos if (options->tcp_rcv_buf > -1)
2718 1.2 christos options->tcp_rcv_buf *=1024;
2719 1.2 christos if (options->tcp_rcv_buf_poll == -1)
2720 1.2 christos options->tcp_rcv_buf_poll = 1;
2721 1.1 christos if (options->control_master == -1)
2722 1.1 christos options->control_master = 0;
2723 1.4 adam if (options->control_persist == -1) {
2724 1.4 adam options->control_persist = 0;
2725 1.4 adam options->control_persist_timeout = 0;
2726 1.4 adam }
2727 1.1 christos if (options->hash_known_hosts == -1)
2728 1.1 christos options->hash_known_hosts = 0;
2729 1.1 christos if (options->tun_open == -1)
2730 1.1 christos options->tun_open = SSH_TUNMODE_NO;
2731 1.1 christos if (options->tun_local == -1)
2732 1.1 christos options->tun_local = SSH_TUNID_ANY;
2733 1.1 christos if (options->tun_remote == -1)
2734 1.1 christos options->tun_remote = SSH_TUNID_ANY;
2735 1.1 christos if (options->permit_local_command == -1)
2736 1.1 christos options->permit_local_command = 0;
2737 1.1 christos if (options->visual_host_key == -1)
2738 1.1 christos options->visual_host_key = 0;
2739 1.5 christos if (options->ip_qos_interactive == -1)
2740 1.25 christos options->ip_qos_interactive = IPTOS_DSCP_AF21;
2741 1.5 christos if (options->ip_qos_bulk == -1)
2742 1.25 christos options->ip_qos_bulk = IPTOS_DSCP_CS1;
2743 1.6 christos if (options->request_tty == -1)
2744 1.6 christos options->request_tty = REQUEST_TTY_AUTO;
2745 1.35 christos if (options->session_type == -1)
2746 1.35 christos options->session_type = SESSION_TYPE_DEFAULT;
2747 1.35 christos if (options->stdin_null == -1)
2748 1.35 christos options->stdin_null = 0;
2749 1.35 christos if (options->fork_after_authentication == -1)
2750 1.35 christos options->fork_after_authentication = 0;
2751 1.12 christos if (options->proxy_use_fdpass == -1)
2752 1.12 christos options->proxy_use_fdpass = 0;
2753 1.12 christos if (options->canonicalize_max_dots == -1)
2754 1.12 christos options->canonicalize_max_dots = 1;
2755 1.12 christos if (options->canonicalize_fallback_local == -1)
2756 1.12 christos options->canonicalize_fallback_local = 1;
2757 1.12 christos if (options->canonicalize_hostname == -1)
2758 1.12 christos options->canonicalize_hostname = SSH_CANONICALISE_NO;
2759 1.13 christos if (options->fingerprint_hash == -1)
2760 1.13 christos options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2761 1.29 christos if (options->sk_provider == NULL)
2762 1.29 christos options->sk_provider = xstrdup("internal");
2763 1.25 christos
2764 1.25 christos /* Expand KEX name lists */
2765 1.25 christos all_cipher = cipher_alg_list(',', 0);
2766 1.25 christos all_mac = mac_alg_list(',');
2767 1.25 christos all_kex = kex_alg_list(',');
2768 1.25 christos all_key = sshkey_alg_list(0, 0, 1, ',');
2769 1.27 christos all_sig = sshkey_alg_list(0, 1, 1, ',');
2770 1.29 christos /* remove unsupported algos from default lists */
2771 1.32 christos def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2772 1.32 christos def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2773 1.32 christos def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2774 1.32 christos def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2775 1.32 christos def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2776 1.25 christos #define ASSEMBLE(what, defaults, all) \
2777 1.25 christos do { \
2778 1.25 christos if ((r = kex_assemble_names(&options->what, \
2779 1.33 christos defaults, all)) != 0) { \
2780 1.33 christos error_fr(r, "%s", #what); \
2781 1.33 christos goto fail; \
2782 1.33 christos } \
2783 1.25 christos } while (0)
2784 1.29 christos ASSEMBLE(ciphers, def_cipher, all_cipher);
2785 1.29 christos ASSEMBLE(macs, def_mac, all_mac);
2786 1.29 christos ASSEMBLE(kex_algorithms, def_kex, all_kex);
2787 1.33 christos ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2788 1.33 christos ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2789 1.29 christos ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2790 1.25 christos #undef ASSEMBLE
2791 1.13 christos
2792 1.7 tls if (options->send_version_first == -1)
2793 1.7 tls options->send_version_first = 1;
2794 1.12 christos #define CLEAR_ON_NONE(v) \
2795 1.12 christos do { \
2796 1.12 christos if (option_clear_or_none(v)) { \
2797 1.12 christos free(v); \
2798 1.12 christos v = NULL; \
2799 1.12 christos } \
2800 1.12 christos } while(0)
2801 1.12 christos CLEAR_ON_NONE(options->local_command);
2802 1.22 christos CLEAR_ON_NONE(options->remote_command);
2803 1.12 christos CLEAR_ON_NONE(options->proxy_command);
2804 1.12 christos CLEAR_ON_NONE(options->control_path);
2805 1.13 christos CLEAR_ON_NONE(options->revoked_host_keys);
2806 1.27 christos CLEAR_ON_NONE(options->pkcs11_provider);
2807 1.29 christos CLEAR_ON_NONE(options->sk_provider);
2808 1.33 christos CLEAR_ON_NONE(options->known_hosts_command);
2809 1.25 christos if (options->jump_host != NULL &&
2810 1.25 christos strcmp(options->jump_host, "none") == 0 &&
2811 1.25 christos options->jump_port == 0 && options->jump_user == NULL) {
2812 1.25 christos free(options->jump_host);
2813 1.25 christos options->jump_host = NULL;
2814 1.25 christos }
2815 1.37 christos if (options->num_permitted_cnames == 1 &&
2816 1.37 christos !config_has_permitted_cnames(options)) {
2817 1.37 christos /* clean up CanonicalizePermittedCNAMEs=none */
2818 1.37 christos free(options->permitted_cnames[0].source_list);
2819 1.37 christos free(options->permitted_cnames[0].target_list);
2820 1.37 christos memset(options->permitted_cnames, '\0',
2821 1.37 christos sizeof(*options->permitted_cnames));
2822 1.37 christos options->num_permitted_cnames = 0;
2823 1.37 christos }
2824 1.19 christos /* options->identity_agent distinguishes NULL from 'none' */
2825 1.1 christos /* options->user will be set in the main program if appropriate */
2826 1.1 christos /* options->hostname will be set in the main program if appropriate */
2827 1.1 christos /* options->host_key_alias should not be set by default */
2828 1.1 christos /* options->preferred_authentications will be set in ssh */
2829 1.33 christos
2830 1.33 christos /* success */
2831 1.33 christos ret = 0;
2832 1.33 christos fail:
2833 1.33 christos free(all_cipher);
2834 1.33 christos free(all_mac);
2835 1.33 christos free(all_kex);
2836 1.33 christos free(all_key);
2837 1.33 christos free(all_sig);
2838 1.33 christos free(def_cipher);
2839 1.33 christos free(def_mac);
2840 1.33 christos free(def_kex);
2841 1.33 christos free(def_key);
2842 1.33 christos free(def_sig);
2843 1.33 christos return ret;
2844 1.33 christos }
2845 1.33 christos
2846 1.33 christos void
2847 1.33 christos free_options(Options *o)
2848 1.33 christos {
2849 1.33 christos int i;
2850 1.33 christos
2851 1.33 christos if (o == NULL)
2852 1.33 christos return;
2853 1.33 christos
2854 1.33 christos #define FREE_ARRAY(type, n, a) \
2855 1.33 christos do { \
2856 1.33 christos type _i; \
2857 1.33 christos for (_i = 0; _i < (n); _i++) \
2858 1.33 christos free((a)[_i]); \
2859 1.33 christos } while (0)
2860 1.33 christos
2861 1.33 christos free(o->forward_agent_sock_path);
2862 1.33 christos free(o->xauth_location);
2863 1.33 christos FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2864 1.33 christos free(o->log_verbose);
2865 1.33 christos free(o->ciphers);
2866 1.33 christos free(o->macs);
2867 1.33 christos free(o->hostkeyalgorithms);
2868 1.33 christos free(o->kex_algorithms);
2869 1.33 christos free(o->ca_sign_algorithms);
2870 1.33 christos free(o->hostname);
2871 1.33 christos free(o->host_key_alias);
2872 1.33 christos free(o->proxy_command);
2873 1.33 christos free(o->user);
2874 1.33 christos FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2875 1.33 christos FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2876 1.33 christos free(o->preferred_authentications);
2877 1.33 christos free(o->bind_address);
2878 1.33 christos free(o->bind_interface);
2879 1.33 christos free(o->pkcs11_provider);
2880 1.33 christos free(o->sk_provider);
2881 1.33 christos for (i = 0; i < o->num_identity_files; i++) {
2882 1.33 christos free(o->identity_files[i]);
2883 1.33 christos sshkey_free(o->identity_keys[i]);
2884 1.33 christos }
2885 1.33 christos for (i = 0; i < o->num_certificate_files; i++) {
2886 1.33 christos free(o->certificate_files[i]);
2887 1.33 christos sshkey_free(o->certificates[i]);
2888 1.33 christos }
2889 1.33 christos free(o->identity_agent);
2890 1.33 christos for (i = 0; i < o->num_local_forwards; i++) {
2891 1.33 christos free(o->local_forwards[i].listen_host);
2892 1.33 christos free(o->local_forwards[i].listen_path);
2893 1.33 christos free(o->local_forwards[i].connect_host);
2894 1.33 christos free(o->local_forwards[i].connect_path);
2895 1.33 christos }
2896 1.33 christos free(o->local_forwards);
2897 1.33 christos for (i = 0; i < o->num_remote_forwards; i++) {
2898 1.33 christos free(o->remote_forwards[i].listen_host);
2899 1.33 christos free(o->remote_forwards[i].listen_path);
2900 1.33 christos free(o->remote_forwards[i].connect_host);
2901 1.33 christos free(o->remote_forwards[i].connect_path);
2902 1.33 christos }
2903 1.33 christos free(o->remote_forwards);
2904 1.33 christos free(o->stdio_forward_host);
2905 1.33 christos FREE_ARRAY(int, o->num_send_env, o->send_env);
2906 1.33 christos free(o->send_env);
2907 1.33 christos FREE_ARRAY(int, o->num_setenv, o->setenv);
2908 1.33 christos free(o->setenv);
2909 1.33 christos free(o->control_path);
2910 1.33 christos free(o->local_command);
2911 1.33 christos free(o->remote_command);
2912 1.33 christos FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2913 1.33 christos for (i = 0; i < o->num_permitted_cnames; i++) {
2914 1.33 christos free(o->permitted_cnames[i].source_list);
2915 1.33 christos free(o->permitted_cnames[i].target_list);
2916 1.33 christos }
2917 1.33 christos free(o->revoked_host_keys);
2918 1.33 christos free(o->hostbased_accepted_algos);
2919 1.33 christos free(o->pubkey_accepted_algos);
2920 1.33 christos free(o->jump_user);
2921 1.33 christos free(o->jump_host);
2922 1.33 christos free(o->jump_extra);
2923 1.33 christos free(o->ignored_unknown);
2924 1.33 christos explicit_bzero(o, sizeof(*o));
2925 1.33 christos #undef FREE_ARRAY
2926 1.1 christos }
2927 1.1 christos
2928 1.12 christos struct fwdarg {
2929 1.12 christos char *arg;
2930 1.12 christos int ispath;
2931 1.12 christos };
2932 1.12 christos
2933 1.12 christos /*
2934 1.12 christos * parse_fwd_field
2935 1.12 christos * parses the next field in a port forwarding specification.
2936 1.12 christos * sets fwd to the parsed field and advances p past the colon
2937 1.12 christos * or sets it to NULL at end of string.
2938 1.12 christos * returns 0 on success, else non-zero.
2939 1.12 christos */
2940 1.12 christos static int
2941 1.12 christos parse_fwd_field(char **p, struct fwdarg *fwd)
2942 1.12 christos {
2943 1.12 christos char *ep, *cp = *p;
2944 1.12 christos int ispath = 0;
2945 1.12 christos
2946 1.12 christos if (*cp == '\0') {
2947 1.12 christos *p = NULL;
2948 1.12 christos return -1; /* end of string */
2949 1.12 christos }
2950 1.12 christos
2951 1.12 christos /*
2952 1.12 christos * A field escaped with square brackets is used literally.
2953 1.12 christos * XXX - allow ']' to be escaped via backslash?
2954 1.12 christos */
2955 1.12 christos if (*cp == '[') {
2956 1.12 christos /* find matching ']' */
2957 1.12 christos for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2958 1.12 christos if (*ep == '/')
2959 1.12 christos ispath = 1;
2960 1.12 christos }
2961 1.12 christos /* no matching ']' or not at end of field. */
2962 1.12 christos if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2963 1.12 christos return -1;
2964 1.12 christos /* NUL terminate the field and advance p past the colon */
2965 1.12 christos *ep++ = '\0';
2966 1.12 christos if (*ep != '\0')
2967 1.12 christos *ep++ = '\0';
2968 1.12 christos fwd->arg = cp + 1;
2969 1.12 christos fwd->ispath = ispath;
2970 1.12 christos *p = ep;
2971 1.12 christos return 0;
2972 1.12 christos }
2973 1.12 christos
2974 1.12 christos for (cp = *p; *cp != '\0'; cp++) {
2975 1.12 christos switch (*cp) {
2976 1.12 christos case '\\':
2977 1.12 christos memmove(cp, cp + 1, strlen(cp + 1) + 1);
2978 1.14 christos if (*cp == '\0')
2979 1.14 christos return -1;
2980 1.12 christos break;
2981 1.12 christos case '/':
2982 1.12 christos ispath = 1;
2983 1.12 christos break;
2984 1.12 christos case ':':
2985 1.12 christos *cp++ = '\0';
2986 1.12 christos goto done;
2987 1.12 christos }
2988 1.12 christos }
2989 1.12 christos done:
2990 1.12 christos fwd->arg = *p;
2991 1.12 christos fwd->ispath = ispath;
2992 1.12 christos *p = cp;
2993 1.12 christos return 0;
2994 1.12 christos }
2995 1.12 christos
2996 1.1 christos /*
2997 1.1 christos * parse_forward
2998 1.1 christos * parses a string containing a port forwarding specification of the form:
2999 1.1 christos * dynamicfwd == 0
3000 1.12 christos * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3001 1.12 christos * listenpath:connectpath
3002 1.1 christos * dynamicfwd == 1
3003 1.1 christos * [listenhost:]listenport
3004 1.1 christos * returns number of arguments parsed or zero on error
3005 1.1 christos */
3006 1.1 christos int
3007 1.12 christos parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3008 1.1 christos {
3009 1.12 christos struct fwdarg fwdargs[4];
3010 1.12 christos char *p, *cp;
3011 1.32 christos int i, err;
3012 1.1 christos
3013 1.12 christos memset(fwd, 0, sizeof(*fwd));
3014 1.12 christos memset(fwdargs, 0, sizeof(fwdargs));
3015 1.1 christos
3016 1.32 christos /*
3017 1.32 christos * We expand environment variables before checking if we think they're
3018 1.32 christos * paths so that if ${VAR} expands to a fully qualified path it is
3019 1.32 christos * treated as a path.
3020 1.32 christos */
3021 1.32 christos cp = p = dollar_expand(&err, fwdspec);
3022 1.32 christos if (p == NULL || err)
3023 1.32 christos return 0;
3024 1.1 christos
3025 1.1 christos /* skip leading spaces */
3026 1.12 christos while (isspace((u_char)*cp))
3027 1.1 christos cp++;
3028 1.1 christos
3029 1.12 christos for (i = 0; i < 4; ++i) {
3030 1.12 christos if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3031 1.1 christos break;
3032 1.12 christos }
3033 1.1 christos
3034 1.1 christos /* Check for trailing garbage */
3035 1.12 christos if (cp != NULL && *cp != '\0') {
3036 1.1 christos i = 0; /* failure */
3037 1.12 christos }
3038 1.1 christos
3039 1.1 christos switch (i) {
3040 1.1 christos case 1:
3041 1.12 christos if (fwdargs[0].ispath) {
3042 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
3043 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
3044 1.12 christos } else {
3045 1.12 christos fwd->listen_host = NULL;
3046 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
3047 1.12 christos }
3048 1.1 christos fwd->connect_host = xstrdup("socks");
3049 1.1 christos break;
3050 1.1 christos
3051 1.1 christos case 2:
3052 1.12 christos if (fwdargs[0].ispath && fwdargs[1].ispath) {
3053 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
3054 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
3055 1.12 christos fwd->connect_path = xstrdup(fwdargs[1].arg);
3056 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
3057 1.12 christos } else if (fwdargs[1].ispath) {
3058 1.12 christos fwd->listen_host = NULL;
3059 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
3060 1.12 christos fwd->connect_path = xstrdup(fwdargs[1].arg);
3061 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
3062 1.12 christos } else {
3063 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
3064 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
3065 1.12 christos fwd->connect_host = xstrdup("socks");
3066 1.12 christos }
3067 1.1 christos break;
3068 1.1 christos
3069 1.1 christos case 3:
3070 1.12 christos if (fwdargs[0].ispath) {
3071 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
3072 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
3073 1.12 christos fwd->connect_host = xstrdup(fwdargs[1].arg);
3074 1.12 christos fwd->connect_port = a2port(fwdargs[2].arg);
3075 1.12 christos } else if (fwdargs[2].ispath) {
3076 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
3077 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
3078 1.12 christos fwd->connect_path = xstrdup(fwdargs[2].arg);
3079 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
3080 1.12 christos } else {
3081 1.12 christos fwd->listen_host = NULL;
3082 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
3083 1.12 christos fwd->connect_host = xstrdup(fwdargs[1].arg);
3084 1.12 christos fwd->connect_port = a2port(fwdargs[2].arg);
3085 1.12 christos }
3086 1.1 christos break;
3087 1.1 christos
3088 1.1 christos case 4:
3089 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
3090 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
3091 1.12 christos fwd->connect_host = xstrdup(fwdargs[2].arg);
3092 1.12 christos fwd->connect_port = a2port(fwdargs[3].arg);
3093 1.1 christos break;
3094 1.1 christos default:
3095 1.1 christos i = 0; /* failure */
3096 1.1 christos }
3097 1.1 christos
3098 1.11 christos free(p);
3099 1.1 christos
3100 1.1 christos if (dynamicfwd) {
3101 1.1 christos if (!(i == 1 || i == 2))
3102 1.1 christos goto fail_free;
3103 1.1 christos } else {
3104 1.12 christos if (!(i == 3 || i == 4)) {
3105 1.12 christos if (fwd->connect_path == NULL &&
3106 1.12 christos fwd->listen_path == NULL)
3107 1.12 christos goto fail_free;
3108 1.12 christos }
3109 1.12 christos if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3110 1.1 christos goto fail_free;
3111 1.1 christos }
3112 1.1 christos
3113 1.12 christos if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3114 1.12 christos (!remotefwd && fwd->listen_port == 0))
3115 1.1 christos goto fail_free;
3116 1.1 christos if (fwd->connect_host != NULL &&
3117 1.1 christos strlen(fwd->connect_host) >= NI_MAXHOST)
3118 1.1 christos goto fail_free;
3119 1.35 christos /*
3120 1.35 christos * XXX - if connecting to a remote socket, max sun len may not
3121 1.35 christos * match this host
3122 1.35 christos */
3123 1.12 christos if (fwd->connect_path != NULL &&
3124 1.12 christos strlen(fwd->connect_path) >= PATH_MAX_SUN)
3125 1.12 christos goto fail_free;
3126 1.1 christos if (fwd->listen_host != NULL &&
3127 1.1 christos strlen(fwd->listen_host) >= NI_MAXHOST)
3128 1.1 christos goto fail_free;
3129 1.12 christos if (fwd->listen_path != NULL &&
3130 1.12 christos strlen(fwd->listen_path) >= PATH_MAX_SUN)
3131 1.12 christos goto fail_free;
3132 1.1 christos
3133 1.1 christos return (i);
3134 1.1 christos
3135 1.1 christos fail_free:
3136 1.11 christos free(fwd->connect_host);
3137 1.11 christos fwd->connect_host = NULL;
3138 1.12 christos free(fwd->connect_path);
3139 1.12 christos fwd->connect_path = NULL;
3140 1.11 christos free(fwd->listen_host);
3141 1.11 christos fwd->listen_host = NULL;
3142 1.12 christos free(fwd->listen_path);
3143 1.12 christos fwd->listen_path = NULL;
3144 1.1 christos return (0);
3145 1.1 christos }
3146 1.13 christos
3147 1.19 christos int
3148 1.19 christos parse_jump(const char *s, Options *o, int active)
3149 1.19 christos {
3150 1.19 christos char *orig, *sdup, *cp;
3151 1.19 christos char *host = NULL, *user = NULL;
3152 1.33 christos int r, ret = -1, port = -1, first;
3153 1.19 christos
3154 1.19 christos active &= o->proxy_command == NULL && o->jump_host == NULL;
3155 1.19 christos
3156 1.19 christos orig = sdup = xstrdup(s);
3157 1.35 christos
3158 1.35 christos /* Remove comment and trailing whitespace */
3159 1.35 christos if ((cp = strchr(orig, '#')) != NULL)
3160 1.35 christos *cp = '\0';
3161 1.35 christos rtrim(orig);
3162 1.35 christos
3163 1.19 christos first = active;
3164 1.19 christos do {
3165 1.25 christos if (strcasecmp(s, "none") == 0)
3166 1.25 christos break;
3167 1.19 christos if ((cp = strrchr(sdup, ',')) == NULL)
3168 1.19 christos cp = sdup; /* last */
3169 1.19 christos else
3170 1.19 christos *cp++ = '\0';
3171 1.19 christos
3172 1.19 christos if (first) {
3173 1.19 christos /* First argument and configuration is active */
3174 1.33 christos r = parse_ssh_uri(cp, &user, &host, &port);
3175 1.33 christos if (r == -1 || (r == 1 &&
3176 1.33 christos parse_user_host_port(cp, &user, &host, &port) != 0))
3177 1.19 christos goto out;
3178 1.19 christos } else {
3179 1.19 christos /* Subsequent argument or inactive configuration */
3180 1.33 christos r = parse_ssh_uri(cp, NULL, NULL, NULL);
3181 1.33 christos if (r == -1 || (r == 1 &&
3182 1.33 christos parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3183 1.19 christos goto out;
3184 1.19 christos }
3185 1.19 christos first = 0; /* only check syntax for subsequent hosts */
3186 1.19 christos } while (cp != sdup);
3187 1.19 christos /* success */
3188 1.19 christos if (active) {
3189 1.25 christos if (strcasecmp(s, "none") == 0) {
3190 1.25 christos o->jump_host = xstrdup("none");
3191 1.25 christos o->jump_port = 0;
3192 1.25 christos } else {
3193 1.25 christos o->jump_user = user;
3194 1.25 christos o->jump_host = host;
3195 1.25 christos o->jump_port = port;
3196 1.25 christos o->proxy_command = xstrdup("none");
3197 1.25 christos user = host = NULL;
3198 1.25 christos if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3199 1.25 christos o->jump_extra = xstrdup(s);
3200 1.25 christos o->jump_extra[cp - s] = '\0';
3201 1.25 christos }
3202 1.19 christos }
3203 1.19 christos }
3204 1.19 christos ret = 0;
3205 1.19 christos out:
3206 1.19 christos free(orig);
3207 1.19 christos free(user);
3208 1.19 christos free(host);
3209 1.19 christos return ret;
3210 1.19 christos }
3211 1.19 christos
3212 1.23 christos int
3213 1.23 christos parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3214 1.23 christos {
3215 1.33 christos char *user = NULL, *host = NULL, *path = NULL;
3216 1.33 christos int r, port;
3217 1.23 christos
3218 1.33 christos r = parse_uri("ssh", uri, &user, &host, &port, &path);
3219 1.23 christos if (r == 0 && path != NULL)
3220 1.23 christos r = -1; /* path not allowed */
3221 1.33 christos if (r == 0) {
3222 1.33 christos if (userp != NULL) {
3223 1.33 christos *userp = user;
3224 1.33 christos user = NULL;
3225 1.33 christos }
3226 1.33 christos if (hostp != NULL) {
3227 1.33 christos *hostp = host;
3228 1.33 christos host = NULL;
3229 1.33 christos }
3230 1.33 christos if (portp != NULL)
3231 1.33 christos *portp = port;
3232 1.33 christos }
3233 1.33 christos free(user);
3234 1.33 christos free(host);
3235 1.33 christos free(path);
3236 1.23 christos return r;
3237 1.23 christos }
3238 1.23 christos
3239 1.13 christos /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3240 1.13 christos static const char *
3241 1.13 christos fmt_multistate_int(int val, const struct multistate *m)
3242 1.13 christos {
3243 1.13 christos u_int i;
3244 1.13 christos
3245 1.13 christos for (i = 0; m[i].key != NULL; i++) {
3246 1.13 christos if (m[i].value == val)
3247 1.13 christos return m[i].key;
3248 1.13 christos }
3249 1.13 christos return "UNKNOWN";
3250 1.13 christos }
3251 1.13 christos
3252 1.13 christos static const char *
3253 1.13 christos fmt_intarg(OpCodes code, int val)
3254 1.13 christos {
3255 1.13 christos if (val == -1)
3256 1.13 christos return "unset";
3257 1.13 christos switch (code) {
3258 1.13 christos case oAddressFamily:
3259 1.13 christos return fmt_multistate_int(val, multistate_addressfamily);
3260 1.13 christos case oVerifyHostKeyDNS:
3261 1.13 christos case oUpdateHostkeys:
3262 1.13 christos return fmt_multistate_int(val, multistate_yesnoask);
3263 1.22 christos case oStrictHostKeyChecking:
3264 1.22 christos return fmt_multistate_int(val, multistate_strict_hostkey);
3265 1.13 christos case oControlMaster:
3266 1.13 christos return fmt_multistate_int(val, multistate_controlmaster);
3267 1.13 christos case oTunnel:
3268 1.13 christos return fmt_multistate_int(val, multistate_tunnel);
3269 1.13 christos case oRequestTTY:
3270 1.13 christos return fmt_multistate_int(val, multistate_requesttty);
3271 1.35 christos case oSessionType:
3272 1.35 christos return fmt_multistate_int(val, multistate_sessiontype);
3273 1.13 christos case oCanonicalizeHostname:
3274 1.13 christos return fmt_multistate_int(val, multistate_canonicalizehostname);
3275 1.25 christos case oAddKeysToAgent:
3276 1.25 christos return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3277 1.13 christos case oFingerprintHash:
3278 1.13 christos return ssh_digest_alg_name(val);
3279 1.13 christos default:
3280 1.13 christos switch (val) {
3281 1.13 christos case 0:
3282 1.13 christos return "no";
3283 1.13 christos case 1:
3284 1.13 christos return "yes";
3285 1.13 christos default:
3286 1.13 christos return "UNKNOWN";
3287 1.13 christos }
3288 1.13 christos }
3289 1.13 christos }
3290 1.13 christos
3291 1.13 christos static const char *
3292 1.13 christos lookup_opcode_name(OpCodes code)
3293 1.13 christos {
3294 1.13 christos u_int i;
3295 1.13 christos
3296 1.13 christos for (i = 0; keywords[i].name != NULL; i++)
3297 1.13 christos if (keywords[i].opcode == code)
3298 1.13 christos return(keywords[i].name);
3299 1.13 christos return "UNKNOWN";
3300 1.13 christos }
3301 1.13 christos
3302 1.13 christos static void
3303 1.13 christos dump_cfg_int(OpCodes code, int val)
3304 1.13 christos {
3305 1.13 christos printf("%s %d\n", lookup_opcode_name(code), val);
3306 1.13 christos }
3307 1.13 christos
3308 1.13 christos static void
3309 1.13 christos dump_cfg_fmtint(OpCodes code, int val)
3310 1.13 christos {
3311 1.13 christos printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3312 1.13 christos }
3313 1.13 christos
3314 1.13 christos static void
3315 1.13 christos dump_cfg_string(OpCodes code, const char *val)
3316 1.13 christos {
3317 1.13 christos if (val == NULL)
3318 1.13 christos return;
3319 1.13 christos printf("%s %s\n", lookup_opcode_name(code), val);
3320 1.13 christos }
3321 1.13 christos
3322 1.13 christos static void
3323 1.13 christos dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3324 1.13 christos {
3325 1.13 christos u_int i;
3326 1.13 christos
3327 1.13 christos for (i = 0; i < count; i++)
3328 1.13 christos printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3329 1.13 christos }
3330 1.13 christos
3331 1.13 christos static void
3332 1.13 christos dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3333 1.13 christos {
3334 1.13 christos u_int i;
3335 1.13 christos
3336 1.13 christos printf("%s", lookup_opcode_name(code));
3337 1.35 christos if (count == 0)
3338 1.35 christos printf(" none");
3339 1.13 christos for (i = 0; i < count; i++)
3340 1.13 christos printf(" %s", vals[i]);
3341 1.13 christos printf("\n");
3342 1.13 christos }
3343 1.13 christos
3344 1.13 christos static void
3345 1.13 christos dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3346 1.13 christos {
3347 1.13 christos const struct Forward *fwd;
3348 1.13 christos u_int i;
3349 1.13 christos
3350 1.13 christos /* oDynamicForward */
3351 1.13 christos for (i = 0; i < count; i++) {
3352 1.13 christos fwd = &fwds[i];
3353 1.21 christos if (code == oDynamicForward && fwd->connect_host != NULL &&
3354 1.13 christos strcmp(fwd->connect_host, "socks") != 0)
3355 1.13 christos continue;
3356 1.21 christos if (code == oLocalForward && fwd->connect_host != NULL &&
3357 1.13 christos strcmp(fwd->connect_host, "socks") == 0)
3358 1.13 christos continue;
3359 1.13 christos printf("%s", lookup_opcode_name(code));
3360 1.13 christos if (fwd->listen_port == PORT_STREAMLOCAL)
3361 1.13 christos printf(" %s", fwd->listen_path);
3362 1.13 christos else if (fwd->listen_host == NULL)
3363 1.13 christos printf(" %d", fwd->listen_port);
3364 1.13 christos else {
3365 1.13 christos printf(" [%s]:%d",
3366 1.13 christos fwd->listen_host, fwd->listen_port);
3367 1.13 christos }
3368 1.13 christos if (code != oDynamicForward) {
3369 1.13 christos if (fwd->connect_port == PORT_STREAMLOCAL)
3370 1.13 christos printf(" %s", fwd->connect_path);
3371 1.13 christos else if (fwd->connect_host == NULL)
3372 1.13 christos printf(" %d", fwd->connect_port);
3373 1.13 christos else {
3374 1.13 christos printf(" [%s]:%d",
3375 1.13 christos fwd->connect_host, fwd->connect_port);
3376 1.13 christos }
3377 1.13 christos }
3378 1.13 christos printf("\n");
3379 1.13 christos }
3380 1.13 christos }
3381 1.13 christos
3382 1.13 christos void
3383 1.13 christos dump_client_config(Options *o, const char *host)
3384 1.13 christos {
3385 1.29 christos int i, r;
3386 1.25 christos char buf[8], *all_key;
3387 1.13 christos
3388 1.29 christos /*
3389 1.29 christos * Expand HostKeyAlgorithms name lists. This isn't handled in
3390 1.29 christos * fill_default_options() like the other algorithm lists because
3391 1.29 christos * the host key algorithms are by default dynamically chosen based
3392 1.29 christos * on the host's keys found in known_hosts.
3393 1.29 christos */
3394 1.25 christos all_key = sshkey_alg_list(0, 0, 1, ',');
3395 1.29 christos if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3396 1.29 christos all_key)) != 0)
3397 1.33 christos fatal_fr(r, "expand HostKeyAlgorithms");
3398 1.25 christos free(all_key);
3399 1.18 christos
3400 1.13 christos /* Most interesting options first: user, host, port */
3401 1.13 christos dump_cfg_string(oUser, o->user);
3402 1.28 christos dump_cfg_string(oHostname, host);
3403 1.13 christos dump_cfg_int(oPort, o->port);
3404 1.13 christos
3405 1.13 christos /* Flag options */
3406 1.13 christos dump_cfg_fmtint(oAddressFamily, o->address_family);
3407 1.13 christos dump_cfg_fmtint(oBatchMode, o->batch_mode);
3408 1.13 christos dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3409 1.13 christos dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3410 1.13 christos dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3411 1.13 christos dump_cfg_fmtint(oCompression, o->compression);
3412 1.13 christos dump_cfg_fmtint(oControlMaster, o->control_master);
3413 1.13 christos dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3414 1.19 christos dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3415 1.13 christos dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3416 1.13 christos dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3417 1.13 christos dump_cfg_fmtint(oForwardX11, o->forward_x11);
3418 1.13 christos dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3419 1.13 christos dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3420 1.13 christos #ifdef GSSAPI
3421 1.13 christos dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3422 1.13 christos dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3423 1.13 christos #endif /* GSSAPI */
3424 1.13 christos dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3425 1.13 christos dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3426 1.13 christos dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3427 1.13 christos dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3428 1.13 christos dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3429 1.13 christos dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3430 1.13 christos dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3431 1.13 christos dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3432 1.13 christos dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3433 1.13 christos dump_cfg_fmtint(oRequestTTY, o->request_tty);
3434 1.35 christos dump_cfg_fmtint(oSessionType, o->session_type);
3435 1.35 christos dump_cfg_fmtint(oStdinNull, o->stdin_null);
3436 1.35 christos dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3437 1.13 christos dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3438 1.13 christos dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3439 1.13 christos dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3440 1.13 christos dump_cfg_fmtint(oTunnel, o->tun_open);
3441 1.13 christos dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3442 1.13 christos dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3443 1.13 christos dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3444 1.13 christos
3445 1.13 christos /* Integer options */
3446 1.13 christos dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3447 1.13 christos dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3448 1.13 christos dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3449 1.13 christos dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3450 1.13 christos dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3451 1.13 christos dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3452 1.13 christos
3453 1.13 christos /* String options */
3454 1.13 christos dump_cfg_string(oBindAddress, o->bind_address);
3455 1.23 christos dump_cfg_string(oBindInterface, o->bind_interface);
3456 1.29 christos dump_cfg_string(oCiphers, o->ciphers);
3457 1.13 christos dump_cfg_string(oControlPath, o->control_path);
3458 1.18 christos dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3459 1.13 christos dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3460 1.33 christos dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3461 1.19 christos dump_cfg_string(oIdentityAgent, o->identity_agent);
3462 1.25 christos dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3463 1.13 christos dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3464 1.29 christos dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3465 1.29 christos dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3466 1.13 christos dump_cfg_string(oLocalCommand, o->local_command);
3467 1.22 christos dump_cfg_string(oRemoteCommand, o->remote_command);
3468 1.13 christos dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3469 1.29 christos dump_cfg_string(oMacs, o->macs);
3470 1.21 christos #ifdef ENABLE_PKCS11
3471 1.13 christos dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3472 1.21 christos #endif
3473 1.29 christos dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3474 1.13 christos dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3475 1.33 christos dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3476 1.13 christos dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3477 1.13 christos dump_cfg_string(oXAuthLocation, o->xauth_location);
3478 1.33 christos dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3479 1.13 christos
3480 1.13 christos /* Forwards */
3481 1.13 christos dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3482 1.13 christos dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3483 1.13 christos dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3484 1.13 christos
3485 1.13 christos /* String array options */
3486 1.13 christos dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3487 1.13 christos dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3488 1.25 christos dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3489 1.13 christos dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3490 1.13 christos dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3491 1.13 christos dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3492 1.25 christos dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3493 1.33 christos dump_cfg_strarray_oneline(oLogVerbose,
3494 1.33 christos o->num_log_verbose, o->log_verbose);
3495 1.13 christos
3496 1.13 christos /* Special cases */
3497 1.13 christos
3498 1.33 christos /* PermitRemoteOpen */
3499 1.33 christos if (o->num_permitted_remote_opens == 0)
3500 1.33 christos printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3501 1.33 christos else
3502 1.33 christos dump_cfg_strarray_oneline(oPermitRemoteOpen,
3503 1.33 christos o->num_permitted_remote_opens, o->permitted_remote_opens);
3504 1.33 christos
3505 1.32 christos /* AddKeysToAgent */
3506 1.32 christos if (o->add_keys_to_agent_lifespan <= 0)
3507 1.32 christos dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3508 1.32 christos else {
3509 1.32 christos printf("addkeystoagent%s %d\n",
3510 1.32 christos o->add_keys_to_agent == 3 ? " confirm" : "",
3511 1.32 christos o->add_keys_to_agent_lifespan);
3512 1.32 christos }
3513 1.32 christos
3514 1.29 christos /* oForwardAgent */
3515 1.29 christos if (o->forward_agent_sock_path == NULL)
3516 1.29 christos dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3517 1.29 christos else
3518 1.29 christos dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3519 1.29 christos
3520 1.13 christos /* oConnectTimeout */
3521 1.13 christos if (o->connection_timeout == -1)
3522 1.13 christos printf("connecttimeout none\n");
3523 1.13 christos else
3524 1.13 christos dump_cfg_int(oConnectTimeout, o->connection_timeout);
3525 1.13 christos
3526 1.13 christos /* oTunnelDevice */
3527 1.13 christos printf("tunneldevice");
3528 1.13 christos if (o->tun_local == SSH_TUNID_ANY)
3529 1.13 christos printf(" any");
3530 1.13 christos else
3531 1.13 christos printf(" %d", o->tun_local);
3532 1.13 christos if (o->tun_remote == SSH_TUNID_ANY)
3533 1.13 christos printf(":any");
3534 1.13 christos else
3535 1.13 christos printf(":%d", o->tun_remote);
3536 1.13 christos printf("\n");
3537 1.13 christos
3538 1.13 christos /* oCanonicalizePermittedCNAMEs */
3539 1.37 christos printf("canonicalizePermittedcnames");
3540 1.37 christos if (o->num_permitted_cnames == 0)
3541 1.37 christos printf(" none");
3542 1.37 christos for (i = 0; i < o->num_permitted_cnames; i++) {
3543 1.37 christos printf(" %s:%s", o->permitted_cnames[i].source_list,
3544 1.37 christos o->permitted_cnames[i].target_list);
3545 1.13 christos }
3546 1.37 christos printf("\n");
3547 1.13 christos
3548 1.13 christos /* oControlPersist */
3549 1.13 christos if (o->control_persist == 0 || o->control_persist_timeout == 0)
3550 1.13 christos dump_cfg_fmtint(oControlPersist, o->control_persist);
3551 1.13 christos else
3552 1.13 christos dump_cfg_int(oControlPersist, o->control_persist_timeout);
3553 1.13 christos
3554 1.13 christos /* oEscapeChar */
3555 1.13 christos if (o->escape_char == SSH_ESCAPECHAR_NONE)
3556 1.13 christos printf("escapechar none\n");
3557 1.13 christos else {
3558 1.19 christos vis(buf, o->escape_char, VIS_WHITE, 0);
3559 1.19 christos printf("escapechar %s\n", buf);
3560 1.13 christos }
3561 1.13 christos
3562 1.13 christos /* oIPQoS */
3563 1.13 christos printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3564 1.13 christos printf("%s\n", iptos2str(o->ip_qos_bulk));
3565 1.13 christos
3566 1.13 christos /* oRekeyLimit */
3567 1.18 christos printf("rekeylimit %llu %d\n",
3568 1.18 christos (unsigned long long)o->rekey_limit, o->rekey_interval);
3569 1.13 christos
3570 1.13 christos /* oStreamLocalBindMask */
3571 1.13 christos printf("streamlocalbindmask 0%o\n",
3572 1.13 christos o->fwd_opts.streamlocal_bind_mask);
3573 1.19 christos
3574 1.25 christos /* oLogFacility */
3575 1.25 christos printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3576 1.25 christos
3577 1.19 christos /* oProxyCommand / oProxyJump */
3578 1.19 christos if (o->jump_host == NULL)
3579 1.19 christos dump_cfg_string(oProxyCommand, o->proxy_command);
3580 1.19 christos else {
3581 1.19 christos /* Check for numeric addresses */
3582 1.19 christos i = strchr(o->jump_host, ':') != NULL ||
3583 1.19 christos strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3584 1.19 christos snprintf(buf, sizeof(buf), "%d", o->jump_port);
3585 1.19 christos printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3586 1.19 christos /* optional additional jump spec */
3587 1.19 christos o->jump_extra == NULL ? "" : o->jump_extra,
3588 1.19 christos o->jump_extra == NULL ? "" : ",",
3589 1.19 christos /* optional user */
3590 1.19 christos o->jump_user == NULL ? "" : o->jump_user,
3591 1.19 christos o->jump_user == NULL ? "" : "@",
3592 1.19 christos /* opening [ if hostname is numeric */
3593 1.19 christos i ? "[" : "",
3594 1.19 christos /* mandatory hostname */
3595 1.19 christos o->jump_host,
3596 1.19 christos /* closing ] if hostname is numeric */
3597 1.19 christos i ? "]" : "",
3598 1.19 christos /* optional port number */
3599 1.19 christos o->jump_port <= 0 ? "" : ":",
3600 1.19 christos o->jump_port <= 0 ? "" : buf);
3601 1.19 christos }
3602 1.13 christos }
3603