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