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