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