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