1 /*
2 * ProFTPD - mod_sftp user authentication
3 * Copyright (c) 2008-2021 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
25 #include "mod_sftp.h"
26 #include "ssh2.h"
27 #include "packet.h"
28 #include "msg.h"
29 #include "disconnect.h"
30 #include "interop.h"
31 #include "auth.h"
32 #include "crypto.h"
33 #include "cipher.h"
34 #include "mac.h"
35 #include "compress.h"
36 #include "session.h"
37 #include "keys.h"
38 #include "keystore.h"
39 #include "kbdint.h"
40 #include "utf8.h"
41 #include "display.h"
42
43 /* From response.c */
44 extern pr_response_t *resp_list, *resp_err_list;
45
46 /* This value of 6 is the same default as OpenSSH's MaxAuthTries. */
47 static unsigned int auth_attempts_max = 6;
48 static unsigned int auth_attempts = 0;
49
50 static pool *auth_pool = NULL;
51 static char *auth_default_dir = NULL;
52
53 static const char *auth_avail_meths = NULL;
54
55 /* This is a bitset of flags, used to check on the authentication method
56 * used by the client, to see if the requested method is even enabled.
57 */
58 static unsigned int auth_meths_enabled_flags = 0;
59
60 static array_header *auth_chains = NULL;
61
62 static int auth_sent_userauth_banner_file = FALSE;
63 static int auth_sent_userauth_success = FALSE;
64
65 static const char *auth_user = NULL;
66 static const char *auth_service = NULL;
67
68 static const char *trace_channel = "ssh2";
69
dup_passwd(pool * p,struct passwd * pw)70 static struct passwd *dup_passwd(pool *p, struct passwd *pw) {
71 struct passwd *res = NULL;
72
73 res = pcalloc(p, sizeof(struct passwd));
74 res->pw_name = pstrdup(p, pw->pw_name);
75 res->pw_uid = pw->pw_uid;
76 res->pw_gid = pw->pw_gid;
77 res->pw_gecos = pstrdup(p, pw->pw_gecos);
78 res->pw_dir = pstrdup(p, pw->pw_dir);
79 res->pw_shell = pstrdup(p, pw->pw_shell);
80
81 return res;
82 }
83
ensure_open_passwd(pool * p)84 static void ensure_open_passwd(pool *p) {
85 pr_auth_setpwent(p);
86 pr_auth_setgrent(p);
87
88 pr_auth_getpwent(p);
89 pr_auth_getgrent(p);
90 }
91
get_default_chdir(pool * p)92 static const char *get_default_chdir(pool *p) {
93 config_rec *c;
94 const char *path = NULL;
95
96 c = find_config(main_server->conf, CONF_PARAM, "DefaultChdir", FALSE);
97 while (c != NULL) {
98 int res;
99
100 pr_signals_handle();
101
102 if (c->argc < 2) {
103 path = c->argv[0];
104 break;
105 }
106
107 res = pr_expr_eval_group_and(((char **) c->argv) + 1);
108 if (res) {
109 path = c->argv[0];
110 break;
111 }
112
113 c = find_config_next(c, c->next, CONF_PARAM, "DefaultChdir", FALSE);
114 }
115
116 if (path &&
117 *path != '/' &&
118 *path != '~') {
119 path = pdircat(p, session.cwd, path, NULL);
120 }
121
122 if (path != NULL) {
123 path = path_subst_uservar(p, &path);
124 }
125
126 return path;
127 }
128
get_default_root(pool * p)129 static const char *get_default_root(pool *p) {
130 config_rec *c;
131 const char *path = NULL;
132
133 c = find_config(main_server->conf, CONF_PARAM, "DefaultRoot", FALSE);
134 while (c) {
135 int res;
136
137 pr_signals_handle();
138
139 if (c->argc < 2) {
140 path = c->argv[0];
141 break;
142 }
143
144 res = pr_expr_eval_group_and(((char **) c->argv) + 1);
145 if (res) {
146 path = c->argv[0];
147 break;
148 }
149
150 c = find_config_next(c, c->next, CONF_PARAM, "DefaultRoot", FALSE);
151 }
152
153 if (path) {
154 path = path_subst_uservar(p, &path);
155
156 if (strncmp(path, "/", 2) == 0) {
157 path = NULL;
158
159 } else {
160 char *real_path;
161 int xerrno = 0;
162
163 PRIVS_USER
164 real_path = dir_realpath(p, path);
165 if (real_path == NULL) {
166 xerrno = errno;
167 }
168 PRIVS_RELINQUISH
169
170 if (real_path) {
171 path = real_path;
172
173 } else {
174 char interp_path[PR_TUNABLE_PATH_MAX + 1];
175
176 memset(interp_path, '\0', sizeof(interp_path));
177 (void) pr_fs_interpolate(path, interp_path, sizeof(interp_path) - 1);
178
179 pr_log_pri(PR_LOG_NOTICE,
180 "notice: unable to use DefaultRoot %s (resolved to '%s'): %s",
181 path, interp_path,
182 strerror(xerrno));
183 }
184 }
185 }
186
187 return path;
188 }
189
set_userauth_methods(void)190 static void set_userauth_methods(void) {
191 config_rec *c;
192 register unsigned int i;
193
194 if (auth_chains != NULL) {
195 return;
196 }
197
198 auth_avail_meths = NULL;
199 auth_meths_enabled_flags = 0;
200
201 c = find_config(main_server->conf, CONF_PARAM, "SFTPAuthMethods", FALSE);
202 if (c != NULL) {
203 /* Sanity checking of the configured methods is done in the postparse
204 * event listener; we can use this as-is without fear.
205 */
206 auth_chains = c->argv[0];
207
208 } else {
209 struct sftp_auth_chain *auth_chain;
210
211 auth_chains = make_array(auth_pool, 0, sizeof(struct sftp_auth_chain *));
212
213 c = find_config(main_server->conf, CONF_PARAM, "SFTPAuthorizedUserKeys",
214 FALSE);
215 if (c != NULL) {
216 auth_chain = sftp_auth_chain_alloc(auth_pool);
217 sftp_auth_chain_add_method(auth_chain, SFTP_AUTH_FL_METH_PUBLICKEY,
218 "publickey", NULL);
219 *((struct sftp_auth_chain **) push_array(auth_chains)) = auth_chain;
220
221 } else {
222 pr_trace_msg(trace_channel, 9, "no SFTPAuthorizedUserKeys configured, "
223 "not offering 'publickey' authentication");
224 }
225
226 c = find_config(main_server->conf, CONF_PARAM, "SFTPAuthorizedHostKeys",
227 FALSE);
228 if (c != NULL) {
229 auth_chain = sftp_auth_chain_alloc(auth_pool);
230 sftp_auth_chain_add_method(auth_chain, SFTP_AUTH_FL_METH_HOSTBASED,
231 "hostbased", NULL);
232 *((struct sftp_auth_chain **) push_array(auth_chains)) = auth_chain;
233
234 } else {
235 pr_trace_msg(trace_channel, 9, "no SFTPAuthorizedHostKeys configured, "
236 "not offering 'hostbased' authentication");
237 }
238
239 if (sftp_kbdint_have_drivers() > 0) {
240 auth_chain = sftp_auth_chain_alloc(auth_pool);
241 sftp_auth_chain_add_method(auth_chain, SFTP_AUTH_FL_METH_KBDINT,
242 "keyboard-interactive", NULL);
243 *((struct sftp_auth_chain **) push_array(auth_chains)) = auth_chain;
244
245 } else {
246 pr_trace_msg(trace_channel, 9, "no kbdint drivers present, not "
247 "offering 'keyboard-interactive' authentication");
248 }
249
250 /* The 'password' method is always available. */
251 auth_chain = sftp_auth_chain_alloc(auth_pool);
252 sftp_auth_chain_add_method(auth_chain, SFTP_AUTH_FL_METH_PASSWORD,
253 "password", NULL);
254 *((struct sftp_auth_chain **) push_array(auth_chains)) = auth_chain;
255 }
256
257 for (i = 0 ; i < auth_chains->nelts; i++) {
258 struct sftp_auth_chain *auth_chain;
259 struct sftp_auth_method *meth;
260
261 auth_chain = ((struct sftp_auth_chain **) auth_chains->elts)[i];
262 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[0];
263
264 if (!(auth_meths_enabled_flags & meth->method_id)) {
265 auth_meths_enabled_flags |= meth->method_id;
266
267 if (auth_avail_meths != NULL) {
268 auth_avail_meths = pstrcat(auth_pool, auth_avail_meths, ",",
269 meth->method_name, NULL);
270 } else {
271 auth_avail_meths = meth->method_name;
272 }
273 }
274 }
275
276 pr_trace_msg(trace_channel, 9, "offering authentication methods: %s",
277 auth_avail_meths);
278
279 /* Prepare the method-specific APIs, too. */
280 if (sftp_auth_hostbased_init(auth_pool) < 0) {
281 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
282 "error preparing for 'hostbased' authentication: %s", strerror(errno));
283 }
284
285 if (sftp_auth_kbdint_init(auth_pool) < 0) {
286 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
287 "error preparing for 'keyboard-interactive' authentication: %s",
288 strerror(errno));
289 }
290
291 if (sftp_auth_password_init(auth_pool) < 0) {
292 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
293 "error preparing for 'password' authentication: %s", strerror(errno));
294 }
295
296 if (sftp_auth_publickey_init(auth_pool) < 0) {
297 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
298 "error preparing for 'publickey' authentication: %s", strerror(errno));
299 }
300 }
301
setup_env(pool * p,const char * user)302 static int setup_env(pool *p, const char *user) {
303 struct passwd *pw;
304 config_rec *c;
305 int login_acl, i, res, root_revoke = TRUE, show_symlinks = FALSE, xerrno;
306 struct stat st;
307 const char *default_chdir, *default_root, *home_dir;
308 const char *sess_ttyname = NULL, *xferlog = NULL;
309 cmd_rec *cmd;
310
311 session.hide_password = TRUE;
312
313 pw = pr_auth_getpwnam(p, user);
314 if (pw == NULL) {
315 xerrno = errno;
316
317 /* This is highly unlikely to happen...*/
318 pr_log_auth(PR_LOG_NOTICE,
319 "USER %s (Login failed): Unable to retrieve user information: %s", user,
320 strerror(xerrno));
321
322 errno = xerrno;
323 return -1;
324 }
325
326 pw = dup_passwd(p, pw);
327
328 if (pw->pw_uid == PR_ROOT_UID) {
329 pr_event_generate("mod_auth.root-login", NULL);
330
331 c = find_config(main_server->conf, CONF_PARAM, "RootLogin", FALSE);
332 if (c) {
333 if (*((int *) c->argv[0]) == FALSE) {
334 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
335 "root login attempted, denied by RootLogin configuration");
336 pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted");
337 return -1;
338 }
339
340 } else {
341 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
342 "root login attempted, denied by RootLogin configuration");
343 pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted");
344 return -1;
345 }
346 }
347
348 res = pr_auth_is_valid_shell(main_server->conf, pw->pw_shell);
349 if (res == FALSE) {
350 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
351 "authentication for user '%s' failed: Invalid shell", user);
352 pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Invalid shell: '%s'",
353 user, pw->pw_shell);
354 return -1;
355 }
356
357 res = pr_auth_banned_by_ftpusers(main_server->conf, pw->pw_name);
358 if (res == TRUE) {
359 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
360 "authentication for user '%s' failed: User in " PR_FTPUSERS_PATH, user);
361 pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): User in "
362 PR_FTPUSERS_PATH, pw->pw_name);
363 return -1;
364 }
365
366 session.user = pstrdup(p, pw->pw_name);
367 session.group = pstrdup(p, pr_auth_gid2name(p, pw->pw_gid));
368
369 session.login_uid = pw->pw_uid;
370 session.login_gid = pw->pw_gid;
371
372 /* Note that we do NOT need to explicitly call pr_auth_get_home() here;
373 * that call already happens in the pr_auth_getpwnam() call above. To
374 * call it again here would cause the home directory to be rewritten twice;
375 * depending on the configured rewrite rules, that would lead to an
376 * incorrect value (Bug#3421).
377 */
378
379 pw->pw_dir = (char *) path_subst_uservar(p, (const char **) &pw->pw_dir);
380
381 if (session.gids == NULL &&
382 session.groups == NULL) {
383 res = pr_auth_getgroups(p, pw->pw_name, &session.gids, &session.groups);
384 if (res < 1) {
385 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
386 "no supplemental groups found for user '%s'", pw->pw_name);
387 }
388 }
389
390 login_acl = login_check_limits(main_server->conf, FALSE, TRUE, &i);
391 if (!login_acl) {
392 pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Limit configuration "
393 "denies login", user);
394 return -1;
395 }
396
397 PRIVS_USER
398 home_dir = dir_realpath(p, pw->pw_dir);
399 PRIVS_RELINQUISH
400
401 if (home_dir != NULL) {
402 sstrncpy(session.cwd, home_dir, sizeof(session.cwd));
403
404 } else {
405 sstrncpy(session.cwd, pw->pw_dir, sizeof(session.cwd));
406 }
407
408 c = find_config(main_server->conf, CONF_PARAM, "CreateHome", FALSE);
409 if (c != NULL) {
410 if (*((unsigned char *) c->argv[0]) == TRUE) {
411 if (create_home(p, session.cwd, user, pw->pw_uid, pw->pw_gid) < 0) {
412 return -1;
413 }
414 }
415 }
416
417 default_chdir = get_default_chdir(p);
418 if (default_chdir != NULL) {
419 default_chdir = dir_abs_path(p, default_chdir, TRUE);
420 sstrncpy(session.cwd, default_chdir, sizeof(session.cwd));
421 }
422
423 /* Make sure any <Limit LOGIN> sections still allow access. */
424 login_acl = login_check_limits(main_server->conf, FALSE, TRUE, &i);
425 if (!login_acl) {
426 pr_log_auth(PR_LOG_NOTICE, "USER %s: Limit configuration denies login",
427 user);
428 return -1;
429 }
430
431 resolve_deferred_dirs(main_server);
432 fixup_dirs(main_server, CF_DEFER);
433
434 session.wtmp_log = TRUE;
435
436 c = find_config(main_server->conf, CONF_PARAM, "WtmpLog", FALSE);
437 if (c &&
438 *((unsigned char *) c->argv[0]) == FALSE) {
439 session.wtmp_log = FALSE;
440 }
441
442 /* As per Bug#3482, we need to disable WtmpLog for FreeBSD 9.0, as
443 * an interim measure.
444 *
445 * The issue is that some platforms update multiple files for a single
446 * pututxline(3) call; proftpd tries to update those files manually,
447 * do to chroots (after which a pututxline(3) call will fail). A proper
448 * solution requires a separate process, running with the correct
449 * privileges, which would handle wtmp logging. The proftpd session
450 * processes would send messages to this logging daemon (via Unix domain
451 * socket, or FIFO, or TCP socket).
452 *
453 * Also note that this hack to disable WtmpLog may need to be extended
454 * to other platforms in the future.
455 */
456 #if defined(HAVE_UTMPX_H) && \
457 defined(__FreeBSD_version) && __FreeBSD_version >= 900007
458 if (session.wtmp_log == TRUE) {
459 session.wtmp_log = FALSE;
460
461 pr_log_debug(DEBUG5,
462 "WtpmLog automatically disabled; see Bug#3482 for details");
463 }
464 #endif
465
466 PRIVS_ROOT
467
468 if (session.wtmp_log) {
469 sess_ttyname = pr_session_get_ttyname(p);
470
471 log_wtmp(sess_ttyname, session.user, session.c->remote_name,
472 session.c->remote_addr);
473 }
474
475 #ifdef PR_USE_LASTLOG
476 c = find_config(main_server->conf, CONF_PARAM, "UseLastlog", FALSE);
477 if (c &&
478 *((unsigned char *) c->argv[0]) == TRUE) {
479 if (sess_ttyname == NULL) {
480 sess_ttyname = pr_session_get_ttyname(p);
481 }
482
483 log_lastlog(pw->pw_uid, session.user, sess_ttyname,
484 session.c->remote_addr);
485 }
486 #endif /* PR_USE_LASTLOG */
487
488 c = find_config(main_server->conf, CONF_PARAM, "TransferLog", FALSE);
489 if (c == NULL) {
490 xferlog = PR_XFERLOG_PATH;
491
492 } else {
493 xferlog = c->argv[0];
494 }
495
496 if (strncasecmp(xferlog, "none", 5) == 0) {
497 xferlog_open(NULL);
498
499 } else {
500 xferlog_open(xferlog);
501 }
502
503 res = set_groups(p, pw->pw_gid, session.gids);
504 xerrno = errno;
505 PRIVS_RELINQUISH
506
507 if (res < 0) {
508 if (xerrno != ENOSYS) {
509 pr_log_pri(PR_LOG_WARNING, "unable to set process groups: %s",
510 strerror(xerrno));
511 }
512 }
513
514 default_root = get_default_root(session.pool);
515 if (default_root) {
516 ensure_open_passwd(p);
517
518 if (pr_auth_chroot(default_root) < 0) {
519 pr_log_pri(PR_LOG_WARNING, "unable to set DefaultRoot directory '%s'",
520 default_root);
521 return -1;
522 }
523
524 if (strncmp(session.cwd, default_root, strlen(default_root)) == 0) {
525 char *new_cwd;
526
527 new_cwd = &session.cwd[strlen(default_root)];
528
529 if (*new_cwd == '/') {
530 new_cwd++;
531 }
532 session.cwd[0] = '/';
533
534 sstrncpy(&session.cwd[1], new_cwd, sizeof(session.cwd));
535 }
536 }
537
538 pr_signals_block();
539 PRIVS_ROOT
540 PRIVS_SETUP(pw->pw_uid, pw->pw_gid)
541 pr_signals_unblock();
542
543 /* Should we give up root privs completely here? */
544 c = find_config(main_server->conf, CONF_PARAM, "RootRevoke", FALSE);
545 if (c != NULL) {
546 root_revoke = *((int *) c->argv[0]);
547
548 if (root_revoke == FALSE) {
549 pr_log_debug(DEBUG8, MOD_SFTP_VERSION
550 ": retaining root privileges per RootRevoke setting");
551 }
552
553 } else {
554 /* Do a recursive look for any UserOwner directives; honoring that
555 * configuration also requires root privs.
556 */
557 c = find_config(main_server->conf, CONF_PARAM, "UserOwner", TRUE);
558 if (c != NULL) {
559 pr_log_debug(DEBUG9, MOD_SFTP_VERSION
560 ": retaining root privileges per UserOwner setting");
561 root_revoke = FALSE;
562 }
563 }
564
565 if (root_revoke) {
566 PRIVS_ROOT
567 PRIVS_REVOKE
568 session.disable_id_switching = TRUE;
569 }
570
571 #ifdef HAVE_GETEUID
572 if (getegid() != pw->pw_gid ||
573 geteuid() != pw->pw_uid) {
574 pr_log_pri(PR_LOG_WARNING,
575 "process effective IDs do not match expected IDs");
576 return -1;
577 }
578 #endif
579
580 if (pw->pw_dir == NULL ||
581 strncmp(pw->pw_dir, "", 1) == 0) {
582 pr_log_pri(PR_LOG_WARNING, "Home directory for user '%s' is NULL/empty",
583 session.user);
584 return -1;
585 }
586
587 c = find_config(main_server->conf, CONF_PARAM, "ShowSymlinks", FALSE);
588 if (c) {
589 if (*((unsigned char *) c->argv[0]) == TRUE) {
590 show_symlinks = TRUE;
591 }
592 }
593
594 if (pr_fsio_chdir_canon(session.cwd, !show_symlinks) < 0) {
595 xerrno = errno;
596
597 if (session.chroot_path != NULL ||
598 default_root != NULL) {
599
600 pr_log_debug(DEBUG2, "unable to chdir to %s (%s), defaulting to chroot "
601 "directory %s", session.cwd, strerror(xerrno),
602 (session.chroot_path ? session.chroot_path : default_root));
603
604 if (pr_fsio_chdir_canon("/", !show_symlinks) == -1) {
605 xerrno = errno;
606
607 pr_log_pri(PR_LOG_NOTICE, "%s chdir(\"/\") failed: %s", session.user,
608 strerror(xerrno));
609 errno = xerrno;
610 return -1;
611 }
612
613 } else if (default_chdir) {
614 pr_log_debug(DEBUG2, "unable to chdir to %s (%s), defaulting to home "
615 "directory %s", session.cwd, strerror(errno), pw->pw_dir);
616
617 if (pr_fsio_chdir_canon(pw->pw_dir, !show_symlinks) == -1) {
618 xerrno = errno;
619
620 pr_log_pri(PR_LOG_NOTICE, "%s chdir(\"%s\") failed: %s", session.user,
621 session.cwd, strerror(xerrno));
622 errno = xerrno;
623 return -1;
624 }
625
626 } else {
627 pr_log_pri(PR_LOG_NOTICE, "%s chdir(\"%s\") failed: %s", session.user,
628 session.cwd, strerror(xerrno));
629 errno = xerrno;
630 return -1;
631 }
632
633 } else {
634 pr_log_debug(DEBUG10, "changed directory to '%s'", session.cwd);
635 }
636
637 sstrncpy(session.cwd, pr_fs_getcwd(), sizeof(session.cwd));
638 sstrncpy(session.vwd, pr_fs_getvwd(), sizeof(session.vwd));
639
640 /* Make sure directory config pointers are set correctly */
641 cmd = pr_cmd_alloc(p, 1, C_PASS);
642 cmd->cmd_class = CL_AUTH|CL_SSH;
643 cmd->arg = "";
644 dir_check_full(p, cmd, G_NONE, session.cwd, NULL);
645
646 session.proc_prefix = pstrdup(session.pool, session.c->remote_name);
647 session.sf_flags = 0;
648
649 pr_log_auth(PR_LOG_INFO, "USER %s: Login successful", user);
650
651 if (pw->pw_uid == PR_ROOT_UID) {
652 pr_log_auth(PR_LOG_WARNING, "ROOT SFTP login successful");
653 }
654
655 if (pr_fsio_stat(session.cwd, &st) != -1) {
656 build_dyn_config(p, session.cwd, &st, TRUE);
657 }
658
659 pr_scoreboard_entry_update(session.pid,
660 PR_SCORE_USER, session.user,
661 PR_SCORE_CWD, session.cwd,
662 NULL);
663
664 pr_timer_remove(PR_TIMER_LOGIN, ANY_MODULE);
665
666 auth_default_dir = pstrdup(session.pool, pr_fs_getvwd());
667
668 session.user = pstrdup(session.pool, session.user);
669
670 if (session.group) {
671 session.group = pstrdup(session.pool, session.group);
672 }
673
674 session.groups = copy_array_str(session.pool, session.groups);
675
676 pr_resolve_fs_map();
677 return 0;
678 }
679
send_userauth_banner_file(void)680 static int send_userauth_banner_file(void) {
681 struct ssh2_packet *pkt;
682 char *path;
683 unsigned char *buf, *ptr;
684 const char *msg;
685 int res;
686 uint32_t buflen, bufsz;
687 config_rec *c;
688 pr_fh_t *fh;
689 pool *sub_pool;
690 struct stat st;
691
692 if (auth_sent_userauth_banner_file) {
693 /* Already sent the banner; no need to do it again. */
694 return 0;
695 }
696
697 c = find_config(main_server->conf, CONF_PARAM, "SFTPDisplayBanner", FALSE);
698 if (c == NULL) {
699 return 0;
700 }
701 path = c->argv[0];
702
703 if (!sftp_interop_supports_feature(SFTP_SSH2_FEAT_USERAUTH_BANNER)) {
704 pr_trace_msg(trace_channel, 3, "unable to send SFTPDisplayBanner '%s': "
705 "USERAUTH_BANNER supported by client", path);
706 return 0;
707 }
708
709 fh = pr_fsio_open_canon(path, O_RDONLY);
710 if (fh == NULL) {
711 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
712 "error opening SFTPDisplayBanner '%s': %s", path, strerror(errno));
713 return 0;
714 }
715
716 res = pr_fsio_fstat(fh, &st);
717 if (res < 0) {
718 int xerrno = errno;
719
720 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
721 "unable to stat SFTPDisplayBanner '%s': %s", path, strerror(xerrno));
722
723 pr_fsio_close(fh);
724 return 0;
725 }
726
727 if (S_ISDIR(st.st_mode)) {
728 int xerrno = EISDIR;
729
730 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
731 "unable to use SFTPDisplayBanner '%s': %s", path, strerror(xerrno));
732
733 pr_fsio_close(fh);
734 return 0;
735 }
736
737 sub_pool = make_sub_pool(auth_pool);
738 pr_pool_tag(sub_pool, "SSH2 auth banner pool");
739
740 msg = sftp_display_fh_get_msg(sub_pool, fh);
741 pr_fsio_close(fh);
742
743 if (msg == NULL) {
744 destroy_pool(sub_pool);
745 return -1;
746 }
747
748 pr_trace_msg(trace_channel, 3,
749 "sending userauth banner from SFTPDisplayBanner file '%s'", path);
750
751 pkt = sftp_ssh2_packet_create(sub_pool);
752
753 buflen = bufsz = strlen(msg) + 32;
754 ptr = buf = palloc(pkt->pool, bufsz);
755
756 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_BANNER);
757 sftp_msg_write_string(&buf, &buflen, msg);
758
759 /* XXX locale of banner */
760 sftp_msg_write_string(&buf, &buflen, "");
761
762 pkt->payload = ptr;
763 pkt->payload_len = (bufsz - buflen);
764
765 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
766 destroy_pool(pkt->pool);
767
768 if (res < 0) {
769 destroy_pool(sub_pool);
770 return -1;
771 }
772
773 auth_sent_userauth_banner_file = TRUE;
774 destroy_pool(sub_pool);
775 return 0;
776 }
777
send_userauth_failure(char * failed_meth)778 static int send_userauth_failure(char *failed_meth) {
779 struct ssh2_packet *pkt;
780 unsigned char *buf, *ptr;
781 char *meths;
782 uint32_t buflen, bufsz = 1024;
783 int res;
784
785 pkt = sftp_ssh2_packet_create(auth_pool);
786
787 if (failed_meth) {
788 register unsigned int i;
789
790 auth_avail_meths = NULL;
791 auth_meths_enabled_flags = 0;
792
793 for (i = 0 ; i < auth_chains->nelts; i++) {
794 register unsigned int j;
795 struct sftp_auth_chain *auth_chain;
796 struct sftp_auth_method *meth = NULL;
797
798 pr_signals_handle();
799 auth_chain = ((struct sftp_auth_chain **) auth_chains->elts)[i];
800
801 for (j = 0; j < auth_chain->methods->nelts; j++) {
802 struct sftp_auth_method *m;
803
804 m = ((struct sftp_auth_method **) auth_chain->methods->elts)[j];
805 if (m->succeeded != TRUE &&
806 m->failed != TRUE) {
807 meth = m;
808 break;
809 }
810 }
811
812 if (meth == NULL) {
813 /* All of the methods in this list have failed; check the next
814 * list.
815 */
816 continue;
817 }
818
819 if (strcmp(meth->method_name, failed_meth) != 0) {
820 if (!(auth_meths_enabled_flags & meth->method_id)) {
821 auth_meths_enabled_flags |= meth->method_id;
822
823 if (auth_avail_meths != NULL) {
824 auth_avail_meths = pstrcat(auth_pool, auth_avail_meths, ",",
825 meth->method_name, NULL);
826 } else {
827 auth_avail_meths = meth->method_name;
828 }
829 }
830 } else {
831 meth->failed = TRUE;
832 }
833 }
834
835 if (auth_avail_meths == NULL) {
836 /* If there are no more auth methods available, we have to disconnect. */
837 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
838 "no more auth methods available, disconnecting");
839 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
840 NULL);
841 }
842
843 } else {
844 if (auth_avail_meths == NULL) {
845 /* This situation can happen when the authentication method succeeded,
846 * BUT the subsequent login actions failed (such as failing to chroot,
847 * no such home directory, etc etc). But we still need a list
848 * of authentication methods to send back to the client in this message;
849 * we thus use the empty string.
850 */
851 auth_avail_meths = "";
852 }
853 }
854
855 meths = pstrdup(pkt->pool, auth_avail_meths);
856
857 buflen = bufsz;
858 ptr = buf = palloc(pkt->pool, bufsz);
859
860 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_FAILURE);
861 sftp_msg_write_string(&buf, &buflen, meths);
862 sftp_msg_write_bool(&buf, &buflen, FALSE);
863
864 pkt->payload = ptr;
865 pkt->payload_len = (bufsz - buflen);
866
867 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
868 "sending userauth failure; remaining userauth methods: %s", meths);
869
870 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
871 if (res < 0) {
872 destroy_pool(pkt->pool);
873 return -1;
874 }
875
876 return 0;
877 }
878
send_userauth_success(void)879 static int send_userauth_success(void) {
880 struct ssh2_packet *pkt;
881 unsigned char *buf, *ptr;
882 uint32_t buflen, bufsz = 1024;
883 int res;
884
885 if (auth_sent_userauth_success) {
886 return 0;
887 }
888
889 pkt = sftp_ssh2_packet_create(auth_pool);
890
891 buflen = bufsz;
892 ptr = buf = palloc(pkt->pool, bufsz);
893
894 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_SUCCESS);
895
896 pkt->payload = ptr;
897 pkt->payload_len = (bufsz - buflen);
898
899 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
900 "sending userauth success");
901
902 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
903 if (res < 0) {
904 destroy_pool(pkt->pool);
905 return -1;
906 }
907
908 auth_sent_userauth_success = TRUE;
909
910 /* We call the compression init routines here as well, in case the
911 * client selected "delayed" compression.
912 */
913 sftp_compress_init_read(SFTP_COMPRESS_FL_AUTHENTICATED);
914 sftp_compress_init_write(SFTP_COMPRESS_FL_AUTHENTICATED);
915
916 return 0;
917 }
918
set_userauth_success(const char * succeeded_meth)919 static int set_userauth_success(const char *succeeded_meth) {
920 register unsigned int i;
921 int completed = FALSE;
922
923 auth_avail_meths = NULL;
924 auth_meths_enabled_flags = 0;
925
926 for (i = 0 ; i < auth_chains->nelts; i++) {
927 register unsigned int j;
928 struct sftp_auth_chain *auth_chain;
929
930 pr_signals_handle();
931 auth_chain = ((struct sftp_auth_chain **) auth_chains->elts)[i];
932
933 for (j = 0; j < auth_chain->methods->nelts; j++) {
934 struct sftp_auth_method *meth = NULL;
935
936 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[j];
937 if (meth->succeeded != TRUE &&
938 meth->failed != TRUE) {
939
940 if (strcmp(meth->method_name, succeeded_meth) == 0) {
941 /* TODO: What about submethods, for kbdint drivers? */
942 meth->succeeded = TRUE;
943 }
944
945 /* Add the next method in the list (if any) to the available methods. */
946 j++;
947 if (j < auth_chain->methods->nelts) {
948 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[j];
949
950 if (!(auth_meths_enabled_flags & meth->method_id)) {
951 auth_meths_enabled_flags |= meth->method_id;
952
953 if (auth_avail_meths != NULL) {
954 auth_avail_meths = pstrcat(auth_pool, auth_avail_meths, ",",
955 meth->method_name, NULL);
956 } else {
957 auth_avail_meths = meth->method_name;
958 }
959 }
960 }
961
962 break;
963 }
964 }
965 }
966
967 /* Now, having marked the list items that have succeeded, check each list
968 * to see if any has been completed.
969 */
970
971 for (i = 0 ; i < auth_chains->nelts; i++) {
972 register unsigned int j;
973 struct sftp_auth_chain *auth_chain;
974 int ok = TRUE;
975
976 pr_signals_handle();
977 auth_chain = ((struct sftp_auth_chain **) auth_chains->elts)[i];
978
979 for (j = 0; j < auth_chain->methods->nelts; j++) {
980 struct sftp_auth_method *meth = NULL;
981
982 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[j];
983 if (meth->succeeded != TRUE) {
984 ok = FALSE;
985 break;
986 }
987 }
988
989 if (ok == TRUE) {
990 /* We have a successfully completed list! */
991 auth_chain->completed = completed = TRUE;
992 break;
993 }
994 }
995
996 if (completed == TRUE) {
997 return 1;
998 }
999
1000 if (auth_avail_meths == NULL) {
1001 /* If there are no more auth methods available, we have to disconnect. */
1002 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1003 "no more auth methods available, disconnecting");
1004 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
1005 NULL);
1006 }
1007
1008 return 0;
1009 }
1010
send_userauth_methods(char partial_success)1011 static int send_userauth_methods(char partial_success) {
1012 struct ssh2_packet *pkt;
1013 unsigned char *buf, *ptr;
1014 uint32_t buflen, bufsz = 1024;
1015 int res;
1016
1017 pkt = sftp_ssh2_packet_create(auth_pool);
1018
1019 buflen = bufsz;
1020 ptr = buf = palloc(pkt->pool, bufsz);
1021
1022 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1023 "sending acceptable userauth methods: %s", auth_avail_meths);
1024
1025 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_FAILURE);
1026 sftp_msg_write_string(&buf, &buflen, auth_avail_meths);
1027 sftp_msg_write_bool(&buf, &buflen, partial_success);
1028
1029 pkt->payload = ptr;
1030 pkt->payload_len = (bufsz - buflen);
1031
1032 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
1033 if (res < 0) {
1034 destroy_pool(pkt->pool);
1035 return -1;
1036 }
1037
1038 return 0;
1039 }
1040
add_cmd_note(cmd_rec * cmd,const char * key,const char * val)1041 static void add_cmd_note(cmd_rec *cmd, const char *key, const char *val) {
1042 int res;
1043
1044 res = pr_table_add(cmd->notes, key, val, 0);
1045 if (res < 0 &&
1046 errno != EEXIST) {
1047 pr_trace_msg(trace_channel, 19, "error adding '%s' command note: %s",
1048 key, strerror(errno));
1049 }
1050 }
1051
remove_cmd_note(cmd_rec * cmd,const char * key)1052 static void remove_cmd_note(cmd_rec *cmd, const char *key) {
1053 (void) pr_table_remove(cmd->notes, key, NULL);
1054 }
1055
dispatch_cmd_err(cmd_rec * cmd)1056 static void dispatch_cmd_err(cmd_rec *cmd) {
1057 pr_response_add_err(R_530, "Login incorrect.");
1058 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1059 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1060 pr_response_clear(&resp_err_list);
1061 }
1062
dispatch_nonfatal_pass(cmd_rec * cmd,const char * method)1063 static void dispatch_nonfatal_pass(cmd_rec *cmd, const char *method) {
1064 const char *note = "mod_sftp.nonfatal-attempt";
1065
1066 add_cmd_note(cmd, note, method);
1067 dispatch_cmd_err(cmd);
1068 remove_cmd_note(cmd, note);
1069 }
1070
incr_auth_attempts(const char * user,cmd_rec * pass_cmd)1071 static void incr_auth_attempts(const char *user, cmd_rec *pass_cmd) {
1072 auth_attempts++;
1073
1074 if (auth_attempts_max > 0 &&
1075 auth_attempts >= auth_attempts_max) {
1076 pr_log_auth(PR_LOG_NOTICE,
1077 "Maximum login attempts (%u) exceeded, connection refused",
1078 auth_attempts_max);
1079 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1080 "Maximum login attempts (%u) exceeded, refusing connection for user '%s'",
1081 auth_attempts_max, user);
1082
1083 /* Ensure that the "mod_auth.orig_user" session note exists before
1084 * dispatching to the PASS error handlers. Some of them look for this
1085 * session note (Issue #693).
1086 */
1087 if (pr_table_add_dup(session.notes, "mod_auth.orig-user", user, 0) < 0 &&
1088 errno != EEXIST) {
1089 pr_log_debug(DEBUG3, "error stashing 'mod_auth.orig-user' in "
1090 "session.notes: %s", strerror(errno));
1091 }
1092
1093 dispatch_cmd_err(pass_cmd);
1094 pr_event_generate("mod_auth.max-login-attempts", session.c);
1095 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1096 }
1097 }
1098
1099 /* Return -1 on error, 0 to continue, and 1 if the authentication succeeded. */
handle_userauth_req(struct ssh2_packet * pkt,char ** service)1100 static int handle_userauth_req(struct ssh2_packet *pkt, char **service) {
1101 unsigned char *buf;
1102 const char *orig_user, *user;
1103 char *method;
1104 uint32_t buflen;
1105 cmd_rec *cmd, *user_cmd, *pass_cmd;
1106 int res, send_userauth_fail = FALSE;
1107 config_rec *c;
1108
1109 buf = pkt->payload;
1110 buflen = pkt->payload_len;
1111
1112 orig_user = sftp_msg_read_string(pkt->pool, &buf, &buflen);
1113
1114 user_cmd = pr_cmd_alloc(pkt->pool, 2, pstrdup(pkt->pool, C_USER), orig_user);
1115 user_cmd->cmd_class = CL_AUTH|CL_SSH;
1116 user_cmd->arg = (char *) orig_user;
1117
1118 pass_cmd = pr_cmd_alloc(pkt->pool, 1, pstrdup(pkt->pool, C_PASS));
1119 pass_cmd->cmd_class = CL_AUTH|CL_SSH;
1120 pass_cmd->arg = pstrdup(pkt->pool, "(hidden)");
1121
1122 /* Dispatch these as PRE_CMDs, so that mod_delay's tactics can be used
1123 * to ameliorate any timing-based attacks.
1124 */
1125 if (pr_cmd_dispatch_phase(user_cmd, PRE_CMD, 0) < 0) {
1126 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1127 "authentication request for user '%s' blocked by '%s' handler",
1128 orig_user, (char *) user_cmd->argv[0]);
1129
1130 dispatch_cmd_err(user_cmd);
1131 return -1;
1132 }
1133
1134 if (strcmp(orig_user, user_cmd->arg) == 0) {
1135 user = orig_user;
1136
1137 } else {
1138 user = user_cmd->arg;
1139 }
1140
1141 if (auth_user != NULL) {
1142 /* Check to see if the client has requested a different user name in
1143 * this USERAUTH_REQUEST. As per Section 5 of RFC4252, if the user
1144 * name changes, we can disconnect the client.
1145 */
1146 if (strcmp(orig_user, auth_user) != 0) {
1147 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1148 "client used different user name '%s' in USERAUTH_REQUEST (was '%s'), "
1149 "disconnecting", orig_user, auth_user);
1150
1151 dispatch_cmd_err(user_cmd);
1152 return -1;
1153 }
1154
1155 } else {
1156 auth_user = pstrdup(auth_pool, orig_user);
1157 }
1158
1159 *service = sftp_msg_read_string(pkt->pool, &buf, &buflen);
1160 if (auth_service != NULL) {
1161 /* Check to see if the client has requested a different service name in
1162 * this USERAUTH_REQUEST. As per Section 5 of RFC4252, if the service
1163 * name changes, we can disconnect the client.
1164 */
1165 if (strcmp(*service, auth_service) != 0) {
1166 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1167 "client used different service name '%s' in USERAUTH_REQUEST (was "
1168 "'%s'), disconnecting", *service, auth_service);
1169
1170 dispatch_cmd_err(user_cmd);
1171 return -1;
1172 }
1173
1174 } else {
1175
1176 /* Check to see if the requested service is one that we support.
1177 *
1178 * As far as I can tell, the only defined 'service names' are:
1179 *
1180 * ssh-userauth (RFC4252)
1181 * ssh-connection (RFC4254)
1182 *
1183 * If the requested service name is NOT one of the above,
1184 * we should disconnect, as recommended by RFC4252.
1185 */
1186
1187 if (strncmp(*service, "ssh-userauth", 13) == 0 ||
1188 strncmp(*service, "ssh-connection", 15) == 0) {
1189 auth_service = pstrdup(auth_pool, *service);
1190
1191 } else {
1192 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1193 "client requested unknown/unsupported service name '%s' in "
1194 "USERAUTH_REQUEST, disconnecting", *service);
1195
1196 dispatch_cmd_err(user_cmd);
1197 return -1;
1198 }
1199 }
1200
1201 pr_response_add(R_331, "Password required for %s", user);
1202 pr_cmd_dispatch_phase(user_cmd, POST_CMD, 0);
1203 pr_cmd_dispatch_phase(user_cmd, LOG_CMD, 0);
1204 pr_response_clear(&resp_list);
1205
1206 method = sftp_msg_read_string(pkt->pool, &buf, &buflen);
1207
1208 pr_trace_msg(trace_channel, 10, "auth requested for user '%s', service '%s', "
1209 "using method '%s'", user, *service, method);
1210
1211 (void) pr_table_remove(session.notes, "mod_auth.orig-user", NULL);
1212 if (pr_table_add_dup(session.notes, "mod_auth.orig-user", user, 0) < 0 &&
1213 errno != EEXIST) {
1214 pr_log_debug(DEBUG3, "error stashing 'mod_auth.orig-user' in "
1215 "session.notes: %s", strerror(errno));
1216 }
1217
1218 cmd = pr_cmd_alloc(pkt->pool, 3, pstrdup(pkt->pool, "USERAUTH_REQUEST"),
1219 pstrdup(pkt->pool, user), pstrdup(pkt->pool, method));
1220 cmd->arg = pstrcat(pkt->pool, user, " ", method, NULL);
1221 cmd->cmd_class = CL_AUTH|CL_SSH;
1222
1223 if (auth_attempts_max > 0 &&
1224 auth_attempts > auth_attempts_max) {
1225 pr_log_auth(PR_LOG_NOTICE,
1226 "Maximum login attempts (%u) exceeded, connection refused",
1227 auth_attempts_max);
1228 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1229 "Maximum login attempts (%u) exceeded, refusing connection for user '%s'",
1230 auth_attempts_max, user);
1231
1232 /* Ensure that the "mod_auth.orig_user" session note exists before
1233 * dispatching to the PASS error handlers. Some of them look for this
1234 * session note (Issue #693).
1235 */
1236 if (pr_table_add_dup(session.notes, "mod_auth.orig-user", user, 0) < 0 &&
1237 errno != EEXIST) {
1238 pr_log_debug(DEBUG3, "error stashing 'mod_auth.orig-user' in "
1239 "session.notes: %s", strerror(errno));
1240 }
1241
1242 dispatch_cmd_err(pass_cmd);
1243 pr_event_generate("mod_auth.max-login-attempts", session.c);
1244 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1245 }
1246
1247 set_userauth_methods();
1248
1249 /* Populate the environment for the requested authentication method,
1250 * so that it can be recorded regardless of success/failure. Note that
1251 * the "none" method is not really expected by users, so we deliberately
1252 * skip/omit that value.
1253 */
1254 if (strcmp(method, "none") != 0) {
1255 pr_env_unset(cmd->pool, "SFTP_USER_AUTH_METHOD");
1256 pr_env_set(cmd->pool, "SFTP_USER_AUTH_METHOD", method);
1257 (void) pr_table_add_dup(session.notes, "SFTP_USER_AUTH_METHOD", method, 0);
1258 }
1259
1260 /* In order for the actual user password (if any) to be populated properly
1261 * in the PRE_CMD PASS dispatch (e.g. this is needed for modules like
1262 * mod_radius; see Bug#3676), the PRE_CMD PASS dispatch needs to happen
1263 * in the method-specific auth functions, not here.
1264 *
1265 * Thus this code will look a little strange; the PRE_CMD PASS dispatching
1266 * happens in the auth-specific functions, but the POST/LOG_CMD PASS
1267 * dispatching will happen here.
1268 */
1269
1270 if (strncmp(method, "none", 5) == 0) {
1271 /* If the client requested the "none" auth method at this point, then
1272 * the list of authentication methods supported by the server is being
1273 * queried.
1274 */
1275 if (send_userauth_methods(FALSE) < 0) {
1276 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1277 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1278 return -1;
1279 }
1280
1281 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1282 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1283 pr_response_clear(&resp_list);
1284
1285 return 0;
1286
1287 } else if (strncmp(method, "publickey", 10) == 0) {
1288 if (auth_meths_enabled_flags & SFTP_AUTH_FL_METH_PUBLICKEY) {
1289 int xerrno;
1290
1291 res = sftp_auth_publickey(pkt, pass_cmd, orig_user, user, *service,
1292 &buf, &buflen, &send_userauth_fail);
1293 xerrno = errno;
1294
1295 if (res < 0) {
1296 pr_event_generate("mod_sftp.ssh2.auth-publickey.failed", NULL);
1297
1298 } else {
1299 pr_event_generate("mod_sftp.ssh2.auth-publickey", NULL);
1300 }
1301
1302 errno = xerrno;
1303
1304 } else {
1305 pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
1306
1307 if (send_userauth_methods(FALSE) < 0) {
1308 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1309 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1310 return -1;
1311 }
1312
1313 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1314 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1315
1316 incr_auth_attempts(user, pass_cmd);
1317 return 0;
1318 }
1319
1320 } else if (strncmp(method, "keyboard-interactive", 21) == 0) {
1321 if (auth_meths_enabled_flags & SFTP_AUTH_FL_METH_KBDINT) {
1322 int xerrno = errno;
1323
1324 res = sftp_auth_kbdint(pkt, pass_cmd, orig_user, user, *service,
1325 &buf, &buflen, &send_userauth_fail);
1326 xerrno = errno;
1327
1328 if (res < 0) {
1329 pr_event_generate("mod_sftp.ssh2.auth-kbdint.failed", NULL);
1330
1331 } else {
1332 pr_event_generate("mod_sftp.ssh2.auth-kbdint", NULL);
1333 }
1334
1335 errno = xerrno;
1336
1337 } else {
1338 pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
1339
1340 if (send_userauth_methods(FALSE) < 0) {
1341 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1342 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1343 return -1;
1344 }
1345
1346 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1347 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1348
1349 incr_auth_attempts(user, pass_cmd);
1350 return 0;
1351 }
1352
1353 } else if (strncmp(method, "password", 9) == 0) {
1354 if (auth_meths_enabled_flags & SFTP_AUTH_FL_METH_PASSWORD) {
1355 int xerrno;
1356
1357 res = sftp_auth_password(pkt, pass_cmd, orig_user, user, *service,
1358 &buf, &buflen, &send_userauth_fail);
1359 xerrno = errno;
1360
1361 if (res < 0) {
1362 pr_event_generate("mod_sftp.ssh2.auth-password.failed", NULL);
1363
1364 } else {
1365 pr_event_generate("mod_sftp.ssh2.auth-password", NULL);
1366 }
1367
1368 errno = xerrno;
1369
1370 } else {
1371 pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
1372
1373 if (send_userauth_methods(FALSE) < 0) {
1374 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1375 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1376 return -1;
1377 }
1378
1379 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1380 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1381
1382 incr_auth_attempts(user, pass_cmd);
1383 return 0;
1384 }
1385
1386 } else if (strncmp(method, "hostbased", 10) == 0) {
1387 if (auth_meths_enabled_flags & SFTP_AUTH_FL_METH_HOSTBASED) {
1388 int xerrno;
1389
1390 res = sftp_auth_hostbased(pkt, pass_cmd, orig_user, user, *service,
1391 &buf, &buflen, &send_userauth_fail);
1392 xerrno = errno;
1393
1394 if (res < 0) {
1395 pr_event_generate("mod_sftp.ssh2.auth-hostbased.failed", NULL);
1396
1397 } else {
1398 pr_event_generate("mod_sftp.ssh2.auth-hostbased", NULL);
1399 }
1400
1401 errno = xerrno;
1402
1403 } else {
1404 pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
1405
1406 if (send_userauth_methods(FALSE) < 0) {
1407 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1408 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1409 return -1;
1410 }
1411
1412 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1413 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1414
1415 incr_auth_attempts(user, pass_cmd);
1416 return 0;
1417 }
1418
1419 } else {
1420 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1421 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1422
1423 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1424 "unsupported authentication method '%s' requested", method);
1425
1426 incr_auth_attempts(user, pass_cmd);
1427 return 0;
1428 }
1429
1430 /* Make sure that the password cmd_rec arg points back to the static
1431 * string for passwords.
1432 */
1433 pass_cmd->arg = pstrdup(pkt->pool, "(hidden)");
1434
1435 if (res <= 0) {
1436 int xerrno = errno;
1437
1438 /* For a failed authentication _attempt_ (but not yet a real error), we
1439 * attach a note to this fake PASS "error" command dispatch, so that
1440 * interested handlers can use it to determine if the command they receive
1441 * is a real error or not, for e.g. logging/accounting purposes
1442 * (Issue #693).
1443 */
1444 if (res < 0) {
1445 dispatch_cmd_err(pass_cmd);
1446
1447 } else {
1448 dispatch_nonfatal_pass(pass_cmd, method);
1449 }
1450
1451 pr_cmd_dispatch_phase(cmd, res == 0 ? POST_CMD : POST_CMD_ERR, 0);
1452 pr_cmd_dispatch_phase(cmd, res == 0 ? LOG_CMD : LOG_CMD_ERR, 0);
1453
1454 if (send_userauth_fail) {
1455 errno = xerrno;
1456
1457 if (send_userauth_failure(errno != EPERM ? NULL : method) < 0) {
1458 return -1;
1459 }
1460
1461 incr_auth_attempts(user, pass_cmd);
1462 }
1463
1464 return res;
1465 }
1466
1467 res = set_userauth_success(method);
1468 if (res == 0) {
1469 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1470 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1471
1472 if (send_userauth_methods(TRUE) < 0) {
1473 return -1;
1474 }
1475
1476 return res;
1477 }
1478
1479 /* Past this point we will not call incr_auth_attempts(); the client has
1480 * successfully authenticated at this point, and should not be penalized
1481 * if an internal error causes the rest of the login process to fail.
1482 * Right?
1483 */
1484
1485 if (setup_env(pkt->pool, user) < 0) {
1486 dispatch_cmd_err(pass_cmd);
1487
1488 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1489 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1490
1491 if (send_userauth_failure(NULL) < 0) {
1492 return -1;
1493 }
1494
1495 return 0;
1496 }
1497
1498 if (send_userauth_success() < 0) {
1499 dispatch_cmd_err(pass_cmd);
1500
1501 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1502 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1503
1504 return -1;
1505 }
1506
1507 if (session.auth_mech != NULL) {
1508 pr_log_debug(DEBUG2, "user '%s' authenticated by %s", user,
1509 session.auth_mech);
1510 }
1511
1512 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1513 "user '%s' authenticated via '%s' method", user, method);
1514
1515 /* This allows for the %s response code LogFormat variable to be populated
1516 * in an AUTH ExtendedLog.
1517 */
1518 pr_response_add(R_230, "User %s logged in", user);
1519 pr_cmd_dispatch_phase(pass_cmd, POST_CMD, 0);
1520 pr_cmd_dispatch_phase(pass_cmd, LOG_CMD, 0);
1521 pr_response_clear(&resp_list);
1522
1523 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1524 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1525
1526 /* At this point, we can look up the Protocols config, which may have
1527 * been tweaked via mod_ifsession's user/group/class-specific sections.
1528 */
1529 c = find_config(main_server->conf, CONF_PARAM, "Protocols", FALSE);
1530 if (c != NULL) {
1531 register unsigned int i;
1532 unsigned int services = 0UL;
1533 array_header *protocols;
1534 char **elts;
1535
1536 protocols = c->argv[0];
1537 elts = protocols->elts;
1538
1539 for (i = 0; i < protocols->nelts; i++) {
1540 char *protocol;
1541
1542 protocol = elts[i];
1543 if (protocol != NULL) {
1544 if (strncasecmp(protocol, "sftp", 5) == 0) {
1545 services |= SFTP_SERVICE_FL_SFTP;
1546
1547 } else if (strncasecmp(protocol, "scp", 4) == 0) {
1548 services |= SFTP_SERVICE_FL_SCP;
1549
1550 } else if (strncasecmp(protocol, "date", 5) == 0) {
1551 services |= SFTP_SERVICE_FL_SCP;
1552 }
1553 }
1554 }
1555
1556 sftp_services = services;
1557 }
1558
1559 return 1;
1560 }
1561
1562 /* Auth Lists API */
sftp_auth_chain_alloc(pool * p)1563 struct sftp_auth_chain *sftp_auth_chain_alloc(pool *p) {
1564 pool *sub_pool;
1565 struct sftp_auth_chain *auth_chain;
1566
1567 if (p == NULL) {
1568 errno = EINVAL;
1569 return NULL;
1570 }
1571
1572 sub_pool = pr_pool_create_sz(p, 256);
1573 pr_pool_tag(sub_pool, "SSH2 Auth Chain Pool");
1574
1575 auth_chain = pcalloc(sub_pool, sizeof(struct sftp_auth_chain));
1576 auth_chain->pool = sub_pool;
1577 auth_chain->methods = make_array(sub_pool, 1,
1578 sizeof(struct sftp_auth_method *));
1579 auth_chain->completed = FALSE;
1580
1581 return auth_chain;
1582 }
1583
1584 /* Check if 'password' or 'hostbased' methods appear multiple times in
1585 * this chain; if so, it's an invalid chain. Multiple 'publickey' or
1586 * 'keyboard-interactive' methods are allowed, though.
1587 */
sftp_auth_chain_isvalid(struct sftp_auth_chain * auth_chain)1588 int sftp_auth_chain_isvalid(struct sftp_auth_chain *auth_chain) {
1589 register unsigned int i;
1590 int has_password = FALSE, has_hostbased = FALSE;
1591
1592 for (i = 0; i < auth_chain->methods->nelts; i++) {
1593 struct sftp_auth_method *meth;
1594
1595 meth = ((struct sftp_auth_method **) auth_chain->methods->elts)[i];
1596
1597 switch (meth->method_id) {
1598 case SFTP_AUTH_FL_METH_PASSWORD:
1599 if (has_password == TRUE) {
1600 errno = EPERM;
1601 return -1;
1602 }
1603
1604 has_password = TRUE;
1605 break;
1606
1607 case SFTP_AUTH_FL_METH_HOSTBASED:
1608 if (has_hostbased == TRUE) {
1609 errno = EPERM;
1610 return -1;
1611 }
1612
1613 has_hostbased = TRUE;
1614 break;
1615
1616 case SFTP_AUTH_FL_METH_PUBLICKEY:
1617 case SFTP_AUTH_FL_METH_KBDINT:
1618 default:
1619 break;
1620 }
1621 }
1622
1623 return 0;
1624 }
1625
sftp_auth_chain_add_method(struct sftp_auth_chain * auth_chain,unsigned int method_id,const char * method_name,const char * submethod_name)1626 int sftp_auth_chain_add_method(struct sftp_auth_chain *auth_chain,
1627 unsigned int method_id, const char *method_name,
1628 const char *submethod_name) {
1629 struct sftp_auth_method *meth;
1630
1631 if (auth_chain == NULL ||
1632 method_name == NULL) {
1633 errno = EINVAL;
1634 return -1;
1635 }
1636
1637 /* We currently only allow submethod names for kbdint methods. */
1638 if (submethod_name != NULL &&
1639 method_id != SFTP_AUTH_FL_METH_KBDINT) {
1640 errno = EPERM;
1641 return -1;
1642 }
1643
1644 meth = pcalloc(auth_chain->pool, sizeof(struct sftp_auth_method));
1645 meth->method_id = method_id;
1646 meth->method_name = pstrdup(auth_chain->pool, method_name);
1647 if (submethod_name != NULL) {
1648 meth->submethod_name = pstrdup(auth_chain->pool, submethod_name);
1649 }
1650 meth->succeeded = FALSE;
1651 meth->failed = FALSE;
1652
1653 *((struct sftp_auth_method **) push_array(auth_chain->methods)) = meth;
1654 return 0;
1655 }
1656
sftp_auth_chain_parse_method(pool * p,const char * name,unsigned int * method_id,const char ** method_name,const char ** submethod_name)1657 int sftp_auth_chain_parse_method(pool *p, const char *name,
1658 unsigned int *method_id, const char **method_name,
1659 const char **submethod_name) {
1660 char *ptr;
1661 size_t method_namelen;
1662
1663 if (name == NULL ||
1664 method_id == NULL ||
1665 method_name == NULL) {
1666 errno = EINVAL;
1667 return -1;
1668 }
1669
1670 /* Look for the syntax indicating a submethod name. */
1671 ptr = strchr(name, ':');
1672 if (ptr == NULL) {
1673 method_namelen = strlen(name);
1674 } else {
1675 method_namelen = ptr - name - 1;
1676 }
1677
1678 if (strncmp(name, "publickey", method_namelen) == 0) {
1679 *method_id = SFTP_AUTH_FL_METH_PUBLICKEY;
1680 *method_name = name;
1681
1682 } else if (strncmp(name, "hostbased", method_namelen) == 0) {
1683 *method_id = SFTP_AUTH_FL_METH_HOSTBASED;
1684 *method_name = name;
1685
1686 } else if (strncmp(name, "password", method_namelen) == 0) {
1687 *method_id = SFTP_AUTH_FL_METH_PASSWORD;
1688 *method_name = name;
1689
1690 } else if (strncmp(name, "keyboard-interactive", method_namelen) == 0) {
1691 *method_id = SFTP_AUTH_FL_METH_KBDINT;
1692
1693 if (sftp_kbdint_have_drivers() == 0) {
1694 errno = EPERM;
1695 return -1;
1696 }
1697
1698 /* If we have a submethod name, check whether it matches one of our
1699 * loaded kbdint drivers.
1700 */
1701 if (ptr != NULL) {
1702 if (sftp_kbdint_get_driver(ptr) == NULL) {
1703 errno = EPERM;
1704 return -1;
1705 }
1706
1707 *method_name = pstrndup(p, name, method_namelen);
1708 if (submethod_name != NULL) {
1709 *submethod_name = ptr;
1710 }
1711
1712 } else {
1713 *method_name = name;
1714 }
1715
1716 } else {
1717 /* Unknown/unsupported method name. */
1718 errno = EINVAL;
1719 return -1;
1720 }
1721
1722 return 0;
1723 }
1724
sftp_auth_chain_parse_method_chain(pool * p,const char * method_list)1725 array_header *sftp_auth_chain_parse_method_chain(pool *p,
1726 const char *method_list) {
1727 char *ptr;
1728 size_t method_listlen;
1729 array_header *method_names;
1730
1731 if (p == NULL ||
1732 method_list == NULL) {
1733 errno = EINVAL;
1734 return NULL;
1735 }
1736
1737 ptr = strchr(method_list, '+');
1738 if (ptr == NULL) {
1739 method_names = make_array(p, 0, sizeof(char *));
1740 *((char **) push_array(method_names)) = pstrdup(p, method_list);
1741 return method_names;
1742 }
1743
1744 if (ptr == method_list) {
1745 /* Leading '+'. */
1746 errno = EPERM;
1747 return NULL;
1748 }
1749
1750 method_listlen = strlen(method_list);
1751 if (method_list[method_listlen-1] == '+') {
1752 /* Trailing '+'. */
1753 errno = EPERM;
1754 return NULL;
1755 }
1756
1757 method_names = make_array(p, 0, sizeof(char *));
1758
1759 while (ptr != NULL) {
1760 size_t namelen;
1761
1762 pr_signals_handle();
1763
1764 namelen = (ptr - method_list);
1765 if (namelen == 0) {
1766 /* Double '+' characters. */
1767 errno = EPERM;
1768 return NULL;
1769 }
1770
1771 *((char **) push_array(method_names)) = pstrndup(p, method_list, namelen);
1772
1773 method_list = ptr + 1;
1774 ptr = strchr(method_list, '+');
1775
1776 /* Don't forget the last name in the list. */
1777 if (ptr == NULL) {
1778 *((char **) push_array(method_names)) = pstrdup(p, method_list);
1779 }
1780 }
1781
1782 return method_names;
1783 }
1784
sftp_auth_get_default_dir(void)1785 char *sftp_auth_get_default_dir(void) {
1786 return auth_default_dir;
1787 }
1788
sftp_auth_send_banner(const char * banner)1789 int sftp_auth_send_banner(const char *banner) {
1790 struct ssh2_packet *pkt;
1791 unsigned char *buf, *ptr;
1792 uint32_t buflen, bufsz;
1793 size_t banner_len;
1794 int res;
1795
1796 if (banner == NULL) {
1797 errno = EINVAL;
1798 return -1;
1799 }
1800
1801 /* If the client has finished authenticating, then we can no longer
1802 * send USERAUTH_BANNER messages.
1803 */
1804 if (sftp_sess_state & SFTP_SESS_STATE_HAVE_AUTH) {
1805 pr_trace_msg(trace_channel, 1,
1806 "unable to send banner: client has authenticated");
1807 return 0;
1808 }
1809
1810 /* Make sure that the given banner string ends in CRLF, as required by
1811 * RFC4252 Section 5.4.
1812 */
1813 banner_len = strlen(banner);
1814 if (banner[banner_len-2] != '\r' ||
1815 banner[banner_len-1] != '\n') {
1816 banner = pstrcat(auth_pool, banner, "\r\n", NULL);
1817 banner_len = strlen(banner);
1818 }
1819
1820 pkt = sftp_ssh2_packet_create(auth_pool);
1821
1822 buflen = bufsz = banner_len + 32;
1823 ptr = buf = palloc(pkt->pool, bufsz);
1824
1825 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_BANNER);
1826 sftp_msg_write_string(&buf, &buflen, banner);
1827
1828 /* XXX locale of banner */
1829 sftp_msg_write_string(&buf, &buflen, "");
1830
1831 pkt->payload = ptr;
1832 pkt->payload_len = (bufsz - buflen);
1833
1834 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1835 "sending userauth banner");
1836
1837 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
1838 if (res < 0) {
1839 destroy_pool(pkt->pool);
1840 return -1;
1841 }
1842
1843 destroy_pool(pkt->pool);
1844 return 0;
1845 }
1846
sftp_auth_handle(struct ssh2_packet * pkt)1847 int sftp_auth_handle(struct ssh2_packet *pkt) {
1848 char *service = NULL;
1849 int res;
1850
1851 /* The send_userauth_banner_file() function makes sure that the
1852 * SFTPDisplayBanner file is not sent multiple times.
1853 */
1854 if (send_userauth_banner_file() < 0) {
1855 return -1;
1856 }
1857
1858 if (pr_response_get_pool() == NULL) {
1859 /* We set this pool for use by the Response API, for logging response codes/
1860 * messages during login.
1861 */
1862 pr_response_set_pool(session.pool);
1863 }
1864
1865 res = handle_userauth_req(pkt, &service);
1866 if (res < 0) {
1867 destroy_pool(pkt->pool);
1868 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_PROTOCOL_ERROR, NULL);
1869 }
1870
1871 destroy_pool(pkt->pool);
1872 return res;
1873 }
1874
sftp_auth_init(void)1875 int sftp_auth_init(void) {
1876
1877 /* There's no point in trying to handle the case where a client will
1878 * want/attempt to authenticate again, as a different user.
1879 *
1880 * The issue is that if a client successfully authenticates, and the
1881 * authenticated session is chrooted, a subsequent attempt to authenticate
1882 * will occur in a chrooted process, and that will likely lead to all
1883 * sorts of brokenness.
1884 */
1885
1886 if (auth_pool == NULL) {
1887 unsigned int *max_logins;
1888
1889 auth_pool = make_sub_pool(sftp_pool);
1890 pr_pool_tag(auth_pool, "SSH2 Auth Pool");
1891
1892 max_logins = get_param_ptr(main_server->conf, "MaxLoginAttempts", FALSE);
1893 if (max_logins != NULL) {
1894 auth_attempts_max = *max_logins;
1895 }
1896 }
1897
1898 return 0;
1899 }
1900