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