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