null

Создание собственного VFS модуля для Samba

Начиная с версии 2.2 Samba поддерживает модульную abstraction layer for virtual file system - VFS  и все операции с файловой системой внутри Samba используют эту прослойку. Такое нововведение позволяет не только упросить использование Samba поверх различных файловых систем, но и дает возможность в любой момент вмешиваться в процесс работы Samba с файловой системой. В заголовочном файле vfs.h описаны все типы операций, которые реализованы в рамках VFS:

typedef enum _vfs_op_type {
        SMB_VFS_OP_NOOP = -1,

        /* Disk operations */

        SMB_VFS_OP_CONNECT = 0,
        SMB_VFS_OP_DISCONNECT,
        SMB_VFS_OP_DISK_FREE,
        SMB_VFS_OP_GET_QUOTA,
        SMB_VFS_OP_SET_QUOTA,
        SMB_VFS_OP_GET_SHADOW_COPY_DATA,
        SMB_VFS_OP_STATVFS,
        SMB_VFS_OP_FS_CAPABILITIES,

        /* Directory operations */

        SMB_VFS_OP_OPENDIR,
        SMB_VFS_OP_READDIR,
        SMB_VFS_OP_SEEKDIR,
        SMB_VFS_OP_TELLDIR,
        SMB_VFS_OP_REWINDDIR,
        SMB_VFS_OP_MKDIR,
        SMB_VFS_OP_RMDIR,
        SMB_VFS_OP_CLOSEDIR,
        SMB_VFS_OP_INIT_SEARCH_OP,

        /* File operations */

        SMB_VFS_OP_OPEN,
        SMB_VFS_OP_CREATE_FILE,
        SMB_VFS_OP_CLOSE,
        SMB_VFS_OP_READ,
        SMB_VFS_OP_PREAD,
        SMB_VFS_OP_WRITE,
        SMB_VFS_OP_PWRITE,
        SMB_VFS_OP_LSEEK,
        SMB_VFS_OP_SENDFILE,
        SMB_VFS_OP_RECVFILE,
        SMB_VFS_OP_RENAME,
        SMB_VFS_OP_FSYNC,
        SMB_VFS_OP_STAT,
        SMB_VFS_OP_FSTAT,
        SMB_VFS_OP_LSTAT,
        SMB_VFS_OP_GET_ALLOC_SIZE,
        SMB_VFS_OP_UNLINK,
        SMB_VFS_OP_CHMOD,
        SMB_VFS_OP_FCHMOD,
        SMB_VFS_OP_CHOWN,
        SMB_VFS_OP_FCHOWN,
        SMB_VFS_OP_LCHOWN,
        SMB_VFS_OP_CHDIR,
        SMB_VFS_OP_GETWD,
        SMB_VFS_OP_NTIMES,
        SMB_VFS_OP_FTRUNCATE,
        SMB_VFS_OP_LOCK,
        SMB_VFS_OP_KERNEL_FLOCK,
        SMB_VFS_OP_LINUX_SETLEASE,
        SMB_VFS_OP_GETLOCK,
        SMB_VFS_OP_SYMLINK,
        SMB_VFS_OP_READLINK,
        SMB_VFS_OP_LINK,
        SMB_VFS_OP_MKNOD,
        SMB_VFS_OP_REALPATH,
        SMB_VFS_OP_NOTIFY_WATCH,
        SMB_VFS_OP_CHFLAGS,
        SMB_VFS_OP_FILE_ID_CREATE,
        SMB_VFS_OP_STREAMINFO,
        SMB_VFS_OP_GET_REAL_FILENAME,
        SMB_VFS_OP_BRL_LOCK_WINDOWS,
        SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
        SMB_VFS_OP_BRL_CANCEL_WINDOWS,
        SMB_VFS_OP_STRICT_LOCK,
        SMB_VFS_OP_STRICT_UNLOCK,

        /* NT ACL operations. */
     
        SMB_VFS_OP_FGET_NT_ACL,
        SMB_VFS_OP_GET_NT_ACL,
        SMB_VFS_OP_FSET_NT_ACL,

        /* POSIX ACL operations. */

        SMB_VFS_OP_CHMOD_ACL,
        SMB_VFS_OP_FCHMOD_ACL,

        SMB_VFS_OP_SYS_ACL_GET_ENTRY,
        SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
        SMB_VFS_OP_SYS_ACL_GET_PERMSET,
        SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
        SMB_VFS_OP_SYS_ACL_GET_FILE,
        SMB_VFS_OP_SYS_ACL_GET_FD,
        SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
        SMB_VFS_OP_SYS_ACL_ADD_PERM,
        SMB_VFS_OP_SYS_ACL_TO_TEXT,
        SMB_VFS_OP_SYS_ACL_INIT,
        SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
        SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
        SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
        SMB_VFS_OP_SYS_ACL_SET_PERMSET,
        SMB_VFS_OP_SYS_ACL_VALID,
        SMB_VFS_OP_SYS_ACL_SET_FILE,
        SMB_VFS_OP_SYS_ACL_SET_FD,
        SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
        SMB_VFS_OP_SYS_ACL_GET_PERM,
        SMB_VFS_OP_SYS_ACL_FREE_TEXT,
        SMB_VFS_OP_SYS_ACL_FREE_ACL,
        SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,

        /* EA operations. */
        SMB_VFS_OP_GETXATTR,
        SMB_VFS_OP_LGETXATTR,
        SMB_VFS_OP_FGETXATTR,
        SMB_VFS_OP_LISTXATTR,
        SMB_VFS_OP_LLISTXATTR,
        SMB_VFS_OP_FLISTXATTR,
        SMB_VFS_OP_REMOVEXATTR,
        SMB_VFS_OP_LREMOVEXATTR,
        SMB_VFS_OP_FREMOVEXATTR,
        SMB_VFS_OP_SETXATTR,
        SMB_VFS_OP_LSETXATTR,
        SMB_VFS_OP_FSETXATTR,

        /* aio operations */
        SMB_VFS_OP_AIO_READ,
        SMB_VFS_OP_AIO_WRITE,
        SMB_VFS_OP_AIO_RETURN,
        SMB_VFS_OP_AIO_CANCEL,
        SMB_VFS_OP_AIO_ERROR,
        SMB_VFS_OP_AIO_FSYNC,
        SMB_VFS_OP_AIO_SUSPEND,
        SMB_VFS_OP_AIO_FORCE,

        /* offline operations */
        SMB_VFS_OP_IS_OFFLINE,
        SMB_VFS_OP_SET_OFFLINE,

        /* This should always be last enum value */

        SMB_VFS_OP_LAST
} vfs_op_type;

Соответственно, можно написать свой VFS модуль и сделать его обработчиком любых из вышеперечисленных операций. В качестве примера хочу рассмотреть создание VFS модуля, который анализирует тип файла в момент его закрытия и удаляет файл, если тот  не соответствует какому-то определенному типу. Тип файла определяется не по расширению, а по фактическому содержимому. На практике, такой модуль можно использовать для разрешения хранения на файловом ресурсе Samba файлов определенных типов. В качестве точки вызова модуля я выбрал операцию закрытия файла исходя из следующих соображений: 

   1. определить тип файла в момент его открытия не всегда возможно, например, при создании соедержимого еще нет, а при перезаписи тип может поменятся
   2. попытка удалить файл в процессе работы может не понравиться приложению, которое с ним работает
   3. подобным образом работают другие VFS модули Samba

Определить тип файла нам поможет библиотека libmagic, которая вместе с программой file входит в состав любой Unix-like операционной системы:

$ file samba-3.4.5.tar.gz camera.avi
samba-3.4.5.tar.gz: gzip compressed data, was "samba-3.4.5.tar", from Unix, last modified: Mon Jan 18 16:31:18 2010, max compression
camera.avi: RIFF (little-endian) data, AVI, 720 x 400, 23.98 fps, video: XviD, audio: Dolby AC3 (stereo, 48000 Hz

 

Рассмотрим исходный текст модуля, комментарии в тексте описывают ход его выполнения:

/*
* VFS module to delete files at closing if their mime type does
* not match with rules.
*
* Copyright (C) Alexander Deiter 2004-2010
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/*
* Short instructions:
*
* Build it with:
*    LDFLAGS = -lmagic
*
* Sample smb.conf:
*
* [test]
*    path = /path/to/test
*    vfs objects = magic_perms
*    magic_perms: filetypes = image/jpeg, application/pdf
*    writeable = yes
*/

#include "includes.h"
#include <magic.h>

#define MODULE_NAME    "magic_perms"
#define FILETYPES    "filetypes"

static int magic_perms_close(vfs_handle_struct *handle, files_struct *fsp)
{
    int i;
    magic_t mc;
    const char *ftype;
    const char **ftypes;
    char *fpath;
    int retval = SMB_VFS_NEXT_CLOSE(handle, fsp);

    /* возвращаем управление если после открытия файл не был модифицирован */
    if ( !fsp->modified ) {
        DEBUG(10,("%s file %s was not modified.\n",
            MODULE_NAME, fsp->fsp_name));
        return retval;
    }

    /* возвращаем управление если это каталог */
    if ( fsp->is_directory ) {
        DEBUG(10,("%s %s like directory.\n",
            MODULE_NAME, fsp->fsp_name));
        return retval;
    }

    /* читаем параметры модуля из smb.conf */
    ftypes = lp_parm_string_list(SNUM(handle->conn),
        (handle->param ? handle->param : MODULE_NAME),
        FILETYPES, NULL);

    /* возвращаем управление если параметры не определены */
    if (!ftypes) {
        DEBUG(2,("%s empty file type list.\n",
            MODULE_NAME));
        return retval;
    }

    /* находим путь к файлу на файловой системе */
    fpath = talloc_asprintf(talloc_tos(), "%s/%s", fsp->conn->connectpath, fsp->fsp_name);
    DEBUG(2,("%s get full path for %s: %s.\n",
        MODULE_NAME, fsp->fsp_name, fpath));

    /* открываем базу данных, в которой описаны все известные типы файлов */
    mc = magic_open(MAGIC_PRESERVE_ATIME|MAGIC_MIME_TYPE);
    if (mc == NULL) {
        DEBUG(2,("%s cannot open magic file: %s.\n",
            MODULE_NAME, strerror(errno)));
        return retval;
    }

    /* загружаем базу данных*/
    if (magic_load(mc, NULL) == -1) {
        DEBUG(2,("%s cannot load magic file: %s.\n",
            MODULE_NAME, magic_error(mc)));
        magic_close(mc);
        return retval;
    }

    /* определяем тип файла */
    ftype = magic_file(mc, fpath);
 
    /* возвращаем управление если тип неизвестен */
    if (ftype == NULL) {
        DEBUG(2,("%s cannot get type for file %s.\n",
            MODULE_NAME, fpath));
        magic_close(mc);
        return retval;
    }

    magic_close(mc);

    DEBUG(2,("%s get magic for %s: %s.\n",
        MODULE_NAME, fpath, ftype));

    /* возвращаем управление если тип файла в списке разрешенных */
    for (i=0; ftypes[i]; i++) {
        if (strcmp(ftype, ftypes[i]) == 0) {
            DEBUG(2,("%s match %s for %s.\n",
                MODULE_NAME, ftype, fpath));
            return retval;
        }
    }

    /* удаляем файл если он не входит в список разрешенных */
    DEBUG(1,("%s unlink file %s with type %s.\n",
        MODULE_NAME, fpath, ftype));
    unlink(fpath);
    TALLOC_FREE(fpath);
    return retval;
}

/* регистрируем модуль для операции закрытия файла */
static vfs_op_tuple magic_perms_op_tuples[] = {
    {SMB_VFS_OP(magic_perms_close),    SMB_VFS_OP_CLOSE,    SMB_VFS_LAYER_TRANSPARENT},
    {SMB_VFS_OP(NULL),        SMB_VFS_OP_NOOP,    SMB_VFS_LAYER_NOOP}

};

/* инициализируем модуль */
NTSTATUS init_samba_module(void)
{
    return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE_NAME, magic_perms_op_tuples);
}

 

Для использования модуля его исходный код необходимо скомпилировать в загружаемую библиотеку. При сборке нам понадобится исходный код Samba. Воспользовавшись системой портов FreeBSD загрузим исходный код продукта и настроим параметры его сборки:

# cd /usr/ports/net/samba34
# make fetch
# make configure

 

Теперь нам останется скопировать файл с исходным кодом модуля в дерево исходных тектстов Samba и изменить сценарий сборки для включения нашего модуля в готовый пакет:

# diff -u work/samba-3.4.5/source3/Makefile.orig work/samba-3.4.5/source3/Makefile
--- work/samba-3.4.5/source3/Makefile.orig    2010-03-21 23:33:54.524574380 +0300
+++ work/samba-3.4.5/source3/Makefile    2010-03-22 01:47:23.172429344 +0300
@@ -231,7 +231,7 @@

SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb

-VFS_MODULES =  bin/recycle.so bin/audit.so bin/extd_audit.so bin/full_audit.so \
+VFS_MODULES =  bin/recycle.so bin/audit.so bin/magic_perms.so bin/extd_audit.so \
PERFCOUNT_MODULES =
PDB_MODULES =
RPC_MODULES =
@@ -645,6 +645,7 @@

VFS_DEFAULT_OBJ = modules/vfs_default.o
VFS_AUDIT_OBJ = modules/vfs_audit.o
+VFS_MAGIC_PERMS_OBJ = modules/vfs_magic_perms.o
VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
VFS_FULL_AUDIT_OBJ = modules/vfs_full_audit.o
VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o
@@ -2502,6 +2503,10 @@
     @echo "Building plugin $@"
     @$(SHLD_MODULE) $(VFS_AUDIT_OBJ)

+bin/magic_perms.so: $(BINARY_PREREQS) $(VFS_MAGIC_PERMS_OBJ)
+    @echo "Building plugin $@"
+    @$(SHLD_MODULE) -lmagic $(VFS_MAGIC_PERMS_OBJ)
+
bin/extd_audit.so: $(BINARY_PREREQS) $(VFS_EXTD_AUDIT_OBJ)
     @echo "Building plugin $@"
     @$(SHLD_MODULE) $(VFS_EXTD_AUDIT_OBJ)

 

Запускаем процесс сборки и установки пакета:

# make package


После непродолжительного ожидания получаем установленный в системе пакет Samba:

# pkg_info -c samba34-3.4.5_1
Information for samba34-3.4.5_1:

Comment:
A free SMB and CIFS client and server for UNIX

 

Для проверки работоспособности модуля настроим минимальную конфигурацию Samba, разрешив на единственном общедоступном ресурсе только два типа файлов изображения в формате jpeg и документы в формате pdf:

# testparm -s
Load smb config files from /usr/local/etc/smb.conf
Processing section "[test]"
Loaded services file OK.
Server role: ROLE_STANDALONE
[global]
    dos charset = cp866
    display charset = UTF-8
    workgroup = MYGROUP
    security = SHARE
    log level = 2
    log file = /var/log/samba34/log.%m
    max log size = 4096

[test]
    path = /var/tmp/test
    read only = No
    guest ok = Yes
    vfs objects = magic_perms
    magic_perms: filetypes = image/jpeg, application/pdf

 

Запустим Samba:

# /usr/local/etc/rc.d/samba start
Removing stale Samba tdb files:  done
Starting nmbd.
Starting smbd.


И попробуем скопировать на ресурс [test] файлы различных типов:

$ smbclient -N //localhost/test
Domain=[MYGROUP] OS=[Unix] Server=[Samba 3.4.5]
Server not using user level security and no password supplied.
smb: \> put space_wind_mp3
putting file space_wind_mp3 as \space_wind.mp3 (17483.8 kb/s) (average 8716.3 kb/s)
smb: \> put 820-1011.pdf
putting file 820-1011.pdf as \820-1011.pdf (620.0 kb/s) (average 3982.8 kb/s)
smb: \> put ssa.jnlp
putting file ssa.jnlp as \ssa.jnlp (2.7 kb/s) (average 2795.6 kb/s)
smb: \> put moz-screenshot.jpg
putting file moz-screenshot.jpg as \moz-screenshot.jpg (206.1 kb/s) (average 2110.4 kb/s)
smb: \>


В журналах Samba мы увидим, что файлы space_wind_mp3 и ssa.jnlp были удалены по причине несоответствия разрешенным типам:


[2010/04/02 00:45:48,  2] modules/vfs_magic_perms.c:77(magic_perms_close)
  magic_perms get full path for space_wind_mp3: /var/tmp/test/space_wind.mp3.
[2010/04/02 00:45:48,  2] modules/vfs_magic_perms.c:104(magic_perms_close)
  magic_perms get magic for /var/tmp/test/space_wind_mp3: audio/mpeg.
[2010/04/02 00:45:48,  1] modules/vfs_magic_perms.c:115(magic_perms_close)
  magic_perms unlink file /var/tmp/test/space_wind_mp3 with type audio/mpeg.
...
[2010/04/02 00:46:26,  2] modules/vfs_magic_perms.c:77(magic_perms_close)
  magic_perms get full path for 820-1011.pdf: /var/tmp/test/820-1011.pdf.
[2010/04/02 00:46:26,  2] modules/vfs_magic_perms.c:104(magic_perms_close)
  magic_perms get magic for /var/tmp/test/820-1011.pdf: application/pdf.
[2010/04/02 00:46:26,  2] modules/vfs_magic_perms.c:109(magic_perms_close)
  magic_perms match application/pdf for /var/tmp/test/820-1011.pdf.
...
[2010/04/02 00:46:42,  2] modules/vfs_magic_perms.c:77(magic_perms_close)
  magic_perms get full path for ssa.jnlp: /var/tmp/test/ssa.jnlp.
[2010/04/02 00:46:42,  2] modules/vfs_magic_perms.c:104(magic_perms_close)
  magic_perms get magic for /var/tmp/test/ssa.jnlp: application/xml.
[2010/04/02 00:46:42,  1] modules/vfs_magic_perms.c:115(magic_perms_close)
  magic_perms unlink file /var/tmp/test/ssa.jnlp with type application/xml.
...
[2010/04/02 00:47:05,  2] modules/vfs_magic_perms.c:77(magic_perms_close)
  magic_perms get full path for moz-screenshot.jpg: /var/tmp/test/moz-screenshot.jpg.
[2010/04/02 00:47:05,  2] modules/vfs_magic_perms.c:104(magic_perms_close)
  magic_perms get magic for /var/tmp/test/moz-screenshot.jpg: image/jpeg.
[2010/04/02 00:47:05,  2] modules/vfs_magic_perms.c:109(magic_perms_close)
  magic_perms match image/jpeg for /var/tmp/test/moz-screenshot.jpg.


Как и множество других открытых програмных продуктов, Samba позволяет легко наращивать свой фунционал, создавая по мере необходимости сколь угодно сложные решения, которые могут решать самые разные задачи.
 




 

Не делайте из еды культа!

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

Ничего не найдено. n is 0