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