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