Приемы профессиональной работы в UNIX


ЗАЩИТА ЛИЧНОЙ ИНФОРМАЦИИ - часть 8


Строка 1 помещает документирующую информацию в символьный массив. При наличии этого текста в объектном модуле команда what(1) может вынуть его оттуда, чтобы мы могли посмотреть его для идентифицирования нашей программы.

Строка 3 подключает файл fcntl.h. Этот файл содержит все определения языка Си для открытия, закрытия, чтения и записи файлов. Строка 4 подключает файл signal.h. Мы используем этот файл для определения переменной SIG_IGN, которая является отметкой игнорирования сигналов (signal_ignore). Строка 5 подключает файл sgtty.h, который мы используем для определения всего, что относится к получению информации о терминале посредством вызова ioctl(2).

Строка 7 определяет размер секретного пароля. Этот размер не обязательно должен быть точно таким, как длина пароля. Этот размер указан для удобства программирования.

Строка 8 объявляет размер буфера, в который каждый раз производится чтение с клавиатуры. Хотя 512 символов слишком много для такого считывания, на самом деле чтение прекращается с приходом символа возврата каретки. Наличие большого буфера дает нам запас памяти.

Строки 9 и 10 определяют управляющие символы звукового сигнала и перевода строки.

Строка 14 объявляет некоторые рабочие переменные. Обратите внимание, что мы используем регистровые целые. Использование регистровых переменных для ускорения работы - полезный прием. Если вы объявили слишком много переменных по сравнению с количеством регистров в вашей машине, не будет никакой ошибки. Оставшиеся переменные рассматриваются как обычные переменные. Переменная fd используется в качестве файлового дескриптора при открытии файла /dev/tty, переменной si g последовательно присваиваются значения всех сигналов, а переменная n представляет собой число прочитанных символов.

Строка 15 определяет секретный массив. Этот символьный массив содержит наш секретный пароль, который прямо закодирован в программе. Строка 16 определяет два буфера, в которые мы читаем вводимые символы. Buf1 предназначен для нашего пользовательского пароля, а buf2 для попытки ввода пароля, который считывается, когда мы хотим прекратить выполнение программы. Строка 17 определяет две рабочие структуры, которые содержат информацию об установках терминала (ioctl). Здесь у нас две структуры, поскольку одна из них - первоначальная, а вторая - та, на которую мы хотим изменить, чтобы не забыть первоначальные установки.

Строки 19-25 загружают пароль в секретный массив. Мы выполняем посимвольное присвоение, поскольку при таком присвоении любая строка символов в объектном модуле получается разорванной. Это мера безопасности для предотвращения возможности зрительного просмотра с целью извлечения ценной информации.

В строке 27 эти два буфера инициализируются в нулевой размер.

Строки 28 и 29 открывают устройство /dev/tty. Если возвращаемый дескриптор файла равен -1, это говорит об ошибке и программа завершается.

Строки 31 и 32 перехватывают все сигналы. Цикл for работает с сигналами, имеющими номера от 2 до 15. Для каждого из этих значений выполняется системный вызов signal с целью игнорирования сигналов с такими значениями.

В строках 34-39 выполняется модификация терминальных характеристик для отключения эхо-отображения символов. Строка 34 получает информацию об установках терминала в структуру sav_tty. Системный вызов gtty - это просто программный интерфейс с системным вызовом ioctl(get_values). Если этот вызов неудачен, программа завершается.

Строка 36 заносит данные из структуры sav_tty в структуру chg_tty. Затем строка 37 присваивает элементу sg_flags результат операции отрицания над его же значением и символом ECHO, что означает "отключить эхо-отображение". После этого строки 38 и 39 записывают измененные значения обратно на терминальное устройство. Системный вызов stty - это просто программный интерфейс с системным вызовом ioctl(set_values).

Строка 41 выводит на экран запрос на ввод пароля. Дескриптор файла 1 является стандартным устройством вывода, а 13 - длина строки символов. Строка 42 читает BSIZ символов из файла /dev/tty. После чтения на экран выдается символ перевода строки. Это необходимо сделать, поскольку при отсутствии эхо-отображения на экран не выводится символ перевода строки, когда вы вводите свой пароль. Поэтому мы вынуждены вставить этот символ здесь сами.

Строки 45-54 представляют собой бесконечный цикл, который читает символы с клавиатуры. Строка 46 выполняет чтение терминала для распознавания пароля. В этой строке введенный пароль помещается в buf2, а не в buf1. Мы выясняем количество символов, прочитанных в buf2 (n). Поскольку индексирование массивов начинается с нуля, а не с 1, при вводе n символов мы попадаем в конец текста и здесь мы вставляем ноль для того, чтобы все, что было введено, представляло собой строку символов. Мы делаем это потому, что команда read не производит обработку символьной строки. Это делают системные вызовы stdio. Их описание находится в разделе (3) руководства по системе, а не в разделе (2). Нам нужно оформить прочитанные символы в виде строки, чтобы ее можно было сравнить с паролями.

Строка 49 сравнивает то, что ввели с клавиатуры, с тем паролем, который вы ввели в начале работы программы. Если эти символьные строки одинаковы, strcmp возвращает значение ноль, которое сообщает о совпадении. Команда break выводит выполнение из цикла for, и программа продолжается. Строка 51 выполняет такое же сравнение с секретным паролем. Если происходит совпадение, вы также выходите из цикла.

Если совпадения не произошло, строка 53 выдает на терминал звуковой сигнал и управление передается оператору read в начало цикла for.

Если произошел выход из цикла for, управление передается строке 55. Происходит запись первоначальной информации об установках терминала, тем самым включается эхо-отображение. Строка 56 закрывает файл /dev/tty, и происходит нормальное завершение работы программы.

Вы могли видите, программа на языке Си, хотя и несколько сложнее, чем на языке shell, но имеет некоторые преимущества. Она не может быть остановлена или нарушена ничем, кроме команды kill -9. Пароль в исполняемом модуле спрятан от любопытных глаз. Вы получаете больший уровень защиты и более ясный подход за счет использования языка низкого уровня и написания более длинной программы.




Начало  Назад  Вперед