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