Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


пятница, 17 октября 2014 г.

SMBCACLS: выдергивание данных из file_ntacls.tdb

В перспективе светит задача переноса данных с одного сервера на другой. Поскольку штатных полномочий доступа в никсах недостаточно для тонкой настройки доступа к файлам на самбе, пришлось воспользоваться дополнительным модулем, который хранит расширенные полномочия в /var/cache/samba/file_ntacls.tdb.
Всё бы ничего, но вот в этом самом файле хранятся не имена файлов, к которым применены допольнительные ACL, а номера их inode. Естественно, в этом случае перенос tdb на другую машину ничего не даст: номера инодов будут гарантированно отличаться и получится каша.

В Netware была дополнительная утилита, которая делала полезную вещь - проходила по дереву каталогов от заданной точки и сбрасывала в файл назначенные каждому файлу и каталогу полномочия. В итоге, даже при полной потере этих дополнительных атрибутов можно было восстановить права на всё.

Ни в самбе, ни в Windows я подобного не нашел. Пришлось думать, как же достать полномочия. Изначально планировалось сделать дамп tdb и анализировать его, но дамп выводился в очень хитрой форме: символы с кодами <32 и >127 выводились в виде стандартных escape-последовательностей, тогда как обычные ASCII-символы выводились в своем символьном представлении. Что-то вроде \0x10Abc-\0x90: "Abc-" - это четыре символа. Быстро сделать парсинг такой смешанной строки средствами оболочки не получилось.
Тогда я понял, что, скорее всего, копаю не в ту сторону. Спасибо Олегу Адианову, чьё возмущение "неправильной постановкой задачи" по парсингу "хитрой строки" натолкнуло меня на мысль попробовать что-то другое.

Этим другим оказалась штатная утилита tdbtool из поставки самбы. У нее есть очень полезный параметр hexkeys, который выводит ключевые поля в виде привычных равномерных дампов.

Под катом текст еще не законченного скрипта, обрабатывающего это безобразие. Скрипт состоит в основном из комментариев, поскольку я не хочу забыть, почему я принял то или иное решение в ходе его написания. Да и заветы Чарльза Уэзерелла я помню...

$ cat /etc/samba/tdbworks 
#!/bin/bash
# создаем уникальное имя файла для дампа
DumpFileName=$(mktemp -t tdbdump.XXXX -u)
echo tempFile=\[$DumpFileName\]

# устройство, на котором ищем файлы и его точка монтирования
SADevice=/dev/sdb1
SAMountPoint=/var

# имя и пароль пользователя для просмотра
SAVUser=домен\\логин
SAVPass=пароль

# на каком устройстве ищем иноды. Если придется собирать с разных, то надо будет дорабатывать скрипт, например,
# чтобы он получал в качестве параметров несколько пар вида device:mountpoint и обрабатывал их последовательно
# префикс имен файлов - куда примонтировано наше устройство

# ДАМПИТЬ НЕ БУДЕМ! ЕСТЬ tdbtool
# дампим конкретный tdb
# и сразу выгребаем из него только иноды, отрезаем первые 35 символов из строки "key(16), чтобы получить номер иноды в текстовом виде
# tdbdump /var/lib/samba/file_ntacls.tdb|grep key\(|sed -r 's/^.{35}//'|sed 's/\"//'>$DumpFileName
# ls -la $DumpFileName
# grep key\( file_ntacls3.dump|sed -r 's/^.{35}//'

cp /var/lib/samba/file_ntacls.tdb ./

# еще одна хитрая конструкция:
 tdbtool ./file_ntacls.tdb hexkeys|sed '/^$/d'|sed '/key 16 bytes/d'|sed -r 's/^.{31}//'| 
 awk -F \  -e '{spaout ="0x" $8 $7 $6 $5 $4 $3 $2 $1; print "\[" spaout "\] \[" strtonum(spaout) "\]"; print strtonum(spaout)>"/tmp/decimalls" }'

# выводим ключи базы данных, каждый ключ занимает три строки
# key 16 bytes
# [000] 11 08 00 00 00 00 00 00  4D 00 08 00 00 00 00 00  ....... M......
# (пустая строка)

# удаляем все пустые и все строки со словами "key 16 bytes"
# затем отрезаем первые 31 символ, получая:

# 4D 00 08 00 00 00 00 00  ....... M......

# В awk всё просто: объявляем, что поля разделяются пробелом "-F \ " (после обратного слэша идут два пробела) и просто соединяем в обратном порядке
# первые 8 полей, дописывая в начало признак гекса. Для преобразования в десятичку используем strtonum, которая знает, что строку с признаком гекса
# надо преобразовать в десятичное число

# еще одна хитрая штука
# можно искать файл по иноде через "find ПУТЬ -inum ИНОДА", а можно и вот так:

# debugfs -R "ncheck $( sed -e :a -e '$!N; s/\n/ /; ta'</tmp/decimalls )" /dev/sdb1 2>/dev/null|tail -n +2
# зачем нужна завершающая двойка я пока не понял, но с ней не выдается название программы
# хитрый sed заменяет переводы строк на пробелы, сливая полученный ранее список "одна строка - одно значение" в длинную строку,
# по сути транспонируя список
# tail отрезает первую строку, в которую debugfs помещает заголовок "таблицы" - "Inode    Pathname"
# необходимо учесть, что debugfs выводит путь к файлу, начиная с точки монтирования, поэтому, если как у меня, /dev/sdb1 смонтировано на /var, то пути
# выглядят как "532484    /samba/scan/cnt30prn000"

# впрочем, можно и без sed-a, awk в данном случае выглядит красивее:
 debugfs -R "ncheck $(awk '{printf("%s ", $0)}'</tmp/decimalls )" $SADevice 2>/dev/null|tail -n +2|awk -F "\t" -r -v SAPrefix=$SAMountPoint -e '{print SAPrefix $2}'>/tmp/foundfiles
# просто выводим всю входную строку с дописанным в конце пробелом, а поскольку это printF, то автоматически перевод строки не добавляется
# Возможно, надо будет сразу выводить данные tdbtool в такой линейный файл, если awk умеет так делать с данными, переданными ему по каналу
# awk-ом выделяем второй столбец, разделитель "табуляция" (по крайней мере hd/hexdump показывает между номером иноды и именем файла код 0х09

# Сразу дописываем /var в начало строки

    rm /tmp/SAACLs
    touch /tmp/SAACLs
cat /tmp/foundfiles|while read line; do
    FullP="$line"
    echo \[$FullP\]
    echo ---
SAmp=$(echo $line|sed "s/\/var\/samba\///"|awk -F "/" -e '{print $1}')
SAfn=$(echo $line|sed -e "s/$SAmp//;s/\/var\/samba\///")
#    echo //cnt30srv042/$SAmp $SAfn
    echo smbcacls //cnt30srv042/$SAmp \"$SAfn\" -U "$SAVUser"%"$SAVPass"|paste -d\; -s
    smbcacls //cnt30srv042/$SAmp "$SAfn" -U $SAVUser%$SAVPass|paste -d\; -s>>/tmp/SAACLs
# почему-то не хочет обрабатываться параметр CONTROL, поэтому вырежем его из исходной строки. И надо разобраться, что там с группами и наследованием
# smbcacls //cnt30srv042/testacl "/Новая папка/молодость" -U домен\\логин%пароль|sed -r -e 's/^CONTROL.*$//;s/\\/\\\\/'|paste -d, -s|sed -e 's/,,/,/'>/tmp/tacl2
    echo ======
done

Комментариев нет:

Отправить комментарий

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