Персональный
сайт
Игоря
Сысоева


 
english
обо мне
 
sysoev.ru
 
nginx
 
mod_accel
mod_realip
mod_deflate
программирование
всякая всячина
windows
freebsd
apache
pppd
unix
web
 
 

Модная аутентификация - PAP и CHAP

 

05.03.1999

До сих пор наш скрипт сам выполнял аутентификацию, то есть, вводил имя и пароль в ответ на запросы удалённой стороны. Но PPP предусматривает и свои способы аутентификации — PAP (Password Authentication Protocol) и CHAP (Challenge Handshake Authentication Protocol) и мы можем ими воспользоваться, если удалённая сторона достаточна сообразительна, чтобы не только выдать "login:", но и провести PAP или CHAP аутентификацию.

Нужно заметить, что комбинация FreeBSD+getty до недавнего времени не была таким сообразительным прибором, но, начиная с FreeBSD 2.2.7,getty распознает начальные LCP-кадры PPP-соединения и может вызывать, скажем, pppd, который и решает, что делать дальше. До этого getty умел только выдать этот самый "login:" и приходилось использовать mgetty.

Так как наш скрипт дозвонки больше не будет заниматься аутентификацией, нужно убрать из него имя пользователя "igor", его пароль "1234567" и ошибку аутентификации "Login incorrect":

        ABORT           "ERROR"                 \
        ABORT           "NO DIALTONE"           \
        TIMEOUT         5                       \
        ""              "AT"                    \
        "OK"            "ATZ"                   \
        "OK"            "ATS7=120"              \
        ABORT           "BUSY"                  \
        ABORT           "NO ANSWER"             \
        ABORT           "NO CARRIER"            \
        "OK"            "ATDP$1"                \
        TIMEOUT         125                     \
        "CONNECT"       "\\с"                   \
        TIMEOUT         30                      \
        "login:"        "\\с"

    if [ "$?" = "0" ]; then
        exit 0
    fi

Теперь скрипт заканчивает работу сразу же, как получит строку "login:". Отметим, что приглашение "login:" не имеет никакого отношения к PAP и CHAP, и pppd воспринимает его не более, как шум в линии, поэтому вместо этой строки может быть любое другое приглашение провайдера, в крайнем случае, "}".

PAP аутентификация происходит следующим образом — при установлении PPP-соединения удалённая сторона предлагает нам аутентификацию PAP. Мы соглашаемся и затем передаём наше имя и пароль открытом текстом. Если удалённую сторону имя и пароль устраивает, то аутентификация считается успешной. Имена и пароли для PAP хранятся в файле /etc/ppp/pap-secrets. У него должны быть такие права доступа "rw- --- ---". Для нашего случая мы запишем в этот файл:

igor            cool            1234567

Формат этой строки таков — наше имя, имя удалённой стороны и пароль. В PAP используется только наше имя и пароль, а имя удалённой стороны "cool" может быть произвольным. В принципе, оно нужно только для того, чтобы pppd мог определить, какой пароль нужно использовать в случае, когда Вы используете одно и то же имя у разных провайдеров, например:

igor            cool            1234567
igor            citynet         7654321

Теперь мы можем звонить провайдеру:

pppd cuaa0 57600 lock connect '/etc/ppp/dial'           \
        user igor remotename cool                       \
        defaultroute noipdefault debug

Параметры user igor и remotename cool позволяют однозначно определить, какой пароль использовать при аутентификации, в данном случае это 1234567. Как уже говорилось, параметр remotename необходим только, если мы не можем однозначно выбрать пароль из файла /etc/ppp/pap-secrets. Имя нашей стороны можно также задать с помощью параметра name igor, но параметр user имеет больший приоритет. Заметим, что хотя пароль передаётся в открытом виде, удалённая сторона может хранить пароль в виде результата какой-либо хэш-функции, например, MD5, в качестве параметра которой выступает пароль.

CHAP аутентификация происходит следующим образом — при установлении PPP-соединения удалённая сторона предлагает нам аутентификацию CHAP. Мы соглашаемся, и удалённая сторона высылает нам ключ (challenge), состоящий из случайной последовательности символов, и своё имя. Мы берём наш пароль и присланный ключ и прогоняем их через алгоритм MD5. Получившийся результат высылаем вместе со своим именем. Удалённая сторона, зная наш пароль и высланный её ключ, в свою очередь, проделывает то же самое у себя, и если её результат совпадает с присланным нами, то аутентификация считается успешной. Таким образом, пароль не передаётся в открытом виде, но удалённая сторона должна хранить наш пароль в открытом виде.

Имена и пароли для CHAP хранятся в файле /etc/ppp/chap-secrets, права доступа у него должны быть такие же, как для PAP: "rw- --- ---", и формат строк тоже совпадает:

igor            cool            1234567

Теперь наша строка для звонка провайдеру выглядит так:

pppd cuaa0 57600 lock connect '/etc/ppp/dial'           \
        user igor                                       \
        defaultroute npipdefault debug

Обратите внимание, что она отличается от PAP только отсутствием параметра remotename. Это объясняется тем, что удалённая сторона сама говорит своё имя, поэтому её имя, записанное в файле /etc/ppp/chap-secrets, не может быть произвольным, как это было в случае с PAP. Даже если Вы зададите параметр remotename, имя, сообщённое удалённой стороной, имеет больший приоритет. Что касается имени нашей стороны, то оно может быть также задано с помощью параметра name igor.

Может ли pppd аутентифицировать себя в одних случаях через PAP, а в других — через CHAP ? Ответ — да. При запуске pppd проверяет, как он может аутентифицировать себя, исходя из локального имени и имени удалённой стороны, то есть, есть ли в файлах /etc/ppp/pap-secrets или /etc/ppp/chap-secrets строки с такими именами. И если, скажем, удалённая сторона предлагает CHAP, а pppd не находит пароль в файле /etc/ppp/chap-secrets, то он запросит PAP и если это устраивает удалённую сторону, то аутентификация пройдёт по PAP.

Кроме того, можно указать pppd, чтобы он не соглашался проводить аутентификацию тем или иным способом или же требовал какого-то одного способа с помощью различных комбинаций параметров refuse-pap, refuse-chap, require-pap и require-chap. Раньше эти параметры назывались соответственно -pap, -chap, +pap и +chap.

(C) Игорь Сысоев
http://sysoev.ru