вторник, апреля 01, 2008

Смена пароля рута

На этой неделе случилось вот что: сбойнула ФС на пром.компе, который работает под соляркой (Solaris 5.10). Ось перестала грузиться, ссылаясь на ошибку, вываливалась в сингл-мод и просила рутовский пасс. Пасса никто не знал. Комп ставили подрядчики, пасс рута не сказали, просто завели пользователя для нас. Возможно, даже прописали его в sudoers, но в текущей ситуации это не помогало. Начали действовать в обход.
В первую очередь сняли жёсткий диск. Чтобы нам жизнь малиной не казалась, он оказался формата 2.5 дюйма. Ничего критического, но переходника usb - mini-ide найти не удалось. Пришлось вставлять этот винт в ноутбук, что радости нам не прибавило. Кто разбирал ноутбуки, поймёт :).
Дальше грузимся с Кноппикса 4го, он винт видит, но как-то совсем генериком. Подумавши, нарезали 5ый Кноппикс, благо образ под ругой был и болванка нашлась. Он уже определил винт нормально. Далее - cfdisk нам рассказывает, что там раздел, а перед ним немного свободного места. Раздел формата - bf, UFS от Соляриса. fdisk говорит тоже самое. Пробуем монтировать:

mount /dev/hda1 /mnt/hda1

и обламываемся. Указание -t ufs не помогает. Слава богу, товарищ Aixrein подсказал:
Все слайсы доступны под следующими свободными именами девайсов. Покажу на примере.
/dev/hda1 ... WIN95
/dev/hda2 ... BSD44
/dev/hda3 ... BSD44
/dev/hda4 ... EXT2FS
Пусть в hda2 несколько слайсов и указанной командой они не монтируются. Линух присваивает им имена начиная от hda5. Т.е.:
mount -t ufs -o ufstype=44bsd /dev/hda5 /mnt/disk

Так и оказалось: покопавшись в /dev/hda* нашли разделы hda5,hda6,hda7. Монтируем снова:
mount /dev/hda1 /mnt/hda1 -t ufs -o sunx86

Опция -o sunx86 нашлась в процессе самостоятельного гуглежа - оказывается, UFS бывает разных типов.
Теперь всё смонтировалось. Видим файлы, всё хорошо. Сейчас нас интересуют файлы /etc/passwd и /etc/shadow. Смотрим в passwd, видим, что надо смотреть в shadow - на месте пароля в passwd стоит "x". Идём в shadow, видим пользователей, в том числе рута и нашего. Дальше - дело техники: меняем хеш пароля рута на хеш пароля нашего пользователя и - вуаля! Пароль рута поменялся на пароль нашего пользователя, а его мы уже знаем. Разумеется, предварительно оба файла скопировали на флешку, ибо бэкапы рулили, рулят и будут рулить.
Скоро сказка сказывается... При попытке записи файла нас обламывают: filesystem is read-only. Тваю мать! Отмонтируем раздел, монтируем с опцией rw, проверяем командой mount - пишут, что раздел rw-таки. Повторяем фокус с заменой хеша - результат тот же. Расстраиваемся и идём пить пиво чай (на работе всё-таки).
После чаепития решили слазить в dmesg:
dmesg | tail.

Кстати, очень полезная вещь, много раз выручала.
Так вот, в выводе dmesg'а написано, что ФС с ошибками и надо бы fsck прогнать. По всей видимости из-за этого и не давали нам писать в эту ФС. Ладно, фигня делов, достаём fsck:
umount /dev/hda5
fsck /dev/hda5 -t ufs

И опять засада - нету у нас fsck.ufs. Что в переводе на русский значит - нечем прочекать. Вот теперь расстраиваемся ещё больше и идём пить пиво, так как день кончился.
К началу следующего дня родился ещё один вариант решения: если мы не можем изменить файл в файловой системе, то кто нам сможет помешать просто изменить несколько байт в секторе жёсткого диска? Некоторое время потратили на поиск соответствующих утилит - хекс-редакторов. Остановились на lde - он специализируется на работе с жёстким диском и есть в Кноппиксе.
Достали ноутбук с нашей соляркой, но, прежде чем продолжить эксперименты, решили проверить сам винж на предмет сбойных секторов, ибо солярка при загрузке упоминал что не может прочесть сектор такой-то с винта. Проверяем:
dd if=/dev/hda of=/dev/zero bs=16K

Копирует... Винт лампочками моргает не переставая... А вот сколько он уже скопировал, и сколько нам ещё ждать по времени - неизвестно. К счастью, в man dd написано, что если послать процессу dd сигнал USR1, то dd выдаст нам статистику, не прерывая работы. Ищем pid dd, создаём ещё одну консоль и там пишем:
ps aux | grep dd

Запоминаем pid (ну, к примеру, 5508), пишем:
kill -USR1 5508

В консоли dd признаётся, сколько он считал записей, сколько записал, сколько это в гигабайтах, сколько времени прошло и какова средняя скорость. Отсюда, путём простых подсчётов, находим оставшееся время. Вышло что-то около 15 минут, при прошедших пяти. Можно было просто подождать, попивая чай, но программисткая мысль пошла дальше, и родила следующюю конструкцию: пишем в консоли с kill'ом
while true ; do { date ; kill - USR1 5508 ; sleep 10 ; } ; done

Результат - каждые 10 секунд dd выводит статистику. Намного приятней распивать чаи, созерцая статистику, чем просто пялится на пустой экран...
В общем итоге, образ 40кагигового винта ушёл в /dev/zero примерно за 20 минут, показав среднюю скорость около 30-35 мбайт/сек, без единой ошибки. Уже легче - винт сам живой, значит, сбой был только на уровне ФС. А это лечить проще, чем искать новый винт и вживлять туда солярку.
Продолжаем лечение:
lde /dev/hda

Там выбираем блочный режим (b), делаем поиск строки (/). Мы искали сначала хеш рута, но с первой попытки попали в какой-то другой файл, поэтому повторили поиск по хешу пароля нашего пользователя. Нашли, разрешили запись на винт (f,w), перешли в режим редактирования (e), переправили хеш рута на хеш нашего пользователя.
Чтобы не перегружаться, решили проверить результат через qemu:
qemu -hda /dev/hda

В Кноппикс не включён ускоряющий модуль kqemu, поэтому процесс идёт неторопливо. Но в итоге проверку пароля мы прошли :). Ура, массы ликуют, дамы бросают в воздух чепчики, суровые админы утирают украдкой скупую слезу - всеобщее счастье :).
Проверку ФС под эмулятором решили не делать: во-первых, железо эмулятора отличается от железа, на котором жила солярка, что может вызвать дополнительные проблемы; во-вторых - будет слишком долго.
Поставили винчестер на его родное место, запустились оттуда, вышли в сингл-мод, ввели пароль,прогнали fsck. Проверка прошла, что-то там исправила. Потом мы перезагрузились и у нас всё забегало.
+P.S. Опус писался постфактум, поэтому вышел немного сумбурным и нет выводов команд.
Все низкоуровневые операции с винчестером надо производить при отмонтированных разделах.