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