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