GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/ssh-keysign/../readconf.c Lines: 0 1286 0.0 %
Date: 2017-11-07 Branches: 0 974 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: readconf.c,v 1.279 2017/09/21 19:16:53 markus 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
/* Check and prepare a domain name: removes trailing '.' and lowercases */
672
static void
673
valid_domain(char *name, const char *filename, int linenum)
674
{
675
	size_t i, l = strlen(name);
676
	u_char c, last = '\0';
677
678
	if (l == 0)
679
		fatal("%s line %d: empty hostname suffix", filename, linenum);
680
	if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
681
		fatal("%s line %d: hostname suffix \"%.100s\" "
682
		    "starts with invalid character", filename, linenum, name);
683
	for (i = 0; i < l; i++) {
684
		c = tolower((u_char)name[i]);
685
		name[i] = (char)c;
686
		if (last == '.' && c == '.')
687
			fatal("%s line %d: hostname suffix \"%.100s\" contains "
688
			    "consecutive separators", filename, linenum, name);
689
		if (c != '.' && c != '-' && !isalnum(c) &&
690
		    c != '_') /* technically invalid, but common */
691
			fatal("%s line %d: hostname suffix \"%.100s\" contains "
692
			    "invalid characters", filename, linenum, name);
693
		last = c;
694
	}
695
	if (name[l - 1] == '.')
696
		name[l - 1] = '\0';
697
}
698
699
/*
700
 * Returns the number of the token pointed to by cp or oBadOption.
701
 */
702
static OpCodes
703
parse_token(const char *cp, const char *filename, int linenum,
704
    const char *ignored_unknown)
705
{
706
	int i;
707
708
	for (i = 0; keywords[i].name; i++)
709
		if (strcmp(cp, keywords[i].name) == 0)
710
			return keywords[i].opcode;
711
	if (ignored_unknown != NULL &&
712
	    match_pattern_list(cp, ignored_unknown, 1) == 1)
713
		return oIgnoredUnknownOption;
714
	error("%s: line %d: Bad configuration option: %s",
715
	    filename, linenum, cp);
716
	return oBadOption;
717
}
718
719
/* Multistate option parsing */
720
struct multistate {
721
	char *key;
722
	int value;
723
};
724
static const struct multistate multistate_flag[] = {
725
	{ "true",			1 },
726
	{ "false",			0 },
727
	{ "yes",			1 },
728
	{ "no",				0 },
729
	{ NULL, -1 }
730
};
731
static const struct multistate multistate_yesnoask[] = {
732
	{ "true",			1 },
733
	{ "false",			0 },
734
	{ "yes",			1 },
735
	{ "no",				0 },
736
	{ "ask",			2 },
737
	{ NULL, -1 }
738
};
739
static const struct multistate multistate_strict_hostkey[] = {
740
	{ "true",			SSH_STRICT_HOSTKEY_YES },
741
	{ "false",			SSH_STRICT_HOSTKEY_OFF },
742
	{ "yes",			SSH_STRICT_HOSTKEY_YES },
743
	{ "no",				SSH_STRICT_HOSTKEY_OFF },
744
	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
745
	{ "off",			SSH_STRICT_HOSTKEY_OFF },
746
	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
747
	{ NULL, -1 }
748
};
749
static const struct multistate multistate_yesnoaskconfirm[] = {
750
	{ "true",			1 },
751
	{ "false",			0 },
752
	{ "yes",			1 },
753
	{ "no",				0 },
754
	{ "ask",			2 },
755
	{ "confirm",			3 },
756
	{ NULL, -1 }
757
};
758
static const struct multistate multistate_addressfamily[] = {
759
	{ "inet",			AF_INET },
760
	{ "inet6",			AF_INET6 },
761
	{ "any",			AF_UNSPEC },
762
	{ NULL, -1 }
763
};
764
static const struct multistate multistate_controlmaster[] = {
765
	{ "true",			SSHCTL_MASTER_YES },
766
	{ "yes",			SSHCTL_MASTER_YES },
767
	{ "false",			SSHCTL_MASTER_NO },
768
	{ "no",				SSHCTL_MASTER_NO },
769
	{ "auto",			SSHCTL_MASTER_AUTO },
770
	{ "ask",			SSHCTL_MASTER_ASK },
771
	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
772
	{ NULL, -1 }
773
};
774
static const struct multistate multistate_tunnel[] = {
775
	{ "ethernet",			SSH_TUNMODE_ETHERNET },
776
	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
777
	{ "true",			SSH_TUNMODE_DEFAULT },
778
	{ "yes",			SSH_TUNMODE_DEFAULT },
779
	{ "false",			SSH_TUNMODE_NO },
780
	{ "no",				SSH_TUNMODE_NO },
781
	{ NULL, -1 }
782
};
783
static const struct multistate multistate_requesttty[] = {
784
	{ "true",			REQUEST_TTY_YES },
785
	{ "yes",			REQUEST_TTY_YES },
786
	{ "false",			REQUEST_TTY_NO },
787
	{ "no",				REQUEST_TTY_NO },
788
	{ "force",			REQUEST_TTY_FORCE },
789
	{ "auto",			REQUEST_TTY_AUTO },
790
	{ NULL, -1 }
791
};
792
static const struct multistate multistate_canonicalizehostname[] = {
793
	{ "true",			SSH_CANONICALISE_YES },
794
	{ "false",			SSH_CANONICALISE_NO },
795
	{ "yes",			SSH_CANONICALISE_YES },
796
	{ "no",				SSH_CANONICALISE_NO },
797
	{ "always",			SSH_CANONICALISE_ALWAYS },
798
	{ NULL, -1 }
799
};
800
801
/*
802
 * Processes a single option line as used in the configuration files. This
803
 * only sets those values that have not already been set.
804
 */
805
int
806
process_config_line(Options *options, struct passwd *pw, const char *host,
807
    const char *original_host, char *line, const char *filename,
808
    int linenum, int *activep, int flags)
809
{
810
	return process_config_line_depth(options, pw, host, original_host,
811
	    line, filename, linenum, activep, flags, 0);
812
}
813
814
#define WHITESPACE " \t\r\n"
815
static int
816
process_config_line_depth(Options *options, struct passwd *pw, const char *host,
817
    const char *original_host, char *line, const char *filename,
818
    int linenum, int *activep, int flags, int depth)
819
{
820
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
821
	char **cpptr, fwdarg[256];
822
	u_int i, *uintptr, max_entries = 0;
823
	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
824
	int remotefwd, dynamicfwd;
825
	LogLevel *log_level_ptr;
826
	SyslogFacility *log_facility_ptr;
827
	long long val64;
828
	size_t len;
829
	struct Forward fwd;
830
	const struct multistate *multistate_ptr;
831
	struct allowed_cname *cname;
832
	glob_t gl;
833
834
	if (activep == NULL) { /* We are processing a command line directive */
835
		cmdline = 1;
836
		activep = &cmdline;
837
	}
838
839
	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
840
	if ((len = strlen(line)) == 0)
841
		return 0;
842
	for (len--; len > 0; len--) {
843
		if (strchr(WHITESPACE "\f", line[len]) == NULL)
844
			break;
845
		line[len] = '\0';
846
	}
847
848
	s = line;
849
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
850
	if ((keyword = strdelim(&s)) == NULL)
851
		return 0;
852
	/* Ignore leading whitespace. */
853
	if (*keyword == '\0')
854
		keyword = strdelim(&s);
855
	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
856
		return 0;
857
	/* Match lowercase keyword */
858
	lowercase(keyword);
859
860
	opcode = parse_token(keyword, filename, linenum,
861
	    options->ignored_unknown);
862
863
	switch (opcode) {
864
	case oBadOption:
865
		/* don't panic, but count bad options */
866
		return -1;
867
	case oIgnore:
868
		return 0;
869
	case oIgnoredUnknownOption:
870
		debug("%s line %d: Ignored unknown option \"%s\"",
871
		    filename, linenum, keyword);
872
		return 0;
873
	case oConnectTimeout:
874
		intptr = &options->connection_timeout;
875
parse_time:
876
		arg = strdelim(&s);
877
		if (!arg || *arg == '\0')
878
			fatal("%s line %d: missing time value.",
879
			    filename, linenum);
880
		if (strcmp(arg, "none") == 0)
881
			value = -1;
882
		else if ((value = convtime(arg)) == -1)
883
			fatal("%s line %d: invalid time value.",
884
			    filename, linenum);
885
		if (*activep && *intptr == -1)
886
			*intptr = value;
887
		break;
888
889
	case oForwardAgent:
890
		intptr = &options->forward_agent;
891
 parse_flag:
892
		multistate_ptr = multistate_flag;
893
 parse_multistate:
894
		arg = strdelim(&s);
895
		if (!arg || *arg == '\0')
896
			fatal("%s line %d: missing argument.",
897
			    filename, linenum);
898
		value = -1;
899
		for (i = 0; multistate_ptr[i].key != NULL; i++) {
900
			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
901
				value = multistate_ptr[i].value;
902
				break;
903
			}
904
		}
905
		if (value == -1)
906
			fatal("%s line %d: unsupported option \"%s\".",
907
			    filename, linenum, arg);
908
		if (*activep && *intptr == -1)
909
			*intptr = value;
910
		break;
911
912
	case oForwardX11:
913
		intptr = &options->forward_x11;
914
		goto parse_flag;
915
916
	case oForwardX11Trusted:
917
		intptr = &options->forward_x11_trusted;
918
		goto parse_flag;
919
920
	case oForwardX11Timeout:
921
		intptr = &options->forward_x11_timeout;
922
		goto parse_time;
923
924
	case oGatewayPorts:
925
		intptr = &options->fwd_opts.gateway_ports;
926
		goto parse_flag;
927
928
	case oExitOnForwardFailure:
929
		intptr = &options->exit_on_forward_failure;
930
		goto parse_flag;
931
932
	case oUsePrivilegedPort:
933
		intptr = &options->use_privileged_port;
934
		goto parse_flag;
935
936
	case oPasswordAuthentication:
937
		intptr = &options->password_authentication;
938
		goto parse_flag;
939
940
	case oKbdInteractiveAuthentication:
941
		intptr = &options->kbd_interactive_authentication;
942
		goto parse_flag;
943
944
	case oKbdInteractiveDevices:
945
		charptr = &options->kbd_interactive_devices;
946
		goto parse_string;
947
948
	case oPubkeyAuthentication:
949
		intptr = &options->pubkey_authentication;
950
		goto parse_flag;
951
952
	case oHostbasedAuthentication:
953
		intptr = &options->hostbased_authentication;
954
		goto parse_flag;
955
956
	case oChallengeResponseAuthentication:
957
		intptr = &options->challenge_response_authentication;
958
		goto parse_flag;
959
960
	case oGssAuthentication:
961
		intptr = &options->gss_authentication;
962
		goto parse_flag;
963
964
	case oGssDelegateCreds:
965
		intptr = &options->gss_deleg_creds;
966
		goto parse_flag;
967
968
	case oBatchMode:
969
		intptr = &options->batch_mode;
970
		goto parse_flag;
971
972
	case oCheckHostIP:
973
		intptr = &options->check_host_ip;
974
		goto parse_flag;
975
976
	case oVerifyHostKeyDNS:
977
		intptr = &options->verify_host_key_dns;
978
		multistate_ptr = multistate_yesnoask;
979
		goto parse_multistate;
980
981
	case oStrictHostKeyChecking:
982
		intptr = &options->strict_host_key_checking;
983
		multistate_ptr = multistate_strict_hostkey;
984
		goto parse_multistate;
985
986
	case oCompression:
987
		intptr = &options->compression;
988
		goto parse_flag;
989
990
	case oTCPKeepAlive:
991
		intptr = &options->tcp_keep_alive;
992
		goto parse_flag;
993
994
	case oNoHostAuthenticationForLocalhost:
995
		intptr = &options->no_host_authentication_for_localhost;
996
		goto parse_flag;
997
998
	case oNumberOfPasswordPrompts:
999
		intptr = &options->number_of_password_prompts;
1000
		goto parse_int;
1001
1002
	case oRekeyLimit:
1003
		arg = strdelim(&s);
1004
		if (!arg || *arg == '\0')
1005
			fatal("%.200s line %d: Missing argument.", filename,
1006
			    linenum);
1007
		if (strcmp(arg, "default") == 0) {
1008
			val64 = 0;
1009
		} else {
1010
			if (scan_scaled(arg, &val64) == -1)
1011
				fatal("%.200s line %d: Bad number '%s': %s",
1012
				    filename, linenum, arg, strerror(errno));
1013
			if (val64 != 0 && val64 < 16)
1014
				fatal("%.200s line %d: RekeyLimit too small",
1015
				    filename, linenum);
1016
		}
1017
		if (*activep && options->rekey_limit == -1)
1018
			options->rekey_limit = val64;
1019
		if (s != NULL) { /* optional rekey interval present */
1020
			if (strcmp(s, "none") == 0) {
1021
				(void)strdelim(&s);	/* discard */
1022
				break;
1023
			}
1024
			intptr = &options->rekey_interval;
1025
			goto parse_time;
1026
		}
1027
		break;
1028
1029
	case oIdentityFile:
1030
		arg = strdelim(&s);
1031
		if (!arg || *arg == '\0')
1032
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1033
		if (*activep) {
1034
			intptr = &options->num_identity_files;
1035
			if (*intptr >= SSH_MAX_IDENTITY_FILES)
1036
				fatal("%.200s line %d: Too many identity files specified (max %d).",
1037
				    filename, linenum, SSH_MAX_IDENTITY_FILES);
1038
			add_identity_file(options, NULL,
1039
			    arg, flags & SSHCONF_USERCONF);
1040
		}
1041
		break;
1042
1043
	case oCertificateFile:
1044
		arg = strdelim(&s);
1045
		if (!arg || *arg == '\0')
1046
			fatal("%.200s line %d: Missing argument.",
1047
			    filename, linenum);
1048
		if (*activep) {
1049
			intptr = &options->num_certificate_files;
1050
			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1051
				fatal("%.200s line %d: Too many certificate "
1052
				    "files specified (max %d).",
1053
				    filename, linenum,
1054
				    SSH_MAX_CERTIFICATE_FILES);
1055
			}
1056
			add_certificate_file(options, arg,
1057
			    flags & SSHCONF_USERCONF);
1058
		}
1059
		break;
1060
1061
	case oXAuthLocation:
1062
		charptr=&options->xauth_location;
1063
		goto parse_string;
1064
1065
	case oUser:
1066
		charptr = &options->user;
1067
parse_string:
1068
		arg = strdelim(&s);
1069
		if (!arg || *arg == '\0')
1070
			fatal("%.200s line %d: Missing argument.",
1071
			    filename, linenum);
1072
		if (*activep && *charptr == NULL)
1073
			*charptr = xstrdup(arg);
1074
		break;
1075
1076
	case oGlobalKnownHostsFile:
1077
		cpptr = (char **)&options->system_hostfiles;
1078
		uintptr = &options->num_system_hostfiles;
1079
		max_entries = SSH_MAX_HOSTS_FILES;
1080
parse_char_array:
1081
		if (*activep && *uintptr == 0) {
1082
			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1083
				if ((*uintptr) >= max_entries)
1084
					fatal("%s line %d: "
1085
					    "too many authorized keys files.",
1086
					    filename, linenum);
1087
				cpptr[(*uintptr)++] = xstrdup(arg);
1088
			}
1089
		}
1090
		return 0;
1091
1092
	case oUserKnownHostsFile:
1093
		cpptr = (char **)&options->user_hostfiles;
1094
		uintptr = &options->num_user_hostfiles;
1095
		max_entries = SSH_MAX_HOSTS_FILES;
1096
		goto parse_char_array;
1097
1098
	case oHostName:
1099
		charptr = &options->hostname;
1100
		goto parse_string;
1101
1102
	case oHostKeyAlias:
1103
		charptr = &options->host_key_alias;
1104
		goto parse_string;
1105
1106
	case oPreferredAuthentications:
1107
		charptr = &options->preferred_authentications;
1108
		goto parse_string;
1109
1110
	case oBindAddress:
1111
		charptr = &options->bind_address;
1112
		goto parse_string;
1113
1114
	case oPKCS11Provider:
1115
		charptr = &options->pkcs11_provider;
1116
		goto parse_string;
1117
1118
	case oProxyCommand:
1119
		charptr = &options->proxy_command;
1120
		/* Ignore ProxyCommand if ProxyJump already specified */
1121
		if (options->jump_host != NULL)
1122
			charptr = &options->jump_host; /* Skip below */
1123
parse_command:
1124
		if (s == NULL)
1125
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1126
		len = strspn(s, WHITESPACE "=");
1127
		if (*activep && *charptr == NULL)
1128
			*charptr = xstrdup(s + len);
1129
		return 0;
1130
1131
	case oProxyJump:
1132
		if (s == NULL) {
1133
			fatal("%.200s line %d: Missing argument.",
1134
			    filename, linenum);
1135
		}
1136
		len = strspn(s, WHITESPACE "=");
1137
		if (parse_jump(s + len, options, *activep) == -1) {
1138
			fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
1139
			    filename, linenum, s + len);
1140
		}
1141
		return 0;
1142
1143
	case oPort:
1144
		intptr = &options->port;
1145
parse_int:
1146
		arg = strdelim(&s);
1147
		if (!arg || *arg == '\0')
1148
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1149
		if (arg[0] < '0' || arg[0] > '9')
1150
			fatal("%.200s line %d: Bad number.", filename, linenum);
1151
1152
		/* Octal, decimal, or hex format? */
1153
		value = strtol(arg, &endofnumber, 0);
1154
		if (arg == endofnumber)
1155
			fatal("%.200s line %d: Bad number.", filename, linenum);
1156
		if (*activep && *intptr == -1)
1157
			*intptr = value;
1158
		break;
1159
1160
	case oConnectionAttempts:
1161
		intptr = &options->connection_attempts;
1162
		goto parse_int;
1163
1164
	case oCiphers:
1165
		arg = strdelim(&s);
1166
		if (!arg || *arg == '\0')
1167
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1168
		if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
1169
			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1170
			    filename, linenum, arg ? arg : "<NONE>");
1171
		if (*activep && options->ciphers == NULL)
1172
			options->ciphers = xstrdup(arg);
1173
		break;
1174
1175
	case oMacs:
1176
		arg = strdelim(&s);
1177
		if (!arg || *arg == '\0')
1178
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1179
		if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
1180
			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1181
			    filename, linenum, arg ? arg : "<NONE>");
1182
		if (*activep && options->macs == NULL)
1183
			options->macs = xstrdup(arg);
1184
		break;
1185
1186
	case oKexAlgorithms:
1187
		arg = strdelim(&s);
1188
		if (!arg || *arg == '\0')
1189
			fatal("%.200s line %d: Missing argument.",
1190
			    filename, linenum);
1191
		if (*arg != '-' &&
1192
		    !kex_names_valid(*arg == '+' ? arg + 1 : arg))
1193
			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1194
			    filename, linenum, arg ? arg : "<NONE>");
1195
		if (*activep && options->kex_algorithms == NULL)
1196
			options->kex_algorithms = xstrdup(arg);
1197
		break;
1198
1199
	case oHostKeyAlgorithms:
1200
		charptr = &options->hostkeyalgorithms;
1201
parse_keytypes:
1202
		arg = strdelim(&s);
1203
		if (!arg || *arg == '\0')
1204
			fatal("%.200s line %d: Missing argument.",
1205
			    filename, linenum);
1206
		if (*arg != '-' &&
1207
		    !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1208
			fatal("%s line %d: Bad key types '%s'.",
1209
				filename, linenum, arg ? arg : "<NONE>");
1210
		if (*activep && *charptr == NULL)
1211
			*charptr = xstrdup(arg);
1212
		break;
1213
1214
	case oLogLevel:
1215
		log_level_ptr = &options->log_level;
1216
		arg = strdelim(&s);
1217
		value = log_level_number(arg);
1218
		if (value == SYSLOG_LEVEL_NOT_SET)
1219
			fatal("%.200s line %d: unsupported log level '%s'",
1220
			    filename, linenum, arg ? arg : "<NONE>");
1221
		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1222
			*log_level_ptr = (LogLevel) value;
1223
		break;
1224
1225
	case oLogFacility:
1226
		log_facility_ptr = &options->log_facility;
1227
		arg = strdelim(&s);
1228
		value = log_facility_number(arg);
1229
		if (value == SYSLOG_FACILITY_NOT_SET)
1230
			fatal("%.200s line %d: unsupported log facility '%s'",
1231
			    filename, linenum, arg ? arg : "<NONE>");
1232
		if (*log_facility_ptr == -1)
1233
			*log_facility_ptr = (SyslogFacility) value;
1234
		break;
1235
1236
	case oLocalForward:
1237
	case oRemoteForward:
1238
	case oDynamicForward:
1239
		arg = strdelim(&s);
1240
		if (arg == NULL || *arg == '\0')
1241
			fatal("%.200s line %d: Missing port argument.",
1242
			    filename, linenum);
1243
1244
		remotefwd = (opcode == oRemoteForward);
1245
		dynamicfwd = (opcode == oDynamicForward);
1246
1247
		if (!dynamicfwd) {
1248
			arg2 = strdelim(&s);
1249
			if (arg2 == NULL || *arg2 == '\0') {
1250
				if (remotefwd)
1251
					dynamicfwd = 1;
1252
				else
1253
					fatal("%.200s line %d: Missing target "
1254
					    "argument.", filename, linenum);
1255
			} else {
1256
				/* construct a string for parse_forward */
1257
				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1258
				    arg2);
1259
			}
1260
		}
1261
		if (dynamicfwd)
1262
			strlcpy(fwdarg, arg, sizeof(fwdarg));
1263
1264
		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1265
			fatal("%.200s line %d: Bad forwarding specification.",
1266
			    filename, linenum);
1267
1268
		if (*activep) {
1269
			if (remotefwd) {
1270
				add_remote_forward(options, &fwd);
1271
			} else {
1272
				add_local_forward(options, &fwd);
1273
			}
1274
		}
1275
		break;
1276
1277
	case oClearAllForwardings:
1278
		intptr = &options->clear_forwardings;
1279
		goto parse_flag;
1280
1281
	case oHost:
1282
		if (cmdline)
1283
			fatal("Host directive not supported as a command-line "
1284
			    "option");
1285
		*activep = 0;
1286
		arg2 = NULL;
1287
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1288
			if ((flags & SSHCONF_NEVERMATCH) != 0)
1289
				break;
1290
			negated = *arg == '!';
1291
			if (negated)
1292
				arg++;
1293
			if (match_pattern(host, arg)) {
1294
				if (negated) {
1295
					debug("%.200s line %d: Skipping Host "
1296
					    "block because of negated match "
1297
					    "for %.100s", filename, linenum,
1298
					    arg);
1299
					*activep = 0;
1300
					break;
1301
				}
1302
				if (!*activep)
1303
					arg2 = arg; /* logged below */
1304
				*activep = 1;
1305
			}
1306
		}
1307
		if (*activep)
1308
			debug("%.200s line %d: Applying options for %.100s",
1309
			    filename, linenum, arg2);
1310
		/* Avoid garbage check below, as strdelim is done. */
1311
		return 0;
1312
1313
	case oMatch:
1314
		if (cmdline)
1315
			fatal("Host directive not supported as a command-line "
1316
			    "option");
1317
		value = match_cfg_line(options, &s, pw, host, original_host,
1318
		    flags & SSHCONF_POSTCANON, filename, linenum);
1319
		if (value < 0)
1320
			fatal("%.200s line %d: Bad Match condition", filename,
1321
			    linenum);
1322
		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1323
		break;
1324
1325
	case oEscapeChar:
1326
		intptr = &options->escape_char;
1327
		arg = strdelim(&s);
1328
		if (!arg || *arg == '\0')
1329
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1330
		if (strcmp(arg, "none") == 0)
1331
			value = SSH_ESCAPECHAR_NONE;
1332
		else if (arg[1] == '\0')
1333
			value = (u_char) arg[0];
1334
		else if (arg[0] == '^' && arg[2] == 0 &&
1335
		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1336
			value = (u_char) arg[1] & 31;
1337
		else {
1338
			fatal("%.200s line %d: Bad escape character.",
1339
			    filename, linenum);
1340
			/* NOTREACHED */
1341
			value = 0;	/* Avoid compiler warning. */
1342
		}
1343
		if (*activep && *intptr == -1)
1344
			*intptr = value;
1345
		break;
1346
1347
	case oAddressFamily:
1348
		intptr = &options->address_family;
1349
		multistate_ptr = multistate_addressfamily;
1350
		goto parse_multistate;
1351
1352
	case oEnableSSHKeysign:
1353
		intptr = &options->enable_ssh_keysign;
1354
		goto parse_flag;
1355
1356
	case oIdentitiesOnly:
1357
		intptr = &options->identities_only;
1358
		goto parse_flag;
1359
1360
	case oServerAliveInterval:
1361
		intptr = &options->server_alive_interval;
1362
		goto parse_time;
1363
1364
	case oServerAliveCountMax:
1365
		intptr = &options->server_alive_count_max;
1366
		goto parse_int;
1367
1368
	case oSendEnv:
1369
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1370
			if (strchr(arg, '=') != NULL)
1371
				fatal("%s line %d: Invalid environment name.",
1372
				    filename, linenum);
1373
			if (!*activep)
1374
				continue;
1375
			if (options->num_send_env >= MAX_SEND_ENV)
1376
				fatal("%s line %d: too many send env.",
1377
				    filename, linenum);
1378
			options->send_env[options->num_send_env++] =
1379
			    xstrdup(arg);
1380
		}
1381
		break;
1382
1383
	case oControlPath:
1384
		charptr = &options->control_path;
1385
		goto parse_string;
1386
1387
	case oControlMaster:
1388
		intptr = &options->control_master;
1389
		multistate_ptr = multistate_controlmaster;
1390
		goto parse_multistate;
1391
1392
	case oControlPersist:
1393
		/* no/false/yes/true, or a time spec */
1394
		intptr = &options->control_persist;
1395
		arg = strdelim(&s);
1396
		if (!arg || *arg == '\0')
1397
			fatal("%.200s line %d: Missing ControlPersist"
1398
			    " argument.", filename, linenum);
1399
		value = 0;
1400
		value2 = 0;	/* timeout */
1401
		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1402
			value = 0;
1403
		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1404
			value = 1;
1405
		else if ((value2 = convtime(arg)) >= 0)
1406
			value = 1;
1407
		else
1408
			fatal("%.200s line %d: Bad ControlPersist argument.",
1409
			    filename, linenum);
1410
		if (*activep && *intptr == -1) {
1411
			*intptr = value;
1412
			options->control_persist_timeout = value2;
1413
		}
1414
		break;
1415
1416
	case oHashKnownHosts:
1417
		intptr = &options->hash_known_hosts;
1418
		goto parse_flag;
1419
1420
	case oTunnel:
1421
		intptr = &options->tun_open;
1422
		multistate_ptr = multistate_tunnel;
1423
		goto parse_multistate;
1424
1425
	case oTunnelDevice:
1426
		arg = strdelim(&s);
1427
		if (!arg || *arg == '\0')
1428
			fatal("%.200s line %d: Missing argument.", filename, linenum);
1429
		value = a2tun(arg, &value2);
1430
		if (value == SSH_TUNID_ERR)
1431
			fatal("%.200s line %d: Bad tun device.", filename, linenum);
1432
		if (*activep) {
1433
			options->tun_local = value;
1434
			options->tun_remote = value2;
1435
		}
1436
		break;
1437
1438
	case oLocalCommand:
1439
		charptr = &options->local_command;
1440
		goto parse_command;
1441
1442
	case oPermitLocalCommand:
1443
		intptr = &options->permit_local_command;
1444
		goto parse_flag;
1445
1446
	case oRemoteCommand:
1447
		charptr = &options->remote_command;
1448
		goto parse_command;
1449
1450
	case oVisualHostKey:
1451
		intptr = &options->visual_host_key;
1452
		goto parse_flag;
1453
1454
	case oInclude:
1455
		if (cmdline)
1456
			fatal("Include directive not supported as a "
1457
			    "command-line option");
1458
		value = 0;
1459
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1460
			/*
1461
			 * Ensure all paths are anchored. User configuration
1462
			 * files may begin with '~/' but system configurations
1463
			 * must not. If the path is relative, then treat it
1464
			 * as living in ~/.ssh for user configurations or
1465
			 * /etc/ssh for system ones.
1466
			 */
1467
			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
1468
				fatal("%.200s line %d: bad include path %s.",
1469
				    filename, linenum, arg);
1470
			if (*arg != '/' && *arg != '~') {
1471
				xasprintf(&arg2, "%s/%s",
1472
				    (flags & SSHCONF_USERCONF) ?
1473
				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1474
			} else
1475
				arg2 = xstrdup(arg);
1476
			memset(&gl, 0, sizeof(gl));
1477
			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1478
			if (r == GLOB_NOMATCH) {
1479
				debug("%.200s line %d: include %s matched no "
1480
				    "files",filename, linenum, arg2);
1481
				free(arg2);
1482
				continue;
1483
			} else if (r != 0 || gl.gl_pathc < 0)
1484
				fatal("%.200s line %d: glob failed for %s.",
1485
				    filename, linenum, arg2);
1486
			free(arg2);
1487
			oactive = *activep;
1488
			for (i = 0; i < (u_int)gl.gl_pathc; i++) {
1489
				debug3("%.200s line %d: Including file %s "
1490
				    "depth %d%s", filename, linenum,
1491
				    gl.gl_pathv[i], depth,
1492
				    oactive ? "" : " (parse only)");
1493
				r = read_config_file_depth(gl.gl_pathv[i],
1494
				    pw, host, original_host, options,
1495
				    flags | SSHCONF_CHECKPERM |
1496
				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1497
				    activep, depth + 1);
1498
				if (r != 1 && errno != ENOENT) {
1499
					fatal("Can't open user config file "
1500
					    "%.100s: %.100s", gl.gl_pathv[i],
1501
					    strerror(errno));
1502
				}
1503
				/*
1504
				 * don't let Match in includes clobber the
1505
				 * containing file's Match state.
1506
				 */
1507
				*activep = oactive;
1508
				if (r != 1)
1509
					value = -1;
1510
			}
1511
			globfree(&gl);
1512
		}
1513
		if (value != 0)
1514
			return value;
1515
		break;
1516
1517
	case oIPQoS:
1518
		arg = strdelim(&s);
1519
		if ((value = parse_ipqos(arg)) == -1)
1520
			fatal("%s line %d: Bad IPQoS value: %s",
1521
			    filename, linenum, arg);
1522
		arg = strdelim(&s);
1523
		if (arg == NULL)
1524
			value2 = value;
1525
		else if ((value2 = parse_ipqos(arg)) == -1)
1526
			fatal("%s line %d: Bad IPQoS value: %s",
1527
			    filename, linenum, arg);
1528
		if (*activep) {
1529
			options->ip_qos_interactive = value;
1530
			options->ip_qos_bulk = value2;
1531
		}
1532
		break;
1533
1534
	case oRequestTTY:
1535
		intptr = &options->request_tty;
1536
		multistate_ptr = multistate_requesttty;
1537
		goto parse_multistate;
1538
1539
	case oIgnoreUnknown:
1540
		charptr = &options->ignored_unknown;
1541
		goto parse_string;
1542
1543
	case oProxyUseFdpass:
1544
		intptr = &options->proxy_use_fdpass;
1545
		goto parse_flag;
1546
1547
	case oCanonicalDomains:
1548
		value = options->num_canonical_domains != 0;
1549
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1550
			valid_domain(arg, filename, linenum);
1551
			if (!*activep || value)
1552
				continue;
1553
			if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1554
				fatal("%s line %d: too many hostname suffixes.",
1555
				    filename, linenum);
1556
			options->canonical_domains[
1557
			    options->num_canonical_domains++] = xstrdup(arg);
1558
		}
1559
		break;
1560
1561
	case oCanonicalizePermittedCNAMEs:
1562
		value = options->num_permitted_cnames != 0;
1563
		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1564
			/* Either '*' for everything or 'list:list' */
1565
			if (strcmp(arg, "*") == 0)
1566
				arg2 = arg;
1567
			else {
1568
				lowercase(arg);
1569
				if ((arg2 = strchr(arg, ':')) == NULL ||
1570
				    arg2[1] == '\0') {
1571
					fatal("%s line %d: "
1572
					    "Invalid permitted CNAME \"%s\"",
1573
					    filename, linenum, arg);
1574
				}
1575
				*arg2 = '\0';
1576
				arg2++;
1577
			}
1578
			if (!*activep || value)
1579
				continue;
1580
			if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1581
				fatal("%s line %d: too many permitted CNAMEs.",
1582
				    filename, linenum);
1583
			cname = options->permitted_cnames +
1584
			    options->num_permitted_cnames++;
1585
			cname->source_list = xstrdup(arg);
1586
			cname->target_list = xstrdup(arg2);
1587
		}
1588
		break;
1589
1590
	case oCanonicalizeHostname:
1591
		intptr = &options->canonicalize_hostname;
1592
		multistate_ptr = multistate_canonicalizehostname;
1593
		goto parse_multistate;
1594
1595
	case oCanonicalizeMaxDots:
1596
		intptr = &options->canonicalize_max_dots;
1597
		goto parse_int;
1598
1599
	case oCanonicalizeFallbackLocal:
1600
		intptr = &options->canonicalize_fallback_local;
1601
		goto parse_flag;
1602
1603
	case oStreamLocalBindMask:
1604
		arg = strdelim(&s);
1605
		if (!arg || *arg == '\0')
1606
			fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1607
		/* Parse mode in octal format */
1608
		value = strtol(arg, &endofnumber, 8);
1609
		if (arg == endofnumber || value < 0 || value > 0777)
1610
			fatal("%.200s line %d: Bad mask.", filename, linenum);
1611
		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1612
		break;
1613
1614
	case oStreamLocalBindUnlink:
1615
		intptr = &options->fwd_opts.streamlocal_bind_unlink;
1616
		goto parse_flag;
1617
1618
	case oRevokedHostKeys:
1619
		charptr = &options->revoked_host_keys;
1620
		goto parse_string;
1621
1622
	case oFingerprintHash:
1623
		intptr = &options->fingerprint_hash;
1624
		arg = strdelim(&s);
1625
		if (!arg || *arg == '\0')
1626
			fatal("%.200s line %d: Missing argument.",
1627
			    filename, linenum);
1628
		if ((value = ssh_digest_alg_by_name(arg)) == -1)
1629
			fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1630
			    filename, linenum, arg);
1631
		if (*activep && *intptr == -1)
1632
			*intptr = value;
1633
		break;
1634
1635
	case oUpdateHostkeys:
1636
		intptr = &options->update_hostkeys;
1637
		multistate_ptr = multistate_yesnoask;
1638
		goto parse_multistate;
1639
1640
	case oHostbasedKeyTypes:
1641
		charptr = &options->hostbased_key_types;
1642
		goto parse_keytypes;
1643
1644
	case oPubkeyAcceptedKeyTypes:
1645
		charptr = &options->pubkey_key_types;
1646
		goto parse_keytypes;
1647
1648
	case oAddKeysToAgent:
1649
		intptr = &options->add_keys_to_agent;
1650
		multistate_ptr = multistate_yesnoaskconfirm;
1651
		goto parse_multistate;
1652
1653
	case oIdentityAgent:
1654
		charptr = &options->identity_agent;
1655
		goto parse_string;
1656
1657
	case oDeprecated:
1658
		debug("%s line %d: Deprecated option \"%s\"",
1659
		    filename, linenum, keyword);
1660
		return 0;
1661
1662
	case oUnsupported:
1663
		error("%s line %d: Unsupported option \"%s\"",
1664
		    filename, linenum, keyword);
1665
		return 0;
1666
1667
	default:
1668
		fatal("%s: Unimplemented opcode %d", __func__, opcode);
1669
	}
1670
1671
	/* Check that there is no garbage at end of line. */
1672
	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1673
		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1674
		    filename, linenum, arg);
1675
	}
1676
	return 0;
1677
}
1678
1679
/*
1680
 * Reads the config file and modifies the options accordingly.  Options
1681
 * should already be initialized before this call.  This never returns if
1682
 * there is an error.  If the file does not exist, this returns 0.
1683
 */
1684
int
1685
read_config_file(const char *filename, struct passwd *pw, const char *host,
1686
    const char *original_host, Options *options, int flags)
1687
{
1688
	int active = 1;
1689
1690
	return read_config_file_depth(filename, pw, host, original_host,
1691
	    options, flags, &active, 0);
1692
}
1693
1694
#define READCONF_MAX_DEPTH	16
1695
static int
1696
read_config_file_depth(const char *filename, struct passwd *pw,
1697
    const char *host, const char *original_host, Options *options,
1698
    int flags, int *activep, int depth)
1699
{
1700
	FILE *f;
1701
	char line[4096];
1702
	int linenum;
1703
	int bad_options = 0;
1704
1705
	if (depth < 0 || depth > READCONF_MAX_DEPTH)
1706
		fatal("Too many recursive configuration includes");
1707
1708
	if ((f = fopen(filename, "r")) == NULL)
1709
		return 0;
1710
1711
	if (flags & SSHCONF_CHECKPERM) {
1712
		struct stat sb;
1713
1714
		if (fstat(fileno(f), &sb) == -1)
1715
			fatal("fstat %s: %s", filename, strerror(errno));
1716
		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1717
		    (sb.st_mode & 022) != 0))
1718
			fatal("Bad owner or permissions on %s", filename);
1719
	}
1720
1721
	debug("Reading configuration data %.200s", filename);
1722
1723
	/*
1724
	 * Mark that we are now processing the options.  This flag is turned
1725
	 * on/off by Host specifications.
1726
	 */
1727
	linenum = 0;
1728
	while (fgets(line, sizeof(line), f)) {
1729
		/* Update line number counter. */
1730
		linenum++;
1731
		if (strlen(line) == sizeof(line) - 1)
1732
			fatal("%s line %d too long", filename, linenum);
1733
		if (process_config_line_depth(options, pw, host, original_host,
1734
		    line, filename, linenum, activep, flags, depth) != 0)
1735
			bad_options++;
1736
	}
1737
	fclose(f);
1738
	if (bad_options > 0)
1739
		fatal("%s: terminating, %d bad configuration options",
1740
		    filename, bad_options);
1741
	return 1;
1742
}
1743
1744
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1745
int
1746
option_clear_or_none(const char *o)
1747
{
1748
	return o == NULL || strcasecmp(o, "none") == 0;
1749
}
1750
1751
/*
1752
 * Initializes options to special values that indicate that they have not yet
1753
 * been set.  Read_config_file will only set options with this value. Options
1754
 * are processed in the following order: command line, user config file,
1755
 * system config file.  Last, fill_default_options is called.
1756
 */
1757
1758
void
1759
initialize_options(Options * options)
1760
{
1761
	memset(options, 'X', sizeof(*options));
1762
	options->forward_agent = -1;
1763
	options->forward_x11 = -1;
1764
	options->forward_x11_trusted = -1;
1765
	options->forward_x11_timeout = -1;
1766
	options->stdio_forward_host = NULL;
1767
	options->stdio_forward_port = 0;
1768
	options->clear_forwardings = -1;
1769
	options->exit_on_forward_failure = -1;
1770
	options->xauth_location = NULL;
1771
	options->fwd_opts.gateway_ports = -1;
1772
	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1773
	options->fwd_opts.streamlocal_bind_unlink = -1;
1774
	options->use_privileged_port = -1;
1775
	options->pubkey_authentication = -1;
1776
	options->challenge_response_authentication = -1;
1777
	options->gss_authentication = -1;
1778
	options->gss_deleg_creds = -1;
1779
	options->password_authentication = -1;
1780
	options->kbd_interactive_authentication = -1;
1781
	options->kbd_interactive_devices = NULL;
1782
	options->hostbased_authentication = -1;
1783
	options->batch_mode = -1;
1784
	options->check_host_ip = -1;
1785
	options->strict_host_key_checking = -1;
1786
	options->compression = -1;
1787
	options->tcp_keep_alive = -1;
1788
	options->port = -1;
1789
	options->address_family = -1;
1790
	options->connection_attempts = -1;
1791
	options->connection_timeout = -1;
1792
	options->number_of_password_prompts = -1;
1793
	options->ciphers = NULL;
1794
	options->macs = NULL;
1795
	options->kex_algorithms = NULL;
1796
	options->hostkeyalgorithms = NULL;
1797
	options->num_identity_files = 0;
1798
	options->num_certificate_files = 0;
1799
	options->hostname = NULL;
1800
	options->host_key_alias = NULL;
1801
	options->proxy_command = NULL;
1802
	options->jump_user = NULL;
1803
	options->jump_host = NULL;
1804
	options->jump_port = -1;
1805
	options->jump_extra = NULL;
1806
	options->user = NULL;
1807
	options->escape_char = -1;
1808
	options->num_system_hostfiles = 0;
1809
	options->num_user_hostfiles = 0;
1810
	options->local_forwards = NULL;
1811
	options->num_local_forwards = 0;
1812
	options->remote_forwards = NULL;
1813
	options->num_remote_forwards = 0;
1814
	options->log_facility = SYSLOG_FACILITY_NOT_SET;
1815
	options->log_level = SYSLOG_LEVEL_NOT_SET;
1816
	options->preferred_authentications = NULL;
1817
	options->bind_address = NULL;
1818
	options->pkcs11_provider = NULL;
1819
	options->enable_ssh_keysign = - 1;
1820
	options->no_host_authentication_for_localhost = - 1;
1821
	options->identities_only = - 1;
1822
	options->rekey_limit = - 1;
1823
	options->rekey_interval = -1;
1824
	options->verify_host_key_dns = -1;
1825
	options->server_alive_interval = -1;
1826
	options->server_alive_count_max = -1;
1827
	options->num_send_env = 0;
1828
	options->control_path = NULL;
1829
	options->control_master = -1;
1830
	options->control_persist = -1;
1831
	options->control_persist_timeout = 0;
1832
	options->hash_known_hosts = -1;
1833
	options->tun_open = -1;
1834
	options->tun_local = -1;
1835
	options->tun_remote = -1;
1836
	options->local_command = NULL;
1837
	options->permit_local_command = -1;
1838
	options->remote_command = NULL;
1839
	options->add_keys_to_agent = -1;
1840
	options->identity_agent = NULL;
1841
	options->visual_host_key = -1;
1842
	options->ip_qos_interactive = -1;
1843
	options->ip_qos_bulk = -1;
1844
	options->request_tty = -1;
1845
	options->proxy_use_fdpass = -1;
1846
	options->ignored_unknown = NULL;
1847
	options->num_canonical_domains = 0;
1848
	options->num_permitted_cnames = 0;
1849
	options->canonicalize_max_dots = -1;
1850
	options->canonicalize_fallback_local = -1;
1851
	options->canonicalize_hostname = -1;
1852
	options->revoked_host_keys = NULL;
1853
	options->fingerprint_hash = -1;
1854
	options->update_hostkeys = -1;
1855
	options->hostbased_key_types = NULL;
1856
	options->pubkey_key_types = NULL;
1857
}
1858
1859
/*
1860
 * A petite version of fill_default_options() that just fills the options
1861
 * needed for hostname canonicalization to proceed.
1862
 */
1863
void
1864
fill_default_options_for_canonicalization(Options *options)
1865
{
1866
	if (options->canonicalize_max_dots == -1)
1867
		options->canonicalize_max_dots = 1;
1868
	if (options->canonicalize_fallback_local == -1)
1869
		options->canonicalize_fallback_local = 1;
1870
	if (options->canonicalize_hostname == -1)
1871
		options->canonicalize_hostname = SSH_CANONICALISE_NO;
1872
}
1873
1874
/*
1875
 * Called after processing other sources of option data, this fills those
1876
 * options for which no value has been specified with their default values.
1877
 */
1878
void
1879
fill_default_options(Options * options)
1880
{
1881
	if (options->forward_agent == -1)
1882
		options->forward_agent = 0;
1883
	if (options->forward_x11 == -1)
1884
		options->forward_x11 = 0;
1885
	if (options->forward_x11_trusted == -1)
1886
		options->forward_x11_trusted = 0;
1887
	if (options->forward_x11_timeout == -1)
1888
		options->forward_x11_timeout = 1200;
1889
	/*
1890
	 * stdio forwarding (-W) changes the default for these but we defer
1891
	 * setting the values so they can be overridden.
1892
	 */
1893
	if (options->exit_on_forward_failure == -1)
1894
		options->exit_on_forward_failure =
1895
		    options->stdio_forward_host != NULL ? 1 : 0;
1896
	if (options->clear_forwardings == -1)
1897
		options->clear_forwardings =
1898
		    options->stdio_forward_host != NULL ? 1 : 0;
1899
	if (options->clear_forwardings == 1)
1900
		clear_forwardings(options);
1901
1902
	if (options->xauth_location == NULL)
1903
		options->xauth_location = _PATH_XAUTH;
1904
	if (options->fwd_opts.gateway_ports == -1)
1905
		options->fwd_opts.gateway_ports = 0;
1906
	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1907
		options->fwd_opts.streamlocal_bind_mask = 0177;
1908
	if (options->fwd_opts.streamlocal_bind_unlink == -1)
1909
		options->fwd_opts.streamlocal_bind_unlink = 0;
1910
	if (options->use_privileged_port == -1)
1911
		options->use_privileged_port = 0;
1912
	if (options->pubkey_authentication == -1)
1913
		options->pubkey_authentication = 1;
1914
	if (options->challenge_response_authentication == -1)
1915
		options->challenge_response_authentication = 1;
1916
	if (options->gss_authentication == -1)
1917
		options->gss_authentication = 0;
1918
	if (options->gss_deleg_creds == -1)
1919
		options->gss_deleg_creds = 0;
1920
	if (options->password_authentication == -1)
1921
		options->password_authentication = 1;
1922
	if (options->kbd_interactive_authentication == -1)
1923
		options->kbd_interactive_authentication = 1;
1924
	if (options->hostbased_authentication == -1)
1925
		options->hostbased_authentication = 0;
1926
	if (options->batch_mode == -1)
1927
		options->batch_mode = 0;
1928
	if (options->check_host_ip == -1)
1929
		options->check_host_ip = 1;
1930
	if (options->strict_host_key_checking == -1)
1931
		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
1932
	if (options->compression == -1)
1933
		options->compression = 0;
1934
	if (options->tcp_keep_alive == -1)
1935
		options->tcp_keep_alive = 1;
1936
	if (options->port == -1)
1937
		options->port = 0;	/* Filled in ssh_connect. */
1938
	if (options->address_family == -1)
1939
		options->address_family = AF_UNSPEC;
1940
	if (options->connection_attempts == -1)
1941
		options->connection_attempts = 1;
1942
	if (options->number_of_password_prompts == -1)
1943
		options->number_of_password_prompts = 3;
1944
	/* options->hostkeyalgorithms, default set in myproposals.h */
1945
	if (options->add_keys_to_agent == -1)
1946
		options->add_keys_to_agent = 0;
1947
	if (options->num_identity_files == 0) {
1948
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
1949
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
1950
		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
1951
		add_identity_file(options, "~/",
1952
		    _PATH_SSH_CLIENT_ID_ED25519, 0);
1953
	}
1954
	if (options->escape_char == -1)
1955
		options->escape_char = '~';
1956
	if (options->num_system_hostfiles == 0) {
1957
		options->system_hostfiles[options->num_system_hostfiles++] =
1958
		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1959
		options->system_hostfiles[options->num_system_hostfiles++] =
1960
		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1961
	}
1962
	if (options->num_user_hostfiles == 0) {
1963
		options->user_hostfiles[options->num_user_hostfiles++] =
1964
		    xstrdup(_PATH_SSH_USER_HOSTFILE);
1965
		options->user_hostfiles[options->num_user_hostfiles++] =
1966
		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
1967
	}
1968
	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1969
		options->log_level = SYSLOG_LEVEL_INFO;
1970
	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
1971
		options->log_facility = SYSLOG_FACILITY_USER;
1972
	if (options->no_host_authentication_for_localhost == - 1)
1973
		options->no_host_authentication_for_localhost = 0;
1974
	if (options->identities_only == -1)
1975
		options->identities_only = 0;
1976
	if (options->enable_ssh_keysign == -1)
1977
		options->enable_ssh_keysign = 0;
1978
	if (options->rekey_limit == -1)
1979
		options->rekey_limit = 0;
1980
	if (options->rekey_interval == -1)
1981
		options->rekey_interval = 0;
1982
	if (options->verify_host_key_dns == -1)
1983
		options->verify_host_key_dns = 0;
1984
	if (options->server_alive_interval == -1)
1985
		options->server_alive_interval = 0;
1986
	if (options->server_alive_count_max == -1)
1987
		options->server_alive_count_max = 3;
1988
	if (options->control_master == -1)
1989
		options->control_master = 0;
1990
	if (options->control_persist == -1) {
1991
		options->control_persist = 0;
1992
		options->control_persist_timeout = 0;
1993
	}
1994
	if (options->hash_known_hosts == -1)
1995
		options->hash_known_hosts = 0;
1996
	if (options->tun_open == -1)
1997
		options->tun_open = SSH_TUNMODE_NO;
1998
	if (options->tun_local == -1)
1999
		options->tun_local = SSH_TUNID_ANY;
2000
	if (options->tun_remote == -1)
2001
		options->tun_remote = SSH_TUNID_ANY;
2002
	if (options->permit_local_command == -1)
2003
		options->permit_local_command = 0;
2004
	if (options->visual_host_key == -1)
2005
		options->visual_host_key = 0;
2006
	if (options->ip_qos_interactive == -1)
2007
		options->ip_qos_interactive = IPTOS_LOWDELAY;
2008
	if (options->ip_qos_bulk == -1)
2009
		options->ip_qos_bulk = IPTOS_THROUGHPUT;
2010
	if (options->request_tty == -1)
2011
		options->request_tty = REQUEST_TTY_AUTO;
2012
	if (options->proxy_use_fdpass == -1)
2013
		options->proxy_use_fdpass = 0;
2014
	if (options->canonicalize_max_dots == -1)
2015
		options->canonicalize_max_dots = 1;
2016
	if (options->canonicalize_fallback_local == -1)
2017
		options->canonicalize_fallback_local = 1;
2018
	if (options->canonicalize_hostname == -1)
2019
		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2020
	if (options->fingerprint_hash == -1)
2021
		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2022
	if (options->update_hostkeys == -1)
2023
		options->update_hostkeys = 0;
2024
	if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 ||
2025
	    kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 ||
2026
	    kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 ||
2027
	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
2028
	    &options->hostbased_key_types) != 0 ||
2029
	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
2030
	    &options->pubkey_key_types) != 0)
2031
		fatal("%s: kex_assemble_names failed", __func__);
2032
2033
#define CLEAR_ON_NONE(v) \
2034
	do { \
2035
		if (option_clear_or_none(v)) { \
2036
			free(v); \
2037
			v = NULL; \
2038
		} \
2039
	} while(0)
2040
	CLEAR_ON_NONE(options->local_command);
2041
	CLEAR_ON_NONE(options->remote_command);
2042
	CLEAR_ON_NONE(options->proxy_command);
2043
	CLEAR_ON_NONE(options->control_path);
2044
	CLEAR_ON_NONE(options->revoked_host_keys);
2045
	/* options->identity_agent distinguishes NULL from 'none' */
2046
	/* options->user will be set in the main program if appropriate */
2047
	/* options->hostname will be set in the main program if appropriate */
2048
	/* options->host_key_alias should not be set by default */
2049
	/* options->preferred_authentications will be set in ssh */
2050
}
2051
2052
struct fwdarg {
2053
	char *arg;
2054
	int ispath;
2055
};
2056
2057
/*
2058
 * parse_fwd_field
2059
 * parses the next field in a port forwarding specification.
2060
 * sets fwd to the parsed field and advances p past the colon
2061
 * or sets it to NULL at end of string.
2062
 * returns 0 on success, else non-zero.
2063
 */
2064
static int
2065
parse_fwd_field(char **p, struct fwdarg *fwd)
2066
{
2067
	char *ep, *cp = *p;
2068
	int ispath = 0;
2069
2070
	if (*cp == '\0') {
2071
		*p = NULL;
2072
		return -1;	/* end of string */
2073
	}
2074
2075
	/*
2076
	 * A field escaped with square brackets is used literally.
2077
	 * XXX - allow ']' to be escaped via backslash?
2078
	 */
2079
	if (*cp == '[') {
2080
		/* find matching ']' */
2081
		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2082
			if (*ep == '/')
2083
				ispath = 1;
2084
		}
2085
		/* no matching ']' or not at end of field. */
2086
		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2087
			return -1;
2088
		/* NUL terminate the field and advance p past the colon */
2089
		*ep++ = '\0';
2090
		if (*ep != '\0')
2091
			*ep++ = '\0';
2092
		fwd->arg = cp + 1;
2093
		fwd->ispath = ispath;
2094
		*p = ep;
2095
		return 0;
2096
	}
2097
2098
	for (cp = *p; *cp != '\0'; cp++) {
2099
		switch (*cp) {
2100
		case '\\':
2101
			memmove(cp, cp + 1, strlen(cp + 1) + 1);
2102
			if (*cp == '\0')
2103
				return -1;
2104
			break;
2105
		case '/':
2106
			ispath = 1;
2107
			break;
2108
		case ':':
2109
			*cp++ = '\0';
2110
			goto done;
2111
		}
2112
	}
2113
done:
2114
	fwd->arg = *p;
2115
	fwd->ispath = ispath;
2116
	*p = cp;
2117
	return 0;
2118
}
2119
2120
/*
2121
 * parse_forward
2122
 * parses a string containing a port forwarding specification of the form:
2123
 *   dynamicfwd == 0
2124
 *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
2125
 *	listenpath:connectpath
2126
 *   dynamicfwd == 1
2127
 *	[listenhost:]listenport
2128
 * returns number of arguments parsed or zero on error
2129
 */
2130
int
2131
parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
2132
{
2133
	struct fwdarg fwdargs[4];
2134
	char *p, *cp;
2135
	int i;
2136
2137
	memset(fwd, 0, sizeof(*fwd));
2138
	memset(fwdargs, 0, sizeof(fwdargs));
2139
2140
	cp = p = xstrdup(fwdspec);
2141
2142
	/* skip leading spaces */
2143
	while (isspace((u_char)*cp))
2144
		cp++;
2145
2146
	for (i = 0; i < 4; ++i) {
2147
		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
2148
			break;
2149
	}
2150
2151
	/* Check for trailing garbage */
2152
	if (cp != NULL && *cp != '\0') {
2153
		i = 0;	/* failure */
2154
	}
2155
2156
	switch (i) {
2157
	case 1:
2158
		if (fwdargs[0].ispath) {
2159
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2160
			fwd->listen_port = PORT_STREAMLOCAL;
2161
		} else {
2162
			fwd->listen_host = NULL;
2163
			fwd->listen_port = a2port(fwdargs[0].arg);
2164
		}
2165
		fwd->connect_host = xstrdup("socks");
2166
		break;
2167
2168
	case 2:
2169
		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2170
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2171
			fwd->listen_port = PORT_STREAMLOCAL;
2172
			fwd->connect_path = xstrdup(fwdargs[1].arg);
2173
			fwd->connect_port = PORT_STREAMLOCAL;
2174
		} else if (fwdargs[1].ispath) {
2175
			fwd->listen_host = NULL;
2176
			fwd->listen_port = a2port(fwdargs[0].arg);
2177
			fwd->connect_path = xstrdup(fwdargs[1].arg);
2178
			fwd->connect_port = PORT_STREAMLOCAL;
2179
		} else {
2180
			fwd->listen_host = xstrdup(fwdargs[0].arg);
2181
			fwd->listen_port = a2port(fwdargs[1].arg);
2182
			fwd->connect_host = xstrdup("socks");
2183
		}
2184
		break;
2185
2186
	case 3:
2187
		if (fwdargs[0].ispath) {
2188
			fwd->listen_path = xstrdup(fwdargs[0].arg);
2189
			fwd->listen_port = PORT_STREAMLOCAL;
2190
			fwd->connect_host = xstrdup(fwdargs[1].arg);
2191
			fwd->connect_port = a2port(fwdargs[2].arg);
2192
		} else if (fwdargs[2].ispath) {
2193
			fwd->listen_host = xstrdup(fwdargs[0].arg);
2194
			fwd->listen_port = a2port(fwdargs[1].arg);
2195
			fwd->connect_path = xstrdup(fwdargs[2].arg);
2196
			fwd->connect_port = PORT_STREAMLOCAL;
2197
		} else {
2198
			fwd->listen_host = NULL;
2199
			fwd->listen_port = a2port(fwdargs[0].arg);
2200
			fwd->connect_host = xstrdup(fwdargs[1].arg);
2201
			fwd->connect_port = a2port(fwdargs[2].arg);
2202
		}
2203
		break;
2204
2205
	case 4:
2206
		fwd->listen_host = xstrdup(fwdargs[0].arg);
2207
		fwd->listen_port = a2port(fwdargs[1].arg);
2208
		fwd->connect_host = xstrdup(fwdargs[2].arg);
2209
		fwd->connect_port = a2port(fwdargs[3].arg);
2210
		break;
2211
	default:
2212
		i = 0; /* failure */
2213
	}
2214
2215
	free(p);
2216
2217
	if (dynamicfwd) {
2218
		if (!(i == 1 || i == 2))
2219
			goto fail_free;
2220
	} else {
2221
		if (!(i == 3 || i == 4)) {
2222
			if (fwd->connect_path == NULL &&
2223
			    fwd->listen_path == NULL)
2224
				goto fail_free;
2225
		}
2226
		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2227
			goto fail_free;
2228
	}
2229
2230
	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2231
	    (!remotefwd && fwd->listen_port == 0))
2232
		goto fail_free;
2233
	if (fwd->connect_host != NULL &&
2234
	    strlen(fwd->connect_host) >= NI_MAXHOST)
2235
		goto fail_free;
2236
	/* XXX - if connecting to a remote socket, max sun len may not match this host */
2237
	if (fwd->connect_path != NULL &&
2238
	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2239
		goto fail_free;
2240
	if (fwd->listen_host != NULL &&
2241
	    strlen(fwd->listen_host) >= NI_MAXHOST)
2242
		goto fail_free;
2243
	if (fwd->listen_path != NULL &&
2244
	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2245
		goto fail_free;
2246
2247
	return (i);
2248
2249
 fail_free:
2250
	free(fwd->connect_host);
2251
	fwd->connect_host = NULL;
2252
	free(fwd->connect_path);
2253
	fwd->connect_path = NULL;
2254
	free(fwd->listen_host);
2255
	fwd->listen_host = NULL;
2256
	free(fwd->listen_path);
2257
	fwd->listen_path = NULL;
2258
	return (0);
2259
}
2260
2261
int
2262
parse_jump(const char *s, Options *o, int active)
2263
{
2264
	char *orig, *sdup, *cp;
2265
	char *host = NULL, *user = NULL;
2266
	int ret = -1, port = -1, first;
2267
2268
	active &= o->proxy_command == NULL && o->jump_host == NULL;
2269
2270
	orig = sdup = xstrdup(s);
2271
	first = active;
2272
	do {
2273
		if ((cp = strrchr(sdup, ',')) == NULL)
2274
			cp = sdup; /* last */
2275
		else
2276
			*cp++ = '\0';
2277
2278
		if (first) {
2279
			/* First argument and configuration is active */
2280
			if (parse_user_host_port(cp, &user, &host, &port) != 0)
2281
				goto out;
2282
		} else {
2283
			/* Subsequent argument or inactive configuration */
2284
			if (parse_user_host_port(cp, NULL, NULL, NULL) != 0)
2285
				goto out;
2286
		}
2287
		first = 0; /* only check syntax for subsequent hosts */
2288
	} while (cp != sdup);
2289
	/* success */
2290
	if (active) {
2291
		o->jump_user = user;
2292
		o->jump_host = host;
2293
		o->jump_port = port;
2294
		o->proxy_command = xstrdup("none");
2295
		user = host = NULL;
2296
		if ((cp = strrchr(s, ',')) != NULL && cp != s) {
2297
			o->jump_extra = xstrdup(s);
2298
			o->jump_extra[cp - s] = '\0';
2299
		}
2300
	}
2301
	ret = 0;
2302
 out:
2303
	free(orig);
2304
	free(user);
2305
	free(host);
2306
	return ret;
2307
}
2308
2309
/* XXX the following is a near-vebatim copy from servconf.c; refactor */
2310
static const char *
2311
fmt_multistate_int(int val, const struct multistate *m)
2312
{
2313
	u_int i;
2314
2315
	for (i = 0; m[i].key != NULL; i++) {
2316
		if (m[i].value == val)
2317
			return m[i].key;
2318
	}
2319
	return "UNKNOWN";
2320
}
2321
2322
static const char *
2323
fmt_intarg(OpCodes code, int val)
2324
{
2325
	if (val == -1)
2326
		return "unset";
2327
	switch (code) {
2328
	case oAddressFamily:
2329
		return fmt_multistate_int(val, multistate_addressfamily);
2330
	case oVerifyHostKeyDNS:
2331
	case oUpdateHostkeys:
2332
		return fmt_multistate_int(val, multistate_yesnoask);
2333
	case oStrictHostKeyChecking:
2334
		return fmt_multistate_int(val, multistate_strict_hostkey);
2335
	case oControlMaster:
2336
		return fmt_multistate_int(val, multistate_controlmaster);
2337
	case oTunnel:
2338
		return fmt_multistate_int(val, multistate_tunnel);
2339
	case oRequestTTY:
2340
		return fmt_multistate_int(val, multistate_requesttty);
2341
	case oCanonicalizeHostname:
2342
		return fmt_multistate_int(val, multistate_canonicalizehostname);
2343
	case oFingerprintHash:
2344
		return ssh_digest_alg_name(val);
2345
	default:
2346
		switch (val) {
2347
		case 0:
2348
			return "no";
2349
		case 1:
2350
			return "yes";
2351
		default:
2352
			return "UNKNOWN";
2353
		}
2354
	}
2355
}
2356
2357
static const char *
2358
lookup_opcode_name(OpCodes code)
2359
{
2360
	u_int i;
2361
2362
	for (i = 0; keywords[i].name != NULL; i++)
2363
		if (keywords[i].opcode == code)
2364
			return(keywords[i].name);
2365
	return "UNKNOWN";
2366
}
2367
2368
static void
2369
dump_cfg_int(OpCodes code, int val)
2370
{
2371
	printf("%s %d\n", lookup_opcode_name(code), val);
2372
}
2373
2374
static void
2375
dump_cfg_fmtint(OpCodes code, int val)
2376
{
2377
	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2378
}
2379
2380
static void
2381
dump_cfg_string(OpCodes code, const char *val)
2382
{
2383
	if (val == NULL)
2384
		return;
2385
	printf("%s %s\n", lookup_opcode_name(code), val);
2386
}
2387
2388
static void
2389
dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2390
{
2391
	u_int i;
2392
2393
	for (i = 0; i < count; i++)
2394
		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2395
}
2396
2397
static void
2398
dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2399
{
2400
	u_int i;
2401
2402
	printf("%s", lookup_opcode_name(code));
2403
	for (i = 0; i < count; i++)
2404
		printf(" %s",  vals[i]);
2405
	printf("\n");
2406
}
2407
2408
static void
2409
dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2410
{
2411
	const struct Forward *fwd;
2412
	u_int i;
2413
2414
	/* oDynamicForward */
2415
	for (i = 0; i < count; i++) {
2416
		fwd = &fwds[i];
2417
		if (code == oDynamicForward && fwd->connect_host != NULL &&
2418
		    strcmp(fwd->connect_host, "socks") != 0)
2419
			continue;
2420
		if (code == oLocalForward && fwd->connect_host != NULL &&
2421
		    strcmp(fwd->connect_host, "socks") == 0)
2422
			continue;
2423
		printf("%s", lookup_opcode_name(code));
2424
		if (fwd->listen_port == PORT_STREAMLOCAL)
2425
			printf(" %s", fwd->listen_path);
2426
		else if (fwd->listen_host == NULL)
2427
			printf(" %d", fwd->listen_port);
2428
		else {
2429
			printf(" [%s]:%d",
2430
			    fwd->listen_host, fwd->listen_port);
2431
		}
2432
		if (code != oDynamicForward) {
2433
			if (fwd->connect_port == PORT_STREAMLOCAL)
2434
				printf(" %s", fwd->connect_path);
2435
			else if (fwd->connect_host == NULL)
2436
				printf(" %d", fwd->connect_port);
2437
			else {
2438
				printf(" [%s]:%d",
2439
				    fwd->connect_host, fwd->connect_port);
2440
			}
2441
		}
2442
		printf("\n");
2443
	}
2444
}
2445
2446
void
2447
dump_client_config(Options *o, const char *host)
2448
{
2449
	int i;
2450
	char buf[8];
2451
2452
	/* This is normally prepared in ssh_kex2 */
2453
	if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0)
2454
		fatal("%s: kex_assemble_names failed", __func__);
2455
2456
	/* Most interesting options first: user, host, port */
2457
	dump_cfg_string(oUser, o->user);
2458
	dump_cfg_string(oHostName, host);
2459
	dump_cfg_int(oPort, o->port);
2460
2461
	/* Flag options */
2462
	dump_cfg_fmtint(oAddressFamily, o->address_family);
2463
	dump_cfg_fmtint(oBatchMode, o->batch_mode);
2464
	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2465
	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2466
	dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2467
	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2468
	dump_cfg_fmtint(oCompression, o->compression);
2469
	dump_cfg_fmtint(oControlMaster, o->control_master);
2470
	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2471
	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
2472
	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2473
	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2474
	dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2475
	dump_cfg_fmtint(oForwardX11, o->forward_x11);
2476
	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2477
	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2478
#ifdef GSSAPI
2479
	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2480
	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2481
#endif /* GSSAPI */
2482
	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2483
	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2484
	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2485
	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2486
	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2487
	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2488
	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2489
	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2490
	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2491
	dump_cfg_fmtint(oRequestTTY, o->request_tty);
2492
	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2493
	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2494
	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2495
	dump_cfg_fmtint(oTunnel, o->tun_open);
2496
	dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
2497
	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2498
	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2499
	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2500
2501
	/* Integer options */
2502
	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2503
	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2504
	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2505
	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2506
	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2507
	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2508
2509
	/* String options */
2510
	dump_cfg_string(oBindAddress, o->bind_address);
2511
	dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2512
	dump_cfg_string(oControlPath, o->control_path);
2513
	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
2514
	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2515
	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2516
	dump_cfg_string(oIdentityAgent, o->identity_agent);
2517
	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2518
	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2519
	dump_cfg_string(oLocalCommand, o->local_command);
2520
	dump_cfg_string(oRemoteCommand, o->remote_command);
2521
	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2522
	dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2523
#ifdef ENABLE_PKCS11
2524
	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2525
#endif
2526
	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2527
	dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
2528
	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2529
	dump_cfg_string(oXAuthLocation, o->xauth_location);
2530
2531
	/* Forwards */
2532
	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2533
	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2534
	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2535
2536
	/* String array options */
2537
	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2538
	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2539
	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2540
	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2541
	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2542
2543
	/* Special cases */
2544
2545
	/* oConnectTimeout */
2546
	if (o->connection_timeout == -1)
2547
		printf("connecttimeout none\n");
2548
	else
2549
		dump_cfg_int(oConnectTimeout, o->connection_timeout);
2550
2551
	/* oTunnelDevice */
2552
	printf("tunneldevice");
2553
	if (o->tun_local == SSH_TUNID_ANY)
2554
		printf(" any");
2555
	else
2556
		printf(" %d", o->tun_local);
2557
	if (o->tun_remote == SSH_TUNID_ANY)
2558
		printf(":any");
2559
	else
2560
		printf(":%d", o->tun_remote);
2561
	printf("\n");
2562
2563
	/* oCanonicalizePermittedCNAMEs */
2564
	if ( o->num_permitted_cnames > 0) {
2565
		printf("canonicalizePermittedcnames");
2566
		for (i = 0; i < o->num_permitted_cnames; i++) {
2567
			printf(" %s:%s", o->permitted_cnames[i].source_list,
2568
			    o->permitted_cnames[i].target_list);
2569
		}
2570
		printf("\n");
2571
	}
2572
2573
	/* oControlPersist */
2574
	if (o->control_persist == 0 || o->control_persist_timeout == 0)
2575
		dump_cfg_fmtint(oControlPersist, o->control_persist);
2576
	else
2577
		dump_cfg_int(oControlPersist, o->control_persist_timeout);
2578
2579
	/* oEscapeChar */
2580
	if (o->escape_char == SSH_ESCAPECHAR_NONE)
2581
		printf("escapechar none\n");
2582
	else {
2583
		vis(buf, o->escape_char, VIS_WHITE, 0);
2584
		printf("escapechar %s\n", buf);
2585
	}
2586
2587
	/* oIPQoS */
2588
	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2589
	printf("%s\n", iptos2str(o->ip_qos_bulk));
2590
2591
	/* oRekeyLimit */
2592
	printf("rekeylimit %llu %d\n",
2593
	    (unsigned long long)o->rekey_limit, o->rekey_interval);
2594
2595
	/* oStreamLocalBindMask */
2596
	printf("streamlocalbindmask 0%o\n",
2597
	    o->fwd_opts.streamlocal_bind_mask);
2598
2599
	/* oProxyCommand / oProxyJump */
2600
	if (o->jump_host == NULL)
2601
		dump_cfg_string(oProxyCommand, o->proxy_command);
2602
	else {
2603
		/* Check for numeric addresses */
2604
		i = strchr(o->jump_host, ':') != NULL ||
2605
		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
2606
		snprintf(buf, sizeof(buf), "%d", o->jump_port);
2607
		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
2608
		    /* optional additional jump spec */
2609
		    o->jump_extra == NULL ? "" : o->jump_extra,
2610
		    o->jump_extra == NULL ? "" : ",",
2611
		    /* optional user */
2612
		    o->jump_user == NULL ? "" : o->jump_user,
2613
		    o->jump_user == NULL ? "" : "@",
2614
		    /* opening [ if hostname is numeric */
2615
		    i ? "[" : "",
2616
		    /* mandatory hostname */
2617
		    o->jump_host,
2618
		    /* closing ] if hostname is numeric */
2619
		    i ? "]" : "",
2620
		    /* optional port number */
2621
		    o->jump_port <= 0 ? "" : ":",
2622
		    o->jump_port <= 0 ? "" : buf);
2623
	}
2624
}