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