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