Import OpenSSH-6.7p1.
[dragonfly.git] / crypto / openssh / readconf.c
blob7948ce1cda719ae949552b338b07b94a892f8865
1 /* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */
2 /*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * Functions for reading the configuration files.
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
15 #include "includes.h"
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/socket.h>
20 #include <sys/wait.h>
21 #include <sys/un.h>
23 #include <netinet/in.h>
24 #include <netinet/in_systm.h>
25 #include <netinet/ip.h>
26 #include <arpa/inet.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <netdb.h>
32 #ifdef HAVE_PATHS_H
33 # include <paths.h>
34 #endif
35 #include <pwd.h>
36 #include <signal.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41 #ifdef HAVE_UTIL_H
42 #include <util.h>
43 #endif
45 #include "xmalloc.h"
46 #include "ssh.h"
47 #include "compat.h"
48 #include "cipher.h"
49 #include "pathnames.h"
50 #include "log.h"
51 #include "key.h"
52 #include "misc.h"
53 #include "readconf.h"
54 #include "match.h"
55 #include "buffer.h"
56 #include "kex.h"
57 #include "mac.h"
58 #include "uidswap.h"
60 /* Format of the configuration file:
62 # Configuration data is parsed as follows:
63 # 1. command line options
64 # 2. user-specific file
65 # 3. system-wide file
66 # Any configuration value is only changed the first time it is set.
67 # Thus, host-specific definitions should be at the beginning of the
68 # configuration file, and defaults at the end.
70 # Host-specific declarations. These may override anything above. A single
71 # host may match multiple declarations; these are processed in the order
72 # that they are given in.
74 Host *.ngs.fi ngs.fi
75 User foo
77 Host fake.com
78 HostName another.host.name.real.org
79 User blaah
80 Port 34289
81 ForwardX11 no
82 ForwardAgent no
84 Host books.com
85 RemoteForward 9999 shadows.cs.hut.fi:9999
86 Cipher 3des
88 Host fascist.blob.com
89 Port 23123
90 User tylonen
91 PasswordAuthentication no
93 Host puukko.hut.fi
94 User t35124p
95 ProxyCommand ssh-proxy %h %p
97 Host *.fr
98 PublicKeyAuthentication no
100 Host *.su
101 Cipher none
102 PasswordAuthentication no
104 Host vpn.fake.com
105 Tunnel yes
106 TunnelDevice 3
108 # Defaults for various options
109 Host *
110 ForwardAgent no
111 ForwardX11 no
112 PasswordAuthentication yes
113 RSAAuthentication yes
114 RhostsRSAAuthentication yes
115 StrictHostKeyChecking yes
116 TcpKeepAlive no
117 IdentityFile ~/.ssh/identity
118 Port 22
119 EscapeChar ~
123 /* Keyword tokens. */
125 typedef enum {
126 oBadOption,
127 oHost, oMatch,
128 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
129 oGatewayPorts, oExitOnForwardFailure,
130 oPasswordAuthentication, oRSAAuthentication,
131 oChallengeResponseAuthentication, oXAuthLocation,
132 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
133 oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
134 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
135 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
136 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
137 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
138 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
139 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
140 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
141 oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
142 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
143 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
144 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
145 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
146 oSendEnv, oControlPath, oControlMaster, oControlPersist,
147 oHashKnownHosts,
148 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
149 oVisualHostKey, oUseRoaming,
150 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
151 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
152 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
153 oStreamLocalBindMask, oStreamLocalBindUnlink,
154 oIgnoredUnknownOption, oDeprecated, oUnsupported
155 } OpCodes;
157 /* Textual representations of the tokens. */
159 static struct {
160 const char *name;
161 OpCodes opcode;
162 } keywords[] = {
163 { "forwardagent", oForwardAgent },
164 { "forwardx11", oForwardX11 },
165 { "forwardx11trusted", oForwardX11Trusted },
166 { "forwardx11timeout", oForwardX11Timeout },
167 { "exitonforwardfailure", oExitOnForwardFailure },
168 { "xauthlocation", oXAuthLocation },
169 { "gatewayports", oGatewayPorts },
170 { "useprivilegedport", oUsePrivilegedPort },
171 { "rhostsauthentication", oDeprecated },
172 { "passwordauthentication", oPasswordAuthentication },
173 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
174 { "kbdinteractivedevices", oKbdInteractiveDevices },
175 { "rsaauthentication", oRSAAuthentication },
176 { "pubkeyauthentication", oPubkeyAuthentication },
177 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
178 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
179 { "hostbasedauthentication", oHostbasedAuthentication },
180 { "challengeresponseauthentication", oChallengeResponseAuthentication },
181 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
182 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
183 { "kerberosauthentication", oUnsupported },
184 { "kerberostgtpassing", oUnsupported },
185 { "afstokenpassing", oUnsupported },
186 #if defined(GSSAPI)
187 { "gssapiauthentication", oGssAuthentication },
188 { "gssapidelegatecredentials", oGssDelegateCreds },
189 #else
190 { "gssapiauthentication", oUnsupported },
191 { "gssapidelegatecredentials", oUnsupported },
192 #endif
193 { "fallbacktorsh", oDeprecated },
194 { "usersh", oDeprecated },
195 { "identityfile", oIdentityFile },
196 { "identityfile2", oIdentityFile }, /* obsolete */
197 { "identitiesonly", oIdentitiesOnly },
198 { "hostname", oHostName },
199 { "hostkeyalias", oHostKeyAlias },
200 { "proxycommand", oProxyCommand },
201 { "port", oPort },
202 { "cipher", oCipher },
203 { "ciphers", oCiphers },
204 { "macs", oMacs },
205 { "protocol", oProtocol },
206 { "remoteforward", oRemoteForward },
207 { "localforward", oLocalForward },
208 { "user", oUser },
209 { "host", oHost },
210 { "match", oMatch },
211 { "escapechar", oEscapeChar },
212 { "globalknownhostsfile", oGlobalKnownHostsFile },
213 { "globalknownhostsfile2", oDeprecated },
214 { "userknownhostsfile", oUserKnownHostsFile },
215 { "userknownhostsfile2", oDeprecated },
216 { "connectionattempts", oConnectionAttempts },
217 { "batchmode", oBatchMode },
218 { "checkhostip", oCheckHostIP },
219 { "stricthostkeychecking", oStrictHostKeyChecking },
220 { "compression", oCompression },
221 { "compressionlevel", oCompressionLevel },
222 { "tcpkeepalive", oTCPKeepAlive },
223 { "keepalive", oTCPKeepAlive }, /* obsolete */
224 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
225 { "loglevel", oLogLevel },
226 { "dynamicforward", oDynamicForward },
227 { "preferredauthentications", oPreferredAuthentications },
228 { "hostkeyalgorithms", oHostKeyAlgorithms },
229 { "bindaddress", oBindAddress },
230 #ifdef ENABLE_PKCS11
231 { "smartcarddevice", oPKCS11Provider },
232 { "pkcs11provider", oPKCS11Provider },
233 #else
234 { "smartcarddevice", oUnsupported },
235 { "pkcs11provider", oUnsupported },
236 #endif
237 { "clearallforwardings", oClearAllForwardings },
238 { "enablesshkeysign", oEnableSSHKeysign },
239 { "verifyhostkeydns", oVerifyHostKeyDNS },
240 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
241 { "rekeylimit", oRekeyLimit },
242 { "connecttimeout", oConnectTimeout },
243 { "addressfamily", oAddressFamily },
244 { "serveraliveinterval", oServerAliveInterval },
245 { "serveralivecountmax", oServerAliveCountMax },
246 { "sendenv", oSendEnv },
247 { "controlpath", oControlPath },
248 { "controlmaster", oControlMaster },
249 { "controlpersist", oControlPersist },
250 { "hashknownhosts", oHashKnownHosts },
251 { "tunnel", oTunnel },
252 { "tunneldevice", oTunnelDevice },
253 { "localcommand", oLocalCommand },
254 { "permitlocalcommand", oPermitLocalCommand },
255 { "visualhostkey", oVisualHostKey },
256 { "useroaming", oUseRoaming },
257 { "kexalgorithms", oKexAlgorithms },
258 { "ipqos", oIPQoS },
259 { "requesttty", oRequestTTY },
260 { "proxyusefdpass", oProxyUseFdpass },
261 { "canonicaldomains", oCanonicalDomains },
262 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
263 { "canonicalizehostname", oCanonicalizeHostname },
264 { "canonicalizemaxdots", oCanonicalizeMaxDots },
265 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
266 { "streamlocalbindmask", oStreamLocalBindMask },
267 { "streamlocalbindunlink", oStreamLocalBindUnlink },
268 { "ignoreunknown", oIgnoreUnknown },
270 { NULL, oBadOption }
274 * Adds a local TCP/IP port forward to options. Never returns if there is an
275 * error.
278 void
279 add_local_forward(Options *options, const struct Forward *newfwd)
281 struct Forward *fwd;
282 #ifndef NO_IPPORT_RESERVED_CONCEPT
283 extern uid_t original_real_uid;
284 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
285 newfwd->listen_path == NULL)
286 fatal("Privileged ports can only be forwarded by root.");
287 #endif
288 options->local_forwards = xrealloc(options->local_forwards,
289 options->num_local_forwards + 1,
290 sizeof(*options->local_forwards));
291 fwd = &options->local_forwards[options->num_local_forwards++];
293 fwd->listen_host = newfwd->listen_host;
294 fwd->listen_port = newfwd->listen_port;
295 fwd->listen_path = newfwd->listen_path;
296 fwd->connect_host = newfwd->connect_host;
297 fwd->connect_port = newfwd->connect_port;
298 fwd->connect_path = newfwd->connect_path;
302 * Adds a remote TCP/IP port forward to options. Never returns if there is
303 * an error.
306 void
307 add_remote_forward(Options *options, const struct Forward *newfwd)
309 struct Forward *fwd;
311 options->remote_forwards = xrealloc(options->remote_forwards,
312 options->num_remote_forwards + 1,
313 sizeof(*options->remote_forwards));
314 fwd = &options->remote_forwards[options->num_remote_forwards++];
316 fwd->listen_host = newfwd->listen_host;
317 fwd->listen_port = newfwd->listen_port;
318 fwd->listen_path = newfwd->listen_path;
319 fwd->connect_host = newfwd->connect_host;
320 fwd->connect_port = newfwd->connect_port;
321 fwd->connect_path = newfwd->connect_path;
322 fwd->handle = newfwd->handle;
323 fwd->allocated_port = 0;
326 static void
327 clear_forwardings(Options *options)
329 int i;
331 for (i = 0; i < options->num_local_forwards; i++) {
332 free(options->local_forwards[i].listen_host);
333 free(options->local_forwards[i].listen_path);
334 free(options->local_forwards[i].connect_host);
335 free(options->local_forwards[i].connect_path);
337 if (options->num_local_forwards > 0) {
338 free(options->local_forwards);
339 options->local_forwards = NULL;
341 options->num_local_forwards = 0;
342 for (i = 0; i < options->num_remote_forwards; i++) {
343 free(options->remote_forwards[i].listen_host);
344 free(options->remote_forwards[i].listen_path);
345 free(options->remote_forwards[i].connect_host);
346 free(options->remote_forwards[i].connect_path);
348 if (options->num_remote_forwards > 0) {
349 free(options->remote_forwards);
350 options->remote_forwards = NULL;
352 options->num_remote_forwards = 0;
353 options->tun_open = SSH_TUNMODE_NO;
356 void
357 add_identity_file(Options *options, const char *dir, const char *filename,
358 int userprovided)
360 char *path;
361 int i;
363 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
364 fatal("Too many identity files specified (max %d)",
365 SSH_MAX_IDENTITY_FILES);
367 if (dir == NULL) /* no dir, filename is absolute */
368 path = xstrdup(filename);
369 else
370 (void)xasprintf(&path, "%.100s%.100s", dir, filename);
372 /* Avoid registering duplicates */
373 for (i = 0; i < options->num_identity_files; i++) {
374 if (options->identity_file_userprovided[i] == userprovided &&
375 strcmp(options->identity_files[i], path) == 0) {
376 debug2("%s: ignoring duplicate key %s", __func__, path);
377 free(path);
378 return;
382 options->identity_file_userprovided[options->num_identity_files] =
383 userprovided;
384 options->identity_files[options->num_identity_files++] = path;
388 default_ssh_port(void)
390 static int port;
391 struct servent *sp;
393 if (port == 0) {
394 sp = getservbyname(SSH_SERVICE_NAME, "tcp");
395 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
397 return port;
401 * Execute a command in a shell.
402 * Return its exit status or -1 on abnormal exit.
404 static int
405 execute_in_shell(const char *cmd)
407 char *shell, *command_string;
408 pid_t pid;
409 int devnull, status;
410 extern uid_t original_real_uid;
412 if ((shell = getenv("SHELL")) == NULL)
413 shell = _PATH_BSHELL;
416 * Use "exec" to avoid "sh -c" processes on some platforms
417 * (e.g. Solaris)
419 xasprintf(&command_string, "exec %s", cmd);
421 /* Need this to redirect subprocess stdin/out */
422 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
423 fatal("open(/dev/null): %s", strerror(errno));
425 debug("Executing command: '%.500s'", cmd);
427 /* Fork and execute the command. */
428 if ((pid = fork()) == 0) {
429 char *argv[4];
431 /* Child. Permanently give up superuser privileges. */
432 permanently_drop_suid(original_real_uid);
434 /* Redirect child stdin and stdout. Leave stderr */
435 if (dup2(devnull, STDIN_FILENO) == -1)
436 fatal("dup2: %s", strerror(errno));
437 if (dup2(devnull, STDOUT_FILENO) == -1)
438 fatal("dup2: %s", strerror(errno));
439 if (devnull > STDERR_FILENO)
440 close(devnull);
441 closefrom(STDERR_FILENO + 1);
443 argv[0] = shell;
444 argv[1] = "-c";
445 argv[2] = command_string;
446 argv[3] = NULL;
448 execv(argv[0], argv);
449 error("Unable to execute '%.100s': %s", cmd, strerror(errno));
450 /* Die with signal to make this error apparent to parent. */
451 signal(SIGTERM, SIG_DFL);
452 kill(getpid(), SIGTERM);
453 _exit(1);
455 /* Parent. */
456 if (pid < 0)
457 fatal("%s: fork: %.100s", __func__, strerror(errno));
459 close(devnull);
460 free(command_string);
462 while (waitpid(pid, &status, 0) == -1) {
463 if (errno != EINTR && errno != EAGAIN)
464 fatal("%s: waitpid: %s", __func__, strerror(errno));
466 if (!WIFEXITED(status)) {
467 error("command '%.100s' exited abnormally", cmd);
468 return -1;
470 debug3("command returned status %d", WEXITSTATUS(status));
471 return WEXITSTATUS(status);
475 * Parse and execute a Match directive.
477 static int
478 match_cfg_line(Options *options, char **condition, struct passwd *pw,
479 const char *host_arg, const char *filename, int linenum)
481 char *arg, *attrib, *cmd, *cp = *condition, *host;
482 const char *ruser;
483 int r, port, result = 1, attributes = 0;
484 size_t len;
485 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
488 * Configuration is likely to be incomplete at this point so we
489 * must be prepared to use default values.
491 port = options->port <= 0 ? default_ssh_port() : options->port;
492 ruser = options->user == NULL ? pw->pw_name : options->user;
493 if (options->hostname != NULL) {
494 /* NB. Please keep in sync with ssh.c:main() */
495 host = percent_expand(options->hostname,
496 "h", host_arg, (char *)NULL);
497 } else
498 host = xstrdup(host_arg);
500 debug3("checking match for '%s' host %s", cp, host);
501 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
502 attributes++;
503 if (strcasecmp(attrib, "all") == 0) {
504 if (attributes != 1 ||
505 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
506 error("'all' cannot be combined with other "
507 "Match attributes");
508 result = -1;
509 goto out;
511 *condition = cp;
512 result = 1;
513 goto out;
515 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
516 error("Missing Match criteria for %s", attrib);
517 result = -1;
518 goto out;
520 len = strlen(arg);
521 if (strcasecmp(attrib, "host") == 0) {
522 if (match_hostname(host, arg, len) != 1)
523 result = 0;
524 else
525 debug("%.200s line %d: matched 'Host %.100s' ",
526 filename, linenum, host);
527 } else if (strcasecmp(attrib, "originalhost") == 0) {
528 if (match_hostname(host_arg, arg, len) != 1)
529 result = 0;
530 else
531 debug("%.200s line %d: matched "
532 "'OriginalHost %.100s' ",
533 filename, linenum, host_arg);
534 } else if (strcasecmp(attrib, "user") == 0) {
535 if (match_pattern_list(ruser, arg, len, 0) != 1)
536 result = 0;
537 else
538 debug("%.200s line %d: matched 'User %.100s' ",
539 filename, linenum, ruser);
540 } else if (strcasecmp(attrib, "localuser") == 0) {
541 if (match_pattern_list(pw->pw_name, arg, len, 0) != 1)
542 result = 0;
543 else
544 debug("%.200s line %d: matched "
545 "'LocalUser %.100s' ",
546 filename, linenum, pw->pw_name);
547 } else if (strcasecmp(attrib, "exec") == 0) {
548 if (gethostname(thishost, sizeof(thishost)) == -1)
549 fatal("gethostname: %s", strerror(errno));
550 strlcpy(shorthost, thishost, sizeof(shorthost));
551 shorthost[strcspn(thishost, ".")] = '\0';
552 snprintf(portstr, sizeof(portstr), "%d", port);
554 cmd = percent_expand(arg,
555 "L", shorthost,
556 "d", pw->pw_dir,
557 "h", host,
558 "l", thishost,
559 "n", host_arg,
560 "p", portstr,
561 "r", ruser,
562 "u", pw->pw_name,
563 (char *)NULL);
564 if (result != 1) {
565 /* skip execution if prior predicate failed */
566 debug("%.200s line %d: skipped exec \"%.100s\"",
567 filename, linenum, cmd);
568 } else {
569 r = execute_in_shell(cmd);
570 if (r == -1) {
571 fatal("%.200s line %d: match exec "
572 "'%.100s' error", filename,
573 linenum, cmd);
574 } else if (r == 0) {
575 debug("%.200s line %d: matched "
576 "'exec \"%.100s\"'", filename,
577 linenum, cmd);
578 } else {
579 debug("%.200s line %d: no match "
580 "'exec \"%.100s\"'", filename,
581 linenum, cmd);
582 result = 0;
585 free(cmd);
586 } else {
587 error("Unsupported Match attribute %s", attrib);
588 result = -1;
589 goto out;
592 if (attributes == 0) {
593 error("One or more attributes required for Match");
594 result = -1;
595 goto out;
597 debug3("match %sfound", result ? "" : "not ");
598 *condition = cp;
599 out:
600 free(host);
601 return result;
604 /* Check and prepare a domain name: removes trailing '.' and lowercases */
605 static void
606 valid_domain(char *name, const char *filename, int linenum)
608 size_t i, l = strlen(name);
609 u_char c, last = '\0';
611 if (l == 0)
612 fatal("%s line %d: empty hostname suffix", filename, linenum);
613 if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
614 fatal("%s line %d: hostname suffix \"%.100s\" "
615 "starts with invalid character", filename, linenum, name);
616 for (i = 0; i < l; i++) {
617 c = tolower((u_char)name[i]);
618 name[i] = (char)c;
619 if (last == '.' && c == '.')
620 fatal("%s line %d: hostname suffix \"%.100s\" contains "
621 "consecutive separators", filename, linenum, name);
622 if (c != '.' && c != '-' && !isalnum(c) &&
623 c != '_') /* technically invalid, but common */
624 fatal("%s line %d: hostname suffix \"%.100s\" contains "
625 "invalid characters", filename, linenum, name);
626 last = c;
628 if (name[l - 1] == '.')
629 name[l - 1] = '\0';
633 * Returns the number of the token pointed to by cp or oBadOption.
635 static OpCodes
636 parse_token(const char *cp, const char *filename, int linenum,
637 const char *ignored_unknown)
639 int i;
641 for (i = 0; keywords[i].name; i++)
642 if (strcmp(cp, keywords[i].name) == 0)
643 return keywords[i].opcode;
644 if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown,
645 strlen(ignored_unknown), 1) == 1)
646 return oIgnoredUnknownOption;
647 error("%s: line %d: Bad configuration option: %s",
648 filename, linenum, cp);
649 return oBadOption;
652 /* Multistate option parsing */
653 struct multistate {
654 char *key;
655 int value;
657 static const struct multistate multistate_flag[] = {
658 { "true", 1 },
659 { "false", 0 },
660 { "yes", 1 },
661 { "no", 0 },
662 { NULL, -1 }
664 static const struct multistate multistate_yesnoask[] = {
665 { "true", 1 },
666 { "false", 0 },
667 { "yes", 1 },
668 { "no", 0 },
669 { "ask", 2 },
670 { NULL, -1 }
672 static const struct multistate multistate_addressfamily[] = {
673 { "inet", AF_INET },
674 { "inet6", AF_INET6 },
675 { "any", AF_UNSPEC },
676 { NULL, -1 }
678 static const struct multistate multistate_controlmaster[] = {
679 { "true", SSHCTL_MASTER_YES },
680 { "yes", SSHCTL_MASTER_YES },
681 { "false", SSHCTL_MASTER_NO },
682 { "no", SSHCTL_MASTER_NO },
683 { "auto", SSHCTL_MASTER_AUTO },
684 { "ask", SSHCTL_MASTER_ASK },
685 { "autoask", SSHCTL_MASTER_AUTO_ASK },
686 { NULL, -1 }
688 static const struct multistate multistate_tunnel[] = {
689 { "ethernet", SSH_TUNMODE_ETHERNET },
690 { "point-to-point", SSH_TUNMODE_POINTOPOINT },
691 { "true", SSH_TUNMODE_DEFAULT },
692 { "yes", SSH_TUNMODE_DEFAULT },
693 { "false", SSH_TUNMODE_NO },
694 { "no", SSH_TUNMODE_NO },
695 { NULL, -1 }
697 static const struct multistate multistate_requesttty[] = {
698 { "true", REQUEST_TTY_YES },
699 { "yes", REQUEST_TTY_YES },
700 { "false", REQUEST_TTY_NO },
701 { "no", REQUEST_TTY_NO },
702 { "force", REQUEST_TTY_FORCE },
703 { "auto", REQUEST_TTY_AUTO },
704 { NULL, -1 }
706 static const struct multistate multistate_canonicalizehostname[] = {
707 { "true", SSH_CANONICALISE_YES },
708 { "false", SSH_CANONICALISE_NO },
709 { "yes", SSH_CANONICALISE_YES },
710 { "no", SSH_CANONICALISE_NO },
711 { "always", SSH_CANONICALISE_ALWAYS },
712 { NULL, -1 }
716 * Processes a single option line as used in the configuration files. This
717 * only sets those values that have not already been set.
719 #define WHITESPACE " \t\r\n"
721 process_config_line(Options *options, struct passwd *pw, const char *host,
722 char *line, const char *filename, int linenum, int *activep, int userconfig)
724 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
725 char **cpptr, fwdarg[256];
726 u_int i, *uintptr, max_entries = 0;
727 int negated, opcode, *intptr, value, value2, cmdline = 0;
728 LogLevel *log_level_ptr;
729 long long val64;
730 size_t len;
731 struct Forward fwd;
732 const struct multistate *multistate_ptr;
733 struct allowed_cname *cname;
735 if (activep == NULL) { /* We are processing a command line directive */
736 cmdline = 1;
737 activep = &cmdline;
740 /* Strip trailing whitespace */
741 for (len = strlen(line) - 1; len > 0; len--) {
742 if (strchr(WHITESPACE, line[len]) == NULL)
743 break;
744 line[len] = '\0';
747 s = line;
748 /* Get the keyword. (Each line is supposed to begin with a keyword). */
749 if ((keyword = strdelim(&s)) == NULL)
750 return 0;
751 /* Ignore leading whitespace. */
752 if (*keyword == '\0')
753 keyword = strdelim(&s);
754 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
755 return 0;
756 /* Match lowercase keyword */
757 lowercase(keyword);
759 opcode = parse_token(keyword, filename, linenum,
760 options->ignored_unknown);
762 switch (opcode) {
763 case oBadOption:
764 /* don't panic, but count bad options */
765 return -1;
766 /* NOTREACHED */
767 case oIgnoredUnknownOption:
768 debug("%s line %d: Ignored unknown option \"%s\"",
769 filename, linenum, keyword);
770 return 0;
771 case oConnectTimeout:
772 intptr = &options->connection_timeout;
773 parse_time:
774 arg = strdelim(&s);
775 if (!arg || *arg == '\0')
776 fatal("%s line %d: missing time value.",
777 filename, linenum);
778 if ((value = convtime(arg)) == -1)
779 fatal("%s line %d: invalid time value.",
780 filename, linenum);
781 if (*activep && *intptr == -1)
782 *intptr = value;
783 break;
785 case oForwardAgent:
786 intptr = &options->forward_agent;
787 parse_flag:
788 multistate_ptr = multistate_flag;
789 parse_multistate:
790 arg = strdelim(&s);
791 if (!arg || *arg == '\0')
792 fatal("%s line %d: missing argument.",
793 filename, linenum);
794 value = -1;
795 for (i = 0; multistate_ptr[i].key != NULL; i++) {
796 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
797 value = multistate_ptr[i].value;
798 break;
801 if (value == -1)
802 fatal("%s line %d: unsupported option \"%s\".",
803 filename, linenum, arg);
804 if (*activep && *intptr == -1)
805 *intptr = value;
806 break;
808 case oForwardX11:
809 intptr = &options->forward_x11;
810 goto parse_flag;
812 case oForwardX11Trusted:
813 intptr = &options->forward_x11_trusted;
814 goto parse_flag;
816 case oForwardX11Timeout:
817 intptr = &options->forward_x11_timeout;
818 goto parse_time;
820 case oGatewayPorts:
821 intptr = &options->fwd_opts.gateway_ports;
822 goto parse_flag;
824 case oExitOnForwardFailure:
825 intptr = &options->exit_on_forward_failure;
826 goto parse_flag;
828 case oUsePrivilegedPort:
829 intptr = &options->use_privileged_port;
830 goto parse_flag;
832 case oPasswordAuthentication:
833 intptr = &options->password_authentication;
834 goto parse_flag;
836 case oKbdInteractiveAuthentication:
837 intptr = &options->kbd_interactive_authentication;
838 goto parse_flag;
840 case oKbdInteractiveDevices:
841 charptr = &options->kbd_interactive_devices;
842 goto parse_string;
844 case oPubkeyAuthentication:
845 intptr = &options->pubkey_authentication;
846 goto parse_flag;
848 case oRSAAuthentication:
849 intptr = &options->rsa_authentication;
850 goto parse_flag;
852 case oRhostsRSAAuthentication:
853 intptr = &options->rhosts_rsa_authentication;
854 goto parse_flag;
856 case oHostbasedAuthentication:
857 intptr = &options->hostbased_authentication;
858 goto parse_flag;
860 case oChallengeResponseAuthentication:
861 intptr = &options->challenge_response_authentication;
862 goto parse_flag;
864 case oGssAuthentication:
865 intptr = &options->gss_authentication;
866 goto parse_flag;
868 case oGssDelegateCreds:
869 intptr = &options->gss_deleg_creds;
870 goto parse_flag;
872 case oBatchMode:
873 intptr = &options->batch_mode;
874 goto parse_flag;
876 case oCheckHostIP:
877 intptr = &options->check_host_ip;
878 goto parse_flag;
880 case oVerifyHostKeyDNS:
881 intptr = &options->verify_host_key_dns;
882 multistate_ptr = multistate_yesnoask;
883 goto parse_multistate;
885 case oStrictHostKeyChecking:
886 intptr = &options->strict_host_key_checking;
887 multistate_ptr = multistate_yesnoask;
888 goto parse_multistate;
890 case oCompression:
891 intptr = &options->compression;
892 goto parse_flag;
894 case oTCPKeepAlive:
895 intptr = &options->tcp_keep_alive;
896 goto parse_flag;
898 case oNoHostAuthenticationForLocalhost:
899 intptr = &options->no_host_authentication_for_localhost;
900 goto parse_flag;
902 case oNumberOfPasswordPrompts:
903 intptr = &options->number_of_password_prompts;
904 goto parse_int;
906 case oCompressionLevel:
907 intptr = &options->compression_level;
908 goto parse_int;
910 case oRekeyLimit:
911 arg = strdelim(&s);
912 if (!arg || *arg == '\0')
913 fatal("%.200s line %d: Missing argument.", filename,
914 linenum);
915 if (strcmp(arg, "default") == 0) {
916 val64 = 0;
917 } else {
918 if (scan_scaled(arg, &val64) == -1)
919 fatal("%.200s line %d: Bad number '%s': %s",
920 filename, linenum, arg, strerror(errno));
921 /* check for too-large or too-small limits */
922 if (val64 > UINT_MAX)
923 fatal("%.200s line %d: RekeyLimit too large",
924 filename, linenum);
925 if (val64 != 0 && val64 < 16)
926 fatal("%.200s line %d: RekeyLimit too small",
927 filename, linenum);
929 if (*activep && options->rekey_limit == -1)
930 options->rekey_limit = (u_int32_t)val64;
931 if (s != NULL) { /* optional rekey interval present */
932 if (strcmp(s, "none") == 0) {
933 (void)strdelim(&s); /* discard */
934 break;
936 intptr = &options->rekey_interval;
937 goto parse_time;
939 break;
941 case oIdentityFile:
942 arg = strdelim(&s);
943 if (!arg || *arg == '\0')
944 fatal("%.200s line %d: Missing argument.", filename, linenum);
945 if (*activep) {
946 intptr = &options->num_identity_files;
947 if (*intptr >= SSH_MAX_IDENTITY_FILES)
948 fatal("%.200s line %d: Too many identity files specified (max %d).",
949 filename, linenum, SSH_MAX_IDENTITY_FILES);
950 add_identity_file(options, NULL, arg, userconfig);
952 break;
954 case oXAuthLocation:
955 charptr=&options->xauth_location;
956 goto parse_string;
958 case oUser:
959 charptr = &options->user;
960 parse_string:
961 arg = strdelim(&s);
962 if (!arg || *arg == '\0')
963 fatal("%.200s line %d: Missing argument.",
964 filename, linenum);
965 if (*activep && *charptr == NULL)
966 *charptr = xstrdup(arg);
967 break;
969 case oGlobalKnownHostsFile:
970 cpptr = (char **)&options->system_hostfiles;
971 uintptr = &options->num_system_hostfiles;
972 max_entries = SSH_MAX_HOSTS_FILES;
973 parse_char_array:
974 if (*activep && *uintptr == 0) {
975 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
976 if ((*uintptr) >= max_entries)
977 fatal("%s line %d: "
978 "too many authorized keys files.",
979 filename, linenum);
980 cpptr[(*uintptr)++] = xstrdup(arg);
983 return 0;
985 case oUserKnownHostsFile:
986 cpptr = (char **)&options->user_hostfiles;
987 uintptr = &options->num_user_hostfiles;
988 max_entries = SSH_MAX_HOSTS_FILES;
989 goto parse_char_array;
991 case oHostName:
992 charptr = &options->hostname;
993 goto parse_string;
995 case oHostKeyAlias:
996 charptr = &options->host_key_alias;
997 goto parse_string;
999 case oPreferredAuthentications:
1000 charptr = &options->preferred_authentications;
1001 goto parse_string;
1003 case oBindAddress:
1004 charptr = &options->bind_address;
1005 goto parse_string;
1007 case oPKCS11Provider:
1008 charptr = &options->pkcs11_provider;
1009 goto parse_string;
1011 case oProxyCommand:
1012 charptr = &options->proxy_command;
1013 parse_command:
1014 if (s == NULL)
1015 fatal("%.200s line %d: Missing argument.", filename, linenum);
1016 len = strspn(s, WHITESPACE "=");
1017 if (*activep && *charptr == NULL)
1018 *charptr = xstrdup(s + len);
1019 return 0;
1021 case oPort:
1022 intptr = &options->port;
1023 parse_int:
1024 arg = strdelim(&s);
1025 if (!arg || *arg == '\0')
1026 fatal("%.200s line %d: Missing argument.", filename, linenum);
1027 if (arg[0] < '0' || arg[0] > '9')
1028 fatal("%.200s line %d: Bad number.", filename, linenum);
1030 /* Octal, decimal, or hex format? */
1031 value = strtol(arg, &endofnumber, 0);
1032 if (arg == endofnumber)
1033 fatal("%.200s line %d: Bad number.", filename, linenum);
1034 if (*activep && *intptr == -1)
1035 *intptr = value;
1036 break;
1038 case oConnectionAttempts:
1039 intptr = &options->connection_attempts;
1040 goto parse_int;
1042 case oCipher:
1043 intptr = &options->cipher;
1044 arg = strdelim(&s);
1045 if (!arg || *arg == '\0')
1046 fatal("%.200s line %d: Missing argument.", filename, linenum);
1047 value = cipher_number(arg);
1048 if (value == -1)
1049 fatal("%.200s line %d: Bad cipher '%s'.",
1050 filename, linenum, arg ? arg : "<NONE>");
1051 if (*activep && *intptr == -1)
1052 *intptr = value;
1053 break;
1055 case oCiphers:
1056 arg = strdelim(&s);
1057 if (!arg || *arg == '\0')
1058 fatal("%.200s line %d: Missing argument.", filename, linenum);
1059 if (!ciphers_valid(arg))
1060 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1061 filename, linenum, arg ? arg : "<NONE>");
1062 if (*activep && options->ciphers == NULL)
1063 options->ciphers = xstrdup(arg);
1064 break;
1066 case oMacs:
1067 arg = strdelim(&s);
1068 if (!arg || *arg == '\0')
1069 fatal("%.200s line %d: Missing argument.", filename, linenum);
1070 if (!mac_valid(arg))
1071 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1072 filename, linenum, arg ? arg : "<NONE>");
1073 if (*activep && options->macs == NULL)
1074 options->macs = xstrdup(arg);
1075 break;
1077 case oKexAlgorithms:
1078 arg = strdelim(&s);
1079 if (!arg || *arg == '\0')
1080 fatal("%.200s line %d: Missing argument.",
1081 filename, linenum);
1082 if (!kex_names_valid(arg))
1083 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1084 filename, linenum, arg ? arg : "<NONE>");
1085 if (*activep && options->kex_algorithms == NULL)
1086 options->kex_algorithms = xstrdup(arg);
1087 break;
1089 case oHostKeyAlgorithms:
1090 arg = strdelim(&s);
1091 if (!arg || *arg == '\0')
1092 fatal("%.200s line %d: Missing argument.", filename, linenum);
1093 if (!key_names_valid2(arg))
1094 fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
1095 filename, linenum, arg ? arg : "<NONE>");
1096 if (*activep && options->hostkeyalgorithms == NULL)
1097 options->hostkeyalgorithms = xstrdup(arg);
1098 break;
1100 case oProtocol:
1101 intptr = &options->protocol;
1102 arg = strdelim(&s);
1103 if (!arg || *arg == '\0')
1104 fatal("%.200s line %d: Missing argument.", filename, linenum);
1105 value = proto_spec(arg);
1106 if (value == SSH_PROTO_UNKNOWN)
1107 fatal("%.200s line %d: Bad protocol spec '%s'.",
1108 filename, linenum, arg ? arg : "<NONE>");
1109 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
1110 *intptr = value;
1111 break;
1113 case oLogLevel:
1114 log_level_ptr = &options->log_level;
1115 arg = strdelim(&s);
1116 value = log_level_number(arg);
1117 if (value == SYSLOG_LEVEL_NOT_SET)
1118 fatal("%.200s line %d: unsupported log level '%s'",
1119 filename, linenum, arg ? arg : "<NONE>");
1120 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1121 *log_level_ptr = (LogLevel) value;
1122 break;
1124 case oLocalForward:
1125 case oRemoteForward:
1126 case oDynamicForward:
1127 arg = strdelim(&s);
1128 if (arg == NULL || *arg == '\0')
1129 fatal("%.200s line %d: Missing port argument.",
1130 filename, linenum);
1132 if (opcode == oLocalForward ||
1133 opcode == oRemoteForward) {
1134 arg2 = strdelim(&s);
1135 if (arg2 == NULL || *arg2 == '\0')
1136 fatal("%.200s line %d: Missing target argument.",
1137 filename, linenum);
1139 /* construct a string for parse_forward */
1140 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
1141 } else if (opcode == oDynamicForward) {
1142 strlcpy(fwdarg, arg, sizeof(fwdarg));
1145 if (parse_forward(&fwd, fwdarg,
1146 opcode == oDynamicForward ? 1 : 0,
1147 opcode == oRemoteForward ? 1 : 0) == 0)
1148 fatal("%.200s line %d: Bad forwarding specification.",
1149 filename, linenum);
1151 if (*activep) {
1152 if (opcode == oLocalForward ||
1153 opcode == oDynamicForward)
1154 add_local_forward(options, &fwd);
1155 else if (opcode == oRemoteForward)
1156 add_remote_forward(options, &fwd);
1158 break;
1160 case oClearAllForwardings:
1161 intptr = &options->clear_forwardings;
1162 goto parse_flag;
1164 case oHost:
1165 if (cmdline)
1166 fatal("Host directive not supported as a command-line "
1167 "option");
1168 *activep = 0;
1169 arg2 = NULL;
1170 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1171 negated = *arg == '!';
1172 if (negated)
1173 arg++;
1174 if (match_pattern(host, arg)) {
1175 if (negated) {
1176 debug("%.200s line %d: Skipping Host "
1177 "block because of negated match "
1178 "for %.100s", filename, linenum,
1179 arg);
1180 *activep = 0;
1181 break;
1183 if (!*activep)
1184 arg2 = arg; /* logged below */
1185 *activep = 1;
1188 if (*activep)
1189 debug("%.200s line %d: Applying options for %.100s",
1190 filename, linenum, arg2);
1191 /* Avoid garbage check below, as strdelim is done. */
1192 return 0;
1194 case oMatch:
1195 if (cmdline)
1196 fatal("Host directive not supported as a command-line "
1197 "option");
1198 value = match_cfg_line(options, &s, pw, host,
1199 filename, linenum);
1200 if (value < 0)
1201 fatal("%.200s line %d: Bad Match condition", filename,
1202 linenum);
1203 *activep = value;
1204 break;
1206 case oEscapeChar:
1207 intptr = &options->escape_char;
1208 arg = strdelim(&s);
1209 if (!arg || *arg == '\0')
1210 fatal("%.200s line %d: Missing argument.", filename, linenum);
1211 if (arg[0] == '^' && arg[2] == 0 &&
1212 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1213 value = (u_char) arg[1] & 31;
1214 else if (strlen(arg) == 1)
1215 value = (u_char) arg[0];
1216 else if (strcmp(arg, "none") == 0)
1217 value = SSH_ESCAPECHAR_NONE;
1218 else {
1219 fatal("%.200s line %d: Bad escape character.",
1220 filename, linenum);
1221 /* NOTREACHED */
1222 value = 0; /* Avoid compiler warning. */
1224 if (*activep && *intptr == -1)
1225 *intptr = value;
1226 break;
1228 case oAddressFamily:
1229 intptr = &options->address_family;
1230 multistate_ptr = multistate_addressfamily;
1231 goto parse_multistate;
1233 case oEnableSSHKeysign:
1234 intptr = &options->enable_ssh_keysign;
1235 goto parse_flag;
1237 case oIdentitiesOnly:
1238 intptr = &options->identities_only;
1239 goto parse_flag;
1241 case oServerAliveInterval:
1242 intptr = &options->server_alive_interval;
1243 goto parse_time;
1245 case oServerAliveCountMax:
1246 intptr = &options->server_alive_count_max;
1247 goto parse_int;
1249 case oSendEnv:
1250 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1251 if (strchr(arg, '=') != NULL)
1252 fatal("%s line %d: Invalid environment name.",
1253 filename, linenum);
1254 if (!*activep)
1255 continue;
1256 if (options->num_send_env >= MAX_SEND_ENV)
1257 fatal("%s line %d: too many send env.",
1258 filename, linenum);
1259 options->send_env[options->num_send_env++] =
1260 xstrdup(arg);
1262 break;
1264 case oControlPath:
1265 charptr = &options->control_path;
1266 goto parse_string;
1268 case oControlMaster:
1269 intptr = &options->control_master;
1270 multistate_ptr = multistate_controlmaster;
1271 goto parse_multistate;
1273 case oControlPersist:
1274 /* no/false/yes/true, or a time spec */
1275 intptr = &options->control_persist;
1276 arg = strdelim(&s);
1277 if (!arg || *arg == '\0')
1278 fatal("%.200s line %d: Missing ControlPersist"
1279 " argument.", filename, linenum);
1280 value = 0;
1281 value2 = 0; /* timeout */
1282 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1283 value = 0;
1284 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1285 value = 1;
1286 else if ((value2 = convtime(arg)) >= 0)
1287 value = 1;
1288 else
1289 fatal("%.200s line %d: Bad ControlPersist argument.",
1290 filename, linenum);
1291 if (*activep && *intptr == -1) {
1292 *intptr = value;
1293 options->control_persist_timeout = value2;
1295 break;
1297 case oHashKnownHosts:
1298 intptr = &options->hash_known_hosts;
1299 goto parse_flag;
1301 case oTunnel:
1302 intptr = &options->tun_open;
1303 multistate_ptr = multistate_tunnel;
1304 goto parse_multistate;
1306 case oTunnelDevice:
1307 arg = strdelim(&s);
1308 if (!arg || *arg == '\0')
1309 fatal("%.200s line %d: Missing argument.", filename, linenum);
1310 value = a2tun(arg, &value2);
1311 if (value == SSH_TUNID_ERR)
1312 fatal("%.200s line %d: Bad tun device.", filename, linenum);
1313 if (*activep) {
1314 options->tun_local = value;
1315 options->tun_remote = value2;
1317 break;
1319 case oLocalCommand:
1320 charptr = &options->local_command;
1321 goto parse_command;
1323 case oPermitLocalCommand:
1324 intptr = &options->permit_local_command;
1325 goto parse_flag;
1327 case oVisualHostKey:
1328 intptr = &options->visual_host_key;
1329 goto parse_flag;
1331 case oIPQoS:
1332 arg = strdelim(&s);
1333 if ((value = parse_ipqos(arg)) == -1)
1334 fatal("%s line %d: Bad IPQoS value: %s",
1335 filename, linenum, arg);
1336 arg = strdelim(&s);
1337 if (arg == NULL)
1338 value2 = value;
1339 else if ((value2 = parse_ipqos(arg)) == -1)
1340 fatal("%s line %d: Bad IPQoS value: %s",
1341 filename, linenum, arg);
1342 if (*activep) {
1343 options->ip_qos_interactive = value;
1344 options->ip_qos_bulk = value2;
1346 break;
1348 case oUseRoaming:
1349 intptr = &options->use_roaming;
1350 goto parse_flag;
1352 case oRequestTTY:
1353 intptr = &options->request_tty;
1354 multistate_ptr = multistate_requesttty;
1355 goto parse_multistate;
1357 case oIgnoreUnknown:
1358 charptr = &options->ignored_unknown;
1359 goto parse_string;
1361 case oProxyUseFdpass:
1362 intptr = &options->proxy_use_fdpass;
1363 goto parse_flag;
1365 case oCanonicalDomains:
1366 value = options->num_canonical_domains != 0;
1367 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1368 valid_domain(arg, filename, linenum);
1369 if (!*activep || value)
1370 continue;
1371 if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1372 fatal("%s line %d: too many hostname suffixes.",
1373 filename, linenum);
1374 options->canonical_domains[
1375 options->num_canonical_domains++] = xstrdup(arg);
1377 break;
1379 case oCanonicalizePermittedCNAMEs:
1380 value = options->num_permitted_cnames != 0;
1381 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1382 /* Either '*' for everything or 'list:list' */
1383 if (strcmp(arg, "*") == 0)
1384 arg2 = arg;
1385 else {
1386 lowercase(arg);
1387 if ((arg2 = strchr(arg, ':')) == NULL ||
1388 arg2[1] == '\0') {
1389 fatal("%s line %d: "
1390 "Invalid permitted CNAME \"%s\"",
1391 filename, linenum, arg);
1393 *arg2 = '\0';
1394 arg2++;
1396 if (!*activep || value)
1397 continue;
1398 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1399 fatal("%s line %d: too many permitted CNAMEs.",
1400 filename, linenum);
1401 cname = options->permitted_cnames +
1402 options->num_permitted_cnames++;
1403 cname->source_list = xstrdup(arg);
1404 cname->target_list = xstrdup(arg2);
1406 break;
1408 case oCanonicalizeHostname:
1409 intptr = &options->canonicalize_hostname;
1410 multistate_ptr = multistate_canonicalizehostname;
1411 goto parse_multistate;
1413 case oCanonicalizeMaxDots:
1414 intptr = &options->canonicalize_max_dots;
1415 goto parse_int;
1417 case oCanonicalizeFallbackLocal:
1418 intptr = &options->canonicalize_fallback_local;
1419 goto parse_flag;
1421 case oStreamLocalBindMask:
1422 arg = strdelim(&s);
1423 if (!arg || *arg == '\0')
1424 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1425 /* Parse mode in octal format */
1426 value = strtol(arg, &endofnumber, 8);
1427 if (arg == endofnumber || value < 0 || value > 0777)
1428 fatal("%.200s line %d: Bad mask.", filename, linenum);
1429 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1430 break;
1432 case oStreamLocalBindUnlink:
1433 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1434 goto parse_flag;
1436 case oDeprecated:
1437 debug("%s line %d: Deprecated option \"%s\"",
1438 filename, linenum, keyword);
1439 return 0;
1441 case oUnsupported:
1442 error("%s line %d: Unsupported option \"%s\"",
1443 filename, linenum, keyword);
1444 return 0;
1446 default:
1447 fatal("process_config_line: Unimplemented opcode %d", opcode);
1450 /* Check that there is no garbage at end of line. */
1451 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1452 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1453 filename, linenum, arg);
1455 return 0;
1460 * Reads the config file and modifies the options accordingly. Options
1461 * should already be initialized before this call. This never returns if
1462 * there is an error. If the file does not exist, this returns 0.
1466 read_config_file(const char *filename, struct passwd *pw, const char *host,
1467 Options *options, int flags)
1469 FILE *f;
1470 char line[1024];
1471 int active, linenum;
1472 int bad_options = 0;
1474 if ((f = fopen(filename, "r")) == NULL)
1475 return 0;
1477 if (flags & SSHCONF_CHECKPERM) {
1478 struct stat sb;
1480 if (fstat(fileno(f), &sb) == -1)
1481 fatal("fstat %s: %s", filename, strerror(errno));
1482 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1483 (sb.st_mode & 022) != 0))
1484 fatal("Bad owner or permissions on %s", filename);
1487 debug("Reading configuration data %.200s", filename);
1490 * Mark that we are now processing the options. This flag is turned
1491 * on/off by Host specifications.
1493 active = 1;
1494 linenum = 0;
1495 while (fgets(line, sizeof(line), f)) {
1496 /* Update line number counter. */
1497 linenum++;
1498 if (process_config_line(options, pw, host, line, filename,
1499 linenum, &active, flags & SSHCONF_USERCONF) != 0)
1500 bad_options++;
1502 fclose(f);
1503 if (bad_options > 0)
1504 fatal("%s: terminating, %d bad configuration options",
1505 filename, bad_options);
1506 return 1;
1509 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
1511 option_clear_or_none(const char *o)
1513 return o == NULL || strcasecmp(o, "none") == 0;
1517 * Initializes options to special values that indicate that they have not yet
1518 * been set. Read_config_file will only set options with this value. Options
1519 * are processed in the following order: command line, user config file,
1520 * system config file. Last, fill_default_options is called.
1523 void
1524 initialize_options(Options * options)
1526 memset(options, 'X', sizeof(*options));
1527 options->forward_agent = -1;
1528 options->forward_x11 = -1;
1529 options->forward_x11_trusted = -1;
1530 options->forward_x11_timeout = -1;
1531 options->exit_on_forward_failure = -1;
1532 options->xauth_location = NULL;
1533 options->fwd_opts.gateway_ports = -1;
1534 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1535 options->fwd_opts.streamlocal_bind_unlink = -1;
1536 options->use_privileged_port = -1;
1537 options->rsa_authentication = -1;
1538 options->pubkey_authentication = -1;
1539 options->challenge_response_authentication = -1;
1540 options->gss_authentication = -1;
1541 options->gss_deleg_creds = -1;
1542 options->password_authentication = -1;
1543 options->kbd_interactive_authentication = -1;
1544 options->kbd_interactive_devices = NULL;
1545 options->rhosts_rsa_authentication = -1;
1546 options->hostbased_authentication = -1;
1547 options->batch_mode = -1;
1548 options->check_host_ip = -1;
1549 options->strict_host_key_checking = -1;
1550 options->compression = -1;
1551 options->tcp_keep_alive = -1;
1552 options->compression_level = -1;
1553 options->port = -1;
1554 options->address_family = -1;
1555 options->connection_attempts = -1;
1556 options->connection_timeout = -1;
1557 options->number_of_password_prompts = -1;
1558 options->cipher = -1;
1559 options->ciphers = NULL;
1560 options->macs = NULL;
1561 options->kex_algorithms = NULL;
1562 options->hostkeyalgorithms = NULL;
1563 options->protocol = SSH_PROTO_UNKNOWN;
1564 options->num_identity_files = 0;
1565 options->hostname = NULL;
1566 options->host_key_alias = NULL;
1567 options->proxy_command = NULL;
1568 options->user = NULL;
1569 options->escape_char = -1;
1570 options->num_system_hostfiles = 0;
1571 options->num_user_hostfiles = 0;
1572 options->local_forwards = NULL;
1573 options->num_local_forwards = 0;
1574 options->remote_forwards = NULL;
1575 options->num_remote_forwards = 0;
1576 options->clear_forwardings = -1;
1577 options->log_level = SYSLOG_LEVEL_NOT_SET;
1578 options->preferred_authentications = NULL;
1579 options->bind_address = NULL;
1580 options->pkcs11_provider = NULL;
1581 options->enable_ssh_keysign = - 1;
1582 options->no_host_authentication_for_localhost = - 1;
1583 options->identities_only = - 1;
1584 options->rekey_limit = - 1;
1585 options->rekey_interval = -1;
1586 options->verify_host_key_dns = -1;
1587 options->server_alive_interval = -1;
1588 options->server_alive_count_max = -1;
1589 options->num_send_env = 0;
1590 options->control_path = NULL;
1591 options->control_master = -1;
1592 options->control_persist = -1;
1593 options->control_persist_timeout = 0;
1594 options->hash_known_hosts = -1;
1595 options->tun_open = -1;
1596 options->tun_local = -1;
1597 options->tun_remote = -1;
1598 options->local_command = NULL;
1599 options->permit_local_command = -1;
1600 options->use_roaming = -1;
1601 options->visual_host_key = -1;
1602 options->ip_qos_interactive = -1;
1603 options->ip_qos_bulk = -1;
1604 options->request_tty = -1;
1605 options->proxy_use_fdpass = -1;
1606 options->ignored_unknown = NULL;
1607 options->num_canonical_domains = 0;
1608 options->num_permitted_cnames = 0;
1609 options->canonicalize_max_dots = -1;
1610 options->canonicalize_fallback_local = -1;
1611 options->canonicalize_hostname = -1;
1615 * A petite version of fill_default_options() that just fills the options
1616 * needed for hostname canonicalization to proceed.
1618 void
1619 fill_default_options_for_canonicalization(Options *options)
1621 if (options->canonicalize_max_dots == -1)
1622 options->canonicalize_max_dots = 1;
1623 if (options->canonicalize_fallback_local == -1)
1624 options->canonicalize_fallback_local = 1;
1625 if (options->canonicalize_hostname == -1)
1626 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1630 * Called after processing other sources of option data, this fills those
1631 * options for which no value has been specified with their default values.
1633 void
1634 fill_default_options(Options * options)
1636 if (options->forward_agent == -1)
1637 options->forward_agent = 0;
1638 if (options->forward_x11 == -1)
1639 options->forward_x11 = 0;
1640 if (options->forward_x11_trusted == -1)
1641 options->forward_x11_trusted = 0;
1642 if (options->forward_x11_timeout == -1)
1643 options->forward_x11_timeout = 1200;
1644 if (options->exit_on_forward_failure == -1)
1645 options->exit_on_forward_failure = 0;
1646 if (options->xauth_location == NULL)
1647 options->xauth_location = _PATH_XAUTH;
1648 if (options->fwd_opts.gateway_ports == -1)
1649 options->fwd_opts.gateway_ports = 0;
1650 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1651 options->fwd_opts.streamlocal_bind_mask = 0177;
1652 if (options->fwd_opts.streamlocal_bind_unlink == -1)
1653 options->fwd_opts.streamlocal_bind_unlink = 0;
1654 if (options->use_privileged_port == -1)
1655 options->use_privileged_port = 0;
1656 if (options->rsa_authentication == -1)
1657 options->rsa_authentication = 1;
1658 if (options->pubkey_authentication == -1)
1659 options->pubkey_authentication = 1;
1660 if (options->challenge_response_authentication == -1)
1661 options->challenge_response_authentication = 1;
1662 if (options->gss_authentication == -1)
1663 options->gss_authentication = 0;
1664 if (options->gss_deleg_creds == -1)
1665 options->gss_deleg_creds = 0;
1666 if (options->password_authentication == -1)
1667 options->password_authentication = 1;
1668 if (options->kbd_interactive_authentication == -1)
1669 options->kbd_interactive_authentication = 1;
1670 if (options->rhosts_rsa_authentication == -1)
1671 options->rhosts_rsa_authentication = 0;
1672 if (options->hostbased_authentication == -1)
1673 options->hostbased_authentication = 0;
1674 if (options->batch_mode == -1)
1675 options->batch_mode = 0;
1676 if (options->check_host_ip == -1)
1677 options->check_host_ip = 1;
1678 if (options->strict_host_key_checking == -1)
1679 options->strict_host_key_checking = 2; /* 2 is default */
1680 if (options->compression == -1)
1681 options->compression = 0;
1682 if (options->tcp_keep_alive == -1)
1683 options->tcp_keep_alive = 1;
1684 if (options->compression_level == -1)
1685 options->compression_level = 6;
1686 if (options->port == -1)
1687 options->port = 0; /* Filled in ssh_connect. */
1688 if (options->address_family == -1)
1689 options->address_family = AF_UNSPEC;
1690 if (options->connection_attempts == -1)
1691 options->connection_attempts = 1;
1692 if (options->number_of_password_prompts == -1)
1693 options->number_of_password_prompts = 3;
1694 /* Selected in ssh_login(). */
1695 if (options->cipher == -1)
1696 options->cipher = SSH_CIPHER_NOT_SET;
1697 /* options->ciphers, default set in myproposals.h */
1698 /* options->macs, default set in myproposals.h */
1699 /* options->kex_algorithms, default set in myproposals.h */
1700 /* options->hostkeyalgorithms, default set in myproposals.h */
1701 if (options->protocol == SSH_PROTO_UNKNOWN)
1702 options->protocol = SSH_PROTO_2;
1703 if (options->num_identity_files == 0) {
1704 if (options->protocol & SSH_PROTO_1) {
1705 add_identity_file(options, "~/",
1706 _PATH_SSH_CLIENT_IDENTITY, 0);
1708 if (options->protocol & SSH_PROTO_2) {
1709 add_identity_file(options, "~/",
1710 _PATH_SSH_CLIENT_ID_RSA, 0);
1711 add_identity_file(options, "~/",
1712 _PATH_SSH_CLIENT_ID_DSA, 0);
1713 #ifdef OPENSSL_HAS_ECC
1714 add_identity_file(options, "~/",
1715 _PATH_SSH_CLIENT_ID_ECDSA, 0);
1716 #endif
1717 add_identity_file(options, "~/",
1718 _PATH_SSH_CLIENT_ID_ED25519, 0);
1721 if (options->escape_char == -1)
1722 options->escape_char = '~';
1723 if (options->num_system_hostfiles == 0) {
1724 options->system_hostfiles[options->num_system_hostfiles++] =
1725 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1726 options->system_hostfiles[options->num_system_hostfiles++] =
1727 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1729 if (options->num_user_hostfiles == 0) {
1730 options->user_hostfiles[options->num_user_hostfiles++] =
1731 xstrdup(_PATH_SSH_USER_HOSTFILE);
1732 options->user_hostfiles[options->num_user_hostfiles++] =
1733 xstrdup(_PATH_SSH_USER_HOSTFILE2);
1735 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1736 options->log_level = SYSLOG_LEVEL_INFO;
1737 if (options->clear_forwardings == 1)
1738 clear_forwardings(options);
1739 if (options->no_host_authentication_for_localhost == - 1)
1740 options->no_host_authentication_for_localhost = 0;
1741 if (options->identities_only == -1)
1742 options->identities_only = 0;
1743 if (options->enable_ssh_keysign == -1)
1744 options->enable_ssh_keysign = 0;
1745 if (options->rekey_limit == -1)
1746 options->rekey_limit = 0;
1747 if (options->rekey_interval == -1)
1748 options->rekey_interval = 0;
1749 if (options->verify_host_key_dns == -1)
1750 options->verify_host_key_dns = 0;
1751 if (options->server_alive_interval == -1)
1752 options->server_alive_interval = 0;
1753 if (options->server_alive_count_max == -1)
1754 options->server_alive_count_max = 3;
1755 if (options->control_master == -1)
1756 options->control_master = 0;
1757 if (options->control_persist == -1) {
1758 options->control_persist = 0;
1759 options->control_persist_timeout = 0;
1761 if (options->hash_known_hosts == -1)
1762 options->hash_known_hosts = 0;
1763 if (options->tun_open == -1)
1764 options->tun_open = SSH_TUNMODE_NO;
1765 if (options->tun_local == -1)
1766 options->tun_local = SSH_TUNID_ANY;
1767 if (options->tun_remote == -1)
1768 options->tun_remote = SSH_TUNID_ANY;
1769 if (options->permit_local_command == -1)
1770 options->permit_local_command = 0;
1771 if (options->use_roaming == -1)
1772 options->use_roaming = 1;
1773 if (options->visual_host_key == -1)
1774 options->visual_host_key = 0;
1775 if (options->ip_qos_interactive == -1)
1776 options->ip_qos_interactive = IPTOS_LOWDELAY;
1777 if (options->ip_qos_bulk == -1)
1778 options->ip_qos_bulk = IPTOS_THROUGHPUT;
1779 if (options->request_tty == -1)
1780 options->request_tty = REQUEST_TTY_AUTO;
1781 if (options->proxy_use_fdpass == -1)
1782 options->proxy_use_fdpass = 0;
1783 if (options->canonicalize_max_dots == -1)
1784 options->canonicalize_max_dots = 1;
1785 if (options->canonicalize_fallback_local == -1)
1786 options->canonicalize_fallback_local = 1;
1787 if (options->canonicalize_hostname == -1)
1788 options->canonicalize_hostname = SSH_CANONICALISE_NO;
1789 #define CLEAR_ON_NONE(v) \
1790 do { \
1791 if (option_clear_or_none(v)) { \
1792 free(v); \
1793 v = NULL; \
1795 } while(0)
1796 CLEAR_ON_NONE(options->local_command);
1797 CLEAR_ON_NONE(options->proxy_command);
1798 CLEAR_ON_NONE(options->control_path);
1799 /* options->user will be set in the main program if appropriate */
1800 /* options->hostname will be set in the main program if appropriate */
1801 /* options->host_key_alias should not be set by default */
1802 /* options->preferred_authentications will be set in ssh */
1805 struct fwdarg {
1806 char *arg;
1807 int ispath;
1811 * parse_fwd_field
1812 * parses the next field in a port forwarding specification.
1813 * sets fwd to the parsed field and advances p past the colon
1814 * or sets it to NULL at end of string.
1815 * returns 0 on success, else non-zero.
1817 static int
1818 parse_fwd_field(char **p, struct fwdarg *fwd)
1820 char *ep, *cp = *p;
1821 int ispath = 0;
1823 if (*cp == '\0') {
1824 *p = NULL;
1825 return -1; /* end of string */
1829 * A field escaped with square brackets is used literally.
1830 * XXX - allow ']' to be escaped via backslash?
1832 if (*cp == '[') {
1833 /* find matching ']' */
1834 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1835 if (*ep == '/')
1836 ispath = 1;
1838 /* no matching ']' or not at end of field. */
1839 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1840 return -1;
1841 /* NUL terminate the field and advance p past the colon */
1842 *ep++ = '\0';
1843 if (*ep != '\0')
1844 *ep++ = '\0';
1845 fwd->arg = cp + 1;
1846 fwd->ispath = ispath;
1847 *p = ep;
1848 return 0;
1851 for (cp = *p; *cp != '\0'; cp++) {
1852 switch (*cp) {
1853 case '\\':
1854 memmove(cp, cp + 1, strlen(cp + 1) + 1);
1855 cp++;
1856 break;
1857 case '/':
1858 ispath = 1;
1859 break;
1860 case ':':
1861 *cp++ = '\0';
1862 goto done;
1865 done:
1866 fwd->arg = *p;
1867 fwd->ispath = ispath;
1868 *p = cp;
1869 return 0;
1873 * parse_forward
1874 * parses a string containing a port forwarding specification of the form:
1875 * dynamicfwd == 0
1876 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
1877 * listenpath:connectpath
1878 * dynamicfwd == 1
1879 * [listenhost:]listenport
1880 * returns number of arguments parsed or zero on error
1883 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1885 struct fwdarg fwdargs[4];
1886 char *p, *cp;
1887 int i;
1889 memset(fwd, 0, sizeof(*fwd));
1890 memset(fwdargs, 0, sizeof(fwdargs));
1892 cp = p = xstrdup(fwdspec);
1894 /* skip leading spaces */
1895 while (isspace((u_char)*cp))
1896 cp++;
1898 for (i = 0; i < 4; ++i) {
1899 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
1900 break;
1903 /* Check for trailing garbage */
1904 if (cp != NULL && *cp != '\0') {
1905 i = 0; /* failure */
1908 switch (i) {
1909 case 1:
1910 if (fwdargs[0].ispath) {
1911 fwd->listen_path = xstrdup(fwdargs[0].arg);
1912 fwd->listen_port = PORT_STREAMLOCAL;
1913 } else {
1914 fwd->listen_host = NULL;
1915 fwd->listen_port = a2port(fwdargs[0].arg);
1917 fwd->connect_host = xstrdup("socks");
1918 break;
1920 case 2:
1921 if (fwdargs[0].ispath && fwdargs[1].ispath) {
1922 fwd->listen_path = xstrdup(fwdargs[0].arg);
1923 fwd->listen_port = PORT_STREAMLOCAL;
1924 fwd->connect_path = xstrdup(fwdargs[1].arg);
1925 fwd->connect_port = PORT_STREAMLOCAL;
1926 } else if (fwdargs[1].ispath) {
1927 fwd->listen_host = NULL;
1928 fwd->listen_port = a2port(fwdargs[0].arg);
1929 fwd->connect_path = xstrdup(fwdargs[1].arg);
1930 fwd->connect_port = PORT_STREAMLOCAL;
1931 } else {
1932 fwd->listen_host = xstrdup(fwdargs[0].arg);
1933 fwd->listen_port = a2port(fwdargs[1].arg);
1934 fwd->connect_host = xstrdup("socks");
1936 break;
1938 case 3:
1939 if (fwdargs[0].ispath) {
1940 fwd->listen_path = xstrdup(fwdargs[0].arg);
1941 fwd->listen_port = PORT_STREAMLOCAL;
1942 fwd->connect_host = xstrdup(fwdargs[1].arg);
1943 fwd->connect_port = a2port(fwdargs[2].arg);
1944 } else if (fwdargs[2].ispath) {
1945 fwd->listen_host = xstrdup(fwdargs[0].arg);
1946 fwd->listen_port = a2port(fwdargs[1].arg);
1947 fwd->connect_path = xstrdup(fwdargs[2].arg);
1948 fwd->connect_port = PORT_STREAMLOCAL;
1949 } else {
1950 fwd->listen_host = NULL;
1951 fwd->listen_port = a2port(fwdargs[0].arg);
1952 fwd->connect_host = xstrdup(fwdargs[1].arg);
1953 fwd->connect_port = a2port(fwdargs[2].arg);
1955 break;
1957 case 4:
1958 fwd->listen_host = xstrdup(fwdargs[0].arg);
1959 fwd->listen_port = a2port(fwdargs[1].arg);
1960 fwd->connect_host = xstrdup(fwdargs[2].arg);
1961 fwd->connect_port = a2port(fwdargs[3].arg);
1962 break;
1963 default:
1964 i = 0; /* failure */
1967 free(p);
1969 if (dynamicfwd) {
1970 if (!(i == 1 || i == 2))
1971 goto fail_free;
1972 } else {
1973 if (!(i == 3 || i == 4)) {
1974 if (fwd->connect_path == NULL &&
1975 fwd->listen_path == NULL)
1976 goto fail_free;
1978 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
1979 goto fail_free;
1982 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
1983 (!remotefwd && fwd->listen_port == 0))
1984 goto fail_free;
1985 if (fwd->connect_host != NULL &&
1986 strlen(fwd->connect_host) >= NI_MAXHOST)
1987 goto fail_free;
1988 /* XXX - if connecting to a remote socket, max sun len may not match this host */
1989 if (fwd->connect_path != NULL &&
1990 strlen(fwd->connect_path) >= PATH_MAX_SUN)
1991 goto fail_free;
1992 if (fwd->listen_host != NULL &&
1993 strlen(fwd->listen_host) >= NI_MAXHOST)
1994 goto fail_free;
1995 if (fwd->listen_path != NULL &&
1996 strlen(fwd->listen_path) >= PATH_MAX_SUN)
1997 goto fail_free;
1999 return (i);
2001 fail_free:
2002 free(fwd->connect_host);
2003 fwd->connect_host = NULL;
2004 free(fwd->connect_path);
2005 fwd->connect_path = NULL;
2006 free(fwd->listen_host);
2007 fwd->listen_host = NULL;
2008 free(fwd->listen_path);
2009 fwd->listen_path = NULL;
2010 return (0);