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