GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/ssh/../readconf.c Lines: 0 1283 0.0 %
Date: 2017-11-13 Branches: 0 960 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: readconf.c,v 1.280 2017/10/21 23:06:24 millert Exp $ */
2
/*
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5
 *                    All rights reserved
6
 * Functions for reading the configuration files.
7
 *
8
 * As far as I am concerned, the code I have written for this software
9
 * can be used freely for any purpose.  Any derived versions of this
10
 * software must be clearly marked as such, and if the derived work is
11
 * incompatible with the protocol description in the RFC file, it must be
12
 * called by a name other than "ssh" or "Secure Shell".
13
 */
14
15
#include <sys/types.h>
16
#include <sys/stat.h>
17
#include <sys/socket.h>
18
#include <sys/wait.h>
19
#include <sys/un.h>
20
21
#include <netinet/in.h>
22
#include <netinet/ip.h>
23
24
#include <ctype.h>
25
#include <errno.h>
26
#include <fcntl.h>
27
#include <glob.h>
28
#include <netdb.h>
29
#include <paths.h>
30
#include <pwd.h>
31
#include <signal.h>
32
#include <stdio.h>
33
#include <string.h>
34
#include <unistd.h>
35
#include <limits.h>
36
#include <util.h>
37
#include <vis.h>
38
39
#include "xmalloc.h"
40
#include "ssh.h"
41
#include "compat.h"
42
#include "cipher.h"
43
#include "pathnames.h"
44
#include "log.h"
45
#include "sshkey.h"
46
#include "misc.h"
47
#include "readconf.h"
48
#include "match.h"
49
#include "kex.h"
50
#include "mac.h"
51
#include "uidswap.h"
52
#include "myproposal.h"
53
#include "digest.h"
54
55
/* Format of the configuration file:
56
57
   # Configuration data is parsed as follows:
58
   #  1. command line options
59
   #  2. user-specific file
60
   #  3. system-wide file
61
   # Any configuration value is only changed the first time it is set.
62
   # Thus, host-specific definitions should be at the beginning of the
63
   # configuration file, and defaults at the end.
64
65
   # Host-specific declarations.  These may override anything above.  A single
66
   # host may match multiple declarations; these are processed in the order
67
   # that they are given in.
68
69
   Host *.ngs.fi ngs.fi
70
     User foo
71
72
   Host fake.com
73
     HostName another.host.name.real.org
74
     User blaah
75
     Port 34289
76
     ForwardX11 no
77
     ForwardAgent no
78
79
   Host books.com
80
     RemoteForward 9999 shadows.cs.hut.fi:9999
81
     Ciphers 3des-cbc
82
83
   Host fascist.blob.com
84
     Port 23123
85
     User tylonen
86
     PasswordAuthentication no
87
88
   Host puukko.hut.fi
89
     User t35124p
90
     ProxyCommand ssh-proxy %h %p
91
92
   Host *.fr
93
     PublicKeyAuthentication no
94
95
   Host *.su
96
     Ciphers aes128-ctr
97
     PasswordAuthentication no
98
99
   Host vpn.fake.com
100
     Tunnel yes
101
     TunnelDevice 3
102
103
   # Defaults for various options
104
   Host *
105
     ForwardAgent no
106
     ForwardX11 no
107
     PasswordAuthentication yes
108
     RSAAuthentication yes
109
     RhostsRSAAuthentication yes
110
     StrictHostKeyChecking yes
111
     TcpKeepAlive no
112
     IdentityFile ~/.ssh/identity
113
     Port 22
114
     EscapeChar ~
115
116
*/
117
118
static int read_config_file_depth(const char *filename, struct passwd *pw,
119
    const char *host, const char *original_host, Options *options,
120
    int flags, int *activep, int depth);
121
static int process_config_line_depth(Options *options, struct passwd *pw,
122
    const char *host, const char *original_host, char *line,
123
    const char *filename, int linenum, int *activep, int flags, int depth);
124
125
/* Keyword tokens. */
126
127
typedef enum {
128
	oBadOption,
129
	oHost, oMatch, oInclude,
130
	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
131
	oGatewayPorts, oExitOnForwardFailure,
132
	oPasswordAuthentication, oRSAAuthentication,
133
	oChallengeResponseAuthentication, oXAuthLocation,
134
	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
135
	oCertificateFile, oAddKeysToAgent, oIdentityAgent,
136
	oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
137
	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
138
	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
139
	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
140
	oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs,
141
	oPubkeyAuthentication,
142
	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
143
	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
144
	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
145
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
146
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
147
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
148
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
149
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
150
	oHashKnownHosts,
151
	oTunnel, oTunnelDevice,
152
	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
153
	oVisualHostKey,
154
	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
155
	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
156
	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
157
	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
158
	oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
159
	oPubkeyAcceptedKeyTypes, oProxyJump,
160
	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
161
} OpCodes;
162
163
/* Textual representations of the tokens. */
164
165
static struct {
166
	const char *name;
167
	OpCodes opcode;
168
} keywords[] = {
169
	/* Deprecated options */
170
	{ "protocol", oIgnore }, /* NB. silently ignored */
171
	{ "cipher", oDeprecated },
172
	{ "fallbacktorsh", oDeprecated },
173
	{ "globalknownhostsfile2", oDeprecated },
174
	{ "rhostsauthentication", oDeprecated },
175
	{ "userknownhostsfile2", oDeprecated },
176
	{ "useroaming", oDeprecated },
177
	{ "usersh", oDeprecated },
178
179
	/* Unsupported options */
180
	{ "afstokenpassing", oUnsupported },
181
	{ "kerberosauthentication", oUnsupported },
182
	{ "kerberostgtpassing", oUnsupported },
183
184
	/* Sometimes-unsupported options */
185
#if defined(GSSAPI)
186
	{ "gssapiauthentication", oGssAuthentication },
187
	{ "gssapidelegatecredentials", oGssDelegateCreds },
188
# else
189
	{ "gssapiauthentication", oUnsupported },
190
	{ "gssapidelegatecredentials", oUnsupported },
191
#endif
192
#ifdef ENABLE_PKCS11
193
	{ "smartcarddevice", oPKCS11Provider },
194
	{ "pkcs11provider", oPKCS11Provider },
195
# else
196
	{ "smartcarddevice", oUnsupported },
197
	{ "pkcs11provider", oUnsupported },
198
#endif
199
	{ "rsaauthentication", oUnsupported },
200
	{ "rhostsrsaauthentication", oUnsupported },
201
	{ "compressionlevel", oUnsupported },
202
203
	{ "forwardagent", oForwardAgent },
204
	{ "forwardx11", oForwardX11 },
205
	{ "forwardx11trusted", oForwardX11Trusted },
206
	{ "forwardx11timeout", oForwardX11Timeout },
207
	{ "exitonforwardfailure", oExitOnForwardFailure },
208
	{ "xauthlocation", oXAuthLocation },
209
	{ "gatewayports", oGatewayPorts },
210
	{ "useprivilegedport", oUsePrivilegedPort },
211
	{ "passwordauthentication", oPasswordAuthentication },
212
	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
213
	{ "kbdinteractivedevices", oKbdInteractiveDevices },
214
	{ "pubkeyauthentication", oPubkeyAuthentication },
215
	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
216
	{ "hostbasedauthentication", oHostbasedAuthentication },
217
	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
218
	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
219
	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
220
	{ "identityfile", oIdentityFile },
221
	{ "identityfile2", oIdentityFile },			/* obsolete */
222
	{ "identitiesonly", oIdentitiesOnly },
223
	{ "certificatefile", oCertificateFile },
224
	{ "addkeystoagent", oAddKeysToAgent },
225
	{ "identityagent", oIdentityAgent },
226
	{ "hostname", oHostName },
227
	{ "hostkeyalias", oHostKeyAlias },
228
	{ "proxycommand", oProxyCommand },
229
	{ "port", oPort },
230
	{ "ciphers", oCiphers },
231
	{ "macs", oMacs },
232
	{ "remoteforward", oRemoteForward },
233
	{ "localforward", oLocalForward },
234
	{ "user", oUser },
235
	{ "host", oHost },
236
	{ "match", oMatch },
237
	{ "escapechar", oEscapeChar },
238
	{ "globalknownhostsfile", oGlobalKnownHostsFile },
239
	{ "userknownhostsfile", oUserKnownHostsFile },
240
	{ "connectionattempts", oConnectionAttempts },
241
	{ "batchmode", oBatchMode },
242
	{ "checkhostip", oCheckHostIP },
243
	{ "stricthostkeychecking", oStrictHostKeyChecking },
244
	{ "compression", oCompression },
245
	{ "tcpkeepalive", oTCPKeepAlive },
246
	{ "keepalive", oTCPKeepAlive },				/* obsolete */
247
	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
248
	{ "syslogfacility", oLogFacility },
249
	{ "loglevel", oLogLevel },
250
	{ "dynamicforward", oDynamicForward },
251
	{ "preferredauthentications", oPreferredAuthentications },
252
	{ "hostkeyalgorithms", oHostKeyAlgorithms },
253
	{ "bindaddress", oBindAddress },
254
	{ "clearallforwardings", oClearAllForwardings },
255
	{ "enablesshkeysign", oEnableSSHKeysign },
256
	{ "verifyhostkeydns", oVerifyHostKeyDNS },
257
	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
258
	{ "rekeylimit", oRekeyLimit },
259
	{ "connecttimeout", oConnectTimeout },
260
	{ "addressfamily", oAddressFamily },
261
	{ "serveraliveinterval", oServerAliveInterval },
262
	{ "serveralivecountmax", oServerAliveCountMax },
263
	{ "sendenv", oSendEnv },
264
	{ "controlpath", oControlPath },
265
	{ "controlmaster", oControlMaster },
266
	{ "controlpersist", oControlPersist },
267
	{ "hashknownhosts", oHashKnownHosts },
268
	{ "include", oInclude },
269
	{ "tunnel", oTunnel },
270
	{ "tunneldevice", oTunnelDevice },
271
	{ "localcommand", oLocalCommand },
272
	{ "permitlocalcommand", oPermitLocalCommand },
273
	{ "remotecommand", oRemoteCommand },
274
	{ "visualhostkey", oVisualHostKey },
275
	{ "kexalgorithms", oKexAlgorithms },
276
	{ "ipqos", oIPQoS },
277
	{ "requesttty", oRequestTTY },
278
	{ "proxyusefdpass", oProxyUseFdpass },
279
	{ "canonicaldomains", oCanonicalDomains },
280
	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
281
	{ "canonicalizehostname", oCanonicalizeHostname },
282
	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
283
	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
284
	{ "streamlocalbindmask", oStreamLocalBindMask },
285
	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
286
	{ "revokedhostkeys", oRevokedHostKeys },
287
	{ "fingerprinthash", oFingerprintHash },
288
	{ "updatehostkeys", oUpdateHostkeys },
289
	{ "hostbasedkeytypes", oHostbasedKeyTypes },
290
	{ "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
291
	{ "ignoreunknown", oIgnoreUnknown },
292
	{ "proxyjump", oProxyJump },
293
294
	{ NULL, oBadOption }
295
};
296
297
/*
298
 * Adds a local TCP/IP port forward to options.  Never returns if there is an
299
 * error.
300
 */
301
302
void
303
add_local_forward(Options *options, const struct Forward *newfwd)
304
{
305
	struct Forward *fwd;
306
	extern uid_t original_real_uid;
307
	int i;
308
309
	if (!bind_permitted(newfwd->listen_port, original_real_uid) &&
310
	    newfwd->listen_path == NULL)
311
		fatal("Privileged ports can only be forwarded by root.");
312
	/* Don't add duplicates */
313
	for (i = 0; i < options->num_local_forwards; i++) {
314
		if (forward_equals(newfwd, options->local_forwards + i))
315
			return;
316
	}
317
	options->local_forwards = xreallocarray(options->local_forwards,
318
	    options->num_local_forwards + 1,
319
	    sizeof(*options->local_forwards));
320
	fwd = &options->local_forwards[options->num_local_forwards++];
321
322
	fwd->listen_host = newfwd->listen_host;
323
	fwd->listen_port = newfwd->listen_port;
324
	fwd->listen_path = newfwd->listen_path;
325
	fwd->connect_host = newfwd->connect_host;
326
	fwd->connect_port = newfwd->connect_port;
327
	fwd->connect_path = newfwd->connect_path;
328
}
329
330
/*
331
 * Adds a remote TCP/IP port forward to options.  Never returns if there is
332
 * an error.
333
 */
334
335
void
336
add_remote_forward(Options *options, const struct Forward *newfwd)
337
{
338
	struct Forward *fwd;
339
	int i;
340
341
	/* Don't add duplicates */
342
	for (i = 0; i < options->num_remote_forwards; i++) {
343
		if (forward_equals(newfwd, options->remote_forwards + i))
344
			return;
345
	}
346
	options->remote_forwards = xreallocarray(options->remote_forwards,
347
	    options->num_remote_forwards + 1,
348
	    sizeof(*options->remote_forwards));
349
	fwd = &options->remote_forwards[options->num_remote_forwards++];
350
351
	fwd->listen_host = newfwd->listen_host;
352
	fwd->listen_port = newfwd->listen_port;
353
	fwd->listen_path = newfwd->listen_path;
354
	fwd->connect_host = newfwd->connect_host;
355
	fwd->connect_port = newfwd->connect_port;
356
	fwd->connect_path = newfwd->connect_path;
357
	fwd->handle = newfwd->handle;
358
	fwd->allocated_port = 0;
359
}
360
361
static void
362
clear_forwardings(Options *options)
363
{
364
	int i;
365
366
	for (i = 0; i < options->num_local_forwards; i++) {
367
		free(options->local_forwards[i].listen_host);
368
		free(options->local_forwards[i].listen_path);
369
		free(options->local_forwards[i].connect_host);
370
		free(options->local_forwards[i].connect_path);
371
	}
372
	if (options->num_local_forwards > 0) {
373
		free(options->local_forwards);
374
		options->local_forwards = NULL;
375
	}
376
	options->num_local_forwards = 0;
377
	for (i = 0; i < options->num_remote_forwards; i++) {
378
		free(options->remote_forwards[i].listen_host);
379
		free(options->remote_forwards[i].listen_path);
380
		free(options->remote_forwards[i].connect_host);
381
		free(options->remote_forwards[i].connect_path);
382
	}
383
	if (options->num_remote_forwards > 0) {
384
		free(options->remote_forwards);
385
		options->remote_forwards = NULL;
386
	}
387
	options->num_remote_forwards = 0;
388
	options->tun_open = SSH_TUNMODE_NO;
389
}
390
391
void
392
add_certificate_file(Options *options, const char *path, int userprovided)
393
{
394
	int i;
395
396
	if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
397
		fatal("Too many certificate files specified (max %d)",
398
		    SSH_MAX_CERTIFICATE_FILES);
399
400
	/* Avoid registering duplicates */
401
	for (i = 0; i < options->num_certificate_files; i++) {
402
		if (options->certificate_file_userprovided[i] == userprovided &&
403
		    strcmp(options->certificate_files[i], path) == 0) {
404
			debug2("%s: ignoring duplicate key %s", __func__, path);
405
			return;
406
		}
407
	}
408
409
	options->certificate_file_userprovided[options->num_certificate_files] =
410
	    userprovided;
411
	options->certificate_files[options->num_certificate_files++] =
412
	    xstrdup(path);
413
}
414
415
void
416
add_identity_file(Options *options, const char *dir, const char *filename,
417
    int userprovided)
418
{
419
	char *path;
420
	int i;
421
422
	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
423
		fatal("Too many identity files specified (max %d)",
424
		    SSH_MAX_IDENTITY_FILES);
425
426
	if (dir == NULL) /* no dir, filename is absolute */
427
		path = xstrdup(filename);
428
	else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
429
		fatal("Identity file path %s too long", path);
430
431
	/* Avoid registering duplicates */
432
	for (i = 0; i < options->num_identity_files; i++) {
433
		if (options->identity_file_userprovided[i] == userprovided &&
434
		    strcmp(options->identity_files[i], path) == 0) {
435
			debug2("%s: ignoring duplicate key %s", __func__, path);
436
			free(path);
437
			return;
438
		}
439
	}
440
441
	options->identity_file_userprovided[options->num_identity_files] =
442
	    userprovided;
443
	options->identity_files[options->num_identity_files++] = path;
444
}
445
446
int
447
default_ssh_port(void)
448
{
449
	static int port;
450
	struct servent *sp;
451
452
	if (port == 0) {
453
		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
454
		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
455
	}
456
	return port;
457
}
458
459
/*
460
 * Execute a command in a shell.
461
 * Return its exit status or -1 on abnormal exit.
462
 */
463
static int
464
execute_in_shell(const char *cmd)
465
{
466
	char *shell;
467
	pid_t pid;
468
	int devnull, status;
469
	extern uid_t original_real_uid;
470
471
	if ((shell = getenv("SHELL")) == NULL)
472
		shell = _PATH_BSHELL;
473
474
	/* Need this to redirect subprocess stdin/out */
475
	if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
476
		fatal("open(/dev/null): %s", strerror(errno));
477
478
	debug("Executing command: '%.500s'", cmd);
479
480
	/* Fork and execute the command. */
481
	if ((pid = fork()) == 0) {
482
		char *argv[4];
483
484
		/* Child.  Permanently give up superuser privileges. */
485
		permanently_drop_suid(original_real_uid);
486
487
		/* Redirect child stdin and stdout. Leave stderr */
488
		if (dup2(devnull, STDIN_FILENO) == -1)
489
			fatal("dup2: %s", strerror(errno));
490
		if (dup2(devnull, STDOUT_FILENO) == -1)
491
			fatal("dup2: %s", strerror(errno));
492
		if (devnull > STDERR_FILENO)
493
			close(devnull);
494
		closefrom(STDERR_FILENO + 1);
495
496
		argv[0] = shell;
497
		argv[1] = "-c";
498
		argv[2] = xstrdup(cmd);
499
		argv[3] = NULL;
500
501
		execv(argv[0], argv);
502
		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
503
		/* Die with signal to make this error apparent to parent. */
504
		signal(SIGTERM, SIG_DFL);
505
		kill(getpid(), SIGTERM);
506
		_exit(1);
507
	}
508
	/* Parent. */
509
	if (pid < 0)
510
		fatal("%s: fork: %.100s", __func__, strerror(errno));
511
512
	close(devnull);
513
514
	while (waitpid(pid, &status, 0) == -1) {
515
		if (errno != EINTR && errno != EAGAIN)
516
			fatal("%s: waitpid: %s", __func__, strerror(errno));
517
	}
518
	if (!WIFEXITED(status)) {
519
		error("command '%.100s' exited abnormally", cmd);
520
		return -1;
521
	}
522
	debug3("command returned status %d", WEXITSTATUS(status));
523
	return WEXITSTATUS(status);
524
}
525
526
/*
527
 * Parse and execute a Match directive.
528
 */
529
static int
530
match_cfg_line(Options *options, char **condition, struct passwd *pw,
531
    const char *host_arg, const char *original_host, int post_canon,
532
    const char *filename, int linenum)
533
{
534
	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
535
	const char *ruser;
536
	int r, port, this_result, result = 1, attributes = 0, negate;
537
	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
538
539
	/*
540
	 * Configuration is likely to be incomplete at this point so we
541
	 * must be prepared to use default values.
542
	 */
543
	port = options->port <= 0 ? default_ssh_port() : options->port;
544
	ruser = options->user == NULL ? pw->pw_name : options->user;
545
	if (post_canon) {
546
		host = xstrdup(options->hostname);
547
	} else if (options->hostname != NULL) {
548
		/* NB. Please keep in sync with ssh.c:main() */
549
		host = percent_expand(options->hostname,
550
		    "h", host_arg, (char *)NULL);
551
	} else {
552
		host = xstrdup(host_arg);
553
	}
554
555
	debug2("checking match for '%s' host %s originally %s",
556
	    cp, host, original_host);
557
	while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
558
		criteria = NULL;
559
		this_result = 1;
560
		if ((negate = attrib[0] == '!'))
561
			attrib++;
562
		/* criteria "all" and "canonical" have no argument */
563
		if (strcasecmp(attrib, "all") == 0) {
564
			if (attributes > 1 ||
565
			    ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
566
				error("%.200s line %d: '%s' cannot be combined "
567
				    "with other Match attributes",
568
				    filename, linenum, oattrib);
569
				result = -1;
570
				goto out;
571
			}
572
			if (result)
573
				result = negate ? 0 : 1;
574
			goto out;
575
		}
576
		attributes++;
577
		if (strcasecmp(attrib, "canonical") == 0) {
578
			r = !!post_canon;  /* force bitmask member to boolean */
579
			if (r == (negate ? 1 : 0))
580
				this_result = result = 0;
581
			debug3("%.200s line %d: %smatched '%s'",
582
			    filename, linenum,
583
			    this_result ? "" : "not ", oattrib);
584
			continue;
585
		}
586
		/* All other criteria require an argument */
587
		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
588
			error("Missing Match criteria for %s", attrib);
589
			result = -1;
590
			goto out;
591
		}
592
		if (strcasecmp(attrib, "host") == 0) {
593
			criteria = xstrdup(host);
594
			r = match_hostname(host, arg) == 1;
595
			if (r == (negate ? 1 : 0))
596
				this_result = result = 0;
597
		} else if (strcasecmp(attrib, "originalhost") == 0) {
598
			criteria = xstrdup(original_host);
599
			r = match_hostname(original_host, arg) == 1;
600
			if (r == (negate ? 1 : 0))
601
				this_result = result = 0;
602
		} else if (strcasecmp(attrib, "user") == 0) {
603
			criteria = xstrdup(ruser);
604
			r = match_pattern_list(ruser, arg, 0) == 1;
605
			if (r == (negate ? 1 : 0))
606
				this_result = result = 0;
607
		} else if (strcasecmp(attrib, "localuser") == 0) {
608
			criteria = xstrdup(pw->pw_name);
609
			r = match_pattern_list(pw->pw_name, arg, 0) == 1;
610
			if (r == (negate ? 1 : 0))
611
				this_result = result = 0;
612
		} else if (strcasecmp(attrib, "exec") == 0) {
613
			if (gethostname(thishost, sizeof(thishost)) == -1)
614
				fatal("gethostname: %s", strerror(errno));
615
			strlcpy(shorthost, thishost, sizeof(shorthost));
616
			shorthost[strcspn(thishost, ".")] = '\0';
617
			snprintf(portstr, sizeof(portstr), "%d", port);
618
619
			cmd = percent_expand(arg,
620
			    "L", shorthost,
621
			    "d", pw->pw_dir,
622
			    "h", host,
623
			    "l", thishost,
624
			    "n", original_host,
625
			    "p", portstr,
626
			    "r", ruser,
627
			    "u", pw->pw_name,
628
			    (char *)NULL);
629
			if (result != 1) {
630
				/* skip execution if prior predicate failed */
631
				debug3("%.200s line %d: skipped exec "
632
				    "\"%.100s\"", filename, linenum, cmd);
633
				free(cmd);
634
				continue;
635
			}
636
			r = execute_in_shell(cmd);
637
			if (r == -1) {
638
				fatal("%.200s line %d: match exec "
639
				    "'%.100s' error", filename,
640
				    linenum, cmd);
641
			}
642
			criteria = xstrdup(cmd);
643
			free(cmd);
644
			/* Force exit status to boolean */
645
			r = r == 0;
646
			if (r == (negate ? 1 : 0))
647
				this_result = result = 0;
648
		} else {
649
			error("Unsupported Match attribute %s", attrib);
650
			result = -1;
651
			goto out;
652
		}
653
		debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
654
		    filename, linenum, this_result ? "": "not ",
655
		    oattrib, criteria);
656
		free(criteria);
657
	}
658
	if (attributes == 0) {
659
		error("One or more attributes required for Match");
660
		result = -1;
661
		goto out;
662
	}
663
 out:
664
	if (result != -1)
665
		debug2("match %sfound", result ? "" : "not ");
666
	*condition = cp;
667
	free(host);
668
	return result;
669
}
670
671
/*
672
 * Returns the number of the token pointed to by cp or oBadOption.
673
 */
674
static OpCodes
675
parse_token(const char *cp, const char *filename, int linenum,
676
    const char *ignored_unknown)
677
{
678
	int i;
679
680
	for (i = 0; keywords[i].name; i++)
681
		if (strcmp(cp, keywords[i].name) == 0)
682
			return keywords[i].opcode;
683
	if (ignored_unknown != NULL &&
684
	    match_pattern_list(cp, ignored_unknown, 1) == 1)
685
		return oIgnoredUnknownOption;
686
	error("%s: line %d: Bad configuration option: %s",
687
	    filename, linenum, cp);
688
	return oBadOption;
689
}
690
691
/* Multistate option parsing */
692
struct multistate {
693
	char *key;
694
	int value;
695
};
696
static const struct multistate multistate_flag[] = {
697
	{ "true",			1 },
698
	{ "false",			0 },
699
	{ "yes",			1 },
700
	{ "no",				0 },
701
	{ NULL, -1 }
702
};
703
static const struct multistate multistate_yesnoask[] = {
704
	{ "true",			1 },
705
	{ "false",			0 },
706
	{ "yes",			1 },
707
	{ "no",				0 },
708
	{ "ask",			2 },
709
	{ NULL, -1 }
710
};
711
static const struct multistate multistate_strict_hostkey[] = {
712
	{ "true",			SSH_STRICT_HOSTKEY_YES },
713
	{ "false",			SSH_STRICT_HOSTKEY_OFF },
714
	{ "yes",			SSH_STRICT_HOSTKEY_YES },
715
	{ "no",				SSH_STRICT_HOSTKEY_OFF },
716
	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
717
	{ "off",			SSH_STRICT_HOSTKEY_OFF },
718
	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
719
	{ NULL, -1 }
720
};
721
static const struct multistate multistate_yesnoaskconfirm[] = {
722
	{ "true",			1 },
723
	{ "false",			0 },
724
	{ "yes",			1 },
725
	{ "no",				0 },
726
	{ "ask",			2 },
727
	{ "confirm",			3 },
728
	{ NULL, -1 }
729
};
730
static const struct multistate multistate_addressfamily[] = {
731
	{ "inet",			AF_INET },
732
	{ "inet6",			AF_INET6 },
733
	{ "any",			AF_UNSPEC },
734
	{ NULL, -1 }
735
};
736
static const struct multistate multistate_controlmaster[] = {
737
	{ "true",			SSHCTL_MASTER_YES },
738
	{ "yes",			SSHCTL_MASTER_YES },
739
	{ "false",			SSHCTL_MASTER_NO },
740
	{ "no",				SSHCTL_MASTER_NO },
741
	{ "auto",			SSHCTL_MASTER_AUTO },
742
	{ "ask",			SSHCTL_MASTER_ASK },
743
	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
744
	{ NULL, -1 }
745
};
746
static const struct multistate multistate_tunnel[] = {
747
	{ "ethernet",			SSH_TUNMODE_ETHERNET },
748
	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
749
	{ "true",			SSH_TUNMODE_DEFAULT },
750
	{ "yes",			SSH_TUNMODE_DEFAULT },
751
	{ "false",			SSH_TUNMODE_NO },
752
	{ "no",				SSH_TUNMODE_NO },
753
	{ NULL, -1 }
754
};
755
static const struct multistate multistate_requesttty[] = {
756
	{ "true",			REQUEST_TTY_YES },
757
	{ "yes",			REQUEST_TTY_YES },
758
	{ "false",			REQUEST_TTY_NO },
759
	{ "no",				REQUEST_TTY_NO },
760
	{ "force",			REQUEST_TTY_FORCE },
761
	{ "auto",			REQUEST_TTY_AUTO },
762
	{ NULL, -1 }
763
};
764
static const struct multistate multistate_canonicalizehostname[] = {
765
	{ "true",			SSH_CANONICALISE_YES },
766
	{ "false",			SSH_CANONICALISE_NO },
767
	{ "yes",			SSH_CANONICALISE_YES },
768
	{ "no",				SSH_CANONICALISE_NO },
769
	{ "always",			SSH_CANONICALISE_ALWAYS },
770
	{ NULL, -1 }
771
};
772
773
/*
774
 * Processes a single option line as used in the configuration files. This
775
 * only sets those values that have not already been set.
776
 */
777
int
778
process_config_line(Options *options, struct passwd *pw, const char *host,
779
    const char *original_host, char *line, const char *filename,
780
    int linenum, int *activep, int flags)
781
{
782
	return process_config_line_depth(options, pw, host, original_host,
783
	    line, filename, linenum, activep, flags, 0);
784
}
785
786
#define WHITESPACE " \t\r\n"
787
static int
788
process_config_line_depth(Options *options, struct passwd *pw, const char *host,
789
    const char *original_host, char *line, const char *filename,
790
    int linenum, int *activep, int flags, int depth)
791
{
792
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
793
	char **cpptr, fwdarg[256];
794
	u_int i, *uintptr, max_entries = 0;
795
	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
796
	int remotefwd, dynamicfwd;
797
	LogLevel *log_level_ptr;
798
	SyslogFacility *log_facility_ptr;
799
	long long val64;
800
	size_t len;
801
	struct Forward fwd;
802
	const struct multistate *multistate_ptr;
803
	struct allowed_cname *cname;
804
	glob_t gl;
805
806
	if (activep == NULL) { /* We are processing a command line directive */
807
		cmdline = 1;
808
		activep = &cmdline;
809
	}
810
811
	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
812
	if ((len = strlen(line)) == 0)
813
		return 0;
814
	for (len--; len > 0; len--) {
815
		if (strchr(WHITESPACE "\f", line[len]) == NULL)
816
			break;
817
		line[len] = '\0';
818
	}
819
820
	s = line;
821
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
822
	if ((keyword = strdelim(&s)) == NULL)
823
		return 0;
824
	/* Ignore leading whitespace. */
825
	if (*keyword == '\0')
826
		keyword = strdelim(&s);
827
	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
828
		return 0;
829
	/* Match lowercase keyword */
830
	lowercase(keyword);
831
832
	opcode = parse_token(keyword, filename, linenum,
833
	    options->ignored_unknown);
834
835
	switch (opcode) {
836
	case oBadOption:
837
		/* don't panic, but count bad options */
838
		return -1;
839
	case oIgnore:
840
		return 0;
841
	case oIgnoredUnknownOption:
842
		debug("%s line %d: Ignored unknown option \"%s\"",
843
		    filename, linenum, keyword);
844
		return 0;
845
	case oConnectTimeout:
846
		intptr = &options->connection_timeout;
847
parse_time:
848
		arg = strdelim(&s);
849
		if (!arg || *arg == '\0')
850
			fatal("%s line %d: missing time value.",
851
			    filename, linenum);
852
		if (strcmp(arg, "none") == 0)
853
			value = -1;
854
		else if ((value = convtime(arg)) == -1)
855
			fatal("%s line %d: invalid time value.",
856
			    filename, linenum);
857
		if (*activep && *intptr == -1)
858
			*intptr = value;
859
		break;
860
861
	case oForwardAgent:
862
		intptr = &options->forward_agent;
863
 parse_flag:
864
		multistate_ptr = multistate_flag;
865
 parse_multistate:
866
		arg = strdelim(&s);
867
		if (!arg || *arg == '\0')
868
			fatal("%s line %d: missing argument.",
869
			    filename, linenum);
870
		value = -1;
871
		for (i = 0; multistate_ptr[i].key != NULL; i++) {
872
			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
873
				value = multistate_ptr[i].value;
874
				break;
875
			}
876
		}
877
		if (value == -1)
878
			fatal("%s line %d: unsupported option \"%s\".",
879
			    filename, linenum, arg);
880
		if (*activep && *intptr == -1)
881
			*intptr = value;
882
		break;
883
884
	case oForwardX11:
885
		intptr = &options->forward_x11;
886
		goto parse_flag;
887
888
	case oForwardX11Trusted:
889
		intptr = &options->forward_x11_trusted;
890
		goto parse_flag;
891
892
	case oForwardX11Timeout:
893
		intptr = &options->forward_x11_timeout;
894
		goto parse_time;
895
896
	case oGatewayPorts:
897
		intptr = &options->fwd_opts.gateway_ports;
898
		goto parse_flag;
899
900
	case oExitOnForwardFailure:
901
		intptr = &options->exit_on_forward_failure;
902
		goto parse_flag;
903
904
	case oUsePrivilegedPort:
905
		intptr = &options->use_privileged_port;
906
		goto parse_flag;
907
908
	case oPasswordAuthentication:
909
		intptr = &options->password_authentication;
910
		goto parse_flag;
911
912
	case oKbdInteractiveAuthentication:
913
		intptr = &options->kbd_interactive_authentication;
914
		goto parse_flag;
915
916
	case oKbdInteractiveDevices:
917
		charptr = &options->kbd_interactive_devices;
918
		goto parse_string;
919
920
	case oPubkeyAuthentication:
921
		intptr = &options->pubkey_authentication;
922
		goto parse_flag;
923
924
	case oHostbasedAuthentication:
925
		intptr = &options->hostbased_authentication;
926
		goto parse_flag;
927
928
	case oChallengeResponseAuthentication:
929
		intptr = &options->challenge_response_authentication;
930
		goto parse_flag;
931
932
	case oGssAuthentication:
933
		intptr = &options->gss_authentication;
934
		goto parse_flag;
935
936
	case oGssDelegateCreds:
937
		intptr = &options->gss_deleg_creds;
938
		goto parse_flag;
939
940
	case oBatchMode:
941
		intptr = &options->batch_mode;
942
		goto parse_flag;
943
944
	case oCheckHostIP:
945
		intptr = &options->check_host_ip;
946
		goto parse_flag;
947
948
	case oVerifyHostKeyDNS:
949
		intptr = &options->verify_host_key_dns;
950
		multistate_ptr = multistate_yesnoask;
951
		goto parse_multistate;
952
953
	case oStrictHostKeyChecking:
954
		intptr = &options->strict_host_key_checking;
955
		multistate_ptr = multistate_strict_hostkey;
956
		goto parse_multistate;
957
958
	case oCompression:
959
		intptr = &options->compression;
960
		goto parse_flag;
961
962
	case oTCPKeepAlive:
963
		intptr = &options->tcp_keep_alive;
964
		goto parse_flag;
965
966
	case oNoHostAuthenticationForLocalhost:
967
		intptr = &options->no_host_authentication_for_localhost;
968
		goto parse_flag;
969
970
	case oNumberOfPasswordPrompts:
971
		intptr = &options->number_of_password_prompts;
972
		goto parse_int;
973
974
	case oRekeyLimit:
975
		arg = strdelim(&s);
976
		if (!arg || *arg == '\0')
977
			fatal("%.200s line %d: Missing argument.", filename,
978
			    linenum);
979
		if (strcmp(arg, "default") == 0) {
980
			val64 = 0;
981
		} else {
982
			if (scan_scaled(arg, &val64) == -1)
983
				fatal("%.200s line %d: Bad number '%s': %s",
984
				    filename, linenum, arg, strerror(errno));
985
			if (val64 != 0 && val64 < 16)
986
				fatal("%.200s line %d: RekeyLimit too small",
987
				    filename, linenum);
988
		}
989
		if (*activep && options->rekey_limit == -1)
990
			options->rekey_limit = val64;
991
		if (s != NULL) { /* optional rekey interval present */
992
			if (strcmp(s, "none") == 0) {
993
				(void)strdelim(&s);	/* discard */
994
				break;
995
			}
996
			intptr = &options->rekey_interval;
997
			goto parse_time;
998
		}
999
		break;
1000
1001
	case oIdentityFile:
1002
		arg = strdelim(&s);
1003
		if (!arg || *arg == '\0')
1004
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1005
		if (*activep) {
1006
			intptr = &options->num_identity_files;
1007
			if (*intptr >= SSH_MAX_IDENTITY_FILES)
1008
				fatal("%.200s line %d: Too many identity files specified (max %d).",
1009
				    filename, linenum, SSH_MAX_IDENTITY_FILES);
1010
			add_identity_file(options, NULL,
1011
			    arg, flags & SSHCONF_USERCONF);
1012
		}
1013
		break;
1014
1015
	case oCertificateFile:
1016
		arg = strdelim(&s);
1017
		if (!arg || *arg == '\0')
1018
			fatal("%.200s line %d: Missing argument.",
1019
			    filename, linenum);
1020
		if (*activep) {
1021
			intptr = &options->num_certificate_files;
1022
			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1023
				fatal("%.200s line %d: Too many certificate "
1024
				    "files specified (max %d).",
1025
				    filename, linenum,
1026
				    SSH_MAX_CERTIFICATE_FILES);
1027
			}
1028
			add_certificate_file(options, arg,
1029
			    flags & SSHCONF_USERCONF);
1030
		}
1031
		break;
1032
1033
	case oXAuthLocation:
1034
		charptr=&options->xauth_location;
1035
		goto parse_string;
1036
1037
	case oUser:
1038
		charptr = &options->user;
1039
parse_string:
1040
		arg = strdelim(&s);
1041
		if (!arg || *arg == '\0')
1042
			fatal("%.200s line %d: Missing argument.",
1043
			    filename, linenum);
1044
		if (*activep && *charptr == NULL)
1045
			*charptr = xstrdup(arg);
1046
		break;
1047
1048
	case oGlobalKnownHostsFile:
1049
		cpptr = (char **)&options->system_hostfiles;
1050
		uintptr = &options->num_system_hostfiles;
1051
		max_entries = SSH_MAX_HOSTS_FILES;
1052
parse_char_array:
1053
		if (*activep && *uintptr == 0) {
1054
			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1055
				if ((*uintptr) >= max_entries)
1056
					fatal("%s line %d: "
1057
					    "too many authorized keys files.",
1058
					    filename, linenum);
1059
				cpptr[(*uintptr)++] = xstrdup(arg);
1060
			}
1061
		}
1062
		return 0;
1063
1064
	case oUserKnownHostsFile:
1065
		cpptr = (char **)&options->user_hostfiles;
1066
		uintptr = &options->num_user_hostfiles;
1067
		max_entries = SSH_MAX_HOSTS_FILES;
1068
		goto parse_char_array;
1069
1070
	case oHostName:
1071
		charptr = &options->hostname;
1072
		goto parse_string;
1073
1074
	case oHostKeyAlias:
1075
		charptr = &options->host_key_alias;
1076
		goto parse_string;
1077
1078
	case oPreferredAuthentications:
1079
		charptr = &options->preferred_authentications;
1080
		goto parse_string;
1081
1082
	case oBindAddress:
1083
		charptr = &options->bind_address;
1084
		goto parse_string;
1085
1086
	case oPKCS11Provider:
1087
		charptr = &options->pkcs11_provider;
1088
		goto parse_string;
1089
1090
	case oProxyCommand:
1091
		charptr = &options->proxy_command;
1092
		/* Ignore ProxyCommand if ProxyJump already specified */
1093
		if (options->jump_host != NULL)
1094
			charptr = &options->jump_host; /* Skip below */
1095
parse_command:
1096
		if (s == NULL)
1097
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1098
		len = strspn(s, WHITESPACE "=");
1099
		if (*activep && *charptr == NULL)
1100
			*charptr = xstrdup(s + len);
1101
		return 0;
1102
1103
	case oProxyJump:
1104
		if (s == NULL) {
1105
			fatal("%.200s line %d: Missing argument.",
1106
			    filename, linenum);
1107
		}
1108
		len = strspn(s, WHITESPACE "=");
1109
		if (parse_jump(s + len, options, *activep) == -1) {
1110
			fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
1111
			    filename, linenum, s + len);
1112
		}
1113
		return 0;
1114
1115
	case oPort:
1116
		intptr = &options->port;
1117
parse_int:
1118
		arg = strdelim(&s);
1119
		if (!arg || *arg == '\0')
1120
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1121
		if (arg[0] < '0' || arg[0] > '9')
1122
			fatal("%.200s line %d: Bad number.", filename, linenum);
1123
1124
		/* Octal, decimal, or hex format? */
1125
		value = strtol(arg, &endofnumber, 0);
1126
		if (arg == endofnumber)
1127
			fatal("%.200s line %d: Bad number.", filename, linenum);
1128
		if (*activep && *intptr == -1)
1129
			*intptr = value;
1130
		break;
1131
1132
	case oConnectionAttempts:
1133
		intptr = &options->connection_attempts;
1134
		goto parse_int;
1135
1136
	case oCiphers:
1137
		arg = strdelim(&s);
1138
		if (!arg || *arg == '\0')
1139
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1140
		if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
1141
			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1142
			    filename, linenum, arg ? arg : "<NONE>");
1143
		if (*activep && options->ciphers == NULL)
1144
			options->ciphers = xstrdup(arg);
1145
		break;
1146
1147
	case oMacs:
1148
		arg = strdelim(&s);
1149
		if (!arg || *arg == '\0')
1150
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1151
		if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
1152
			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1153
			    filename, linenum, arg ? arg : "<NONE>");
1154
		if (*activep && options->macs == NULL)
1155
			options->macs = xstrdup(arg);
1156
		break;
1157
1158
	case oKexAlgorithms:
1159
		arg = strdelim(&s);
1160
		if (!arg || *arg == '\0')
1161
			fatal("%.200s line %d: Missing argument.",
1162
			    filename, linenum);
1163
		if (*arg != '-' &&
1164
		    !kex_names_valid(*arg == '+' ? arg + 1 : arg))
1165
			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1166
			    filename, linenum, arg ? arg : "<NONE>");
1167
		if (*activep && options->kex_algorithms == NULL)
1168
			options->kex_algorithms = xstrdup(arg);
1169
		break;
1170
1171
	case oHostKeyAlgorithms:
1172
		charptr = &options->hostkeyalgorithms;
1173
parse_keytypes:
1174
		arg = strdelim(&s);
1175
		if (!arg || *arg == '\0')
1176
			fatal("%.200s line %d: Missing argument.",
1177
			    filename, linenum);
1178
		if (*arg != '-' &&
1179
		    !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1180
			fatal("%s line %d: Bad key types '%s'.",
1181
				filename, linenum, arg ? arg : "<NONE>");
1182
		if (*activep && *charptr == NULL)
1183
			*charptr = xstrdup(arg);
1184
		break;
1185
1186
	case oLogLevel:
1187
		log_level_ptr = &options->log_level;
1188
		arg = strdelim(&s);
1189
		value = log_level_number(arg);
1190
		if (value == SYSLOG_LEVEL_NOT_SET)
1191
			fatal("%.200s line %d: unsupported log level '%s'",
1192
			    filename, linenum, arg ? arg : "<NONE>");
1193
		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1194
			*log_level_ptr = (LogLevel) value;
1195
		break;
1196
1197
	case oLogFacility:
1198
		log_facility_ptr = &options->log_facility;
1199
		arg = strdelim(&s);
1200
		value = log_facility_number(arg);
1201
		if (value == SYSLOG_FACILITY_NOT_SET)
1202
			fatal("%.200s line %d: unsupported log facility '%s'",
1203
			    filename, linenum, arg ? arg : "<NONE>");
1204
		if (*log_facility_ptr == -1)
1205
			*log_facility_ptr = (SyslogFacility) value;
1206
		break;
1207
1208
	case oLocalForward:
1209
	case oRemoteForward:
1210
	case oDynamicForward:
1211
		arg = strdelim(&s);
1212
		if (arg == NULL || *arg == '\0')
1213
			fatal("%.200s line %d: Missing port argument.",
1214
			    filename, linenum);
1215
1216
		remotefwd = (opcode == oRemoteForward);
1217
		dynamicfwd = (opcode == oDynamicForward);
1218
1219
		if (!dynamicfwd) {
1220
			arg2 = strdelim(&s);
1221
			if (arg2 == NULL || *arg2 == '\0') {
1222
				if (remotefwd)
1223
					dynamicfwd = 1;
1224
				else
1225
					fatal("%.200s line %d: Missing target "
1226
					    "argument.", filename, linenum);
1227
			} else {
1228
				/* construct a string for parse_forward */
1229
				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1230
				    arg2);
1231
			}
1232
		}
1233
		if (dynamicfwd)
1234
			strlcpy(fwdarg, arg, sizeof(fwdarg));
1235
1236
		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1237
			fatal("%.200s line %d: Bad forwarding specification.",
1238
			    filename, linenum);
1239
1240
		if (*activep) {
1241
			if (remotefwd) {
1242
				add_remote_forward(options, &fwd);
1243
			} else {
1244
				add_local_forward(options, &fwd);
1245
			}
1246
		}
1247
		break;
1248
1249
	case oClearAllForwardings:
1250
		intptr = &options->clear_forwardings;
1251
		goto parse_flag;
1252
1253
	case oHost:
1254
		if (cmdline)
1255
			fatal("Host directive not supported as a command-line "
1256
			    "option");
1257
		*activep = 0;
1258
		arg2 = NULL;
1259
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1260
			if ((flags & SSHCONF_NEVERMATCH) != 0)
1261
				break;
1262
			negated = *arg == '!';
1263
			if (negated)
1264
				arg++;
1265
			if (match_pattern(host, arg)) {
1266
				if (negated) {
1267
					debug("%.200s line %d: Skipping Host "
1268
					    "block because of negated match "
1269
					    "for %.100s", filename, linenum,
1270
					    arg);
1271
					*activep = 0;
1272
					break;
1273
				}
1274
				if (!*activep)
1275
					arg2 = arg; /* logged below */
1276
				*activep = 1;
1277
			}
1278
		}
1279
		if (*activep)
1280
			debug("%.200s line %d: Applying options for %.100s",
1281
			    filename, linenum, arg2);
1282
		/* Avoid garbage check below, as strdelim is done. */
1283
		return 0;
1284
1285
	case oMatch:
1286
		if (cmdline)
1287
			fatal("Host directive not supported as a command-line "
1288
			    "option");
1289
		value = match_cfg_line(options, &s, pw, host, original_host,
1290
		    flags & SSHCONF_POSTCANON, filename, linenum);
1291
		if (value < 0)
1292
			fatal("%.200s line %d: Bad Match condition", filename,
1293
			    linenum);
1294
		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1295
		break;
1296
1297
	case oEscapeChar:
1298
		intptr = &options->escape_char;
1299
		arg = strdelim(&s);
1300
		if (!arg || *arg == '\0')
1301
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1302
		if (strcmp(arg, "none") == 0)
1303
			value = SSH_ESCAPECHAR_NONE;
1304
		else if (arg[1] == '\0')
1305
			value = (u_char) arg[0];
1306
		else if (arg[0] == '^' && arg[2] == 0 &&
1307
		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1308
			value = (u_char) arg[1] & 31;
1309
		else {
1310
			fatal("%.200s line %d: Bad escape character.",
1311
			    filename, linenum);
1312
			/* NOTREACHED */
1313
			value = 0;	/* Avoid compiler warning. */
1314
		}
1315
		if (*activep && *intptr == -1)
1316
			*intptr = value;
1317
		break;
1318
1319
	case oAddressFamily:
1320
		intptr = &options->address_family;
1321
		multistate_ptr = multistate_addressfamily;
1322
		goto parse_multistate;
1323
1324
	case oEnableSSHKeysign:
1325
		intptr = &options->enable_ssh_keysign;
1326
		goto parse_flag;
1327
1328
	case oIdentitiesOnly:
1329
		intptr = &options->identities_only;
1330
		goto parse_flag;
1331
1332
	case oServerAliveInterval:
1333
		intptr = &options->server_alive_interval;
1334
		goto parse_time;
1335
1336
	case oServerAliveCountMax:
1337
		intptr = &options->server_alive_count_max;
1338
		goto parse_int;
1339
1340
	case oSendEnv:
1341
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1342
			if (strchr(arg, '=') != NULL)
1343
				fatal("%s line %d: Invalid environment name.",
1344
				    filename, linenum);
1345
			if (!*activep)
1346
				continue;
1347
			if (options->num_send_env >= MAX_SEND_ENV)
1348
				fatal("%s line %d: too many send env.",
1349
				    filename, linenum);
1350
			options->send_env[options->num_send_env++] =
1351
			    xstrdup(arg);
1352
		}
1353
		break;
1354
1355
	case oControlPath:
1356
		charptr = &options->control_path;
1357
		goto parse_string;
1358
1359
	case oControlMaster:
1360
		intptr = &options->control_master;
1361
		multistate_ptr = multistate_controlmaster;
1362
		goto parse_multistate;
1363
1364
	case oControlPersist:
1365
		/* no/false/yes/true, or a time spec */
1366
		intptr = &options->control_persist;
1367
		arg = strdelim(&s);
1368
		if (!arg || *arg == '\0')
1369
			fatal("%.200s line %d: Missing ControlPersist"
1370
			    " argument.", filename, linenum);
1371
		value = 0;
1372
		value2 = 0;	/* timeout */
1373
		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1374
			value = 0;
1375
		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1376
			value = 1;
1377
		else if ((value2 = convtime(arg)) >= 0)
1378
			value = 1;
1379
		else
1380
			fatal("%.200s line %d: Bad ControlPersist argument.",
1381
			    filename, linenum);
1382
		if (*activep && *intptr == -1) {
1383
			*intptr = value;
1384
			options->control_persist_timeout = value2;
1385
		}
1386
		break;
1387
1388
	case oHashKnownHosts:
1389
		intptr = &options->hash_known_hosts;
1390
		goto parse_flag;
1391
1392
	case oTunnel:
1393
		intptr = &options->tun_open;
1394
		multistate_ptr = multistate_tunnel;
1395
		goto parse_multistate;
1396
1397
	case oTunnelDevice:
1398
		arg = strdelim(&s);
1399
		if (!arg || *arg == '\0')
1400
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1401
		value = a2tun(arg, &value2);
1402
		if (value == SSH_TUNID_ERR)
1403
			fatal("%.200s line %d: Bad tun device.", filename, linenum);
1404
		if (*activep) {
1405
			options->tun_local = value;
1406
			options->tun_remote = value2;
1407
		}
1408
		break;
1409
1410
	case oLocalCommand:
1411
		charptr = &options->local_command;
1412
		goto parse_command;
1413
1414
	case oPermitLocalCommand:
1415
		intptr = &options->permit_local_command;
1416
		goto parse_flag;
1417
1418
	case oRemoteCommand:
1419
		charptr = &options->remote_command;
1420
		goto parse_command;
1421
1422
	case oVisualHostKey:
1423
		intptr = &options->visual_host_key;
1424
		goto parse_flag;
1425
1426
	case oInclude:
1427
		if (cmdline)
1428
			fatal("Include directive not supported as a "
1429
			    "command-line option");
1430
		value = 0;
1431
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1432
			/*
1433
			 * Ensure all paths are anchored. User configuration
1434
			 * files may begin with '~/' but system configurations
1435
			 * must not. If the path is relative, then treat it
1436
			 * as living in ~/.ssh for user configurations or
1437
			 * /etc/ssh for system ones.
1438
			 */
1439
			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
1440
				fatal("%.200s line %d: bad include path %s.",
1441
				    filename, linenum, arg);
1442
			if (*arg != '/' && *arg != '~') {
1443
				xasprintf(&arg2, "%s/%s",
1444
				    (flags & SSHCONF_USERCONF) ?
1445
				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1446
			} else
1447
				arg2 = xstrdup(arg);
1448
			memset(&gl, 0, sizeof(gl));
1449
			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1450
			if (r == GLOB_NOMATCH) {
1451
				debug("%.200s line %d: include %s matched no "
1452
				    "files",filename, linenum, arg2);
1453
				free(arg2);
1454
				continue;
1455
			} else if (r != 0 || gl.gl_pathc < 0)
1456
				fatal("%.200s line %d: glob failed for %s.",
1457
				    filename, linenum, arg2);
1458
			free(arg2);
1459
			oactive = *activep;
1460
			for (i = 0; i < (u_int)gl.gl_pathc; i++) {
1461
				debug3("%.200s line %d: Including file %s "
1462
				    "depth %d%s", filename, linenum,
1463
				    gl.gl_pathv[i], depth,
1464
				    oactive ? "" : " (parse only)");
1465
				r = read_config_file_depth(gl.gl_pathv[i],
1466
				    pw, host, original_host, options,
1467
				    flags | SSHCONF_CHECKPERM |
1468
				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1469
				    activep, depth + 1);
1470
				if (r != 1 && errno != ENOENT) {
1471
					fatal("Can't open user config file "
1472
					    "%.100s: %.100s", gl.gl_pathv[i],
1473
					    strerror(errno));
1474
				}
1475
				/*
1476
				 * don't let Match in includes clobber the
1477
				 * containing file's Match state.
1478
				 */
1479
				*activep = oactive;
1480
				if (r != 1)
1481
					value = -1;
1482
			}
1483
			globfree(&gl);
1484
		}
1485
		if (value != 0)
1486
			return value;
1487
		break;
1488
1489
	case oIPQoS:
1490
		arg = strdelim(&s);
1491
		if ((value = parse_ipqos(arg)) == -1)
1492
			fatal("%s line %d: Bad IPQoS value: %s",
1493
			    filename, linenum, arg);
1494
		arg = strdelim(&s);
1495
		if (arg == NULL)
1496
			value2 = value;
1497
		else if ((value2 = parse_ipqos(arg)) == -1)
1498
			fatal("%s line %d: Bad IPQoS value: %s",
1499
			    filename, linenum, arg);
1500
		if (*activep) {
1501
			options->ip_qos_interactive = value;
1502
			options->ip_qos_bulk = value2;
1503
		}
1504
		break;
1505
1506
	case oRequestTTY:
1507
		intptr = &options->request_tty;
1508
		multistate_ptr = multistate_requesttty;
1509
		goto parse_multistate;
1510
1511
	case oIgnoreUnknown:
1512
		charptr = &options->ignored_unknown;
1513
		goto parse_string;
1514
1515
	case oProxyUseFdpass:
1516
		intptr = &options->proxy_use_fdpass;
1517
		goto parse_flag;
1518
1519
	case oCanonicalDomains:
1520
		value = options->num_canonical_domains != 0;
1521
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1522
			const char *errstr;
1523
			if (!valid_domain(arg, 1, &errstr)) {
1524
				fatal("%s line %d: %s", filename, linenum,
1525
				    errstr);
1526
			}
1527
			if (!*activep || value)
1528
				continue;
1529
			if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1530
				fatal("%s line %d: too many hostname suffixes.",
1531
				    filename, linenum);
1532
			options->canonical_domains[
1533
			    options->num_canonical_domains++] = xstrdup(arg);
1534
		}
1535
		break;
1536
1537
	case oCanonicalizePermittedCNAMEs:
1538
		value = options->num_permitted_cnames != 0;
1539
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1540
			/* Either '*' for everything or 'list:list' */
1541
			if (strcmp(arg, "*") == 0)
1542
				arg2 = arg;
1543
			else {
1544
				lowercase(arg);
1545
				if ((arg2 = strchr(arg, ':')) == NULL ||
1546
				    arg2[1] == '\0') {
1547
					fatal("%s line %d: "
1548
					    "Invalid permitted CNAME \"%s\"",
1549
					    filename, linenum, arg);
1550
				}
1551
				*arg2 = '\0';
1552
				arg2++;
1553
			}
1554
			if (!*activep || value)
1555
				continue;
1556
			if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1557
				fatal("%s line %d: too many permitted CNAMEs.",
1558
				    filename, linenum);
1559
			cname = options->permitted_cnames +
1560
			    options->num_permitted_cnames++;
1561
			cname->source_list = xstrdup(arg);
1562
			cname->target_list = xstrdup(arg2);
1563
		}
1564
		break;
1565
1566
	case oCanonicalizeHostname:
1567
		intptr = &options->canonicalize_hostname;
1568
		multistate_ptr = multistate_canonicalizehostname;
1569
		goto parse_multistate;
1570
1571
	case oCanonicalizeMaxDots:
1572
		intptr = &options->canonicalize_max_dots;
1573
		goto parse_int;
1574
1575
	case oCanonicalizeFallbackLocal:
1576
		intptr = &options->canonicalize_fallback_local;
1577
		goto parse_flag;
1578
1579
	case oStreamLocalBindMask:
1580
		arg = strdelim(&s);
1581
		if (!arg || *arg == '\0')
1582
			fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1583
		/* Parse mode in octal format */
1584
		value = strtol(arg, &endofnumber, 8);
1585
		if (arg == endofnumber || value < 0 || value > 0777)
1586
			fatal("%.200s line %d: Bad mask.", filename, linenum);
1587
		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1588
		break;
1589
1590
	case oStreamLocalBindUnlink:
1591
		intptr = &options->fwd_opts.streamlocal_bind_unlink;
1592
		goto parse_flag;
1593
1594
	case oRevokedHostKeys:
1595
		charptr = &options->revoked_host_keys;
1596
		goto parse_string;
1597
1598
	case oFingerprintHash:
1599
		intptr = &options->fingerprint_hash;
1600
		arg = strdelim(&s);
1601
		if (!arg || *arg == '\0')
1602
			fatal("%.200s line %d: Missing argument.",
1603
			    filename, linenum);
1604
		if ((value = ssh_digest_alg_by_name(arg)) == -1)
1605
			fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1606
			    filename, linenum, arg);
1607
		if (*activep && *intptr == -1)
1608
			*intptr = value;
1609
		break;
1610
1611
	case oUpdateHostkeys:
1612
		intptr = &options->update_hostkeys;
1613
		multistate_ptr = multistate_yesnoask;
1614
		goto parse_multistate;
1615
1616
	case oHostbasedKeyTypes:
1617
		charptr = &options->hostbased_key_types;
1618
		goto parse_keytypes;
1619
1620
	case oPubkeyAcceptedKeyTypes:
1621
		charptr = &options->pubkey_key_types;
1622
		goto parse_keytypes;
1623
1624
	case oAddKeysToAgent:
1625
		intptr = &options->add_keys_to_agent;
1626
		multistate_ptr = multistate_yesnoaskconfirm;
1627
		goto parse_multistate;
1628
1629
	case oIdentityAgent:
1630
		charptr = &options->identity_agent;
1631
		goto parse_string;
1632
1633
	case oDeprecated:
1634
		debug("%s line %d: Deprecated option \"%s\"",
1635
		    filename, linenum, keyword);
1636
		return 0;
1637
1638
	case oUnsupported:
1639
		error("%s line %d: Unsupported option \"%s\"",
1640
		    filename, linenum, keyword);
1641
		return 0;
1642
1643
	default:
1644
		fatal("%s: Unimplemented opcode %d", __func__, opcode);
1645
	}
1646
1647
	/* Check that there is no garbage at end of line. */
1648
	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1649
		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1650
		    filename, linenum, arg);
1651
	}
1652
	return 0;
1653
}
1654
1655
/*
1656
 * Reads the config file and modifies the options accordingly.  Options
1657
 * should already be initialized before this call.  This never returns if
1658
 * there is an error.  If the file does not exist, this returns 0.
1659
 */
1660
int
1661
read_config_file(const char *filename, struct passwd *pw, const char *host,
1662
    const char *original_host, Options *options, int flags)
1663
{
1664
	int active = 1;
1665
1666
	return read_config_file_depth(filename, pw, host, original_host,
1667
	    options, flags, &active, 0);
1668
}
1669
1670
#define READCONF_MAX_DEPTH	16
1671
static int
1672
read_config_file_depth(const char *filename, struct passwd *pw,
1673
    const char *host, const char *original_host, Options *options,
1674
    int flags, int *activep, int depth)
1675
{
1676
	FILE *f;
1677
	char line[4096];
1678
	int linenum;
1679
	int bad_options = 0;
1680
1681
	if (depth < 0 || depth > READCONF_MAX_DEPTH)
1682
		fatal("Too many recursive configuration includes");
1683
1684
	if ((f = fopen(filename, "r")) == NULL)
1685
		return 0;
1686
1687
	if (flags & SSHCONF_CHECKPERM) {
1688
		struct stat sb;
1689
1690
		if (fstat(fileno(f), &sb) == -1)
1691
			fatal("fstat %s: %s", filename, strerror(errno));
1692
		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1693
		    (sb.st_mode & 022) != 0))
1694
			fatal("Bad owner or permissions on %s", filename);
1695
	}
1696
1697
	debug("Reading configuration data %.200s", filename);
1698
1699
	/*
1700
	 * Mark that we are now processing the options.  This flag is turned
1701
	 * on/off by Host specifications.
1702
	 */
1703
	linenum = 0;
1704
	while (fgets(line, sizeof(line), f)) {
1705
		/* Update line number counter. */
1706
		linenum++;
1707
		if (strlen(line) == sizeof(line) - 1)
1708
			fatal("%s line %d too long", filename, linenum);
1709
		if (process_config_line_depth(options, pw, host, original_host,
1710
		    line, filename, linenum, activep, flags, depth) != 0)
1711
			bad_options++;
1712
	}
1713
	fclose(f);
1714
	if (bad_options > 0)
1715
		fatal("%s: terminating, %d bad configuration options",
1716
		    filename, bad_options);
1717
	return 1;
1718
}
1719
1720
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1721
int
1722
option_clear_or_none(const char *o)
1723
{
1724
	return o == NULL || strcasecmp(o, "none") == 0;
1725
}
1726
1727
/*
1728
 * Initializes options to special values that indicate that they have not yet
1729
 * been set.  Read_config_file will only set options with this value. Options
1730
 * are processed in the following order: command line, user config file,
1731
 * system config file.  Last, fill_default_options is called.
1732
 */
1733
1734
void
1735
initialize_options(Options * options)
1736
{
1737
	memset(options, 'X', sizeof(*options));
1738
	options->forward_agent = -1;
1739
	options->forward_x11 = -1;
1740
	options->forward_x11_trusted = -1;
1741
	options->forward_x11_timeout = -1;
1742
	options->stdio_forward_host = NULL;
1743
	options->stdio_forward_port = 0;
1744
	options->clear_forwardings = -1;
1745
	options->exit_on_forward_failure = -1;
1746
	options->xauth_location = NULL;
1747
	options->fwd_opts.gateway_ports = -1;
1748
	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1749
	options->fwd_opts.streamlocal_bind_unlink = -1;
1750
	options->use_privileged_port = -1;
1751
	options->pubkey_authentication = -1;
1752
	options->challenge_response_authentication = -1;
1753
	options->gss_authentication = -1;
1754
	options->gss_deleg_creds = -1;
1755
	options->password_authentication = -1;
1756
	options->kbd_interactive_authentication = -1;
1757
	options->kbd_interactive_devices = NULL;
1758
	options->hostbased_authentication = -1;
1759
	options->batch_mode = -1;
1760
	options->check_host_ip = -1;
1761
	options->strict_host_key_checking = -1;
1762
	options->compression = -1;
1763
	options->tcp_keep_alive = -1;
1764
	options->port = -1;
1765
	options->address_family = -1;
1766
	options->connection_attempts = -1;
1767
	options->connection_timeout = -1;
1768
	options->number_of_password_prompts = -1;
1769
	options->ciphers = NULL;
1770
	options->macs = NULL;
1771
	options->kex_algorithms = NULL;
1772
	options->hostkeyalgorithms = NULL;
1773
	options->num_identity_files = 0;
1774
	options->num_certificate_files = 0;
1775
	options->hostname = NULL;
1776
	options->host_key_alias = NULL;
1777
	options->proxy_command = NULL;
1778
	options->jump_user = NULL;
1779
	options->jump_host = NULL;
1780
	options->jump_port = -1;
1781
	options->jump_extra = NULL;
1782
	options->user = NULL;
1783
	options->escape_char = -1;
1784
	options->num_system_hostfiles = 0;
1785
	options->num_user_hostfiles = 0;
1786
	options->local_forwards = NULL;
1787
	options->num_local_forwards = 0;
1788
	options->remote_forwards = NULL;
1789
	options->num_remote_forwards = 0;
1790
	options->log_facility = SYSLOG_FACILITY_NOT_SET;
1791
	options->log_level = SYSLOG_LEVEL_NOT_SET;
1792
	options->preferred_authentications = NULL;
1793
	options->bind_address = NULL;
1794
	options->pkcs11_provider = NULL;
1795
	options->enable_ssh_keysign = - 1;
1796
	options->no_host_authentication_for_localhost = - 1;
1797
	options->identities_only = - 1;
1798
	options->rekey_limit = - 1;
1799
	options->rekey_interval = -1;
1800
	options->verify_host_key_dns = -1;
1801
	options->server_alive_interval = -1;
1802
	options->server_alive_count_max = -1;
1803
	options->num_send_env = 0;
1804
	options->control_path = NULL;
1805
	options->control_master = -1;
1806
	options->control_persist = -1;
1807
	options->control_persist_timeout = 0;
1808
	options->hash_known_hosts = -1;
1809
	options->tun_open = -1;
1810
	options->tun_local = -1;
1811
	options->tun_remote = -1;
1812
	options->local_command = NULL;
1813
	options->permit_local_command = -1;
1814
	options->remote_command = NULL;
1815
	options->add_keys_to_agent = -1;
1816
	options->identity_agent = NULL;
1817
	options->visual_host_key = -1;
1818
	options->ip_qos_interactive = -1;
1819
	options->ip_qos_bulk = -1;
1820
	options->request_tty = -1;
1821
	options->proxy_use_fdpass = -1;
1822
	options->ignored_unknown = NULL;
1823
	options->num_canonical_domains = 0;
1824
	options->num_permitted_cnames = 0;
1825
	options->canonicalize_max_dots = -1;
1826
	options->canonicalize_fallback_local = -1;
1827
	options->canonicalize_hostname = -1;
1828
	options->revoked_host_keys = NULL;
1829
	options->fingerprint_hash = -1;
1830
	options->update_hostkeys = -1;
1831
	options->hostbased_key_types = NULL;
1832
	options->pubkey_key_types = NULL;
1833
}
1834
1835
/*
1836
 * A petite version of fill_default_options() that just fills the options
1837
 * needed for hostname canonicalization to proceed.
1838
 */
1839
void
1840
fill_default_options_for_canonicalization(Options *options)
1841
{
1842
	if (options->canonicalize_max_dots == -1)
1843
		options->canonicalize_max_dots = 1;
1844
	if (options->canonicalize_fallback_local == -1)
1845
		options->canonicalize_fallback_local = 1;
1846
	if (options->canonicalize_hostname == -1)
1847
		options->canonicalize_hostname = SSH_CANONICALISE_NO;
1848
}
1849
1850
/*
1851
 * Called after processing other sources of option data, this fills those
1852
 * options for which no value has been specified with their default values.
1853
 */
1854
void
1855
fill_default_options(Options * options)
1856
{
1857
	if (options->forward_agent == -1)
1858
		options->forward_agent = 0;
1859
	if (options->forward_x11 == -1)
1860
		options->forward_x11 = 0;
1861
	if (options->forward_x11_trusted == -1)
1862
		options->forward_x11_trusted = 0;
1863
	if (options->forward_x11_timeout == -1)
1864
		options->forward_x11_timeout = 1200;
1865
	/*
1866
	 * stdio forwarding (-W) changes the default for these but we defer
1867
	 * setting the values so they can be overridden.
1868
	 */
1869
	if (options->exit_on_forward_failure == -1)
1870
		options->exit_on_forward_failure =
1871
		    options->stdio_forward_host != NULL ? 1 : 0;
1872
	if (options->clear_forwardings == -1)
1873
		options->clear_forwardings =
1874
		    options->stdio_forward_host != NULL ? 1 : 0;
1875
	if (options->clear_forwardings == 1)
1876
		clear_forwardings(options);
1877
1878
	if (options->xauth_location == NULL)
1879
		options->xauth_location = _PATH_XAUTH;
1880
	if (options->fwd_opts.gateway_ports == -1)
1881
		options->fwd_opts.gateway_ports = 0;
1882
	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1883
		options->fwd_opts.streamlocal_bind_mask = 0177;
1884
	if (options->fwd_opts.streamlocal_bind_unlink == -1)
1885
		options->fwd_opts.streamlocal_bind_unlink = 0;
1886
	if (options->use_privileged_port == -1)
1887
		options->use_privileged_port = 0;
1888
	if (options->pubkey_authentication == -1)
1889
		options->pubkey_authentication = 1;
1890
	if (options->challenge_response_authentication == -1)
1891
		options->challenge_response_authentication = 1;
1892
	if (options->gss_authentication == -1)
1893
		options->gss_authentication = 0;
1894
	if (options->gss_deleg_creds == -1)
1895
		options->gss_deleg_creds = 0;
1896
	if (options->password_authentication == -1)
1897
		options->password_authentication = 1;
1898
	if (options->kbd_interactive_authentication == -1)
1899
		options->kbd_interactive_authentication = 1;
1900
	if (options->hostbased_authentication == -1)
1901
		options->hostbased_authentication = 0;
1902
	if (options->batch_mode == -1)
1903
		options->batch_mode = 0;
1904
	if (options->check_host_ip == -1)
1905
		options->check_host_ip = 1;
1906
	if (options->strict_host_key_checking == -1)
1907
		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
1908
	if (options->compression == -1)
1909
		options->compression = 0;
1910
	if (options->tcp_keep_alive == -1)
1911
		options->tcp_keep_alive = 1;
1912
	if (options->port == -1)
1913
		options->port = 0;	/* Filled in ssh_connect. */
1914
	if (options->address_family == -1)
1915
		options->address_family = AF_UNSPEC;
1916
	if (options->connection_attempts == -1)
1917
		options->connection_attempts = 1;
1918
	if (options->number_of_password_prompts == -1)
1919
		options->number_of_password_prompts = 3;
1920
	/* options->hostkeyalgorithms, default set in myproposals.h */
1921
	if (options->add_keys_to_agent == -1)
1922
		options->add_keys_to_agent = 0;
1923
	if (options->num_identity_files == 0) {
1924
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
1925
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
1926
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
1927
		add_identity_file(options, "~/",
1928
		    _PATH_SSH_CLIENT_ID_ED25519, 0);
1929
	}
1930
	if (options->escape_char == -1)
1931
		options->escape_char = '~';
1932
	if (options->num_system_hostfiles == 0) {
1933
		options->system_hostfiles[options->num_system_hostfiles++] =
1934
		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1935
		options->system_hostfiles[options->num_system_hostfiles++] =
1936
		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1937
	}
1938
	if (options->num_user_hostfiles == 0) {
1939
		options->user_hostfiles[options->num_user_hostfiles++] =
1940
		    xstrdup(_PATH_SSH_USER_HOSTFILE);
1941
		options->user_hostfiles[options->num_user_hostfiles++] =
1942
		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
1943
	}
1944
	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1945
		options->log_level = SYSLOG_LEVEL_INFO;
1946
	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
1947
		options->log_facility = SYSLOG_FACILITY_USER;
1948
	if (options->no_host_authentication_for_localhost == - 1)
1949
		options->no_host_authentication_for_localhost = 0;
1950
	if (options->identities_only == -1)
1951
		options->identities_only = 0;
1952
	if (options->enable_ssh_keysign == -1)
1953
		options->enable_ssh_keysign = 0;
1954
	if (options->rekey_limit == -1)
1955
		options->rekey_limit = 0;
1956
	if (options->rekey_interval == -1)
1957
		options->rekey_interval = 0;
1958
	if (options->verify_host_key_dns == -1)
1959
		options->verify_host_key_dns = 0;
1960
	if (options->server_alive_interval == -1)
1961
		options->server_alive_interval = 0;
1962
	if (options->server_alive_count_max == -1)
1963
		options->server_alive_count_max = 3;
1964
	if (options->control_master == -1)
1965
		options->control_master = 0;
1966
	if (options->control_persist == -1) {
1967
		options->control_persist = 0;
1968
		options->control_persist_timeout = 0;
1969
	}
1970
	if (options->hash_known_hosts == -1)
1971
		options->hash_known_hosts = 0;
1972
	if (options->tun_open == -1)
1973
		options->tun_open = SSH_TUNMODE_NO;
1974
	if (options->tun_local == -1)
1975
		options->tun_local = SSH_TUNID_ANY;
1976
	if (options->tun_remote == -1)
1977
		options->tun_remote = SSH_TUNID_ANY;
1978
	if (options->permit_local_command == -1)
1979
		options->permit_local_command = 0;
1980
	if (options->visual_host_key == -1)
1981
		options->visual_host_key = 0;
1982
	if (options->ip_qos_interactive == -1)
1983
		options->ip_qos_interactive = IPTOS_LOWDELAY;
1984
	if (options->ip_qos_bulk == -1)
1985
		options->ip_qos_bulk = IPTOS_THROUGHPUT;
1986
	if (options->request_tty == -1)
1987
		options->request_tty = REQUEST_TTY_AUTO;
1988
	if (options->proxy_use_fdpass == -1)
1989
		options->proxy_use_fdpass = 0;
1990
	if (options->canonicalize_max_dots == -1)
1991
		options->canonicalize_max_dots = 1;
1992
	if (options->canonicalize_fallback_local == -1)
1993
		options->canonicalize_fallback_local = 1;
1994
	if (options->canonicalize_hostname == -1)
1995
		options->canonicalize_hostname = SSH_CANONICALISE_NO;
1996
	if (options->fingerprint_hash == -1)
1997
		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
1998
	if (options->update_hostkeys == -1)
1999
		options->update_hostkeys = 0;
2000
	if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 ||
2001
	    kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 ||
2002
	    kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 ||
2003
	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
2004
	    &options->hostbased_key_types) != 0 ||
2005
	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
2006
	    &options->pubkey_key_types) != 0)
2007
		fatal("%s: kex_assemble_names failed", __func__);
2008
2009
#define CLEAR_ON_NONE(v) \
2010
	do { \
2011
		if (option_clear_or_none(v)) { \
2012
			free(v); \
2013
			v = NULL; \
2014
		} \
2015
	} while(0)
2016
	CLEAR_ON_NONE(options->local_command);
2017
	CLEAR_ON_NONE(options->remote_command);
2018
	CLEAR_ON_NONE(options->proxy_command);
2019
	CLEAR_ON_NONE(options->control_path);
2020
	CLEAR_ON_NONE(options->revoked_host_keys);
2021
	/* options->identity_agent distinguishes NULL from 'none' */
2022
	/* options->user will be set in the main program if appropriate */
2023
	/* options->hostname will be set in the main program if appropriate */
2024
	/* options->host_key_alias should not be set by default */
2025
	/* options->preferred_authentications will be set in ssh */
2026
}
2027
2028
struct fwdarg {
2029
	char *arg;
2030
	int ispath;
2031
};
2032
2033
/*
2034
 * parse_fwd_field
2035
 * parses the next field in a port forwarding specification.
2036
 * sets fwd to the parsed field and advances p past the colon
2037
 * or sets it to NULL at end of string.
2038
 * returns 0 on success, else non-zero.
2039
 */
2040
static int
2041
parse_fwd_field(char **p, struct fwdarg *fwd)
2042
{
2043
	char *ep, *cp = *p;
2044
	int ispath = 0;
2045
2046
	if (*cp == '\0') {
2047
		*p = NULL;
2048
		return -1;	/* end of string */
2049
	}
2050
2051
	/*
2052
	 * A field escaped with square brackets is used literally.
2053
	 * XXX - allow ']' to be escaped via backslash?
2054
	 */
2055
	if (*cp == '[') {
2056
		/* find matching ']' */
2057
		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2058
			if (*ep == '/')
2059
				ispath = 1;
2060
		}
2061
		/* no matching ']' or not at end of field. */
2062
		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2063
			return -1;
2064
		/* NUL terminate the field and advance p past the colon */
2065
		*ep++ = '\0';
2066
		if (*ep != '\0')
2067
			*ep++ = '\0';
2068
		fwd->arg = cp + 1;
2069
		fwd->ispath = ispath;
2070
		*p = ep;
2071
		return 0;
2072
	}
2073
2074
	for (cp = *p; *cp != '\0'; cp++) {
2075
		switch (*cp) {
2076
		case '\\':
2077
			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2078
			if (*cp == '\0')
2079
				return -1;
2080
			break;
2081
		case '/':
2082
			ispath = 1;
2083
			break;
2084
		case ':':
2085
			*cp++ = '\0';
2086
			goto done;
2087
		}
2088
	}
2089
done:
2090
	fwd->arg = *p;
2091
	fwd->ispath = ispath;
2092
	*p = cp;
2093
	return 0;
2094
}
2095
2096
/*
2097
 * parse_forward
2098
 * parses a string containing a port forwarding specification of the form:
2099
 *   dynamicfwd == 0
2100
 *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2101
 *	listenpath:connectpath
2102
 *   dynamicfwd == 1
2103
 *	[listenhost:]listenport
2104
 * returns number of arguments parsed or zero on error
2105
 */
2106
int
2107
parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2108
{
2109
	struct fwdarg fwdargs[4];
2110
	char *p, *cp;
2111
	int i;
2112
2113
	memset(fwd, 0, sizeof(*fwd));
2114
	memset(fwdargs, 0, sizeof(fwdargs));
2115
2116
	cp = p = xstrdup(fwdspec);
2117
2118
	/* skip leading spaces */
2119
	while (isspace((u_char)*cp))
2120
		cp++;
2121
2122
	for (i = 0; i < 4; ++i) {
2123
		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2124
			break;
2125
	}
2126
2127
	/* Check for trailing garbage */
2128
	if (cp != NULL && *cp != '\0') {
2129
		i = 0;	/* failure */
2130
	}
2131
2132
	switch (i) {
2133
	case 1:
2134
		if (fwdargs[0].ispath) {
2135
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2136
			fwd->listen_port = PORT_STREAMLOCAL;
2137
		} else {
2138
			fwd->listen_host = NULL;
2139
			fwd->listen_port = a2port(fwdargs[0].arg);
2140
		}
2141
		fwd->connect_host = xstrdup("socks");
2142
		break;
2143
2144
	case 2:
2145
		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2146
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2147
			fwd->listen_port = PORT_STREAMLOCAL;
2148
			fwd->connect_path = xstrdup(fwdargs[1].arg);
2149
			fwd->connect_port = PORT_STREAMLOCAL;
2150
		} else if (fwdargs[1].ispath) {
2151
			fwd->listen_host = NULL;
2152
			fwd->listen_port = a2port(fwdargs[0].arg);
2153
			fwd->connect_path = xstrdup(fwdargs[1].arg);
2154
			fwd->connect_port = PORT_STREAMLOCAL;
2155
		} else {
2156
			fwd->listen_host = xstrdup(fwdargs[0].arg);
2157
			fwd->listen_port = a2port(fwdargs[1].arg);
2158
			fwd->connect_host = xstrdup("socks");
2159
		}
2160
		break;
2161
2162
	case 3:
2163
		if (fwdargs[0].ispath) {
2164
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2165
			fwd->listen_port = PORT_STREAMLOCAL;
2166
			fwd->connect_host = xstrdup(fwdargs[1].arg);
2167
			fwd->connect_port = a2port(fwdargs[2].arg);
2168
		} else if (fwdargs[2].ispath) {
2169
			fwd->listen_host = xstrdup(fwdargs[0].arg);
2170
			fwd->listen_port = a2port(fwdargs[1].arg);
2171
			fwd->connect_path = xstrdup(fwdargs[2].arg);
2172
			fwd->connect_port = PORT_STREAMLOCAL;
2173
		} else {
2174
			fwd->listen_host = NULL;
2175
			fwd->listen_port = a2port(fwdargs[0].arg);
2176
			fwd->connect_host = xstrdup(fwdargs[1].arg);
2177
			fwd->connect_port = a2port(fwdargs[2].arg);
2178
		}
2179
		break;
2180
2181
	case 4:
2182
		fwd->listen_host = xstrdup(fwdargs[0].arg);
2183
		fwd->listen_port = a2port(fwdargs[1].arg);
2184
		fwd->connect_host = xstrdup(fwdargs[2].arg);
2185
		fwd->connect_port = a2port(fwdargs[3].arg);
2186
		break;
2187
	default:
2188
		i = 0; /* failure */
2189
	}
2190
2191
	free(p);
2192
2193
	if (dynamicfwd) {
2194
		if (!(i == 1 || i == 2))
2195
			goto fail_free;
2196
	} else {
2197
		if (!(i == 3 || i == 4)) {
2198
			if (fwd->connect_path == NULL &&
2199
			    fwd->listen_path == NULL)
2200
				goto fail_free;
2201
		}
2202
		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2203
			goto fail_free;
2204
	}
2205
2206
	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2207
	    (!remotefwd && fwd->listen_port == 0))
2208
		goto fail_free;
2209
	if (fwd->connect_host != NULL &&
2210
	    strlen(fwd->connect_host) >= NI_MAXHOST)
2211
		goto fail_free;
2212
	/* XXX - if connecting to a remote socket, max sun len may not match this host */
2213
	if (fwd->connect_path != NULL &&
2214
	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2215
		goto fail_free;
2216
	if (fwd->listen_host != NULL &&
2217
	    strlen(fwd->listen_host) >= NI_MAXHOST)
2218
		goto fail_free;
2219
	if (fwd->listen_path != NULL &&
2220
	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2221
		goto fail_free;
2222
2223
	return (i);
2224
2225
 fail_free:
2226
	free(fwd->connect_host);
2227
	fwd->connect_host = NULL;
2228
	free(fwd->connect_path);
2229
	fwd->connect_path = NULL;
2230
	free(fwd->listen_host);
2231
	fwd->listen_host = NULL;
2232
	free(fwd->listen_path);
2233
	fwd->listen_path = NULL;
2234
	return (0);
2235
}
2236
2237
int
2238
parse_jump(const char *s, Options *o, int active)
2239
{
2240
	char *orig, *sdup, *cp;
2241
	char *host = NULL, *user = NULL;
2242
	int ret = -1, port = -1, first;
2243
2244
	active &= o->proxy_command == NULL && o->jump_host == NULL;
2245
2246
	orig = sdup = xstrdup(s);
2247
	first = active;
2248
	do {
2249
		if ((cp = strrchr(sdup, ',')) == NULL)
2250
			cp = sdup; /* last */
2251
		else
2252
			*cp++ = '\0';
2253
2254
		if (first) {
2255
			/* First argument and configuration is active */
2256
			if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
2257
			    parse_user_host_port(cp, &user, &host, &port) != 0)
2258
				goto out;
2259
		} else {
2260
			/* Subsequent argument or inactive configuration */
2261
			if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
2262
			    parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2263
				goto out;
2264
		}
2265
		first = 0; /* only check syntax for subsequent hosts */
2266
	} while (cp != sdup);
2267
	/* success */
2268
	if (active) {
2269
		o->jump_user = user;
2270
		o->jump_host = host;
2271
		o->jump_port = port;
2272
		o->proxy_command = xstrdup("none");
2273
		user = host = NULL;
2274
		if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2275
			o->jump_extra = xstrdup(s);
2276
			o->jump_extra[cp - s] = '\0';
2277
		}
2278
	}
2279
	ret = 0;
2280
 out:
2281
	free(orig);
2282
	free(user);
2283
	free(host);
2284
	return ret;
2285
}
2286
2287
int
2288
parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
2289
{
2290
	char *path;
2291
	int r;
2292
2293
	r = parse_uri("ssh", uri, userp, hostp, portp, &path);
2294
	if (r == 0 && path != NULL)
2295
		r = -1;		/* path not allowed */
2296
	return r;
2297
}
2298
2299
/* XXX the following is a near-vebatim copy from servconf.c; refactor */
2300
static const char *
2301
fmt_multistate_int(int val, const struct multistate *m)
2302
{
2303
	u_int i;
2304
2305
	for (i = 0; m[i].key != NULL; i++) {
2306
		if (m[i].value == val)
2307
			return m[i].key;
2308
	}
2309
	return "UNKNOWN";
2310
}
2311
2312
static const char *
2313
fmt_intarg(OpCodes code, int val)
2314
{
2315
	if (val == -1)
2316
		return "unset";
2317
	switch (code) {
2318
	case oAddressFamily:
2319
		return fmt_multistate_int(val, multistate_addressfamily);
2320
	case oVerifyHostKeyDNS:
2321
	case oUpdateHostkeys:
2322
		return fmt_multistate_int(val, multistate_yesnoask);
2323
	case oStrictHostKeyChecking:
2324
		return fmt_multistate_int(val, multistate_strict_hostkey);
2325
	case oControlMaster:
2326
		return fmt_multistate_int(val, multistate_controlmaster);
2327
	case oTunnel:
2328
		return fmt_multistate_int(val, multistate_tunnel);
2329
	case oRequestTTY:
2330
		return fmt_multistate_int(val, multistate_requesttty);
2331
	case oCanonicalizeHostname:
2332
		return fmt_multistate_int(val, multistate_canonicalizehostname);
2333
	case oFingerprintHash:
2334
		return ssh_digest_alg_name(val);
2335
	default:
2336
		switch (val) {
2337
		case 0:
2338
			return "no";
2339
		case 1:
2340
			return "yes";
2341
		default:
2342
			return "UNKNOWN";
2343
		}
2344
	}
2345
}
2346
2347
static const char *
2348
lookup_opcode_name(OpCodes code)
2349
{
2350
	u_int i;
2351
2352
	for (i = 0; keywords[i].name != NULL; i++)
2353
		if (keywords[i].opcode == code)
2354
			return(keywords[i].name);
2355
	return "UNKNOWN";
2356
}
2357
2358
static void
2359
dump_cfg_int(OpCodes code, int val)
2360
{
2361
	printf("%s %d\n", lookup_opcode_name(code), val);
2362
}
2363
2364
static void
2365
dump_cfg_fmtint(OpCodes code, int val)
2366
{
2367
	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2368
}
2369
2370
static void
2371
dump_cfg_string(OpCodes code, const char *val)
2372
{
2373
	if (val == NULL)
2374
		return;
2375
	printf("%s %s\n", lookup_opcode_name(code), val);
2376
}
2377
2378
static void
2379
dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2380
{
2381
	u_int i;
2382
2383
	for (i = 0; i < count; i++)
2384
		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2385
}
2386
2387
static void
2388
dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2389
{
2390
	u_int i;
2391
2392
	printf("%s", lookup_opcode_name(code));
2393
	for (i = 0; i < count; i++)
2394
		printf(" %s",  vals[i]);
2395
	printf("\n");
2396
}
2397
2398
static void
2399
dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2400
{
2401
	const struct Forward *fwd;
2402
	u_int i;
2403
2404
	/* oDynamicForward */
2405
	for (i = 0; i < count; i++) {
2406
		fwd = &fwds[i];
2407
		if (code == oDynamicForward && fwd->connect_host != NULL &&
2408
		    strcmp(fwd->connect_host, "socks") != 0)
2409
			continue;
2410
		if (code == oLocalForward && fwd->connect_host != NULL &&
2411
		    strcmp(fwd->connect_host, "socks") == 0)
2412
			continue;
2413
		printf("%s", lookup_opcode_name(code));
2414
		if (fwd->listen_port == PORT_STREAMLOCAL)
2415
			printf(" %s", fwd->listen_path);
2416
		else if (fwd->listen_host == NULL)
2417
			printf(" %d", fwd->listen_port);
2418
		else {
2419
			printf(" [%s]:%d",
2420
			    fwd->listen_host, fwd->listen_port);
2421
		}
2422
		if (code != oDynamicForward) {
2423
			if (fwd->connect_port == PORT_STREAMLOCAL)
2424
				printf(" %s", fwd->connect_path);
2425
			else if (fwd->connect_host == NULL)
2426
				printf(" %d", fwd->connect_port);
2427
			else {
2428
				printf(" [%s]:%d",
2429
				    fwd->connect_host, fwd->connect_port);
2430
			}
2431
		}
2432
		printf("\n");
2433
	}
2434
}
2435
2436
void
2437
dump_client_config(Options *o, const char *host)
2438
{
2439
	int i;
2440
	char buf[8];
2441
2442
	/* This is normally prepared in ssh_kex2 */
2443
	if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0)
2444
		fatal("%s: kex_assemble_names failed", __func__);
2445
2446
	/* Most interesting options first: user, host, port */
2447
	dump_cfg_string(oUser, o->user);
2448
	dump_cfg_string(oHostName, host);
2449
	dump_cfg_int(oPort, o->port);
2450
2451
	/* Flag options */
2452
	dump_cfg_fmtint(oAddressFamily, o->address_family);
2453
	dump_cfg_fmtint(oBatchMode, o->batch_mode);
2454
	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2455
	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2456
	dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2457
	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2458
	dump_cfg_fmtint(oCompression, o->compression);
2459
	dump_cfg_fmtint(oControlMaster, o->control_master);
2460
	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2461
	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2462
	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2463
	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2464
	dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2465
	dump_cfg_fmtint(oForwardX11, o->forward_x11);
2466
	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2467
	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2468
#ifdef GSSAPI
2469
	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2470
	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2471
#endif /* GSSAPI */
2472
	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2473
	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2474
	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2475
	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2476
	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2477
	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2478
	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2479
	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2480
	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2481
	dump_cfg_fmtint(oRequestTTY, o->request_tty);
2482
	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2483
	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2484
	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2485
	dump_cfg_fmtint(oTunnel, o->tun_open);
2486
	dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
2487
	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2488
	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2489
	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2490
2491
	/* Integer options */
2492
	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2493
	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2494
	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2495
	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2496
	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2497
	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2498
2499
	/* String options */
2500
	dump_cfg_string(oBindAddress, o->bind_address);
2501
	dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2502
	dump_cfg_string(oControlPath, o->control_path);
2503
	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2504
	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2505
	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2506
	dump_cfg_string(oIdentityAgent, o->identity_agent);
2507
	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2508
	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2509
	dump_cfg_string(oLocalCommand, o->local_command);
2510
	dump_cfg_string(oRemoteCommand, o->remote_command);
2511
	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2512
	dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2513
#ifdef ENABLE_PKCS11
2514
	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2515
#endif
2516
	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2517
	dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2518
	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2519
	dump_cfg_string(oXAuthLocation, o->xauth_location);
2520
2521
	/* Forwards */
2522
	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2523
	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2524
	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2525
2526
	/* String array options */
2527
	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2528
	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2529
	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2530
	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2531
	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2532
2533
	/* Special cases */
2534
2535
	/* oConnectTimeout */
2536
	if (o->connection_timeout == -1)
2537
		printf("connecttimeout none\n");
2538
	else
2539
		dump_cfg_int(oConnectTimeout, o->connection_timeout);
2540
2541
	/* oTunnelDevice */
2542
	printf("tunneldevice");
2543
	if (o->tun_local == SSH_TUNID_ANY)
2544
		printf(" any");
2545
	else
2546
		printf(" %d", o->tun_local);
2547
	if (o->tun_remote == SSH_TUNID_ANY)
2548
		printf(":any");
2549
	else
2550
		printf(":%d", o->tun_remote);
2551
	printf("\n");
2552
2553
	/* oCanonicalizePermittedCNAMEs */
2554
	if ( o->num_permitted_cnames > 0) {
2555
		printf("canonicalizePermittedcnames");
2556
		for (i = 0; i < o->num_permitted_cnames; i++) {
2557
			printf(" %s:%s", o->permitted_cnames[i].source_list,
2558
			    o->permitted_cnames[i].target_list);
2559
		}
2560
		printf("\n");
2561
	}
2562
2563
	/* oControlPersist */
2564
	if (o->control_persist == 0 || o->control_persist_timeout == 0)
2565
		dump_cfg_fmtint(oControlPersist, o->control_persist);
2566
	else
2567
		dump_cfg_int(oControlPersist, o->control_persist_timeout);
2568
2569
	/* oEscapeChar */
2570
	if (o->escape_char == SSH_ESCAPECHAR_NONE)
2571
		printf("escapechar none\n");
2572
	else {
2573
		vis(buf, o->escape_char, VIS_WHITE, 0);
2574
		printf("escapechar %s\n", buf);
2575
	}
2576
2577
	/* oIPQoS */
2578
	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2579
	printf("%s\n", iptos2str(o->ip_qos_bulk));
2580
2581
	/* oRekeyLimit */
2582
	printf("rekeylimit %llu %d\n",
2583
	    (unsigned long long)o->rekey_limit, o->rekey_interval);
2584
2585
	/* oStreamLocalBindMask */
2586
	printf("streamlocalbindmask 0%o\n",
2587
	    o->fwd_opts.streamlocal_bind_mask);
2588
2589
	/* oProxyCommand / oProxyJump */
2590
	if (o->jump_host == NULL)
2591
		dump_cfg_string(oProxyCommand, o->proxy_command);
2592
	else {
2593
		/* Check for numeric addresses */
2594
		i = strchr(o->jump_host, ':') != NULL ||
2595
		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2596
		snprintf(buf, sizeof(buf), "%d", o->jump_port);
2597
		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2598
		    /* optional additional jump spec */
2599
		    o->jump_extra == NULL ? "" : o->jump_extra,
2600
		    o->jump_extra == NULL ? "" : ",",
2601
		    /* optional user */
2602
		    o->jump_user == NULL ? "" : o->jump_user,
2603
		    o->jump_user == NULL ? "" : "@",
2604
		    /* opening [ if hostname is numeric */
2605
		    i ? "[" : "",
2606
		    /* mandatory hostname */
2607
		    o->jump_host,
2608
		    /* closing ] if hostname is numeric */
2609
		    i ? "]" : "",
2610
		    /* optional port number */
2611
		    o->jump_port <= 0 ? "" : ":",
2612
		    o->jump_port <= 0 ? "" : buf);
2613
	}
2614
}