1 /*
2 * ProFTPD - mod_sftp
3 * Copyright (c) 2008-2020 TJ Saunders
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, TJ Saunders and other respective copyright holders
20 * give permission to link this program with OpenSSL, and distribute the
21 * resulting executable, without including the source code for OpenSSL in the
22 * source distribution.
23 *
24 * -----DO NOT EDIT BELOW THIS LINE-----
25 * $Archive: mod_sftp.a$
26 * $Libraries: -lcrypto$
27 */
28
29 #include "mod_sftp.h"
30 #include "ssh2.h"
31 #include "packet.h"
32 #include "interop.h"
33 #include "crypto.h"
34 #include "cipher.h"
35 #include "mac.h"
36 #include "keys.h"
37 #include "keystore.h"
38 #include "disconnect.h"
39 #include "kex.h"
40 #include "blacklist.h"
41 #include "service.h"
42 #include "auth.h"
43 #include "channel.h"
44 #include "tap.h"
45 #include "kbdint.h"
46 #include "fxp.h"
47 #include "utf8.h"
48
49 #if defined(HAVE_SODIUM_H)
50 # include <sodium.h>
51 #endif /* HAVE_SODIUM_H */
52
53 extern xaset_t *server_list;
54
55 module sftp_module;
56
57 int sftp_logfd = -1;
58 const char *sftp_logname = NULL;
59 pool *sftp_pool = NULL;
60 conn_t *sftp_conn = NULL;
61 unsigned int sftp_sess_state = 0;
62 unsigned long sftp_opts = 0UL;
63 unsigned int sftp_services = SFTP_SERVICE_DEFAULT;
64
65 static int sftp_engine = 0;
66 static const char *sftp_client_version = NULL;
67 static const char *sftp_server_version = SFTP_ID_DEFAULT_STRING;
68
69 /* Flags for changing how hostkeys are handled. */
70 #define SFTP_HOSTKEY_FL_CLEAR_RSA_KEY 0x001
71 #define SFTP_HOSTKEY_FL_CLEAR_DSA_KEY 0x002
72 #define SFTP_HOSTKEY_FL_CLEAR_ECDSA_KEY 0x004
73 #define SFTP_HOSTKEY_FL_CLEAR_ED25519_KEY 0x008
74
75 static const char *trace_channel = "ssh2";
76
sftp_have_authenticated(cmd_rec * cmd)77 static int sftp_have_authenticated(cmd_rec *cmd) {
78 return (sftp_sess_state & SFTP_SESS_STATE_HAVE_AUTH);
79 }
80
sftp_get_client_version(conn_t * conn)81 static int sftp_get_client_version(conn_t *conn) {
82 int res;
83
84 /* 255 is the RFC-defined maximum banner/ID string size */
85 char buf[256], *banner = NULL;
86 size_t buflen = 0;
87
88 /* Read client version. This looks ugly, reading one byte at a time.
89 * It is necessary, though. The banner sent by the client is not of any
90 * guaranteed length. The client might also send the next SSH packet in
91 * the exchange, such that both messages are in the socket buffer. If
92 * we read too much of the banner, we'll read into the KEXINIT, for example,
93 * and cause problems later.
94 */
95
96 while (TRUE) {
97 register unsigned int i;
98 int bad_proto = FALSE;
99
100 pr_signals_handle();
101
102 memset(buf, '\0', sizeof(buf));
103
104 for (i = 0; i < sizeof(buf) - 1; i++) {
105 res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1, 0);
106 while (res <= 0) {
107 int xerrno = errno;
108
109 if (xerrno == EINTR) {
110 pr_signals_handle();
111
112 res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1, 0);
113 continue;
114 }
115
116 if (res < 0) {
117 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
118 "error reading from client rfd %d: %s", conn->rfd,
119 strerror(xerrno));
120 }
121
122 errno = xerrno;
123 return res;
124 }
125
126 /* We continue reading until the client has sent the terminating
127 * CRLF sequence.
128 */
129 if (buf[i] == '\r') {
130 buf[i] = '\0';
131 continue;
132 }
133
134 if (buf[i] == '\n') {
135 buf[i] = '\0';
136 break;
137 }
138 }
139
140 if (i == sizeof(buf)-1) {
141 bad_proto = TRUE;
142
143 } else {
144 buf[sizeof(buf)-1] = '\0';
145 buflen = strlen(buf);
146 }
147
148 /* If the line does not begin with "SSH-2.0-", skip it. RFC4253, Section
149 * 4.2 does not specify what should happen if the client sends data
150 * other than the proper version string initially.
151 *
152 * If we have been configured for compatibility with old protocol
153 * implementations, check for "SSH-1.99-" as well.
154 *
155 * OpenSSH simply disconnects the client after saying "Protocol mismatch"
156 * if the client's version string does not begin with "SSH-2.0-"
157 * (or "SSH-1.99-"). Works for me.
158 */
159 if (bad_proto == FALSE) {
160 if (strncmp(buf, "SSH-2.0-", 8) != 0) {
161 bad_proto = TRUE;
162
163 if (sftp_opts & SFTP_OPT_OLD_PROTO_COMPAT) {
164 if (strncmp(buf, "SSH-1.99-", 9) == 0) {
165 if (buflen == 9) {
166 /* The client sent ONLY "SSH-1.99-". OpenSSH handles this as a
167 * "Protocol mismatch", so shall we.
168 */
169 bad_proto = TRUE;
170
171 } else {
172 banner = buf + 9;
173 bad_proto = FALSE;
174 }
175 }
176 }
177
178 } else {
179 if (buflen == 8) {
180 /* The client sent ONLY "SSH-2.0-". OpenSSH handles this as a
181 * "Protocol mismatch", so shall we.
182 */
183 bad_proto = TRUE;
184
185 } else {
186 banner = buf + 8;
187 }
188 }
189 }
190
191 if (banner != NULL) {
192 char *k, *v;
193
194 k = pstrdup(session.pool, "SFTP_CLIENT_BANNER");
195 v = pstrdup(session.pool, banner);
196 pr_env_unset(session.pool, k);
197 pr_env_set(session.pool, k, v);
198 (void) pr_table_add(session.notes, k, v, 0);
199 }
200
201 if (bad_proto) {
202 const char *errstr = "Protocol mismatch.\n";
203
204 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
205 "Bad protocol version '%.100s' from %s", buf,
206 pr_netaddr_get_ipstr(session.c->remote_addr));
207
208 if (write(conn->wfd, errstr, strlen(errstr)) < 0) {
209 pr_trace_msg("ssh2", 9,
210 "error sending 'Protocol mismatch' message to client: %s",
211 strerror(errno));
212 }
213
214 errno = EINVAL;
215 return -1;
216 }
217
218 break;
219 }
220
221 sftp_client_version = pstrdup(sftp_pool, buf);
222 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
223 "received client version '%s'", sftp_client_version);
224
225 if (sftp_interop_handle_version(sftp_pool, sftp_client_version) < 0) {
226 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
227 "error checking client version '%s' for interoperability: %s",
228 sftp_client_version, strerror(errno));
229 }
230
231 return 0;
232 }
233
sftp_cmd_loop(server_rec * s,conn_t * conn)234 static void sftp_cmd_loop(server_rec *s, conn_t *conn) {
235 int res;
236 char buf[256];
237 const char *k, *v;
238
239 sftp_conn = conn;
240 pr_session_set_protocol("ssh2");
241
242 if (sftp_opts & SFTP_OPT_PESSIMISTIC_KEXINIT) {
243 /* If we are being pessimistic, we will send our version string to the
244 * client now, and send our KEXINIT message later.
245 */
246 res = sftp_ssh2_packet_send_version();
247
248 } else {
249 /* If we are being optimistic, we can reduce the connection latency
250 * by sending our KEXINIT message now; this will have the server version
251 * string automatically prepended.
252 */
253 res = sftp_kex_send_first_kexinit();
254 }
255
256 if (res < 0) {
257 pr_session_disconnect(&sftp_module, PR_SESS_DISCONNECT_BY_APPLICATION,
258 NULL);
259 }
260
261 res = sftp_get_client_version(conn);
262 if (res < 0) {
263 pr_session_disconnect(&sftp_module, PR_SESS_DISCONNECT_BY_APPLICATION,
264 NULL);
265 }
266
267 sftp_kex_init(sftp_client_version, sftp_server_version);
268 sftp_service_init();
269 sftp_auth_init();
270 sftp_channel_init();
271
272 /* Set the initial timeout for reading packets from clients. Using
273 * a value of zero sets the default timeout value (i.e. TimeoutIdle).
274 */
275 sftp_ssh2_packet_set_poll_timeout(0);
276
277 k = pstrdup(session.pool, "SFTP");
278 v = pstrdup(session.pool, "1");
279 pr_env_set(session.pool, k, v);
280 (void) pr_table_add(session.notes, k, v, 0);
281
282 k = pstrdup(session.pool, "SFTP_LIBRARY_VERSION");
283 v = pstrdup(session.pool, OPENSSL_VERSION_TEXT);
284 pr_env_set(session.pool, k, v);
285 (void) pr_table_add(session.notes, k, v, 0);
286
287 memset(buf, '\0', sizeof(buf));
288 k = pstrdup(session.pool, "SSH_CONNECTION");
289 pr_snprintf(buf, sizeof(buf)-1, "%.50s %d %.50s %d",
290 pr_netaddr_get_ipstr(conn->remote_addr), conn->remote_port,
291 pr_netaddr_get_ipstr(conn->local_addr), conn->local_port);
292 v = pstrdup(session.pool, buf);
293 pr_env_set(session.pool, k, v);
294 (void) pr_table_add(session.notes, k, v, 0);
295
296 /* If we didn't send our KEXINIT earlier, send it now. */
297 if (sftp_opts & SFTP_OPT_PESSIMISTIC_KEXINIT) {
298 res = sftp_kex_send_first_kexinit();
299 if (res < 0) {
300 pr_session_disconnect(&sftp_module, PR_SESS_DISCONNECT_BY_APPLICATION,
301 NULL);
302 }
303 }
304
305 while (TRUE) {
306 pr_signals_handle();
307
308 res = sftp_ssh2_packet_handle();
309 if (res < 0) {
310 break;
311 }
312 }
313
314 return;
315 }
316
317 /* Configuration handlers
318 */
319
320 /* usage: SFTPAcceptEnv env1 ... envN */
set_sftpacceptenv(cmd_rec * cmd)321 MODRET set_sftpacceptenv(cmd_rec *cmd) {
322 register unsigned int i;
323 config_rec *c;
324 array_header *accepted_envs;
325
326 if (cmd->argc < 2) {
327 CONF_ERROR(cmd, "wrong number of parameters");
328 }
329
330 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
331
332 c = add_config_param(cmd->argv[0], 1, NULL);
333 accepted_envs = make_array(c->pool, 0, sizeof(char *));
334
335 for (i = 1; i < cmd->argc; i++) {
336 *((char **) push_array(accepted_envs)) = pstrdup(c->pool, cmd->argv[i]);
337 }
338 c->argv[0] = (void *) accepted_envs;
339
340 return PR_HANDLED(cmd);
341 }
342
343 /* usage: SFTPAuthMethods method-list1 ... method-listN */
set_sftpauthmeths(cmd_rec * cmd)344 MODRET set_sftpauthmeths(cmd_rec *cmd) {
345 register unsigned int i;
346 config_rec *c;
347 array_header *auth_chains;
348
349 if (cmd->argc < 2) {
350 CONF_ERROR(cmd, "Wrong number of parameters");
351 }
352
353 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
354
355 c = add_config_param(cmd->argv[0], 1, NULL);
356 auth_chains = make_array(c->pool, 0, sizeof(struct sftp_auth_chain *));
357
358 for (i = 1; i < cmd->argc; i++) {
359 array_header *method_names;
360 register unsigned int j;
361 struct sftp_auth_chain *auth_chain;
362
363 method_names = sftp_auth_chain_parse_method_chain(cmd->tmp_pool,
364 cmd->argv[i]);
365 if (method_names == NULL) {
366 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
367 "invalid authentication parameter: ", (char *) cmd->argv[i], NULL));
368 }
369
370 auth_chain = sftp_auth_chain_alloc(c->pool);
371 for (j = 0; j < method_names->nelts; j++) {
372 int res;
373 char *name;
374 unsigned int method_id = 0;
375 const char *method_name = NULL, *submethod_name = NULL;
376
377 name = ((char **) method_names->elts)[j];
378
379 res = sftp_auth_chain_parse_method(c->pool, name, &method_id,
380 &method_name, &submethod_name);
381 if (res < 0) {
382 /* Make for a slightly better/more informative error message. */
383 if (method_id == SFTP_AUTH_FL_METH_KBDINT) {
384 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
385 "unsupported authentication method '", name,
386 "': No drivers loaded", NULL));
387
388 } else {
389 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
390 "unsupported authentication method '", name, "': ",
391 strerror(errno), NULL));
392 }
393 }
394
395 sftp_auth_chain_add_method(auth_chain, method_id, method_name,
396 submethod_name);
397 }
398
399 if (sftp_auth_chain_isvalid(auth_chain) < 0) {
400 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
401 "unsupportable chain of authentication methods '",
402 (char *) cmd->argv[i], "': ", strerror(errno), NULL));
403 }
404
405 *((struct sftp_auth_chain **) push_array(auth_chains)) = auth_chain;
406 }
407
408 c->argv[0] = auth_chains;
409 return PR_HANDLED(cmd);
410 }
411
412 /* usage: SFTPAuthorized{Host,User}Keys store1 ... */
set_sftpauthorizedkeys(cmd_rec * cmd)413 MODRET set_sftpauthorizedkeys(cmd_rec *cmd) {
414 register unsigned int i;
415 int requested_key_type = 0;
416 config_rec *c;
417
418 if (cmd->argc < 2) {
419 CONF_ERROR(cmd, "wrong number of parameters");
420 }
421
422 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
423
424 if (strncasecmp(cmd->argv[0], "SFTPAuthorizedHostKeys", 23) == 0) {
425 requested_key_type = SFTP_SSH2_HOST_KEY_STORE;
426
427 } else if (strncasecmp(cmd->argv[0], "SFTPAuthorizedUserKeys", 23) == 0) {
428 requested_key_type = SFTP_SSH2_USER_KEY_STORE;
429 }
430
431 for (i = 1; i < cmd->argc; i++) {
432 char *ptr;
433
434 /* Separate the parameter into its separate store-type:store-info pieces. */
435 ptr = strchr(cmd->argv[i], ':');
436 if (ptr == NULL) {
437 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "badly formatted parameter: '",
438 (char *) cmd->argv[i], "'", NULL));
439 }
440 *ptr = '\0';
441
442 /* Verify that the requested store type has been registered, and supports
443 * the type of keystore requested (host or user key).
444 */
445 if (sftp_keystore_supports_store(cmd->argv[i], requested_key_type) < 0) {
446 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unsupported key store: '",
447 (char *) cmd->argv[i], "'", NULL));
448 }
449
450 *ptr = ':';
451 }
452
453 c = add_config_param(cmd->argv[0], 0);
454 c->argc = cmd->argc-1;
455 c->argv = pcalloc(c->pool, c->argc * (sizeof(char *)));
456 for (i = 1; i < cmd->argc; i++) {
457 c->argv[i-1] = pstrdup(c->pool, cmd->argv[i]);
458 }
459
460 return PR_HANDLED(cmd);
461 }
462
463 /* usage: SFTPCiphers list */
set_sftpciphers(cmd_rec * cmd)464 MODRET set_sftpciphers(cmd_rec *cmd) {
465 register unsigned int i;
466 config_rec *c;
467
468 if (cmd->argc < 2) {
469 CONF_ERROR(cmd, "Wrong number of parameters");
470 }
471
472 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
473
474 for (i = 1; i < cmd->argc; i++) {
475 if (sftp_crypto_get_cipher(cmd->argv[i], NULL, NULL) == NULL) {
476 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
477 "unsupported cipher algorithm: ", (char *) cmd->argv[i], NULL));
478 }
479 }
480
481 c = add_config_param(cmd->argv[0], cmd->argc-1, NULL);
482 for (i = 1; i < cmd->argc; i++) {
483 c->argv[i-1] = pstrdup(c->pool, cmd->argv[i]);
484 }
485
486 return PR_HANDLED(cmd);
487 }
488
489 /* usage: SFTPClientAlive count interval */
set_sftpclientalive(cmd_rec * cmd)490 MODRET set_sftpclientalive(cmd_rec *cmd) {
491 int count, interval;
492 config_rec *c;
493
494 CHECK_ARGS(cmd, 2);
495 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
496
497 count = atoi(cmd->argv[1]);
498 if (count < 0) {
499 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "max count '",
500 (char *) cmd->argv[1], "' must be equal to or greater than zero", NULL));
501 }
502
503 interval = atoi(cmd->argv[2]);
504 if (interval < 0) {
505 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "interval '", (char *) cmd->argv[2],
506 "' must be equal to or greater than zero", NULL));
507 }
508
509 c = add_config_param(cmd->argv[0], 2, NULL, NULL);
510 c->argv[0] = palloc(c->pool, sizeof(unsigned int));
511 *((unsigned int *) c->argv[0]) = count;
512 c->argv[1] = palloc(c->pool, sizeof(unsigned int));
513 *((unsigned int *) c->argv[1]) = interval;
514
515 return PR_HANDLED(cmd);
516 }
517
518 /* usage: SFTPClientMatch pattern key1 val1 ... */
set_sftpclientmatch(cmd_rec * cmd)519 MODRET set_sftpclientmatch(cmd_rec *cmd) {
520 #ifdef PR_USE_REGEX
521 register unsigned int i;
522 config_rec *c;
523 pr_table_t *tab;
524 pr_regex_t *pre;
525 int res;
526
527 if (cmd->argc < 4) {
528 CONF_ERROR(cmd, "Wrong number of parameters");
529
530 } else {
531 int npairs;
532
533 /* Make sure we have an even number of args for the key/value pairs. */
534
535 npairs = cmd->argc - 2;
536 if (npairs % 2 != 0) {
537 CONF_ERROR(cmd, "Wrong number of parameters");
538 }
539 }
540
541 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
542
543 pre = pr_regexp_alloc(&sftp_module);
544
545 res = pr_regexp_compile(pre, cmd->argv[1], REG_EXTENDED|REG_NOSUB);
546 if (res != 0) {
547 char errstr[200];
548
549 memset(errstr, '\0', sizeof(errstr));
550 pr_regexp_error(res, pre, errstr, sizeof(errstr));
551 pr_regexp_free(NULL, pre);
552
553 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", (char *) cmd->argv[1],
554 "' failed regex compilation: ", errstr, NULL));
555 }
556
557 c = add_config_param(cmd->argv[0], 3, NULL, NULL, NULL);
558 c->argv[0] = pstrdup(c->pool, cmd->argv[1]);
559 c->argv[1] = pre;
560
561 tab = pr_table_alloc(c->pool, 0);
562
563 c->argv[2] = tab;
564
565 for (i = 2; i < cmd->argc; i++) {
566 if (strncmp(cmd->argv[i], "channelWindowSize", 18) == 0) {
567 off_t window_size;
568 void *value;
569 char *arg, units[3];
570 size_t arglen;
571
572 arg = pstrdup(cmd->tmp_pool, cmd->argv[i+1]);
573 arglen = strlen(arg);
574
575 memset(units, '\0', sizeof(units));
576
577 if (arglen >= 3) {
578 /* Look for any possible "GB", "MB", "KB", "B" suffixes. */
579
580 if ((arg[arglen-2] == 'G' || arg[arglen-2] == 'g') &&
581 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
582 units[0] = 'G';
583 units[1] = 'B';
584 arg[arglen-2] = '\0';
585 arg[arglen-1] = '\0';
586 arglen -= 2;
587
588 } else if ((arg[arglen-2] == 'M' || arg[arglen-2] == 'm') &&
589 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
590 units[0] = 'M';
591 units[1] = 'B';
592 arg[arglen-2] = '\0';
593 arg[arglen-1] = '\0';
594 arglen -= 2;
595
596 } else if ((arg[arglen-2] == 'K' || arg[arglen-2] == 'k') &&
597 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
598 units[0] = 'K';
599 units[1] = 'B';
600 arg[arglen-2] = '\0';
601 arg[arglen-1] = '\0';
602 arglen -= 2;
603
604 } else if (arg[arglen-1] == 'B' || arg[arglen-1] == 'b') {
605 units[0] = 'B';
606 arg[arglen-1] = '\0';
607 arglen--;
608 }
609
610 } else if (arglen >= 2) {
611 /* Look for any possible "B" suffix. */
612 if (arg[arglen-1] == 'B' || arg[arglen-1] == 'b') {
613 units[0] = 'B';
614 arg[arglen-1] = '\0';
615 arglen--;
616 }
617 }
618
619 if (pr_str_get_nbytes(arg, units, &window_size) < 0) {
620 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
621 "error parsing 'channelWindowSize' value ", cmd->argv[i+1], ": ",
622 strerror(errno), NULL));
623 }
624
625 value = palloc(c->pool, sizeof(uint32_t));
626 *((uint32_t *) value) = (uint32_t) window_size;
627
628 if (pr_table_add(tab, pstrdup(c->pool, "channelWindowSize"), value,
629 sizeof(uint32_t)) < 0) {
630 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
631 "error storing 'channelWindowSize' value: ", strerror(errno), NULL));
632 }
633
634 /* Don't forget to advance i past the value. */
635 i++;
636
637 } else if (strncmp(cmd->argv[i], "channelPacketSize", 18) == 0) {
638 off_t packet_size;
639 void *value;
640 char *arg, units[3];
641 size_t arglen;
642
643 arg = pstrdup(cmd->tmp_pool, cmd->argv[i+1]);
644 arglen = strlen(arg);
645
646 memset(units, '\0', sizeof(units));
647
648 if (arglen >= 3) {
649 /* Look for any possible "GB", "MB", "KB", "B" suffixes. */
650
651 if ((arg[arglen-2] == 'G' || arg[arglen-2] == 'g') &&
652 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
653 units[0] = 'G';
654 units[1] = 'B';
655 arg[arglen-2] = '\0';
656 arg[arglen-1] = '\0';
657 arglen -= 2;
658
659 } else if ((arg[arglen-2] == 'M' || arg[arglen-2] == 'm') &&
660 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
661 units[0] = 'M';
662 units[1] = 'B';
663 arg[arglen-2] = '\0';
664 arg[arglen-1] = '\0';
665 arglen -= 2;
666
667 } else if ((arg[arglen-2] == 'K' || arg[arglen-2] == 'k') &&
668 (arg[arglen-1] == 'B' || arg[arglen-1] == 'b')) {
669 units[0] = 'K';
670 units[1] = 'B';
671 arg[arglen-2] = '\0';
672 arg[arglen-1] = '\0';
673 arglen -= 2;
674
675 } else if (arg[arglen-1] == 'B' || arg[arglen-1] == 'b') {
676 units[0] = 'B';
677 arg[arglen-1] = '\0';
678 arglen--;
679 }
680
681 } else if (arglen >= 2) {
682 /* Look for any possible "B" suffix. */
683 if (arg[arglen-1] == 'B' || arg[arglen-1] == 'b') {
684 units[0] = 'B';
685 arg[arglen-1] = '\0';
686 arglen--;
687 }
688 }
689
690 if (pr_str_get_nbytes(arg, units, &packet_size) < 0) {
691 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
692 "error parsing 'channelPacketSize' value ", cmd->argv[i+1], ": ",
693 strerror(errno), NULL));
694 }
695
696 if (packet_size > SFTP_MAX_PACKET_LEN) {
697 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
698 "'channelPacketSize' value ", cmd->argv[i+1], " too large, must be "
699 "less than 35000B", NULL));
700 }
701
702 value = palloc(c->pool, sizeof(uint32_t));
703 *((uint32_t *) value) = (uint32_t) packet_size;
704
705 if (pr_table_add(tab, pstrdup(c->pool, "channelPacketSize"), value,
706 sizeof(uint32_t)) < 0) {
707 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
708 "error storing 'channelPacketSize' value: ", strerror(errno), NULL));
709 }
710
711 /* Don't forget to advance i past the value. */
712 i++;
713
714 } else if (strncmp(cmd->argv[i], "pessimisticNewkeys", 19) == 0) {
715 int pessimistic_newkeys;
716 void *value;
717
718 pessimistic_newkeys = get_boolean(cmd, i+1);
719 if (pessimistic_newkeys == -1) {
720 CONF_ERROR(cmd, "expected Boolean parameter");
721 }
722
723 value = palloc(c->pool, sizeof(int));
724 *((int *) value) = pessimistic_newkeys;
725
726 if (pr_table_add(tab, pstrdup(c->pool, "pessimisticNewkeys"), value,
727 sizeof(int)) < 0) {
728 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
729 "error storing 'pessimisticNewkeys' value: ", strerror(errno), NULL));
730 }
731
732 /* Don't forget to advance i past the value. */
733 i++;
734
735 } else if (strncmp(cmd->argv[i], "sftpProtocolVersion", 20) == 0) {
736 void *min_value, *max_value;
737 char *ptr = NULL;
738
739 /* Check for a range of values. */
740 ptr = strchr(cmd->argv[i+1], '-');
741
742 if (ptr == NULL) {
743 long protocol_version;
744
745 /* Just a single value. */
746
747 protocol_version = strtol(cmd->argv[i+1], &ptr, 10);
748 if (ptr && *ptr) {
749 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
750 "badly formatted 'sftpProtocolVersion' value: ", cmd->argv[i+1],
751 NULL));
752 }
753
754 if (protocol_version < 1 ||
755 protocol_version > 6) {
756 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
757 "'sftpProtocolVersion' value ", cmd->argv[i+1],
758 " must be between 1 and 6: ", strerror(errno), NULL));
759 }
760
761 min_value = palloc(c->pool, sizeof(unsigned int));
762 *((unsigned int *) min_value) = (unsigned int) protocol_version;
763
764 max_value = palloc(c->pool, sizeof(unsigned int));
765 *((unsigned int *) max_value) = (unsigned int) protocol_version;
766
767 } else {
768 long min_version, max_version;
769 char *tmp = NULL;
770
771 /* We have a range of values. */
772
773 *ptr = '\0';
774 min_version = strtol(cmd->argv[i+1], &tmp, 10);
775
776 if (tmp && *tmp) {
777 *ptr = '-';
778 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
779 "badly formatted 'sftpProtocolVersion' value: ", cmd->argv[i+1],
780 NULL));
781 }
782 *ptr = '-';
783
784 if (min_version < 1 ||
785 min_version > 6) {
786 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
787 "'sftpProtocolVersion' value ", cmd->argv[i+1],
788 " must be between 1 and 6: ", strerror(errno), NULL));
789 }
790
791 min_value = palloc(c->pool, sizeof(unsigned int));
792 *((unsigned int *) min_value) = (unsigned int) min_version;
793
794 *ptr = '\0';
795 tmp = NULL;
796 max_version = strtol(ptr + 1, &tmp, 10);
797
798 if (tmp && *tmp) {
799 *ptr = '-';
800 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
801 "badly formatted 'sftpProtocolVersion' value: ", cmd->argv[i+1],
802 NULL));
803 }
804 *ptr = '-';
805
806 if (max_version < 1 ||
807 max_version > 6) {
808 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
809 "'sftpProtocolVersion' value ", cmd->argv[i+1],
810 " must be between 1 and 6: ", strerror(errno), NULL));
811 }
812
813 max_value = palloc(c->pool, sizeof(unsigned int));
814 *((unsigned int *) max_value) = (unsigned int) max_version;
815 }
816
817 if (pr_table_add(tab, pstrdup(c->pool, "sftpMinProtocolVersion"),
818 min_value, sizeof(unsigned int)) < 0) {
819 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
820 "error storing 'sftpProtocolVersion' value: ", strerror(errno),
821 NULL));
822 }
823
824 if (pr_table_add(tab, pstrdup(c->pool, "sftpMaxProtocolVersion"),
825 max_value, sizeof(unsigned int)) < 0) {
826 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
827 "error storing 'sftpProtocolVersion' value: ", strerror(errno),
828 NULL));
829 }
830
831 /* Don't forget to advance i past the value. */
832 i++;
833
834 } else if (strncmp(cmd->argv[i], "sftpUTF8ProtocolVersion", 24) == 0) {
835 #ifdef PR_USE_NLS
836 char *ptr = NULL;
837 void *value;
838 long protocol_version;
839
840 protocol_version = strtol(cmd->argv[i+1], &ptr, 10);
841 if (ptr && *ptr) {
842 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
843 "badly formatted 'sftpUTF8ProtocolVersion' value: ", cmd->argv[i+1],
844 NULL));
845 }
846
847 if (protocol_version < 1 ||
848 protocol_version > 6) {
849 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
850 "'sftpUTF8ProtocolVersion' value ", cmd->argv[i+1], NULL));
851 }
852
853 value = palloc(c->pool, sizeof(unsigned int));
854 *((unsigned int *) value) = (unsigned int) protocol_version;
855
856 if (pr_table_add(tab, pstrdup(c->pool, "sftpUTF8ProtocolVersion"),
857 value, sizeof(unsigned int)) < 0) {
858 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
859 "error storing 'sftpUTF8ProtocolVersion' value: ", strerror(errno),
860 NULL));
861 }
862
863 /* Don't forget to advance i past the value. */
864 i++;
865 #else
866 CONF_ERROR(cmd, "'sftpUTF8ProtocolVersion' requires NLS support (--enable-nls)");
867 #endif /* PR_USE_NLS */
868 } else {
869 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown SFTPClientMatch key: '",
870 cmd->argv[i], "'", NULL));
871 }
872 }
873
874 return PR_HANDLED(cmd);
875
876 #else /* no regular expression support at the moment */
877 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "The ", cmd->argv[0],
878 " directive cannot be used on this system, as you do not have POSIX "
879 "compliant regex support", NULL));
880 #endif
881 }
882
883 /* usage: SFTPCompression on|off|delayed */
set_sftpcompression(cmd_rec * cmd)884 MODRET set_sftpcompression(cmd_rec *cmd) {
885 config_rec *c;
886 int bool;
887
888 if (cmd->argc != 2) {
889 CONF_ERROR(cmd, "Wrong number of parameters");
890 }
891
892 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
893
894 #ifdef HAVE_ZLIB_H
895 bool = get_boolean(cmd, 1);
896 if (bool == -1) {
897 if (strncasecmp(cmd->argv[1], "delayed", 8) != 0) {
898 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
899 "unknown compression setting: ", cmd->argv[1], NULL));
900 }
901
902 bool = 2;
903 }
904 #else
905 pr_log_debug(DEBUG0, MOD_SFTP_VERSION ": platform lacks zlib support, ignoring SFTPCompression");
906 bool = 0;
907 #endif /* !HAVE_ZLIB_H */
908
909 c = add_config_param(cmd->argv[0], 1, NULL);
910 c->argv[0] = pcalloc(c->pool, sizeof(int));
911 *((int *) c->argv[0]) = bool;
912
913 return PR_HANDLED(cmd);
914 }
915
916 /* usage: SFTPCryptoDevice engine|"ALL" */
set_sftpcryptodevice(cmd_rec * cmd)917 MODRET set_sftpcryptodevice(cmd_rec *cmd) {
918 #if OPENSSL_VERSION_NUMBER > 0x000907000L
919 CHECK_ARGS(cmd, 1);
920 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
921
922 (void) add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
923 return PR_HANDLED(cmd);
924
925 #else /* OpenSSL is too old for ENGINE support */
926 CONF_ERROR(cmd, "unsupportable (OpenSSL version is too old");
927 #endif
928 }
929
930 /* usage: SFTPDHParamFile path */
set_sftpdhparamfile(cmd_rec * cmd)931 MODRET set_sftpdhparamfile(cmd_rec *cmd) {
932 CHECK_ARGS(cmd, 1);
933 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
934
935 if (pr_fs_valid_path(cmd->argv[1]) < 0) {
936 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
937 "unable to use '", cmd->argv[1], "'", NULL));
938 }
939
940 (void) add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
941 return PR_HANDLED(cmd);
942 }
943
944 /* usage: SFTPDigests list */
set_sftpdigests(cmd_rec * cmd)945 MODRET set_sftpdigests(cmd_rec *cmd) {
946 register unsigned int i;
947 config_rec *c;
948
949 if (cmd->argc < 2) {
950 CONF_ERROR(cmd, "Wrong number of parameters");
951 }
952
953 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
954
955 for (i = 1; i < cmd->argc; i++) {
956 if (sftp_crypto_get_digest(cmd->argv[i], NULL) == NULL) {
957 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
958 "unsupported digest algorithm: ", cmd->argv[i], NULL));
959 }
960 }
961
962 c = add_config_param(cmd->argv[0], cmd->argc-1, NULL);
963 for (i = 1; i < cmd->argc; i++) {
964 c->argv[i-1] = pstrdup(c->pool, cmd->argv[i]);
965 }
966
967 return PR_HANDLED(cmd);
968 }
969
970 /* usage: SFTPDisplayBanner path */
set_sftpdisplaybanner(cmd_rec * cmd)971 MODRET set_sftpdisplaybanner(cmd_rec *cmd) {
972 CHECK_ARGS(cmd, 1);
973 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
974
975 add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
976 return PR_HANDLED(cmd);
977 }
978
979 /* usage: SFTPEngine on|off */
set_sftpengine(cmd_rec * cmd)980 MODRET set_sftpengine(cmd_rec *cmd) {
981 int bool = 1;
982 config_rec *c;
983
984 CHECK_ARGS(cmd, 1);
985 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
986
987 bool = get_boolean(cmd, 1);
988 if (bool == -1)
989 CONF_ERROR(cmd, "expected Boolean parameter");
990
991 c = add_config_param(cmd->argv[0], 1, NULL);
992 c->argv[0] = pcalloc(c->pool, sizeof(int));
993 *((int *) c->argv[0]) = bool;
994
995 return PR_HANDLED(cmd);
996 }
997
998 /* usage: SFTPExtensions ext1 ... extN */
set_sftpextensions(cmd_rec * cmd)999 MODRET set_sftpextensions(cmd_rec *cmd) {
1000 register unsigned int i;
1001 config_rec *c;
1002 unsigned long ext_flags = SFTP_FXP_EXT_DEFAULT;
1003
1004 if (cmd->argc < 2) {
1005 CONF_ERROR(cmd, "wrong number of parameters");
1006 }
1007
1008 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1009
1010 for (i = 1; i < cmd->argc; i++) {
1011 char action, *ext;
1012
1013 ext = cmd->argv[i];
1014 action = *ext;
1015
1016 if (action != '-' &&
1017 action != '+') {
1018 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad option: '", ext, "'",
1019 NULL));
1020 }
1021
1022 ext++;
1023
1024 if (strncasecmp(ext, "checkFile", 10) == 0) {
1025 switch (action) {
1026 case '-':
1027 ext_flags &= ~SFTP_FXP_EXT_CHECK_FILE;
1028 break;
1029
1030 case '+':
1031 ext_flags |= SFTP_FXP_EXT_CHECK_FILE;
1032 break;
1033 }
1034
1035 } else if (strncasecmp(ext, "copyFile", 9) == 0) {
1036 switch (action) {
1037 case '-':
1038 ext_flags &= ~SFTP_FXP_EXT_COPY_FILE;
1039 break;
1040
1041 case '+':
1042 ext_flags |= SFTP_FXP_EXT_COPY_FILE;
1043 break;
1044 }
1045
1046 } else if (strncasecmp(ext, "fsync", 6) == 0) {
1047 switch (action) {
1048 case '-':
1049 ext_flags &= ~SFTP_FXP_EXT_FSYNC;
1050 break;
1051
1052 case '+':
1053 ext_flags |= SFTP_FXP_EXT_FSYNC;
1054 break;
1055 }
1056
1057 } else if (strncasecmp(ext, "vendorID", 9) == 0) {
1058 switch (action) {
1059 case '-':
1060 ext_flags &= ~SFTP_FXP_EXT_VENDOR_ID;
1061 break;
1062
1063 case '+':
1064 ext_flags |= SFTP_FXP_EXT_VENDOR_ID;
1065 break;
1066 }
1067
1068 } else if (strncasecmp(ext, "versionSelect", 14) == 0) {
1069 switch (action) {
1070 case '-':
1071 ext_flags &= ~SFTP_FXP_EXT_VERSION_SELECT;
1072 break;
1073
1074 case '+':
1075 ext_flags |= SFTP_FXP_EXT_VERSION_SELECT;
1076 break;
1077 }
1078
1079 } else if (strncasecmp(ext, "posixRename", 12) == 0) {
1080 switch (action) {
1081 case '-':
1082 ext_flags &= ~SFTP_FXP_EXT_POSIX_RENAME;
1083 break;
1084
1085 case '+':
1086 ext_flags |= SFTP_FXP_EXT_POSIX_RENAME;
1087 break;
1088 }
1089
1090 } else if (strncasecmp(ext, "spaceAvailable", 15) == 0) {
1091 #ifdef HAVE_SYS_STATVFS_H
1092 switch (action) {
1093 case '-':
1094 ext_flags &= ~SFTP_FXP_EXT_SPACE_AVAIL;
1095 break;
1096
1097 case '+':
1098 ext_flags |= SFTP_FXP_EXT_SPACE_AVAIL;
1099 break;
1100 }
1101 #else
1102 pr_log_debug(DEBUG0, "%s: spaceAvailable extension not supported "
1103 "on this system; requires statvfs(3) support", cmd->argv[0]);
1104 #endif /* !HAVE_SYS_STATVFS_H */
1105
1106
1107 } else if (strncasecmp(ext, "statvfs", 8) == 0) {
1108 #ifdef HAVE_SYS_STATVFS_H
1109 switch (action) {
1110 case '-':
1111 ext_flags &= ~SFTP_FXP_EXT_STATVFS;
1112 break;
1113
1114 case '+':
1115 ext_flags |= SFTP_FXP_EXT_STATVFS;
1116 break;
1117 }
1118 #else
1119 pr_log_debug(DEBUG0, "%s: statvfs@openssh.com extension not supported "
1120 "on this system; requires statvfs(3) support", cmd->argv[0]);
1121 #endif /* !HAVE_SYS_STATVFS_H */
1122
1123 } else if (strncasecmp(ext, "hardlink", 9) == 0) {
1124 switch (action) {
1125 case '-':
1126 ext_flags &= ~SFTP_FXP_EXT_HARDLINK;
1127 break;
1128
1129 case '+':
1130 ext_flags |= SFTP_FXP_EXT_HARDLINK;
1131 break;
1132 }
1133
1134 } else if (strncasecmp(ext, "xattr", 8) == 0) {
1135 #ifdef HAVE_SYS_XATTR_H
1136 switch (action) {
1137 case '-':
1138 ext_flags &= ~SFTP_FXP_EXT_XATTR;
1139 break;
1140
1141 case '+':
1142 ext_flags |= SFTP_FXP_EXT_XATTR;
1143 break;
1144 }
1145 #else
1146 pr_log_debug(DEBUG0, "%s: xattr@proftpd.org extension not supported "
1147 "on this system; requires extended attribute support",
1148 (char *) cmd->argv[0]);
1149 #endif /* HAVE_SYS_XATTR_H */
1150
1151 } else {
1152 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown extension: '",
1153 ext, "'", NULL));
1154 }
1155 }
1156
1157 c = add_config_param(cmd->argv[0], 1, NULL);
1158 c->argv[0] = palloc(c->pool, sizeof(unsigned long));
1159 *((unsigned long *) c->argv[0]) = ext_flags;
1160
1161 return PR_HANDLED(cmd);
1162 }
1163
1164 /* usage: SFTPHostKey path|"agent:/..."|"NoRSA"|"NoDSA"|"NoECDSA"|"NoED25519" */
set_sftphostkey(cmd_rec * cmd)1165 MODRET set_sftphostkey(cmd_rec *cmd) {
1166 struct stat st;
1167 int flags = 0;
1168 config_rec *c;
1169 const char *path = NULL;
1170
1171 CHECK_ARGS(cmd, 1);
1172 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1173
1174 if (strncasecmp(cmd->argv[1], "NoRSA", 6) == 0) {
1175 flags |= SFTP_HOSTKEY_FL_CLEAR_RSA_KEY;
1176
1177 } else if (strncasecmp(cmd->argv[1], "NoDSA", 6) == 0) {
1178 flags |= SFTP_HOSTKEY_FL_CLEAR_DSA_KEY;
1179
1180 } else if (strncasecmp(cmd->argv[1], "NoECDSA", 8) == 0) {
1181 flags |= SFTP_HOSTKEY_FL_CLEAR_ECDSA_KEY;
1182
1183 } else if (strncasecmp(cmd->argv[1], "NoED25519", 10) == 0) {
1184 flags |= SFTP_HOSTKEY_FL_CLEAR_ED25519_KEY;
1185 }
1186
1187 if (strncmp(cmd->argv[1], "agent:", 6) != 0 &&
1188 flags == 0) {
1189 int res, xerrno;
1190
1191 path = cmd->argv[1];
1192 if (*path != '/') {
1193 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "must be an absolute path: ",
1194 path, NULL));
1195 }
1196
1197 PRIVS_ROOT
1198 res = stat(path, &st);
1199 xerrno = errno;
1200 PRIVS_RELINQUISH
1201
1202 if (res < 0) {
1203 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unable to check '", path,
1204 "': ", strerror(xerrno), NULL));
1205 }
1206
1207 if ((st.st_mode & S_IRWXG) ||
1208 (st.st_mode & S_IRWXO)) {
1209 int insecure_hostkey_perms = FALSE;
1210
1211 /* Check for the InsecureHostKeyPerms SFTPOption. */
1212 c = find_config(cmd->server->conf, CONF_PARAM, "SFTPOptions", FALSE);
1213 while (c != NULL) {
1214 unsigned long opts;
1215
1216 pr_signals_handle();
1217
1218 opts = *((unsigned long *) c->argv[0]);
1219 if (opts & SFTP_OPT_INSECURE_HOSTKEY_PERMS) {
1220 insecure_hostkey_perms = TRUE;
1221 break;
1222 }
1223
1224 c = find_config_next(c, c->next, CONF_PARAM, "SFTPOptions", FALSE);
1225 }
1226
1227 if (insecure_hostkey_perms) {
1228 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION ": unable to use '%s' "
1229 "as host key, as it is group- or world-accessible", path);
1230
1231 } else {
1232 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unable to use '", path,
1233 "' as host key, as it is group- or world-accessible", NULL));
1234 }
1235 }
1236 }
1237
1238 c = add_config_param_str(cmd->argv[0], 2, NULL, NULL);
1239 c->argv[0] = pstrdup(c->pool, path);
1240 c->argv[1] = palloc(c->pool, sizeof(int));
1241 *((int *) c->argv[1]) = flags;
1242 return PR_HANDLED(cmd);
1243 }
1244
1245 /* usage: SFTPKeyBlacklist "none"|path */
set_sftpkeyblacklist(cmd_rec * cmd)1246 MODRET set_sftpkeyblacklist(cmd_rec *cmd) {
1247 CHECK_ARGS(cmd, 1);
1248 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1249
1250 if (strncasecmp(cmd->argv[1], "none", 5) != 0) {
1251 if (pr_fs_valid_path(cmd->argv[1]) < 0) {
1252 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "path '", cmd->argv[1],
1253 "' not an absolute path", NULL));
1254 }
1255
1256 if (!exists2(cmd->tmp_pool, cmd->argv[1])) {
1257 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "path '", cmd->argv[1],
1258 "' not found", NULL));
1259 }
1260 }
1261
1262 add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1263 return PR_HANDLED(cmd);
1264 }
1265
1266 /* usage: SFTPKeyExchanges list */
set_sftpkeyexchanges(cmd_rec * cmd)1267 MODRET set_sftpkeyexchanges(cmd_rec *cmd) {
1268 register unsigned int i;
1269 config_rec *c;
1270 char *exchanges = "";
1271
1272 if (cmd->argc < 2) {
1273 CONF_ERROR(cmd, "Wrong number of parameters");
1274 }
1275
1276 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1277
1278 for (i = 1; i < cmd->argc; i++) {
1279 if (strncmp(cmd->argv[i], "diffie-hellman-group1-sha1", 27) != 0 &&
1280 strncmp(cmd->argv[i], "diffie-hellman-group14-sha1", 28) != 0 &&
1281 #if (OPENSSL_VERSION_NUMBER > 0x000907000L && defined(OPENSSL_FIPS)) || \
1282 (OPENSSL_VERSION_NUMBER > 0x000908000L)
1283 strncmp(cmd->argv[i], "diffie-hellman-group14-sha256", 30) != 0 &&
1284 strncmp(cmd->argv[i], "diffie-hellman-group16-sha512", 30) != 0 &&
1285 strncmp(cmd->argv[i], "diffie-hellman-group18-sha512", 30) != 0 &&
1286 strncmp(cmd->argv[i], "diffie-hellman-group-exchange-sha256", 37) != 0 &&
1287 #endif
1288 strncmp(cmd->argv[i], "diffie-hellman-group-exchange-sha1", 35) != 0 &&
1289 #ifdef PR_USE_OPENSSL_ECC
1290 strncmp(cmd->argv[i], "ecdh-sha2-nistp256", 19) != 0 &&
1291 strncmp(cmd->argv[i], "ecdh-sha2-nistp384", 19) != 0 &&
1292 strncmp(cmd->argv[i], "ecdh-sha2-nistp521", 19) != 0 &&
1293 #endif /* PR_USE_OPENSSL_ECC */
1294 #if defined(HAVE_SODIUM_H) && defined(HAVE_SHA256_OPENSSL)
1295 strncmp(cmd->argv[i], "curve25519-sha256@libssh.org", 22) != 0 &&
1296 #endif /* HAVE_SODIUM_H and HAVE_SHA256_OPENSSL */
1297 strncmp(cmd->argv[i], "rsa1024-sha1", 13) != 0) {
1298
1299 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
1300 "unsupported key exchange algorithm: ", cmd->argv[i], NULL));
1301 }
1302 }
1303
1304 c = add_config_param(cmd->argv[0], 1, NULL);
1305
1306 for (i = 1; i < cmd->argc; i++) {
1307 exchanges = pstrcat(c->pool, exchanges, *exchanges ? "," : "", cmd->argv[i],
1308 NULL);
1309 }
1310 c->argv[0] = exchanges;
1311
1312 return PR_HANDLED(cmd);
1313 }
1314
1315 /* usage: SFTPKeyLimits limit1 ... limitN */
set_sftpkeylimits(cmd_rec * cmd)1316 MODRET set_sftpkeylimits(cmd_rec *cmd) {
1317 register unsigned int i;
1318 config_rec *c;
1319
1320 if (cmd->argc < 3 ||
1321 ((cmd->argc-1) % 2 != 0)) {
1322 CONF_ERROR(cmd, "wrong number of parameters");
1323 }
1324 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1325
1326 c = add_config_param(cmd->argv[0], 3, NULL, NULL, NULL);
1327
1328 for (i = 1; i < cmd->argc; i++) {
1329 if (strcasecmp(cmd->argv[i], "MinimumRSASize") == 0) {
1330 int nbits;
1331
1332 nbits = atoi(cmd->argv[++i]);
1333 if (nbits < 0) {
1334 CONF_ERROR(cmd, "minimum key size must be zero or greater");
1335 }
1336
1337 c->argv[0] = palloc(c->pool, sizeof(int));
1338 *((int *) c->argv[0]) = nbits;
1339
1340 } else if (strcasecmp(cmd->argv[i], "MinimumDSASize") == 0) {
1341 int nbits;
1342
1343 nbits = atoi(cmd->argv[++i]);
1344 if (nbits < 0) {
1345 CONF_ERROR(cmd, "minimum key size must be zero or greater");
1346 }
1347
1348 c->argv[1] = palloc(c->pool, sizeof(int));
1349 *((int *) c->argv[1]) = nbits;
1350
1351 } else if (strcasecmp(cmd->argv[i], "MinimumECSize") == 0) {
1352 int nbits;
1353
1354 nbits = atoi(cmd->argv[++i]);
1355 if (nbits < 0) {
1356 CONF_ERROR(cmd, "minimum key size must be zero or greater");
1357 }
1358
1359 c->argv[2] = palloc(c->pool, sizeof(int));
1360 *((int *) c->argv[2]) = nbits;
1361
1362 } else {
1363 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown SFTPKeyLimit '",
1364 cmd->argv[i], "'", NULL));
1365 }
1366 }
1367
1368 return PR_HANDLED(cmd);
1369 }
1370
1371 /* usage: SFTPLog path|"none" */
set_sftplog(cmd_rec * cmd)1372 MODRET set_sftplog(cmd_rec *cmd) {
1373 CHECK_ARGS(cmd, 1);
1374 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1375
1376 (void) add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1377 return PR_HANDLED(cmd);
1378 }
1379
1380 /* usage: SFTPMaxChannels max */
set_sftpmaxchannels(cmd_rec * cmd)1381 MODRET set_sftpmaxchannels(cmd_rec *cmd) {
1382 config_rec *c;
1383 unsigned int max;
1384 char *ptr = NULL;
1385
1386 CHECK_ARGS(cmd, 1);
1387 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1388
1389 max = strtoul(cmd->argv[1], &ptr, 10);
1390
1391 if (ptr && *ptr) {
1392 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "maximum channel count '",
1393 cmd->argv[1], "' must be numeric", NULL));
1394 }
1395
1396 if (max == 0) {
1397 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "maximum channel count '",
1398 cmd->argv[1], "' must be greater than zero", NULL));
1399 }
1400
1401 c = add_config_param(cmd->argv[0], 1, NULL);
1402 c->argv[0] = palloc(c->pool, sizeof(unsigned int));
1403 *((unsigned int *) c->argv[0]) = max;
1404
1405 return PR_HANDLED(cmd);
1406 }
1407
1408 /* usage: SFTPOptions opt1 ... optN */
set_sftpoptions(cmd_rec * cmd)1409 MODRET set_sftpoptions(cmd_rec *cmd) {
1410 register unsigned int i;
1411 config_rec *c;
1412 unsigned long opts = 0UL;
1413
1414 if (cmd->argc-1 == 0)
1415 CONF_ERROR(cmd, "wrong number of parameters");
1416
1417 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1418
1419 c = add_config_param(cmd->argv[0], 1, NULL);
1420
1421 for (i = 1; i < cmd->argc; i++) {
1422 if (strncmp(cmd->argv[i], "IgnoreSFTPUploadPerms", 22) == 0) {
1423 opts |= SFTP_OPT_IGNORE_SFTP_UPLOAD_PERMS;
1424
1425 } else if (strncmp(cmd->argv[i], "IgnoreSFTPSetOwners", 19) == 0) {
1426 opts |= SFTP_OPT_IGNORE_SFTP_SET_OWNERS;
1427
1428 } else if (strncmp(cmd->argv[i], "IgnoreSFTPSetPerms", 19) == 0) {
1429 opts |= SFTP_OPT_IGNORE_SFTP_SET_PERMS;
1430
1431 } else if (strncmp(cmd->argv[i], "IgnoreSFTPSetTimes", 19) == 0) {
1432 opts |= SFTP_OPT_IGNORE_SFTP_SET_TIMES;
1433
1434 } else if (strncmp(cmd->argv[i], "IgnoreSCPUploadPerms", 20) == 0) {
1435 opts |= SFTP_OPT_IGNORE_SCP_UPLOAD_PERMS;
1436
1437 } else if (strncmp(cmd->argv[i], "IgnoreSCPUploadTimes", 20) == 0) {
1438 opts |= SFTP_OPT_IGNORE_SCP_UPLOAD_TIMES;
1439
1440 } else if (strncmp(cmd->argv[i], "OldProtocolCompat", 18) == 0) {
1441 opts |= SFTP_OPT_OLD_PROTO_COMPAT;
1442
1443 /* This option also automatically enables PessimisticKexint,
1444 * as per the comments in RFC4253, Section 5.1.
1445 */
1446 opts |= SFTP_OPT_PESSIMISTIC_KEXINIT;
1447
1448 } else if (strncmp(cmd->argv[i], "PessimisticKexinit", 19) == 0) {
1449 opts |= SFTP_OPT_PESSIMISTIC_KEXINIT;
1450
1451 } else if (strncmp(cmd->argv[i], "MatchKeySubject", 16) == 0) {
1452 opts |= SFTP_OPT_MATCH_KEY_SUBJECT;
1453
1454 } else if (strcmp(cmd->argv[i], "AllowInsecureLogin") == 0) {
1455 opts |= SFTP_OPT_ALLOW_INSECURE_LOGIN;
1456
1457 } else if (strcmp(cmd->argv[i], "InsecureHostKeyPerms") == 0) {
1458 opts |= SFTP_OPT_INSECURE_HOSTKEY_PERMS;
1459
1460 } else if (strcmp(cmd->argv[i], "AllowWeakDH") == 0) {
1461 opts |= SFTP_OPT_ALLOW_WEAK_DH;
1462
1463 } else if (strcmp(cmd->argv[i], "IgnoreFIFOs") == 0) {
1464 opts |= SFTP_OPT_IGNORE_FIFOS;
1465
1466 } else if (strcmp(cmd->argv[i],
1467 "IgnoreSFTPUploadExtendedAttributes") == 0) {
1468 opts |= SFTP_OPT_IGNORE_SFTP_UPLOAD_XATTRS;
1469
1470 } else if (strcmp(cmd->argv[i], "IgnoreSFTPSetExtendedAttributes") == 0) {
1471 opts |= SFTP_OPT_IGNORE_SFTP_SET_XATTRS;
1472
1473 } else if (strcmp(cmd->argv[i], "IncludeSFTPTimes") == 0) {
1474 opts |= SFTP_OPT_INCLUDE_SFTP_TIMES;
1475
1476 } else if (strcmp(cmd->argv[i], "NoExtensionNegotiation") == 0) {
1477 opts |= SFTP_OPT_NO_EXT_INFO;
1478
1479 } else {
1480 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown SFTPOption '",
1481 cmd->argv[i], "'", NULL));
1482 }
1483 }
1484
1485 c->argv[0] = pcalloc(c->pool, sizeof(unsigned long));
1486 *((unsigned long *) c->argv[0]) = opts;
1487
1488 return PR_HANDLED(cmd);
1489 }
1490
1491 /* usage: SFTPPassPhraseProvider path */
set_sftppassphraseprovider(cmd_rec * cmd)1492 MODRET set_sftppassphraseprovider(cmd_rec *cmd) {
1493 struct stat st;
1494 char *path;
1495
1496 CHECK_ARGS(cmd, 1);
1497 CHECK_CONF(cmd, CONF_ROOT);
1498
1499 path = cmd->argv[1];
1500
1501 if (*path != '/') {
1502 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "must be a full path: '", path, "'",
1503 NULL));
1504 }
1505
1506 if (stat(path, &st) < 0) {
1507 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error checking '", path, "': ",
1508 strerror(errno), NULL));
1509 }
1510
1511 if (!S_ISREG(st.st_mode)) {
1512 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unable to use '", path,
1513 ": Not a regular file", NULL));
1514 }
1515
1516 add_config_param_str(cmd->argv[0], 1, path);
1517 return PR_HANDLED(cmd);
1518 }
1519
1520 /* usage: SFTPRekey "none"|"required" [interval bytes [timeout]] */
set_sftprekey(cmd_rec * cmd)1521 MODRET set_sftprekey(cmd_rec *cmd) {
1522 config_rec *c;
1523 int rekey_interval;
1524 unsigned long rekey_mbytes;
1525 char *ptr = NULL;
1526
1527 if (cmd->argc-1 < 1 || cmd->argc-1 > 4) {
1528 CONF_ERROR(cmd, "wrong number of parameters");
1529 }
1530
1531 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1532
1533 if (strncasecmp(cmd->argv[1], "none", 5) == 0) {
1534 c = add_config_param(cmd->argv[0], 1, NULL);
1535 c->argv[0] = pcalloc(c->pool, sizeof(int));
1536 *((int *) c->argv[0]) = FALSE;
1537
1538 return PR_HANDLED(cmd);
1539 }
1540
1541 if (strncasecmp(cmd->argv[1], "required", 9) != 0) {
1542 CONF_ERROR(cmd, "expected either 'none' or 'required'");
1543 }
1544
1545 if (cmd->argc-1 == 4) {
1546 /* The admin specified a rekey timeout as well. Nice. */
1547 c = add_config_param(cmd->argv[0], 4, NULL, NULL, NULL, NULL);
1548
1549 } else {
1550 /* The admin did not specify rekey timeout as well. Oh well. */
1551 c = add_config_param(cmd->argv[0], 3, NULL, NULL, NULL);
1552 }
1553
1554 c->argv[0] = pcalloc(c->pool, sizeof(int));
1555 *((int *) c->argv[0]) = TRUE;
1556
1557 if (cmd->argc-1 >= 2) {
1558 rekey_interval = atoi(cmd->argv[2]);
1559
1560 } else {
1561 /* Default: one hour. */
1562 rekey_interval = 3600;
1563 }
1564
1565 if (rekey_interval > 0) {
1566 c->argv[1] = pcalloc(c->pool, sizeof(int));
1567 *((int *) c->argv[1]) = rekey_interval;
1568
1569 } else {
1570 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "rekey interval '", cmd->argv[2],
1571 "' must be greater than zero", NULL));
1572 }
1573
1574 if (cmd->argc-1 >= 3) {
1575 rekey_mbytes = strtoul(cmd->argv[3], &ptr, 10);
1576 if (ptr && *ptr) {
1577 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "rekey MB '", cmd->argv[3],
1578 "' must be numeric", NULL));
1579 }
1580
1581 } else {
1582 /* Default: 2 GB */
1583 rekey_mbytes = (2 * 1024);
1584 }
1585
1586 c->argv[2] = pcalloc(c->pool, sizeof(off_t));
1587 *((off_t *) c->argv[2]) = (off_t) rekey_mbytes * 1024 * 1024;
1588
1589 if (cmd->argc-1 == 4) {
1590 int rekey_timeout;
1591
1592 rekey_timeout = atoi(cmd->argv[4]);
1593 if (rekey_timeout > 0) {
1594 c->argv[3] = pcalloc(c->pool, sizeof(int));
1595 *((int *) c->argv[3]) = rekey_timeout;
1596
1597 } else {
1598 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "rekey timeout '", cmd->argv[4],
1599 "' must be greater than zero", NULL));
1600 }
1601 }
1602
1603 return PR_HANDLED(cmd);
1604 }
1605
1606 /* usage: SFTPTrafficPolicy policy */
set_sftptrafficpolicy(cmd_rec * cmd)1607 MODRET set_sftptrafficpolicy(cmd_rec *cmd) {
1608 CHECK_ARGS(cmd, 1);
1609 CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1610
1611 if (sftp_tap_have_policy(cmd->argv[1]) < 0) {
1612 CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", cmd->argv[1],
1613 "' is not a recognized policy", NULL));
1614 }
1615
1616 (void) add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1617 return PR_HANDLED(cmd);
1618 }
1619
1620 /* Event handlers
1621 */
1622
sftp_chroot_ev(const void * event_data,void * user_data)1623 static void sftp_chroot_ev(const void *event_data, void *user_data) {
1624 (void) pr_table_add_dup(session.notes, "mod_sftp.chroot-path", event_data, 0);
1625 }
1626
1627 extern pid_t mpid;
1628
sftp_exit_ev(const void * event_data,void * user_data)1629 static void sftp_exit_ev(const void *event_data, void *user_data) {
1630
1631 /* Close any channels/sessions that remain open. */
1632 sftp_channel_free();
1633
1634 sftp_keys_free();
1635 sftp_kex_free();
1636
1637 sftp_crypto_free(0);
1638 sftp_utf8_free();
1639
1640 if (sftp_logfd >= 0) {
1641 (void) close(sftp_logfd);
1642 sftp_logfd = -1;
1643 }
1644 }
1645
sftp_ban_class_ev(const void * event_data,void * user_data)1646 static void sftp_ban_class_ev(const void *event_data, void *user_data) {
1647 const char *proto;
1648
1649 proto = pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT);
1650
1651 /* Only send an SSH2 DISCONNECT if we're dealing with an SSH2 client. */
1652 if (strncmp(proto, "SSH2", 5) == 0) {
1653 sftp_disconnect_send(SFTP_SSH2_DISCONNECT_BY_APPLICATION, "Banned",
1654 __FILE__, __LINE__, "");
1655 }
1656 }
1657
sftp_ban_host_ev(const void * event_data,void * user_data)1658 static void sftp_ban_host_ev(const void *event_data, void *user_data) {
1659 const char *proto;
1660
1661 proto = pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT);
1662
1663 /* Only send an SSH2 DISCONNECT if we're dealing with an SSH2 client. */
1664 if (strncmp(proto, "SSH2", 5) == 0) {
1665 char *ban_msg = "Banned", *name;
1666
1667 name = user_data;
1668 if (name != NULL) {
1669 ban_msg = pstrcat(sftp_pool, "Host ", name, " has been banned", NULL);
1670 }
1671
1672 sftp_disconnect_send(SFTP_SSH2_DISCONNECT_BY_APPLICATION, ban_msg,
1673 __FILE__, __LINE__, "");
1674 }
1675 }
1676
sftp_ban_user_ev(const void * event_data,void * user_data)1677 static void sftp_ban_user_ev(const void *event_data, void *user_data) {
1678 const char *proto;
1679
1680 proto = pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT);
1681
1682 /* Only send an SSH2 DISCONNECT if we're dealing with an SSH2 client. */
1683 if (strncmp(proto, "SSH2", 5) == 0) {
1684 char *ban_msg = "Banned", *name;
1685
1686 name = user_data;
1687 if (name != NULL) {
1688 ban_msg = pstrcat(sftp_pool, "User ", name, " has been banned", NULL);
1689 }
1690
1691 sftp_disconnect_send(SFTP_SSH2_DISCONNECT_BY_APPLICATION, ban_msg,
1692 __FILE__, __LINE__, "");
1693 }
1694 }
1695
sftp_max_conns_ev(const void * event_data,void * user_data)1696 static void sftp_max_conns_ev(const void *event_data, void *user_data) {
1697 const char *proto;
1698
1699 proto = pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT);
1700
1701 /* Only send an SSH2 DISCONNECT if we're dealing with an SSH2 client. */
1702 if (strncmp(proto, "SSH2", 5) == 0) {
1703 sftp_disconnect_send(SFTP_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS,
1704 "Maximum connections for host/user reached", __FILE__, __LINE__, "");
1705 }
1706 }
1707
1708 #if defined(PR_SHARED_MODULE)
sftp_mod_unload_ev(const void * event_data,void * user_data)1709 static void sftp_mod_unload_ev(const void *event_data, void *user_data) {
1710 if (strncmp((const char *) event_data, "mod_sftp.c", 11) == 0) {
1711 /* Unregister ourselves from all events. */
1712 pr_event_unregister(&sftp_module, NULL, NULL);
1713
1714 sftp_interop_free();
1715 sftp_keystore_free();
1716 sftp_keys_free();
1717 sftp_cipher_free();
1718 sftp_mac_free();
1719 pr_response_block(FALSE);
1720 sftp_utf8_free();
1721
1722 /* Clean up the OpenSSL stuff. */
1723 sftp_crypto_free(0);
1724
1725 destroy_pool(sftp_pool);
1726 sftp_pool = NULL;
1727
1728 close(sftp_logfd);
1729 sftp_logfd = -1;
1730 }
1731 }
1732 #endif
1733
sftp_postparse_ev(const void * event_data,void * user_data)1734 static void sftp_postparse_ev(const void *event_data, void *user_data) {
1735 config_rec *c;
1736 server_rec *s;
1737
1738 /* Initialize OpenSSL. */
1739 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1740 OPENSSL_config(NULL);
1741 #endif /* prior to OpenSSL-1.1.x */
1742 ERR_load_crypto_strings();
1743 OpenSSL_add_all_algorithms();
1744
1745 c = find_config(main_server->conf, CONF_PARAM, "SFTPPassPhraseProvider",
1746 FALSE);
1747 if (c) {
1748 sftp_keys_set_passphrase_provider(c->argv[0]);
1749 }
1750
1751 sftp_keys_get_passphrases();
1752
1753 /* Initialize the interoperability checks here, so that all session
1754 * processes share the compiled regexes in memory.
1755 */
1756 if (sftp_interop_init() < 0) {
1757 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION
1758 ": error preparing interoperability checks: %s", strerror(errno));
1759 }
1760
1761 /* Check for incompatible SFTPAuthMethods configurations. For example,
1762 * configuring:
1763 *
1764 * SFTPAuthMethods hostbased+password
1765 *
1766 * without also configuring SFTPAuthorizedHostKeys means that authentication
1767 * will never succeed.
1768 *
1769 * While here, we also check for unsupported configuration directives, and
1770 * warn if found.
1771 */
1772 for (s = (server_rec *) server_list->xas_list; s; s = s->next) {
1773 int supports_hostbased = FALSE, supports_publickey = FALSE, use_sftp = FALSE;
1774
1775 c = find_config(s->conf, CONF_PARAM, "SFTPEngine", FALSE);
1776 if (c != NULL) {
1777 use_sftp = *((int *) c->argv[0]);
1778 }
1779
1780 if (use_sftp == FALSE) {
1781 /* No need to check further if mod_sftp is not enabled. */
1782 continue;
1783 }
1784
1785 c = find_config(s->conf, CONF_PARAM, "SFTPAuthorizedHostKeys", FALSE);
1786 if (c != NULL) {
1787 supports_hostbased = TRUE;
1788 }
1789
1790 c = find_config(s->conf, CONF_PARAM, "SFTPAuthorizedUserKeys", FALSE);
1791 if (c != NULL) {
1792 supports_publickey = TRUE;
1793 }
1794
1795 c = find_config(s->conf, CONF_PARAM, "SFTPAuthMethods", FALSE);
1796 if (c != NULL) {
1797 register unsigned int i;
1798 array_header *auth_chains;
1799
1800 auth_chains = c->argv[0];
1801
1802 for (i = 0; i < auth_chains->nelts; i++) {
1803 register unsigned int j;
1804 struct sftp_auth_chain *auth_chain;
1805
1806 auth_chain = ((struct sftp_auth_chain **) auth_chains->elts)[i];
1807 for (j = 0; j < auth_chain->methods->nelts; j++) {
1808 struct sftp_auth_method *meth;
1809
1810 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[j];
1811
1812 if (meth->method_id == SFTP_AUTH_FL_METH_HOSTBASED &&
1813 supports_hostbased == FALSE) {
1814 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION
1815 ": Server '%s': cannot support authentication method '%s' "
1816 "without SFTPAuthorizedHostKeys configuration", s->ServerName,
1817 meth->method_name);
1818 pr_session_disconnect(&sftp_module, PR_SESS_DISCONNECT_BAD_CONFIG,
1819 NULL);
1820 }
1821
1822 if (meth->method_id == SFTP_AUTH_FL_METH_PUBLICKEY &&
1823 supports_publickey == FALSE) {
1824 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION
1825 ": Server '%s': cannot support authentication method '%s' "
1826 "without SFTPAuthorizedUserKeys configuration", s->ServerName,
1827 meth->method_name);
1828 pr_session_disconnect(&sftp_module, PR_SESS_DISCONNECT_BAD_CONFIG,
1829 NULL);
1830 }
1831 }
1832 }
1833 }
1834
1835 /* The following directives are documented as not supported:
1836 * <Anonymous>
1837 * ListOptions
1838 * MaxRetrieveFileSize
1839 */
1840
1841 c = find_config(s->conf, CONF_ANON, NULL, FALSE);
1842 if (c != NULL) {
1843 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
1844 ": Server '%s': <Anonymous> configuration is not supported by "
1845 "mod_sftp, and will be ignored", s->ServerName);
1846 }
1847
1848 c = find_config(s->conf, CONF_PARAM, "ListOptions", TRUE);
1849 if (c != NULL) {
1850 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
1851 ": Server '%s': ListOptions directive is not supported by mod_sftp, "
1852 "and will be ignored", s->ServerName);
1853 }
1854
1855 c = find_config(s->conf, CONF_PARAM, "MaxRetrieveFileSize", TRUE);
1856 if (c != NULL) {
1857 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
1858 ": Server '%s': MaxRetrieveFileSize directive is not supported by "
1859 "mod_sftp, and will be ignored", s->ServerName);
1860 }
1861 }
1862 }
1863
sftp_restart_ev(const void * event_data,void * user_data)1864 static void sftp_restart_ev(const void *event_data, void *user_data) {
1865
1866 /* Clear the host keys. */
1867 sftp_keys_free();
1868
1869 /* Clear the client banner regexes. */
1870 sftp_interop_free();
1871 }
1872
sftp_shutdown_ev(const void * event_data,void * user_data)1873 static void sftp_shutdown_ev(const void *event_data, void *user_data) {
1874 sftp_interop_free();
1875 sftp_keystore_free();
1876 sftp_keys_free();
1877 sftp_cipher_free();
1878 sftp_mac_free();
1879 sftp_utf8_free();
1880
1881 /* Clean up the OpenSSL stuff. */
1882 sftp_crypto_free(0);
1883
1884 destroy_pool(sftp_pool);
1885 sftp_pool = NULL;
1886
1887 if (sftp_logfd >= 0) {
1888 close(sftp_logfd);
1889 sftp_logfd = -1;
1890 }
1891 }
1892
sftp_timeoutlogin_ev(const void * event_data,void * user_data)1893 static void sftp_timeoutlogin_ev(const void *event_data, void *user_data) {
1894 if (sftp_sess_state & SFTP_SESS_STATE_HAVE_KEX) {
1895 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1896 }
1897 }
1898
1899 #ifdef PR_USE_DEVEL
pool_printf(const char * fmt,...)1900 static void pool_printf(const char *fmt, ...) {
1901 char buf[PR_TUNABLE_BUFFER_SIZE];
1902 va_list msg;
1903
1904 memset(buf, '\0', sizeof(buf));
1905
1906 va_start(msg, fmt);
1907 pr_vsnprintf(buf, sizeof(buf), fmt, msg);
1908 va_end(msg);
1909
1910 buf[sizeof(buf)-1] = '\0';
1911 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s", buf);
1912 }
1913
sftp_sigusr2_ev(const void * event_data,void * user_data)1914 static void sftp_sigusr2_ev(const void *event_data, void *user_data) {
1915 /* Note: the mod_shaper module deliberately uses the SIGUSR2 signal
1916 * for handling shaping. Thus we only want to dump out the pools
1917 * IFF mod_shaper is NOT present.
1918 */
1919 if (pr_module_exists("mod_shaper.c") == FALSE) {
1920 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s",
1921 "-----BEGIN POOL DUMP-----");
1922 pr_pool_debug_memory(pool_printf);
1923 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s",
1924 "-----END POOL DUMP-----");
1925 }
1926 }
1927 #endif /* PR_USE_DEVEL */
1928
sftp_wrap_conn_denied_ev(const void * event_data,void * user_data)1929 static void sftp_wrap_conn_denied_ev(const void *event_data, void *user_data) {
1930 const char *proto;
1931
1932 proto = pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT);
1933
1934 /* Only send an SSH2 DISCONNECT if we're dealing with an SSH2 client. */
1935 if (strncmp(proto, "SSH2", 5) == 0) {
1936 const char *msg;
1937
1938 msg = get_param_ptr(main_server->conf, "WrapDenyMsg", FALSE);
1939 if (msg != NULL) {
1940 const char *user;
1941
1942 user = session.user;
1943 if (user == NULL) {
1944 user = pr_table_get(session.notes, "mod_auth.orig-user", NULL);
1945 }
1946
1947 /* If the client has authenticated, we can interpolate any '%u'
1948 * variable in the configured deny message.
1949 */
1950 msg = sreplace(sftp_pool, msg, "%u", user, NULL);
1951
1952 } else {
1953 /* XXX This needs to be properly localized. However, trying to use
1954 * the _("") construction here causes mod_sftp.c to fail compilation
1955 * (see Bug#3677), so leave it hardcoded for now.
1956 */
1957 msg = "Access denied";
1958 }
1959
1960 /* If the client has completed the KEXINIT, we can simply use
1961 * sftp_disconnect_send().
1962 */
1963 if (sftp_sess_state & SFTP_SESS_STATE_HAVE_KEX) {
1964 sftp_disconnect_send(SFTP_SSH2_DISCONNECT_BY_APPLICATION, msg,
1965 __FILE__, __LINE__, "");
1966
1967 } else {
1968 /* If the client has not completed the KEXINIT, then just send the
1969 * disconnected message, if any, directly. Make sure to terminate
1970 * the message with a newline character.
1971 */
1972 msg = pstrcat(sftp_pool, msg, "\n", NULL);
1973
1974 /* Make sure we block the Response API, otherwise mod_wrap/mod_wrap2 will
1975 * also be sending its response, and the SSH client may be confused.
1976 */
1977 pr_response_block(TRUE);
1978
1979 if (write(session.c->wfd, msg, strlen(msg)) < 0) {
1980 pr_trace_msg("ssh2", 9,
1981 "error sending mod_wrap2 connection denied message to client: %s",
1982 strerror(errno));
1983 }
1984 }
1985 }
1986 }
1987
1988 /* Initialization routines
1989 */
1990
sftp_init(void)1991 static int sftp_init(void) {
1992 unsigned long openssl_version;
1993
1994 /* Check that the OpenSSL headers used match the version of the
1995 * OpenSSL library used.
1996 *
1997 * For now, we only log if there is a difference.
1998 */
1999 openssl_version = SSLeay();
2000
2001 if (openssl_version != OPENSSL_VERSION_NUMBER) {
2002 int unexpected_version_mismatch = TRUE;
2003
2004 if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) {
2005 /* OpenSSL versions after 1.0.0 try to maintain ABI compatibility.
2006 * So we will warn about header/library version mismatches only if
2007 * the library is older than the headers.
2008 */
2009 if (openssl_version >= OPENSSL_VERSION_NUMBER) {
2010 unexpected_version_mismatch = FALSE;
2011 }
2012 }
2013
2014 if (unexpected_version_mismatch == TRUE) {
2015 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
2016 ": compiled using OpenSSL version '%s' headers, but linked to "
2017 "OpenSSL version '%s' library", OPENSSL_VERSION_TEXT,
2018 SSLeay_version(SSLEAY_VERSION));
2019 }
2020 }
2021
2022 pr_log_debug(DEBUG2, MOD_SFTP_VERSION ": using " OPENSSL_VERSION_TEXT);
2023
2024 #if defined(HAVE_SODIUM_H)
2025 if (sodium_init() < 0) {
2026 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION
2027 ": error initializing libsodium");
2028
2029 } else {
2030 const char *sodium_version;
2031
2032 sodium_version = sodium_version_string();
2033 pr_log_debug(DEBUG2, MOD_SFTP_VERSION ": using libsodium-%s",
2034 sodium_version);
2035 }
2036 #endif /* HAVE_SODIUM_H */
2037
2038 sftp_keystore_init();
2039 sftp_cipher_init();
2040 sftp_mac_init();
2041
2042 pr_event_register(&sftp_module, "mod_ban.ban-class", sftp_ban_class_ev, NULL);
2043 pr_event_register(&sftp_module, "mod_ban.ban-host", sftp_ban_host_ev, NULL);
2044 pr_event_register(&sftp_module, "mod_ban.ban-user", sftp_ban_user_ev, NULL);
2045
2046 /* Listen for mod_wrap/mod_wrap2 connection denied events, so that we can
2047 * attempt to display any deny messages from those modules to the connecting
2048 * SSH2 client.
2049 */
2050 pr_event_register(&sftp_module, "mod_wrap.connection-denied",
2051 sftp_wrap_conn_denied_ev, NULL);
2052
2053 #if defined(PR_SHARED_MODULE)
2054 pr_event_register(&sftp_module, "core.module-unload", sftp_mod_unload_ev,
2055 NULL);
2056 #endif
2057 pr_event_register(&sftp_module, "core.postparse", sftp_postparse_ev, NULL);
2058 pr_event_register(&sftp_module, "core.restart", sftp_restart_ev, NULL);
2059 pr_event_register(&sftp_module, "core.shutdown", sftp_shutdown_ev, NULL);
2060 pr_event_register(&sftp_module, "core.timeout-login", sftp_timeoutlogin_ev,
2061 NULL);
2062
2063 return 0;
2064 }
2065
sftp_sess_init(void)2066 static int sftp_sess_init(void) {
2067 config_rec *c;
2068 int times_gmt = TRUE;
2069
2070 c = find_config(main_server->conf, CONF_PARAM, "SFTPEngine", FALSE);
2071 if (c != NULL) {
2072 sftp_engine = *((int *) c->argv[0]);
2073 }
2074
2075 if (sftp_engine == FALSE) {
2076 return 0;
2077 }
2078
2079 pr_event_register(&sftp_module, "core.chroot", sftp_chroot_ev, NULL);
2080 pr_event_register(&sftp_module, "core.exit", sftp_exit_ev, NULL);
2081 #ifdef PR_USE_DEVEL
2082 pr_event_register(&sftp_module, "core.signal.USR2", sftp_sigusr2_ev, NULL);
2083 #endif /* PR_USE_DEVEL */
2084 pr_event_register(&sftp_module, "mod_auth.max-clients",
2085 sftp_max_conns_ev, NULL);
2086 pr_event_register(&sftp_module, "mod_auth.max-clients-per-class",
2087 sftp_max_conns_ev, NULL);
2088 pr_event_register(&sftp_module, "mod_auth.max-clients-per-host",
2089 sftp_max_conns_ev, NULL);
2090 pr_event_register(&sftp_module, "mod_auth.max-clients-per-user",
2091 sftp_max_conns_ev, NULL);
2092 pr_event_register(&sftp_module, "mod_auth.max-connections-per-host",
2093 sftp_max_conns_ev, NULL);
2094 pr_event_register(&sftp_module, "mod_auth.max-hosts-per-user",
2095 sftp_max_conns_ev, NULL);
2096
2097 c = find_config(main_server->conf, CONF_PARAM, "SFTPLog", FALSE);
2098 if (c != NULL) {
2099 sftp_logname = c->argv[0];
2100
2101 if (strcasecmp(sftp_logname, "none") != 0) {
2102 int res, xerrno;
2103
2104 pr_signals_block();
2105 PRIVS_ROOT
2106 res = pr_log_openfile(sftp_logname, &sftp_logfd, PR_LOG_SYSTEM_MODE);
2107 xerrno = errno;
2108 PRIVS_RELINQUISH
2109 pr_signals_unblock();
2110
2111 if (res < 0) {
2112 if (res == -1) {
2113 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION
2114 ": notice: unable to open SFTPLog '%s': %s", sftp_logname,
2115 strerror(xerrno));
2116
2117 } else if (res == PR_LOG_WRITABLE_DIR) {
2118 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
2119 ": notice: unable to open SFTPLog '%s': parent directory is "
2120 "world-writable", sftp_logname);
2121
2122 } else if (res == PR_LOG_SYMLINK) {
2123 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION
2124 ": notice: unable to open SFTPLog '%s': cannot log to a symlink",
2125 sftp_logname);
2126 }
2127 }
2128 }
2129 }
2130
2131 if (pr_define_exists("SFTP_USE_FIPS")) {
2132 #ifdef OPENSSL_FIPS
2133 if (!FIPS_mode()) {
2134
2135 /* Make sure OpenSSL is set to use the default RNG, as per an email
2136 * discussion on the OpenSSL developer list:
2137 *
2138 * "The internal FIPS logic uses the default RNG to see the FIPS RNG
2139 * as part of the self test process..."
2140 */
2141 RAND_set_rand_method(NULL);
2142
2143 if (!FIPS_mode_set(1)) {
2144 const char *errstr;
2145
2146 errstr = sftp_crypto_get_errors();
2147 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2148 "unable to use FIPS mode: %s", errstr);
2149 pr_log_pri(PR_LOG_ERR, MOD_SFTP_VERSION ": unable to use FIPS mode: %s",
2150 errstr);
2151
2152 errno = EACCES;
2153 return -1;
2154
2155 } else {
2156 pr_log_pri(PR_LOG_NOTICE, MOD_SFTP_VERSION ": FIPS mode enabled");
2157 }
2158
2159 } else {
2160 pr_log_pri(PR_LOG_DEBUG, MOD_SFTP_VERSION ": FIPS mode already enabled");
2161 }
2162 #else
2163 pr_log_pri(PR_LOG_WARNING, MOD_SFTP_VERSION ": FIPS mode requested, but " OPENSSL_VERSION_TEXT " not built with FIPS support");
2164 #endif /* OPENSSL_FIPS */
2165 }
2166
2167 #if OPENSSL_VERSION_NUMBER > 0x000907000L
2168 /* Handle any requested crypto accelerators/drivers. */
2169 c = find_config(main_server->conf, CONF_PARAM, "SFTPCryptoDevice", FALSE);
2170 if (c) {
2171 if (sftp_crypto_set_driver(c->argv[0]) < 0) {
2172 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2173 "unable use SFTPCryptoDevice '%s': %s", (const char *) c->argv[0],
2174 strerror(errno));
2175 }
2176 }
2177 #endif
2178
2179 sftp_pool = make_sub_pool(session.pool);
2180 pr_pool_tag(sftp_pool, MOD_SFTP_VERSION);
2181
2182 /* Clear out FTP-isms. */
2183 session.data_port = 0;
2184
2185 c = find_config(main_server->conf, CONF_PARAM, "SFTPOptions", FALSE);
2186 while (c != NULL) {
2187 unsigned long opts;
2188
2189 pr_signals_handle();
2190
2191 opts = *((unsigned long *) c->argv[0]);
2192 sftp_opts |= opts;
2193
2194 c = find_config_next(c, c->next, CONF_PARAM, "SFTPOptions", FALSE);
2195 }
2196
2197 /* We do two passes through the configured hostkeys. On the first pass,
2198 * we focus on loading all of the configured keys. On the second pass,
2199 * we focus on handling any of the hostkey flags that would e.g. clear the
2200 * previously loaded keys.
2201 */
2202
2203 c = find_config(main_server->conf, CONF_PARAM, "SFTPHostKey", FALSE);
2204 while (c) {
2205 const char *path = c->argv[0];
2206 int flags = *((int *) c->argv[1]);
2207
2208 if (path != NULL &&
2209 flags == 0) {
2210 /* This pool needs to have the lifetime of the session, since the hostkey
2211 * data is needed for rekeying, and rekeying can happen at any time
2212 * during the session.
2213 */
2214 if (sftp_keys_get_hostkey(sftp_pool, path) < 0) {
2215 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2216 "error loading hostkey '%s', skipping key", path);
2217 }
2218 }
2219
2220 c = find_config_next(c, c->next, CONF_PARAM, "SFTPHostKey", FALSE);
2221 }
2222
2223 c = find_config(main_server->conf, CONF_PARAM, "SFTPHostKey", FALSE);
2224 while (c) {
2225 int flags = *((int *) c->argv[1]);
2226
2227 if (flags != 0) {
2228 /* Handle any flags, such as for clearing previous host keys. */
2229 if (flags & SFTP_HOSTKEY_FL_CLEAR_RSA_KEY) {
2230 if (sftp_keys_clear_rsa_hostkey() < 0) {
2231 pr_trace_msg(trace_channel, 13,
2232 "error clearing RSA hostkey: %s", strerror(errno));
2233
2234 } else {
2235 pr_trace_msg(trace_channel, 9, "cleared RSA hostkey");
2236 }
2237
2238 } else if (flags & SFTP_HOSTKEY_FL_CLEAR_DSA_KEY) {
2239 if (sftp_keys_clear_dsa_hostkey() < 0) {
2240 pr_trace_msg(trace_channel, 13,
2241 "error clearing DSA hostkey: %s", strerror(errno));
2242
2243 } else {
2244 pr_trace_msg(trace_channel, 9, "cleared DSA hostkey");
2245 }
2246
2247 } else if (flags & SFTP_HOSTKEY_FL_CLEAR_ECDSA_KEY) {
2248 if (sftp_keys_clear_ecdsa_hostkey() < 0) {
2249 pr_trace_msg(trace_channel, 13,
2250 "error clearing ECDSA hostkey(s): %s", strerror(errno));
2251
2252 } else {
2253 pr_trace_msg(trace_channel, 9, "cleared ECDSA hostkey(s)");
2254 }
2255
2256 } else if (flags & SFTP_HOSTKEY_FL_CLEAR_ED25519_KEY) {
2257 if (sftp_keys_clear_ed25519_hostkey() < 0) {
2258 pr_trace_msg(trace_channel, 13,
2259 "error clearing ED25519 hostkey(s): %s", strerror(errno));
2260
2261 } else {
2262 pr_trace_msg(trace_channel, 9, "cleared ED25519 hostkey(s)");
2263 }
2264 }
2265 }
2266
2267 c = find_config_next(c, c->next, CONF_PARAM, "SFTPHostKey", FALSE);
2268 }
2269
2270 /* Support having either an RSA hostkey, a DSA hostkey, an ECDSA hostkey,
2271 * an ED25519 hostkey, or any combination thereof. But we have to have at
2272 * least one hostkey.
2273 */
2274 if (sftp_keys_have_dsa_hostkey() < 0 &&
2275 sftp_keys_have_rsa_hostkey() < 0 &&
2276 sftp_keys_have_ecdsa_hostkey(sftp_pool, NULL) < 0 &&
2277 sftp_keys_have_ed25519_hostkey()) {
2278 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2279 "no available host keys, unable to handle session");
2280 errno = EACCES;
2281 return -1;
2282 }
2283
2284 c = find_config(main_server->conf, CONF_PARAM, "SFTPKeyLimits", FALSE);
2285 if (c != NULL) {
2286 int rsa_min = -1, dsa_min = -1, ec_min = -1;
2287
2288 if (c->argv[0] != NULL) {
2289 rsa_min = *((int *) c->argv[0]);
2290 }
2291
2292 if (c->argv[1] != NULL) {
2293 dsa_min = *((int *) c->argv[1]);
2294 }
2295
2296 if (c->argv[2] != NULL) {
2297 ec_min = *((int *) c->argv[2]);
2298 }
2299
2300 if (rsa_min > -1 ||
2301 dsa_min > -1 ||
2302 ec_min > -1) {
2303 if (sftp_keys_set_key_limits(rsa_min, dsa_min, ec_min) < 0) {
2304 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2305 "error setting SFTPKeyLimits: %s", strerror(errno));
2306 }
2307 }
2308 }
2309
2310 c = find_config(main_server->conf, CONF_PARAM, "SFTPKeyBlacklist", FALSE);
2311 if (c != NULL) {
2312 if (strncasecmp((char *) c->argv[0], "none", 5) != 0) {
2313 sftp_blacklist_set_file(c->argv[0]);
2314
2315 } else {
2316 /* Admin explicitly requested no checking of a key blacklist. */
2317 sftp_blacklist_set_file(NULL);
2318 }
2319 }
2320
2321 c = find_config(main_server->conf, CONF_PARAM, "SFTPMaxChannels", FALSE);
2322 if (c) {
2323 sftp_channel_set_max_count(*((unsigned int *) c->argv[0]));
2324 }
2325
2326 c = find_config(main_server->conf, CONF_PARAM, "DisplayLogin", FALSE);
2327 if (c) {
2328 const char *path;
2329
2330 path = c->argv[0];
2331 if (sftp_fxp_set_displaylogin(path) < 0) {
2332 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2333 "error using DisplayLogin '%s': %s", path, strerror(errno));
2334 }
2335 }
2336
2337 c = find_config(main_server->conf, CONF_PARAM, "ServerIdent", FALSE);
2338 if (c) {
2339 if (*((unsigned char *) c->argv[0]) == FALSE) {
2340 /* The admin configured "ServerIdent off". Set the version string to
2341 * just "mod_sftp", and that's it, no version.
2342 */
2343 sftp_server_version = pstrcat(sftp_pool, SFTP_ID_PREFIX, "mod_sftp",
2344 NULL);
2345 sftp_ssh2_packet_set_version(sftp_server_version);
2346
2347 } else {
2348 /* The admin configured "ServerIdent on", and possibly some custom
2349 * string.
2350 */
2351 if (c->argc > 1) {
2352 sftp_server_version = pstrcat(sftp_pool, SFTP_ID_PREFIX, c->argv[1],
2353 NULL);
2354 sftp_ssh2_packet_set_version(sftp_server_version);
2355 }
2356 }
2357 }
2358
2359 c = find_config(main_server->conf, CONF_PARAM, "TimesGMT", FALSE);
2360 if (c) {
2361 times_gmt = *((unsigned char *) c->argv[0]);
2362 }
2363
2364 pr_response_block(TRUE);
2365
2366 c = find_config(main_server->conf, CONF_PARAM, "SFTPExtensions", FALSE);
2367 if (c) {
2368 sftp_fxp_set_extensions(*((unsigned long *) c->argv[0]));
2369 }
2370
2371 sftp_fxp_use_gmt(times_gmt);
2372
2373 c = find_config(main_server->conf, CONF_PARAM, "SFTPClientAlive", FALSE);
2374 if (c) {
2375 unsigned int count, interval;
2376
2377 count = *((unsigned int *) c->argv[0]);
2378 interval = *((unsigned int *) c->argv[1]);
2379
2380 (void) sftp_ssh2_packet_set_client_alive(count, interval);
2381
2382 pr_trace_msg("ssh2", 7,
2383 "client alive checks requested after %u secs, up to %u times",
2384 interval, count);
2385 }
2386
2387 /* Check for any rekey policy. */
2388 c = find_config(main_server->conf, CONF_PARAM, "SFTPRekey", FALSE);
2389 if (c) {
2390 int rekey;
2391
2392 /* The possible int values here are:
2393 *
2394 * 0 (disable rekeying)
2395 * 1 (enable rekeying, with parameters)
2396 */
2397
2398 rekey = *((int *) c->argv[0]);
2399 if (rekey) {
2400 int rekey_interval;
2401 off_t rekey_size;
2402
2403 rekey_interval = *((int *) c->argv[1]);
2404 rekey_size = *((off_t *) c->argv[2]);
2405
2406 pr_trace_msg("ssh2", 6, "SSH2 rekeys requested after %d secs "
2407 "or %" PR_LU " bytes", rekey_interval, (pr_off_t) rekey_size);
2408 sftp_kex_rekey_set_interval(rekey_interval);
2409 sftp_ssh2_packet_rekey_set_size(rekey_size);
2410
2411 if (c->argc == 4) {
2412 int rekey_timeout;
2413
2414 rekey_timeout = *((int *) c->argv[3]);
2415
2416 pr_trace_msg("ssh2", 6, "SSH2 rekeying has %d %s to complete",
2417 rekey_timeout, rekey_timeout != 1 ? "secs" : "sec");
2418 sftp_kex_rekey_set_timeout(rekey_timeout);
2419 }
2420
2421 } else {
2422 sftp_kex_rekey_set_interval(0);
2423 sftp_kex_rekey_set_timeout(0);
2424 sftp_ssh2_packet_rekey_set_seqno(0);
2425 sftp_ssh2_packet_rekey_set_size(0);
2426
2427 pr_trace_msg("ssh2", 6,
2428 "SSH2 server-requested rekeys disabled by SFTPRekey");
2429 }
2430
2431 } else {
2432
2433 /* Set the default rekey values: 1 hour (3600 secs) and 2 GB.
2434 * Also, as per RFC4344, rekeys will be requested whenever the
2435 * packet sequence numbers reach rollover; these are handled by
2436 * default in packet.c.
2437 */
2438 sftp_kex_rekey_set_interval(3600);
2439 sftp_ssh2_packet_rekey_set_size((off_t) 2147483648UL);
2440 }
2441
2442 /* Enable traffic analysis protection (TAP) after keys have been
2443 * exchanged, based on the configured policy.
2444 */
2445 c = find_config(main_server->conf, CONF_PARAM, "SFTPTrafficPolicy", FALSE);
2446 if (c) {
2447 const char *policy = c->argv[0];
2448
2449 if (sftp_tap_set_policy(policy) < 0) {
2450 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2451 "error setting TrafficPolicy '%s': %s", policy, strerror(errno));
2452
2453 } else {
2454 pr_trace_msg("ssh2", 9, "using TAP policy '%s'", policy);
2455 }
2456 }
2457
2458 pr_session_set_protocol("ssh2");
2459
2460 /* Use our own "authenticated yet?" check. */
2461 set_auth_check(sftp_have_authenticated);
2462
2463 pr_cmd_set_handler(sftp_cmd_loop);
2464
2465 /* Check for any UseEncoding directives. Specifically, we're interested
2466 * in the charset portion; the encoding is always UTF8 for SFTP clients
2467 * (when applicable).
2468 */
2469
2470 c = find_config(main_server->conf, CONF_PARAM, "UseEncoding", FALSE);
2471 if (c) {
2472 if (c->argc == 2) {
2473 char *charset;
2474
2475 charset = c->argv[0];
2476
2477 if (sftp_utf8_set_charset(charset) < 0) {
2478 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2479 "error setting local charset '%s': %s", charset, strerror(errno));
2480
2481 /* Re-initialize the UTF8 conversion handles. */
2482 (void) sftp_utf8_free();
2483 sftp_utf8_init();
2484 }
2485
2486 } else {
2487 sftp_utf8_init();
2488 }
2489
2490 } else {
2491 sftp_utf8_init();
2492 }
2493
2494 return 0;
2495 }
2496
2497 /* Module API tables
2498 */
2499
2500 static conftable sftp_conftab[] = {
2501 { "SFTPAcceptEnv", set_sftpacceptenv, NULL },
2502 { "SFTPAuthMethods", set_sftpauthmeths, NULL },
2503 { "SFTPAuthorizedHostKeys", set_sftpauthorizedkeys, NULL },
2504 { "SFTPAuthorizedUserKeys", set_sftpauthorizedkeys, NULL },
2505 { "SFTPCiphers", set_sftpciphers, NULL },
2506 { "SFTPClientAlive", set_sftpclientalive, NULL },
2507 { "SFTPClientMatch", set_sftpclientmatch, NULL },
2508 { "SFTPCompression", set_sftpcompression, NULL },
2509 { "SFTPCryptoDevice", set_sftpcryptodevice, NULL },
2510 { "SFTPDHParamFile", set_sftpdhparamfile, NULL },
2511 { "SFTPDigests", set_sftpdigests, NULL },
2512 { "SFTPDisplayBanner", set_sftpdisplaybanner, NULL },
2513 { "SFTPEngine", set_sftpengine, NULL },
2514 { "SFTPExtensions", set_sftpextensions, NULL },
2515 { "SFTPHostKey", set_sftphostkey, NULL },
2516 { "SFTPKeyBlacklist", set_sftpkeyblacklist, NULL },
2517 { "SFTPKeyExchanges", set_sftpkeyexchanges, NULL },
2518 { "SFTPKeyLimits", set_sftpkeylimits, NULL },
2519 { "SFTPLog", set_sftplog, NULL },
2520 { "SFTPMaxChannels", set_sftpmaxchannels, NULL },
2521 { "SFTPOptions", set_sftpoptions, NULL },
2522 { "SFTPPassPhraseProvider", set_sftppassphraseprovider, NULL },
2523 { "SFTPRekey", set_sftprekey, NULL },
2524 { "SFTPTrafficPolicy", set_sftptrafficpolicy, NULL },
2525 { NULL }
2526 };
2527
2528 module sftp_module = {
2529 /* Always NULL */
2530 NULL, NULL,
2531
2532 /* Module API version */
2533 0x20,
2534
2535 /* Module name */
2536 "sftp",
2537
2538 /* Module configuration handler table */
2539 sftp_conftab,
2540
2541 /* Module command handler table */
2542 NULL,
2543
2544 /* Module authentication handler table */
2545 NULL,
2546
2547 /* Module initialization */
2548 sftp_init,
2549
2550 /* Session initialization */
2551 sftp_sess_init,
2552
2553 /* Module version */
2554 MOD_SFTP_VERSION
2555 };
2556
2557