Это более жесткий вариант предыдущего вопроса неправильное владение или режимы для компонента каталога chroot.
В этом другом вопросе мы узнаем, что openssh отказывается chroot пользователя в его собственный домашний каталог, если этот домашний каталог имеет обычные разрешения. Вместо этого вам нужно сделать root владельцем домашнего каталога пользователя. Это предотвращает загрузку пользователем в свой домашний каталог.
Я работаю с программой, которую позвоню stupid_legacy_application
или SLA
для краткости, который хочет отправить мне свой вывод через sftp upload. И он настаивает на загрузке в корневой каталог (который кажется клиенту). Загрузка не выполняется, и в журнале сервера остаются следующие сообщения:
Jun 17 18:05:53 sftphost sftp-server[29031]: open "/SLA\\SLA_Data_ 2018617_18551.zip" flags WRITE,CREATE,TRUNCATE mode 0666
Jun 17 18:05:53 sftphost sftp-server[29031]: sent status Permission denied
Обратите внимание на сочетание косой черты и обратной косой черты в пути. Я предполагаю, что это было предназначено для разговора с каким-то сервером Windows sftp, и /SLA
должен быть каталогом.
Если я не исключаю пользователя, он пытается загрузить в настоящий корневой каталог и терпит неудачу. Если я исключаю пользователя и не подключаю каталог к корневому, sshd не разрешает вход в систему. Если я исключаю пользователя и подключаю каталог к корневому, он снова терпит неудачу. Если я добавлю разрешение на запись для пользователя через биты группы или мира, sshd не разрешит вход в систему.
Я даже пытался обмануть его с помощью ACL, думая, что sshd не заметит ничего, кроме традиционных разрешений, но я обманул только себя (см. этот вопрос почему это не работает).
Перекомпиляция sshd с взломанной проверкой прав доступа к каталогам выглядит единственным способом решить эту проблему. Есть ли другой путь? Он не должен быть чистым, так как мне нужно, чтобы он работал только один раз, а сервер - это одноразовая виртуальная машина.
Я нашел несколько рабочих решений этой проблемы, большинство из которых можно было использовать только из-за моей готовности выбросить сервер после того, как я получил эту загрузку. Но есть один, который я считаю довольно разумным.
Сначала самое уродливое решение:
Плохая идея №1 - Забудьте о chroot и chmod 777 /
. Openssh проверяет наличие нормальных разрешений только при chroot.
Плохая идея №2 - разрешить клиенту писать в настоящий корневой каталог (как в плохой идее №1) можно сделать более тонко, с разрешениями группы или пользовательским ACL.
Плохая идея №3 - Как я уже писал в вопросе, можно взломать проверку разрешений из sshd. Просто найдите сообщение об ошибке bad ownership or modes for chroot
в источнике измените ближайший 022
к 002
и он больше не заметит потерю разрешений групп и ACL в chroot.
Хорошая идея (?) - Эта обратная косая черта является источником проблемы. Если бы клиент просто загрузил в /SLA/SLA_Data_blah_blah.zip
все было бы хорошо. Итак, давайте просто исправим обратную косую черту в точке, где она попадает в файловую систему, обернув open
системный вызов:
/* wrapopen.c */
#define _GNU_SOURCE
#include <string.h>
#include <sys/types.h>
#include <dlfcn.h>
static int (*libc_open)(const char *, int, mode_t);
/* Behave like normal open() but translate backslashes to slashes. */
int open(const char *fn, int flags, mode_t mode)
{
char fn_fixed[strlen(fn)+1], *p;
strcpy(fn_fixed, fn);
for(p=fn_fixed;*p;++p)
if(*p == '\\')
*p = '/';
if(!libc_open)
libc_open = dlsym(RTLD_NEXT, "open");
return libc_open(fn_fixed, flags, mode);
}
Использование:
$ gcc -fPIC -shared wrapopen.c -o wrapopen.so -ldl
$ /etc/init.d/ssh stop
$ LD_PRELOAD=$PWD/wrapopen.so /usr/sbin/sshd
Теперь, когда sshd пытается создать SLA\SLA_Data_blah_blah
это фактически создает SLA/SLA_Data_blah_blah
. Пользователь может иметь chroot-права, chroot принадлежит root-режиму 755, SLA
каталог в chroot принадлежит пользователю, и загрузка работает.