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