GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
|||
2 |
/* $OpenBSD: servconf.c,v 1.312 2017/10/02 19:33:20 djm Exp $ */ |
||
3 |
/* |
||
4 |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
||
5 |
* All rights reserved |
||
6 |
* |
||
7 |
* As far as I am concerned, the code I have written for this software |
||
8 |
* can be used freely for any purpose. Any derived versions of this |
||
9 |
* software must be clearly marked as such, and if the derived work is |
||
10 |
* incompatible with the protocol description in the RFC file, it must be |
||
11 |
* called by a name other than "ssh" or "Secure Shell". |
||
12 |
*/ |
||
13 |
|||
14 |
#include <sys/types.h> |
||
15 |
#include <sys/socket.h> |
||
16 |
#include <sys/queue.h> |
||
17 |
|||
18 |
#include <netinet/in.h> |
||
19 |
#include <netinet/ip.h> |
||
20 |
|||
21 |
#include <ctype.h> |
||
22 |
#include <netdb.h> |
||
23 |
#include <pwd.h> |
||
24 |
#include <stdio.h> |
||
25 |
#include <stdlib.h> |
||
26 |
#include <string.h> |
||
27 |
#include <signal.h> |
||
28 |
#include <unistd.h> |
||
29 |
#include <limits.h> |
||
30 |
#include <stdarg.h> |
||
31 |
#include <errno.h> |
||
32 |
#include <util.h> |
||
33 |
|||
34 |
#include "xmalloc.h" |
||
35 |
#include "ssh.h" |
||
36 |
#include "log.h" |
||
37 |
#include "buffer.h" |
||
38 |
#include "misc.h" |
||
39 |
#include "servconf.h" |
||
40 |
#include "compat.h" |
||
41 |
#include "pathnames.h" |
||
42 |
#include "cipher.h" |
||
43 |
#include "key.h" |
||
44 |
#include "kex.h" |
||
45 |
#include "mac.h" |
||
46 |
#include "match.h" |
||
47 |
#include "channels.h" |
||
48 |
#include "groupaccess.h" |
||
49 |
#include "canohost.h" |
||
50 |
#include "packet.h" |
||
51 |
#include "hostfile.h" |
||
52 |
#include "auth.h" |
||
53 |
#include "myproposal.h" |
||
54 |
#include "digest.h" |
||
55 |
|||
56 |
static void add_listen_addr(ServerOptions *, char *, int); |
||
57 |
static void add_one_listen_addr(ServerOptions *, char *, int); |
||
58 |
|||
59 |
/* Use of privilege separation or not */ |
||
60 |
extern int use_privsep; |
||
61 |
extern Buffer cfg; |
||
62 |
|||
63 |
/* Initializes the server options to their default values. */ |
||
64 |
|||
65 |
void |
||
66 |
initialize_server_options(ServerOptions *options) |
||
67 |
{ |
||
68 |
36 |
memset(options, 0, sizeof(*options)); |
|
69 |
18 |
options->num_ports = 0; |
|
70 |
18 |
options->ports_from_cmdline = 0; |
|
71 |
18 |
options->queued_listen_addrs = NULL; |
|
72 |
18 |
options->num_queued_listens = 0; |
|
73 |
18 |
options->listen_addrs = NULL; |
|
74 |
18 |
options->address_family = -1; |
|
75 |
18 |
options->num_host_key_files = 0; |
|
76 |
18 |
options->num_host_cert_files = 0; |
|
77 |
18 |
options->host_key_agent = NULL; |
|
78 |
18 |
options->pid_file = NULL; |
|
79 |
18 |
options->login_grace_time = -1; |
|
80 |
18 |
options->permit_root_login = PERMIT_NOT_SET; |
|
81 |
18 |
options->ignore_rhosts = -1; |
|
82 |
18 |
options->ignore_user_known_hosts = -1; |
|
83 |
18 |
options->print_motd = -1; |
|
84 |
18 |
options->print_lastlog = -1; |
|
85 |
18 |
options->x11_forwarding = -1; |
|
86 |
18 |
options->x11_display_offset = -1; |
|
87 |
18 |
options->x11_use_localhost = -1; |
|
88 |
18 |
options->permit_tty = -1; |
|
89 |
18 |
options->permit_user_rc = -1; |
|
90 |
18 |
options->xauth_location = NULL; |
|
91 |
18 |
options->strict_modes = -1; |
|
92 |
18 |
options->tcp_keep_alive = -1; |
|
93 |
18 |
options->log_facility = SYSLOG_FACILITY_NOT_SET; |
|
94 |
18 |
options->log_level = SYSLOG_LEVEL_NOT_SET; |
|
95 |
18 |
options->hostbased_authentication = -1; |
|
96 |
18 |
options->hostbased_uses_name_from_packet_only = -1; |
|
97 |
18 |
options->hostbased_key_types = NULL; |
|
98 |
18 |
options->hostkeyalgorithms = NULL; |
|
99 |
18 |
options->pubkey_authentication = -1; |
|
100 |
18 |
options->pubkey_key_types = NULL; |
|
101 |
18 |
options->kerberos_authentication = -1; |
|
102 |
18 |
options->kerberos_or_local_passwd = -1; |
|
103 |
18 |
options->kerberos_ticket_cleanup = -1; |
|
104 |
18 |
options->kerberos_get_afs_token = -1; |
|
105 |
18 |
options->gss_authentication=-1; |
|
106 |
18 |
options->gss_cleanup_creds = -1; |
|
107 |
18 |
options->gss_strict_acceptor = -1; |
|
108 |
18 |
options->password_authentication = -1; |
|
109 |
18 |
options->kbd_interactive_authentication = -1; |
|
110 |
18 |
options->challenge_response_authentication = -1; |
|
111 |
18 |
options->permit_empty_passwd = -1; |
|
112 |
18 |
options->permit_user_env = -1; |
|
113 |
18 |
options->compression = -1; |
|
114 |
18 |
options->rekey_limit = -1; |
|
115 |
18 |
options->rekey_interval = -1; |
|
116 |
18 |
options->allow_tcp_forwarding = -1; |
|
117 |
18 |
options->allow_streamlocal_forwarding = -1; |
|
118 |
18 |
options->allow_agent_forwarding = -1; |
|
119 |
18 |
options->num_allow_users = 0; |
|
120 |
18 |
options->num_deny_users = 0; |
|
121 |
18 |
options->num_allow_groups = 0; |
|
122 |
18 |
options->num_deny_groups = 0; |
|
123 |
18 |
options->ciphers = NULL; |
|
124 |
18 |
options->macs = NULL; |
|
125 |
18 |
options->kex_algorithms = NULL; |
|
126 |
18 |
options->fwd_opts.gateway_ports = -1; |
|
127 |
18 |
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; |
|
128 |
18 |
options->fwd_opts.streamlocal_bind_unlink = -1; |
|
129 |
18 |
options->num_subsystems = 0; |
|
130 |
18 |
options->max_startups_begin = -1; |
|
131 |
18 |
options->max_startups_rate = -1; |
|
132 |
18 |
options->max_startups = -1; |
|
133 |
18 |
options->max_authtries = -1; |
|
134 |
18 |
options->max_sessions = -1; |
|
135 |
18 |
options->banner = NULL; |
|
136 |
18 |
options->use_dns = -1; |
|
137 |
18 |
options->client_alive_interval = -1; |
|
138 |
18 |
options->client_alive_count_max = -1; |
|
139 |
18 |
options->num_authkeys_files = 0; |
|
140 |
18 |
options->num_accept_env = 0; |
|
141 |
18 |
options->permit_tun = -1; |
|
142 |
18 |
options->permitted_opens = NULL; |
|
143 |
18 |
options->adm_forced_command = NULL; |
|
144 |
18 |
options->chroot_directory = NULL; |
|
145 |
18 |
options->authorized_keys_command = NULL; |
|
146 |
18 |
options->authorized_keys_command_user = NULL; |
|
147 |
18 |
options->revoked_keys_file = NULL; |
|
148 |
18 |
options->trusted_user_ca_keys = NULL; |
|
149 |
18 |
options->authorized_principals_file = NULL; |
|
150 |
18 |
options->authorized_principals_command = NULL; |
|
151 |
18 |
options->authorized_principals_command_user = NULL; |
|
152 |
18 |
options->ip_qos_interactive = -1; |
|
153 |
18 |
options->ip_qos_bulk = -1; |
|
154 |
18 |
options->version_addendum = NULL; |
|
155 |
18 |
options->fingerprint_hash = -1; |
|
156 |
18 |
options->disable_forwarding = -1; |
|
157 |
18 |
options->expose_userauth_info = -1; |
|
158 |
18 |
} |
|
159 |
|||
160 |
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ |
||
161 |
static int |
||
162 |
option_clear_or_none(const char *o) |
||
163 |
{ |
||
164 |
✓✓ | 612 |
return o == NULL || strcasecmp(o, "none") == 0; |
165 |
} |
||
166 |
|||
167 |
static void |
||
168 |
assemble_algorithms(ServerOptions *o) |
||
169 |
{ |
||
170 |
✓✗✗✓ |
54 |
if (kex_assemble_names(KEX_SERVER_ENCRYPT, &o->ciphers) != 0 || |
171 |
✓✗ | 18 |
kex_assemble_names(KEX_SERVER_MAC, &o->macs) != 0 || |
172 |
✓✗ | 18 |
kex_assemble_names(KEX_SERVER_KEX, &o->kex_algorithms) != 0 || |
173 |
18 |
kex_assemble_names(KEX_DEFAULT_PK_ALG, |
|
174 |
✓✗ | 36 |
&o->hostkeyalgorithms) != 0 || |
175 |
18 |
kex_assemble_names(KEX_DEFAULT_PK_ALG, |
|
176 |
✓✗ | 36 |
&o->hostbased_key_types) != 0 || |
177 |
18 |
kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->pubkey_key_types) != 0) |
|
178 |
fatal("kex_assemble_names failed"); |
||
179 |
18 |
} |
|
180 |
|||
181 |
void |
||
182 |
fill_default_server_options(ServerOptions *options) |
||
183 |
{ |
||
184 |
int i; |
||
185 |
|||
186 |
✗✓ | 36 |
if (options->num_host_key_files == 0) { |
187 |
/* fill default hostkeys */ |
||
188 |
options->host_key_files[options->num_host_key_files++] = |
||
189 |
_PATH_HOST_RSA_KEY_FILE; |
||
190 |
options->host_key_files[options->num_host_key_files++] = |
||
191 |
_PATH_HOST_DSA_KEY_FILE; |
||
192 |
options->host_key_files[options->num_host_key_files++] = |
||
193 |
_PATH_HOST_ECDSA_KEY_FILE; |
||
194 |
options->host_key_files[options->num_host_key_files++] = |
||
195 |
_PATH_HOST_ED25519_KEY_FILE; |
||
196 |
} |
||
197 |
/* No certificates by default */ |
||
198 |
✗✓ | 18 |
if (options->num_ports == 0) |
199 |
options->ports[options->num_ports++] = SSH_DEFAULT_PORT; |
||
200 |
✗✓ | 18 |
if (options->address_family == -1) |
201 |
options->address_family = AF_UNSPEC; |
||
202 |
✗✓ | 18 |
if (options->listen_addrs == NULL) |
203 |
add_listen_addr(options, NULL, 0); |
||
204 |
✗✓ | 18 |
if (options->pid_file == NULL) |
205 |
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); |
||
206 |
✓✗ | 18 |
if (options->login_grace_time == -1) |
207 |
18 |
options->login_grace_time = 120; |
|
208 |
✓✗ | 18 |
if (options->permit_root_login == PERMIT_NOT_SET) |
209 |
18 |
options->permit_root_login = PERMIT_NO_PASSWD; |
|
210 |
✓✗ | 18 |
if (options->ignore_rhosts == -1) |
211 |
18 |
options->ignore_rhosts = 1; |
|
212 |
✓✗ | 18 |
if (options->ignore_user_known_hosts == -1) |
213 |
18 |
options->ignore_user_known_hosts = 0; |
|
214 |
✓✗ | 18 |
if (options->print_motd == -1) |
215 |
18 |
options->print_motd = 1; |
|
216 |
✓✗ | 18 |
if (options->print_lastlog == -1) |
217 |
18 |
options->print_lastlog = 1; |
|
218 |
✓✗ | 18 |
if (options->x11_forwarding == -1) |
219 |
18 |
options->x11_forwarding = 0; |
|
220 |
✓✗ | 18 |
if (options->x11_display_offset == -1) |
221 |
18 |
options->x11_display_offset = 10; |
|
222 |
✓✗ | 18 |
if (options->x11_use_localhost == -1) |
223 |
18 |
options->x11_use_localhost = 1; |
|
224 |
✓✗ | 18 |
if (options->xauth_location == NULL) |
225 |
18 |
options->xauth_location = xstrdup(_PATH_XAUTH); |
|
226 |
✓✗ | 18 |
if (options->permit_tty == -1) |
227 |
18 |
options->permit_tty = 1; |
|
228 |
✓✗ | 18 |
if (options->permit_user_rc == -1) |
229 |
18 |
options->permit_user_rc = 1; |
|
230 |
✓✓ | 18 |
if (options->strict_modes == -1) |
231 |
12 |
options->strict_modes = 1; |
|
232 |
✓✗ | 18 |
if (options->tcp_keep_alive == -1) |
233 |
18 |
options->tcp_keep_alive = 1; |
|
234 |
✓✗ | 18 |
if (options->log_facility == SYSLOG_FACILITY_NOT_SET) |
235 |
18 |
options->log_facility = SYSLOG_FACILITY_AUTH; |
|
236 |
✗✓ | 18 |
if (options->log_level == SYSLOG_LEVEL_NOT_SET) |
237 |
options->log_level = SYSLOG_LEVEL_INFO; |
||
238 |
✓✗ | 18 |
if (options->hostbased_authentication == -1) |
239 |
18 |
options->hostbased_authentication = 0; |
|
240 |
✓✗ | 18 |
if (options->hostbased_uses_name_from_packet_only == -1) |
241 |
18 |
options->hostbased_uses_name_from_packet_only = 0; |
|
242 |
✓✗ | 18 |
if (options->pubkey_authentication == -1) |
243 |
18 |
options->pubkey_authentication = 1; |
|
244 |
✓✗ | 18 |
if (options->kerberos_authentication == -1) |
245 |
18 |
options->kerberos_authentication = 0; |
|
246 |
✓✗ | 18 |
if (options->kerberos_or_local_passwd == -1) |
247 |
18 |
options->kerberos_or_local_passwd = 1; |
|
248 |
✓✗ | 18 |
if (options->kerberos_ticket_cleanup == -1) |
249 |
18 |
options->kerberos_ticket_cleanup = 1; |
|
250 |
✓✗ | 18 |
if (options->kerberos_get_afs_token == -1) |
251 |
18 |
options->kerberos_get_afs_token = 0; |
|
252 |
✓✗ | 18 |
if (options->gss_authentication == -1) |
253 |
18 |
options->gss_authentication = 0; |
|
254 |
✓✗ | 18 |
if (options->gss_cleanup_creds == -1) |
255 |
18 |
options->gss_cleanup_creds = 1; |
|
256 |
✓✗ | 18 |
if (options->gss_strict_acceptor == -1) |
257 |
18 |
options->gss_strict_acceptor = 1; |
|
258 |
✓✗ | 18 |
if (options->password_authentication == -1) |
259 |
18 |
options->password_authentication = 1; |
|
260 |
✓✗ | 18 |
if (options->kbd_interactive_authentication == -1) |
261 |
18 |
options->kbd_interactive_authentication = 0; |
|
262 |
✓✗ | 18 |
if (options->challenge_response_authentication == -1) |
263 |
18 |
options->challenge_response_authentication = 1; |
|
264 |
✓✗ | 18 |
if (options->permit_empty_passwd == -1) |
265 |
18 |
options->permit_empty_passwd = 0; |
|
266 |
✓✗ | 18 |
if (options->permit_user_env == -1) |
267 |
18 |
options->permit_user_env = 0; |
|
268 |
✓✗ | 18 |
if (options->compression == -1) |
269 |
18 |
options->compression = COMP_DELAYED; |
|
270 |
✓✗ | 18 |
if (options->rekey_limit == -1) |
271 |
18 |
options->rekey_limit = 0; |
|
272 |
✓✗ | 18 |
if (options->rekey_interval == -1) |
273 |
18 |
options->rekey_interval = 0; |
|
274 |
✓✗ | 18 |
if (options->allow_tcp_forwarding == -1) |
275 |
18 |
options->allow_tcp_forwarding = FORWARD_ALLOW; |
|
276 |
✓✗ | 18 |
if (options->allow_streamlocal_forwarding == -1) |
277 |
18 |
options->allow_streamlocal_forwarding = FORWARD_ALLOW; |
|
278 |
✓✗ | 18 |
if (options->allow_agent_forwarding == -1) |
279 |
18 |
options->allow_agent_forwarding = 1; |
|
280 |
✓✗ | 18 |
if (options->fwd_opts.gateway_ports == -1) |
281 |
18 |
options->fwd_opts.gateway_ports = 0; |
|
282 |
✓✗ | 18 |
if (options->max_startups == -1) |
283 |
18 |
options->max_startups = 100; |
|
284 |
✓✗ | 18 |
if (options->max_startups_rate == -1) |
285 |
18 |
options->max_startups_rate = 30; /* 30% */ |
|
286 |
✓✗ | 18 |
if (options->max_startups_begin == -1) |
287 |
18 |
options->max_startups_begin = 10; |
|
288 |
✓✗ | 18 |
if (options->max_authtries == -1) |
289 |
18 |
options->max_authtries = DEFAULT_AUTH_FAIL_MAX; |
|
290 |
✓✗ | 18 |
if (options->max_sessions == -1) |
291 |
18 |
options->max_sessions = DEFAULT_SESSIONS_MAX; |
|
292 |
✓✗ | 18 |
if (options->use_dns == -1) |
293 |
18 |
options->use_dns = 0; |
|
294 |
✓✗ | 18 |
if (options->client_alive_interval == -1) |
295 |
18 |
options->client_alive_interval = 0; |
|
296 |
✓✗ | 18 |
if (options->client_alive_count_max == -1) |
297 |
18 |
options->client_alive_count_max = 3; |
|
298 |
✗✓ | 18 |
if (options->num_authkeys_files == 0) { |
299 |
options->authorized_keys_files[options->num_authkeys_files++] = |
||
300 |
xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); |
||
301 |
options->authorized_keys_files[options->num_authkeys_files++] = |
||
302 |
xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); |
||
303 |
} |
||
304 |
✓✗ | 18 |
if (options->permit_tun == -1) |
305 |
18 |
options->permit_tun = SSH_TUNMODE_NO; |
|
306 |
✓✗ | 18 |
if (options->ip_qos_interactive == -1) |
307 |
18 |
options->ip_qos_interactive = IPTOS_LOWDELAY; |
|
308 |
✓✗ | 18 |
if (options->ip_qos_bulk == -1) |
309 |
18 |
options->ip_qos_bulk = IPTOS_THROUGHPUT; |
|
310 |
✓✗ | 18 |
if (options->version_addendum == NULL) |
311 |
18 |
options->version_addendum = xstrdup(""); |
|
312 |
✓✗ | 18 |
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) |
313 |
18 |
options->fwd_opts.streamlocal_bind_mask = 0177; |
|
314 |
✓✗ | 18 |
if (options->fwd_opts.streamlocal_bind_unlink == -1) |
315 |
18 |
options->fwd_opts.streamlocal_bind_unlink = 0; |
|
316 |
✓✗ | 18 |
if (options->fingerprint_hash == -1) |
317 |
18 |
options->fingerprint_hash = SSH_FP_HASH_DEFAULT; |
|
318 |
✓✗ | 18 |
if (options->disable_forwarding == -1) |
319 |
18 |
options->disable_forwarding = 0; |
|
320 |
✓✗ | 18 |
if (options->expose_userauth_info == -1) |
321 |
18 |
options->expose_userauth_info = 0; |
|
322 |
|||
323 |
18 |
assemble_algorithms(options); |
|
324 |
|||
325 |
/* Turn privilege separation and sandboxing on by default */ |
||
326 |
✓✗ | 18 |
if (use_privsep == -1) |
327 |
18 |
use_privsep = PRIVSEP_ON; |
|
328 |
|||
329 |
#define CLEAR_ON_NONE(v) \ |
||
330 |
do { \ |
||
331 |
if (option_clear_or_none(v)) { \ |
||
332 |
free(v); \ |
||
333 |
v = NULL; \ |
||
334 |
} \ |
||
335 |
} while(0) |
||
336 |
✗✓ | 18 |
CLEAR_ON_NONE(options->pid_file); |
337 |
✗✓ | 18 |
CLEAR_ON_NONE(options->xauth_location); |
338 |
✓✗ | 36 |
CLEAR_ON_NONE(options->banner); |
339 |
✓✗ | 36 |
CLEAR_ON_NONE(options->trusted_user_ca_keys); |
340 |
✓✗ | 36 |
CLEAR_ON_NONE(options->revoked_keys_file); |
341 |
✓✗ | 36 |
CLEAR_ON_NONE(options->authorized_principals_file); |
342 |
✓✗ | 36 |
CLEAR_ON_NONE(options->adm_forced_command); |
343 |
✓✗ | 36 |
CLEAR_ON_NONE(options->chroot_directory); |
344 |
✓✓ | 108 |
for (i = 0; i < options->num_host_key_files; i++) |
345 |
✗✓ | 36 |
CLEAR_ON_NONE(options->host_key_files[i]); |
346 |
✗✓ | 36 |
for (i = 0; i < options->num_host_cert_files; i++) |
347 |
CLEAR_ON_NONE(options->host_cert_files[i]); |
||
348 |
#undef CLEAR_ON_NONE |
||
349 |
|||
350 |
/* Similar handling for AuthenticationMethods=any */ |
||
351 |
✗✓✗✗ |
18 |
if (options->num_auth_methods == 1 && |
352 |
strcmp(options->auth_methods[0], "any") == 0) { |
||
353 |
free(options->auth_methods[0]); |
||
354 |
options->auth_methods[0] = NULL; |
||
355 |
options->num_auth_methods = 0; |
||
356 |
} |
||
357 |
|||
358 |
18 |
} |
|
359 |
|||
360 |
/* Keyword tokens. */ |
||
361 |
typedef enum { |
||
362 |
sBadOption, /* == unknown option */ |
||
363 |
sPort, sHostKeyFile, sLoginGraceTime, |
||
364 |
sPermitRootLogin, sLogFacility, sLogLevel, |
||
365 |
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, |
||
366 |
sKerberosGetAFSToken, |
||
367 |
sKerberosTgtPassing, sChallengeResponseAuthentication, |
||
368 |
sPasswordAuthentication, sKbdInteractiveAuthentication, |
||
369 |
sListenAddress, sAddressFamily, |
||
370 |
sPrintMotd, sPrintLastLog, sIgnoreRhosts, |
||
371 |
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, |
||
372 |
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, |
||
373 |
sPermitUserEnvironment, sAllowTcpForwarding, sCompression, |
||
374 |
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, |
||
375 |
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, |
||
376 |
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, |
||
377 |
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, |
||
378 |
sBanner, sUseDNS, sHostbasedAuthentication, |
||
379 |
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, |
||
380 |
sHostKeyAlgorithms, |
||
381 |
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, |
||
382 |
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, |
||
383 |
sAcceptEnv, sPermitTunnel, |
||
384 |
sMatch, sPermitOpen, sForceCommand, sChrootDirectory, |
||
385 |
sUsePrivilegeSeparation, sAllowAgentForwarding, |
||
386 |
sHostCertificate, |
||
387 |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
||
388 |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
||
389 |
sKexAlgorithms, sIPQoS, sVersionAddendum, |
||
390 |
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
||
391 |
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, |
||
392 |
sStreamLocalBindMask, sStreamLocalBindUnlink, |
||
393 |
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, |
||
394 |
sExposeAuthInfo, |
||
395 |
sDeprecated, sIgnore, sUnsupported |
||
396 |
} ServerOpCodes; |
||
397 |
|||
398 |
#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ |
||
399 |
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ |
||
400 |
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) |
||
401 |
|||
402 |
/* Textual representation of the tokens. */ |
||
403 |
static struct { |
||
404 |
const char *name; |
||
405 |
ServerOpCodes opcode; |
||
406 |
u_int flags; |
||
407 |
} keywords[] = { |
||
408 |
{ "port", sPort, SSHCFG_GLOBAL }, |
||
409 |
{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, |
||
410 |
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ |
||
411 |
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, |
||
412 |
{ "pidfile", sPidFile, SSHCFG_GLOBAL }, |
||
413 |
{ "serverkeybits", sDeprecated, SSHCFG_GLOBAL }, |
||
414 |
{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, |
||
415 |
{ "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, |
||
416 |
{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, |
||
417 |
{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, |
||
418 |
{ "loglevel", sLogLevel, SSHCFG_ALL }, |
||
419 |
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, |
||
420 |
{ "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, |
||
421 |
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, |
||
422 |
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, |
||
423 |
{ "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL }, |
||
424 |
{ "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, |
||
425 |
{ "rsaauthentication", sDeprecated, SSHCFG_ALL }, |
||
426 |
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, |
||
427 |
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, |
||
428 |
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ |
||
429 |
#ifdef KRB5 |
||
430 |
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, |
||
431 |
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, |
||
432 |
{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, |
||
433 |
{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, |
||
434 |
#else |
||
435 |
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL }, |
||
436 |
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, |
||
437 |
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, |
||
438 |
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, |
||
439 |
#endif |
||
440 |
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, |
||
441 |
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, |
||
442 |
#ifdef GSSAPI |
||
443 |
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, |
||
444 |
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, |
||
445 |
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, |
||
446 |
#else |
||
447 |
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL }, |
||
448 |
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, |
||
449 |
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, |
||
450 |
#endif |
||
451 |
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, |
||
452 |
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, |
||
453 |
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, |
||
454 |
{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ |
||
455 |
{ "checkmail", sDeprecated, SSHCFG_GLOBAL }, |
||
456 |
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL }, |
||
457 |
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, |
||
458 |
{ "printmotd", sPrintMotd, SSHCFG_GLOBAL }, |
||
459 |
{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, |
||
460 |
{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, |
||
461 |
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, |
||
462 |
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL }, |
||
463 |
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, |
||
464 |
{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, |
||
465 |
{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, |
||
466 |
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL }, |
||
467 |
{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, |
||
468 |
{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, |
||
469 |
{ "uselogin", sDeprecated, SSHCFG_GLOBAL }, |
||
470 |
{ "compression", sCompression, SSHCFG_GLOBAL }, |
||
471 |
{ "rekeylimit", sRekeyLimit, SSHCFG_ALL }, |
||
472 |
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, |
||
473 |
{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ |
||
474 |
{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, |
||
475 |
{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, |
||
476 |
{ "allowusers", sAllowUsers, SSHCFG_ALL }, |
||
477 |
{ "denyusers", sDenyUsers, SSHCFG_ALL }, |
||
478 |
{ "allowgroups", sAllowGroups, SSHCFG_ALL }, |
||
479 |
{ "denygroups", sDenyGroups, SSHCFG_ALL }, |
||
480 |
{ "ciphers", sCiphers, SSHCFG_GLOBAL }, |
||
481 |
{ "macs", sMacs, SSHCFG_GLOBAL }, |
||
482 |
{ "protocol", sIgnore, SSHCFG_GLOBAL }, |
||
483 |
{ "gatewayports", sGatewayPorts, SSHCFG_ALL }, |
||
484 |
{ "subsystem", sSubsystem, SSHCFG_GLOBAL }, |
||
485 |
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, |
||
486 |
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, |
||
487 |
{ "maxsessions", sMaxSessions, SSHCFG_ALL }, |
||
488 |
{ "banner", sBanner, SSHCFG_ALL }, |
||
489 |
{ "usedns", sUseDNS, SSHCFG_GLOBAL }, |
||
490 |
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, |
||
491 |
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, |
||
492 |
{ "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL }, |
||
493 |
{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, |
||
494 |
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, |
||
495 |
{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, |
||
496 |
{ "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, |
||
497 |
{ "acceptenv", sAcceptEnv, SSHCFG_ALL }, |
||
498 |
{ "permittunnel", sPermitTunnel, SSHCFG_ALL }, |
||
499 |
{ "permittty", sPermitTTY, SSHCFG_ALL }, |
||
500 |
{ "permituserrc", sPermitUserRC, SSHCFG_ALL }, |
||
501 |
{ "match", sMatch, SSHCFG_ALL }, |
||
502 |
{ "permitopen", sPermitOpen, SSHCFG_ALL }, |
||
503 |
{ "forcecommand", sForceCommand, SSHCFG_ALL }, |
||
504 |
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, |
||
505 |
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, |
||
506 |
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL }, |
||
507 |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
||
508 |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
||
509 |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
||
510 |
{ "ipqos", sIPQoS, SSHCFG_ALL }, |
||
511 |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
||
512 |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
||
513 |
{ "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, |
||
514 |
{ "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, |
||
515 |
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, |
||
516 |
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, |
||
517 |
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, |
||
518 |
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, |
||
519 |
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, |
||
520 |
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, |
||
521 |
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL }, |
||
522 |
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, |
||
523 |
{ NULL, sBadOption, 0 } |
||
524 |
}; |
||
525 |
|||
526 |
static struct { |
||
527 |
int val; |
||
528 |
char *text; |
||
529 |
} tunmode_desc[] = { |
||
530 |
{ SSH_TUNMODE_NO, "no" }, |
||
531 |
{ SSH_TUNMODE_POINTOPOINT, "point-to-point" }, |
||
532 |
{ SSH_TUNMODE_ETHERNET, "ethernet" }, |
||
533 |
{ SSH_TUNMODE_YES, "yes" }, |
||
534 |
{ -1, NULL } |
||
535 |
}; |
||
536 |
|||
537 |
/* |
||
538 |
* Returns the number of the token pointed to by cp or sBadOption. |
||
539 |
*/ |
||
540 |
|||
541 |
static ServerOpCodes |
||
542 |
parse_token(const char *cp, const char *filename, |
||
543 |
int linenum, u_int *flags) |
||
544 |
{ |
||
545 |
u_int i; |
||
546 |
|||
547 |
✓✗ | 14652 |
for (i = 0; keywords[i].name; i++) |
548 |
✓✓ | 7224 |
if (strcasecmp(cp, keywords[i].name) == 0) { |
549 |
204 |
*flags = keywords[i].flags; |
|
550 |
204 |
return keywords[i].opcode; |
|
551 |
} |
||
552 |
|||
553 |
error("%s: line %d: Bad configuration option: %s", |
||
554 |
filename, linenum, cp); |
||
555 |
return sBadOption; |
||
556 |
204 |
} |
|
557 |
|||
558 |
char * |
||
559 |
derelativise_path(const char *path) |
||
560 |
{ |
||
561 |
108 |
char *expanded, *ret, cwd[PATH_MAX]; |
|
562 |
|||
563 |
✗✓ | 54 |
if (strcasecmp(path, "none") == 0) |
564 |
return xstrdup("none"); |
||
565 |
54 |
expanded = tilde_expand_filename(path, getuid()); |
|
566 |
✓✗ | 54 |
if (*expanded == '/') |
567 |
54 |
return expanded; |
|
568 |
if (getcwd(cwd, sizeof(cwd)) == NULL) |
||
569 |
fatal("%s: getcwd: %s", __func__, strerror(errno)); |
||
570 |
xasprintf(&ret, "%s/%s", cwd, expanded); |
||
571 |
free(expanded); |
||
572 |
return ret; |
||
573 |
54 |
} |
|
574 |
|||
575 |
static void |
||
576 |
add_listen_addr(ServerOptions *options, char *addr, int port) |
||
577 |
{ |
||
578 |
u_int i; |
||
579 |
|||
580 |
✓✗ | 36 |
if (port == 0) |
581 |
✓✓ | 72 |
for (i = 0; i < options->num_ports; i++) |
582 |
18 |
add_one_listen_addr(options, addr, options->ports[i]); |
|
583 |
else |
||
584 |
add_one_listen_addr(options, addr, port); |
||
585 |
18 |
} |
|
586 |
|||
587 |
static void |
||
588 |
add_one_listen_addr(ServerOptions *options, char *addr, int port) |
||
589 |
{ |
||
590 |
36 |
struct addrinfo hints, *ai, *aitop; |
|
591 |
18 |
char strport[NI_MAXSERV]; |
|
592 |
int gaierr; |
||
593 |
|||
594 |
18 |
memset(&hints, 0, sizeof(hints)); |
|
595 |
18 |
hints.ai_family = options->address_family; |
|
596 |
18 |
hints.ai_socktype = SOCK_STREAM; |
|
597 |
18 |
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; |
|
598 |
18 |
snprintf(strport, sizeof strport, "%d", port); |
|
599 |
✗✓ | 18 |
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) |
600 |
fatal("bad addr or host: %s (%s)", |
||
601 |
addr ? addr : "<NULL>", |
||
602 |
ssh_gai_strerror(gaierr)); |
||
603 |
✗✓ | 36 |
for (ai = aitop; ai->ai_next; ai = ai->ai_next) |
604 |
; |
||
605 |
18 |
ai->ai_next = options->listen_addrs; |
|
606 |
18 |
options->listen_addrs = aitop; |
|
607 |
18 |
} |
|
608 |
|||
609 |
/* |
||
610 |
* Queue a ListenAddress to be processed once we have all of the Ports |
||
611 |
* and AddressFamily options. |
||
612 |
*/ |
||
613 |
static void |
||
614 |
queue_listen_addr(ServerOptions *options, char *addr, int port) |
||
615 |
{ |
||
616 |
18 |
options->queued_listen_addrs = xreallocarray( |
|
617 |
36 |
options->queued_listen_addrs, options->num_queued_listens + 1, |
|
618 |
sizeof(addr)); |
||
619 |
18 |
options->queued_listen_ports = xreallocarray( |
|
620 |
18 |
options->queued_listen_ports, options->num_queued_listens + 1, |
|
621 |
sizeof(port)); |
||
622 |
18 |
options->queued_listen_addrs[options->num_queued_listens] = |
|
623 |
18 |
xstrdup(addr); |
|
624 |
18 |
options->queued_listen_ports[options->num_queued_listens] = port; |
|
625 |
18 |
options->num_queued_listens++; |
|
626 |
18 |
} |
|
627 |
|||
628 |
/* |
||
629 |
* Process queued (text) ListenAddress entries. |
||
630 |
*/ |
||
631 |
static void |
||
632 |
process_queued_listen_addrs(ServerOptions *options) |
||
633 |
{ |
||
634 |
u_int i; |
||
635 |
|||
636 |
✗✓ | 36 |
if (options->num_ports == 0) |
637 |
options->ports[options->num_ports++] = SSH_DEFAULT_PORT; |
||
638 |
✗✓ | 18 |
if (options->address_family == -1) |
639 |
options->address_family = AF_UNSPEC; |
||
640 |
|||
641 |
✓✓ | 72 |
for (i = 0; i < options->num_queued_listens; i++) { |
642 |
36 |
add_listen_addr(options, options->queued_listen_addrs[i], |
|
643 |
18 |
options->queued_listen_ports[i]); |
|
644 |
18 |
free(options->queued_listen_addrs[i]); |
|
645 |
18 |
options->queued_listen_addrs[i] = NULL; |
|
646 |
} |
||
647 |
18 |
free(options->queued_listen_addrs); |
|
648 |
18 |
options->queued_listen_addrs = NULL; |
|
649 |
18 |
free(options->queued_listen_ports); |
|
650 |
18 |
options->queued_listen_ports = NULL; |
|
651 |
18 |
options->num_queued_listens = 0; |
|
652 |
18 |
} |
|
653 |
|||
654 |
/* |
||
655 |
* Inform channels layer of permitopen options from configuration. |
||
656 |
*/ |
||
657 |
void |
||
658 |
process_permitopen(struct ssh *ssh, ServerOptions *options) |
||
659 |
{ |
||
660 |
u_int i; |
||
661 |
int port; |
||
662 |
char *host, *arg, *oarg; |
||
663 |
|||
664 |
channel_clear_adm_permitted_opens(ssh); |
||
665 |
if (options->num_permitted_opens == 0) |
||
666 |
return; /* permit any */ |
||
667 |
|||
668 |
/* handle keywords: "any" / "none" */ |
||
669 |
if (options->num_permitted_opens == 1 && |
||
670 |
strcmp(options->permitted_opens[0], "any") == 0) |
||
671 |
return; |
||
672 |
if (options->num_permitted_opens == 1 && |
||
673 |
strcmp(options->permitted_opens[0], "none") == 0) { |
||
674 |
channel_disable_adm_local_opens(ssh); |
||
675 |
return; |
||
676 |
} |
||
677 |
/* Otherwise treat it as a list of permitted host:port */ |
||
678 |
for (i = 0; i < options->num_permitted_opens; i++) { |
||
679 |
oarg = arg = xstrdup(options->permitted_opens[i]); |
||
680 |
host = hpdelim(&arg); |
||
681 |
if (host == NULL) |
||
682 |
fatal("%s: missing host in PermitOpen", __func__); |
||
683 |
host = cleanhostname(host); |
||
684 |
if (arg == NULL || ((port = permitopen_port(arg)) < 0)) |
||
685 |
fatal("%s: bad port number in PermitOpen", __func__); |
||
686 |
/* Send it to channels layer */ |
||
687 |
channel_add_adm_permitted_opens(ssh, host, port); |
||
688 |
free(oarg); |
||
689 |
} |
||
690 |
} |
||
691 |
|||
692 |
struct connection_info * |
||
693 |
get_connection_info(int populate, int use_dns) |
||
694 |
{ |
||
695 |
36 |
struct ssh *ssh = active_state; /* XXX */ |
|
696 |
static struct connection_info ci; |
||
697 |
|||
698 |
✓✗ | 18 |
if (!populate) |
699 |
18 |
return &ci; |
|
700 |
ci.host = auth_get_canonical_hostname(ssh, use_dns); |
||
701 |
ci.address = ssh_remote_ipaddr(ssh); |
||
702 |
ci.laddress = ssh_local_ipaddr(ssh); |
||
703 |
ci.lport = ssh_local_port(ssh); |
||
704 |
return &ci; |
||
705 |
18 |
} |
|
706 |
|||
707 |
/* |
||
708 |
* The strategy for the Match blocks is that the config file is parsed twice. |
||
709 |
* |
||
710 |
* The first time is at startup. activep is initialized to 1 and the |
||
711 |
* directives in the global context are processed and acted on. Hitting a |
||
712 |
* Match directive unsets activep and the directives inside the block are |
||
713 |
* checked for syntax only. |
||
714 |
* |
||
715 |
* The second time is after a connection has been established but before |
||
716 |
* authentication. activep is initialized to 2 and global config directives |
||
717 |
* are ignored since they have already been processed. If the criteria in a |
||
718 |
* Match block is met, activep is set and the subsequent directives |
||
719 |
* processed and actioned until EOF or another Match block unsets it. Any |
||
720 |
* options set are copied into the main server config. |
||
721 |
* |
||
722 |
* Potential additions/improvements: |
||
723 |
* - Add Match support for pre-kex directives, eg. Ciphers. |
||
724 |
* |
||
725 |
* - Add a Tag directive (idea from David Leonard) ala pf, eg: |
||
726 |
* Match Address 192.168.0.* |
||
727 |
* Tag trusted |
||
728 |
* Match Group wheel |
||
729 |
* Tag trusted |
||
730 |
* Match Tag trusted |
||
731 |
* AllowTcpForwarding yes |
||
732 |
* GatewayPorts clientspecified |
||
733 |
* [...] |
||
734 |
* |
||
735 |
* - Add a PermittedChannelRequests directive |
||
736 |
* Match Group shell |
||
737 |
* PermittedChannelRequests session,forwarded-tcpip |
||
738 |
*/ |
||
739 |
|||
740 |
static int |
||
741 |
match_cfg_line_group(const char *grps, int line, const char *user) |
||
742 |
{ |
||
743 |
int result = 0; |
||
744 |
struct passwd *pw; |
||
745 |
|||
746 |
if (user == NULL) |
||
747 |
goto out; |
||
748 |
|||
749 |
if ((pw = getpwnam(user)) == NULL) { |
||
750 |
debug("Can't match group at line %d because user %.100s does " |
||
751 |
"not exist", line, user); |
||
752 |
} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { |
||
753 |
debug("Can't Match group because user %.100s not in any group " |
||
754 |
"at line %d", user, line); |
||
755 |
} else if (ga_match_pattern_list(grps) != 1) { |
||
756 |
debug("user %.100s does not match group list %.100s at line %d", |
||
757 |
user, grps, line); |
||
758 |
} else { |
||
759 |
debug("user %.100s matched group list %.100s at line %d", user, |
||
760 |
grps, line); |
||
761 |
result = 1; |
||
762 |
} |
||
763 |
out: |
||
764 |
ga_free(); |
||
765 |
return result; |
||
766 |
} |
||
767 |
|||
768 |
/* |
||
769 |
* All of the attributes on a single Match line are ANDed together, so we need |
||
770 |
* to check every attribute and set the result to zero if any attribute does |
||
771 |
* not match. |
||
772 |
*/ |
||
773 |
static int |
||
774 |
match_cfg_line(char **condition, int line, struct connection_info *ci) |
||
775 |
{ |
||
776 |
int result = 1, attributes = 0, port; |
||
777 |
char *arg, *attrib, *cp = *condition; |
||
778 |
|||
779 |
if (ci == NULL) |
||
780 |
debug3("checking syntax for 'Match %s'", cp); |
||
781 |
else |
||
782 |
debug3("checking match for '%s' user %s host %s addr %s " |
||
783 |
"laddr %s lport %d", cp, ci->user ? ci->user : "(null)", |
||
784 |
ci->host ? ci->host : "(null)", |
||
785 |
ci->address ? ci->address : "(null)", |
||
786 |
ci->laddress ? ci->laddress : "(null)", ci->lport); |
||
787 |
|||
788 |
while ((attrib = strdelim(&cp)) && *attrib != '\0') { |
||
789 |
attributes++; |
||
790 |
if (strcasecmp(attrib, "all") == 0) { |
||
791 |
if (attributes != 1 || |
||
792 |
((arg = strdelim(&cp)) != NULL && *arg != '\0')) { |
||
793 |
error("'all' cannot be combined with other " |
||
794 |
"Match attributes"); |
||
795 |
return -1; |
||
796 |
} |
||
797 |
*condition = cp; |
||
798 |
return 1; |
||
799 |
} |
||
800 |
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { |
||
801 |
error("Missing Match criteria for %s", attrib); |
||
802 |
return -1; |
||
803 |
} |
||
804 |
if (strcasecmp(attrib, "user") == 0) { |
||
805 |
if (ci == NULL || ci->user == NULL) { |
||
806 |
result = 0; |
||
807 |
continue; |
||
808 |
} |
||
809 |
if (match_pattern_list(ci->user, arg, 0) != 1) |
||
810 |
result = 0; |
||
811 |
else |
||
812 |
debug("user %.100s matched 'User %.100s' at " |
||
813 |
"line %d", ci->user, arg, line); |
||
814 |
} else if (strcasecmp(attrib, "group") == 0) { |
||
815 |
if (ci == NULL || ci->user == NULL) { |
||
816 |
result = 0; |
||
817 |
continue; |
||
818 |
} |
||
819 |
switch (match_cfg_line_group(arg, line, ci->user)) { |
||
820 |
case -1: |
||
821 |
return -1; |
||
822 |
case 0: |
||
823 |
result = 0; |
||
824 |
} |
||
825 |
} else if (strcasecmp(attrib, "host") == 0) { |
||
826 |
if (ci == NULL || ci->host == NULL) { |
||
827 |
result = 0; |
||
828 |
continue; |
||
829 |
} |
||
830 |
if (match_hostname(ci->host, arg) != 1) |
||
831 |
result = 0; |
||
832 |
else |
||
833 |
debug("connection from %.100s matched 'Host " |
||
834 |
"%.100s' at line %d", ci->host, arg, line); |
||
835 |
} else if (strcasecmp(attrib, "address") == 0) { |
||
836 |
if (ci == NULL || ci->address == NULL) { |
||
837 |
result = 0; |
||
838 |
continue; |
||
839 |
} |
||
840 |
switch (addr_match_list(ci->address, arg)) { |
||
841 |
case 1: |
||
842 |
debug("connection from %.100s matched 'Address " |
||
843 |
"%.100s' at line %d", ci->address, arg, line); |
||
844 |
break; |
||
845 |
case 0: |
||
846 |
case -1: |
||
847 |
result = 0; |
||
848 |
break; |
||
849 |
case -2: |
||
850 |
return -1; |
||
851 |
} |
||
852 |
} else if (strcasecmp(attrib, "localaddress") == 0){ |
||
853 |
if (ci == NULL || ci->laddress == NULL) { |
||
854 |
result = 0; |
||
855 |
continue; |
||
856 |
} |
||
857 |
switch (addr_match_list(ci->laddress, arg)) { |
||
858 |
case 1: |
||
859 |
debug("connection from %.100s matched " |
||
860 |
"'LocalAddress %.100s' at line %d", |
||
861 |
ci->laddress, arg, line); |
||
862 |
break; |
||
863 |
case 0: |
||
864 |
case -1: |
||
865 |
result = 0; |
||
866 |
break; |
||
867 |
case -2: |
||
868 |
return -1; |
||
869 |
} |
||
870 |
} else if (strcasecmp(attrib, "localport") == 0) { |
||
871 |
if ((port = a2port(arg)) == -1) { |
||
872 |
error("Invalid LocalPort '%s' on Match line", |
||
873 |
arg); |
||
874 |
return -1; |
||
875 |
} |
||
876 |
if (ci == NULL || ci->lport == 0) { |
||
877 |
result = 0; |
||
878 |
continue; |
||
879 |
} |
||
880 |
/* TODO support port lists */ |
||
881 |
if (port == ci->lport) |
||
882 |
debug("connection from %.100s matched " |
||
883 |
"'LocalPort %d' at line %d", |
||
884 |
ci->laddress, port, line); |
||
885 |
else |
||
886 |
result = 0; |
||
887 |
} else { |
||
888 |
error("Unsupported Match attribute %s", attrib); |
||
889 |
return -1; |
||
890 |
} |
||
891 |
} |
||
892 |
if (attributes == 0) { |
||
893 |
error("One or more attributes required for Match"); |
||
894 |
return -1; |
||
895 |
} |
||
896 |
if (ci != NULL) |
||
897 |
debug3("match %sfound", result ? "" : "not "); |
||
898 |
*condition = cp; |
||
899 |
return result; |
||
900 |
} |
||
901 |
|||
902 |
#define WHITESPACE " \t\r\n" |
||
903 |
|||
904 |
/* Multistate option parsing */ |
||
905 |
struct multistate { |
||
906 |
char *key; |
||
907 |
int value; |
||
908 |
}; |
||
909 |
static const struct multistate multistate_addressfamily[] = { |
||
910 |
{ "inet", AF_INET }, |
||
911 |
{ "inet6", AF_INET6 }, |
||
912 |
{ "any", AF_UNSPEC }, |
||
913 |
{ NULL, -1 } |
||
914 |
}; |
||
915 |
static const struct multistate multistate_permitrootlogin[] = { |
||
916 |
{ "without-password", PERMIT_NO_PASSWD }, |
||
917 |
{ "prohibit-password", PERMIT_NO_PASSWD }, |
||
918 |
{ "forced-commands-only", PERMIT_FORCED_ONLY }, |
||
919 |
{ "yes", PERMIT_YES }, |
||
920 |
{ "no", PERMIT_NO }, |
||
921 |
{ NULL, -1 } |
||
922 |
}; |
||
923 |
static const struct multistate multistate_compression[] = { |
||
924 |
{ "yes", COMP_DELAYED }, |
||
925 |
{ "delayed", COMP_DELAYED }, |
||
926 |
{ "no", COMP_NONE }, |
||
927 |
{ NULL, -1 } |
||
928 |
}; |
||
929 |
static const struct multistate multistate_gatewayports[] = { |
||
930 |
{ "clientspecified", 2 }, |
||
931 |
{ "yes", 1 }, |
||
932 |
{ "no", 0 }, |
||
933 |
{ NULL, -1 } |
||
934 |
}; |
||
935 |
static const struct multistate multistate_tcpfwd[] = { |
||
936 |
{ "yes", FORWARD_ALLOW }, |
||
937 |
{ "all", FORWARD_ALLOW }, |
||
938 |
{ "no", FORWARD_DENY }, |
||
939 |
{ "remote", FORWARD_REMOTE }, |
||
940 |
{ "local", FORWARD_LOCAL }, |
||
941 |
{ NULL, -1 } |
||
942 |
}; |
||
943 |
|||
944 |
int |
||
945 |
process_server_config_line(ServerOptions *options, char *line, |
||
946 |
const char *filename, int linenum, int *activep, |
||
947 |
struct connection_info *connectinfo) |
||
948 |
{ |
||
949 |
480 |
char *cp, **charptr, *arg, *arg2, *p; |
|
950 |
240 |
int cmdline = 0, *intptr, value, value2, n, port; |
|
951 |
SyslogFacility *log_facility_ptr; |
||
952 |
LogLevel *log_level_ptr; |
||
953 |
ServerOpCodes opcode; |
||
954 |
240 |
u_int i, flags = 0; |
|
955 |
size_t len; |
||
956 |
240 |
long long val64; |
|
957 |
const struct multistate *multistate_ptr; |
||
958 |
|||
959 |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */ |
||
960 |
✓✓ | 240 |
if ((len = strlen(line)) == 0) |
961 |
36 |
return 0; |
|
962 |
✓✗ | 408 |
for (len--; len > 0; len--) { |
963 |
✗✓ | 204 |
if (strchr(WHITESPACE "\f", line[len]) == NULL) |
964 |
break; |
||
965 |
line[len] = '\0'; |
||
966 |
} |
||
967 |
|||
968 |
204 |
cp = line; |
|
969 |
✗✓ | 204 |
if ((arg = strdelim(&cp)) == NULL) |
970 |
return 0; |
||
971 |
/* Ignore leading whitespace */ |
||
972 |
✗✓ | 204 |
if (*arg == '\0') |
973 |
arg = strdelim(&cp); |
||
974 |
✓✗✓✗ ✗✓ |
612 |
if (!arg || !*arg || *arg == '#') |
975 |
return 0; |
||
976 |
intptr = NULL; |
||
977 |
charptr = NULL; |
||
978 |
204 |
opcode = parse_token(arg, filename, linenum, &flags); |
|
979 |
|||
980 |
✗✓ | 204 |
if (activep == NULL) { /* We are processing a command line directive */ |
981 |
cmdline = 1; |
||
982 |
activep = &cmdline; |
||
983 |
} |
||
984 |
✓✗ | 204 |
if (*activep && opcode != sMatch) |
985 |
204 |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
|
986 |
✗✓✗✗ |
204 |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
987 |
if (connectinfo == NULL) { |
||
988 |
fatal("%s line %d: Directive '%s' is not allowed " |
||
989 |
"within a Match block", filename, linenum, arg); |
||
990 |
} else { /* this is a directive we have already processed */ |
||
991 |
while (arg) |
||
992 |
arg = strdelim(&cp); |
||
993 |
return 0; |
||
994 |
} |
||
995 |
} |
||
996 |
|||
997 |
✗✓✗✓ ✓✓✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✓✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗ |
240 |
switch (opcode) { |
998 |
case sBadOption: |
||
999 |
return -1; |
||
1000 |
case sPort: |
||
1001 |
/* ignore ports from configfile if cmdline specifies ports */ |
||
1002 |
✗✓ | 18 |
if (options->ports_from_cmdline) |
1003 |
return 0; |
||
1004 |
✗✓ | 18 |
if (options->num_ports >= MAX_PORTS) |
1005 |
fatal("%s line %d: too many ports.", |
||
1006 |
filename, linenum); |
||
1007 |
18 |
arg = strdelim(&cp); |
|
1008 |
✓✗✗✓ |
36 |
if (!arg || *arg == '\0') |
1009 |
fatal("%s line %d: missing port number.", |
||
1010 |
filename, linenum); |
||
1011 |
18 |
options->ports[options->num_ports++] = a2port(arg); |
|
1012 |
✗✓ | 18 |
if (options->ports[options->num_ports-1] <= 0) |
1013 |
fatal("%s line %d: Badly formatted port number.", |
||
1014 |
filename, linenum); |
||
1015 |
break; |
||
1016 |
|||
1017 |
case sLoginGraceTime: |
||
1018 |
intptr = &options->login_grace_time; |
||
1019 |
parse_time: |
||
1020 |
arg = strdelim(&cp); |
||
1021 |
if (!arg || *arg == '\0') |
||
1022 |
fatal("%s line %d: missing time value.", |
||
1023 |
filename, linenum); |
||
1024 |
if ((value = convtime(arg)) == -1) |
||
1025 |
fatal("%s line %d: invalid time value.", |
||
1026 |
filename, linenum); |
||
1027 |
if (*activep && *intptr == -1) |
||
1028 |
*intptr = value; |
||
1029 |
break; |
||
1030 |
|||
1031 |
case sListenAddress: |
||
1032 |
18 |
arg = strdelim(&cp); |
|
1033 |
✓✗✗✓ |
36 |
if (arg == NULL || *arg == '\0') |
1034 |
fatal("%s line %d: missing address", |
||
1035 |
filename, linenum); |
||
1036 |
/* check for bare IPv6 address: no "[]" and 2 or more ":" */ |
||
1037 |
✓✗✗✗ |
36 |
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL |
1038 |
✗✓ | 18 |
&& strchr(p+1, ':') != NULL) { |
1039 |
queue_listen_addr(options, arg, 0); |
||
1040 |
break; |
||
1041 |
} |
||
1042 |
18 |
p = hpdelim(&arg); |
|
1043 |
✗✓ | 18 |
if (p == NULL) |
1044 |
fatal("%s line %d: bad address:port usage", |
||
1045 |
filename, linenum); |
||
1046 |
18 |
p = cleanhostname(p); |
|
1047 |
✓✗ | 18 |
if (arg == NULL) |
1048 |
18 |
port = 0; |
|
1049 |
else if ((port = a2port(arg)) <= 0) |
||
1050 |
fatal("%s line %d: bad port number", filename, linenum); |
||
1051 |
|||
1052 |
18 |
queue_listen_addr(options, p, port); |
|
1053 |
|||
1054 |
18 |
break; |
|
1055 |
|||
1056 |
case sAddressFamily: |
||
1057 |
18 |
intptr = &options->address_family; |
|
1058 |
18 |
multistate_ptr = multistate_addressfamily; |
|
1059 |
parse_multistate: |
||
1060 |
18 |
arg = strdelim(&cp); |
|
1061 |
✓✗✗✓ |
36 |
if (!arg || *arg == '\0') |
1062 |
fatal("%s line %d: missing argument.", |
||
1063 |
filename, linenum); |
||
1064 |
value = -1; |
||
1065 |
✓✗ | 36 |
for (i = 0; multistate_ptr[i].key != NULL; i++) { |
1066 |
✓✗ | 18 |
if (strcasecmp(arg, multistate_ptr[i].key) == 0) { |
1067 |
18 |
value = multistate_ptr[i].value; |
|
1068 |
18 |
break; |
|
1069 |
} |
||
1070 |
} |
||
1071 |
✗✓ | 18 |
if (value == -1) |
1072 |
fatal("%s line %d: unsupported option \"%s\".", |
||
1073 |
filename, linenum, arg); |
||
1074 |
✓✗✓✗ |
36 |
if (*activep && *intptr == -1) |
1075 |
18 |
*intptr = value; |
|
1076 |
break; |
||
1077 |
|||
1078 |
case sHostKeyFile: |
||
1079 |
36 |
intptr = &options->num_host_key_files; |
|
1080 |
✗✓ | 36 |
if (*intptr >= MAX_HOSTKEYS) |
1081 |
fatal("%s line %d: too many host keys specified (max %d).", |
||
1082 |
filename, linenum, MAX_HOSTKEYS); |
||
1083 |
36 |
charptr = &options->host_key_files[*intptr]; |
|
1084 |
parse_filename: |
||
1085 |
54 |
arg = strdelim(&cp); |
|
1086 |
✓✗✗✓ |
108 |
if (!arg || *arg == '\0') |
1087 |
fatal("%s line %d: missing file name.", |
||
1088 |
filename, linenum); |
||
1089 |
✓✗✓✗ |
108 |
if (*activep && *charptr == NULL) { |
1090 |
54 |
*charptr = derelativise_path(arg); |
|
1091 |
/* increase optional counter */ |
||
1092 |
✓✓ | 54 |
if (intptr != NULL) |
1093 |
36 |
*intptr = *intptr + 1; |
|
1094 |
} |
||
1095 |
break; |
||
1096 |
|||
1097 |
case sHostKeyAgent: |
||
1098 |
charptr = &options->host_key_agent; |
||
1099 |
arg = strdelim(&cp); |
||
1100 |
if (!arg || *arg == '\0') |
||
1101 |
fatal("%s line %d: missing socket name.", |
||
1102 |
filename, linenum); |
||
1103 |
if (*activep && *charptr == NULL) |
||
1104 |
*charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? |
||
1105 |
xstrdup(arg) : derelativise_path(arg); |
||
1106 |
break; |
||
1107 |
|||
1108 |
case sHostCertificate: |
||
1109 |
intptr = &options->num_host_cert_files; |
||
1110 |
if (*intptr >= MAX_HOSTKEYS) |
||
1111 |
fatal("%s line %d: too many host certificates " |
||
1112 |
"specified (max %d).", filename, linenum, |
||
1113 |
MAX_HOSTCERTS); |
||
1114 |
charptr = &options->host_cert_files[*intptr]; |
||
1115 |
goto parse_filename; |
||
1116 |
|||
1117 |
case sPidFile: |
||
1118 |
18 |
charptr = &options->pid_file; |
|
1119 |
18 |
goto parse_filename; |
|
1120 |
|||
1121 |
case sPermitRootLogin: |
||
1122 |
intptr = &options->permit_root_login; |
||
1123 |
multistate_ptr = multistate_permitrootlogin; |
||
1124 |
goto parse_multistate; |
||
1125 |
|||
1126 |
case sIgnoreRhosts: |
||
1127 |
intptr = &options->ignore_rhosts; |
||
1128 |
parse_flag: |
||
1129 |
6 |
arg = strdelim(&cp); |
|
1130 |
✓✗✗✓ |
12 |
if (!arg || *arg == '\0') |
1131 |
fatal("%s line %d: missing yes/no argument.", |
||
1132 |
filename, linenum); |
||
1133 |
value = 0; /* silence compiler */ |
||
1134 |
✗✓ | 6 |
if (strcmp(arg, "yes") == 0) |
1135 |
value = 1; |
||
1136 |
✓✗ | 6 |
else if (strcmp(arg, "no") == 0) |
1137 |
value = 0; |
||
1138 |
else |
||
1139 |
fatal("%s line %d: Bad yes/no argument: %s", |
||
1140 |
filename, linenum, arg); |
||
1141 |
✓✗✓✗ |
12 |
if (*activep && *intptr == -1) |
1142 |
6 |
*intptr = value; |
|
1143 |
break; |
||
1144 |
|||
1145 |
case sIgnoreUserKnownHosts: |
||
1146 |
intptr = &options->ignore_user_known_hosts; |
||
1147 |
goto parse_flag; |
||
1148 |
|||
1149 |
case sHostbasedAuthentication: |
||
1150 |
intptr = &options->hostbased_authentication; |
||
1151 |
goto parse_flag; |
||
1152 |
|||
1153 |
case sHostbasedUsesNameFromPacketOnly: |
||
1154 |
intptr = &options->hostbased_uses_name_from_packet_only; |
||
1155 |
goto parse_flag; |
||
1156 |
|||
1157 |
case sHostbasedAcceptedKeyTypes: |
||
1158 |
charptr = &options->hostbased_key_types; |
||
1159 |
parse_keytypes: |
||
1160 |
arg = strdelim(&cp); |
||
1161 |
if (!arg || *arg == '\0') |
||
1162 |
fatal("%s line %d: Missing argument.", |
||
1163 |
filename, linenum); |
||
1164 |
if (*arg != '-' && |
||
1165 |
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) |
||
1166 |
fatal("%s line %d: Bad key types '%s'.", |
||
1167 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1168 |
if (*activep && *charptr == NULL) |
||
1169 |
*charptr = xstrdup(arg); |
||
1170 |
break; |
||
1171 |
|||
1172 |
case sHostKeyAlgorithms: |
||
1173 |
charptr = &options->hostkeyalgorithms; |
||
1174 |
goto parse_keytypes; |
||
1175 |
|||
1176 |
case sPubkeyAuthentication: |
||
1177 |
intptr = &options->pubkey_authentication; |
||
1178 |
goto parse_flag; |
||
1179 |
|||
1180 |
case sPubkeyAcceptedKeyTypes: |
||
1181 |
charptr = &options->pubkey_key_types; |
||
1182 |
goto parse_keytypes; |
||
1183 |
|||
1184 |
case sKerberosAuthentication: |
||
1185 |
intptr = &options->kerberos_authentication; |
||
1186 |
goto parse_flag; |
||
1187 |
|||
1188 |
case sKerberosOrLocalPasswd: |
||
1189 |
intptr = &options->kerberos_or_local_passwd; |
||
1190 |
goto parse_flag; |
||
1191 |
|||
1192 |
case sKerberosTicketCleanup: |
||
1193 |
intptr = &options->kerberos_ticket_cleanup; |
||
1194 |
goto parse_flag; |
||
1195 |
|||
1196 |
case sKerberosGetAFSToken: |
||
1197 |
intptr = &options->kerberos_get_afs_token; |
||
1198 |
goto parse_flag; |
||
1199 |
|||
1200 |
case sGssAuthentication: |
||
1201 |
intptr = &options->gss_authentication; |
||
1202 |
goto parse_flag; |
||
1203 |
|||
1204 |
case sGssCleanupCreds: |
||
1205 |
intptr = &options->gss_cleanup_creds; |
||
1206 |
goto parse_flag; |
||
1207 |
|||
1208 |
case sGssStrictAcceptor: |
||
1209 |
intptr = &options->gss_strict_acceptor; |
||
1210 |
goto parse_flag; |
||
1211 |
|||
1212 |
case sPasswordAuthentication: |
||
1213 |
intptr = &options->password_authentication; |
||
1214 |
goto parse_flag; |
||
1215 |
|||
1216 |
case sKbdInteractiveAuthentication: |
||
1217 |
intptr = &options->kbd_interactive_authentication; |
||
1218 |
goto parse_flag; |
||
1219 |
|||
1220 |
case sChallengeResponseAuthentication: |
||
1221 |
intptr = &options->challenge_response_authentication; |
||
1222 |
goto parse_flag; |
||
1223 |
|||
1224 |
case sPrintMotd: |
||
1225 |
intptr = &options->print_motd; |
||
1226 |
goto parse_flag; |
||
1227 |
|||
1228 |
case sPrintLastLog: |
||
1229 |
intptr = &options->print_lastlog; |
||
1230 |
goto parse_flag; |
||
1231 |
|||
1232 |
case sX11Forwarding: |
||
1233 |
intptr = &options->x11_forwarding; |
||
1234 |
goto parse_flag; |
||
1235 |
|||
1236 |
case sX11DisplayOffset: |
||
1237 |
intptr = &options->x11_display_offset; |
||
1238 |
parse_int: |
||
1239 |
arg = strdelim(&cp); |
||
1240 |
if (!arg || *arg == '\0') |
||
1241 |
fatal("%s line %d: missing integer value.", |
||
1242 |
filename, linenum); |
||
1243 |
value = atoi(arg); |
||
1244 |
if (*activep && *intptr == -1) |
||
1245 |
*intptr = value; |
||
1246 |
break; |
||
1247 |
|||
1248 |
case sX11UseLocalhost: |
||
1249 |
intptr = &options->x11_use_localhost; |
||
1250 |
goto parse_flag; |
||
1251 |
|||
1252 |
case sXAuthLocation: |
||
1253 |
charptr = &options->xauth_location; |
||
1254 |
goto parse_filename; |
||
1255 |
|||
1256 |
case sPermitTTY: |
||
1257 |
intptr = &options->permit_tty; |
||
1258 |
goto parse_flag; |
||
1259 |
|||
1260 |
case sPermitUserRC: |
||
1261 |
intptr = &options->permit_user_rc; |
||
1262 |
goto parse_flag; |
||
1263 |
|||
1264 |
case sStrictModes: |
||
1265 |
6 |
intptr = &options->strict_modes; |
|
1266 |
6 |
goto parse_flag; |
|
1267 |
|||
1268 |
case sTCPKeepAlive: |
||
1269 |
intptr = &options->tcp_keep_alive; |
||
1270 |
goto parse_flag; |
||
1271 |
|||
1272 |
case sEmptyPasswd: |
||
1273 |
intptr = &options->permit_empty_passwd; |
||
1274 |
goto parse_flag; |
||
1275 |
|||
1276 |
case sPermitUserEnvironment: |
||
1277 |
intptr = &options->permit_user_env; |
||
1278 |
goto parse_flag; |
||
1279 |
|||
1280 |
case sCompression: |
||
1281 |
intptr = &options->compression; |
||
1282 |
multistate_ptr = multistate_compression; |
||
1283 |
goto parse_multistate; |
||
1284 |
|||
1285 |
case sRekeyLimit: |
||
1286 |
arg = strdelim(&cp); |
||
1287 |
if (!arg || *arg == '\0') |
||
1288 |
fatal("%.200s line %d: Missing argument.", filename, |
||
1289 |
linenum); |
||
1290 |
if (strcmp(arg, "default") == 0) { |
||
1291 |
val64 = 0; |
||
1292 |
} else { |
||
1293 |
if (scan_scaled(arg, &val64) == -1) |
||
1294 |
fatal("%.200s line %d: Bad number '%s': %s", |
||
1295 |
filename, linenum, arg, strerror(errno)); |
||
1296 |
if (val64 != 0 && val64 < 16) |
||
1297 |
fatal("%.200s line %d: RekeyLimit too small", |
||
1298 |
filename, linenum); |
||
1299 |
} |
||
1300 |
if (*activep && options->rekey_limit == -1) |
||
1301 |
options->rekey_limit = val64; |
||
1302 |
if (cp != NULL) { /* optional rekey interval present */ |
||
1303 |
if (strcmp(cp, "none") == 0) { |
||
1304 |
(void)strdelim(&cp); /* discard */ |
||
1305 |
break; |
||
1306 |
} |
||
1307 |
intptr = &options->rekey_interval; |
||
1308 |
goto parse_time; |
||
1309 |
} |
||
1310 |
break; |
||
1311 |
|||
1312 |
case sGatewayPorts: |
||
1313 |
intptr = &options->fwd_opts.gateway_ports; |
||
1314 |
multistate_ptr = multistate_gatewayports; |
||
1315 |
goto parse_multistate; |
||
1316 |
|||
1317 |
case sUseDNS: |
||
1318 |
intptr = &options->use_dns; |
||
1319 |
goto parse_flag; |
||
1320 |
|||
1321 |
case sLogFacility: |
||
1322 |
log_facility_ptr = &options->log_facility; |
||
1323 |
arg = strdelim(&cp); |
||
1324 |
value = log_facility_number(arg); |
||
1325 |
if (value == SYSLOG_FACILITY_NOT_SET) |
||
1326 |
fatal("%.200s line %d: unsupported log facility '%s'", |
||
1327 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1328 |
if (*log_facility_ptr == -1) |
||
1329 |
*log_facility_ptr = (SyslogFacility) value; |
||
1330 |
break; |
||
1331 |
|||
1332 |
case sLogLevel: |
||
1333 |
18 |
log_level_ptr = &options->log_level; |
|
1334 |
18 |
arg = strdelim(&cp); |
|
1335 |
18 |
value = log_level_number(arg); |
|
1336 |
✗✓ | 18 |
if (value == SYSLOG_LEVEL_NOT_SET) |
1337 |
fatal("%.200s line %d: unsupported log level '%s'", |
||
1338 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1339 |
✓✗✓✗ |
36 |
if (*activep && *log_level_ptr == -1) |
1340 |
18 |
*log_level_ptr = (LogLevel) value; |
|
1341 |
break; |
||
1342 |
|||
1343 |
case sAllowTcpForwarding: |
||
1344 |
intptr = &options->allow_tcp_forwarding; |
||
1345 |
multistate_ptr = multistate_tcpfwd; |
||
1346 |
goto parse_multistate; |
||
1347 |
|||
1348 |
case sAllowStreamLocalForwarding: |
||
1349 |
intptr = &options->allow_streamlocal_forwarding; |
||
1350 |
multistate_ptr = multistate_tcpfwd; |
||
1351 |
goto parse_multistate; |
||
1352 |
|||
1353 |
case sAllowAgentForwarding: |
||
1354 |
intptr = &options->allow_agent_forwarding; |
||
1355 |
goto parse_flag; |
||
1356 |
|||
1357 |
case sDisableForwarding: |
||
1358 |
intptr = &options->disable_forwarding; |
||
1359 |
goto parse_flag; |
||
1360 |
|||
1361 |
case sAllowUsers: |
||
1362 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
||
1363 |
if (options->num_allow_users >= MAX_ALLOW_USERS) |
||
1364 |
fatal("%s line %d: too many allow users.", |
||
1365 |
filename, linenum); |
||
1366 |
if (match_user(NULL, NULL, NULL, arg) == -1) |
||
1367 |
fatal("%s line %d: invalid AllowUsers pattern: " |
||
1368 |
"\"%.100s\"", filename, linenum, arg); |
||
1369 |
if (!*activep) |
||
1370 |
continue; |
||
1371 |
options->allow_users[options->num_allow_users++] = |
||
1372 |
xstrdup(arg); |
||
1373 |
} |
||
1374 |
break; |
||
1375 |
|||
1376 |
case sDenyUsers: |
||
1377 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
||
1378 |
if (options->num_deny_users >= MAX_DENY_USERS) |
||
1379 |
fatal("%s line %d: too many deny users.", |
||
1380 |
filename, linenum); |
||
1381 |
if (match_user(NULL, NULL, NULL, arg) == -1) |
||
1382 |
fatal("%s line %d: invalid DenyUsers pattern: " |
||
1383 |
"\"%.100s\"", filename, linenum, arg); |
||
1384 |
if (!*activep) |
||
1385 |
continue; |
||
1386 |
options->deny_users[options->num_deny_users++] = |
||
1387 |
xstrdup(arg); |
||
1388 |
} |
||
1389 |
break; |
||
1390 |
|||
1391 |
case sAllowGroups: |
||
1392 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
||
1393 |
if (options->num_allow_groups >= MAX_ALLOW_GROUPS) |
||
1394 |
fatal("%s line %d: too many allow groups.", |
||
1395 |
filename, linenum); |
||
1396 |
if (!*activep) |
||
1397 |
continue; |
||
1398 |
options->allow_groups[options->num_allow_groups++] = |
||
1399 |
xstrdup(arg); |
||
1400 |
} |
||
1401 |
break; |
||
1402 |
|||
1403 |
case sDenyGroups: |
||
1404 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
||
1405 |
if (options->num_deny_groups >= MAX_DENY_GROUPS) |
||
1406 |
fatal("%s line %d: too many deny groups.", |
||
1407 |
filename, linenum); |
||
1408 |
if (!*activep) |
||
1409 |
continue; |
||
1410 |
options->deny_groups[options->num_deny_groups++] = |
||
1411 |
xstrdup(arg); |
||
1412 |
} |
||
1413 |
break; |
||
1414 |
|||
1415 |
case sCiphers: |
||
1416 |
arg = strdelim(&cp); |
||
1417 |
if (!arg || *arg == '\0') |
||
1418 |
fatal("%s line %d: Missing argument.", filename, linenum); |
||
1419 |
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg)) |
||
1420 |
fatal("%s line %d: Bad SSH2 cipher spec '%s'.", |
||
1421 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1422 |
if (options->ciphers == NULL) |
||
1423 |
options->ciphers = xstrdup(arg); |
||
1424 |
break; |
||
1425 |
|||
1426 |
case sMacs: |
||
1427 |
arg = strdelim(&cp); |
||
1428 |
if (!arg || *arg == '\0') |
||
1429 |
fatal("%s line %d: Missing argument.", filename, linenum); |
||
1430 |
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg)) |
||
1431 |
fatal("%s line %d: Bad SSH2 mac spec '%s'.", |
||
1432 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1433 |
if (options->macs == NULL) |
||
1434 |
options->macs = xstrdup(arg); |
||
1435 |
break; |
||
1436 |
|||
1437 |
case sKexAlgorithms: |
||
1438 |
arg = strdelim(&cp); |
||
1439 |
if (!arg || *arg == '\0') |
||
1440 |
fatal("%s line %d: Missing argument.", |
||
1441 |
filename, linenum); |
||
1442 |
if (*arg != '-' && |
||
1443 |
!kex_names_valid(*arg == '+' ? arg + 1 : arg)) |
||
1444 |
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", |
||
1445 |
filename, linenum, arg ? arg : "<NONE>"); |
||
1446 |
if (options->kex_algorithms == NULL) |
||
1447 |
options->kex_algorithms = xstrdup(arg); |
||
1448 |
break; |
||
1449 |
|||
1450 |
case sSubsystem: |
||
1451 |
✗✓ | 18 |
if (options->num_subsystems >= MAX_SUBSYSTEMS) { |
1452 |
fatal("%s line %d: too many subsystems defined.", |
||
1453 |
filename, linenum); |
||
1454 |
} |
||
1455 |
18 |
arg = strdelim(&cp); |
|
1456 |
✓✗✗✓ |
36 |
if (!arg || *arg == '\0') |
1457 |
fatal("%s line %d: Missing subsystem name.", |
||
1458 |
filename, linenum); |
||
1459 |
✗✓ | 18 |
if (!*activep) { |
1460 |
arg = strdelim(&cp); |
||
1461 |
break; |
||
1462 |
} |
||
1463 |
✗✓ | 36 |
for (i = 0; i < options->num_subsystems; i++) |
1464 |
if (strcmp(arg, options->subsystem_name[i]) == 0) |
||
1465 |
fatal("%s line %d: Subsystem '%s' already defined.", |
||
1466 |
filename, linenum, arg); |
||
1467 |
18 |
options->subsystem_name[options->num_subsystems] = xstrdup(arg); |
|
1468 |
18 |
arg = strdelim(&cp); |
|
1469 |
✓✗✗✓ |
36 |
if (!arg || *arg == '\0') |
1470 |
fatal("%s line %d: Missing subsystem command.", |
||
1471 |
filename, linenum); |
||
1472 |
18 |
options->subsystem_command[options->num_subsystems] = xstrdup(arg); |
|
1473 |
|||
1474 |
/* Collect arguments (separate to executable) */ |
||
1475 |
18 |
p = xstrdup(arg); |
|
1476 |
18 |
len = strlen(p) + 1; |
|
1477 |
✗✓✗✗ |
36 |
while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { |
1478 |
len += 1 + strlen(arg); |
||
1479 |
p = xreallocarray(p, 1, len); |
||
1480 |
strlcat(p, " ", len); |
||
1481 |
strlcat(p, arg, len); |
||
1482 |
} |
||
1483 |
18 |
options->subsystem_args[options->num_subsystems] = p; |
|
1484 |
18 |
options->num_subsystems++; |
|
1485 |
18 |
break; |
|
1486 |
|||
1487 |
case sMaxStartups: |
||
1488 |
arg = strdelim(&cp); |
||
1489 |
if (!arg || *arg == '\0') |
||
1490 |
fatal("%s line %d: Missing MaxStartups spec.", |
||
1491 |
filename, linenum); |
||
1492 |
if ((n = sscanf(arg, "%d:%d:%d", |
||
1493 |
&options->max_startups_begin, |
||
1494 |
&options->max_startups_rate, |
||
1495 |
&options->max_startups)) == 3) { |
||
1496 |
if (options->max_startups_begin > |
||
1497 |
options->max_startups || |
||
1498 |
options->max_startups_rate > 100 || |
||
1499 |
options->max_startups_rate < 1) |
||
1500 |
fatal("%s line %d: Illegal MaxStartups spec.", |
||
1501 |
filename, linenum); |
||
1502 |
} else if (n != 1) |
||
1503 |
fatal("%s line %d: Illegal MaxStartups spec.", |
||
1504 |
filename, linenum); |
||
1505 |
else |
||
1506 |
options->max_startups = options->max_startups_begin; |
||
1507 |
break; |
||
1508 |
|||
1509 |
case sMaxAuthTries: |
||
1510 |
intptr = &options->max_authtries; |
||
1511 |
goto parse_int; |
||
1512 |
|||
1513 |
case sMaxSessions: |
||
1514 |
intptr = &options->max_sessions; |
||
1515 |
goto parse_int; |
||
1516 |
|||
1517 |
case sBanner: |
||
1518 |
charptr = &options->banner; |
||
1519 |
goto parse_filename; |
||
1520 |
|||
1521 |
/* |
||
1522 |
* These options can contain %X options expanded at |
||
1523 |
* connect time, so that you can specify paths like: |
||
1524 |
* |
||
1525 |
* AuthorizedKeysFile /etc/ssh_keys/%u |
||
1526 |
*/ |
||
1527 |
case sAuthorizedKeysFile: |
||
1528 |
✓✗✓✗ |
36 |
if (*activep && options->num_authkeys_files == 0) { |
1529 |
✓✓✓✗ |
72 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
1530 |
✗✓ | 18 |
if (options->num_authkeys_files >= |
1531 |
MAX_AUTHKEYS_FILES) |
||
1532 |
fatal("%s line %d: " |
||
1533 |
"too many authorized keys files.", |
||
1534 |
filename, linenum); |
||
1535 |
36 |
options->authorized_keys_files[ |
|
1536 |
36 |
options->num_authkeys_files++] = |
|
1537 |
18 |
tilde_expand_filename(arg, getuid()); |
|
1538 |
} |
||
1539 |
} |
||
1540 |
18 |
return 0; |
|
1541 |
|||
1542 |
case sAuthorizedPrincipalsFile: |
||
1543 |
charptr = &options->authorized_principals_file; |
||
1544 |
arg = strdelim(&cp); |
||
1545 |
if (!arg || *arg == '\0') |
||
1546 |
fatal("%s line %d: missing file name.", |
||
1547 |
filename, linenum); |
||
1548 |
if (*activep && *charptr == NULL) { |
||
1549 |
*charptr = tilde_expand_filename(arg, getuid()); |
||
1550 |
/* increase optional counter */ |
||
1551 |
if (intptr != NULL) |
||
1552 |
*intptr = *intptr + 1; |
||
1553 |
} |
||
1554 |
break; |
||
1555 |
|||
1556 |
case sClientAliveInterval: |
||
1557 |
intptr = &options->client_alive_interval; |
||
1558 |
goto parse_time; |
||
1559 |
|||
1560 |
case sClientAliveCountMax: |
||
1561 |
intptr = &options->client_alive_count_max; |
||
1562 |
goto parse_int; |
||
1563 |
|||
1564 |
case sAcceptEnv: |
||
1565 |
✓✓✓✗ |
144 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
1566 |
✗✓ | 36 |
if (strchr(arg, '=') != NULL) |
1567 |
fatal("%s line %d: Invalid environment name.", |
||
1568 |
filename, linenum); |
||
1569 |
✗✓ | 36 |
if (options->num_accept_env >= MAX_ACCEPT_ENV) |
1570 |
fatal("%s line %d: too many allow env.", |
||
1571 |
filename, linenum); |
||
1572 |
✗✓ | 36 |
if (!*activep) |
1573 |
continue; |
||
1574 |
36 |
options->accept_env[options->num_accept_env++] = |
|
1575 |
36 |
xstrdup(arg); |
|
1576 |
} |
||
1577 |
break; |
||
1578 |
|||
1579 |
case sPermitTunnel: |
||
1580 |
intptr = &options->permit_tun; |
||
1581 |
arg = strdelim(&cp); |
||
1582 |
if (!arg || *arg == '\0') |
||
1583 |
fatal("%s line %d: Missing yes/point-to-point/" |
||
1584 |
"ethernet/no argument.", filename, linenum); |
||
1585 |
value = -1; |
||
1586 |
for (i = 0; tunmode_desc[i].val != -1; i++) |
||
1587 |
if (strcmp(tunmode_desc[i].text, arg) == 0) { |
||
1588 |
value = tunmode_desc[i].val; |
||
1589 |
break; |
||
1590 |
} |
||
1591 |
if (value == -1) |
||
1592 |
fatal("%s line %d: Bad yes/point-to-point/ethernet/" |
||
1593 |
"no argument: %s", filename, linenum, arg); |
||
1594 |
if (*activep && *intptr == -1) |
||
1595 |
*intptr = value; |
||
1596 |
break; |
||
1597 |
|||
1598 |
case sMatch: |
||
1599 |
if (cmdline) |
||
1600 |
fatal("Match directive not supported as a command-line " |
||
1601 |
"option"); |
||
1602 |
value = match_cfg_line(&cp, linenum, connectinfo); |
||
1603 |
if (value < 0) |
||
1604 |
fatal("%s line %d: Bad Match condition", filename, |
||
1605 |
linenum); |
||
1606 |
*activep = value; |
||
1607 |
break; |
||
1608 |
|||
1609 |
case sPermitOpen: |
||
1610 |
arg = strdelim(&cp); |
||
1611 |
if (!arg || *arg == '\0') |
||
1612 |
fatal("%s line %d: missing PermitOpen specification", |
||
1613 |
filename, linenum); |
||
1614 |
i = options->num_permitted_opens; /* modified later */ |
||
1615 |
if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { |
||
1616 |
if (*activep && i == 0) { |
||
1617 |
options->num_permitted_opens = 1; |
||
1618 |
options->permitted_opens = xcalloc(1, |
||
1619 |
sizeof(*options->permitted_opens)); |
||
1620 |
options->permitted_opens[0] = xstrdup(arg); |
||
1621 |
} |
||
1622 |
break; |
||
1623 |
} |
||
1624 |
for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { |
||
1625 |
arg2 = xstrdup(arg); |
||
1626 |
p = hpdelim(&arg); |
||
1627 |
if (p == NULL) |
||
1628 |
fatal("%s line %d: missing host in PermitOpen", |
||
1629 |
filename, linenum); |
||
1630 |
p = cleanhostname(p); |
||
1631 |
if (arg == NULL || ((port = permitopen_port(arg)) < 0)) |
||
1632 |
fatal("%s line %d: bad port number in " |
||
1633 |
"PermitOpen", filename, linenum); |
||
1634 |
if (*activep && i == 0) { |
||
1635 |
options->permitted_opens = xrecallocarray( |
||
1636 |
options->permitted_opens, |
||
1637 |
options->num_permitted_opens, |
||
1638 |
options->num_permitted_opens + 1, |
||
1639 |
sizeof(*options->permitted_opens)); |
||
1640 |
i = options->num_permitted_opens++; |
||
1641 |
options->permitted_opens[i] = arg2; |
||
1642 |
} else |
||
1643 |
free(arg2); |
||
1644 |
} |
||
1645 |
break; |
||
1646 |
|||
1647 |
case sForceCommand: |
||
1648 |
if (cp == NULL || *cp == '\0') |
||
1649 |
fatal("%.200s line %d: Missing argument.", filename, |
||
1650 |
linenum); |
||
1651 |
len = strspn(cp, WHITESPACE); |
||
1652 |
if (*activep && options->adm_forced_command == NULL) |
||
1653 |
options->adm_forced_command = xstrdup(cp + len); |
||
1654 |
return 0; |
||
1655 |
|||
1656 |
case sChrootDirectory: |
||
1657 |
charptr = &options->chroot_directory; |
||
1658 |
|||
1659 |
arg = strdelim(&cp); |
||
1660 |
if (!arg || *arg == '\0') |
||
1661 |
fatal("%s line %d: missing file name.", |
||
1662 |
filename, linenum); |
||
1663 |
if (*activep && *charptr == NULL) |
||
1664 |
*charptr = xstrdup(arg); |
||
1665 |
break; |
||
1666 |
|||
1667 |
case sTrustedUserCAKeys: |
||
1668 |
charptr = &options->trusted_user_ca_keys; |
||
1669 |
goto parse_filename; |
||
1670 |
|||
1671 |
case sRevokedKeys: |
||
1672 |
charptr = &options->revoked_keys_file; |
||
1673 |
goto parse_filename; |
||
1674 |
|||
1675 |
case sIPQoS: |
||
1676 |
arg = strdelim(&cp); |
||
1677 |
if ((value = parse_ipqos(arg)) == -1) |
||
1678 |
fatal("%s line %d: Bad IPQoS value: %s", |
||
1679 |
filename, linenum, arg); |
||
1680 |
arg = strdelim(&cp); |
||
1681 |
if (arg == NULL) |
||
1682 |
value2 = value; |
||
1683 |
else if ((value2 = parse_ipqos(arg)) == -1) |
||
1684 |
fatal("%s line %d: Bad IPQoS value: %s", |
||
1685 |
filename, linenum, arg); |
||
1686 |
if (*activep) { |
||
1687 |
options->ip_qos_interactive = value; |
||
1688 |
options->ip_qos_bulk = value2; |
||
1689 |
} |
||
1690 |
break; |
||
1691 |
|||
1692 |
case sVersionAddendum: |
||
1693 |
if (cp == NULL || *cp == '\0') |
||
1694 |
fatal("%.200s line %d: Missing argument.", filename, |
||
1695 |
linenum); |
||
1696 |
len = strspn(cp, WHITESPACE); |
||
1697 |
if (*activep && options->version_addendum == NULL) { |
||
1698 |
if (strcasecmp(cp + len, "none") == 0) |
||
1699 |
options->version_addendum = xstrdup(""); |
||
1700 |
else if (strchr(cp + len, '\r') != NULL) |
||
1701 |
fatal("%.200s line %d: Invalid argument", |
||
1702 |
filename, linenum); |
||
1703 |
else |
||
1704 |
options->version_addendum = xstrdup(cp + len); |
||
1705 |
} |
||
1706 |
return 0; |
||
1707 |
|||
1708 |
case sAuthorizedKeysCommand: |
||
1709 |
if (cp == NULL) |
||
1710 |
fatal("%.200s line %d: Missing argument.", filename, |
||
1711 |
linenum); |
||
1712 |
len = strspn(cp, WHITESPACE); |
||
1713 |
if (*activep && options->authorized_keys_command == NULL) { |
||
1714 |
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) |
||
1715 |
fatal("%.200s line %d: AuthorizedKeysCommand " |
||
1716 |
"must be an absolute path", |
||
1717 |
filename, linenum); |
||
1718 |
options->authorized_keys_command = xstrdup(cp + len); |
||
1719 |
} |
||
1720 |
return 0; |
||
1721 |
|||
1722 |
case sAuthorizedKeysCommandUser: |
||
1723 |
charptr = &options->authorized_keys_command_user; |
||
1724 |
|||
1725 |
arg = strdelim(&cp); |
||
1726 |
if (!arg || *arg == '\0') |
||
1727 |
fatal("%s line %d: missing AuthorizedKeysCommandUser " |
||
1728 |
"argument.", filename, linenum); |
||
1729 |
if (*activep && *charptr == NULL) |
||
1730 |
*charptr = xstrdup(arg); |
||
1731 |
break; |
||
1732 |
|||
1733 |
case sAuthorizedPrincipalsCommand: |
||
1734 |
if (cp == NULL) |
||
1735 |
fatal("%.200s line %d: Missing argument.", filename, |
||
1736 |
linenum); |
||
1737 |
len = strspn(cp, WHITESPACE); |
||
1738 |
if (*activep && |
||
1739 |
options->authorized_principals_command == NULL) { |
||
1740 |
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) |
||
1741 |
fatal("%.200s line %d: " |
||
1742 |
"AuthorizedPrincipalsCommand must be " |
||
1743 |
"an absolute path", filename, linenum); |
||
1744 |
options->authorized_principals_command = |
||
1745 |
xstrdup(cp + len); |
||
1746 |
} |
||
1747 |
return 0; |
||
1748 |
|||
1749 |
case sAuthorizedPrincipalsCommandUser: |
||
1750 |
charptr = &options->authorized_principals_command_user; |
||
1751 |
|||
1752 |
arg = strdelim(&cp); |
||
1753 |
if (!arg || *arg == '\0') |
||
1754 |
fatal("%s line %d: missing " |
||
1755 |
"AuthorizedPrincipalsCommandUser argument.", |
||
1756 |
filename, linenum); |
||
1757 |
if (*activep && *charptr == NULL) |
||
1758 |
*charptr = xstrdup(arg); |
||
1759 |
break; |
||
1760 |
|||
1761 |
case sAuthenticationMethods: |
||
1762 |
if (options->num_auth_methods == 0) { |
||
1763 |
value = 0; /* seen "any" pseudo-method */ |
||
1764 |
value2 = 0; /* sucessfully parsed any method */ |
||
1765 |
while ((arg = strdelim(&cp)) && *arg != '\0') { |
||
1766 |
if (options->num_auth_methods >= |
||
1767 |
MAX_AUTH_METHODS) |
||
1768 |
fatal("%s line %d: " |
||
1769 |
"too many authentication methods.", |
||
1770 |
filename, linenum); |
||
1771 |
if (strcmp(arg, "any") == 0) { |
||
1772 |
if (options->num_auth_methods > 0) { |
||
1773 |
fatal("%s line %d: \"any\" " |
||
1774 |
"must appear alone in " |
||
1775 |
"AuthenticationMethods", |
||
1776 |
filename, linenum); |
||
1777 |
} |
||
1778 |
value = 1; |
||
1779 |
} else if (value) { |
||
1780 |
fatal("%s line %d: \"any\" must appear " |
||
1781 |
"alone in AuthenticationMethods", |
||
1782 |
filename, linenum); |
||
1783 |
} else if (auth2_methods_valid(arg, 0) != 0) { |
||
1784 |
fatal("%s line %d: invalid " |
||
1785 |
"authentication method list.", |
||
1786 |
filename, linenum); |
||
1787 |
} |
||
1788 |
value2 = 1; |
||
1789 |
if (!*activep) |
||
1790 |
continue; |
||
1791 |
options->auth_methods[ |
||
1792 |
options->num_auth_methods++] = xstrdup(arg); |
||
1793 |
} |
||
1794 |
if (value2 == 0) { |
||
1795 |
fatal("%s line %d: no AuthenticationMethods " |
||
1796 |
"specified", filename, linenum); |
||
1797 |
} |
||
1798 |
} |
||
1799 |
return 0; |
||
1800 |
|||
1801 |
case sStreamLocalBindMask: |
||
1802 |
arg = strdelim(&cp); |
||
1803 |
if (!arg || *arg == '\0') |
||
1804 |
fatal("%s line %d: missing StreamLocalBindMask " |
||
1805 |
"argument.", filename, linenum); |
||
1806 |
/* Parse mode in octal format */ |
||
1807 |
value = strtol(arg, &p, 8); |
||
1808 |
if (arg == p || value < 0 || value > 0777) |
||
1809 |
fatal("%s line %d: Bad mask.", filename, linenum); |
||
1810 |
if (*activep) |
||
1811 |
options->fwd_opts.streamlocal_bind_mask = (mode_t)value; |
||
1812 |
break; |
||
1813 |
|||
1814 |
case sStreamLocalBindUnlink: |
||
1815 |
intptr = &options->fwd_opts.streamlocal_bind_unlink; |
||
1816 |
goto parse_flag; |
||
1817 |
|||
1818 |
case sFingerprintHash: |
||
1819 |
arg = strdelim(&cp); |
||
1820 |
if (!arg || *arg == '\0') |
||
1821 |
fatal("%.200s line %d: Missing argument.", |
||
1822 |
filename, linenum); |
||
1823 |
if ((value = ssh_digest_alg_by_name(arg)) == -1) |
||
1824 |
fatal("%.200s line %d: Invalid hash algorithm \"%s\".", |
||
1825 |
filename, linenum, arg); |
||
1826 |
if (*activep) |
||
1827 |
options->fingerprint_hash = value; |
||
1828 |
break; |
||
1829 |
|||
1830 |
case sExposeAuthInfo: |
||
1831 |
intptr = &options->expose_userauth_info; |
||
1832 |
goto parse_flag; |
||
1833 |
|||
1834 |
case sDeprecated: |
||
1835 |
case sIgnore: |
||
1836 |
case sUnsupported: |
||
1837 |
do_log2(opcode == sIgnore ? |
||
1838 |
SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, |
||
1839 |
"%s line %d: %s option %s", filename, linenum, |
||
1840 |
opcode == sUnsupported ? "Unsupported" : "Deprecated", arg); |
||
1841 |
while (arg) |
||
1842 |
arg = strdelim(&cp); |
||
1843 |
break; |
||
1844 |
|||
1845 |
default: |
||
1846 |
fatal("%s line %d: Missing handler for opcode %s (%d)", |
||
1847 |
filename, linenum, arg, opcode); |
||
1848 |
} |
||
1849 |
✗✓✗✗ |
186 |
if ((arg = strdelim(&cp)) != NULL && *arg != '\0') |
1850 |
fatal("%s line %d: garbage at end of line; \"%.200s\".", |
||
1851 |
filename, linenum, arg); |
||
1852 |
186 |
return 0; |
|
1853 |
240 |
} |
|
1854 |
|||
1855 |
/* Reads the server configuration file. */ |
||
1856 |
|||
1857 |
void |
||
1858 |
load_server_config(const char *filename, Buffer *conf) |
||
1859 |
{ |
||
1860 |
36 |
char line[4096], *cp; |
|
1861 |
FILE *f; |
||
1862 |
int lineno = 0; |
||
1863 |
|||
1864 |
18 |
debug2("%s: filename %s", __func__, filename); |
|
1865 |
✗✓ | 18 |
if ((f = fopen(filename, "r")) == NULL) { |
1866 |
perror(filename); |
||
1867 |
exit(1); |
||
1868 |
} |
||
1869 |
18 |
buffer_clear(conf); |
|
1870 |
✓✓ | 480 |
while (fgets(line, sizeof(line), f)) { |
1871 |
222 |
lineno++; |
|
1872 |
✗✓ | 222 |
if (strlen(line) == sizeof(line) - 1) |
1873 |
fatal("%s line %d too long", filename, lineno); |
||
1874 |
/* |
||
1875 |
* Trim out comments and strip whitespace |
||
1876 |
* NB - preserve newlines, they are needed to reproduce |
||
1877 |
* line numbers later for error messages |
||
1878 |
*/ |
||
1879 |
✓✓ | 222 |
if ((cp = strchr(line, '#')) != NULL) |
1880 |
18 |
memcpy(cp, "\n", 2); |
|
1881 |
222 |
cp = line + strspn(line, " \t\r"); |
|
1882 |
|||
1883 |
222 |
buffer_append(conf, cp, strlen(cp)); |
|
1884 |
} |
||
1885 |
18 |
buffer_append(conf, "\0", 1); |
|
1886 |
18 |
fclose(f); |
|
1887 |
18 |
debug2("%s: done config len = %d", __func__, buffer_len(conf)); |
|
1888 |
18 |
} |
|
1889 |
|||
1890 |
void |
||
1891 |
parse_server_match_config(ServerOptions *options, |
||
1892 |
struct connection_info *connectinfo) |
||
1893 |
{ |
||
1894 |
ServerOptions mo; |
||
1895 |
|||
1896 |
initialize_server_options(&mo); |
||
1897 |
parse_server_config(&mo, "reprocess config", &cfg, connectinfo); |
||
1898 |
copy_set_server_options(options, &mo, 0); |
||
1899 |
} |
||
1900 |
|||
1901 |
int parse_server_match_testspec(struct connection_info *ci, char *spec) |
||
1902 |
{ |
||
1903 |
char *p; |
||
1904 |
|||
1905 |
while ((p = strsep(&spec, ",")) && *p != '\0') { |
||
1906 |
if (strncmp(p, "addr=", 5) == 0) { |
||
1907 |
ci->address = xstrdup(p + 5); |
||
1908 |
} else if (strncmp(p, "host=", 5) == 0) { |
||
1909 |
ci->host = xstrdup(p + 5); |
||
1910 |
} else if (strncmp(p, "user=", 5) == 0) { |
||
1911 |
ci->user = xstrdup(p + 5); |
||
1912 |
} else if (strncmp(p, "laddr=", 6) == 0) { |
||
1913 |
ci->laddress = xstrdup(p + 6); |
||
1914 |
} else if (strncmp(p, "lport=", 6) == 0) { |
||
1915 |
ci->lport = a2port(p + 6); |
||
1916 |
if (ci->lport == -1) { |
||
1917 |
fprintf(stderr, "Invalid port '%s' in test mode" |
||
1918 |
" specification %s\n", p+6, p); |
||
1919 |
return -1; |
||
1920 |
} |
||
1921 |
} else { |
||
1922 |
fprintf(stderr, "Invalid test mode specification %s\n", |
||
1923 |
p); |
||
1924 |
return -1; |
||
1925 |
} |
||
1926 |
} |
||
1927 |
return 0; |
||
1928 |
} |
||
1929 |
|||
1930 |
/* |
||
1931 |
* returns 1 for a complete spec, 0 for partial spec and -1 for an |
||
1932 |
* empty spec. |
||
1933 |
*/ |
||
1934 |
int server_match_spec_complete(struct connection_info *ci) |
||
1935 |
{ |
||
1936 |
✗✓✗✗ ✗✗ |
36 |
if (ci->user && ci->host && ci->address) |
1937 |
return 1; /* complete */ |
||
1938 |
✓✗✓✗ ✓✗ |
54 |
if (!ci->user && !ci->host && !ci->address) |
1939 |
18 |
return -1; /* empty */ |
|
1940 |
return 0; /* partial */ |
||
1941 |
18 |
} |
|
1942 |
|||
1943 |
/* |
||
1944 |
* Copy any supported values that are set. |
||
1945 |
* |
||
1946 |
* If the preauth flag is set, we do not bother copying the string or |
||
1947 |
* array values that are not used pre-authentication, because any that we |
||
1948 |
* do use must be explictly sent in mm_getpwnamallow(). |
||
1949 |
*/ |
||
1950 |
void |
||
1951 |
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) |
||
1952 |
{ |
||
1953 |
#define M_CP_INTOPT(n) do {\ |
||
1954 |
if (src->n != -1) \ |
||
1955 |
dst->n = src->n; \ |
||
1956 |
} while (0) |
||
1957 |
|||
1958 |
M_CP_INTOPT(password_authentication); |
||
1959 |
M_CP_INTOPT(gss_authentication); |
||
1960 |
M_CP_INTOPT(pubkey_authentication); |
||
1961 |
M_CP_INTOPT(kerberos_authentication); |
||
1962 |
M_CP_INTOPT(hostbased_authentication); |
||
1963 |
M_CP_INTOPT(hostbased_uses_name_from_packet_only); |
||
1964 |
M_CP_INTOPT(kbd_interactive_authentication); |
||
1965 |
M_CP_INTOPT(permit_root_login); |
||
1966 |
M_CP_INTOPT(permit_empty_passwd); |
||
1967 |
|||
1968 |
M_CP_INTOPT(allow_tcp_forwarding); |
||
1969 |
M_CP_INTOPT(allow_streamlocal_forwarding); |
||
1970 |
M_CP_INTOPT(allow_agent_forwarding); |
||
1971 |
M_CP_INTOPT(disable_forwarding); |
||
1972 |
M_CP_INTOPT(expose_userauth_info); |
||
1973 |
M_CP_INTOPT(permit_tun); |
||
1974 |
M_CP_INTOPT(fwd_opts.gateway_ports); |
||
1975 |
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); |
||
1976 |
M_CP_INTOPT(x11_display_offset); |
||
1977 |
M_CP_INTOPT(x11_forwarding); |
||
1978 |
M_CP_INTOPT(x11_use_localhost); |
||
1979 |
M_CP_INTOPT(permit_tty); |
||
1980 |
M_CP_INTOPT(permit_user_rc); |
||
1981 |
M_CP_INTOPT(max_sessions); |
||
1982 |
M_CP_INTOPT(max_authtries); |
||
1983 |
M_CP_INTOPT(client_alive_count_max); |
||
1984 |
M_CP_INTOPT(client_alive_interval); |
||
1985 |
M_CP_INTOPT(ip_qos_interactive); |
||
1986 |
M_CP_INTOPT(ip_qos_bulk); |
||
1987 |
M_CP_INTOPT(rekey_limit); |
||
1988 |
M_CP_INTOPT(rekey_interval); |
||
1989 |
M_CP_INTOPT(log_level); |
||
1990 |
|||
1991 |
/* |
||
1992 |
* The bind_mask is a mode_t that may be unsigned, so we can't use |
||
1993 |
* M_CP_INTOPT - it does a signed comparison that causes compiler |
||
1994 |
* warnings. |
||
1995 |
*/ |
||
1996 |
if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { |
||
1997 |
dst->fwd_opts.streamlocal_bind_mask = |
||
1998 |
src->fwd_opts.streamlocal_bind_mask; |
||
1999 |
} |
||
2000 |
|||
2001 |
/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ |
||
2002 |
#define M_CP_STROPT(n) do {\ |
||
2003 |
if (src->n != NULL && dst->n != src->n) { \ |
||
2004 |
free(dst->n); \ |
||
2005 |
dst->n = src->n; \ |
||
2006 |
} \ |
||
2007 |
} while(0) |
||
2008 |
#define M_CP_STRARRAYOPT(n, num_n) do {\ |
||
2009 |
if (src->num_n != 0) { \ |
||
2010 |
for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ |
||
2011 |
dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ |
||
2012 |
} \ |
||
2013 |
} while(0) |
||
2014 |
#define M_CP_STRARRAYOPT_ALLOC(n, num_n) do { \ |
||
2015 |
if (src->num_n != 0) { \ |
||
2016 |
dst->n = xcalloc(src->num_n, sizeof(*dst->n)); \ |
||
2017 |
M_CP_STRARRAYOPT(n, num_n); \ |
||
2018 |
dst->num_n = src->num_n; \ |
||
2019 |
} \ |
||
2020 |
} while(0) |
||
2021 |
|||
2022 |
/* See comment in servconf.h */ |
||
2023 |
COPY_MATCH_STRING_OPTS(); |
||
2024 |
|||
2025 |
/* Arguments that accept '+...' need to be expanded */ |
||
2026 |
assemble_algorithms(dst); |
||
2027 |
|||
2028 |
/* |
||
2029 |
* The only things that should be below this point are string options |
||
2030 |
* which are only used after authentication. |
||
2031 |
*/ |
||
2032 |
if (preauth) |
||
2033 |
return; |
||
2034 |
|||
2035 |
/* These options may be "none" to clear a global setting */ |
||
2036 |
M_CP_STROPT(adm_forced_command); |
||
2037 |
if (option_clear_or_none(dst->adm_forced_command)) { |
||
2038 |
free(dst->adm_forced_command); |
||
2039 |
dst->adm_forced_command = NULL; |
||
2040 |
} |
||
2041 |
M_CP_STROPT(chroot_directory); |
||
2042 |
if (option_clear_or_none(dst->chroot_directory)) { |
||
2043 |
free(dst->chroot_directory); |
||
2044 |
dst->chroot_directory = NULL; |
||
2045 |
} |
||
2046 |
} |
||
2047 |
|||
2048 |
#undef M_CP_INTOPT |
||
2049 |
#undef M_CP_STROPT |
||
2050 |
#undef M_CP_STRARRAYOPT |
||
2051 |
#undef M_CP_STRARRAYOPT_ALLOC |
||
2052 |
|||
2053 |
void |
||
2054 |
parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, |
||
2055 |
struct connection_info *connectinfo) |
||
2056 |
{ |
||
2057 |
36 |
int active, linenum, bad_options = 0; |
|
2058 |
18 |
char *cp, *obuf, *cbuf; |
|
2059 |
|||
2060 |
18 |
debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); |
|
2061 |
|||
2062 |
✗✓ | 18 |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) |
2063 |
fatal("%s: sshbuf_dup_string failed", __func__); |
||
2064 |
18 |
active = connectinfo ? 0 : 1; |
|
2065 |
linenum = 1; |
||
2066 |
✓✓ | 276 |
while ((cp = strsep(&cbuf, "\n")) != NULL) { |
2067 |
✓✗ | 480 |
if (process_server_config_line(options, cp, filename, |
2068 |
480 |
linenum++, &active, connectinfo) != 0) |
|
2069 |
bad_options++; |
||
2070 |
} |
||
2071 |
18 |
free(obuf); |
|
2072 |
✗✓ | 18 |
if (bad_options > 0) |
2073 |
fatal("%s: terminating, %d bad configuration options", |
||
2074 |
filename, bad_options); |
||
2075 |
18 |
process_queued_listen_addrs(options); |
|
2076 |
18 |
} |
|
2077 |
|||
2078 |
static const char * |
||
2079 |
fmt_multistate_int(int val, const struct multistate *m) |
||
2080 |
{ |
||
2081 |
u_int i; |
||
2082 |
|||
2083 |
for (i = 0; m[i].key != NULL; i++) { |
||
2084 |
if (m[i].value == val) |
||
2085 |
return m[i].key; |
||
2086 |
} |
||
2087 |
return "UNKNOWN"; |
||
2088 |
} |
||
2089 |
|||
2090 |
static const char * |
||
2091 |
fmt_intarg(ServerOpCodes code, int val) |
||
2092 |
{ |
||
2093 |
if (val == -1) |
||
2094 |
return "unset"; |
||
2095 |
switch (code) { |
||
2096 |
case sAddressFamily: |
||
2097 |
return fmt_multistate_int(val, multistate_addressfamily); |
||
2098 |
case sPermitRootLogin: |
||
2099 |
return fmt_multistate_int(val, multistate_permitrootlogin); |
||
2100 |
case sGatewayPorts: |
||
2101 |
return fmt_multistate_int(val, multistate_gatewayports); |
||
2102 |
case sCompression: |
||
2103 |
return fmt_multistate_int(val, multistate_compression); |
||
2104 |
case sAllowTcpForwarding: |
||
2105 |
return fmt_multistate_int(val, multistate_tcpfwd); |
||
2106 |
case sAllowStreamLocalForwarding: |
||
2107 |
return fmt_multistate_int(val, multistate_tcpfwd); |
||
2108 |
case sFingerprintHash: |
||
2109 |
return ssh_digest_alg_name(val); |
||
2110 |
default: |
||
2111 |
switch (val) { |
||
2112 |
case 0: |
||
2113 |
return "no"; |
||
2114 |
case 1: |
||
2115 |
return "yes"; |
||
2116 |
default: |
||
2117 |
return "UNKNOWN"; |
||
2118 |
} |
||
2119 |
} |
||
2120 |
} |
||
2121 |
|||
2122 |
static const char * |
||
2123 |
lookup_opcode_name(ServerOpCodes code) |
||
2124 |
{ |
||
2125 |
u_int i; |
||
2126 |
|||
2127 |
for (i = 0; keywords[i].name != NULL; i++) |
||
2128 |
if (keywords[i].opcode == code) |
||
2129 |
return(keywords[i].name); |
||
2130 |
return "UNKNOWN"; |
||
2131 |
} |
||
2132 |
|||
2133 |
static void |
||
2134 |
dump_cfg_int(ServerOpCodes code, int val) |
||
2135 |
{ |
||
2136 |
printf("%s %d\n", lookup_opcode_name(code), val); |
||
2137 |
} |
||
2138 |
|||
2139 |
static void |
||
2140 |
dump_cfg_oct(ServerOpCodes code, int val) |
||
2141 |
{ |
||
2142 |
printf("%s 0%o\n", lookup_opcode_name(code), val); |
||
2143 |
} |
||
2144 |
|||
2145 |
static void |
||
2146 |
dump_cfg_fmtint(ServerOpCodes code, int val) |
||
2147 |
{ |
||
2148 |
printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); |
||
2149 |
} |
||
2150 |
|||
2151 |
static void |
||
2152 |
dump_cfg_string(ServerOpCodes code, const char *val) |
||
2153 |
{ |
||
2154 |
printf("%s %s\n", lookup_opcode_name(code), |
||
2155 |
val == NULL ? "none" : val); |
||
2156 |
} |
||
2157 |
|||
2158 |
static void |
||
2159 |
dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) |
||
2160 |
{ |
||
2161 |
u_int i; |
||
2162 |
|||
2163 |
for (i = 0; i < count; i++) |
||
2164 |
printf("%s %s\n", lookup_opcode_name(code), vals[i]); |
||
2165 |
} |
||
2166 |
|||
2167 |
static void |
||
2168 |
dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) |
||
2169 |
{ |
||
2170 |
u_int i; |
||
2171 |
|||
2172 |
if (count <= 0 && code != sAuthenticationMethods) |
||
2173 |
return; |
||
2174 |
printf("%s", lookup_opcode_name(code)); |
||
2175 |
for (i = 0; i < count; i++) |
||
2176 |
printf(" %s", vals[i]); |
||
2177 |
if (code == sAuthenticationMethods && count == 0) |
||
2178 |
printf(" any"); |
||
2179 |
printf("\n"); |
||
2180 |
} |
||
2181 |
|||
2182 |
void |
||
2183 |
dump_config(ServerOptions *o) |
||
2184 |
{ |
||
2185 |
u_int i; |
||
2186 |
int ret; |
||
2187 |
struct addrinfo *ai; |
||
2188 |
char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; |
||
2189 |
char *laddr1 = xstrdup(""), *laddr2 = NULL; |
||
2190 |
|||
2191 |
/* these are usually at the top of the config */ |
||
2192 |
for (i = 0; i < o->num_ports; i++) |
||
2193 |
printf("port %d\n", o->ports[i]); |
||
2194 |
dump_cfg_fmtint(sAddressFamily, o->address_family); |
||
2195 |
|||
2196 |
/* |
||
2197 |
* ListenAddress must be after Port. add_one_listen_addr pushes |
||
2198 |
* addresses onto a stack, so to maintain ordering we need to |
||
2199 |
* print these in reverse order. |
||
2200 |
*/ |
||
2201 |
for (ai = o->listen_addrs; ai; ai = ai->ai_next) { |
||
2202 |
if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, |
||
2203 |
sizeof(addr), port, sizeof(port), |
||
2204 |
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { |
||
2205 |
error("getnameinfo failed: %.100s", |
||
2206 |
(ret != EAI_SYSTEM) ? gai_strerror(ret) : |
||
2207 |
strerror(errno)); |
||
2208 |
} else { |
||
2209 |
laddr2 = laddr1; |
||
2210 |
if (ai->ai_family == AF_INET6) |
||
2211 |
xasprintf(&laddr1, "listenaddress [%s]:%s\n%s", |
||
2212 |
addr, port, laddr2); |
||
2213 |
else |
||
2214 |
xasprintf(&laddr1, "listenaddress %s:%s\n%s", |
||
2215 |
addr, port, laddr2); |
||
2216 |
free(laddr2); |
||
2217 |
} |
||
2218 |
} |
||
2219 |
printf("%s", laddr1); |
||
2220 |
free(laddr1); |
||
2221 |
|||
2222 |
/* integer arguments */ |
||
2223 |
dump_cfg_int(sLoginGraceTime, o->login_grace_time); |
||
2224 |
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); |
||
2225 |
dump_cfg_int(sMaxAuthTries, o->max_authtries); |
||
2226 |
dump_cfg_int(sMaxSessions, o->max_sessions); |
||
2227 |
dump_cfg_int(sClientAliveInterval, o->client_alive_interval); |
||
2228 |
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); |
||
2229 |
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); |
||
2230 |
|||
2231 |
/* formatted integer arguments */ |
||
2232 |
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); |
||
2233 |
dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); |
||
2234 |
dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); |
||
2235 |
dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); |
||
2236 |
dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, |
||
2237 |
o->hostbased_uses_name_from_packet_only); |
||
2238 |
dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); |
||
2239 |
#ifdef KRB5 |
||
2240 |
dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); |
||
2241 |
dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); |
||
2242 |
dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); |
||
2243 |
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); |
||
2244 |
#endif |
||
2245 |
#ifdef GSSAPI |
||
2246 |
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); |
||
2247 |
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); |
||
2248 |
#endif |
||
2249 |
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); |
||
2250 |
dump_cfg_fmtint(sKbdInteractiveAuthentication, |
||
2251 |
o->kbd_interactive_authentication); |
||
2252 |
dump_cfg_fmtint(sChallengeResponseAuthentication, |
||
2253 |
o->challenge_response_authentication); |
||
2254 |
dump_cfg_fmtint(sPrintMotd, o->print_motd); |
||
2255 |
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); |
||
2256 |
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); |
||
2257 |
dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); |
||
2258 |
dump_cfg_fmtint(sPermitTTY, o->permit_tty); |
||
2259 |
dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); |
||
2260 |
dump_cfg_fmtint(sStrictModes, o->strict_modes); |
||
2261 |
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); |
||
2262 |
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); |
||
2263 |
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); |
||
2264 |
dump_cfg_fmtint(sCompression, o->compression); |
||
2265 |
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); |
||
2266 |
dump_cfg_fmtint(sUseDNS, o->use_dns); |
||
2267 |
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); |
||
2268 |
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); |
||
2269 |
dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); |
||
2270 |
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); |
||
2271 |
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); |
||
2272 |
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); |
||
2273 |
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); |
||
2274 |
|||
2275 |
/* string arguments */ |
||
2276 |
dump_cfg_string(sPidFile, o->pid_file); |
||
2277 |
dump_cfg_string(sXAuthLocation, o->xauth_location); |
||
2278 |
dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); |
||
2279 |
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); |
||
2280 |
dump_cfg_string(sBanner, o->banner); |
||
2281 |
dump_cfg_string(sForceCommand, o->adm_forced_command); |
||
2282 |
dump_cfg_string(sChrootDirectory, o->chroot_directory); |
||
2283 |
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); |
||
2284 |
dump_cfg_string(sRevokedKeys, o->revoked_keys_file); |
||
2285 |
dump_cfg_string(sAuthorizedPrincipalsFile, |
||
2286 |
o->authorized_principals_file); |
||
2287 |
dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' |
||
2288 |
? "none" : o->version_addendum); |
||
2289 |
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); |
||
2290 |
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); |
||
2291 |
dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); |
||
2292 |
dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); |
||
2293 |
dump_cfg_string(sHostKeyAgent, o->host_key_agent); |
||
2294 |
dump_cfg_string(sKexAlgorithms, |
||
2295 |
o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); |
||
2296 |
dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? |
||
2297 |
o->hostbased_key_types : KEX_DEFAULT_PK_ALG); |
||
2298 |
dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ? |
||
2299 |
o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); |
||
2300 |
dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? |
||
2301 |
o->pubkey_key_types : KEX_DEFAULT_PK_ALG); |
||
2302 |
|||
2303 |
/* string arguments requiring a lookup */ |
||
2304 |
dump_cfg_string(sLogLevel, log_level_name(o->log_level)); |
||
2305 |
dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); |
||
2306 |
|||
2307 |
/* string array arguments */ |
||
2308 |
dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, |
||
2309 |
o->authorized_keys_files); |
||
2310 |
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, |
||
2311 |
o->host_key_files); |
||
2312 |
dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, |
||
2313 |
o->host_cert_files); |
||
2314 |
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); |
||
2315 |
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); |
||
2316 |
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); |
||
2317 |
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); |
||
2318 |
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); |
||
2319 |
dump_cfg_strarray_oneline(sAuthenticationMethods, |
||
2320 |
o->num_auth_methods, o->auth_methods); |
||
2321 |
|||
2322 |
/* other arguments */ |
||
2323 |
for (i = 0; i < o->num_subsystems; i++) |
||
2324 |
printf("subsystem %s %s\n", o->subsystem_name[i], |
||
2325 |
o->subsystem_args[i]); |
||
2326 |
|||
2327 |
printf("maxstartups %d:%d:%d\n", o->max_startups_begin, |
||
2328 |
o->max_startups_rate, o->max_startups); |
||
2329 |
|||
2330 |
for (i = 0; tunmode_desc[i].val != -1; i++) |
||
2331 |
if (tunmode_desc[i].val == o->permit_tun) { |
||
2332 |
s = tunmode_desc[i].text; |
||
2333 |
break; |
||
2334 |
} |
||
2335 |
dump_cfg_string(sPermitTunnel, s); |
||
2336 |
|||
2337 |
printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); |
||
2338 |
printf("%s\n", iptos2str(o->ip_qos_bulk)); |
||
2339 |
|||
2340 |
printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, |
||
2341 |
o->rekey_interval); |
||
2342 |
|||
2343 |
printf("permitopen"); |
||
2344 |
if (o->num_permitted_opens == 0) |
||
2345 |
printf(" any"); |
||
2346 |
else { |
||
2347 |
for (i = 0; i < o->num_permitted_opens; i++) |
||
2348 |
printf(" %s", o->permitted_opens[i]); |
||
2349 |
} |
||
2350 |
printf("\n"); |
||
2351 |
} |
Generated by: GCOVR (Version 3.3) |