Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Из этого выпуска вы узнаете: о новых возможностях ModSecurity по нормализации


Добрый день, уважаемый подписчик.

Перед вами 6 выпуск рассылки "Информационный бюллетень от ApacheDev.ru". Это первый выпуск, который вышел на базе сервиса Subscribe.ru. Я надеюсь, что теперь у вас не будет проблем с получением писем, да и архив рассылки всегда будет под рукой. Архив же предыдущих выпусков скоро будет выложен на сайте ApacheDev.ru. Ну а теперь перейдем к более важным вещам :)

Из этого выпуска вы узнаете о новых возможностях ModSecurity по нормализации входного потока; о библиотеке Serf, которая предоставляет простой API для выполнения клиентских запросов; и напоследок, сможете прочитать последнюю статью из серии про mod_dav, благодаря которой вы научитесь создавать собственные dav-провайдеры. Приятного чтения.


Интересное из мира Apache

Нормализирующие возможности ModSecurity 2

На сайте ApacheDev.ru опубликована заметка о новых возможностях ModSecurity 2 - функциях нормализации входного потока. Всего предоставлено 19 функций, например: lowercase, removeNulls, compressWhitespace, urlDecode и др. Использование явных преобразований входных данных существенно повышает надежность защиты. Подробнее...

Библиотека Serf

Недавно на конференции разработчиков Apache наткнулся на библиотеку Serf. Ее рекомендовал Paul Querna для использования при разработке модулей Apache. Основное ее предназначение - это предоставление простого API для реализации функциональности HTTP клиента: отправка запросов, получение ответов и т.п. Исходники Serf можно взять тут: http://svn.webdav.org/repos/projects/serf/trunk/. Также Paul ищет разработчиков, кто создал бы сайт библиотеки Serf. Так что, если у вас есть желание, то пишите на chip(at)force-elite.com.


Статья выпуска

В предыдущей статье мы рассмотрели реализацию протокола WebDAV в сервере Apache. В этой статье, которая является последней в серии, мы рассмотрим устройство модуля mod_dav - центрального модуля поддержки протокола WebDAV в Apache.

Введение

Как уже было сказано в предыдущих статьях, модуль mod_dav является интерфейсным модулем, в котором происходит только обработка протокола WebDAV, а реализацию взаимодействия с хранилищем ресурсов, хранения свойств, и т.п. модуль mod_dav делегирует сторонним модулям (back-end модулям или dav-провайдерами). В mod_dav такое взаимодействие реализовано в виде нескольких семейств хуков (сгруппированных по функциональности), обработчики которых должны быть реализованы dav-провайдерами.

Всего в mod_dav предоставлено семь групп хуков: обработка двух из них обязательна, а остальных опционально. Сперва мы покажем общую схему, а затем опишем основные группы подробно.

Архитектура mod_dav

Архитектура mod_dav

На рисунке изображены все группы хуков, предоставляемых модулем mod_dav. Синим цветом выделены те группы хуков, для которых в dav-провайдере необходимы обработчики. Сейчас мы кратко рассмотрим каждую из этих групп, а ниже уже более детально изучим самые важные их них.

Название группыОписание
dav_hooks_repositoryОбязательная группа хуков. Объединяет хуки, отвечающие за взаимодействие с хранилищем ресурсов.
dav_hooks_propdbОбязательная группа хуков. В ней собраны хуки необходимые для работы со свойствами ресурсов (метаданными).
dav_hooks_livepropХуки для работы с Live-свойствами. Live-свойства предназначены для хранения значений, определяемых сервером, например: "getcontentlength" - длина тела ответа.
dav_hooks_locksХуки для работы с блокировками ресурсов.
dav_hooks_vsnВерсионность ресурсов.
dav_hooks_bindingСвязывание ресурсов.
dav_hooks_searchПоиск ресурсов.

Теперь подробно рассмотрим три наиболее важные группы: dav_hooks_repository, dav_hooks_propdb и dav_hooks_locks.

mod_dav: Работа с хранилищем ресурсов

Для взаимодействия с хранилищем (репозитарием) ресурсов в mod_dav существует группа хуков dav_hooks_repository. Основное ее предназначение - это обрабатывать входные и выходные потоки хранилища ресурсов. Обработчики этих хуков также обеспечивают выполнение основных файловых операций над ресурсами, например: копирование/перемещение ресурсов, создание коллекции, удаление ресурса и т.п.

Рассмотрим все хуки этой группы подробнее:

get_resource
Один из главных хуков данной группы. Обработчик хука get_resource связывает ресурс с URI запроса. Он должен возвращать структуру dav_resource, описывающую запрошенный ресурс. Структура dav_resource возвращается даже в случае, если запрошенный ресурс не существует.
get_parent_resource
Обработчик этого хука возвращает описатель (дескриптор) родительского ресурса для запрошенного URI. Если URI запроса указывает на корневую коллекцию, тогда возвращается NULL.
is_same_resource
Определяет, ссылаются ли два дескриптора на один и тот же ресурс.
is_parent_resource
Служит для определения, является ли один ресурс родительским для другого.
open_stream
Создает структуру потока - dav_stream, необходимую при заливке ресурса. Обработчик вызывается каждый раз, когда в хранилище добавляется новый ресурс.
close_stream
Закрывает открытый поток. Вызывается после того, как ресурс полностью залит.
write_stream
Вызывается циклически для блочной обработки данных закачиваемого ресурса.
seek_stream
Абсолютное смещение в потоке. Используется для поддержки заголовка Content-Range в методах GET/PUT.
set_headers
Вызывается перед отправкой ответа клиенту для установки заголовков. Обработчик хука deliver не вызывается, если используется метод HEAD.
deliver
Одни из главных хуков группы. Используется для отправки ресурса в заданный фильтр. Используется как для ресурсов, так и для коллекций.
create_collection
Создает коллекцию. В случае если коллекция создана успешно, обработчик должен вернуть NULL.
copy_resource
Хук копирования ресурса или коллекции. Свойства ресурсов также копируются.
move_resource
Перенос ресурса.
remove_resource
Хук удаления ресурса или коллекции. При удалении ресурса также удаляются и его свойства.
walk
Хук обхода иерархии коллекций и ресурсов. Используется, когда запрос поступил на коллекцию и глубина обхода больше 0 (т.е. необходимо обработать вложенные объекты).
getetag
Получить ETag для ресурса.

mod_dav: Работа со свойствами

Второй важнейшей и обязательной группой хуков является группа работы со свойствами. Основной задачей обработчиков этой группы является организация хранения свойств ресурсов и коллекций. Также они обеспечивают выполнения всех операций над свойствами. Рассмотрим эти хуки.

open
Получаем дескриптор хранилища свойств.
close
Закрываем открытое хранилище свойств.
define_namespaces
Определение внутренних пространств имен для свойств.
output_value
Получение значения определенного свойства для указанного ресурса.
map_namespaces
Отображение глобальных пространств имен на пространства имен dav-провайдера.
store
Сохранить значение свойства для указанного имени.
remove
Удалить свойство.
exists
Проверяет, существует ли такое свойство.
first_name
Возвращает имя первого свойства ресурса.
next_name
Возвращает имя следующего свойства.
get_rollback
apply_rollback
Поддержка механизма отката изменений. Провайдером задается структура dav_deadprop_rollback, в которой хранятся старые имена и значения свойств.

mod_dav: Блокировки

Последняя группа, которую мы рассмотрим, отвечает за функционирование механизма блокировок. Она не является обязательной, но необходима для реализации методов WebDAV: Lock и Unlock.

get_supportedlock
Возвращает значение свойства supportedlock для ресурса.
parse_locktoken
Парсит поступивший токен блокировки. Тут мы создаем и возвращаем структуру dav_locktoken.
format_locktoken
Преобразуем структуру dav_locktoken в строку URI.
compare_locktoken
Сравниваем два токена блокировок.
open_lockdb
Открывает и подготавливает хранилище блокировок. Dav-провайдер может воспользоваться значением директивы DAVLockDB для размещения своего хранилища (значение можно получить с помощью функции dav_get_lockdb_path()).
close_lockdb
Хук завершения работы с блокировками.
remove_locknull_state
Выводим ресурс из состояния lock-null.
create_lock
Создаем блокировку для ресурса. В обработчике этого хука должен быть создан токен новой блокировки.
get_locks
Получить все блокировки указанного ресурса.
find_lock
Найти блокировку ресурса по заданному токену.
has_locks
Хук проверки ресурса на наличие блокировок. Должна возвращать TRUE, даже если у ресурса есть только блокировки с истекшим сроком жизни (time-out).
append_locks
Добавить блокировки ресурсу.
remove_lock
Удалить блокировку с заданным токеном.
refresh_locks
Обновить блокировки у ресурса. Список токенов задает блокировки, которые необходимо обновить. Также в качестве аргумента передается структура time_t, описывающая текущее время.
lookup_resource
Найти ресурс, связанный с указанным токеном блокировки.

Теперь, после рассмотрения основных групп хуков модуля mod_dav, перейдем к практике. И посмотрим на код модуля-провайдера. Я не буду мешать код с текстом, поэтому все пояснения оформлены в виде комментариев к коду.

Совет: Нижеизложенный код изучать лучше с конца.

Структура dav - провайдера

// структура модуля для хранения директив
typedef struct {
    const char *test_dav_directive;
}test_dav_server_conf;


// Обработчик хука post_config
static int test_dav_post_config(apr_pool_t *p, apr_pool_t *plog,
                                apr_pool_t *ptemp, server_rec *s) {

    // Выполняем действия, необходимые для инициализации
    // Данный обработчик вызывается после загрузки модули и 
    // после обработки конфигурации
    // (Примечание: Данный обработчик выполняется при загрузке дважды.
    // Способ обойти такое поведение читайте в статье :
    // http://apachedev.ru/2006/03/13/problemi-pri-sozdanii-modula/)
 return OK;
}

// Создать структуру конфигурации модуля
static void *create_server_config(apr_pool_t *p, server_rec *s){
    test_dav_server_conf *conf = NULL;
    conf = (test_dav_server_conf*)apr_palloc(p, sizeof(*conf));
    return (void*)conf;
}

// Обработчик директивы
static const char *test_dav_cmd(cmd_parms *cmd, void *config,
                                const char *arg1){
    test_dav_server_conf *conf;
    // Получить указатель на структуру конфигурации модуля
    conf = ap_get_module_config(cmd->server->module_config, &test_dav_provider_module);
    // Сохранить значение директивы
    conf->test_dav_directive = apr_pstrdup(cmd->pool, arg1);
    return NULL;
}


// Директивы модуля
static const command_rec test_dav_cmds[] = {
    // Декларация директивы и ее обработчика
    AP_INIT_TAKE1("tes_dav_directive", test_dav_cmd, NULL, ACCESS_CONF|RSRC_CONF,
                "Тестовая директива с одним аргументом"),
    {NULL}
};

// Структура DAV провайдера
static dav_provider test_dav_provider =
{
    &test_dav_hooks_repos,      // Работа с хранилищем
    &test_dav_hooks_propdb,     // Работа со свойствами
    &test_dav_hooks_locks,      // Блокировка
    NULL,                       // Версионность
    NULL,                       // Связывание
    NULL                        // Поиск
};

// Регистрация обработчиков хуков
static void register_hooks(apr_pool_t *pconf){

    ap_hook_post_config(test_dav_post_config, NULL, NULL, APR_HOOK_MIDDLE);
    // Регистрация DAV провайдера
    dav_register_provider(pconf, "test_dav_provider", &test_dav_provider);
}

// Главная структура модуля Apache
module AP_MODULE_DECLARE_DATA test_dav_provider_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    create_server_config, // создание конфигурации модуля
    NULL,
    test_dav_cmds, // список директив модуля
    register_hooks, // регистрация обработчиков
};

Данный код, а также код обработчиков test_dav_hooks_repos, test_dav_hooks_propdb и test_dav_hooks_locks можно скачать в виде архива.

Послесловие

Это последняя статья из серии про модуль mod_dav. Надеюсь, что она стала вам полезной и сняла часть вопросов, касающихся реализации WebDAV в сервере. Если у вас остались вопросы, то присылайте их мне на info@apachedev.ru.


В избранное