1 /* $OpenBSD: servconf.c,v 1.167 2006/12/14 10:01:14 dtucker Exp $ */ 2 /* 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * 6 * As far as I am concerned, the code I have written for this software 7 * can be used freely for any purpose. Any derived versions of this 8 * software must be clearly marked as such, and if the derived work is 9 * incompatible with the protocol description in the RFC file, it must be 10 * called by a name other than "ssh" or "Secure Shell". 11 */ 12 13 #include <sys/types.h> 14 #include <sys/socket.h> 15 16 #include <netdb.h> 17 #include <pwd.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <signal.h> 22 #include <unistd.h> 23 #include <stdarg.h> 24 25 #include "xmalloc.h" 26 #include "ssh.h" 27 #include "log.h" 28 #include "buffer.h" 29 #include "servconf.h" 30 #include "compat.h" 31 #include "pathnames.h" 32 #include "misc.h" 33 #include "cipher.h" 34 #include "key.h" 35 #include "kex.h" 36 #include "mac.h" 37 #include "match.h" 38 #include "channels.h" 39 #include "groupaccess.h" 40 41 static void add_listen_addr(ServerOptions *, char *, u_short); 42 static void add_one_listen_addr(ServerOptions *, char *, u_short); 43 44 /* Use of privilege separation or not */ 45 extern int use_privsep; 46 extern Buffer cfg; 47 48 /* Initializes the server options to their default values. */ 49 50 void 51 initialize_server_options(ServerOptions *options) 52 { 53 memset(options, 0, sizeof(*options)); 54 options->num_ports = 0; 55 options->ports_from_cmdline = 0; 56 options->listen_addrs = NULL; 57 options->address_family = -1; 58 options->num_host_key_files = 0; 59 options->pid_file = NULL; 60 options->server_key_bits = -1; 61 options->login_grace_time = -1; 62 options->key_regeneration_time = -1; 63 options->permit_root_login = PERMIT_NOT_SET; 64 options->ignore_rhosts = -1; 65 options->ignore_user_known_hosts = -1; 66 options->print_motd = -1; 67 options->print_lastlog = -1; 68 options->x11_forwarding = -1; 69 options->x11_display_offset = -1; 70 options->x11_use_localhost = -1; 71 options->xauth_location = NULL; 72 options->strict_modes = -1; 73 options->tcp_keep_alive = -1; 74 options->log_facility = SYSLOG_FACILITY_NOT_SET; 75 options->log_level = SYSLOG_LEVEL_NOT_SET; 76 options->rhosts_rsa_authentication = -1; 77 options->hostbased_authentication = -1; 78 options->hostbased_uses_name_from_packet_only = -1; 79 options->rsa_authentication = -1; 80 options->pubkey_authentication = -1; 81 options->kerberos_authentication = -1; 82 options->kerberos_or_local_passwd = -1; 83 options->kerberos_ticket_cleanup = -1; 84 options->kerberos_get_afs_token = -1; 85 options->gss_authentication=-1; 86 options->gss_cleanup_creds = -1; 87 options->password_authentication = -1; 88 options->kbd_interactive_authentication = -1; 89 options->challenge_response_authentication = -1; 90 options->permit_empty_passwd = -1; 91 options->permit_user_env = -1; 92 options->use_login = -1; 93 options->compression = -1; 94 options->allow_tcp_forwarding = -1; 95 options->num_allow_users = 0; 96 options->num_deny_users = 0; 97 options->num_allow_groups = 0; 98 options->num_deny_groups = 0; 99 options->ciphers = NULL; 100 options->macs = NULL; 101 options->protocol = SSH_PROTO_UNKNOWN; 102 options->gateway_ports = -1; 103 options->num_subsystems = 0; 104 options->max_startups_begin = -1; 105 options->max_startups_rate = -1; 106 options->max_startups = -1; 107 options->max_authtries = -1; 108 options->banner = NULL; 109 options->use_dns = -1; 110 options->client_alive_interval = -1; 111 options->client_alive_count_max = -1; 112 options->authorized_keys_file = NULL; 113 options->authorized_keys_file2 = NULL; 114 options->num_accept_env = 0; 115 options->permit_tun = -1; 116 options->num_permitted_opens = -1; 117 options->adm_forced_command = NULL; 118 } 119 120 void 121 fill_default_server_options(ServerOptions *options) 122 { 123 if (options->protocol == SSH_PROTO_UNKNOWN) 124 options->protocol = SSH_PROTO_1|SSH_PROTO_2; 125 if (options->num_host_key_files == 0) { 126 /* fill default hostkeys for protocols */ 127 if (options->protocol & SSH_PROTO_1) 128 options->host_key_files[options->num_host_key_files++] = 129 _PATH_HOST_KEY_FILE; 130 if (options->protocol & SSH_PROTO_2) { 131 options->host_key_files[options->num_host_key_files++] = 132 _PATH_HOST_RSA_KEY_FILE; 133 options->host_key_files[options->num_host_key_files++] = 134 _PATH_HOST_DSA_KEY_FILE; 135 } 136 } 137 if (options->num_ports == 0) 138 options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 139 if (options->listen_addrs == NULL) 140 add_listen_addr(options, NULL, 0); 141 if (options->pid_file == NULL) 142 options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 143 if (options->server_key_bits == -1) 144 options->server_key_bits = 768; 145 if (options->login_grace_time == -1) 146 options->login_grace_time = 120; 147 if (options->key_regeneration_time == -1) 148 options->key_regeneration_time = 3600; 149 if (options->permit_root_login == PERMIT_NOT_SET) 150 options->permit_root_login = PERMIT_YES; 151 if (options->ignore_rhosts == -1) 152 options->ignore_rhosts = 1; 153 if (options->ignore_user_known_hosts == -1) 154 options->ignore_user_known_hosts = 0; 155 if (options->print_motd == -1) 156 options->print_motd = 1; 157 if (options->print_lastlog == -1) 158 options->print_lastlog = 1; 159 if (options->x11_forwarding == -1) 160 options->x11_forwarding = 0; 161 if (options->x11_display_offset == -1) 162 options->x11_display_offset = 10; 163 if (options->x11_use_localhost == -1) 164 options->x11_use_localhost = 1; 165 if (options->xauth_location == NULL) 166 options->xauth_location = _PATH_XAUTH; 167 if (options->strict_modes == -1) 168 options->strict_modes = 1; 169 if (options->tcp_keep_alive == -1) 170 options->tcp_keep_alive = 1; 171 if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 172 options->log_facility = SYSLOG_FACILITY_AUTH; 173 if (options->log_level == SYSLOG_LEVEL_NOT_SET) 174 options->log_level = SYSLOG_LEVEL_INFO; 175 if (options->rhosts_rsa_authentication == -1) 176 options->rhosts_rsa_authentication = 0; 177 if (options->hostbased_authentication == -1) 178 options->hostbased_authentication = 0; 179 if (options->hostbased_uses_name_from_packet_only == -1) 180 options->hostbased_uses_name_from_packet_only = 0; 181 if (options->rsa_authentication == -1) 182 options->rsa_authentication = 1; 183 if (options->pubkey_authentication == -1) 184 options->pubkey_authentication = 1; 185 if (options->kerberos_authentication == -1) 186 options->kerberos_authentication = 0; 187 if (options->kerberos_or_local_passwd == -1) 188 options->kerberos_or_local_passwd = 1; 189 if (options->kerberos_ticket_cleanup == -1) 190 options->kerberos_ticket_cleanup = 1; 191 if (options->kerberos_get_afs_token == -1) 192 options->kerberos_get_afs_token = 0; 193 if (options->gss_authentication == -1) 194 options->gss_authentication = 0; 195 if (options->gss_cleanup_creds == -1) 196 options->gss_cleanup_creds = 1; 197 if (options->password_authentication == -1) 198 options->password_authentication = 1; 199 if (options->kbd_interactive_authentication == -1) 200 options->kbd_interactive_authentication = 0; 201 if (options->challenge_response_authentication == -1) 202 options->challenge_response_authentication = 1; 203 if (options->permit_empty_passwd == -1) 204 options->permit_empty_passwd = 0; 205 if (options->permit_user_env == -1) 206 options->permit_user_env = 0; 207 if (options->use_login == -1) 208 options->use_login = 0; 209 if (options->compression == -1) 210 options->compression = COMP_DELAYED; 211 if (options->allow_tcp_forwarding == -1) 212 options->allow_tcp_forwarding = 1; 213 if (options->gateway_ports == -1) 214 options->gateway_ports = 0; 215 if (options->max_startups == -1) 216 options->max_startups = 10; 217 if (options->max_startups_rate == -1) 218 options->max_startups_rate = 100; /* 100% */ 219 if (options->max_startups_begin == -1) 220 options->max_startups_begin = options->max_startups; 221 if (options->max_authtries == -1) 222 options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 223 if (options->use_dns == -1) 224 options->use_dns = 1; 225 if (options->client_alive_interval == -1) 226 options->client_alive_interval = 0; 227 if (options->client_alive_count_max == -1) 228 options->client_alive_count_max = 3; 229 if (options->authorized_keys_file2 == NULL) { 230 /* authorized_keys_file2 falls back to authorized_keys_file */ 231 if (options->authorized_keys_file != NULL) 232 options->authorized_keys_file2 = options->authorized_keys_file; 233 else 234 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; 235 } 236 if (options->authorized_keys_file == NULL) 237 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; 238 if (options->permit_tun == -1) 239 options->permit_tun = SSH_TUNMODE_NO; 240 241 /* Turn privilege separation on by default */ 242 if (use_privsep == -1) 243 use_privsep = 1; 244 } 245 246 /* Keyword tokens. */ 247 typedef enum { 248 sBadOption, /* == unknown option */ 249 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 250 sPermitRootLogin, sLogFacility, sLogLevel, 251 sRhostsRSAAuthentication, sRSAAuthentication, 252 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 253 sKerberosGetAFSToken, 254 sKerberosTgtPassing, sChallengeResponseAuthentication, 255 sPasswordAuthentication, sKbdInteractiveAuthentication, 256 sListenAddress, sAddressFamily, 257 sPrintMotd, sPrintLastLog, sIgnoreRhosts, 258 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 259 sStrictModes, sEmptyPasswd, sTCPKeepAlive, 260 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 261 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 262 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 263 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, 264 sMaxStartups, sMaxAuthTries, 265 sBanner, sUseDNS, sHostbasedAuthentication, 266 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 267 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 268 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, 269 sMatch, sPermitOpen, sForceCommand, 270 sUsePrivilegeSeparation, 271 sDeprecated, sUnsupported 272 } ServerOpCodes; 273 274 #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 275 #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 276 #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 277 278 /* Textual representation of the tokens. */ 279 static struct { 280 const char *name; 281 ServerOpCodes opcode; 282 u_int flags; 283 } keywords[] = { 284 { "port", sPort, SSHCFG_GLOBAL }, 285 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 286 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 287 { "pidfile", sPidFile, SSHCFG_GLOBAL }, 288 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 289 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 290 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 291 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL }, 292 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 293 { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 294 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 295 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL }, 296 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL }, 297 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL }, 298 { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL }, 299 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, 300 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 301 #ifdef KRB5 302 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL }, 303 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 304 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 305 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 306 #else 307 { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL }, 308 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 309 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 310 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 311 #endif 312 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 313 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 314 #ifdef GSSAPI 315 { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL }, 316 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 317 #else 318 { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL }, 319 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 320 #endif 321 { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL }, 322 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL }, 323 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 324 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 325 { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 326 { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 327 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 328 { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 329 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 330 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 331 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 332 { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 333 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 334 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 335 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 336 { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 337 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL }, 338 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 339 { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 340 { "compression", sCompression, SSHCFG_GLOBAL }, 341 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 342 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 343 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 344 { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, 345 { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, 346 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, 347 { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, 348 { "ciphers", sCiphers, SSHCFG_GLOBAL }, 349 { "macs", sMacs, SSHCFG_GLOBAL }, 350 { "protocol", sProtocol, SSHCFG_GLOBAL }, 351 { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 352 { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 353 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 354 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, 355 { "banner", sBanner, SSHCFG_GLOBAL }, 356 { "usedns", sUseDNS, SSHCFG_GLOBAL }, 357 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 358 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 359 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 360 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 361 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, 362 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, 363 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 364 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, 365 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, 366 { "match", sMatch, SSHCFG_ALL }, 367 { "permitopen", sPermitOpen, SSHCFG_ALL }, 368 { "forcecommand", sForceCommand, SSHCFG_ALL }, 369 { NULL, sBadOption, 0 } 370 }; 371 372 /* 373 * Returns the number of the token pointed to by cp or sBadOption. 374 */ 375 376 static ServerOpCodes 377 parse_token(const char *cp, const char *filename, 378 int linenum, u_int *flags) 379 { 380 u_int i; 381 382 for (i = 0; keywords[i].name; i++) 383 if (strcasecmp(cp, keywords[i].name) == 0) { 384 *flags = keywords[i].flags; 385 return keywords[i].opcode; 386 } 387 388 error("%s: line %d: Bad configuration option: %s", 389 filename, linenum, cp); 390 return sBadOption; 391 } 392 393 static void 394 add_listen_addr(ServerOptions *options, char *addr, u_short port) 395 { 396 u_int i; 397 398 if (options->num_ports == 0) 399 options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 400 if (options->address_family == -1) 401 options->address_family = AF_UNSPEC; 402 if (port == 0) 403 for (i = 0; i < options->num_ports; i++) 404 add_one_listen_addr(options, addr, options->ports[i]); 405 else 406 add_one_listen_addr(options, addr, port); 407 } 408 409 static void 410 add_one_listen_addr(ServerOptions *options, char *addr, u_short port) 411 { 412 struct addrinfo hints, *ai, *aitop; 413 char strport[NI_MAXSERV]; 414 int gaierr; 415 416 memset(&hints, 0, sizeof(hints)); 417 hints.ai_family = options->address_family; 418 hints.ai_socktype = SOCK_STREAM; 419 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 420 snprintf(strport, sizeof strport, "%u", port); 421 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 422 fatal("bad addr or host: %s (%s)", 423 addr ? addr : "<NULL>", 424 gai_strerror(gaierr)); 425 for (ai = aitop; ai->ai_next; ai = ai->ai_next) 426 ; 427 ai->ai_next = options->listen_addrs; 428 options->listen_addrs = aitop; 429 } 430 431 /* 432 * The strategy for the Match blocks is that the config file is parsed twice. 433 * 434 * The first time is at startup. activep is initialized to 1 and the 435 * directives in the global context are processed and acted on. Hitting a 436 * Match directive unsets activep and the directives inside the block are 437 * checked for syntax only. 438 * 439 * The second time is after a connection has been established but before 440 * authentication. activep is initialized to 2 and global config directives 441 * are ignored since they have already been processed. If the criteria in a 442 * Match block is met, activep is set and the subsequent directives 443 * processed and actioned until EOF or another Match block unsets it. Any 444 * options set are copied into the main server config. 445 * 446 * Potential additions/improvements: 447 * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 448 * 449 * - Add a Tag directive (idea from David Leonard) ala pf, eg: 450 * Match Address 192.168.0.* 451 * Tag trusted 452 * Match Group wheel 453 * Tag trusted 454 * Match Tag trusted 455 * AllowTcpForwarding yes 456 * GatewayPorts clientspecified 457 * [...] 458 * 459 * - Add a PermittedChannelRequests directive 460 * Match Group shell 461 * PermittedChannelRequests session,forwarded-tcpip 462 */ 463 464 static int 465 match_cfg_line_group(const char *grps, int line, const char *user) 466 { 467 int result = 0; 468 u_int ngrps = 0; 469 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS]; 470 struct passwd *pw; 471 472 /* 473 * Even if we do not have a user yet, we still need to check for 474 * valid syntax. 475 */ 476 arg = cp = xstrdup(grps); 477 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') { 478 if (ngrps >= MAX_MATCH_GROUPS) { 479 error("line %d: too many groups in Match Group", line); 480 result = -1; 481 goto out; 482 } 483 grplist[ngrps++] = p; 484 } 485 486 if (user == NULL) 487 goto out; 488 489 if ((pw = getpwnam(user)) == NULL) { 490 debug("Can't match group at line %d because user %.100s does " 491 "not exist", line, user); 492 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 493 debug("Can't Match group because user %.100s not in any group " 494 "at line %d", user, line); 495 } else if (ga_match(grplist, ngrps) != 1) { 496 debug("user %.100s does not match group %.100s at line %d", 497 user, arg, line); 498 } else { 499 debug("user %.100s matched group %.100s at line %d", user, 500 arg, line); 501 result = 1; 502 } 503 out: 504 ga_free(); 505 xfree(arg); 506 return result; 507 } 508 509 static int 510 match_cfg_line(char **condition, int line, const char *user, const char *host, 511 const char *address) 512 { 513 int result = 1; 514 char *arg, *attrib, *cp = *condition; 515 size_t len; 516 517 if (user == NULL) 518 debug3("checking syntax for 'Match %s'", cp); 519 else 520 debug3("checking match for '%s' user %s host %s addr %s", cp, 521 user ? user : "(null)", host ? host : "(null)", 522 address ? address : "(null)"); 523 524 while ((attrib = strdelim(&cp)) && *attrib != '\0') { 525 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 526 error("Missing Match criteria for %s", attrib); 527 return -1; 528 } 529 len = strlen(arg); 530 if (strcasecmp(attrib, "user") == 0) { 531 if (!user) { 532 result = 0; 533 continue; 534 } 535 if (match_pattern_list(user, arg, len, 0) != 1) 536 result = 0; 537 else 538 debug("user %.100s matched 'User %.100s' at " 539 "line %d", user, arg, line); 540 } else if (strcasecmp(attrib, "group") == 0) { 541 switch (match_cfg_line_group(arg, line, user)) { 542 case -1: 543 return -1; 544 case 0: 545 result = 0; 546 } 547 } else if (strcasecmp(attrib, "host") == 0) { 548 if (!host) { 549 result = 0; 550 continue; 551 } 552 if (match_hostname(host, arg, len) != 1) 553 result = 0; 554 else 555 debug("connection from %.100s matched 'Host " 556 "%.100s' at line %d", host, arg, line); 557 } else if (strcasecmp(attrib, "address") == 0) { 558 debug("address '%s' arg '%s'", address, arg); 559 if (!address) { 560 result = 0; 561 continue; 562 } 563 if (match_hostname(address, arg, len) != 1) 564 result = 0; 565 else 566 debug("connection from %.100s matched 'Address " 567 "%.100s' at line %d", address, arg, line); 568 } else { 569 error("Unsupported Match attribute %s", attrib); 570 return -1; 571 } 572 } 573 if (user != NULL) 574 debug3("match %sfound", result ? "" : "not "); 575 *condition = cp; 576 return result; 577 } 578 579 #define WHITESPACE " \t\r\n" 580 581 int 582 process_server_config_line(ServerOptions *options, char *line, 583 const char *filename, int linenum, int *activep, const char *user, 584 const char *host, const char *address) 585 { 586 char *cp, **charptr, *arg, *p; 587 int cmdline = 0, *intptr, value, n; 588 ServerOpCodes opcode; 589 u_short port; 590 u_int i, flags = 0; 591 size_t len; 592 593 cp = line; 594 if ((arg = strdelim(&cp)) == NULL) 595 return 0; 596 /* Ignore leading whitespace */ 597 if (*arg == '\0') 598 arg = strdelim(&cp); 599 if (!arg || !*arg || *arg == '#') 600 return 0; 601 intptr = NULL; 602 charptr = NULL; 603 opcode = parse_token(arg, filename, linenum, &flags); 604 605 if (activep == NULL) { /* We are processing a command line directive */ 606 cmdline = 1; 607 activep = &cmdline; 608 } 609 if (*activep && opcode != sMatch) 610 debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 611 if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 612 if (user == NULL) { 613 fatal("%s line %d: Directive '%s' is not allowed " 614 "within a Match block", filename, linenum, arg); 615 } else { /* this is a directive we have already processed */ 616 while (arg) 617 arg = strdelim(&cp); 618 return 0; 619 } 620 } 621 622 switch (opcode) { 623 case sBadOption: 624 return -1; 625 case sPort: 626 /* ignore ports from configfile if cmdline specifies ports */ 627 if (options->ports_from_cmdline) 628 return 0; 629 if (options->listen_addrs != NULL) 630 fatal("%s line %d: ports must be specified before " 631 "ListenAddress.", filename, linenum); 632 if (options->num_ports >= MAX_PORTS) 633 fatal("%s line %d: too many ports.", 634 filename, linenum); 635 arg = strdelim(&cp); 636 if (!arg || *arg == '\0') 637 fatal("%s line %d: missing port number.", 638 filename, linenum); 639 options->ports[options->num_ports++] = a2port(arg); 640 if (options->ports[options->num_ports-1] == 0) 641 fatal("%s line %d: Badly formatted port number.", 642 filename, linenum); 643 break; 644 645 case sServerKeyBits: 646 intptr = &options->server_key_bits; 647 parse_int: 648 arg = strdelim(&cp); 649 if (!arg || *arg == '\0') 650 fatal("%s line %d: missing integer value.", 651 filename, linenum); 652 value = atoi(arg); 653 if (*activep && *intptr == -1) 654 *intptr = value; 655 break; 656 657 case sLoginGraceTime: 658 intptr = &options->login_grace_time; 659 parse_time: 660 arg = strdelim(&cp); 661 if (!arg || *arg == '\0') 662 fatal("%s line %d: missing time value.", 663 filename, linenum); 664 if ((value = convtime(arg)) == -1) 665 fatal("%s line %d: invalid time value.", 666 filename, linenum); 667 if (*intptr == -1) 668 *intptr = value; 669 break; 670 671 case sKeyRegenerationTime: 672 intptr = &options->key_regeneration_time; 673 goto parse_time; 674 675 case sListenAddress: 676 arg = strdelim(&cp); 677 if (arg == NULL || *arg == '\0') 678 fatal("%s line %d: missing address", 679 filename, linenum); 680 /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 681 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 682 && strchr(p+1, ':') != NULL) { 683 add_listen_addr(options, arg, 0); 684 break; 685 } 686 p = hpdelim(&arg); 687 if (p == NULL) 688 fatal("%s line %d: bad address:port usage", 689 filename, linenum); 690 p = cleanhostname(p); 691 if (arg == NULL) 692 port = 0; 693 else if ((port = a2port(arg)) == 0) 694 fatal("%s line %d: bad port number", filename, linenum); 695 696 add_listen_addr(options, p, port); 697 698 break; 699 700 case sAddressFamily: 701 arg = strdelim(&cp); 702 if (!arg || *arg == '\0') 703 fatal("%s line %d: missing address family.", 704 filename, linenum); 705 intptr = &options->address_family; 706 if (options->listen_addrs != NULL) 707 fatal("%s line %d: address family must be specified before " 708 "ListenAddress.", filename, linenum); 709 if (strcasecmp(arg, "inet") == 0) 710 value = AF_INET; 711 else if (strcasecmp(arg, "inet6") == 0) 712 value = AF_INET6; 713 else if (strcasecmp(arg, "any") == 0) 714 value = AF_UNSPEC; 715 else 716 fatal("%s line %d: unsupported address family \"%s\".", 717 filename, linenum, arg); 718 if (*intptr == -1) 719 *intptr = value; 720 break; 721 722 case sHostKeyFile: 723 intptr = &options->num_host_key_files; 724 if (*intptr >= MAX_HOSTKEYS) 725 fatal("%s line %d: too many host keys specified (max %d).", 726 filename, linenum, MAX_HOSTKEYS); 727 charptr = &options->host_key_files[*intptr]; 728 parse_filename: 729 arg = strdelim(&cp); 730 if (!arg || *arg == '\0') 731 fatal("%s line %d: missing file name.", 732 filename, linenum); 733 if (*activep && *charptr == NULL) { 734 *charptr = tilde_expand_filename(arg, getuid()); 735 /* increase optional counter */ 736 if (intptr != NULL) 737 *intptr = *intptr + 1; 738 } 739 break; 740 741 case sPidFile: 742 charptr = &options->pid_file; 743 goto parse_filename; 744 745 case sPermitRootLogin: 746 intptr = &options->permit_root_login; 747 arg = strdelim(&cp); 748 if (!arg || *arg == '\0') 749 fatal("%s line %d: missing yes/" 750 "without-password/forced-commands-only/no " 751 "argument.", filename, linenum); 752 value = 0; /* silence compiler */ 753 if (strcmp(arg, "without-password") == 0) 754 value = PERMIT_NO_PASSWD; 755 else if (strcmp(arg, "forced-commands-only") == 0) 756 value = PERMIT_FORCED_ONLY; 757 else if (strcmp(arg, "yes") == 0) 758 value = PERMIT_YES; 759 else if (strcmp(arg, "no") == 0) 760 value = PERMIT_NO; 761 else 762 fatal("%s line %d: Bad yes/" 763 "without-password/forced-commands-only/no " 764 "argument: %s", filename, linenum, arg); 765 if (*intptr == -1) 766 *intptr = value; 767 break; 768 769 case sIgnoreRhosts: 770 intptr = &options->ignore_rhosts; 771 parse_flag: 772 arg = strdelim(&cp); 773 if (!arg || *arg == '\0') 774 fatal("%s line %d: missing yes/no argument.", 775 filename, linenum); 776 value = 0; /* silence compiler */ 777 if (strcmp(arg, "yes") == 0) 778 value = 1; 779 else if (strcmp(arg, "no") == 0) 780 value = 0; 781 else 782 fatal("%s line %d: Bad yes/no argument: %s", 783 filename, linenum, arg); 784 if (*activep && *intptr == -1) 785 *intptr = value; 786 break; 787 788 case sIgnoreUserKnownHosts: 789 intptr = &options->ignore_user_known_hosts; 790 goto parse_flag; 791 792 case sRhostsRSAAuthentication: 793 intptr = &options->rhosts_rsa_authentication; 794 goto parse_flag; 795 796 case sHostbasedAuthentication: 797 intptr = &options->hostbased_authentication; 798 goto parse_flag; 799 800 case sHostbasedUsesNameFromPacketOnly: 801 intptr = &options->hostbased_uses_name_from_packet_only; 802 goto parse_flag; 803 804 case sRSAAuthentication: 805 intptr = &options->rsa_authentication; 806 goto parse_flag; 807 808 case sPubkeyAuthentication: 809 intptr = &options->pubkey_authentication; 810 goto parse_flag; 811 812 case sKerberosAuthentication: 813 intptr = &options->kerberos_authentication; 814 goto parse_flag; 815 816 case sKerberosOrLocalPasswd: 817 intptr = &options->kerberos_or_local_passwd; 818 goto parse_flag; 819 820 case sKerberosTicketCleanup: 821 intptr = &options->kerberos_ticket_cleanup; 822 goto parse_flag; 823 824 case sKerberosGetAFSToken: 825 intptr = &options->kerberos_get_afs_token; 826 goto parse_flag; 827 828 case sGssAuthentication: 829 intptr = &options->gss_authentication; 830 goto parse_flag; 831 832 case sGssCleanupCreds: 833 intptr = &options->gss_cleanup_creds; 834 goto parse_flag; 835 836 case sPasswordAuthentication: 837 intptr = &options->password_authentication; 838 goto parse_flag; 839 840 case sKbdInteractiveAuthentication: 841 intptr = &options->kbd_interactive_authentication; 842 goto parse_flag; 843 844 case sChallengeResponseAuthentication: 845 intptr = &options->challenge_response_authentication; 846 goto parse_flag; 847 848 case sPrintMotd: 849 intptr = &options->print_motd; 850 goto parse_flag; 851 852 case sPrintLastLog: 853 intptr = &options->print_lastlog; 854 goto parse_flag; 855 856 case sX11Forwarding: 857 intptr = &options->x11_forwarding; 858 goto parse_flag; 859 860 case sX11DisplayOffset: 861 intptr = &options->x11_display_offset; 862 goto parse_int; 863 864 case sX11UseLocalhost: 865 intptr = &options->x11_use_localhost; 866 goto parse_flag; 867 868 case sXAuthLocation: 869 charptr = &options->xauth_location; 870 goto parse_filename; 871 872 case sStrictModes: 873 intptr = &options->strict_modes; 874 goto parse_flag; 875 876 case sTCPKeepAlive: 877 intptr = &options->tcp_keep_alive; 878 goto parse_flag; 879 880 case sEmptyPasswd: 881 intptr = &options->permit_empty_passwd; 882 goto parse_flag; 883 884 case sPermitUserEnvironment: 885 intptr = &options->permit_user_env; 886 goto parse_flag; 887 888 case sUseLogin: 889 intptr = &options->use_login; 890 goto parse_flag; 891 892 case sCompression: 893 intptr = &options->compression; 894 arg = strdelim(&cp); 895 if (!arg || *arg == '\0') 896 fatal("%s line %d: missing yes/no/delayed " 897 "argument.", filename, linenum); 898 value = 0; /* silence compiler */ 899 if (strcmp(arg, "delayed") == 0) 900 value = COMP_DELAYED; 901 else if (strcmp(arg, "yes") == 0) 902 value = COMP_ZLIB; 903 else if (strcmp(arg, "no") == 0) 904 value = COMP_NONE; 905 else 906 fatal("%s line %d: Bad yes/no/delayed " 907 "argument: %s", filename, linenum, arg); 908 if (*intptr == -1) 909 *intptr = value; 910 break; 911 912 case sGatewayPorts: 913 intptr = &options->gateway_ports; 914 arg = strdelim(&cp); 915 if (!arg || *arg == '\0') 916 fatal("%s line %d: missing yes/no/clientspecified " 917 "argument.", filename, linenum); 918 value = 0; /* silence compiler */ 919 if (strcmp(arg, "clientspecified") == 0) 920 value = 2; 921 else if (strcmp(arg, "yes") == 0) 922 value = 1; 923 else if (strcmp(arg, "no") == 0) 924 value = 0; 925 else 926 fatal("%s line %d: Bad yes/no/clientspecified " 927 "argument: %s", filename, linenum, arg); 928 if (*intptr == -1) 929 *intptr = value; 930 break; 931 932 case sUseDNS: 933 intptr = &options->use_dns; 934 goto parse_flag; 935 936 case sLogFacility: 937 intptr = (int *) &options->log_facility; 938 arg = strdelim(&cp); 939 value = log_facility_number(arg); 940 if (value == SYSLOG_FACILITY_NOT_SET) 941 fatal("%.200s line %d: unsupported log facility '%s'", 942 filename, linenum, arg ? arg : "<NONE>"); 943 if (*intptr == -1) 944 *intptr = (SyslogFacility) value; 945 break; 946 947 case sLogLevel: 948 intptr = (int *) &options->log_level; 949 arg = strdelim(&cp); 950 value = log_level_number(arg); 951 if (value == SYSLOG_LEVEL_NOT_SET) 952 fatal("%.200s line %d: unsupported log level '%s'", 953 filename, linenum, arg ? arg : "<NONE>"); 954 if (*intptr == -1) 955 *intptr = (LogLevel) value; 956 break; 957 958 case sAllowTcpForwarding: 959 intptr = &options->allow_tcp_forwarding; 960 goto parse_flag; 961 962 case sUsePrivilegeSeparation: 963 intptr = &use_privsep; 964 goto parse_flag; 965 966 case sAllowUsers: 967 while ((arg = strdelim(&cp)) && *arg != '\0') { 968 if (options->num_allow_users >= MAX_ALLOW_USERS) 969 fatal("%s line %d: too many allow users.", 970 filename, linenum); 971 options->allow_users[options->num_allow_users++] = 972 xstrdup(arg); 973 } 974 break; 975 976 case sDenyUsers: 977 while ((arg = strdelim(&cp)) && *arg != '\0') { 978 if (options->num_deny_users >= MAX_DENY_USERS) 979 fatal("%s line %d: too many deny users.", 980 filename, linenum); 981 options->deny_users[options->num_deny_users++] = 982 xstrdup(arg); 983 } 984 break; 985 986 case sAllowGroups: 987 while ((arg = strdelim(&cp)) && *arg != '\0') { 988 if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 989 fatal("%s line %d: too many allow groups.", 990 filename, linenum); 991 options->allow_groups[options->num_allow_groups++] = 992 xstrdup(arg); 993 } 994 break; 995 996 case sDenyGroups: 997 while ((arg = strdelim(&cp)) && *arg != '\0') { 998 if (options->num_deny_groups >= MAX_DENY_GROUPS) 999 fatal("%s line %d: too many deny groups.", 1000 filename, linenum); 1001 options->deny_groups[options->num_deny_groups++] = xstrdup(arg); 1002 } 1003 break; 1004 1005 case sCiphers: 1006 arg = strdelim(&cp); 1007 if (!arg || *arg == '\0') 1008 fatal("%s line %d: Missing argument.", filename, linenum); 1009 if (!ciphers_valid(arg)) 1010 fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 1011 filename, linenum, arg ? arg : "<NONE>"); 1012 if (options->ciphers == NULL) 1013 options->ciphers = xstrdup(arg); 1014 break; 1015 1016 case sMacs: 1017 arg = strdelim(&cp); 1018 if (!arg || *arg == '\0') 1019 fatal("%s line %d: Missing argument.", filename, linenum); 1020 if (!mac_valid(arg)) 1021 fatal("%s line %d: Bad SSH2 mac spec '%s'.", 1022 filename, linenum, arg ? arg : "<NONE>"); 1023 if (options->macs == NULL) 1024 options->macs = xstrdup(arg); 1025 break; 1026 1027 case sProtocol: 1028 intptr = &options->protocol; 1029 arg = strdelim(&cp); 1030 if (!arg || *arg == '\0') 1031 fatal("%s line %d: Missing argument.", filename, linenum); 1032 value = proto_spec(arg); 1033 if (value == SSH_PROTO_UNKNOWN) 1034 fatal("%s line %d: Bad protocol spec '%s'.", 1035 filename, linenum, arg ? arg : "<NONE>"); 1036 if (*intptr == SSH_PROTO_UNKNOWN) 1037 *intptr = value; 1038 break; 1039 1040 case sSubsystem: 1041 if (options->num_subsystems >= MAX_SUBSYSTEMS) { 1042 fatal("%s line %d: too many subsystems defined.", 1043 filename, linenum); 1044 } 1045 arg = strdelim(&cp); 1046 if (!arg || *arg == '\0') 1047 fatal("%s line %d: Missing subsystem name.", 1048 filename, linenum); 1049 if (!*activep) { 1050 arg = strdelim(&cp); 1051 break; 1052 } 1053 for (i = 0; i < options->num_subsystems; i++) 1054 if (strcmp(arg, options->subsystem_name[i]) == 0) 1055 fatal("%s line %d: Subsystem '%s' already defined.", 1056 filename, linenum, arg); 1057 options->subsystem_name[options->num_subsystems] = xstrdup(arg); 1058 arg = strdelim(&cp); 1059 if (!arg || *arg == '\0') 1060 fatal("%s line %d: Missing subsystem command.", 1061 filename, linenum); 1062 options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1063 1064 /* Collect arguments (separate to executable) */ 1065 p = xstrdup(arg); 1066 len = strlen(p) + 1; 1067 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 1068 len += 1 + strlen(arg); 1069 p = xrealloc(p, 1, len); 1070 strlcat(p, " ", len); 1071 strlcat(p, arg, len); 1072 } 1073 options->subsystem_args[options->num_subsystems] = p; 1074 options->num_subsystems++; 1075 break; 1076 1077 case sMaxStartups: 1078 arg = strdelim(&cp); 1079 if (!arg || *arg == '\0') 1080 fatal("%s line %d: Missing MaxStartups spec.", 1081 filename, linenum); 1082 if ((n = sscanf(arg, "%d:%d:%d", 1083 &options->max_startups_begin, 1084 &options->max_startups_rate, 1085 &options->max_startups)) == 3) { 1086 if (options->max_startups_begin > 1087 options->max_startups || 1088 options->max_startups_rate > 100 || 1089 options->max_startups_rate < 1) 1090 fatal("%s line %d: Illegal MaxStartups spec.", 1091 filename, linenum); 1092 } else if (n != 1) 1093 fatal("%s line %d: Illegal MaxStartups spec.", 1094 filename, linenum); 1095 else 1096 options->max_startups = options->max_startups_begin; 1097 break; 1098 1099 case sMaxAuthTries: 1100 intptr = &options->max_authtries; 1101 goto parse_int; 1102 1103 case sBanner: 1104 charptr = &options->banner; 1105 goto parse_filename; 1106 /* 1107 * These options can contain %X options expanded at 1108 * connect time, so that you can specify paths like: 1109 * 1110 * AuthorizedKeysFile /etc/ssh_keys/%u 1111 */ 1112 case sAuthorizedKeysFile: 1113 case sAuthorizedKeysFile2: 1114 charptr = (opcode == sAuthorizedKeysFile) ? 1115 &options->authorized_keys_file : 1116 &options->authorized_keys_file2; 1117 goto parse_filename; 1118 1119 case sClientAliveInterval: 1120 intptr = &options->client_alive_interval; 1121 goto parse_time; 1122 1123 case sClientAliveCountMax: 1124 intptr = &options->client_alive_count_max; 1125 goto parse_int; 1126 1127 case sAcceptEnv: 1128 while ((arg = strdelim(&cp)) && *arg != '\0') { 1129 if (strchr(arg, '=') != NULL) 1130 fatal("%s line %d: Invalid environment name.", 1131 filename, linenum); 1132 if (options->num_accept_env >= MAX_ACCEPT_ENV) 1133 fatal("%s line %d: too many allow env.", 1134 filename, linenum); 1135 if (!*activep) 1136 break; 1137 options->accept_env[options->num_accept_env++] = 1138 xstrdup(arg); 1139 } 1140 break; 1141 1142 case sPermitTunnel: 1143 intptr = &options->permit_tun; 1144 arg = strdelim(&cp); 1145 if (!arg || *arg == '\0') 1146 fatal("%s line %d: Missing yes/point-to-point/" 1147 "ethernet/no argument.", filename, linenum); 1148 value = 0; /* silence compiler */ 1149 if (strcasecmp(arg, "ethernet") == 0) 1150 value = SSH_TUNMODE_ETHERNET; 1151 else if (strcasecmp(arg, "point-to-point") == 0) 1152 value = SSH_TUNMODE_POINTOPOINT; 1153 else if (strcasecmp(arg, "yes") == 0) 1154 value = SSH_TUNMODE_YES; 1155 else if (strcasecmp(arg, "no") == 0) 1156 value = SSH_TUNMODE_NO; 1157 else 1158 fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1159 "no argument: %s", filename, linenum, arg); 1160 if (*intptr == -1) 1161 *intptr = value; 1162 break; 1163 1164 case sMatch: 1165 if (cmdline) 1166 fatal("Match directive not supported as a command-line " 1167 "option"); 1168 value = match_cfg_line(&cp, linenum, user, host, address); 1169 if (value < 0) 1170 fatal("%s line %d: Bad Match condition", filename, 1171 linenum); 1172 *activep = value; 1173 break; 1174 1175 case sPermitOpen: 1176 arg = strdelim(&cp); 1177 if (!arg || *arg == '\0') 1178 fatal("%s line %d: missing PermitOpen specification", 1179 filename, linenum); 1180 n = options->num_permitted_opens; /* modified later */ 1181 if (strcmp(arg, "any") == 0) { 1182 if (*activep && n == -1) { 1183 channel_clear_adm_permitted_opens(); 1184 options->num_permitted_opens = 0; 1185 } 1186 break; 1187 } 1188 if (*activep && n == -1) 1189 channel_clear_adm_permitted_opens(); 1190 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1191 p = hpdelim(&arg); 1192 if (p == NULL) 1193 fatal("%s line %d: missing host in PermitOpen", 1194 filename, linenum); 1195 p = cleanhostname(p); 1196 if (arg == NULL || (port = a2port(arg)) == 0) 1197 fatal("%s line %d: bad port number in " 1198 "PermitOpen", filename, linenum); 1199 if (*activep && n == -1) 1200 options->num_permitted_opens = 1201 channel_add_adm_permitted_opens(p, port); 1202 } 1203 break; 1204 1205 case sForceCommand: 1206 if (cp == NULL) 1207 fatal("%.200s line %d: Missing argument.", filename, 1208 linenum); 1209 len = strspn(cp, WHITESPACE); 1210 if (*activep && options->adm_forced_command == NULL) 1211 options->adm_forced_command = xstrdup(cp + len); 1212 return 0; 1213 1214 case sDeprecated: 1215 logit("%s line %d: Deprecated option %s", 1216 filename, linenum, arg); 1217 while (arg) 1218 arg = strdelim(&cp); 1219 break; 1220 1221 case sUnsupported: 1222 logit("%s line %d: Unsupported option %s", 1223 filename, linenum, arg); 1224 while (arg) 1225 arg = strdelim(&cp); 1226 break; 1227 1228 default: 1229 fatal("%s line %d: Missing handler for opcode %s (%d)", 1230 filename, linenum, arg, opcode); 1231 } 1232 if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 1233 fatal("%s line %d: garbage at end of line; \"%.200s\".", 1234 filename, linenum, arg); 1235 return 0; 1236 } 1237 1238 /* Reads the server configuration file. */ 1239 1240 void 1241 load_server_config(const char *filename, Buffer *conf) 1242 { 1243 char line[1024], *cp; 1244 FILE *f; 1245 1246 debug2("%s: filename %s", __func__, filename); 1247 if ((f = fopen(filename, "r")) == NULL) { 1248 perror(filename); 1249 exit(1); 1250 } 1251 buffer_clear(conf); 1252 while (fgets(line, sizeof(line), f)) { 1253 /* 1254 * Trim out comments and strip whitespace 1255 * NB - preserve newlines, they are needed to reproduce 1256 * line numbers later for error messages 1257 */ 1258 if ((cp = strchr(line, '#')) != NULL) 1259 memcpy(cp, "\n", 2); 1260 cp = line + strspn(line, " \t\r"); 1261 1262 buffer_append(conf, cp, strlen(cp)); 1263 } 1264 buffer_append(conf, "\0", 1); 1265 fclose(f); 1266 debug2("%s: done config len = %d", __func__, buffer_len(conf)); 1267 } 1268 1269 void 1270 parse_server_match_config(ServerOptions *options, const char *user, 1271 const char *host, const char *address) 1272 { 1273 ServerOptions mo; 1274 1275 initialize_server_options(&mo); 1276 parse_server_config(&mo, "reprocess config", &cfg, user, host, address); 1277 copy_set_server_options(options, &mo); 1278 } 1279 1280 /* Copy any (supported) values that are set */ 1281 void 1282 copy_set_server_options(ServerOptions *dst, ServerOptions *src) 1283 { 1284 if (src->allow_tcp_forwarding != -1) 1285 dst->allow_tcp_forwarding = src->allow_tcp_forwarding; 1286 if (src->gateway_ports != -1) 1287 dst->gateway_ports = src->gateway_ports; 1288 if (src->adm_forced_command != NULL) { 1289 if (dst->adm_forced_command != NULL) 1290 xfree(dst->adm_forced_command); 1291 dst->adm_forced_command = src->adm_forced_command; 1292 } 1293 if (src->x11_display_offset != -1) 1294 dst->x11_display_offset = src->x11_display_offset; 1295 if (src->x11_forwarding != -1) 1296 dst->x11_forwarding = src->x11_forwarding; 1297 if (src->x11_use_localhost != -1) 1298 dst->x11_use_localhost = src->x11_use_localhost; 1299 } 1300 1301 void 1302 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1303 const char *user, const char *host, const char *address) 1304 { 1305 int active, linenum, bad_options = 0; 1306 char *cp, *obuf, *cbuf; 1307 1308 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 1309 1310 obuf = cbuf = xstrdup(buffer_ptr(conf)); 1311 active = user ? 0 : 1; 1312 linenum = 1; 1313 while ((cp = strsep(&cbuf, "\n")) != NULL) { 1314 if (process_server_config_line(options, cp, filename, 1315 linenum++, &active, user, host, address) != 0) 1316 bad_options++; 1317 } 1318 xfree(obuf); 1319 if (bad_options > 0) 1320 fatal("%s: terminating, %d bad configuration options", 1321 filename, bad_options); 1322 } 1323