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