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