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