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