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