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