ЗАЩИТА ЛИЧНОЙ ИНФОРМАЦИИ

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

Любая компьютерная система требует некоторого рода защиты. Уровни защиты включают в себя физическую защиту (центрального процессора, дисков и терминалов), защиту файлов, защиту процессов и всей работающей системы. В многопользовательской среде еще более важно усиливать защиту. Каждый пользователь имеет право засекречивать и защищать свою среду и свои файлы. Ни один компьютер не имеет стопроцентной защиты. Ваша среда лишь настолько защищена, насколько вы сделали ее таковой. Защитные мероприятия могут достигать такой степени, что начинают мешать свободному обмену идеями и затруднять использование гибкости системы или исследование ее новых аспектов. Лично я считаю, что пользователи должны иметь свободу делать все, что они хотят, пока это не вредит системе или другим пользователям. Большинство информации, приведенной в данной книге, подтверждает это убеждение.

Тип защиты, который обсуждается в данной главе, касается личного аспекта защиты пользователя системы UNIX. Я хочу, чтобы место, где физически находятся мои разработки, мой регистрационный каталог и любые процессы, которые я запускаю в системе, были защищены. Для полного комфорта мне нужно знать, что никто не влезет в мои вещи (посредством обычных методов доступа или взлома) и не будет заглядывать мне через плечо, чтобы наблюдать, чем я занимаюсь.

В данном разделе мы рассмотрим инструментальные средства acme, inuse и lock. Acme - это препроцессор к команде UNIX'а acctcom. Acctcom выполняет довольно неплохую работу по отображению учетной информации, но некоторые опции требуется указывать все время. Acme устанавливает их для нас. Напомним, что учетные записи хранятся в виде структуры, а не в текстовом виде, и поэтому мы заставляем acctcom показывать их для нас.

Следующее средство, inuse, позволяет вам установить ваш терминал как "занятый", когда вы куда-нибудь уходите. Это эффективно блокирует его и не позволяет никому использовать его. Для реализации такого блокирования представлены программы как на языке Си, так и на языке интерпретатора shell.

Последнее средство, lock, используется для блокирования и разблокирования прав доступа к файлу и является на самом деле простым интерфейсом с командой chmod.


      ИМЯ:  acme

acme Отображение учетной информации обо мне

НАЗНАЧЕНИЕ

Генерирует опции, необходимые для вывода на экран информации обо мне, которая хранится в учетном файле.

ФОРМАТ ВЫЗОВА

     acme [-l] [-u]

ПРИМЕР ВЫЗОВА

acme -u Выводит всю учетную информацию о пользователе с именем $LOGNAME

ТЕКСТ ПРОГРАММЫ

    1   :
    2   # @(#) acme v1.0  Give accounting info on me Author: Russ Sage
    2а                    Дать учетную информацию обо мне
     
    4   if [ "$1" != "-l" -a "$1" != "-u" ]
    5     then  echo "usage: acme [-l] [-u]" >&2
    6           echo "     -l for ttyline"   >&2
    7           echo "     -u for user name" >&2
    8           exit 0
    9   fi
     
    11  OPT=""
    12  for ARG in $*
    13  do
    14          case $ARG in
    15          -l)     OPT="$OPT -l `basename \`tty\``";;
    16          -u)     OPT="$OPT -u $LOGNAME";;
    17          *)      OPT="$OPT $ARG";;
    18          esac
    19  done
     
    21  echo "acctcom $OPT"
    22  acctcom $OPT

ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ

ARG Каждое значение, указанное в командной строке
LOGNAME Переменная среды, содержащая мое регистрационное имя
OPT Объединенный список всех опций и их аргументов

ОПИСАНИЕ

Зачем нам нужен командный файл acme?

Большинство больших систем UNIX запускают стандартное программное обеспечение для сбора учетной информации об использовании системы. Результаты учетных транзакций передаются обычно в файл /usr/adm/pacct. Фактически сбор учетной информации выполняется ядром системы. Каждый раз при завершении процесса программы сбора учетной информации в ядре производят одну запись. Переключателем, который включает и выключает эту операцию, является acct(2). Команды пользовательского уровня также взаимодействуют с системным вызовом (acct on(1M)) и печатают результаты сбора учетной информации (acctcom(1)).

Теперь, когда мы знаем, где находятся учетные записи и как они туда попадают, нам нужно напечатать эту информацию. Acctcom может печатать таблицы с информацией, но вам необходимо знать, какой использовать индекс. Просмотр может производится по номеру терминальной линии (это полезно, если идентификатор процесса был изменен командой setuid), по имени пользователя, по группе, по времени и т.д. Я наиболее часто использую опции поиска информации по номеру линии терминала и по имени пользователя. С их помощью вы можете получить список всех основных данных, имеющих отношение к вам. Когда вы вызываете acctcom с этими опциями, вам необходимо указать дополнительную информацию, такую как имя вашего терминала и ваше пользовательское имя. Было бы хорошо, если бы мы могли уменьшить количество нажатий на клавиши и объем вычислений, требуемых для получения информации. Для этого и предназначен acme.

Что делает acme?

Acme - это интерфейсный процессор для команды acctcom(1). Он служит для выдачи информации, которая требуется согласно указанным опциям. Вы должны только дать командному файлу acme опции в сокращенном виде, а все остальное он сделает сам. Если acme вызывается без аргументов, программа acctcom выведет по умолчанию все записи.

Команда acctcom имеет много опций. В действительности мы используем одну или две, но зато используем их часто. Двумя опциями, которые понимает acme, являются -l и -u. Когда указана опция -l, acme получает имя вашего терминала и помещает его в командную строку. Если указана опция -u, acme получает ваше пользовательское имя и тоже вставляет его в командную строку. Время от времени используются другие опции для бавления специфической информации или небольшого изменения выходного формата. Для того чтобы была возможность использовать другие опции команды acctcom, acme включает в командную строку, формируемую для fcctcom, любые дополнительные корректные опции acctcom, переданные в командной строке для acme. Таким образом, acme поддерживает базовые возможности, а кроме того позволяет вам подгонять команду под ваш вкус.

Перед тем, как начнется выполнение команды acctcom, на экран выводится расширенный вид командной строки, так что вы можете видеть командную строку, сгенерированную acme. Без этого может получиться путаница, поскольку вы не будете знать, что собирается делать программа.

ПРИМЕРЫ

     1. $ acme

Выдача ВСЕХ моих учетных данных. Это последовательный список всех команд, которые были запущены начиная с момента загрузки по настоящее время. Счастливого чтения!

     2. $ acme -u -b

Печать в обратном порядке всех учетных записей с моим пользовательским именем. Обратный порядок означает - от самой последней из предыдущих команд до моей первой команды.

     3. $ acme -l

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

ПОЯСНЕНИЯ

В строках 4-9 выполняется проверка на наличие ошибок. Если первый позиционный параметр не -l и не -u, то это ошибка. Выводится сообщение об этом и программа завершается.

В строке 11 переменная OPT инициализируется пустой строкой. Эта переменная содержит все дополнительные опции acctcom и их аргументы.

Строки 12-19 представляют собой цикл for, который повторяется по всем позиционным параметрам. Каждый аргумент сверяется в операторе case с допустимыми опциями. Если опцией является -l (строка 15), в переменную OPT заносится то значение, которое она уже имеет, опция -l и добавляется имя терминального устройства, полученное от команды UNIX'а tty. Команда tty выводит и префикс /dev, который не нужен. Для того чтобы избавиться от этого префикса, мы берем из этой символьной строки только основное имя.

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

После того обработки всех опций строка 21 выводит на экран командную строку, которая должна быть выполнена, так что мы знаем, что мы задавали. В строке 22 выполняется сама команда acctcom. Выходной результат соответствует описанию acctcom(1).


      ИМЯ:   inuse

inuse Запретить использование терминала

НАЗНАЧЕНИЕ

Блокирует ваш терминал путем перевода в состояние занятости. Если кто-либо попытается вторгнуться, вы это заметите.

ФОРМАТ ВЫЗОВА

      inuse

ПРИМЕРЫ ВЫЗОВА

inuse Перевод терминала в состояние занятости

mypasswd Вводится мой пароль, но не отображается на экран

ТЕКСТ ПРОГРАММЫ

    1   :
    2   # @(#) inuse v1.0  Disable terminal and alert if used  Author: Russ Sage
    2а    Запретить использование терминала и сообщить о попытке использования
     
    4   trap "echo you\'re BUSTED!!; stty echo; kill $$" 2 15
     
    6   PATH=/bin:/usr/bin
    7   SECRET="secret"
     
    9   stty -echo
    10  echo "Lock string: \c"
    11  read BUF1
    12  echo
     
    14  while :
    15  do
    16          BUF2=`line < /dev/tty`
    17          if [ "$BUF2" = "$BUF1" ]
    18            then  break
    19          elif [ "$BUF2" = "$SECRET" ]
    20            then  break
    21          fi
    22          echo "^G\c"
    23  done
    24  stty echo

ОПИСАНИЕ

Зачем нам нужен командный файл inuse?

Рабочий день всегда загружен: много людей, еще больше бумаг, всякие поручения и так далее и так далее. Когда вы покидаете свое рабочее место, что вы собираетесь делать со своим зарегистрированным терминалом? Каждый раз входить в систему и выходить из нее слишком долго, но вы не хотите оставлять вашу работу открытой для всех. Вам необходима программа, которую вы можете запустить на время вашего отсутствия и которая не позволит другим людям использовать то, что вы делаете.

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

Что делает inuse?

Inuse переводит ваш терминал в режим вечной работы. Это означает, что терминал не отвечает на ваши запросы или запросы кого-то другого. Когда вы готовы разблокировать ваш терминал, введите секретный пароль или пароль, который вы придумали.

Когда вы первый раз вызываете inuse, у вас запрашивается пароль. Эхо-отображение на терминал отключено, поэтому пароль не выводится на экран. Для гарантии того, что никто не пытается переадресовать командному файлу inuse какой-либо файл данных, все операции чтения производятся непосредственно из файла терминального устройства /dev/tty, а не через файловый дескриптор стандартного ввода. Это позволяет защититься от попыток других пользователей вторгнуться в работу терминала путем посылки на стандартный ввод файла большого размера, содержащего разные слова.

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

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

ПОЯСНЕНИЯ

Строка 4 инициализирует оператор trap. При активизации обработчика trap выполняются три команды.

Целью применения ловушки trap является реагирование на любую попытку прервать работу командного файла и прорваться на ваш терминал. Первая команда выдает предупреждение о том, что вы вторгаетесь. Вторая команда переключает терминал обратно в режим эхо-отображения, так что все, что будет впоследствии введено с клавиатуры, отобразится на экране. и последняя команда заставляет программу совершить самоубийство. Как мы увидим позже, это самоубийство является особым родом прекращения работы программы. Обращение к "самому себе" в операторе kill выполняется с использованием метасимволов $$, которые представляют собой идентификационный номер выполняющегося shell-процесса. Обработчик ловушек включается сигналами 2 и 15, которыми являются прерывание и программное завершение соответственно. Отметим, что сигнал выхода из программы (сигнал 3) здесь не используется. Причину этого мы объясним позже.

Строка 6 устанавливает маршрут, по которому может обращаться inuse. Тем самым inuse никогда не сможет быть "застигнут врасплох" кем-нибудь, кто проник незаметно (в "троянском коне"). Строка 7 инициализирует секретный пароль значением "secret", которое совсем не секретно. Вы можете изменить пароль на любое слово перед установкой командного файла в вашей системе. В правах доступа к файлу, в котором хранится текст данной shell-программы, вы должны запретить возможность чтения. В противном случае другие пользователи смогут увидеть секретное слово.

Строка 9 отключает эхо-отображение, строка 10 печатает запрос пароля, а строка 11 читает пароль, который вы вводите, и заносит его в переменную BUF1.

Строки 14-23 представляют собой вечный цикл while, который можно прервать только вводом правильного пароля. Строка 16 читает ввод с клавиатуры. При нажатии возврата каретки строка 17 проверяет, соответствует ли то, что введено с клавиатуры, паролю пользователя. Если нет, переменная BUF2 сравнивается с секретным паролем. Если какой-то из паролей совпадает, оператор break производит выход из цикла while, тем самым прекращая выполнение программы. Если введенные данные не соответствуют ни одному из паролей, то в строке 22 выдается звуковой сигнал и снова начинает выполняться оператор чтения клавиатуры.

Если пароль введен правильно, в строке 24 включается эхо-отображение на терминал и программа завершается. Если происходит прерывание, активизируется оператор trap. Данная операция подробно рассматривается ниже.

ПОДРОБНЕЕ О ЛОВУШКАХ

Нам нужно рассмотреть смысл клавиши выхода из программы. Она производит прерывание, похожее на все другие прерывания, но кроме того выводит дамп памяти для запущенного процесса. Мы оставляем клавишу выхода нетронутой оператором trap, поскольку она становится нашей последней надеждой на приостановление командного файла inuse. Когда ваш терминал заблокирован, он эхо-отображает вводимые с клавиатуры символы, но не реагирует на них. Тот, кто нажимает на клавиши, видит это и пытается выйти из ситуации, нажимая на клавишу прерывания (обычно это клавиша DEL). Когда он это делает, на экран выводится сообщение "you're busted", эхо-отображение снова включается и программа сама себя уничтожает (сигнал 15). Когда сигнал уничтожения принимается программой, этот сигнал ловится, печатается сообщение и программа снова сама себя уничтожает. Эта последовательность выполняется снова и снова, как в вечном цикле. Каждый раз, когда ловушка уничтожается и снова запускается, используется стек. Если все это будет выполняться достаточно долго, то весь стек заполнится записями об активизации и переполнится, аварийно завершая весь сеанс работы.

Если клавиша выхода будет нажата до активизации оператора trap, то программа завершится чисто. Если же клавиша выхода будет нажата после начала работы оператора trap, то произойдет выдача дампа памяти процесса и программа завершится. Это не совсем честный прием, но программирование на языке shell вынуждено быть именно таким, и это предупреждает вас о том, что что= то не в порядке.

Текущие значения клавиш для сигналов прерывания и выхода отображаются командой stty(1). Эти значения можно переустановить в любые по вашему желанию. У меня текущие установки такие:

        speed 9600 baud; intr = DEL; quit = ^|; erase = ^h; kill = ^u;
        eof = ^d;

Набрав на клавиатуре "stty intr z", вы можете установить символ z в качестве сигнала прерывания ваших процессов, поэтому такое изменение клавиши прерывания и запуск бесконечного цикла представляет собой еще один способ защиты вашего сеанса работы. Поскольку вам потом нужно будет вернуть старое значение, вы должны запомнить то, что вы делали. Такой настройкой сигналов вы можете делать с вашим терминалом почти все, что хотите. Этот подход дает меньшую степень защиты, чем перехват прерываний, но может обеспечить вас минимальной защитой, не приводя к выдаче дампа памяти.

Теперь мы представляем версию на языке Си.

ТЕКСТ ПРОГРАММЫ inuse НА ЯЗЫКЕ СИ

    1   char id[] = "@(#) inuse v1.0 Disable terminal Author: Russ Sage";
     
    3   #include
    4   #include
    5   #include
     
    7   #define SSIZ 7
    8   #define BSIZ 512
    9   #define BELL "\07"
    10  #define LF   "\n"
     
    12  main()
    13  {
    14          register int fd, sig, n;
    15          char    secret[SSIZ];
    16          char    buf1[BSIZ], buf2[BSIZ];
    17          struct  sgttyb sav_tty, chg_tty;
     
    19          secret[0] = 's';
    20          secret[1] = 'e';
    21          secret[2] = 'c';
    22          secret[3] = 'r';
    23          secret[4] = 'e';
    24          secret[5] = 't';
    25          secret[6] = '\n';
     
    27          buf1[0] = buf2[0] = '\0';
    28          if ((fd = open("/dev/tty",O_RDONLY)) == -1)
    29                  exit(1);
     
    31          for (sig = 2; sig <= 15; sig++)
    32                  signal(sig, SIG_IGN);
     
    34          if (gtty(0, &sav_tty))
    35                  exit(2);
    36          chg_tty = sav_tty;
    37          chg_tty.sg_flags &= ~ECHO;
    38          if (stty(0, &chg_tty))
    39                  exit(3);
     
    41          write(1,"Lock string: ",13);
    42          read(fd, buf1, BSIZ);
    43          write(1, LF, 1);
     
    45          for (;;) {
    46                  n = read(fd, buf2, BSIZ);
    47                  buf2[n] = '\0';
     
    49                  if (strcmp(buf2, buf1) == 0)
    50                          break;
    51                  if (strcmp(buf2, secret) == 0)
    52                          break;
    53                  write(1, BELL, 1);
    54          }
    55          stty(0, &sav_tty);
    56          close(fd);
    57  }

ОПИСАНИЕ

Зачем нам нужна программа inuse (си)?

Версия inuse на языке Си работает почти так же, как и версия на языке shell. Основное отличие заключается в том, что командные файлы на языке shell пользуются командами раздела (1), в то время как программы на Си используют команды разделов (2) и (3).

Что делает программа inuse (си)?

Теоретические основы функционирования такие же, как и в shell-версии. Инициализируется секретный пароль (в данном случае применяется такой синтаксис, чтобы команда strings(1) не смогла посмотреть его в исполняемом модуле), перехватываются сигналы, читается пароль пользователя и начинается бесконечный цикл, который читает символы с клавиатуры. Как только на клавиатуре что-то набрано и нажата клавиша возврата каретки, входные данные сравниваются с двумя известными паролями. Если они соответствуют одному из паролей, программа переустанавливает терминал и завершается. Если совпадения не произошло, терминал выдает звуковой сигнал и снова читает клавиатуру.

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

ПОЯСНЕНИЯ

Строка 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. Пароль в исполняемом модуле спрятан от любопытных глаз. Вы получаете больший уровень защиты и более ясный подход за счет использования языка низкого уровня и написания более длинной программы.


      ИМЯ: lock

lock Блокирование и разблокирование файлов

НАЗНАЧЕНИЕ

Изменяет права доступа к файлам на запись и чтение, что выглядит как блокирование и разблокирование.

ФОРМАТ ВЫЗОВА

      lock [-u] file [...]

ПРИМЕР ВЫЗОВА

     lock $HOME

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

ТЕКСТ ПРОГРАММЫ

    1   :
    2   # @(#) lock v1.0  Lock and unlock files  Author: Russ Sage
    2а                    Блокирование и разблокирование файлов
     
    4   if [ $# -eq 0 ]
    5     then echo "lock: incorrect argument count" >&2
    6          echo "usage: lock [-u] file [...]"    >&2
    7          exit 1
    8   fi
     
    10  if [ "`echo $1 | cut -c1`" = "-" -a "$1" != "-u" ]
    11    then  echo "lock: invalid argument $1"   >&2
    12          echo "usage: lock [-u] file [...]" >&2
    13          exit 1
    14  fi
     
    16  MODE1="go-rw"
    17  MODE2="u-w"
     
    19  if [ "$1" = "-u" ]
    20    then  shift
    21          MODE1="go+r"
    22          MODE2="u+w"
    23  fi
     
    25  chmod $MODE1 $@
    26  chmod $MODE2 $@

ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ

MODE1 Режимы доступа к файлу, относящиеся к группе пользователей и другим пользователям
MODE2 Режимы доступа к файлу, относящиеся к владельцу

ОПИСАНИЕ

Зачем нам нужен командный файл lock?

Все файлы в системе UNIX имеют некоторые права доступа. Эти режимы изменяются в соответствии с тем, как используется этот файл. Для каждого файла должны быть установлены три набора прав доступа - для владельца, группы и других пользователей. Обычно текстовые файлы имеют режим 644, а исполняемые и каталоги - 755. Некоторые системы присваивают по умолчанию другие значения.

Если вы хотите ограничить права чтения или записи, следует использовать команду chmod(1). Новый режим должен указываться либо как абсолютное восьмеричное число (например, 777), либо как буквенное выражение, указывающее, какая категория пользователей что может делать (например, ugo+rwx). Если вы хотите добавить или запретить определенные возможности, легче использовать для этого буквенное выражение. Но даже в таком случае нам будет полезно средство, позволяющее уменьшить число нажатий на клавиши и избавляющее от необходимости точно запоминать все, что касается прав доступа к файлу.

Что делает lock?

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

Входными данными для lock являются имена файлов. Допускается использование символьной строки с любым набором имен файлов. В ней должно находиться по крайней мере одно имя файла. Имена файлов с указанием каталогов также допускаются.

Действие lock по умолчанию - блокирование указанного файла. Опция -u разблокирует указанный файл.

Если команде chmod передано неверное имя файла, это создает проблемы для нее и в этом случае выводится сообщение об ошибке.

ПРИМЕРЫ

    1.  $ lock -u $HOME/src *.c

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

    2.  $ lock $HOME/bin

Блокирует мой каталог bin так, чтобы никто не мог читать или писать в него файлы. Даже хотя мой каталог нельзя читать, любой посторонний может все же войти в него командой cd, если установлен бит x. Если он попытается выполнить команду ls, каждый файл будет выдавать сообщение об ошибке вида "filename not found" (файл с именем "filename" не найден). Никто не может получить информацию из индексного дескриптора файла, такую как временные характеристики и права доступа, но любой может увидеть имена всех файлов из сообщения об ошибке.

ПОЯСНЕНИЯ

Строки 4-8 проверяют счетчик аргументов. Если не был указан ни один аргумент, выводится сообщение об ошибке. Должно быть указано хотя бы одно имя файла.

Строки 10-14 проверяют, является ли первый символ первого позиционного параметра знаком "минус" и отличается ли первая опция от допустимой опции -u. Если эти условия выполняются, выводится сообщение об ошибке и программа завершается.

Строки 16 и 17 инициализируют установки режимов прав доступа по умолчанию. MODE1 устанавливается для запрета чтения и записи категориям пользователей "группа" и "другие". MODE2 устанавливается для запрета пользователю (т.е. мне) права записи. Это страховка для меня от случайной записи в файл. Нам нужны две такие переменные, поскольку эти два режима довольно разные. Единственный способ сделать это - дважды вызвать команду chmod с двумя различными установками.

Строки 19-23 проверяют, была ли указана в командной строке опция -u. Если была, она убирается из командной строки командой shift и переменные режима инициализируются для разблокирования файлов. Строка 21 разрешает возможность чтения группе пользователей и другим. Строка 22 разрешает мне возможность записи. Обратите внимание, что в командном файле lock не происходит модификации битов x, s или t. Это сделано намеренно, поскольку бит x должен быть установлен только в случае, если файл может быть исполняемым. Для каталогов бит x должен быть установлен только в случае, если вы хотите, чтобы другие пользователи могли заходить в этот каталог. Мы также никогда не устанавливаем возможность записи для группы пользователей и для других пользователей, но мы отключаем ее при блокировании файлов. Это дополнительная мера предосторожности на случай, если файл имеет установленными такие права доступа к нему, которые мы по каким-то причинам не желаем оставлять.

В строках 25 и 26 выполняется команда chmod. Параметр $@ использован как обозначение всех имен файлов, указанных в командной строке. Такой способ позволяет вам вызывать lock с несколькими именами файлов.

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

Назад | Содержание | Вперед