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