readconf.c revision 1.12 1 1.11 christos /* $NetBSD: readconf.c,v 1.12 2014/10/19 16:30:58 christos Exp $ */
2 1.12 christos /* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */
3 1.1 christos /*
4 1.1 christos * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
5 1.1 christos * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
6 1.1 christos * All rights reserved
7 1.1 christos * Functions for reading the configuration files.
8 1.1 christos *
9 1.1 christos * As far as I am concerned, the code I have written for this software
10 1.1 christos * can be used freely for any purpose. Any derived versions of this
11 1.1 christos * software must be clearly marked as such, and if the derived work is
12 1.1 christos * incompatible with the protocol description in the RFC file, it must be
13 1.1 christos * called by a name other than "ssh" or "Secure Shell".
14 1.1 christos */
15 1.1 christos
16 1.2 christos #include "includes.h"
17 1.11 christos __RCSID("$NetBSD: readconf.c,v 1.12 2014/10/19 16:30:58 christos Exp $");
18 1.1 christos #include <sys/types.h>
19 1.1 christos #include <sys/stat.h>
20 1.1 christos #include <sys/socket.h>
21 1.12 christos #include <sys/wait.h>
22 1.12 christos #include <sys/un.h>
23 1.1 christos
24 1.1 christos #include <netinet/in.h>
25 1.5 christos #include <netinet/in_systm.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.1 christos #include <netdb.h>
32 1.12 christos #include <paths.h>
33 1.12 christos #include <pwd.h>
34 1.1 christos #include <signal.h>
35 1.1 christos #include <stdio.h>
36 1.1 christos #include <string.h>
37 1.1 christos #include <unistd.h>
38 1.2 christos #include <limits.h>
39 1.11 christos #include <util.h>
40 1.1 christos
41 1.1 christos #include "xmalloc.h"
42 1.1 christos #include "ssh.h"
43 1.1 christos #include "compat.h"
44 1.1 christos #include "cipher.h"
45 1.1 christos #include "pathnames.h"
46 1.1 christos #include "log.h"
47 1.1 christos #include "key.h"
48 1.12 christos #include "misc.h"
49 1.1 christos #include "readconf.h"
50 1.1 christos #include "match.h"
51 1.1 christos #include "buffer.h"
52 1.1 christos #include "kex.h"
53 1.1 christos #include "mac.h"
54 1.11 christos #include "fmt_scaled.h"
55 1.12 christos #include "uidswap.h"
56 1.1 christos
57 1.1 christos /* Format of the configuration file:
58 1.1 christos
59 1.1 christos # Configuration data is parsed as follows:
60 1.1 christos # 1. command line options
61 1.1 christos # 2. user-specific file
62 1.1 christos # 3. system-wide file
63 1.1 christos # Any configuration value is only changed the first time it is set.
64 1.1 christos # Thus, host-specific definitions should be at the beginning of the
65 1.1 christos # configuration file, and defaults at the end.
66 1.1 christos
67 1.1 christos # Host-specific declarations. These may override anything above. A single
68 1.1 christos # host may match multiple declarations; these are processed in the order
69 1.1 christos # that they are given in.
70 1.1 christos
71 1.1 christos Host *.ngs.fi ngs.fi
72 1.1 christos User foo
73 1.1 christos
74 1.1 christos Host fake.com
75 1.1 christos HostName another.host.name.real.org
76 1.1 christos User blaah
77 1.1 christos Port 34289
78 1.1 christos ForwardX11 no
79 1.1 christos ForwardAgent no
80 1.1 christos
81 1.1 christos Host books.com
82 1.1 christos RemoteForward 9999 shadows.cs.hut.fi:9999
83 1.1 christos Cipher 3des
84 1.1 christos
85 1.1 christos Host fascist.blob.com
86 1.1 christos Port 23123
87 1.1 christos User tylonen
88 1.1 christos PasswordAuthentication no
89 1.1 christos
90 1.1 christos Host puukko.hut.fi
91 1.1 christos User t35124p
92 1.1 christos ProxyCommand ssh-proxy %h %p
93 1.1 christos
94 1.1 christos Host *.fr
95 1.1 christos PublicKeyAuthentication no
96 1.1 christos
97 1.1 christos Host *.su
98 1.1 christos Cipher none
99 1.1 christos PasswordAuthentication no
100 1.1 christos
101 1.1 christos Host vpn.fake.com
102 1.1 christos Tunnel yes
103 1.1 christos TunnelDevice 3
104 1.1 christos
105 1.1 christos # Defaults for various options
106 1.1 christos Host *
107 1.1 christos ForwardAgent no
108 1.1 christos ForwardX11 no
109 1.1 christos PasswordAuthentication yes
110 1.1 christos RSAAuthentication yes
111 1.1 christos RhostsRSAAuthentication yes
112 1.1 christos StrictHostKeyChecking yes
113 1.1 christos TcpKeepAlive no
114 1.1 christos IdentityFile ~/.ssh/identity
115 1.1 christos Port 22
116 1.1 christos EscapeChar ~
117 1.1 christos
118 1.1 christos */
119 1.1 christos
120 1.1 christos /* Keyword tokens. */
121 1.1 christos
122 1.1 christos typedef enum {
123 1.1 christos oBadOption,
124 1.12 christos oHost, oMatch,
125 1.4 adam oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
126 1.4 adam oGatewayPorts, oExitOnForwardFailure,
127 1.1 christos oPasswordAuthentication, oRSAAuthentication,
128 1.1 christos oChallengeResponseAuthentication, oXAuthLocation,
129 1.2 christos #if defined(KRB4) || defined(KRB5)
130 1.2 christos oKerberosAuthentication,
131 1.2 christos #endif
132 1.2 christos #if defined(AFS) || defined(KRB5)
133 1.2 christos oKerberosTgtPassing,
134 1.2 christos #endif
135 1.2 christos #ifdef AFS
136 1.2 christos oAFSTokenPassing,
137 1.2 christos #endif
138 1.1 christos oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
139 1.12 christos oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
140 1.1 christos oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
141 1.1 christos oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
142 1.1 christos oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
143 1.1 christos oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
144 1.1 christos oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
145 1.1 christos oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
146 1.1 christos oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
147 1.4 adam oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
148 1.1 christos oClearAllForwardings, oNoHostAuthenticationForLocalhost,
149 1.1 christos oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
150 1.1 christos oAddressFamily, oGssAuthentication, oGssDelegateCreds,
151 1.1 christos oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
152 1.4 adam oSendEnv, oControlPath, oControlMaster, oControlPersist,
153 1.4 adam oHashKnownHosts,
154 1.1 christos oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
155 1.12 christos oVisualHostKey, oUseRoaming,
156 1.12 christos oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
157 1.12 christos oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
158 1.12 christos oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
159 1.12 christos oStreamLocalBindMask, oStreamLocalBindUnlink,
160 1.2 christos oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
161 1.2 christos oHPNBufferSize,
162 1.7 tls oSendVersionFirst,
163 1.12 christos oIgnoredUnknownOption, oDeprecated, oUnsupported
164 1.1 christos } OpCodes;
165 1.1 christos
166 1.1 christos /* Textual representations of the tokens. */
167 1.1 christos
168 1.1 christos static struct {
169 1.1 christos const char *name;
170 1.1 christos OpCodes opcode;
171 1.1 christos } keywords[] = {
172 1.1 christos { "forwardagent", oForwardAgent },
173 1.1 christos { "forwardx11", oForwardX11 },
174 1.1 christos { "forwardx11trusted", oForwardX11Trusted },
175 1.4 adam { "forwardx11timeout", oForwardX11Timeout },
176 1.1 christos { "exitonforwardfailure", oExitOnForwardFailure },
177 1.1 christos { "xauthlocation", oXAuthLocation },
178 1.1 christos { "gatewayports", oGatewayPorts },
179 1.1 christos { "useprivilegedport", oUsePrivilegedPort },
180 1.1 christos { "rhostsauthentication", oDeprecated },
181 1.1 christos { "passwordauthentication", oPasswordAuthentication },
182 1.1 christos { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
183 1.1 christos { "kbdinteractivedevices", oKbdInteractiveDevices },
184 1.1 christos { "rsaauthentication", oRSAAuthentication },
185 1.1 christos { "pubkeyauthentication", oPubkeyAuthentication },
186 1.1 christos { "dsaauthentication", oPubkeyAuthentication }, /* alias */
187 1.1 christos { "rhostsrsaauthentication", oRhostsRSAAuthentication },
188 1.1 christos { "hostbasedauthentication", oHostbasedAuthentication },
189 1.1 christos { "challengeresponseauthentication", oChallengeResponseAuthentication },
190 1.1 christos { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
191 1.1 christos { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
192 1.2 christos #if defined(KRB4) || defined(KRB5)
193 1.2 christos { "kerberosauthentication", oKerberosAuthentication },
194 1.2 christos #endif
195 1.2 christos #if defined(AFS) || defined(KRB5)
196 1.2 christos { "kerberostgtpassing", oKerberosTgtPassing },
197 1.2 christos { "kerberos5tgtpassing", oKerberosTgtPassing }, /* alias */
198 1.2 christos { "kerberos4tgtpassing", oKerberosTgtPassing }, /* alias */
199 1.2 christos #endif
200 1.2 christos #ifdef AFS
201 1.2 christos { "afstokenpassing", oAFSTokenPassing },
202 1.2 christos #endif
203 1.1 christos #if defined(GSSAPI)
204 1.1 christos { "gssapiauthentication", oGssAuthentication },
205 1.1 christos { "gssapidelegatecredentials", oGssDelegateCreds },
206 1.1 christos #else
207 1.1 christos { "gssapiauthentication", oUnsupported },
208 1.1 christos { "gssapidelegatecredentials", oUnsupported },
209 1.1 christos #endif
210 1.1 christos { "fallbacktorsh", oDeprecated },
211 1.1 christos { "usersh", oDeprecated },
212 1.1 christos { "identityfile", oIdentityFile },
213 1.1 christos { "identityfile2", oIdentityFile }, /* obsolete */
214 1.1 christos { "identitiesonly", oIdentitiesOnly },
215 1.1 christos { "hostname", oHostName },
216 1.1 christos { "hostkeyalias", oHostKeyAlias },
217 1.1 christos { "proxycommand", oProxyCommand },
218 1.1 christos { "port", oPort },
219 1.1 christos { "cipher", oCipher },
220 1.1 christos { "ciphers", oCiphers },
221 1.1 christos { "macs", oMacs },
222 1.1 christos { "protocol", oProtocol },
223 1.1 christos { "remoteforward", oRemoteForward },
224 1.1 christos { "localforward", oLocalForward },
225 1.1 christos { "user", oUser },
226 1.1 christos { "host", oHost },
227 1.12 christos { "match", oMatch },
228 1.1 christos { "escapechar", oEscapeChar },
229 1.1 christos { "globalknownhostsfile", oGlobalKnownHostsFile },
230 1.6 christos { "globalknownhostsfile2", oDeprecated },
231 1.1 christos { "userknownhostsfile", oUserKnownHostsFile },
232 1.6 christos { "userknownhostsfile2", oDeprecated },
233 1.1 christos { "connectionattempts", oConnectionAttempts },
234 1.1 christos { "batchmode", oBatchMode },
235 1.1 christos { "checkhostip", oCheckHostIP },
236 1.1 christos { "stricthostkeychecking", oStrictHostKeyChecking },
237 1.1 christos { "compression", oCompression },
238 1.1 christos { "compressionlevel", oCompressionLevel },
239 1.1 christos { "tcpkeepalive", oTCPKeepAlive },
240 1.1 christos { "keepalive", oTCPKeepAlive }, /* obsolete */
241 1.1 christos { "numberofpasswordprompts", oNumberOfPasswordPrompts },
242 1.1 christos { "loglevel", oLogLevel },
243 1.1 christos { "dynamicforward", oDynamicForward },
244 1.1 christos { "preferredauthentications", oPreferredAuthentications },
245 1.1 christos { "hostkeyalgorithms", oHostKeyAlgorithms },
246 1.1 christos { "bindaddress", oBindAddress },
247 1.4 adam #ifdef ENABLE_PKCS11
248 1.4 adam { "smartcarddevice", oPKCS11Provider },
249 1.4 adam { "pkcs11provider", oPKCS11Provider },
250 1.1 christos #else
251 1.1 christos { "smartcarddevice", oUnsupported },
252 1.4 adam { "pkcs11provider", oUnsupported },
253 1.1 christos #endif
254 1.1 christos { "clearallforwardings", oClearAllForwardings },
255 1.1 christos { "enablesshkeysign", oEnableSSHKeysign },
256 1.1 christos { "verifyhostkeydns", oVerifyHostKeyDNS },
257 1.1 christos { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
258 1.1 christos { "rekeylimit", oRekeyLimit },
259 1.1 christos { "connecttimeout", oConnectTimeout },
260 1.1 christos { "addressfamily", oAddressFamily },
261 1.1 christos { "serveraliveinterval", oServerAliveInterval },
262 1.1 christos { "serveralivecountmax", oServerAliveCountMax },
263 1.1 christos { "sendenv", oSendEnv },
264 1.1 christos { "controlpath", oControlPath },
265 1.1 christos { "controlmaster", oControlMaster },
266 1.4 adam { "controlpersist", oControlPersist },
267 1.1 christos { "hashknownhosts", oHashKnownHosts },
268 1.1 christos { "tunnel", oTunnel },
269 1.1 christos { "tunneldevice", oTunnelDevice },
270 1.1 christos { "localcommand", oLocalCommand },
271 1.1 christos { "permitlocalcommand", oPermitLocalCommand },
272 1.1 christos { "visualhostkey", oVisualHostKey },
273 1.3 christos { "useroaming", oUseRoaming },
274 1.5 christos { "kexalgorithms", oKexAlgorithms },
275 1.5 christos { "ipqos", oIPQoS },
276 1.6 christos { "requesttty", oRequestTTY },
277 1.12 christos { "proxyusefdpass", oProxyUseFdpass },
278 1.12 christos { "canonicaldomains", oCanonicalDomains },
279 1.12 christos { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
280 1.12 christos { "canonicalizehostname", oCanonicalizeHostname },
281 1.12 christos { "canonicalizemaxdots", oCanonicalizeMaxDots },
282 1.12 christos { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
283 1.12 christos { "streamlocalbindmask", oStreamLocalBindMask },
284 1.12 christos { "streamlocalbindunlink", oStreamLocalBindUnlink },
285 1.2 christos { "noneenabled", oNoneEnabled },
286 1.2 christos { "tcprcvbufpoll", oTcpRcvBufPoll },
287 1.2 christos { "tcprcvbuf", oTcpRcvBuf },
288 1.2 christos { "noneswitch", oNoneSwitch },
289 1.2 christos { "hpndisabled", oHPNDisabled },
290 1.2 christos { "hpnbuffersize", oHPNBufferSize },
291 1.7 tls { "sendversionfirst", oSendVersionFirst },
292 1.12 christos { "ignoreunknown", oIgnoreUnknown },
293 1.1 christos { NULL, oBadOption }
294 1.1 christos };
295 1.1 christos
296 1.1 christos /*
297 1.1 christos * Adds a local TCP/IP port forward to options. Never returns if there is an
298 1.1 christos * error.
299 1.1 christos */
300 1.1 christos
301 1.1 christos void
302 1.12 christos add_local_forward(Options *options, const struct Forward *newfwd)
303 1.1 christos {
304 1.12 christos struct Forward *fwd;
305 1.1 christos extern uid_t original_real_uid;
306 1.4 adam
307 1.12 christos if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
308 1.12 christos newfwd->listen_path == NULL)
309 1.1 christos fatal("Privileged ports can only be forwarded by root.");
310 1.4 adam options->local_forwards = xrealloc(options->local_forwards,
311 1.4 adam options->num_local_forwards + 1,
312 1.4 adam sizeof(*options->local_forwards));
313 1.1 christos fwd = &options->local_forwards[options->num_local_forwards++];
314 1.1 christos
315 1.1 christos fwd->listen_host = newfwd->listen_host;
316 1.1 christos fwd->listen_port = newfwd->listen_port;
317 1.12 christos fwd->listen_path = newfwd->listen_path;
318 1.1 christos fwd->connect_host = newfwd->connect_host;
319 1.1 christos fwd->connect_port = newfwd->connect_port;
320 1.12 christos fwd->connect_path = newfwd->connect_path;
321 1.1 christos }
322 1.1 christos
323 1.1 christos /*
324 1.1 christos * Adds a remote TCP/IP port forward to options. Never returns if there is
325 1.1 christos * an error.
326 1.1 christos */
327 1.1 christos
328 1.1 christos void
329 1.12 christos add_remote_forward(Options *options, const struct Forward *newfwd)
330 1.1 christos {
331 1.12 christos struct Forward *fwd;
332 1.4 adam
333 1.4 adam options->remote_forwards = xrealloc(options->remote_forwards,
334 1.4 adam options->num_remote_forwards + 1,
335 1.4 adam sizeof(*options->remote_forwards));
336 1.1 christos fwd = &options->remote_forwards[options->num_remote_forwards++];
337 1.1 christos
338 1.1 christos fwd->listen_host = newfwd->listen_host;
339 1.1 christos fwd->listen_port = newfwd->listen_port;
340 1.12 christos fwd->listen_path = newfwd->listen_path;
341 1.1 christos fwd->connect_host = newfwd->connect_host;
342 1.1 christos fwd->connect_port = newfwd->connect_port;
343 1.12 christos fwd->connect_path = newfwd->connect_path;
344 1.8 christos fwd->handle = newfwd->handle;
345 1.4 adam fwd->allocated_port = 0;
346 1.1 christos }
347 1.1 christos
348 1.1 christos static void
349 1.1 christos clear_forwardings(Options *options)
350 1.1 christos {
351 1.1 christos int i;
352 1.1 christos
353 1.1 christos for (i = 0; i < options->num_local_forwards; i++) {
354 1.11 christos free(options->local_forwards[i].listen_host);
355 1.12 christos free(options->local_forwards[i].listen_path);
356 1.11 christos free(options->local_forwards[i].connect_host);
357 1.12 christos free(options->local_forwards[i].connect_path);
358 1.1 christos }
359 1.4 adam if (options->num_local_forwards > 0) {
360 1.11 christos free(options->local_forwards);
361 1.4 adam options->local_forwards = NULL;
362 1.4 adam }
363 1.1 christos options->num_local_forwards = 0;
364 1.1 christos for (i = 0; i < options->num_remote_forwards; i++) {
365 1.11 christos free(options->remote_forwards[i].listen_host);
366 1.12 christos free(options->remote_forwards[i].listen_path);
367 1.11 christos free(options->remote_forwards[i].connect_host);
368 1.12 christos free(options->remote_forwards[i].connect_path);
369 1.1 christos }
370 1.4 adam if (options->num_remote_forwards > 0) {
371 1.11 christos free(options->remote_forwards);
372 1.4 adam options->remote_forwards = NULL;
373 1.4 adam }
374 1.1 christos options->num_remote_forwards = 0;
375 1.1 christos options->tun_open = SSH_TUNMODE_NO;
376 1.1 christos }
377 1.1 christos
378 1.9 mlelstv void
379 1.9 mlelstv add_identity_file(Options *options, const char *dir, const char *filename,
380 1.9 mlelstv int userprovided)
381 1.9 mlelstv {
382 1.9 mlelstv char *path;
383 1.12 christos int i;
384 1.9 mlelstv
385 1.9 mlelstv if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
386 1.9 mlelstv fatal("Too many identity files specified (max %d)",
387 1.9 mlelstv SSH_MAX_IDENTITY_FILES);
388 1.9 mlelstv
389 1.9 mlelstv if (dir == NULL) /* no dir, filename is absolute */
390 1.9 mlelstv path = xstrdup(filename);
391 1.9 mlelstv else
392 1.9 mlelstv (void)xasprintf(&path, "%.100s%.100s", dir, filename);
393 1.9 mlelstv
394 1.12 christos /* Avoid registering duplicates */
395 1.12 christos for (i = 0; i < options->num_identity_files; i++) {
396 1.12 christos if (options->identity_file_userprovided[i] == userprovided &&
397 1.12 christos strcmp(options->identity_files[i], path) == 0) {
398 1.12 christos debug2("%s: ignoring duplicate key %s", __func__, path);
399 1.12 christos free(path);
400 1.12 christos return;
401 1.12 christos }
402 1.12 christos }
403 1.12 christos
404 1.9 mlelstv options->identity_file_userprovided[options->num_identity_files] =
405 1.9 mlelstv userprovided;
406 1.9 mlelstv options->identity_files[options->num_identity_files++] = path;
407 1.9 mlelstv }
408 1.9 mlelstv
409 1.12 christos int
410 1.12 christos default_ssh_port(void)
411 1.12 christos {
412 1.12 christos static int port;
413 1.12 christos struct servent *sp;
414 1.12 christos
415 1.12 christos if (port == 0) {
416 1.12 christos sp = getservbyname(SSH_SERVICE_NAME, "tcp");
417 1.12 christos port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
418 1.12 christos }
419 1.12 christos return port;
420 1.12 christos }
421 1.12 christos
422 1.12 christos /*
423 1.12 christos * Execute a command in a shell.
424 1.12 christos * Return its exit status or -1 on abnormal exit.
425 1.12 christos */
426 1.12 christos static int
427 1.12 christos execute_in_shell(const char *cmd)
428 1.12 christos {
429 1.12 christos const char *shell;
430 1.12 christos char *command_string;
431 1.12 christos pid_t pid;
432 1.12 christos int devnull, status;
433 1.12 christos extern uid_t original_real_uid;
434 1.12 christos
435 1.12 christos if ((shell = getenv("SHELL")) == NULL)
436 1.12 christos shell = _PATH_BSHELL;
437 1.12 christos
438 1.12 christos /*
439 1.12 christos * Use "exec" to avoid "sh -c" processes on some platforms
440 1.12 christos * (e.g. Solaris)
441 1.12 christos */
442 1.12 christos xasprintf(&command_string, "exec %s", cmd);
443 1.12 christos
444 1.12 christos /* Need this to redirect subprocess stdin/out */
445 1.12 christos if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
446 1.12 christos fatal("open(/dev/null): %s", strerror(errno));
447 1.12 christos
448 1.12 christos debug("Executing command: '%.500s'", cmd);
449 1.12 christos
450 1.12 christos /* Fork and execute the command. */
451 1.12 christos if ((pid = fork()) == 0) {
452 1.12 christos char *argv[4];
453 1.12 christos
454 1.12 christos /* Child. Permanently give up superuser privileges. */
455 1.12 christos permanently_drop_suid(original_real_uid);
456 1.12 christos
457 1.12 christos /* Redirect child stdin and stdout. Leave stderr */
458 1.12 christos if (dup2(devnull, STDIN_FILENO) == -1)
459 1.12 christos fatal("dup2: %s", strerror(errno));
460 1.12 christos if (dup2(devnull, STDOUT_FILENO) == -1)
461 1.12 christos fatal("dup2: %s", strerror(errno));
462 1.12 christos if (devnull > STDERR_FILENO)
463 1.12 christos close(devnull);
464 1.12 christos closefrom(STDERR_FILENO + 1);
465 1.12 christos
466 1.12 christos argv[0] = __UNCONST(shell);
467 1.12 christos argv[1] = __UNCONST("-c");
468 1.12 christos argv[2] = command_string;
469 1.12 christos argv[3] = NULL;
470 1.12 christos
471 1.12 christos execv(argv[0], argv);
472 1.12 christos error("Unable to execute '%.100s': %s", cmd, strerror(errno));
473 1.12 christos /* Die with signal to make this error apparent to parent. */
474 1.12 christos signal(SIGTERM, SIG_DFL);
475 1.12 christos kill(getpid(), SIGTERM);
476 1.12 christos _exit(1);
477 1.12 christos }
478 1.12 christos /* Parent. */
479 1.12 christos if (pid < 0)
480 1.12 christos fatal("%s: fork: %.100s", __func__, strerror(errno));
481 1.12 christos
482 1.12 christos close(devnull);
483 1.12 christos free(command_string);
484 1.12 christos
485 1.12 christos while (waitpid(pid, &status, 0) == -1) {
486 1.12 christos if (errno != EINTR && errno != EAGAIN)
487 1.12 christos fatal("%s: waitpid: %s", __func__, strerror(errno));
488 1.12 christos }
489 1.12 christos if (!WIFEXITED(status)) {
490 1.12 christos error("command '%.100s' exited abnormally", cmd);
491 1.12 christos return -1;
492 1.12 christos }
493 1.12 christos debug3("command returned status %d", WEXITSTATUS(status));
494 1.12 christos return WEXITSTATUS(status);
495 1.12 christos }
496 1.12 christos
497 1.12 christos /*
498 1.12 christos * Parse and execute a Match directive.
499 1.12 christos */
500 1.12 christos static int
501 1.12 christos match_cfg_line(Options *options, char **condition, struct passwd *pw,
502 1.12 christos const char *host_arg, const char *filename, int linenum)
503 1.12 christos {
504 1.12 christos char *arg, *attrib, *cmd, *cp = *condition, *host;
505 1.12 christos const char *ruser;
506 1.12 christos int r, port, result = 1, attributes = 0;
507 1.12 christos size_t len;
508 1.12 christos char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
509 1.12 christos
510 1.12 christos /*
511 1.12 christos * Configuration is likely to be incomplete at this point so we
512 1.12 christos * must be prepared to use default values.
513 1.12 christos */
514 1.12 christos port = options->port <= 0 ? default_ssh_port() : options->port;
515 1.12 christos ruser = options->user == NULL ? pw->pw_name : options->user;
516 1.12 christos if (options->hostname != NULL) {
517 1.12 christos /* NB. Please keep in sync with ssh.c:main() */
518 1.12 christos host = percent_expand(options->hostname,
519 1.12 christos "h", host_arg, (char *)NULL);
520 1.12 christos } else
521 1.12 christos host = xstrdup(host_arg);
522 1.12 christos
523 1.12 christos debug3("checking match for '%s' host %s", cp, host);
524 1.12 christos while ((attrib = strdelim(&cp)) && *attrib != '\0') {
525 1.12 christos attributes++;
526 1.12 christos if (strcasecmp(attrib, "all") == 0) {
527 1.12 christos if (attributes != 1 ||
528 1.12 christos ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
529 1.12 christos error("'all' cannot be combined with other "
530 1.12 christos "Match attributes");
531 1.12 christos result = -1;
532 1.12 christos goto out;
533 1.12 christos }
534 1.12 christos *condition = cp;
535 1.12 christos result = 1;
536 1.12 christos goto out;
537 1.12 christos }
538 1.12 christos if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
539 1.12 christos error("Missing Match criteria for %s", attrib);
540 1.12 christos result = -1;
541 1.12 christos goto out;
542 1.12 christos }
543 1.12 christos len = strlen(arg);
544 1.12 christos if (strcasecmp(attrib, "host") == 0) {
545 1.12 christos if (match_hostname(host, arg, len) != 1)
546 1.12 christos result = 0;
547 1.12 christos else
548 1.12 christos debug("%.200s line %d: matched 'Host %.100s' ",
549 1.12 christos filename, linenum, host);
550 1.12 christos } else if (strcasecmp(attrib, "originalhost") == 0) {
551 1.12 christos if (match_hostname(host_arg, arg, len) != 1)
552 1.12 christos result = 0;
553 1.12 christos else
554 1.12 christos debug("%.200s line %d: matched "
555 1.12 christos "'OriginalHost %.100s' ",
556 1.12 christos filename, linenum, host_arg);
557 1.12 christos } else if (strcasecmp(attrib, "user") == 0) {
558 1.12 christos if (match_pattern_list(ruser, arg, len, 0) != 1)
559 1.12 christos result = 0;
560 1.12 christos else
561 1.12 christos debug("%.200s line %d: matched 'User %.100s' ",
562 1.12 christos filename, linenum, ruser);
563 1.12 christos } else if (strcasecmp(attrib, "localuser") == 0) {
564 1.12 christos if (match_pattern_list(pw->pw_name, arg, len, 0) != 1)
565 1.12 christos result = 0;
566 1.12 christos else
567 1.12 christos debug("%.200s line %d: matched "
568 1.12 christos "'LocalUser %.100s' ",
569 1.12 christos filename, linenum, pw->pw_name);
570 1.12 christos } else if (strcasecmp(attrib, "exec") == 0) {
571 1.12 christos if (gethostname(thishost, sizeof(thishost)) == -1)
572 1.12 christos fatal("gethostname: %s", strerror(errno));
573 1.12 christos strlcpy(shorthost, thishost, sizeof(shorthost));
574 1.12 christos shorthost[strcspn(thishost, ".")] = '\0';
575 1.12 christos snprintf(portstr, sizeof(portstr), "%d", port);
576 1.12 christos
577 1.12 christos cmd = percent_expand(arg,
578 1.12 christos "L", shorthost,
579 1.12 christos "d", pw->pw_dir,
580 1.12 christos "h", host,
581 1.12 christos "l", thishost,
582 1.12 christos "n", host_arg,
583 1.12 christos "p", portstr,
584 1.12 christos "r", ruser,
585 1.12 christos "u", pw->pw_name,
586 1.12 christos (char *)NULL);
587 1.12 christos if (result != 1) {
588 1.12 christos /* skip execution if prior predicate failed */
589 1.12 christos debug("%.200s line %d: skipped exec \"%.100s\"",
590 1.12 christos filename, linenum, cmd);
591 1.12 christos } else {
592 1.12 christos r = execute_in_shell(cmd);
593 1.12 christos if (r == -1) {
594 1.12 christos fatal("%.200s line %d: match exec "
595 1.12 christos "'%.100s' error", filename,
596 1.12 christos linenum, cmd);
597 1.12 christos } else if (r == 0) {
598 1.12 christos debug("%.200s line %d: matched "
599 1.12 christos "'exec \"%.100s\"'", filename,
600 1.12 christos linenum, cmd);
601 1.12 christos } else {
602 1.12 christos debug("%.200s line %d: no match "
603 1.12 christos "'exec \"%.100s\"'", filename,
604 1.12 christos linenum, cmd);
605 1.12 christos result = 0;
606 1.12 christos }
607 1.12 christos }
608 1.12 christos free(cmd);
609 1.12 christos } else {
610 1.12 christos error("Unsupported Match attribute %s", attrib);
611 1.12 christos result = -1;
612 1.12 christos goto out;
613 1.12 christos }
614 1.12 christos }
615 1.12 christos if (attributes == 0) {
616 1.12 christos error("One or more attributes required for Match");
617 1.12 christos result = -1;
618 1.12 christos goto out;
619 1.12 christos }
620 1.12 christos debug3("match %sfound", result ? "" : "not ");
621 1.12 christos *condition = cp;
622 1.12 christos out:
623 1.12 christos free(host);
624 1.12 christos return result;
625 1.12 christos }
626 1.12 christos
627 1.12 christos /* Check and prepare a domain name: removes trailing '.' and lowercases */
628 1.12 christos static void
629 1.12 christos valid_domain(char *name, const char *filename, int linenum)
630 1.12 christos {
631 1.12 christos size_t i, l = strlen(name);
632 1.12 christos u_char c, last = '\0';
633 1.12 christos
634 1.12 christos if (l == 0)
635 1.12 christos fatal("%s line %d: empty hostname suffix", filename, linenum);
636 1.12 christos if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
637 1.12 christos fatal("%s line %d: hostname suffix \"%.100s\" "
638 1.12 christos "starts with invalid character", filename, linenum, name);
639 1.12 christos for (i = 0; i < l; i++) {
640 1.12 christos c = tolower((u_char)name[i]);
641 1.12 christos name[i] = (char)c;
642 1.12 christos if (last == '.' && c == '.')
643 1.12 christos fatal("%s line %d: hostname suffix \"%.100s\" contains "
644 1.12 christos "consecutive separators", filename, linenum, name);
645 1.12 christos if (c != '.' && c != '-' && !isalnum(c) &&
646 1.12 christos c != '_') /* technically invalid, but common */
647 1.12 christos fatal("%s line %d: hostname suffix \"%.100s\" contains "
648 1.12 christos "invalid characters", filename, linenum, name);
649 1.12 christos last = c;
650 1.12 christos }
651 1.12 christos if (name[l - 1] == '.')
652 1.12 christos name[l - 1] = '\0';
653 1.12 christos }
654 1.12 christos
655 1.1 christos /*
656 1.1 christos * Returns the number of the token pointed to by cp or oBadOption.
657 1.1 christos */
658 1.1 christos static OpCodes
659 1.11 christos parse_token(const char *cp, const char *filename, int linenum,
660 1.11 christos const char *ignored_unknown)
661 1.1 christos {
662 1.11 christos int i;
663 1.1 christos
664 1.1 christos for (i = 0; keywords[i].name; i++)
665 1.11 christos if (strcmp(cp, keywords[i].name) == 0)
666 1.1 christos return keywords[i].opcode;
667 1.11 christos if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
668 1.11 christos strlen(ignored_unknown), 1) == 1)
669 1.11 christos return oIgnoredUnknownOption;
670 1.1 christos error("%s: line %d: Bad configuration option: %s",
671 1.1 christos filename, linenum, cp);
672 1.1 christos return oBadOption;
673 1.1 christos }
674 1.1 christos
675 1.12 christos /* Multistate option parsing */
676 1.12 christos struct multistate {
677 1.12 christos const char *key;
678 1.12 christos int value;
679 1.12 christos };
680 1.12 christos static const struct multistate multistate_flag[] = {
681 1.12 christos { "true", 1 },
682 1.12 christos { "false", 0 },
683 1.12 christos { "yes", 1 },
684 1.12 christos { "no", 0 },
685 1.12 christos { NULL, -1 }
686 1.12 christos };
687 1.12 christos static const struct multistate multistate_yesnoask[] = {
688 1.12 christos { "true", 1 },
689 1.12 christos { "false", 0 },
690 1.12 christos { "yes", 1 },
691 1.12 christos { "no", 0 },
692 1.12 christos { "ask", 2 },
693 1.12 christos { NULL, -1 }
694 1.12 christos };
695 1.12 christos static const struct multistate multistate_addressfamily[] = {
696 1.12 christos { "inet", AF_INET },
697 1.12 christos { "inet6", AF_INET6 },
698 1.12 christos { "any", AF_UNSPEC },
699 1.12 christos { NULL, -1 }
700 1.12 christos };
701 1.12 christos static const struct multistate multistate_controlmaster[] = {
702 1.12 christos { "true", SSHCTL_MASTER_YES },
703 1.12 christos { "yes", SSHCTL_MASTER_YES },
704 1.12 christos { "false", SSHCTL_MASTER_NO },
705 1.12 christos { "no", SSHCTL_MASTER_NO },
706 1.12 christos { "auto", SSHCTL_MASTER_AUTO },
707 1.12 christos { "ask", SSHCTL_MASTER_ASK },
708 1.12 christos { "autoask", SSHCTL_MASTER_AUTO_ASK },
709 1.12 christos { NULL, -1 }
710 1.12 christos };
711 1.12 christos static const struct multistate multistate_tunnel[] = {
712 1.12 christos { "ethernet", SSH_TUNMODE_ETHERNET },
713 1.12 christos { "point-to-point", SSH_TUNMODE_POINTOPOINT },
714 1.12 christos { "true", SSH_TUNMODE_DEFAULT },
715 1.12 christos { "yes", SSH_TUNMODE_DEFAULT },
716 1.12 christos { "false", SSH_TUNMODE_NO },
717 1.12 christos { "no", SSH_TUNMODE_NO },
718 1.12 christos { NULL, -1 }
719 1.12 christos };
720 1.12 christos static const struct multistate multistate_requesttty[] = {
721 1.12 christos { "true", REQUEST_TTY_YES },
722 1.12 christos { "yes", REQUEST_TTY_YES },
723 1.12 christos { "false", REQUEST_TTY_NO },
724 1.12 christos { "no", REQUEST_TTY_NO },
725 1.12 christos { "force", REQUEST_TTY_FORCE },
726 1.12 christos { "auto", REQUEST_TTY_AUTO },
727 1.12 christos { NULL, -1 }
728 1.12 christos };
729 1.12 christos static const struct multistate multistate_canonicalizehostname[] = {
730 1.12 christos { "true", SSH_CANONICALISE_YES },
731 1.12 christos { "false", SSH_CANONICALISE_NO },
732 1.12 christos { "yes", SSH_CANONICALISE_YES },
733 1.12 christos { "no", SSH_CANONICALISE_NO },
734 1.12 christos { "always", SSH_CANONICALISE_ALWAYS },
735 1.12 christos { NULL, -1 }
736 1.12 christos };
737 1.12 christos
738 1.1 christos /*
739 1.1 christos * Processes a single option line as used in the configuration files. This
740 1.1 christos * only sets those values that have not already been set.
741 1.1 christos */
742 1.1 christos #define WHITESPACE " \t\r\n"
743 1.1 christos int
744 1.12 christos process_config_line(Options *options, struct passwd *pw, const char *host,
745 1.12 christos char *line, const char *filename, int linenum, int *activep, int userconfig)
746 1.1 christos {
747 1.6 christos char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
748 1.6 christos char **cpptr, fwdarg[256];
749 1.11 christos u_int i, *uintptr, max_entries = 0;
750 1.12 christos int negated, opcode, *intptr, value, value2, cmdline = 0;
751 1.1 christos LogLevel *log_level_ptr;
752 1.11 christos long long val64;
753 1.1 christos size_t len;
754 1.12 christos struct Forward fwd;
755 1.12 christos const struct multistate *multistate_ptr;
756 1.12 christos struct allowed_cname *cname;
757 1.12 christos
758 1.12 christos if (activep == NULL) { /* We are processing a command line directive */
759 1.12 christos cmdline = 1;
760 1.12 christos activep = &cmdline;
761 1.12 christos }
762 1.1 christos
763 1.1 christos /* Strip trailing whitespace */
764 1.1 christos for (len = strlen(line) - 1; len > 0; len--) {
765 1.1 christos if (strchr(WHITESPACE, line[len]) == NULL)
766 1.1 christos break;
767 1.1 christos line[len] = '\0';
768 1.1 christos }
769 1.1 christos
770 1.1 christos s = line;
771 1.1 christos /* Get the keyword. (Each line is supposed to begin with a keyword). */
772 1.1 christos if ((keyword = strdelim(&s)) == NULL)
773 1.1 christos return 0;
774 1.1 christos /* Ignore leading whitespace. */
775 1.1 christos if (*keyword == '\0')
776 1.1 christos keyword = strdelim(&s);
777 1.1 christos if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
778 1.1 christos return 0;
779 1.11 christos /* Match lowercase keyword */
780 1.12 christos lowercase(keyword);
781 1.1 christos
782 1.11 christos opcode = parse_token(keyword, filename, linenum,
783 1.11 christos options->ignored_unknown);
784 1.1 christos
785 1.1 christos switch (opcode) {
786 1.1 christos case oBadOption:
787 1.1 christos /* don't panic, but count bad options */
788 1.1 christos return -1;
789 1.1 christos /* NOTREACHED */
790 1.11 christos case oIgnoredUnknownOption:
791 1.11 christos debug("%s line %d: Ignored unknown option \"%s\"",
792 1.11 christos filename, linenum, keyword);
793 1.11 christos return 0;
794 1.1 christos case oConnectTimeout:
795 1.1 christos intptr = &options->connection_timeout;
796 1.1 christos parse_time:
797 1.1 christos arg = strdelim(&s);
798 1.1 christos if (!arg || *arg == '\0')
799 1.1 christos fatal("%s line %d: missing time value.",
800 1.1 christos filename, linenum);
801 1.1 christos if ((value = convtime(arg)) == -1)
802 1.1 christos fatal("%s line %d: invalid time value.",
803 1.1 christos filename, linenum);
804 1.1 christos if (*activep && *intptr == -1)
805 1.1 christos *intptr = value;
806 1.1 christos break;
807 1.1 christos
808 1.1 christos case oForwardAgent:
809 1.1 christos intptr = &options->forward_agent;
810 1.12 christos parse_flag:
811 1.12 christos multistate_ptr = multistate_flag;
812 1.12 christos parse_multistate:
813 1.1 christos arg = strdelim(&s);
814 1.1 christos if (!arg || *arg == '\0')
815 1.12 christos fatal("%s line %d: missing argument.",
816 1.12 christos filename, linenum);
817 1.12 christos value = -1;
818 1.12 christos for (i = 0; multistate_ptr[i].key != NULL; i++) {
819 1.12 christos if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
820 1.12 christos value = multistate_ptr[i].value;
821 1.12 christos break;
822 1.12 christos }
823 1.12 christos }
824 1.12 christos if (value == -1)
825 1.12 christos fatal("%s line %d: unsupported option \"%s\".",
826 1.12 christos filename, linenum, arg);
827 1.1 christos if (*activep && *intptr == -1)
828 1.1 christos *intptr = value;
829 1.1 christos break;
830 1.1 christos
831 1.1 christos case oForwardX11:
832 1.1 christos intptr = &options->forward_x11;
833 1.1 christos goto parse_flag;
834 1.1 christos
835 1.1 christos case oForwardX11Trusted:
836 1.1 christos intptr = &options->forward_x11_trusted;
837 1.1 christos goto parse_flag;
838 1.4 adam
839 1.4 adam case oForwardX11Timeout:
840 1.4 adam intptr = &options->forward_x11_timeout;
841 1.4 adam goto parse_time;
842 1.1 christos
843 1.1 christos case oGatewayPorts:
844 1.12 christos intptr = &options->fwd_opts.gateway_ports;
845 1.1 christos goto parse_flag;
846 1.1 christos
847 1.1 christos case oExitOnForwardFailure:
848 1.1 christos intptr = &options->exit_on_forward_failure;
849 1.1 christos goto parse_flag;
850 1.1 christos
851 1.1 christos case oUsePrivilegedPort:
852 1.1 christos intptr = &options->use_privileged_port;
853 1.1 christos goto parse_flag;
854 1.1 christos
855 1.1 christos case oPasswordAuthentication:
856 1.1 christos intptr = &options->password_authentication;
857 1.1 christos goto parse_flag;
858 1.1 christos
859 1.1 christos case oKbdInteractiveAuthentication:
860 1.1 christos intptr = &options->kbd_interactive_authentication;
861 1.1 christos goto parse_flag;
862 1.1 christos
863 1.1 christos case oKbdInteractiveDevices:
864 1.1 christos charptr = &options->kbd_interactive_devices;
865 1.1 christos goto parse_string;
866 1.1 christos
867 1.1 christos case oPubkeyAuthentication:
868 1.1 christos intptr = &options->pubkey_authentication;
869 1.1 christos goto parse_flag;
870 1.1 christos
871 1.1 christos case oRSAAuthentication:
872 1.1 christos intptr = &options->rsa_authentication;
873 1.1 christos goto parse_flag;
874 1.1 christos
875 1.1 christos case oRhostsRSAAuthentication:
876 1.1 christos intptr = &options->rhosts_rsa_authentication;
877 1.1 christos goto parse_flag;
878 1.1 christos
879 1.1 christos case oHostbasedAuthentication:
880 1.1 christos intptr = &options->hostbased_authentication;
881 1.1 christos goto parse_flag;
882 1.1 christos
883 1.1 christos case oChallengeResponseAuthentication:
884 1.1 christos intptr = &options->challenge_response_authentication;
885 1.1 christos goto parse_flag;
886 1.1 christos
887 1.2 christos #if defined(KRB4) || defined(KRB5)
888 1.2 christos case oKerberosAuthentication:
889 1.2 christos intptr = &options->kerberos_authentication;
890 1.2 christos goto parse_flag;
891 1.2 christos #endif
892 1.2 christos #if defined(AFS) || defined(KRB5)
893 1.2 christos case oKerberosTgtPassing:
894 1.2 christos intptr = &options->kerberos_tgt_passing;
895 1.2 christos goto parse_flag;
896 1.2 christos #endif
897 1.2 christos
898 1.1 christos case oGssAuthentication:
899 1.1 christos intptr = &options->gss_authentication;
900 1.1 christos goto parse_flag;
901 1.1 christos
902 1.2 christos #ifdef AFS
903 1.2 christos case oAFSTokenPassing:
904 1.2 christos intptr = &options->afs_token_passing;
905 1.2 christos goto parse_flag;
906 1.2 christos #endif
907 1.2 christos
908 1.1 christos case oGssDelegateCreds:
909 1.1 christos intptr = &options->gss_deleg_creds;
910 1.1 christos goto parse_flag;
911 1.1 christos
912 1.1 christos case oBatchMode:
913 1.1 christos intptr = &options->batch_mode;
914 1.1 christos goto parse_flag;
915 1.1 christos
916 1.1 christos case oCheckHostIP:
917 1.1 christos intptr = &options->check_host_ip;
918 1.1 christos goto parse_flag;
919 1.1 christos
920 1.2 christos case oNoneEnabled:
921 1.2 christos intptr = &options->none_enabled;
922 1.2 christos goto parse_flag;
923 1.2 christos
924 1.2 christos /* we check to see if the command comes from the */
925 1.2 christos /* command line or not. If it does then enable it */
926 1.2 christos /* otherwise fail. NONE should never be a default configuration */
927 1.2 christos case oNoneSwitch:
928 1.2 christos if(strcmp(filename,"command-line")==0)
929 1.2 christos {
930 1.2 christos intptr = &options->none_switch;
931 1.2 christos goto parse_flag;
932 1.2 christos } else {
933 1.2 christos error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
934 1.2 christos error("Continuing...");
935 1.2 christos debug("NoneSwitch directive found in %.200s.", filename);
936 1.2 christos return 0;
937 1.2 christos }
938 1.2 christos
939 1.2 christos case oHPNDisabled:
940 1.2 christos intptr = &options->hpn_disabled;
941 1.2 christos goto parse_flag;
942 1.2 christos
943 1.2 christos case oHPNBufferSize:
944 1.2 christos intptr = &options->hpn_buffer_size;
945 1.2 christos goto parse_int;
946 1.2 christos
947 1.2 christos case oTcpRcvBufPoll:
948 1.2 christos intptr = &options->tcp_rcv_buf_poll;
949 1.2 christos goto parse_flag;
950 1.2 christos
951 1.1 christos case oVerifyHostKeyDNS:
952 1.1 christos intptr = &options->verify_host_key_dns;
953 1.12 christos multistate_ptr = multistate_yesnoask;
954 1.12 christos goto parse_multistate;
955 1.1 christos
956 1.1 christos case oStrictHostKeyChecking:
957 1.1 christos intptr = &options->strict_host_key_checking;
958 1.12 christos multistate_ptr = multistate_yesnoask;
959 1.12 christos goto parse_multistate;
960 1.1 christos
961 1.1 christos case oCompression:
962 1.1 christos intptr = &options->compression;
963 1.1 christos goto parse_flag;
964 1.1 christos
965 1.1 christos case oTCPKeepAlive:
966 1.1 christos intptr = &options->tcp_keep_alive;
967 1.1 christos goto parse_flag;
968 1.1 christos
969 1.1 christos case oNoHostAuthenticationForLocalhost:
970 1.1 christos intptr = &options->no_host_authentication_for_localhost;
971 1.1 christos goto parse_flag;
972 1.1 christos
973 1.1 christos case oNumberOfPasswordPrompts:
974 1.1 christos intptr = &options->number_of_password_prompts;
975 1.1 christos goto parse_int;
976 1.1 christos
977 1.1 christos case oCompressionLevel:
978 1.1 christos intptr = &options->compression_level;
979 1.1 christos goto parse_int;
980 1.1 christos
981 1.1 christos case oRekeyLimit:
982 1.1 christos arg = strdelim(&s);
983 1.1 christos if (!arg || *arg == '\0')
984 1.11 christos fatal("%.200s line %d: Missing argument.", filename,
985 1.11 christos linenum);
986 1.11 christos if (strcmp(arg, "default") == 0) {
987 1.11 christos val64 = 0;
988 1.11 christos } else {
989 1.11 christos if (scan_scaled(arg, &val64) == -1)
990 1.11 christos fatal("%.200s line %d: Bad number '%s': %s",
991 1.11 christos filename, linenum, arg, strerror(errno));
992 1.11 christos /* check for too-large or too-small limits */
993 1.11 christos if (val64 > UINT_MAX)
994 1.11 christos fatal("%.200s line %d: RekeyLimit too large",
995 1.11 christos filename, linenum);
996 1.11 christos if (val64 != 0 && val64 < 16)
997 1.11 christos fatal("%.200s line %d: RekeyLimit too small",
998 1.11 christos filename, linenum);
999 1.1 christos }
1000 1.1 christos if (*activep && options->rekey_limit == -1)
1001 1.1 christos options->rekey_limit = (u_int32_t)val64;
1002 1.11 christos if (s != NULL) { /* optional rekey interval present */
1003 1.11 christos if (strcmp(s, "none") == 0) {
1004 1.11 christos (void)strdelim(&s); /* discard */
1005 1.11 christos break;
1006 1.11 christos }
1007 1.11 christos intptr = &options->rekey_interval;
1008 1.11 christos goto parse_time;
1009 1.11 christos }
1010 1.1 christos break;
1011 1.1 christos
1012 1.1 christos case oIdentityFile:
1013 1.1 christos arg = strdelim(&s);
1014 1.1 christos if (!arg || *arg == '\0')
1015 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1016 1.1 christos if (*activep) {
1017 1.1 christos intptr = &options->num_identity_files;
1018 1.1 christos if (*intptr >= SSH_MAX_IDENTITY_FILES)
1019 1.1 christos fatal("%.200s line %d: Too many identity files specified (max %d).",
1020 1.1 christos filename, linenum, SSH_MAX_IDENTITY_FILES);
1021 1.9 mlelstv add_identity_file(options, NULL, arg, userconfig);
1022 1.1 christos }
1023 1.1 christos break;
1024 1.1 christos
1025 1.1 christos case oXAuthLocation:
1026 1.1 christos charptr=&options->xauth_location;
1027 1.1 christos goto parse_string;
1028 1.1 christos
1029 1.1 christos case oUser:
1030 1.1 christos charptr = &options->user;
1031 1.1 christos parse_string:
1032 1.1 christos arg = strdelim(&s);
1033 1.1 christos if (!arg || *arg == '\0')
1034 1.6 christos fatal("%.200s line %d: Missing argument.",
1035 1.6 christos filename, linenum);
1036 1.1 christos if (*activep && *charptr == NULL)
1037 1.1 christos *charptr = xstrdup(arg);
1038 1.1 christos break;
1039 1.1 christos
1040 1.1 christos case oGlobalKnownHostsFile:
1041 1.6 christos cpptr = (char **)&options->system_hostfiles;
1042 1.6 christos uintptr = &options->num_system_hostfiles;
1043 1.6 christos max_entries = SSH_MAX_HOSTS_FILES;
1044 1.6 christos parse_char_array:
1045 1.6 christos if (*activep && *uintptr == 0) {
1046 1.6 christos while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1047 1.6 christos if ((*uintptr) >= max_entries)
1048 1.6 christos fatal("%s line %d: "
1049 1.6 christos "too many authorized keys files.",
1050 1.6 christos filename, linenum);
1051 1.6 christos cpptr[(*uintptr)++] = xstrdup(arg);
1052 1.6 christos }
1053 1.6 christos }
1054 1.6 christos return 0;
1055 1.1 christos
1056 1.1 christos case oUserKnownHostsFile:
1057 1.6 christos cpptr = (char **)&options->user_hostfiles;
1058 1.6 christos uintptr = &options->num_user_hostfiles;
1059 1.6 christos max_entries = SSH_MAX_HOSTS_FILES;
1060 1.6 christos goto parse_char_array;
1061 1.1 christos
1062 1.1 christos case oHostName:
1063 1.1 christos charptr = &options->hostname;
1064 1.1 christos goto parse_string;
1065 1.1 christos
1066 1.1 christos case oHostKeyAlias:
1067 1.1 christos charptr = &options->host_key_alias;
1068 1.1 christos goto parse_string;
1069 1.1 christos
1070 1.1 christos case oPreferredAuthentications:
1071 1.1 christos charptr = &options->preferred_authentications;
1072 1.1 christos goto parse_string;
1073 1.1 christos
1074 1.1 christos case oBindAddress:
1075 1.1 christos charptr = &options->bind_address;
1076 1.1 christos goto parse_string;
1077 1.1 christos
1078 1.4 adam case oPKCS11Provider:
1079 1.4 adam charptr = &options->pkcs11_provider;
1080 1.1 christos goto parse_string;
1081 1.1 christos
1082 1.1 christos case oProxyCommand:
1083 1.1 christos charptr = &options->proxy_command;
1084 1.1 christos parse_command:
1085 1.1 christos if (s == NULL)
1086 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1087 1.1 christos len = strspn(s, WHITESPACE "=");
1088 1.1 christos if (*activep && *charptr == NULL)
1089 1.1 christos *charptr = xstrdup(s + len);
1090 1.1 christos return 0;
1091 1.1 christos
1092 1.1 christos case oPort:
1093 1.1 christos intptr = &options->port;
1094 1.1 christos parse_int:
1095 1.1 christos arg = strdelim(&s);
1096 1.1 christos if (!arg || *arg == '\0')
1097 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1098 1.1 christos if (arg[0] < '0' || arg[0] > '9')
1099 1.1 christos fatal("%.200s line %d: Bad number.", filename, linenum);
1100 1.1 christos
1101 1.1 christos /* Octal, decimal, or hex format? */
1102 1.1 christos value = strtol(arg, &endofnumber, 0);
1103 1.1 christos if (arg == endofnumber)
1104 1.1 christos fatal("%.200s line %d: Bad number.", filename, linenum);
1105 1.1 christos if (*activep && *intptr == -1)
1106 1.1 christos *intptr = value;
1107 1.1 christos break;
1108 1.1 christos
1109 1.1 christos case oConnectionAttempts:
1110 1.1 christos intptr = &options->connection_attempts;
1111 1.1 christos goto parse_int;
1112 1.1 christos
1113 1.2 christos case oTcpRcvBuf:
1114 1.2 christos intptr = &options->tcp_rcv_buf;
1115 1.2 christos goto parse_int;
1116 1.2 christos
1117 1.1 christos case oCipher:
1118 1.1 christos intptr = &options->cipher;
1119 1.1 christos arg = strdelim(&s);
1120 1.1 christos if (!arg || *arg == '\0')
1121 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1122 1.1 christos value = cipher_number(arg);
1123 1.1 christos if (value == -1)
1124 1.1 christos fatal("%.200s line %d: Bad cipher '%s'.",
1125 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1126 1.1 christos if (*activep && *intptr == -1)
1127 1.1 christos *intptr = value;
1128 1.1 christos break;
1129 1.1 christos
1130 1.1 christos case oCiphers:
1131 1.1 christos arg = strdelim(&s);
1132 1.1 christos if (!arg || *arg == '\0')
1133 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1134 1.1 christos if (!ciphers_valid(arg))
1135 1.1 christos fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1136 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1137 1.1 christos if (*activep && options->ciphers == NULL)
1138 1.1 christos options->ciphers = xstrdup(arg);
1139 1.1 christos break;
1140 1.1 christos
1141 1.1 christos case oMacs:
1142 1.1 christos arg = strdelim(&s);
1143 1.1 christos if (!arg || *arg == '\0')
1144 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1145 1.1 christos if (!mac_valid(arg))
1146 1.1 christos fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1147 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1148 1.1 christos if (*activep && options->macs == NULL)
1149 1.1 christos options->macs = xstrdup(arg);
1150 1.1 christos break;
1151 1.1 christos
1152 1.5 christos case oKexAlgorithms:
1153 1.5 christos arg = strdelim(&s);
1154 1.5 christos if (!arg || *arg == '\0')
1155 1.5 christos fatal("%.200s line %d: Missing argument.",
1156 1.5 christos filename, linenum);
1157 1.5 christos if (!kex_names_valid(arg))
1158 1.5 christos fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1159 1.5 christos filename, linenum, arg ? arg : "<NONE>");
1160 1.5 christos if (*activep && options->kex_algorithms == NULL)
1161 1.5 christos options->kex_algorithms = xstrdup(arg);
1162 1.5 christos break;
1163 1.5 christos
1164 1.1 christos case oHostKeyAlgorithms:
1165 1.1 christos arg = strdelim(&s);
1166 1.1 christos if (!arg || *arg == '\0')
1167 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1168 1.1 christos if (!key_names_valid2(arg))
1169 1.1 christos fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
1170 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1171 1.1 christos if (*activep && options->hostkeyalgorithms == NULL)
1172 1.1 christos options->hostkeyalgorithms = xstrdup(arg);
1173 1.1 christos break;
1174 1.1 christos
1175 1.1 christos case oProtocol:
1176 1.1 christos intptr = &options->protocol;
1177 1.1 christos arg = strdelim(&s);
1178 1.1 christos if (!arg || *arg == '\0')
1179 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1180 1.1 christos value = proto_spec(arg);
1181 1.1 christos if (value == SSH_PROTO_UNKNOWN)
1182 1.1 christos fatal("%.200s line %d: Bad protocol spec '%s'.",
1183 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1184 1.1 christos if (*activep && *intptr == SSH_PROTO_UNKNOWN)
1185 1.1 christos *intptr = value;
1186 1.1 christos break;
1187 1.1 christos
1188 1.1 christos case oLogLevel:
1189 1.1 christos log_level_ptr = &options->log_level;
1190 1.1 christos arg = strdelim(&s);
1191 1.1 christos value = log_level_number(arg);
1192 1.1 christos if (value == SYSLOG_LEVEL_NOT_SET)
1193 1.1 christos fatal("%.200s line %d: unsupported log level '%s'",
1194 1.1 christos filename, linenum, arg ? arg : "<NONE>");
1195 1.1 christos if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1196 1.1 christos *log_level_ptr = (LogLevel) value;
1197 1.1 christos break;
1198 1.1 christos
1199 1.1 christos case oLocalForward:
1200 1.1 christos case oRemoteForward:
1201 1.1 christos case oDynamicForward:
1202 1.1 christos arg = strdelim(&s);
1203 1.1 christos if (arg == NULL || *arg == '\0')
1204 1.1 christos fatal("%.200s line %d: Missing port argument.",
1205 1.1 christos filename, linenum);
1206 1.1 christos
1207 1.1 christos if (opcode == oLocalForward ||
1208 1.1 christos opcode == oRemoteForward) {
1209 1.1 christos arg2 = strdelim(&s);
1210 1.1 christos if (arg2 == NULL || *arg2 == '\0')
1211 1.1 christos fatal("%.200s line %d: Missing target argument.",
1212 1.1 christos filename, linenum);
1213 1.1 christos
1214 1.1 christos /* construct a string for parse_forward */
1215 1.1 christos snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
1216 1.1 christos } else if (opcode == oDynamicForward) {
1217 1.1 christos strlcpy(fwdarg, arg, sizeof(fwdarg));
1218 1.1 christos }
1219 1.1 christos
1220 1.1 christos if (parse_forward(&fwd, fwdarg,
1221 1.1 christos opcode == oDynamicForward ? 1 : 0,
1222 1.1 christos opcode == oRemoteForward ? 1 : 0) == 0)
1223 1.1 christos fatal("%.200s line %d: Bad forwarding specification.",
1224 1.1 christos filename, linenum);
1225 1.1 christos
1226 1.1 christos if (*activep) {
1227 1.1 christos if (opcode == oLocalForward ||
1228 1.1 christos opcode == oDynamicForward)
1229 1.1 christos add_local_forward(options, &fwd);
1230 1.1 christos else if (opcode == oRemoteForward)
1231 1.1 christos add_remote_forward(options, &fwd);
1232 1.1 christos }
1233 1.1 christos break;
1234 1.1 christos
1235 1.1 christos case oClearAllForwardings:
1236 1.1 christos intptr = &options->clear_forwardings;
1237 1.1 christos goto parse_flag;
1238 1.1 christos
1239 1.1 christos case oHost:
1240 1.12 christos if (cmdline)
1241 1.12 christos fatal("Host directive not supported as a command-line "
1242 1.12 christos "option");
1243 1.1 christos *activep = 0;
1244 1.6 christos arg2 = NULL;
1245 1.6 christos while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1246 1.6 christos negated = *arg == '!';
1247 1.6 christos if (negated)
1248 1.6 christos arg++;
1249 1.1 christos if (match_pattern(host, arg)) {
1250 1.6 christos if (negated) {
1251 1.6 christos debug("%.200s line %d: Skipping Host "
1252 1.6 christos "block because of negated match "
1253 1.6 christos "for %.100s", filename, linenum,
1254 1.6 christos arg);
1255 1.6 christos *activep = 0;
1256 1.6 christos break;
1257 1.6 christos }
1258 1.6 christos if (!*activep)
1259 1.6 christos arg2 = arg; /* logged below */
1260 1.1 christos *activep = 1;
1261 1.1 christos }
1262 1.6 christos }
1263 1.6 christos if (*activep)
1264 1.6 christos debug("%.200s line %d: Applying options for %.100s",
1265 1.6 christos filename, linenum, arg2);
1266 1.1 christos /* Avoid garbage check below, as strdelim is done. */
1267 1.1 christos return 0;
1268 1.1 christos
1269 1.12 christos case oMatch:
1270 1.12 christos if (cmdline)
1271 1.12 christos fatal("Host directive not supported as a command-line "
1272 1.12 christos "option");
1273 1.12 christos value = match_cfg_line(options, &s, pw, host,
1274 1.12 christos filename, linenum);
1275 1.12 christos if (value < 0)
1276 1.12 christos fatal("%.200s line %d: Bad Match condition", filename,
1277 1.12 christos linenum);
1278 1.12 christos *activep = value;
1279 1.12 christos break;
1280 1.12 christos
1281 1.1 christos case oEscapeChar:
1282 1.1 christos intptr = &options->escape_char;
1283 1.1 christos arg = strdelim(&s);
1284 1.1 christos if (!arg || *arg == '\0')
1285 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1286 1.2 christos value = 0; /* To avoid compiler warning... */
1287 1.1 christos if (arg[0] == '^' && arg[2] == 0 &&
1288 1.1 christos (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1289 1.1 christos value = (u_char) arg[1] & 31;
1290 1.1 christos else if (strlen(arg) == 1)
1291 1.1 christos value = (u_char) arg[0];
1292 1.1 christos else if (strcmp(arg, "none") == 0)
1293 1.1 christos value = SSH_ESCAPECHAR_NONE;
1294 1.1 christos else {
1295 1.1 christos fatal("%.200s line %d: Bad escape character.",
1296 1.1 christos filename, linenum);
1297 1.1 christos /* NOTREACHED */
1298 1.1 christos value = 0; /* Avoid compiler warning. */
1299 1.1 christos }
1300 1.1 christos if (*activep && *intptr == -1)
1301 1.1 christos *intptr = value;
1302 1.1 christos break;
1303 1.1 christos
1304 1.1 christos case oAddressFamily:
1305 1.1 christos intptr = &options->address_family;
1306 1.12 christos multistate_ptr = multistate_addressfamily;
1307 1.12 christos goto parse_multistate;
1308 1.1 christos
1309 1.1 christos case oEnableSSHKeysign:
1310 1.1 christos intptr = &options->enable_ssh_keysign;
1311 1.1 christos goto parse_flag;
1312 1.1 christos
1313 1.1 christos case oIdentitiesOnly:
1314 1.1 christos intptr = &options->identities_only;
1315 1.1 christos goto parse_flag;
1316 1.1 christos
1317 1.1 christos case oServerAliveInterval:
1318 1.1 christos intptr = &options->server_alive_interval;
1319 1.1 christos goto parse_time;
1320 1.1 christos
1321 1.1 christos case oServerAliveCountMax:
1322 1.1 christos intptr = &options->server_alive_count_max;
1323 1.1 christos goto parse_int;
1324 1.1 christos
1325 1.1 christos case oSendEnv:
1326 1.1 christos while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1327 1.1 christos if (strchr(arg, '=') != NULL)
1328 1.1 christos fatal("%s line %d: Invalid environment name.",
1329 1.1 christos filename, linenum);
1330 1.1 christos if (!*activep)
1331 1.1 christos continue;
1332 1.1 christos if (options->num_send_env >= MAX_SEND_ENV)
1333 1.1 christos fatal("%s line %d: too many send env.",
1334 1.1 christos filename, linenum);
1335 1.1 christos options->send_env[options->num_send_env++] =
1336 1.1 christos xstrdup(arg);
1337 1.1 christos }
1338 1.1 christos break;
1339 1.1 christos
1340 1.1 christos case oControlPath:
1341 1.1 christos charptr = &options->control_path;
1342 1.1 christos goto parse_string;
1343 1.1 christos
1344 1.1 christos case oControlMaster:
1345 1.1 christos intptr = &options->control_master;
1346 1.12 christos multistate_ptr = multistate_controlmaster;
1347 1.12 christos goto parse_multistate;
1348 1.1 christos
1349 1.4 adam case oControlPersist:
1350 1.4 adam /* no/false/yes/true, or a time spec */
1351 1.4 adam intptr = &options->control_persist;
1352 1.4 adam arg = strdelim(&s);
1353 1.4 adam if (!arg || *arg == '\0')
1354 1.4 adam fatal("%.200s line %d: Missing ControlPersist"
1355 1.4 adam " argument.", filename, linenum);
1356 1.4 adam value = 0;
1357 1.4 adam value2 = 0; /* timeout */
1358 1.4 adam if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1359 1.4 adam value = 0;
1360 1.4 adam else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1361 1.4 adam value = 1;
1362 1.4 adam else if ((value2 = convtime(arg)) >= 0)
1363 1.4 adam value = 1;
1364 1.4 adam else
1365 1.4 adam fatal("%.200s line %d: Bad ControlPersist argument.",
1366 1.4 adam filename, linenum);
1367 1.4 adam if (*activep && *intptr == -1) {
1368 1.4 adam *intptr = value;
1369 1.4 adam options->control_persist_timeout = value2;
1370 1.4 adam }
1371 1.4 adam break;
1372 1.4 adam
1373 1.1 christos case oHashKnownHosts:
1374 1.1 christos intptr = &options->hash_known_hosts;
1375 1.1 christos goto parse_flag;
1376 1.1 christos
1377 1.1 christos case oTunnel:
1378 1.1 christos intptr = &options->tun_open;
1379 1.12 christos multistate_ptr = multistate_tunnel;
1380 1.12 christos goto parse_multistate;
1381 1.1 christos
1382 1.1 christos case oTunnelDevice:
1383 1.1 christos arg = strdelim(&s);
1384 1.1 christos if (!arg || *arg == '\0')
1385 1.1 christos fatal("%.200s line %d: Missing argument.", filename, linenum);
1386 1.1 christos value = a2tun(arg, &value2);
1387 1.1 christos if (value == SSH_TUNID_ERR)
1388 1.1 christos fatal("%.200s line %d: Bad tun device.", filename, linenum);
1389 1.1 christos if (*activep) {
1390 1.1 christos options->tun_local = value;
1391 1.1 christos options->tun_remote = value2;
1392 1.1 christos }
1393 1.1 christos break;
1394 1.1 christos
1395 1.1 christos case oLocalCommand:
1396 1.1 christos charptr = &options->local_command;
1397 1.1 christos goto parse_command;
1398 1.1 christos
1399 1.1 christos case oPermitLocalCommand:
1400 1.1 christos intptr = &options->permit_local_command;
1401 1.1 christos goto parse_flag;
1402 1.1 christos
1403 1.1 christos case oVisualHostKey:
1404 1.1 christos intptr = &options->visual_host_key;
1405 1.1 christos goto parse_flag;
1406 1.1 christos
1407 1.5 christos case oIPQoS:
1408 1.5 christos arg = strdelim(&s);
1409 1.5 christos if ((value = parse_ipqos(arg)) == -1)
1410 1.5 christos fatal("%s line %d: Bad IPQoS value: %s",
1411 1.5 christos filename, linenum, arg);
1412 1.5 christos arg = strdelim(&s);
1413 1.5 christos if (arg == NULL)
1414 1.5 christos value2 = value;
1415 1.5 christos else if ((value2 = parse_ipqos(arg)) == -1)
1416 1.5 christos fatal("%s line %d: Bad IPQoS value: %s",
1417 1.5 christos filename, linenum, arg);
1418 1.5 christos if (*activep) {
1419 1.5 christos options->ip_qos_interactive = value;
1420 1.5 christos options->ip_qos_bulk = value2;
1421 1.5 christos }
1422 1.5 christos break;
1423 1.5 christos
1424 1.3 christos case oUseRoaming:
1425 1.3 christos intptr = &options->use_roaming;
1426 1.3 christos goto parse_flag;
1427 1.3 christos
1428 1.6 christos case oRequestTTY:
1429 1.6 christos intptr = &options->request_tty;
1430 1.12 christos multistate_ptr = multistate_requesttty;
1431 1.12 christos goto parse_multistate;
1432 1.6 christos
1433 1.7 tls case oSendVersionFirst:
1434 1.7 tls intptr = &options->send_version_first;
1435 1.7 tls goto parse_flag;
1436 1.7 tls
1437 1.11 christos case oIgnoreUnknown:
1438 1.11 christos charptr = &options->ignored_unknown;
1439 1.11 christos goto parse_string;
1440 1.11 christos
1441 1.12 christos case oProxyUseFdpass:
1442 1.12 christos intptr = &options->proxy_use_fdpass;
1443 1.12 christos goto parse_flag;
1444 1.12 christos
1445 1.12 christos case oCanonicalDomains:
1446 1.12 christos value = options->num_canonical_domains != 0;
1447 1.12 christos while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1448 1.12 christos valid_domain(arg, filename, linenum);
1449 1.12 christos if (!*activep || value)
1450 1.12 christos continue;
1451 1.12 christos if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1452 1.12 christos fatal("%s line %d: too many hostname suffixes.",
1453 1.12 christos filename, linenum);
1454 1.12 christos options->canonical_domains[
1455 1.12 christos options->num_canonical_domains++] = xstrdup(arg);
1456 1.12 christos }
1457 1.12 christos break;
1458 1.12 christos
1459 1.12 christos case oCanonicalizePermittedCNAMEs:
1460 1.12 christos value = options->num_permitted_cnames != 0;
1461 1.12 christos while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1462 1.12 christos /* Either '*' for everything or 'list:list' */
1463 1.12 christos if (strcmp(arg, "*") == 0)
1464 1.12 christos arg2 = arg;
1465 1.12 christos else {
1466 1.12 christos lowercase(arg);
1467 1.12 christos if ((arg2 = strchr(arg, ':')) == NULL ||
1468 1.12 christos arg2[1] == '\0') {
1469 1.12 christos fatal("%s line %d: "
1470 1.12 christos "Invalid permitted CNAME \"%s\"",
1471 1.12 christos filename, linenum, arg);
1472 1.12 christos }
1473 1.12 christos *arg2 = '\0';
1474 1.12 christos arg2++;
1475 1.12 christos }
1476 1.12 christos if (!*activep || value)
1477 1.12 christos continue;
1478 1.12 christos if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1479 1.12 christos fatal("%s line %d: too many permitted CNAMEs.",
1480 1.12 christos filename, linenum);
1481 1.12 christos cname = options->permitted_cnames +
1482 1.12 christos options->num_permitted_cnames++;
1483 1.12 christos cname->source_list = xstrdup(arg);
1484 1.12 christos cname->target_list = xstrdup(arg2);
1485 1.12 christos }
1486 1.12 christos break;
1487 1.12 christos
1488 1.12 christos case oCanonicalizeHostname:
1489 1.12 christos intptr = &options->canonicalize_hostname;
1490 1.12 christos multistate_ptr = multistate_canonicalizehostname;
1491 1.12 christos goto parse_multistate;
1492 1.12 christos
1493 1.12 christos case oCanonicalizeMaxDots:
1494 1.12 christos intptr = &options->canonicalize_max_dots;
1495 1.12 christos goto parse_int;
1496 1.12 christos
1497 1.12 christos case oCanonicalizeFallbackLocal:
1498 1.12 christos intptr = &options->canonicalize_fallback_local;
1499 1.12 christos goto parse_flag;
1500 1.12 christos
1501 1.12 christos case oStreamLocalBindMask:
1502 1.12 christos arg = strdelim(&s);
1503 1.12 christos if (!arg || *arg == '\0')
1504 1.12 christos fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1505 1.12 christos /* Parse mode in octal format */
1506 1.12 christos value = strtol(arg, &endofnumber, 8);
1507 1.12 christos if (arg == endofnumber || value < 0 || value > 0777)
1508 1.12 christos fatal("%.200s line %d: Bad mask.", filename, linenum);
1509 1.12 christos options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1510 1.12 christos break;
1511 1.12 christos
1512 1.12 christos case oStreamLocalBindUnlink:
1513 1.12 christos intptr = &options->fwd_opts.streamlocal_bind_unlink;
1514 1.12 christos goto parse_flag;
1515 1.12 christos
1516 1.1 christos case oDeprecated:
1517 1.1 christos debug("%s line %d: Deprecated option \"%s\"",
1518 1.1 christos filename, linenum, keyword);
1519 1.1 christos return 0;
1520 1.1 christos
1521 1.1 christos case oUnsupported:
1522 1.1 christos error("%s line %d: Unsupported option \"%s\"",
1523 1.1 christos filename, linenum, keyword);
1524 1.1 christos return 0;
1525 1.1 christos
1526 1.1 christos default:
1527 1.1 christos fatal("process_config_line: Unimplemented opcode %d", opcode);
1528 1.1 christos }
1529 1.1 christos
1530 1.1 christos /* Check that there is no garbage at end of line. */
1531 1.1 christos if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1532 1.1 christos fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1533 1.1 christos filename, linenum, arg);
1534 1.1 christos }
1535 1.1 christos return 0;
1536 1.1 christos }
1537 1.1 christos
1538 1.1 christos
1539 1.1 christos /*
1540 1.1 christos * Reads the config file and modifies the options accordingly. Options
1541 1.1 christos * should already be initialized before this call. This never returns if
1542 1.1 christos * there is an error. If the file does not exist, this returns 0.
1543 1.1 christos */
1544 1.1 christos
1545 1.1 christos int
1546 1.12 christos read_config_file(const char *filename, struct passwd *pw, const char *host,
1547 1.12 christos Options *options, int flags)
1548 1.1 christos {
1549 1.1 christos FILE *f;
1550 1.1 christos char line[1024];
1551 1.1 christos int active, linenum;
1552 1.1 christos int bad_options = 0;
1553 1.1 christos
1554 1.1 christos if ((f = fopen(filename, "r")) == NULL)
1555 1.1 christos return 0;
1556 1.1 christos
1557 1.9 mlelstv if (flags & SSHCONF_CHECKPERM) {
1558 1.1 christos struct stat sb;
1559 1.1 christos
1560 1.1 christos if (fstat(fileno(f), &sb) == -1)
1561 1.1 christos fatal("fstat %s: %s", filename, strerror(errno));
1562 1.1 christos if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1563 1.1 christos (sb.st_mode & 022) != 0))
1564 1.1 christos fatal("Bad owner or permissions on %s", filename);
1565 1.1 christos }
1566 1.1 christos
1567 1.1 christos debug("Reading configuration data %.200s", filename);
1568 1.1 christos
1569 1.1 christos /*
1570 1.1 christos * Mark that we are now processing the options. This flag is turned
1571 1.1 christos * on/off by Host specifications.
1572 1.1 christos */
1573 1.1 christos active = 1;
1574 1.1 christos linenum = 0;
1575 1.1 christos while (fgets(line, sizeof(line), f)) {
1576 1.1 christos /* Update line number counter. */
1577 1.1 christos linenum++;
1578 1.12 christos if (process_config_line(options, pw, host, line, filename,
1579 1.12 christos linenum, &active, flags & SSHCONF_USERCONF) != 0)
1580 1.1 christos bad_options++;
1581 1.1 christos }
1582 1.1 christos fclose(f);
1583 1.1 christos if (bad_options > 0)
1584 1.1 christos fatal("%s: terminating, %d bad configuration options",
1585 1.1 christos filename, bad_options);
1586 1.1 christos return 1;
1587 1.1 christos }
1588 1.1 christos
1589 1.12 christos /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1590 1.12 christos int
1591 1.12 christos option_clear_or_none(const char *o)
1592 1.12 christos {
1593 1.12 christos return o == NULL || strcasecmp(o, "none") == 0;
1594 1.12 christos }
1595 1.12 christos
1596 1.1 christos /*
1597 1.1 christos * Initializes options to special values that indicate that they have not yet
1598 1.1 christos * been set. Read_config_file will only set options with this value. Options
1599 1.1 christos * are processed in the following order: command line, user config file,
1600 1.1 christos * system config file. Last, fill_default_options is called.
1601 1.1 christos */
1602 1.1 christos
1603 1.1 christos void
1604 1.1 christos initialize_options(Options * options)
1605 1.1 christos {
1606 1.1 christos memset(options, 'X', sizeof(*options));
1607 1.1 christos options->forward_agent = -1;
1608 1.1 christos options->forward_x11 = -1;
1609 1.1 christos options->forward_x11_trusted = -1;
1610 1.4 adam options->forward_x11_timeout = -1;
1611 1.1 christos options->exit_on_forward_failure = -1;
1612 1.1 christos options->xauth_location = NULL;
1613 1.12 christos options->fwd_opts.gateway_ports = -1;
1614 1.12 christos options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1615 1.12 christos options->fwd_opts.streamlocal_bind_unlink = -1;
1616 1.1 christos options->use_privileged_port = -1;
1617 1.1 christos options->rsa_authentication = -1;
1618 1.1 christos options->pubkey_authentication = -1;
1619 1.1 christos options->challenge_response_authentication = -1;
1620 1.2 christos #if defined(KRB4) || defined(KRB5)
1621 1.2 christos options->kerberos_authentication = -1;
1622 1.2 christos #endif
1623 1.2 christos #if defined(AFS) || defined(KRB5)
1624 1.2 christos options->kerberos_tgt_passing = -1;
1625 1.2 christos #endif
1626 1.2 christos #ifdef AFS
1627 1.2 christos options->afs_token_passing = -1;
1628 1.2 christos #endif
1629 1.1 christos options->gss_authentication = -1;
1630 1.1 christos options->gss_deleg_creds = -1;
1631 1.1 christos options->password_authentication = -1;
1632 1.1 christos options->kbd_interactive_authentication = -1;
1633 1.1 christos options->kbd_interactive_devices = NULL;
1634 1.1 christos options->rhosts_rsa_authentication = -1;
1635 1.1 christos options->hostbased_authentication = -1;
1636 1.1 christos options->batch_mode = -1;
1637 1.1 christos options->check_host_ip = -1;
1638 1.1 christos options->strict_host_key_checking = -1;
1639 1.1 christos options->compression = -1;
1640 1.1 christos options->tcp_keep_alive = -1;
1641 1.1 christos options->compression_level = -1;
1642 1.1 christos options->port = -1;
1643 1.1 christos options->address_family = -1;
1644 1.1 christos options->connection_attempts = -1;
1645 1.1 christos options->connection_timeout = -1;
1646 1.1 christos options->number_of_password_prompts = -1;
1647 1.1 christos options->cipher = -1;
1648 1.1 christos options->ciphers = NULL;
1649 1.1 christos options->macs = NULL;
1650 1.5 christos options->kex_algorithms = NULL;
1651 1.1 christos options->hostkeyalgorithms = NULL;
1652 1.1 christos options->protocol = SSH_PROTO_UNKNOWN;
1653 1.1 christos options->num_identity_files = 0;
1654 1.1 christos options->hostname = NULL;
1655 1.1 christos options->host_key_alias = NULL;
1656 1.1 christos options->proxy_command = NULL;
1657 1.1 christos options->user = NULL;
1658 1.1 christos options->escape_char = -1;
1659 1.6 christos options->num_system_hostfiles = 0;
1660 1.6 christos options->num_user_hostfiles = 0;
1661 1.4 adam options->local_forwards = NULL;
1662 1.1 christos options->num_local_forwards = 0;
1663 1.4 adam options->remote_forwards = NULL;
1664 1.1 christos options->num_remote_forwards = 0;
1665 1.1 christos options->clear_forwardings = -1;
1666 1.1 christos options->log_level = SYSLOG_LEVEL_NOT_SET;
1667 1.1 christos options->preferred_authentications = NULL;
1668 1.1 christos options->bind_address = NULL;
1669 1.4 adam options->pkcs11_provider = NULL;
1670 1.1 christos options->enable_ssh_keysign = - 1;
1671 1.1 christos options->no_host_authentication_for_localhost = - 1;
1672 1.1 christos options->identities_only = - 1;
1673 1.1 christos options->rekey_limit = - 1;
1674 1.11 christos options->rekey_interval = -1;
1675 1.1 christos options->verify_host_key_dns = -1;
1676 1.1 christos options->server_alive_interval = -1;
1677 1.1 christos options->server_alive_count_max = -1;
1678 1.1 christos options->num_send_env = 0;
1679 1.1 christos options->control_path = NULL;
1680 1.1 christos options->control_master = -1;
1681 1.4 adam options->control_persist = -1;
1682 1.4 adam options->control_persist_timeout = 0;
1683 1.1 christos options->hash_known_hosts = -1;
1684 1.1 christos options->tun_open = -1;
1685 1.1 christos options->tun_local = -1;
1686 1.1 christos options->tun_remote = -1;
1687 1.1 christos options->local_command = NULL;
1688 1.1 christos options->permit_local_command = -1;
1689 1.3 christos options->use_roaming = -1;
1690 1.1 christos options->visual_host_key = -1;
1691 1.5 christos options->ip_qos_interactive = -1;
1692 1.5 christos options->ip_qos_bulk = -1;
1693 1.6 christos options->request_tty = -1;
1694 1.12 christos options->proxy_use_fdpass = -1;
1695 1.11 christos options->ignored_unknown = NULL;
1696 1.12 christos options->num_canonical_domains = 0;
1697 1.12 christos options->num_permitted_cnames = 0;
1698 1.12 christos options->canonicalize_max_dots = -1;
1699 1.12 christos options->canonicalize_fallback_local = -1;
1700 1.12 christos options->canonicalize_hostname = -1;
1701 1.2 christos options->none_switch = -1;
1702 1.2 christos options->none_enabled = -1;
1703 1.2 christos options->hpn_disabled = -1;
1704 1.2 christos options->hpn_buffer_size = -1;
1705 1.2 christos options->tcp_rcv_buf_poll = -1;
1706 1.2 christos options->tcp_rcv_buf = -1;
1707 1.7 tls options->send_version_first = -1;
1708 1.1 christos }
1709 1.1 christos
1710 1.1 christos /*
1711 1.12 christos * A petite version of fill_default_options() that just fills the options
1712 1.12 christos * needed for hostname canonicalization to proceed.
1713 1.12 christos */
1714 1.12 christos void
1715 1.12 christos fill_default_options_for_canonicalization(Options *options)
1716 1.12 christos {
1717 1.12 christos if (options->canonicalize_max_dots == -1)
1718 1.12 christos options->canonicalize_max_dots = 1;
1719 1.12 christos if (options->canonicalize_fallback_local == -1)
1720 1.12 christos options->canonicalize_fallback_local = 1;
1721 1.12 christos if (options->canonicalize_hostname == -1)
1722 1.12 christos options->canonicalize_hostname = SSH_CANONICALISE_NO;
1723 1.12 christos }
1724 1.12 christos
1725 1.12 christos /*
1726 1.1 christos * Called after processing other sources of option data, this fills those
1727 1.1 christos * options for which no value has been specified with their default values.
1728 1.1 christos */
1729 1.1 christos void
1730 1.1 christos fill_default_options(Options * options)
1731 1.1 christos {
1732 1.1 christos if (options->forward_agent == -1)
1733 1.1 christos options->forward_agent = 0;
1734 1.1 christos if (options->forward_x11 == -1)
1735 1.1 christos options->forward_x11 = 0;
1736 1.1 christos if (options->forward_x11_trusted == -1)
1737 1.1 christos options->forward_x11_trusted = 0;
1738 1.4 adam if (options->forward_x11_timeout == -1)
1739 1.4 adam options->forward_x11_timeout = 1200;
1740 1.1 christos if (options->exit_on_forward_failure == -1)
1741 1.1 christos options->exit_on_forward_failure = 0;
1742 1.1 christos if (options->xauth_location == NULL)
1743 1.5 christos options->xauth_location = __UNCONST(_PATH_XAUTH);
1744 1.12 christos if (options->fwd_opts.gateway_ports == -1)
1745 1.12 christos options->fwd_opts.gateway_ports = 0;
1746 1.12 christos if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1747 1.12 christos options->fwd_opts.streamlocal_bind_mask = 0177;
1748 1.12 christos if (options->fwd_opts.streamlocal_bind_unlink == -1)
1749 1.12 christos options->fwd_opts.streamlocal_bind_unlink = 0;
1750 1.1 christos if (options->use_privileged_port == -1)
1751 1.1 christos options->use_privileged_port = 0;
1752 1.1 christos if (options->rsa_authentication == -1)
1753 1.1 christos options->rsa_authentication = 1;
1754 1.1 christos if (options->pubkey_authentication == -1)
1755 1.1 christos options->pubkey_authentication = 1;
1756 1.1 christos if (options->challenge_response_authentication == -1)
1757 1.1 christos options->challenge_response_authentication = 1;
1758 1.2 christos #if defined(KRB4) || defined(KRB5)
1759 1.2 christos if (options->kerberos_authentication == -1)
1760 1.2 christos options->kerberos_authentication = 1;
1761 1.2 christos #endif
1762 1.2 christos #if defined(AFS) || defined(KRB5)
1763 1.2 christos if (options->kerberos_tgt_passing == -1)
1764 1.2 christos options->kerberos_tgt_passing = 1;
1765 1.2 christos #endif
1766 1.2 christos #ifdef AFS
1767 1.2 christos if (options->afs_token_passing == -1)
1768 1.2 christos options->afs_token_passing = 1;
1769 1.2 christos #endif
1770 1.1 christos if (options->gss_authentication == -1)
1771 1.1 christos options->gss_authentication = 0;
1772 1.1 christos if (options->gss_deleg_creds == -1)
1773 1.1 christos options->gss_deleg_creds = 0;
1774 1.1 christos if (options->password_authentication == -1)
1775 1.1 christos options->password_authentication = 1;
1776 1.1 christos if (options->kbd_interactive_authentication == -1)
1777 1.1 christos options->kbd_interactive_authentication = 1;
1778 1.1 christos if (options->rhosts_rsa_authentication == -1)
1779 1.1 christos options->rhosts_rsa_authentication = 0;
1780 1.1 christos if (options->hostbased_authentication == -1)
1781 1.1 christos options->hostbased_authentication = 0;
1782 1.1 christos if (options->batch_mode == -1)
1783 1.1 christos options->batch_mode = 0;
1784 1.1 christos if (options->check_host_ip == -1)
1785 1.1 christos options->check_host_ip = 1;
1786 1.1 christos if (options->strict_host_key_checking == -1)
1787 1.1 christos options->strict_host_key_checking = 2; /* 2 is default */
1788 1.1 christos if (options->compression == -1)
1789 1.1 christos options->compression = 0;
1790 1.1 christos if (options->tcp_keep_alive == -1)
1791 1.1 christos options->tcp_keep_alive = 1;
1792 1.1 christos if (options->compression_level == -1)
1793 1.1 christos options->compression_level = 6;
1794 1.1 christos if (options->port == -1)
1795 1.1 christos options->port = 0; /* Filled in ssh_connect. */
1796 1.1 christos if (options->address_family == -1)
1797 1.1 christos options->address_family = AF_UNSPEC;
1798 1.1 christos if (options->connection_attempts == -1)
1799 1.1 christos options->connection_attempts = 1;
1800 1.1 christos if (options->number_of_password_prompts == -1)
1801 1.1 christos options->number_of_password_prompts = 3;
1802 1.1 christos /* Selected in ssh_login(). */
1803 1.1 christos if (options->cipher == -1)
1804 1.1 christos options->cipher = SSH_CIPHER_NOT_SET;
1805 1.1 christos /* options->ciphers, default set in myproposals.h */
1806 1.1 christos /* options->macs, default set in myproposals.h */
1807 1.5 christos /* options->kex_algorithms, default set in myproposals.h */
1808 1.1 christos /* options->hostkeyalgorithms, default set in myproposals.h */
1809 1.1 christos if (options->protocol == SSH_PROTO_UNKNOWN)
1810 1.4 adam options->protocol = SSH_PROTO_2;
1811 1.1 christos if (options->num_identity_files == 0) {
1812 1.1 christos if (options->protocol & SSH_PROTO_1) {
1813 1.10 mlelstv add_identity_file(options, "~/",
1814 1.10 mlelstv _PATH_SSH_CLIENT_IDENTITY, 0);
1815 1.1 christos }
1816 1.1 christos if (options->protocol & SSH_PROTO_2) {
1817 1.10 mlelstv add_identity_file(options, "~/",
1818 1.10 mlelstv _PATH_SSH_CLIENT_ID_RSA, 0);
1819 1.10 mlelstv add_identity_file(options, "~/",
1820 1.10 mlelstv _PATH_SSH_CLIENT_ID_DSA, 0);
1821 1.10 mlelstv add_identity_file(options, "~/",
1822 1.10 mlelstv _PATH_SSH_CLIENT_ID_ECDSA, 0);
1823 1.12 christos add_identity_file(options, "~/",
1824 1.12 christos _PATH_SSH_CLIENT_ID_ED25519, 0);
1825 1.1 christos }
1826 1.1 christos }
1827 1.1 christos if (options->escape_char == -1)
1828 1.1 christos options->escape_char = '~';
1829 1.6 christos if (options->num_system_hostfiles == 0) {
1830 1.6 christos options->system_hostfiles[options->num_system_hostfiles++] =
1831 1.6 christos xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1832 1.6 christos options->system_hostfiles[options->num_system_hostfiles++] =
1833 1.6 christos xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1834 1.6 christos }
1835 1.6 christos if (options->num_user_hostfiles == 0) {
1836 1.6 christos options->user_hostfiles[options->num_user_hostfiles++] =
1837 1.6 christos xstrdup(_PATH_SSH_USER_HOSTFILE);
1838 1.6 christos options->user_hostfiles[options->num_user_hostfiles++] =
1839 1.6 christos xstrdup(_PATH_SSH_USER_HOSTFILE2);
1840 1.6 christos }
1841 1.1 christos if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1842 1.1 christos options->log_level = SYSLOG_LEVEL_INFO;
1843 1.1 christos if (options->clear_forwardings == 1)
1844 1.1 christos clear_forwardings(options);
1845 1.1 christos if (options->no_host_authentication_for_localhost == - 1)
1846 1.1 christos options->no_host_authentication_for_localhost = 0;
1847 1.1 christos if (options->identities_only == -1)
1848 1.1 christos options->identities_only = 0;
1849 1.1 christos if (options->enable_ssh_keysign == -1)
1850 1.1 christos options->enable_ssh_keysign = 0;
1851 1.1 christos if (options->rekey_limit == -1)
1852 1.1 christos options->rekey_limit = 0;
1853 1.11 christos if (options->rekey_interval == -1)
1854 1.11 christos options->rekey_interval = 0;
1855 1.1 christos if (options->verify_host_key_dns == -1)
1856 1.1 christos options->verify_host_key_dns = 0;
1857 1.1 christos if (options->server_alive_interval == -1)
1858 1.1 christos options->server_alive_interval = 0;
1859 1.1 christos if (options->server_alive_count_max == -1)
1860 1.1 christos options->server_alive_count_max = 3;
1861 1.2 christos if (options->none_switch == -1)
1862 1.2 christos options->none_switch = 0;
1863 1.2 christos if (options->hpn_disabled == -1)
1864 1.2 christos options->hpn_disabled = 0;
1865 1.2 christos if (options->hpn_buffer_size > -1)
1866 1.2 christos {
1867 1.2 christos /* if a user tries to set the size to 0 set it to 1KB */
1868 1.2 christos if (options->hpn_buffer_size == 0)
1869 1.2 christos options->hpn_buffer_size = 1024;
1870 1.2 christos /*limit the buffer to 64MB*/
1871 1.2 christos if (options->hpn_buffer_size > 65536)
1872 1.2 christos {
1873 1.2 christos options->hpn_buffer_size = 65536*1024;
1874 1.2 christos debug("User requested buffer larger than 64MB. Request reverted to 64MB");
1875 1.2 christos }
1876 1.2 christos debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
1877 1.2 christos }
1878 1.2 christos if (options->tcp_rcv_buf == 0)
1879 1.2 christos options->tcp_rcv_buf = 1;
1880 1.2 christos if (options->tcp_rcv_buf > -1)
1881 1.2 christos options->tcp_rcv_buf *=1024;
1882 1.2 christos if (options->tcp_rcv_buf_poll == -1)
1883 1.2 christos options->tcp_rcv_buf_poll = 1;
1884 1.1 christos if (options->control_master == -1)
1885 1.1 christos options->control_master = 0;
1886 1.4 adam if (options->control_persist == -1) {
1887 1.4 adam options->control_persist = 0;
1888 1.4 adam options->control_persist_timeout = 0;
1889 1.4 adam }
1890 1.1 christos if (options->hash_known_hosts == -1)
1891 1.1 christos options->hash_known_hosts = 0;
1892 1.1 christos if (options->tun_open == -1)
1893 1.1 christos options->tun_open = SSH_TUNMODE_NO;
1894 1.1 christos if (options->tun_local == -1)
1895 1.1 christos options->tun_local = SSH_TUNID_ANY;
1896 1.1 christos if (options->tun_remote == -1)
1897 1.1 christos options->tun_remote = SSH_TUNID_ANY;
1898 1.1 christos if (options->permit_local_command == -1)
1899 1.1 christos options->permit_local_command = 0;
1900 1.3 christos if (options->use_roaming == -1)
1901 1.3 christos options->use_roaming = 1;
1902 1.1 christos if (options->visual_host_key == -1)
1903 1.1 christos options->visual_host_key = 0;
1904 1.5 christos if (options->ip_qos_interactive == -1)
1905 1.5 christos options->ip_qos_interactive = IPTOS_LOWDELAY;
1906 1.5 christos if (options->ip_qos_bulk == -1)
1907 1.5 christos options->ip_qos_bulk = IPTOS_THROUGHPUT;
1908 1.6 christos if (options->request_tty == -1)
1909 1.6 christos options->request_tty = REQUEST_TTY_AUTO;
1910 1.12 christos if (options->proxy_use_fdpass == -1)
1911 1.12 christos options->proxy_use_fdpass = 0;
1912 1.12 christos if (options->canonicalize_max_dots == -1)
1913 1.12 christos options->canonicalize_max_dots = 1;
1914 1.12 christos if (options->canonicalize_fallback_local == -1)
1915 1.12 christos options->canonicalize_fallback_local = 1;
1916 1.12 christos if (options->canonicalize_hostname == -1)
1917 1.12 christos options->canonicalize_hostname = SSH_CANONICALISE_NO;
1918 1.7 tls if (options->send_version_first == -1)
1919 1.7 tls options->send_version_first = 1;
1920 1.12 christos #define CLEAR_ON_NONE(v) \
1921 1.12 christos do { \
1922 1.12 christos if (option_clear_or_none(v)) { \
1923 1.12 christos free(v); \
1924 1.12 christos v = NULL; \
1925 1.12 christos } \
1926 1.12 christos } while(0)
1927 1.12 christos CLEAR_ON_NONE(options->local_command);
1928 1.12 christos CLEAR_ON_NONE(options->proxy_command);
1929 1.12 christos CLEAR_ON_NONE(options->control_path);
1930 1.1 christos /* options->user will be set in the main program if appropriate */
1931 1.1 christos /* options->hostname will be set in the main program if appropriate */
1932 1.1 christos /* options->host_key_alias should not be set by default */
1933 1.1 christos /* options->preferred_authentications will be set in ssh */
1934 1.1 christos }
1935 1.1 christos
1936 1.12 christos struct fwdarg {
1937 1.12 christos char *arg;
1938 1.12 christos int ispath;
1939 1.12 christos };
1940 1.12 christos
1941 1.12 christos /*
1942 1.12 christos * parse_fwd_field
1943 1.12 christos * parses the next field in a port forwarding specification.
1944 1.12 christos * sets fwd to the parsed field and advances p past the colon
1945 1.12 christos * or sets it to NULL at end of string.
1946 1.12 christos * returns 0 on success, else non-zero.
1947 1.12 christos */
1948 1.12 christos static int
1949 1.12 christos parse_fwd_field(char **p, struct fwdarg *fwd)
1950 1.12 christos {
1951 1.12 christos char *ep, *cp = *p;
1952 1.12 christos int ispath = 0;
1953 1.12 christos
1954 1.12 christos if (*cp == '\0') {
1955 1.12 christos *p = NULL;
1956 1.12 christos return -1; /* end of string */
1957 1.12 christos }
1958 1.12 christos
1959 1.12 christos /*
1960 1.12 christos * A field escaped with square brackets is used literally.
1961 1.12 christos * XXX - allow ']' to be escaped via backslash?
1962 1.12 christos */
1963 1.12 christos if (*cp == '[') {
1964 1.12 christos /* find matching ']' */
1965 1.12 christos for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1966 1.12 christos if (*ep == '/')
1967 1.12 christos ispath = 1;
1968 1.12 christos }
1969 1.12 christos /* no matching ']' or not at end of field. */
1970 1.12 christos if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1971 1.12 christos return -1;
1972 1.12 christos /* NUL terminate the field and advance p past the colon */
1973 1.12 christos *ep++ = '\0';
1974 1.12 christos if (*ep != '\0')
1975 1.12 christos *ep++ = '\0';
1976 1.12 christos fwd->arg = cp + 1;
1977 1.12 christos fwd->ispath = ispath;
1978 1.12 christos *p = ep;
1979 1.12 christos return 0;
1980 1.12 christos }
1981 1.12 christos
1982 1.12 christos for (cp = *p; *cp != '\0'; cp++) {
1983 1.12 christos switch (*cp) {
1984 1.12 christos case '\\':
1985 1.12 christos memmove(cp, cp + 1, strlen(cp + 1) + 1);
1986 1.12 christos cp++;
1987 1.12 christos break;
1988 1.12 christos case '/':
1989 1.12 christos ispath = 1;
1990 1.12 christos break;
1991 1.12 christos case ':':
1992 1.12 christos *cp++ = '\0';
1993 1.12 christos goto done;
1994 1.12 christos }
1995 1.12 christos }
1996 1.12 christos done:
1997 1.12 christos fwd->arg = *p;
1998 1.12 christos fwd->ispath = ispath;
1999 1.12 christos *p = cp;
2000 1.12 christos return 0;
2001 1.12 christos }
2002 1.12 christos
2003 1.1 christos /*
2004 1.1 christos * parse_forward
2005 1.1 christos * parses a string containing a port forwarding specification of the form:
2006 1.1 christos * dynamicfwd == 0
2007 1.12 christos * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2008 1.12 christos * listenpath:connectpath
2009 1.1 christos * dynamicfwd == 1
2010 1.1 christos * [listenhost:]listenport
2011 1.1 christos * returns number of arguments parsed or zero on error
2012 1.1 christos */
2013 1.1 christos int
2014 1.12 christos parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2015 1.1 christos {
2016 1.12 christos struct fwdarg fwdargs[4];
2017 1.12 christos char *p, *cp;
2018 1.1 christos int i;
2019 1.1 christos
2020 1.12 christos memset(fwd, 0, sizeof(*fwd));
2021 1.12 christos memset(fwdargs, 0, sizeof(fwdargs));
2022 1.1 christos
2023 1.1 christos cp = p = xstrdup(fwdspec);
2024 1.1 christos
2025 1.1 christos /* skip leading spaces */
2026 1.12 christos while (isspace((u_char)*cp))
2027 1.1 christos cp++;
2028 1.1 christos
2029 1.12 christos for (i = 0; i < 4; ++i) {
2030 1.12 christos if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2031 1.1 christos break;
2032 1.12 christos }
2033 1.1 christos
2034 1.1 christos /* Check for trailing garbage */
2035 1.12 christos if (cp != NULL && *cp != '\0') {
2036 1.1 christos i = 0; /* failure */
2037 1.12 christos }
2038 1.1 christos
2039 1.1 christos switch (i) {
2040 1.1 christos case 1:
2041 1.12 christos if (fwdargs[0].ispath) {
2042 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
2043 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
2044 1.12 christos } else {
2045 1.12 christos fwd->listen_host = NULL;
2046 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
2047 1.12 christos }
2048 1.1 christos fwd->connect_host = xstrdup("socks");
2049 1.1 christos break;
2050 1.1 christos
2051 1.1 christos case 2:
2052 1.12 christos if (fwdargs[0].ispath && fwdargs[1].ispath) {
2053 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
2054 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
2055 1.12 christos fwd->connect_path = xstrdup(fwdargs[1].arg);
2056 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
2057 1.12 christos } else if (fwdargs[1].ispath) {
2058 1.12 christos fwd->listen_host = NULL;
2059 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
2060 1.12 christos fwd->connect_path = xstrdup(fwdargs[1].arg);
2061 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
2062 1.12 christos } else {
2063 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
2064 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
2065 1.12 christos fwd->connect_host = xstrdup("socks");
2066 1.12 christos }
2067 1.1 christos break;
2068 1.1 christos
2069 1.1 christos case 3:
2070 1.12 christos if (fwdargs[0].ispath) {
2071 1.12 christos fwd->listen_path = xstrdup(fwdargs[0].arg);
2072 1.12 christos fwd->listen_port = PORT_STREAMLOCAL;
2073 1.12 christos fwd->connect_host = xstrdup(fwdargs[1].arg);
2074 1.12 christos fwd->connect_port = a2port(fwdargs[2].arg);
2075 1.12 christos } else if (fwdargs[2].ispath) {
2076 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
2077 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
2078 1.12 christos fwd->connect_path = xstrdup(fwdargs[2].arg);
2079 1.12 christos fwd->connect_port = PORT_STREAMLOCAL;
2080 1.12 christos } else {
2081 1.12 christos fwd->listen_host = NULL;
2082 1.12 christos fwd->listen_port = a2port(fwdargs[0].arg);
2083 1.12 christos fwd->connect_host = xstrdup(fwdargs[1].arg);
2084 1.12 christos fwd->connect_port = a2port(fwdargs[2].arg);
2085 1.12 christos }
2086 1.1 christos break;
2087 1.1 christos
2088 1.1 christos case 4:
2089 1.12 christos fwd->listen_host = xstrdup(fwdargs[0].arg);
2090 1.12 christos fwd->listen_port = a2port(fwdargs[1].arg);
2091 1.12 christos fwd->connect_host = xstrdup(fwdargs[2].arg);
2092 1.12 christos fwd->connect_port = a2port(fwdargs[3].arg);
2093 1.1 christos break;
2094 1.1 christos default:
2095 1.1 christos i = 0; /* failure */
2096 1.1 christos }
2097 1.1 christos
2098 1.11 christos free(p);
2099 1.1 christos
2100 1.1 christos if (dynamicfwd) {
2101 1.1 christos if (!(i == 1 || i == 2))
2102 1.1 christos goto fail_free;
2103 1.1 christos } else {
2104 1.12 christos if (!(i == 3 || i == 4)) {
2105 1.12 christos if (fwd->connect_path == NULL &&
2106 1.12 christos fwd->listen_path == NULL)
2107 1.12 christos goto fail_free;
2108 1.12 christos }
2109 1.12 christos if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2110 1.1 christos goto fail_free;
2111 1.1 christos }
2112 1.1 christos
2113 1.12 christos if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2114 1.12 christos (!remotefwd && fwd->listen_port == 0))
2115 1.1 christos goto fail_free;
2116 1.1 christos if (fwd->connect_host != NULL &&
2117 1.1 christos strlen(fwd->connect_host) >= NI_MAXHOST)
2118 1.1 christos goto fail_free;
2119 1.12 christos /* XXX - if connecting to a remote socket, max sun len may not match this host */
2120 1.12 christos if (fwd->connect_path != NULL &&
2121 1.12 christos strlen(fwd->connect_path) >= PATH_MAX_SUN)
2122 1.12 christos goto fail_free;
2123 1.1 christos if (fwd->listen_host != NULL &&
2124 1.1 christos strlen(fwd->listen_host) >= NI_MAXHOST)
2125 1.1 christos goto fail_free;
2126 1.12 christos if (fwd->listen_path != NULL &&
2127 1.12 christos strlen(fwd->listen_path) >= PATH_MAX_SUN)
2128 1.12 christos goto fail_free;
2129 1.1 christos
2130 1.1 christos return (i);
2131 1.1 christos
2132 1.1 christos fail_free:
2133 1.11 christos free(fwd->connect_host);
2134 1.11 christos fwd->connect_host = NULL;
2135 1.12 christos free(fwd->connect_path);
2136 1.12 christos fwd->connect_path = NULL;
2137 1.11 christos free(fwd->listen_host);
2138 1.11 christos fwd->listen_host = NULL;
2139 1.12 christos free(fwd->listen_path);
2140 1.12 christos fwd->listen_path = NULL;
2141 1.1 christos return (0);
2142 1.1 christos }
2143