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