1 /* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */ 2 /* $FreeBSD$ */ 3 /* 4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 6 * All rights reserved 7 * Functions for reading the configuration files. 8 * 9 * As far as I am concerned, the code I have written for this software 10 * can be used freely for any purpose. Any derived versions of this 11 * software must be clearly marked as such, and if the derived work is 12 * incompatible with the protocol description in the RFC file, it must be 13 * called by a name other than "ssh" or "Secure Shell". 14 */ 15 16 #include "includes.h" 17 __RCSID("$FreeBSD$"); 18 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <sys/socket.h> 22 #include <sys/sysctl.h> 23 #include <sys/wait.h> 24 25 #include <netinet/in.h> 26 #include <netinet/in_systm.h> 27 #include <netinet/ip.h> 28 29 #include <ctype.h> 30 #include <errno.h> 31 #include <fcntl.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 46 #include "xmalloc.h" 47 #include "ssh.h" 48 #include "compat.h" 49 #include "cipher.h" 50 #include "pathnames.h" 51 #include "log.h" 52 #include "key.h" 53 #include "readconf.h" 54 #include "match.h" 55 #include "misc.h" 56 #include "buffer.h" 57 #include "kex.h" 58 #include "mac.h" 59 #include "uidswap.h" 60 #include "version.h" 61 62 /* Format of the configuration file: 63 64 # Configuration data is parsed as follows: 65 # 1. command line options 66 # 2. user-specific file 67 # 3. system-wide file 68 # Any configuration value is only changed the first time it is set. 69 # Thus, host-specific definitions should be at the beginning of the 70 # configuration file, and defaults at the end. 71 72 # Host-specific declarations. These may override anything above. A single 73 # host may match multiple declarations; these are processed in the order 74 # that they are given in. 75 76 Host *.ngs.fi ngs.fi 77 User foo 78 79 Host fake.com 80 HostName another.host.name.real.org 81 User blaah 82 Port 34289 83 ForwardX11 no 84 ForwardAgent no 85 86 Host books.com 87 RemoteForward 9999 shadows.cs.hut.fi:9999 88 Cipher 3des 89 90 Host fascist.blob.com 91 Port 23123 92 User tylonen 93 PasswordAuthentication no 94 95 Host puukko.hut.fi 96 User t35124p 97 ProxyCommand ssh-proxy %h %p 98 99 Host *.fr 100 PublicKeyAuthentication no 101 102 Host *.su 103 Cipher none 104 PasswordAuthentication no 105 106 Host vpn.fake.com 107 Tunnel yes 108 TunnelDevice 3 109 110 # Defaults for various options 111 Host * 112 ForwardAgent no 113 ForwardX11 no 114 PasswordAuthentication yes 115 RSAAuthentication yes 116 RhostsRSAAuthentication yes 117 StrictHostKeyChecking yes 118 TcpKeepAlive no 119 IdentityFile ~/.ssh/identity 120 Port 22 121 EscapeChar ~ 122 123 */ 124 125 /* Keyword tokens. */ 126 127 typedef enum { 128 oBadOption, 129 oHost, oMatch, 130 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 131 oGatewayPorts, oExitOnForwardFailure, 132 oPasswordAuthentication, oRSAAuthentication, 133 oChallengeResponseAuthentication, oXAuthLocation, 134 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 135 oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 136 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 137 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 138 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 139 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 140 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 141 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 142 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 143 oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, 144 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 145 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 146 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 147 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 148 oSendEnv, oControlPath, oControlMaster, oControlPersist, 149 oHashKnownHosts, 150 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 151 oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 152 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 153 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 154 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 155 oIgnoredUnknownOption, 156 oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf, 157 #ifdef NONE_CIPHER_ENABLED 158 oNoneEnabled, oNoneSwitch, 159 #endif 160 oVersionAddendum, oDeprecated, oUnsupported 161 } OpCodes; 162 163 /* Textual representations of the tokens. */ 164 165 static struct { 166 const char *name; 167 OpCodes opcode; 168 } keywords[] = { 169 { "forwardagent", oForwardAgent }, 170 { "forwardx11", oForwardX11 }, 171 { "forwardx11trusted", oForwardX11Trusted }, 172 { "forwardx11timeout", oForwardX11Timeout }, 173 { "exitonforwardfailure", oExitOnForwardFailure }, 174 { "xauthlocation", oXAuthLocation }, 175 { "gatewayports", oGatewayPorts }, 176 { "useprivilegedport", oUsePrivilegedPort }, 177 { "rhostsauthentication", oDeprecated }, 178 { "passwordauthentication", oPasswordAuthentication }, 179 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 180 { "kbdinteractivedevices", oKbdInteractiveDevices }, 181 { "rsaauthentication", oRSAAuthentication }, 182 { "pubkeyauthentication", oPubkeyAuthentication }, 183 { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 184 { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 185 { "hostbasedauthentication", oHostbasedAuthentication }, 186 { "challengeresponseauthentication", oChallengeResponseAuthentication }, 187 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 188 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 189 { "kerberosauthentication", oUnsupported }, 190 { "kerberostgtpassing", oUnsupported }, 191 { "afstokenpassing", oUnsupported }, 192 #if defined(GSSAPI) 193 { "gssapiauthentication", oGssAuthentication }, 194 { "gssapidelegatecredentials", oGssDelegateCreds }, 195 #else 196 { "gssapiauthentication", oUnsupported }, 197 { "gssapidelegatecredentials", oUnsupported }, 198 #endif 199 { "fallbacktorsh", oDeprecated }, 200 { "usersh", oDeprecated }, 201 { "identityfile", oIdentityFile }, 202 { "identityfile2", oIdentityFile }, /* obsolete */ 203 { "identitiesonly", oIdentitiesOnly }, 204 { "hostname", oHostName }, 205 { "hostkeyalias", oHostKeyAlias }, 206 { "proxycommand", oProxyCommand }, 207 { "port", oPort }, 208 { "cipher", oCipher }, 209 { "ciphers", oCiphers }, 210 { "macs", oMacs }, 211 { "protocol", oProtocol }, 212 { "remoteforward", oRemoteForward }, 213 { "localforward", oLocalForward }, 214 { "user", oUser }, 215 { "host", oHost }, 216 { "match", oMatch }, 217 { "escapechar", oEscapeChar }, 218 { "globalknownhostsfile", oGlobalKnownHostsFile }, 219 { "globalknownhostsfile2", oDeprecated }, 220 { "userknownhostsfile", oUserKnownHostsFile }, 221 { "userknownhostsfile2", oDeprecated }, 222 { "connectionattempts", oConnectionAttempts }, 223 { "batchmode", oBatchMode }, 224 { "checkhostip", oCheckHostIP }, 225 { "stricthostkeychecking", oStrictHostKeyChecking }, 226 { "compression", oCompression }, 227 { "compressionlevel", oCompressionLevel }, 228 { "tcpkeepalive", oTCPKeepAlive }, 229 { "keepalive", oTCPKeepAlive }, /* obsolete */ 230 { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 231 { "loglevel", oLogLevel }, 232 { "dynamicforward", oDynamicForward }, 233 { "preferredauthentications", oPreferredAuthentications }, 234 { "hostkeyalgorithms", oHostKeyAlgorithms }, 235 { "bindaddress", oBindAddress }, 236 #ifdef ENABLE_PKCS11 237 { "smartcarddevice", oPKCS11Provider }, 238 { "pkcs11provider", oPKCS11Provider }, 239 #else 240 { "smartcarddevice", oUnsupported }, 241 { "pkcs11provider", oUnsupported }, 242 #endif 243 { "clearallforwardings", oClearAllForwardings }, 244 { "enablesshkeysign", oEnableSSHKeysign }, 245 { "verifyhostkeydns", oVerifyHostKeyDNS }, 246 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 247 { "rekeylimit", oRekeyLimit }, 248 { "connecttimeout", oConnectTimeout }, 249 { "addressfamily", oAddressFamily }, 250 { "serveraliveinterval", oServerAliveInterval }, 251 { "serveralivecountmax", oServerAliveCountMax }, 252 { "sendenv", oSendEnv }, 253 { "controlpath", oControlPath }, 254 { "controlmaster", oControlMaster }, 255 { "controlpersist", oControlPersist }, 256 { "hashknownhosts", oHashKnownHosts }, 257 { "tunnel", oTunnel }, 258 { "tunneldevice", oTunnelDevice }, 259 { "localcommand", oLocalCommand }, 260 { "permitlocalcommand", oPermitLocalCommand }, 261 { "visualhostkey", oVisualHostKey }, 262 { "useroaming", oUseRoaming }, 263 #ifdef JPAKE 264 { "zeroknowledgepasswordauthentication", 265 oZeroKnowledgePasswordAuthentication }, 266 #else 267 { "zeroknowledgepasswordauthentication", oUnsupported }, 268 #endif 269 { "kexalgorithms", oKexAlgorithms }, 270 { "ipqos", oIPQoS }, 271 { "requesttty", oRequestTTY }, 272 { "proxyusefdpass", oProxyUseFdpass }, 273 { "canonicaldomains", oCanonicalDomains }, 274 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 275 { "canonicalizehostname", oCanonicalizeHostname }, 276 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 277 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 278 { "ignoreunknown", oIgnoreUnknown }, 279 { "hpndisabled", oHPNDisabled }, 280 { "hpnbuffersize", oHPNBufferSize }, 281 { "tcprcvbufpoll", oTcpRcvBufPoll }, 282 { "tcprcvbuf", oTcpRcvBuf }, 283 #ifdef NONE_CIPHER_ENABLED 284 { "noneenabled", oNoneEnabled }, 285 { "noneswitch", oNoneSwitch }, 286 #endif 287 { "versionaddendum", oVersionAddendum }, 288 289 { NULL, oBadOption } 290 }; 291 292 /* 293 * Adds a local TCP/IP port forward to options. Never returns if there is an 294 * error. 295 */ 296 297 void 298 add_local_forward(Options *options, const Forward *newfwd) 299 { 300 Forward *fwd; 301 #ifndef NO_IPPORT_RESERVED_CONCEPT 302 extern uid_t original_real_uid; 303 int ipport_reserved; 304 #ifdef __FreeBSD__ 305 size_t len_ipport_reserved = sizeof(ipport_reserved); 306 307 if (sysctlbyname("net.inet.ip.portrange.reservedhigh", 308 &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0) 309 ipport_reserved = IPPORT_RESERVED; 310 else 311 ipport_reserved++; 312 #else 313 ipport_reserved = IPPORT_RESERVED; 314 #endif 315 if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) 316 fatal("Privileged ports can only be forwarded by root."); 317 #endif 318 options->local_forwards = xrealloc(options->local_forwards, 319 options->num_local_forwards + 1, 320 sizeof(*options->local_forwards)); 321 fwd = &options->local_forwards[options->num_local_forwards++]; 322 323 fwd->listen_host = newfwd->listen_host; 324 fwd->listen_port = newfwd->listen_port; 325 fwd->connect_host = newfwd->connect_host; 326 fwd->connect_port = newfwd->connect_port; 327 } 328 329 /* 330 * Adds a remote TCP/IP port forward to options. Never returns if there is 331 * an error. 332 */ 333 334 void 335 add_remote_forward(Options *options, const Forward *newfwd) 336 { 337 Forward *fwd; 338 339 options->remote_forwards = xrealloc(options->remote_forwards, 340 options->num_remote_forwards + 1, 341 sizeof(*options->remote_forwards)); 342 fwd = &options->remote_forwards[options->num_remote_forwards++]; 343 344 fwd->listen_host = newfwd->listen_host; 345 fwd->listen_port = newfwd->listen_port; 346 fwd->connect_host = newfwd->connect_host; 347 fwd->connect_port = newfwd->connect_port; 348 fwd->handle = newfwd->handle; 349 fwd->allocated_port = 0; 350 } 351 352 static void 353 clear_forwardings(Options *options) 354 { 355 int i; 356 357 for (i = 0; i < options->num_local_forwards; i++) { 358 free(options->local_forwards[i].listen_host); 359 free(options->local_forwards[i].connect_host); 360 } 361 if (options->num_local_forwards > 0) { 362 free(options->local_forwards); 363 options->local_forwards = NULL; 364 } 365 options->num_local_forwards = 0; 366 for (i = 0; i < options->num_remote_forwards; i++) { 367 free(options->remote_forwards[i].listen_host); 368 free(options->remote_forwards[i].connect_host); 369 } 370 if (options->num_remote_forwards > 0) { 371 free(options->remote_forwards); 372 options->remote_forwards = NULL; 373 } 374 options->num_remote_forwards = 0; 375 options->tun_open = SSH_TUNMODE_NO; 376 } 377 378 void 379 add_identity_file(Options *options, const char *dir, const char *filename, 380 int userprovided) 381 { 382 char *path; 383 384 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 385 fatal("Too many identity files specified (max %d)", 386 SSH_MAX_IDENTITY_FILES); 387 388 if (dir == NULL) /* no dir, filename is absolute */ 389 path = xstrdup(filename); 390 else 391 (void)xasprintf(&path, "%.100s%.100s", dir, filename); 392 393 options->identity_file_userprovided[options->num_identity_files] = 394 userprovided; 395 options->identity_files[options->num_identity_files++] = path; 396 } 397 398 int 399 default_ssh_port(void) 400 { 401 static int port; 402 struct servent *sp; 403 404 if (port == 0) { 405 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 406 port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 407 } 408 return port; 409 } 410 411 /* 412 * Execute a command in a shell. 413 * Return its exit status or -1 on abnormal exit. 414 */ 415 static int 416 execute_in_shell(const char *cmd) 417 { 418 char *shell, *command_string; 419 pid_t pid; 420 int devnull, status; 421 extern uid_t original_real_uid; 422 423 if ((shell = getenv("SHELL")) == NULL) 424 shell = _PATH_BSHELL; 425 426 /* 427 * Use "exec" to avoid "sh -c" processes on some platforms 428 * (e.g. Solaris) 429 */ 430 xasprintf(&command_string, "exec %s", cmd); 431 432 /* Need this to redirect subprocess stdin/out */ 433 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) 434 fatal("open(/dev/null): %s", strerror(errno)); 435 436 debug("Executing command: '%.500s'", cmd); 437 438 /* Fork and execute the command. */ 439 if ((pid = fork()) == 0) { 440 char *argv[4]; 441 442 /* Child. Permanently give up superuser privileges. */ 443 permanently_drop_suid(original_real_uid); 444 445 /* Redirect child stdin and stdout. Leave stderr */ 446 if (dup2(devnull, STDIN_FILENO) == -1) 447 fatal("dup2: %s", strerror(errno)); 448 if (dup2(devnull, STDOUT_FILENO) == -1) 449 fatal("dup2: %s", strerror(errno)); 450 if (devnull > STDERR_FILENO) 451 close(devnull); 452 closefrom(STDERR_FILENO + 1); 453 454 argv[0] = shell; 455 argv[1] = "-c"; 456 argv[2] = command_string; 457 argv[3] = NULL; 458 459 execv(argv[0], argv); 460 error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 461 /* Die with signal to make this error apparent to parent. */ 462 signal(SIGTERM, SIG_DFL); 463 kill(getpid(), SIGTERM); 464 _exit(1); 465 } 466 /* Parent. */ 467 if (pid < 0) 468 fatal("%s: fork: %.100s", __func__, strerror(errno)); 469 470 close(devnull); 471 free(command_string); 472 473 while (waitpid(pid, &status, 0) == -1) { 474 if (errno != EINTR && errno != EAGAIN) 475 fatal("%s: waitpid: %s", __func__, strerror(errno)); 476 } 477 if (!WIFEXITED(status)) { 478 error("command '%.100s' exited abnormally", cmd); 479 return -1; 480 } 481 debug3("command returned status %d", WEXITSTATUS(status)); 482 return WEXITSTATUS(status); 483 } 484 485 /* 486 * Parse and execute a Match directive. 487 */ 488 static int 489 match_cfg_line(Options *options, char **condition, struct passwd *pw, 490 const char *host_arg, const char *filename, int linenum) 491 { 492 char *arg, *attrib, *cmd, *cp = *condition, *host; 493 const char *ruser; 494 int r, port, result = 1, attributes = 0; 495 size_t len; 496 char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 497 498 /* 499 * Configuration is likely to be incomplete at this point so we 500 * must be prepared to use default values. 501 */ 502 port = options->port <= 0 ? default_ssh_port() : options->port; 503 ruser = options->user == NULL ? pw->pw_name : options->user; 504 if (options->hostname != NULL) { 505 /* NB. Please keep in sync with ssh.c:main() */ 506 host = percent_expand(options->hostname, 507 "h", host_arg, (char *)NULL); 508 } else 509 host = xstrdup(host_arg); 510 511 debug3("checking match for '%s' host %s", cp, host); 512 while ((attrib = strdelim(&cp)) && *attrib != '\0') { 513 attributes++; 514 if (strcasecmp(attrib, "all") == 0) { 515 if (attributes != 1 || 516 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 517 error("'all' cannot be combined with other " 518 "Match attributes"); 519 result = -1; 520 goto out; 521 } 522 *condition = cp; 523 result = 1; 524 goto out; 525 } 526 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 527 error("Missing Match criteria for %s", attrib); 528 result = -1; 529 goto out; 530 } 531 len = strlen(arg); 532 if (strcasecmp(attrib, "host") == 0) { 533 if (match_hostname(host, arg, len) != 1) 534 result = 0; 535 else 536 debug("%.200s line %d: matched 'Host %.100s' ", 537 filename, linenum, host); 538 } else if (strcasecmp(attrib, "originalhost") == 0) { 539 if (match_hostname(host_arg, arg, len) != 1) 540 result = 0; 541 else 542 debug("%.200s line %d: matched " 543 "'OriginalHost %.100s' ", 544 filename, linenum, host_arg); 545 } else if (strcasecmp(attrib, "user") == 0) { 546 if (match_pattern_list(ruser, arg, len, 0) != 1) 547 result = 0; 548 else 549 debug("%.200s line %d: matched 'User %.100s' ", 550 filename, linenum, ruser); 551 } else if (strcasecmp(attrib, "localuser") == 0) { 552 if (match_pattern_list(pw->pw_name, arg, len, 0) != 1) 553 result = 0; 554 else 555 debug("%.200s line %d: matched " 556 "'LocalUser %.100s' ", 557 filename, linenum, pw->pw_name); 558 } else if (strcasecmp(attrib, "exec") == 0) { 559 if (gethostname(thishost, sizeof(thishost)) == -1) 560 fatal("gethostname: %s", strerror(errno)); 561 strlcpy(shorthost, thishost, sizeof(shorthost)); 562 shorthost[strcspn(thishost, ".")] = '\0'; 563 snprintf(portstr, sizeof(portstr), "%d", port); 564 565 cmd = percent_expand(arg, 566 "L", shorthost, 567 "d", pw->pw_dir, 568 "h", host, 569 "l", thishost, 570 "n", host_arg, 571 "p", portstr, 572 "r", ruser, 573 "u", pw->pw_name, 574 (char *)NULL); 575 r = execute_in_shell(cmd); 576 if (r == -1) { 577 fatal("%.200s line %d: match exec '%.100s' " 578 "error", filename, linenum, cmd); 579 } else if (r == 0) { 580 debug("%.200s line %d: matched " 581 "'exec \"%.100s\"' ", 582 filename, linenum, cmd); 583 } else 584 result = 0; 585 free(cmd); 586 } else { 587 error("Unsupported Match attribute %s", attrib); 588 result = -1; 589 goto out; 590 } 591 } 592 if (attributes == 0) { 593 error("One or more attributes required for Match"); 594 result = -1; 595 goto out; 596 } 597 debug3("match %sfound", result ? "" : "not "); 598 *condition = cp; 599 out: 600 free(host); 601 return result; 602 } 603 604 /* Check and prepare a domain name: removes trailing '.' and lowercases */ 605 static void 606 valid_domain(char *name, const char *filename, int linenum) 607 { 608 size_t i, l = strlen(name); 609 u_char c, last = '\0'; 610 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; 627 } 628 if (name[l - 1] == '.') 629 name[l - 1] = '\0'; 630 } 631 632 /* 633 * Returns the number of the token pointed to by cp or oBadOption. 634 */ 635 static OpCodes 636 parse_token(const char *cp, const char *filename, int linenum, 637 const char *ignored_unknown) 638 { 639 int i; 640 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; 650 } 651 652 /* Multistate option parsing */ 653 struct multistate { 654 char *key; 655 int value; 656 }; 657 static const struct multistate multistate_flag[] = { 658 { "true", 1 }, 659 { "false", 0 }, 660 { "yes", 1 }, 661 { "no", 0 }, 662 { NULL, -1 } 663 }; 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 } 671 }; 672 static const struct multistate multistate_addressfamily[] = { 673 { "inet", AF_INET }, 674 { "inet6", AF_INET6 }, 675 { "any", AF_UNSPEC }, 676 { NULL, -1 } 677 }; 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 } 687 }; 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 } 696 }; 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 } 705 }; 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 } 713 }; 714 715 /* 716 * Processes a single option line as used in the configuration files. This 717 * only sets those values that have not already been set. 718 */ 719 #define WHITESPACE " \t\r\n" 720 int 721 process_config_line(Options *options, struct passwd *pw, const char *host, 722 char *line, const char *filename, int linenum, int *activep, int userconfig) 723 { 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 Forward fwd; 732 const struct multistate *multistate_ptr; 733 struct allowed_cname *cname; 734 735 if (activep == NULL) { /* We are processing a command line directive */ 736 cmdline = 1; 737 activep = &cmdline; 738 } 739 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'; 745 } 746 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); 758 759 opcode = parse_token(keyword, filename, linenum, 760 options->ignored_unknown); 761 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; 784 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; 799 } 800 } 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; 807 808 case oForwardX11: 809 intptr = &options->forward_x11; 810 goto parse_flag; 811 812 case oForwardX11Trusted: 813 intptr = &options->forward_x11_trusted; 814 goto parse_flag; 815 816 case oForwardX11Timeout: 817 intptr = &options->forward_x11_timeout; 818 goto parse_time; 819 820 case oGatewayPorts: 821 intptr = &options->gateway_ports; 822 goto parse_flag; 823 824 case oExitOnForwardFailure: 825 intptr = &options->exit_on_forward_failure; 826 goto parse_flag; 827 828 case oUsePrivilegedPort: 829 intptr = &options->use_privileged_port; 830 goto parse_flag; 831 832 case oPasswordAuthentication: 833 intptr = &options->password_authentication; 834 goto parse_flag; 835 836 case oZeroKnowledgePasswordAuthentication: 837 intptr = &options->zero_knowledge_password_authentication; 838 goto parse_flag; 839 840 case oKbdInteractiveAuthentication: 841 intptr = &options->kbd_interactive_authentication; 842 goto parse_flag; 843 844 case oKbdInteractiveDevices: 845 charptr = &options->kbd_interactive_devices; 846 goto parse_string; 847 848 case oPubkeyAuthentication: 849 intptr = &options->pubkey_authentication; 850 goto parse_flag; 851 852 case oRSAAuthentication: 853 intptr = &options->rsa_authentication; 854 goto parse_flag; 855 856 case oRhostsRSAAuthentication: 857 intptr = &options->rhosts_rsa_authentication; 858 goto parse_flag; 859 860 case oHostbasedAuthentication: 861 intptr = &options->hostbased_authentication; 862 goto parse_flag; 863 864 case oChallengeResponseAuthentication: 865 intptr = &options->challenge_response_authentication; 866 goto parse_flag; 867 868 case oGssAuthentication: 869 intptr = &options->gss_authentication; 870 goto parse_flag; 871 872 case oGssDelegateCreds: 873 intptr = &options->gss_deleg_creds; 874 goto parse_flag; 875 876 case oBatchMode: 877 intptr = &options->batch_mode; 878 goto parse_flag; 879 880 case oCheckHostIP: 881 intptr = &options->check_host_ip; 882 goto parse_flag; 883 884 case oVerifyHostKeyDNS: 885 intptr = &options->verify_host_key_dns; 886 multistate_ptr = multistate_yesnoask; 887 goto parse_multistate; 888 889 case oStrictHostKeyChecking: 890 intptr = &options->strict_host_key_checking; 891 multistate_ptr = multistate_yesnoask; 892 goto parse_multistate; 893 894 case oCompression: 895 intptr = &options->compression; 896 goto parse_flag; 897 898 case oTCPKeepAlive: 899 intptr = &options->tcp_keep_alive; 900 goto parse_flag; 901 902 case oNoHostAuthenticationForLocalhost: 903 intptr = &options->no_host_authentication_for_localhost; 904 goto parse_flag; 905 906 case oNumberOfPasswordPrompts: 907 intptr = &options->number_of_password_prompts; 908 goto parse_int; 909 910 case oCompressionLevel: 911 intptr = &options->compression_level; 912 goto parse_int; 913 914 case oRekeyLimit: 915 arg = strdelim(&s); 916 if (!arg || *arg == '\0') 917 fatal("%.200s line %d: Missing argument.", filename, 918 linenum); 919 if (strcmp(arg, "default") == 0) { 920 val64 = 0; 921 } else { 922 if (scan_scaled(arg, &val64) == -1) 923 fatal("%.200s line %d: Bad number '%s': %s", 924 filename, linenum, arg, strerror(errno)); 925 /* check for too-large or too-small limits */ 926 if (val64 > UINT_MAX) 927 fatal("%.200s line %d: RekeyLimit too large", 928 filename, linenum); 929 if (val64 != 0 && val64 < 16) 930 fatal("%.200s line %d: RekeyLimit too small", 931 filename, linenum); 932 } 933 if (*activep && options->rekey_limit == -1) 934 options->rekey_limit = (u_int32_t)val64; 935 if (s != NULL) { /* optional rekey interval present */ 936 if (strcmp(s, "none") == 0) { 937 (void)strdelim(&s); /* discard */ 938 break; 939 } 940 intptr = &options->rekey_interval; 941 goto parse_time; 942 } 943 break; 944 945 case oIdentityFile: 946 arg = strdelim(&s); 947 if (!arg || *arg == '\0') 948 fatal("%.200s line %d: Missing argument.", filename, linenum); 949 if (*activep) { 950 intptr = &options->num_identity_files; 951 if (*intptr >= SSH_MAX_IDENTITY_FILES) 952 fatal("%.200s line %d: Too many identity files specified (max %d).", 953 filename, linenum, SSH_MAX_IDENTITY_FILES); 954 add_identity_file(options, NULL, arg, userconfig); 955 } 956 break; 957 958 case oXAuthLocation: 959 charptr=&options->xauth_location; 960 goto parse_string; 961 962 case oUser: 963 charptr = &options->user; 964 parse_string: 965 arg = strdelim(&s); 966 if (!arg || *arg == '\0') 967 fatal("%.200s line %d: Missing argument.", 968 filename, linenum); 969 if (*activep && *charptr == NULL) 970 *charptr = xstrdup(arg); 971 break; 972 973 case oGlobalKnownHostsFile: 974 cpptr = (char **)&options->system_hostfiles; 975 uintptr = &options->num_system_hostfiles; 976 max_entries = SSH_MAX_HOSTS_FILES; 977 parse_char_array: 978 if (*activep && *uintptr == 0) { 979 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 980 if ((*uintptr) >= max_entries) 981 fatal("%s line %d: " 982 "too many authorized keys files.", 983 filename, linenum); 984 cpptr[(*uintptr)++] = xstrdup(arg); 985 } 986 } 987 return 0; 988 989 case oUserKnownHostsFile: 990 cpptr = (char **)&options->user_hostfiles; 991 uintptr = &options->num_user_hostfiles; 992 max_entries = SSH_MAX_HOSTS_FILES; 993 goto parse_char_array; 994 995 case oHostName: 996 charptr = &options->hostname; 997 goto parse_string; 998 999 case oHostKeyAlias: 1000 charptr = &options->host_key_alias; 1001 goto parse_string; 1002 1003 case oPreferredAuthentications: 1004 charptr = &options->preferred_authentications; 1005 goto parse_string; 1006 1007 case oBindAddress: 1008 charptr = &options->bind_address; 1009 goto parse_string; 1010 1011 case oPKCS11Provider: 1012 charptr = &options->pkcs11_provider; 1013 goto parse_string; 1014 1015 case oProxyCommand: 1016 charptr = &options->proxy_command; 1017 parse_command: 1018 if (s == NULL) 1019 fatal("%.200s line %d: Missing argument.", filename, linenum); 1020 len = strspn(s, WHITESPACE "="); 1021 if (*activep && *charptr == NULL) 1022 *charptr = xstrdup(s + len); 1023 return 0; 1024 1025 case oPort: 1026 intptr = &options->port; 1027 parse_int: 1028 arg = strdelim(&s); 1029 if (!arg || *arg == '\0') 1030 fatal("%.200s line %d: Missing argument.", filename, linenum); 1031 if (arg[0] < '0' || arg[0] > '9') 1032 fatal("%.200s line %d: Bad number.", filename, linenum); 1033 1034 /* Octal, decimal, or hex format? */ 1035 value = strtol(arg, &endofnumber, 0); 1036 if (arg == endofnumber) 1037 fatal("%.200s line %d: Bad number.", filename, linenum); 1038 if (*activep && *intptr == -1) 1039 *intptr = value; 1040 break; 1041 1042 case oConnectionAttempts: 1043 intptr = &options->connection_attempts; 1044 goto parse_int; 1045 1046 case oCipher: 1047 intptr = &options->cipher; 1048 arg = strdelim(&s); 1049 if (!arg || *arg == '\0') 1050 fatal("%.200s line %d: Missing argument.", filename, linenum); 1051 value = cipher_number(arg); 1052 if (value == -1) 1053 fatal("%.200s line %d: Bad cipher '%s'.", 1054 filename, linenum, arg ? arg : "<NONE>"); 1055 if (*activep && *intptr == -1) 1056 *intptr = value; 1057 break; 1058 1059 case oCiphers: 1060 arg = strdelim(&s); 1061 if (!arg || *arg == '\0') 1062 fatal("%.200s line %d: Missing argument.", filename, linenum); 1063 if (!ciphers_valid(arg)) 1064 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1065 filename, linenum, arg ? arg : "<NONE>"); 1066 if (*activep && options->ciphers == NULL) 1067 options->ciphers = xstrdup(arg); 1068 break; 1069 1070 case oMacs: 1071 arg = strdelim(&s); 1072 if (!arg || *arg == '\0') 1073 fatal("%.200s line %d: Missing argument.", filename, linenum); 1074 if (!mac_valid(arg)) 1075 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 1076 filename, linenum, arg ? arg : "<NONE>"); 1077 if (*activep && options->macs == NULL) 1078 options->macs = xstrdup(arg); 1079 break; 1080 1081 case oKexAlgorithms: 1082 arg = strdelim(&s); 1083 if (!arg || *arg == '\0') 1084 fatal("%.200s line %d: Missing argument.", 1085 filename, linenum); 1086 if (!kex_names_valid(arg)) 1087 fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1088 filename, linenum, arg ? arg : "<NONE>"); 1089 if (*activep && options->kex_algorithms == NULL) 1090 options->kex_algorithms = xstrdup(arg); 1091 break; 1092 1093 case oHostKeyAlgorithms: 1094 arg = strdelim(&s); 1095 if (!arg || *arg == '\0') 1096 fatal("%.200s line %d: Missing argument.", filename, linenum); 1097 if (!key_names_valid2(arg)) 1098 fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 1099 filename, linenum, arg ? arg : "<NONE>"); 1100 if (*activep && options->hostkeyalgorithms == NULL) 1101 options->hostkeyalgorithms = xstrdup(arg); 1102 break; 1103 1104 case oProtocol: 1105 intptr = &options->protocol; 1106 arg = strdelim(&s); 1107 if (!arg || *arg == '\0') 1108 fatal("%.200s line %d: Missing argument.", filename, linenum); 1109 value = proto_spec(arg); 1110 if (value == SSH_PROTO_UNKNOWN) 1111 fatal("%.200s line %d: Bad protocol spec '%s'.", 1112 filename, linenum, arg ? arg : "<NONE>"); 1113 if (*activep && *intptr == SSH_PROTO_UNKNOWN) 1114 *intptr = value; 1115 break; 1116 1117 case oLogLevel: 1118 log_level_ptr = &options->log_level; 1119 arg = strdelim(&s); 1120 value = log_level_number(arg); 1121 if (value == SYSLOG_LEVEL_NOT_SET) 1122 fatal("%.200s line %d: unsupported log level '%s'", 1123 filename, linenum, arg ? arg : "<NONE>"); 1124 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1125 *log_level_ptr = (LogLevel) value; 1126 break; 1127 1128 case oLocalForward: 1129 case oRemoteForward: 1130 case oDynamicForward: 1131 arg = strdelim(&s); 1132 if (arg == NULL || *arg == '\0') 1133 fatal("%.200s line %d: Missing port argument.", 1134 filename, linenum); 1135 1136 if (opcode == oLocalForward || 1137 opcode == oRemoteForward) { 1138 arg2 = strdelim(&s); 1139 if (arg2 == NULL || *arg2 == '\0') 1140 fatal("%.200s line %d: Missing target argument.", 1141 filename, linenum); 1142 1143 /* construct a string for parse_forward */ 1144 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 1145 } else if (opcode == oDynamicForward) { 1146 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1147 } 1148 1149 if (parse_forward(&fwd, fwdarg, 1150 opcode == oDynamicForward ? 1 : 0, 1151 opcode == oRemoteForward ? 1 : 0) == 0) 1152 fatal("%.200s line %d: Bad forwarding specification.", 1153 filename, linenum); 1154 1155 if (*activep) { 1156 if (opcode == oLocalForward || 1157 opcode == oDynamicForward) 1158 add_local_forward(options, &fwd); 1159 else if (opcode == oRemoteForward) 1160 add_remote_forward(options, &fwd); 1161 } 1162 break; 1163 1164 case oClearAllForwardings: 1165 intptr = &options->clear_forwardings; 1166 goto parse_flag; 1167 1168 case oHost: 1169 if (cmdline) 1170 fatal("Host directive not supported as a command-line " 1171 "option"); 1172 *activep = 0; 1173 arg2 = NULL; 1174 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1175 negated = *arg == '!'; 1176 if (negated) 1177 arg++; 1178 if (match_pattern(host, arg)) { 1179 if (negated) { 1180 debug("%.200s line %d: Skipping Host " 1181 "block because of negated match " 1182 "for %.100s", filename, linenum, 1183 arg); 1184 *activep = 0; 1185 break; 1186 } 1187 if (!*activep) 1188 arg2 = arg; /* logged below */ 1189 *activep = 1; 1190 } 1191 } 1192 if (*activep) 1193 debug("%.200s line %d: Applying options for %.100s", 1194 filename, linenum, arg2); 1195 /* Avoid garbage check below, as strdelim is done. */ 1196 return 0; 1197 1198 case oMatch: 1199 if (cmdline) 1200 fatal("Host directive not supported as a command-line " 1201 "option"); 1202 value = match_cfg_line(options, &s, pw, host, 1203 filename, linenum); 1204 if (value < 0) 1205 fatal("%.200s line %d: Bad Match condition", filename, 1206 linenum); 1207 *activep = value; 1208 break; 1209 1210 case oEscapeChar: 1211 intptr = &options->escape_char; 1212 arg = strdelim(&s); 1213 if (!arg || *arg == '\0') 1214 fatal("%.200s line %d: Missing argument.", filename, linenum); 1215 if (arg[0] == '^' && arg[2] == 0 && 1216 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1217 value = (u_char) arg[1] & 31; 1218 else if (strlen(arg) == 1) 1219 value = (u_char) arg[0]; 1220 else if (strcmp(arg, "none") == 0) 1221 value = SSH_ESCAPECHAR_NONE; 1222 else { 1223 fatal("%.200s line %d: Bad escape character.", 1224 filename, linenum); 1225 /* NOTREACHED */ 1226 value = 0; /* Avoid compiler warning. */ 1227 } 1228 if (*activep && *intptr == -1) 1229 *intptr = value; 1230 break; 1231 1232 case oAddressFamily: 1233 intptr = &options->address_family; 1234 multistate_ptr = multistate_addressfamily; 1235 goto parse_multistate; 1236 1237 case oEnableSSHKeysign: 1238 intptr = &options->enable_ssh_keysign; 1239 goto parse_flag; 1240 1241 case oIdentitiesOnly: 1242 intptr = &options->identities_only; 1243 goto parse_flag; 1244 1245 case oServerAliveInterval: 1246 intptr = &options->server_alive_interval; 1247 goto parse_time; 1248 1249 case oServerAliveCountMax: 1250 intptr = &options->server_alive_count_max; 1251 goto parse_int; 1252 1253 case oSendEnv: 1254 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1255 if (strchr(arg, '=') != NULL) 1256 fatal("%s line %d: Invalid environment name.", 1257 filename, linenum); 1258 if (!*activep) 1259 continue; 1260 if (options->num_send_env >= MAX_SEND_ENV) 1261 fatal("%s line %d: too many send env.", 1262 filename, linenum); 1263 options->send_env[options->num_send_env++] = 1264 xstrdup(arg); 1265 } 1266 break; 1267 1268 case oControlPath: 1269 charptr = &options->control_path; 1270 goto parse_string; 1271 1272 case oControlMaster: 1273 intptr = &options->control_master; 1274 multistate_ptr = multistate_controlmaster; 1275 goto parse_multistate; 1276 1277 case oControlPersist: 1278 /* no/false/yes/true, or a time spec */ 1279 intptr = &options->control_persist; 1280 arg = strdelim(&s); 1281 if (!arg || *arg == '\0') 1282 fatal("%.200s line %d: Missing ControlPersist" 1283 " argument.", filename, linenum); 1284 value = 0; 1285 value2 = 0; /* timeout */ 1286 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1287 value = 0; 1288 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1289 value = 1; 1290 else if ((value2 = convtime(arg)) >= 0) 1291 value = 1; 1292 else 1293 fatal("%.200s line %d: Bad ControlPersist argument.", 1294 filename, linenum); 1295 if (*activep && *intptr == -1) { 1296 *intptr = value; 1297 options->control_persist_timeout = value2; 1298 } 1299 break; 1300 1301 case oHashKnownHosts: 1302 intptr = &options->hash_known_hosts; 1303 goto parse_flag; 1304 1305 case oTunnel: 1306 intptr = &options->tun_open; 1307 multistate_ptr = multistate_tunnel; 1308 goto parse_multistate; 1309 1310 case oTunnelDevice: 1311 arg = strdelim(&s); 1312 if (!arg || *arg == '\0') 1313 fatal("%.200s line %d: Missing argument.", filename, linenum); 1314 value = a2tun(arg, &value2); 1315 if (value == SSH_TUNID_ERR) 1316 fatal("%.200s line %d: Bad tun device.", filename, linenum); 1317 if (*activep) { 1318 options->tun_local = value; 1319 options->tun_remote = value2; 1320 } 1321 break; 1322 1323 case oLocalCommand: 1324 charptr = &options->local_command; 1325 goto parse_command; 1326 1327 case oPermitLocalCommand: 1328 intptr = &options->permit_local_command; 1329 goto parse_flag; 1330 1331 case oVisualHostKey: 1332 intptr = &options->visual_host_key; 1333 goto parse_flag; 1334 1335 case oIPQoS: 1336 arg = strdelim(&s); 1337 if ((value = parse_ipqos(arg)) == -1) 1338 fatal("%s line %d: Bad IPQoS value: %s", 1339 filename, linenum, arg); 1340 arg = strdelim(&s); 1341 if (arg == NULL) 1342 value2 = value; 1343 else if ((value2 = parse_ipqos(arg)) == -1) 1344 fatal("%s line %d: Bad IPQoS value: %s", 1345 filename, linenum, arg); 1346 if (*activep) { 1347 options->ip_qos_interactive = value; 1348 options->ip_qos_bulk = value2; 1349 } 1350 break; 1351 1352 case oUseRoaming: 1353 intptr = &options->use_roaming; 1354 goto parse_flag; 1355 1356 case oRequestTTY: 1357 intptr = &options->request_tty; 1358 multistate_ptr = multistate_requesttty; 1359 goto parse_multistate; 1360 1361 case oHPNDisabled: 1362 intptr = &options->hpn_disabled; 1363 goto parse_flag; 1364 1365 case oHPNBufferSize: 1366 intptr = &options->hpn_buffer_size; 1367 goto parse_int; 1368 1369 case oTcpRcvBufPoll: 1370 intptr = &options->tcp_rcv_buf_poll; 1371 goto parse_flag; 1372 1373 case oTcpRcvBuf: 1374 intptr = &options->tcp_rcv_buf; 1375 goto parse_int; 1376 1377 #ifdef NONE_CIPHER_ENABLED 1378 case oNoneEnabled: 1379 intptr = &options->none_enabled; 1380 goto parse_flag; 1381 1382 /* 1383 * We check to see if the command comes from the command line or not. 1384 * If it does then enable it otherwise fail. NONE must never be a 1385 * default configuration. 1386 */ 1387 case oNoneSwitch: 1388 if (strcmp(filename,"command-line") == 0) { 1389 intptr = &options->none_switch; 1390 goto parse_flag; 1391 } else { 1392 debug("NoneSwitch directive found in %.200s.", 1393 filename); 1394 error("NoneSwitch is found in %.200s.\n" 1395 "You may only use this configuration option " 1396 "from the command line", filename); 1397 error("Continuing..."); 1398 return 0; 1399 } 1400 #endif 1401 1402 case oVersionAddendum: 1403 if (s == NULL) 1404 fatal("%.200s line %d: Missing argument.", filename, 1405 linenum); 1406 len = strspn(s, WHITESPACE); 1407 if (*activep && options->version_addendum == NULL) { 1408 if (strcasecmp(s + len, "none") == 0) 1409 options->version_addendum = xstrdup(""); 1410 else if (strchr(s + len, '\r') != NULL) 1411 fatal("%.200s line %d: Invalid argument", 1412 filename, linenum); 1413 else 1414 options->version_addendum = xstrdup(s + len); 1415 } 1416 return 0; 1417 1418 case oIgnoreUnknown: 1419 charptr = &options->ignored_unknown; 1420 goto parse_string; 1421 1422 case oProxyUseFdpass: 1423 intptr = &options->proxy_use_fdpass; 1424 goto parse_flag; 1425 1426 case oCanonicalDomains: 1427 value = options->num_canonical_domains != 0; 1428 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1429 valid_domain(arg, filename, linenum); 1430 if (!*activep || value) 1431 continue; 1432 if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1433 fatal("%s line %d: too many hostname suffixes.", 1434 filename, linenum); 1435 options->canonical_domains[ 1436 options->num_canonical_domains++] = xstrdup(arg); 1437 } 1438 break; 1439 1440 case oCanonicalizePermittedCNAMEs: 1441 value = options->num_permitted_cnames != 0; 1442 while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1443 /* Either '*' for everything or 'list:list' */ 1444 if (strcmp(arg, "*") == 0) 1445 arg2 = arg; 1446 else { 1447 lowercase(arg); 1448 if ((arg2 = strchr(arg, ':')) == NULL || 1449 arg2[1] == '\0') { 1450 fatal("%s line %d: " 1451 "Invalid permitted CNAME \"%s\"", 1452 filename, linenum, arg); 1453 } 1454 *arg2 = '\0'; 1455 arg2++; 1456 } 1457 if (!*activep || value) 1458 continue; 1459 if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1460 fatal("%s line %d: too many permitted CNAMEs.", 1461 filename, linenum); 1462 cname = options->permitted_cnames + 1463 options->num_permitted_cnames++; 1464 cname->source_list = xstrdup(arg); 1465 cname->target_list = xstrdup(arg2); 1466 } 1467 break; 1468 1469 case oCanonicalizeHostname: 1470 intptr = &options->canonicalize_hostname; 1471 multistate_ptr = multistate_canonicalizehostname; 1472 goto parse_multistate; 1473 1474 case oCanonicalizeMaxDots: 1475 intptr = &options->canonicalize_max_dots; 1476 goto parse_int; 1477 1478 case oCanonicalizeFallbackLocal: 1479 intptr = &options->canonicalize_fallback_local; 1480 goto parse_flag; 1481 1482 case oDeprecated: 1483 debug("%s line %d: Deprecated option \"%s\"", 1484 filename, linenum, keyword); 1485 return 0; 1486 1487 case oUnsupported: 1488 error("%s line %d: Unsupported option \"%s\"", 1489 filename, linenum, keyword); 1490 return 0; 1491 1492 default: 1493 fatal("process_config_line: Unimplemented opcode %d", opcode); 1494 } 1495 1496 /* Check that there is no garbage at end of line. */ 1497 if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1498 fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1499 filename, linenum, arg); 1500 } 1501 return 0; 1502 } 1503 1504 1505 /* 1506 * Reads the config file and modifies the options accordingly. Options 1507 * should already be initialized before this call. This never returns if 1508 * there is an error. If the file does not exist, this returns 0. 1509 */ 1510 1511 int 1512 read_config_file(const char *filename, struct passwd *pw, const char *host, 1513 Options *options, int flags) 1514 { 1515 FILE *f; 1516 char line[1024]; 1517 int active, linenum; 1518 int bad_options = 0; 1519 1520 if ((f = fopen(filename, "r")) == NULL) 1521 return 0; 1522 1523 if (flags & SSHCONF_CHECKPERM) { 1524 struct stat sb; 1525 1526 if (fstat(fileno(f), &sb) == -1) 1527 fatal("fstat %s: %s", filename, strerror(errno)); 1528 if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 1529 (sb.st_mode & 022) != 0)) 1530 fatal("Bad owner or permissions on %s", filename); 1531 } 1532 1533 debug("Reading configuration data %.200s", filename); 1534 1535 /* 1536 * Mark that we are now processing the options. This flag is turned 1537 * on/off by Host specifications. 1538 */ 1539 active = 1; 1540 linenum = 0; 1541 while (fgets(line, sizeof(line), f)) { 1542 /* Update line number counter. */ 1543 linenum++; 1544 if (process_config_line(options, pw, host, line, filename, 1545 linenum, &active, flags & SSHCONF_USERCONF) != 0) 1546 bad_options++; 1547 } 1548 fclose(f); 1549 if (bad_options > 0) 1550 fatal("%s: terminating, %d bad configuration options", 1551 filename, bad_options); 1552 return 1; 1553 } 1554 1555 /* 1556 * Initializes options to special values that indicate that they have not yet 1557 * been set. Read_config_file will only set options with this value. Options 1558 * are processed in the following order: command line, user config file, 1559 * system config file. Last, fill_default_options is called. 1560 */ 1561 1562 void 1563 initialize_options(Options * options) 1564 { 1565 memset(options, 'X', sizeof(*options)); 1566 options->forward_agent = -1; 1567 options->forward_x11 = -1; 1568 options->forward_x11_trusted = -1; 1569 options->forward_x11_timeout = -1; 1570 options->exit_on_forward_failure = -1; 1571 options->xauth_location = NULL; 1572 options->gateway_ports = -1; 1573 options->use_privileged_port = -1; 1574 options->rsa_authentication = -1; 1575 options->pubkey_authentication = -1; 1576 options->challenge_response_authentication = -1; 1577 options->gss_authentication = -1; 1578 options->gss_deleg_creds = -1; 1579 options->password_authentication = -1; 1580 options->kbd_interactive_authentication = -1; 1581 options->kbd_interactive_devices = NULL; 1582 options->rhosts_rsa_authentication = -1; 1583 options->hostbased_authentication = -1; 1584 options->batch_mode = -1; 1585 options->check_host_ip = -1; 1586 options->strict_host_key_checking = -1; 1587 options->compression = -1; 1588 options->tcp_keep_alive = -1; 1589 options->compression_level = -1; 1590 options->port = -1; 1591 options->address_family = -1; 1592 options->connection_attempts = -1; 1593 options->connection_timeout = -1; 1594 options->number_of_password_prompts = -1; 1595 options->cipher = -1; 1596 options->ciphers = NULL; 1597 options->macs = NULL; 1598 options->kex_algorithms = NULL; 1599 options->hostkeyalgorithms = NULL; 1600 options->protocol = SSH_PROTO_UNKNOWN; 1601 options->num_identity_files = 0; 1602 options->hostname = NULL; 1603 options->host_key_alias = NULL; 1604 options->proxy_command = NULL; 1605 options->user = NULL; 1606 options->escape_char = -1; 1607 options->num_system_hostfiles = 0; 1608 options->num_user_hostfiles = 0; 1609 options->local_forwards = NULL; 1610 options->num_local_forwards = 0; 1611 options->remote_forwards = NULL; 1612 options->num_remote_forwards = 0; 1613 options->clear_forwardings = -1; 1614 options->log_level = SYSLOG_LEVEL_NOT_SET; 1615 options->preferred_authentications = NULL; 1616 options->bind_address = NULL; 1617 options->pkcs11_provider = NULL; 1618 options->enable_ssh_keysign = - 1; 1619 options->no_host_authentication_for_localhost = - 1; 1620 options->identities_only = - 1; 1621 options->rekey_limit = - 1; 1622 options->rekey_interval = -1; 1623 options->verify_host_key_dns = -1; 1624 options->server_alive_interval = -1; 1625 options->server_alive_count_max = -1; 1626 options->num_send_env = 0; 1627 options->control_path = NULL; 1628 options->control_master = -1; 1629 options->control_persist = -1; 1630 options->control_persist_timeout = 0; 1631 options->hash_known_hosts = -1; 1632 options->tun_open = -1; 1633 options->tun_local = -1; 1634 options->tun_remote = -1; 1635 options->local_command = NULL; 1636 options->permit_local_command = -1; 1637 options->use_roaming = -1; 1638 options->visual_host_key = -1; 1639 options->zero_knowledge_password_authentication = -1; 1640 options->ip_qos_interactive = -1; 1641 options->ip_qos_bulk = -1; 1642 options->request_tty = -1; 1643 options->proxy_use_fdpass = -1; 1644 options->ignored_unknown = NULL; 1645 options->num_canonical_domains = 0; 1646 options->num_permitted_cnames = 0; 1647 options->canonicalize_max_dots = -1; 1648 options->canonicalize_fallback_local = -1; 1649 options->canonicalize_hostname = -1; 1650 options->version_addendum = NULL; 1651 options->hpn_disabled = -1; 1652 options->hpn_buffer_size = -1; 1653 options->tcp_rcv_buf_poll = -1; 1654 options->tcp_rcv_buf = -1; 1655 #ifdef NONE_CIPHER_ENABLED 1656 options->none_enabled = -1; 1657 options->none_switch = -1; 1658 #endif 1659 } 1660 1661 /* 1662 * Called after processing other sources of option data, this fills those 1663 * options for which no value has been specified with their default values. 1664 */ 1665 1666 void 1667 fill_default_options(Options * options) 1668 { 1669 if (options->forward_agent == -1) 1670 options->forward_agent = 0; 1671 if (options->forward_x11 == -1) 1672 options->forward_x11 = 0; 1673 if (options->forward_x11_trusted == -1) 1674 options->forward_x11_trusted = 0; 1675 if (options->forward_x11_timeout == -1) 1676 options->forward_x11_timeout = 1200; 1677 if (options->exit_on_forward_failure == -1) 1678 options->exit_on_forward_failure = 0; 1679 if (options->xauth_location == NULL) 1680 options->xauth_location = _PATH_XAUTH; 1681 if (options->gateway_ports == -1) 1682 options->gateway_ports = 0; 1683 if (options->use_privileged_port == -1) 1684 options->use_privileged_port = 0; 1685 if (options->rsa_authentication == -1) 1686 options->rsa_authentication = 1; 1687 if (options->pubkey_authentication == -1) 1688 options->pubkey_authentication = 1; 1689 if (options->challenge_response_authentication == -1) 1690 options->challenge_response_authentication = 1; 1691 if (options->gss_authentication == -1) 1692 options->gss_authentication = 0; 1693 if (options->gss_deleg_creds == -1) 1694 options->gss_deleg_creds = 0; 1695 if (options->password_authentication == -1) 1696 options->password_authentication = 1; 1697 if (options->kbd_interactive_authentication == -1) 1698 options->kbd_interactive_authentication = 1; 1699 if (options->rhosts_rsa_authentication == -1) 1700 options->rhosts_rsa_authentication = 0; 1701 if (options->hostbased_authentication == -1) 1702 options->hostbased_authentication = 0; 1703 if (options->batch_mode == -1) 1704 options->batch_mode = 0; 1705 if (options->check_host_ip == -1) 1706 options->check_host_ip = 0; 1707 if (options->strict_host_key_checking == -1) 1708 options->strict_host_key_checking = 2; /* 2 is default */ 1709 if (options->compression == -1) 1710 options->compression = 0; 1711 if (options->tcp_keep_alive == -1) 1712 options->tcp_keep_alive = 1; 1713 if (options->compression_level == -1) 1714 options->compression_level = 6; 1715 if (options->port == -1) 1716 options->port = 0; /* Filled in ssh_connect. */ 1717 if (options->address_family == -1) 1718 options->address_family = AF_UNSPEC; 1719 if (options->connection_attempts == -1) 1720 options->connection_attempts = 1; 1721 if (options->number_of_password_prompts == -1) 1722 options->number_of_password_prompts = 3; 1723 /* Selected in ssh_login(). */ 1724 if (options->cipher == -1) 1725 options->cipher = SSH_CIPHER_NOT_SET; 1726 /* options->ciphers, default set in myproposals.h */ 1727 /* options->macs, default set in myproposals.h */ 1728 /* options->kex_algorithms, default set in myproposals.h */ 1729 /* options->hostkeyalgorithms, default set in myproposals.h */ 1730 if (options->protocol == SSH_PROTO_UNKNOWN) 1731 options->protocol = SSH_PROTO_2; 1732 if (options->num_identity_files == 0) { 1733 if (options->protocol & SSH_PROTO_1) { 1734 add_identity_file(options, "~/", 1735 _PATH_SSH_CLIENT_IDENTITY, 0); 1736 } 1737 if (options->protocol & SSH_PROTO_2) { 1738 add_identity_file(options, "~/", 1739 _PATH_SSH_CLIENT_ID_RSA, 0); 1740 add_identity_file(options, "~/", 1741 _PATH_SSH_CLIENT_ID_DSA, 0); 1742 #ifdef OPENSSL_HAS_ECC 1743 add_identity_file(options, "~/", 1744 _PATH_SSH_CLIENT_ID_ECDSA, 0); 1745 #endif 1746 add_identity_file(options, "~/", 1747 _PATH_SSH_CLIENT_ID_ED25519, 0); 1748 } 1749 } 1750 if (options->escape_char == -1) 1751 options->escape_char = '~'; 1752 if (options->num_system_hostfiles == 0) { 1753 options->system_hostfiles[options->num_system_hostfiles++] = 1754 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1755 options->system_hostfiles[options->num_system_hostfiles++] = 1756 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1757 } 1758 if (options->num_user_hostfiles == 0) { 1759 options->user_hostfiles[options->num_user_hostfiles++] = 1760 xstrdup(_PATH_SSH_USER_HOSTFILE); 1761 options->user_hostfiles[options->num_user_hostfiles++] = 1762 xstrdup(_PATH_SSH_USER_HOSTFILE2); 1763 } 1764 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 1765 options->log_level = SYSLOG_LEVEL_INFO; 1766 if (options->clear_forwardings == 1) 1767 clear_forwardings(options); 1768 if (options->no_host_authentication_for_localhost == - 1) 1769 options->no_host_authentication_for_localhost = 0; 1770 if (options->identities_only == -1) 1771 options->identities_only = 0; 1772 if (options->enable_ssh_keysign == -1) 1773 options->enable_ssh_keysign = 0; 1774 if (options->rekey_limit == -1) 1775 options->rekey_limit = 0; 1776 if (options->rekey_interval == -1) 1777 options->rekey_interval = 0; 1778 #if HAVE_LDNS 1779 if (options->verify_host_key_dns == -1) 1780 /* automatically trust a verified SSHFP record */ 1781 options->verify_host_key_dns = 1; 1782 #else 1783 if (options->verify_host_key_dns == -1) 1784 options->verify_host_key_dns = 0; 1785 #endif 1786 if (options->server_alive_interval == -1) 1787 options->server_alive_interval = 0; 1788 if (options->server_alive_count_max == -1) 1789 options->server_alive_count_max = 3; 1790 if (options->control_master == -1) 1791 options->control_master = 0; 1792 if (options->control_persist == -1) { 1793 options->control_persist = 0; 1794 options->control_persist_timeout = 0; 1795 } 1796 if (options->hash_known_hosts == -1) 1797 options->hash_known_hosts = 0; 1798 if (options->tun_open == -1) 1799 options->tun_open = SSH_TUNMODE_NO; 1800 if (options->tun_local == -1) 1801 options->tun_local = SSH_TUNID_ANY; 1802 if (options->tun_remote == -1) 1803 options->tun_remote = SSH_TUNID_ANY; 1804 if (options->permit_local_command == -1) 1805 options->permit_local_command = 0; 1806 if (options->use_roaming == -1) 1807 options->use_roaming = 1; 1808 if (options->visual_host_key == -1) 1809 options->visual_host_key = 0; 1810 if (options->zero_knowledge_password_authentication == -1) 1811 options->zero_knowledge_password_authentication = 0; 1812 if (options->ip_qos_interactive == -1) 1813 options->ip_qos_interactive = IPTOS_LOWDELAY; 1814 if (options->ip_qos_bulk == -1) 1815 options->ip_qos_bulk = IPTOS_THROUGHPUT; 1816 if (options->request_tty == -1) 1817 options->request_tty = REQUEST_TTY_AUTO; 1818 if (options->proxy_use_fdpass == -1) 1819 options->proxy_use_fdpass = 0; 1820 if (options->canonicalize_max_dots == -1) 1821 options->canonicalize_max_dots = 1; 1822 if (options->canonicalize_fallback_local == -1) 1823 options->canonicalize_fallback_local = 1; 1824 if (options->canonicalize_hostname == -1) 1825 options->canonicalize_hostname = SSH_CANONICALISE_NO; 1826 #define CLEAR_ON_NONE(v) \ 1827 do { \ 1828 if (v != NULL && strcasecmp(v, "none") == 0) { \ 1829 free(v); \ 1830 v = NULL; \ 1831 } \ 1832 } while(0) 1833 CLEAR_ON_NONE(options->local_command); 1834 CLEAR_ON_NONE(options->proxy_command); 1835 CLEAR_ON_NONE(options->control_path); 1836 /* options->user will be set in the main program if appropriate */ 1837 /* options->hostname will be set in the main program if appropriate */ 1838 /* options->host_key_alias should not be set by default */ 1839 /* options->preferred_authentications will be set in ssh */ 1840 if (options->version_addendum == NULL) 1841 options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 1842 if (options->hpn_disabled == -1) 1843 options->hpn_disabled = 0; 1844 if (options->hpn_buffer_size > -1) 1845 { 1846 u_int maxlen; 1847 1848 /* If a user tries to set the size to 0 set it to 1KB. */ 1849 if (options->hpn_buffer_size == 0) 1850 options->hpn_buffer_size = 1024; 1851 /* Limit the buffer to BUFFER_MAX_LEN. */ 1852 maxlen = buffer_get_max_len(); 1853 if (options->hpn_buffer_size > (maxlen / 1024)) { 1854 debug("User requested buffer larger than %ub: %ub. " 1855 "Request reverted to %ub", maxlen, 1856 options->hpn_buffer_size * 1024, maxlen); 1857 options->hpn_buffer_size = maxlen; 1858 } 1859 debug("hpn_buffer_size set to %d", options->hpn_buffer_size); 1860 } 1861 if (options->tcp_rcv_buf == 0) 1862 options->tcp_rcv_buf = 1; 1863 if (options->tcp_rcv_buf > -1) 1864 options->tcp_rcv_buf *= 1024; 1865 if (options->tcp_rcv_buf_poll == -1) 1866 options->tcp_rcv_buf_poll = 1; 1867 #ifdef NONE_CIPHER_ENABLED 1868 /* options->none_enabled must not be set by default */ 1869 if (options->none_switch == -1) 1870 options->none_switch = 0; 1871 #endif 1872 } 1873 1874 /* 1875 * parse_forward 1876 * parses a string containing a port forwarding specification of the form: 1877 * dynamicfwd == 0 1878 * [listenhost:]listenport:connecthost:connectport 1879 * dynamicfwd == 1 1880 * [listenhost:]listenport 1881 * returns number of arguments parsed or zero on error 1882 */ 1883 int 1884 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 1885 { 1886 int i; 1887 char *p, *cp, *fwdarg[4]; 1888 1889 memset(fwd, '\0', sizeof(*fwd)); 1890 1891 cp = p = xstrdup(fwdspec); 1892 1893 /* skip leading spaces */ 1894 while (isspace((u_char)*cp)) 1895 cp++; 1896 1897 for (i = 0; i < 4; ++i) 1898 if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1899 break; 1900 1901 /* Check for trailing garbage */ 1902 if (cp != NULL) 1903 i = 0; /* failure */ 1904 1905 switch (i) { 1906 case 1: 1907 fwd->listen_host = NULL; 1908 fwd->listen_port = a2port(fwdarg[0]); 1909 fwd->connect_host = xstrdup("socks"); 1910 break; 1911 1912 case 2: 1913 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1914 fwd->listen_port = a2port(fwdarg[1]); 1915 fwd->connect_host = xstrdup("socks"); 1916 break; 1917 1918 case 3: 1919 fwd->listen_host = NULL; 1920 fwd->listen_port = a2port(fwdarg[0]); 1921 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1922 fwd->connect_port = a2port(fwdarg[2]); 1923 break; 1924 1925 case 4: 1926 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1927 fwd->listen_port = a2port(fwdarg[1]); 1928 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1929 fwd->connect_port = a2port(fwdarg[3]); 1930 break; 1931 default: 1932 i = 0; /* failure */ 1933 } 1934 1935 free(p); 1936 1937 if (dynamicfwd) { 1938 if (!(i == 1 || i == 2)) 1939 goto fail_free; 1940 } else { 1941 if (!(i == 3 || i == 4)) 1942 goto fail_free; 1943 if (fwd->connect_port <= 0) 1944 goto fail_free; 1945 } 1946 1947 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 1948 goto fail_free; 1949 1950 if (fwd->connect_host != NULL && 1951 strlen(fwd->connect_host) >= NI_MAXHOST) 1952 goto fail_free; 1953 if (fwd->listen_host != NULL && 1954 strlen(fwd->listen_host) >= NI_MAXHOST) 1955 goto fail_free; 1956 1957 1958 return (i); 1959 1960 fail_free: 1961 free(fwd->connect_host); 1962 fwd->connect_host = NULL; 1963 free(fwd->listen_host); 1964 fwd->listen_host = NULL; 1965 return (0); 1966 } 1967