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