UNIX: разработка сетевых приложений - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
36 allocations. 0 bytes
added at Thu Jun 5 21:01:31 2003, first used at Thu Jun 5 21:15:07 2003
Source address: 127.0.0.1/128 (IP proto 255)
Dest address: 127.0.0.1/128 (IP proto 255)
Authentication key. 160 bits: 0x0123456789abcdef0123456789abcdef01234567
Из этого дампа видно, что ядро изменило значение протокола с 0 на 255. Это артефакт реализации, а не общее свойство сокетов PF_KEY. Кроме того, ядро изменило длину префикса с 32 на 128. Это какая-то проблема, связанная с протоколами IPv4 и IPv6. Ядро возвращает расширение (с номером 19), которое не обрабатывается нашей программой выведения дампа. Неизвестные расширения пропускаются (их длина имеется в соответствующем поле). Наконец, возвращается расширение времени жизни (листинг 19.7), содержащее информацию о текущем времени жизни соглашения о безопасности.
Листинг 19.7. Структура расширения времени жизни
struct sadb_lifetime {
u_int16_t sadb_lifetime_len; /* длина расширения / 8 */
u_int16_t sadb_lifetime_exttype; /* SADB_EXT_LIFETIME_{SOFT,HARD,CURRENT} */
u_int32_t sadb_lifetime_allocations; /* количество соединений, конечных
точек или потоков */
u_int64_t sadb_lifetime_bytes; /* количество байтов */
u_int64_t sadb_lifetime_addtime; /* время создания либо время от создания
до устаревания */
u_int64_t sadb_lifetime_usetime; /* время первого использования или время от
первого использования до устаревания */
};
Расширения времени жизни бывают трех типов. Расширения SADB_LIFETIME_SOFT и SADB_LIFETIME_HARD задают гибкое и жесткое ограничения на время жизни соглашения. Сообщение SADB_EXPIRE отправляется ядром в случае превышения гибкого ограничения на время жизни. После достижения жесткого ограничения использование соглашения прекращается. Расширение SADB_LIFETIME_CURRENT возвращается в ответ на SADB_DUMP, SADB_EXPIRE и SADB_GET и описывает соответствующие параметры текущего соглашения.
19.5. Динамическое управление SA
Для повышения безопасности требуется периодическая смена ключей. Обычно для этого используется протокол типа IKE (RFC 2409 [43]).
ПРИМЕЧАНИЕВ момент написания этой книги рабочая группа IETF по IPSec разрабатывала замену для протокола IKE.
Демон, обеспечивающий безопасность, регистрируется в ядре при помощи сообщения SADB_REGISTER, указывая в поле sadb_msg_satype (см. табл. 19.2) тип соглашения о безопасности, которое он умеет обрабатывать. Если демон может работать с несколькими типами соглашений, он должен отправить несколько сообщений SADB_REGISTER, зарегистрировав в каждом из них ровно один тип SA. В ответном сообщении SADB_REGISTER ядро указывает поддерживаемые алгоритмы шифрования или аутентификации (в отдельном расширении), а также длины ключей для этих алгоритмов. Расширение поддерживаемых алгоритмов описывается структурой sadb_supported, представленной в листинге 19.8. Структура содержит заголовок, за которым следуют описания алгоритма шифрования или аутентификации в полях sadb_alg.
Листинг 19.8. Структура, описывающая поддерживаемые алгоритмы
struct sadb_supported {
u_int16_t sadb_supported_len; /* длина расширения и списка алгоритмов / 8 */
u_int16_t sadb_supported_exttype; /* SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} */
u_int32_t sadb_supported_reserved; /* зарезервировано для расширения в будущем */
};
/* далее следует список алгоритмов */
struct sadb_alg {
u_int8_t sadb_alg_id; /* идентификатор алгоритма из табл. 19.5 */
u_int8_t sadb_alg_ivlen; /* длина IV или нуль */
u_int16_t sadb_alg_minbits; /* минимальная длина ключа */
u_int16_t sadb_alg_maxbits; /* максимальная длина ключа */
u_int16_t sadb_alg_reserved; /* зарезервировано для расширения в будущем */
};
После заголовка sadb_supported следует по одной структуре sadb_alg для каждого алгоритма, поддерживаемого системой. На рис. 19.1 представлен возможный ответ на сообщение, регистрирующее обработчик SA типа SADB_SATYPE_ESP.
Рис. 19.1. Данные, возвращаемые ядром в ответ на команду SADB_REGISTER
Программа, представленная в листинге 19.9, просто регистрируется в ядре в качестве обработчика заданного механизма безопасности и выводит ответ ядра, содержащий список поддерживаемых алгоритмов.
Листинг 19.9. Регистрация демона-обработчика
//key/register.c
1 void
2 sadb_register(int type)
3 {
4 int s;
5 char buf[4096]; /* XXX */
6 struct sadb_msg msg;
7 int goteof;
8 int mypid;
9 s = Socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
10 mypid = getpid();
11 /* формирование и отправка запроса SADB_REGISTER */
12 bzero(&msg, sizeof(msg));
13 msg.sadb_msg_version = PF_KEY_V2;
14 msg.sadb_msg_type = SADB_REGISTER;
15 msg.sadb_msg_satype = type;
16 msg.sadb_msg_len = sizeof(msg) / 8;
17 msg.sadb_msg_pid = mypid;
18 printf("Sending register message:n");
19 print_sadb_msg(&msg, sizeof(msg));
20 Write(s, &msg, sizeof(msg));
21 printf("nReply returned:n");
22 /* Чтение и вывод ответа SADB_REGISTER, игнорирование всех прочих
сообщений */
23 for (;;) {
24 int msglen;
25 struct sadb_msg *msgp;
26 msglen = Read(s, &buf, sizeof(buf));
27 msgp = (struct sadb_msg*)&buf;
28 if (msgp->sadb_msg_pid == mypid &&
29 msgp->sadb_msg_type == SADB_REGISTER) {
30 print_sadb_msg(msgp, msglen);
31 break;
32 }
33 }
34 close(s);
35 }
Открытие сокета PF_KEY1-9 Мы открываем сокет PF_KEY.
Сохранение PID10 Поскольку ядро будет адресовать нам свои сообщения по идентификатору процесса, нам необходимо сохранить его, чтобы иметь возможность впоследствии отбирать интересующие нас сообщения.
Создание сообщения SADB_REGISTER11-17 Подобно SADB_DUMP, сообщение SADB_REGISTER не требует никаких расширений. Мы обнуляем сообщение, после чего заполняем интересующие нас поля структуры.
Вывод и отправка сообщения18-20 Мы отображаем подготовленное сообщение на экране при помощи функции print_sadb_msg, после чего записываем сообщение в сокет.
Ожидание ответа23-30 Мы считываем сообщения из сокета, ожидая ответа на наше сообщение о регистрации. Ответ адресован по идентификатору процесса и представляет собой сообщение SADB_REGISTER. Он содержит список поддерживаемых алгоритмов, который выводится нашей функцией print_sadb_msg.
Пример
Мы запускаем программу register в системе, поддерживающей на несколько протоколов больше, чем описано в RFC 2367.
macosx % register -t ah
Sending register message:
SADB Message Register, errno 0, satype IPsec AH, seq 0, pid 20746
Reply returned:
SADB Message Register, errno 0, satype IPsec AH, seq 0, pid 20746
Supported authentication algorithms:
HMAC-MD5 ivlen 0 bits 128-128
HMAC-SHA-1 ivlen 0 bits 160-160
Keyed MD5 ivlen 0 bits 128-128
Keyed SHA-1 ivlen 0 bits 160-160
Null ivlen 0 bits 0-2048
SHA2-256 ivlen 0 bits 256-256
SHA2-384 ivlen 0 bits 384-384
SHA2-512 ivlen 0 bits 512-512
Supported encryption algorithms:
DES-CBC ivlen 8 bits 64-64
3DES-CBC ivlen 8 bits 192-192
Null ivlen 0 bits 0-2048
Blowfish-CBC ivlen 8 bits 40-448
CAST128-CBC ivlen 8 bits 40-128
AES ivlen 16 bits 128-256
Если ядру требуется связаться с собеседником, а соответствующая политика требует наличия соглашения о безопасности, но соглашение таковое отсутствует, ядро отправляет на зарегистрировавшиеся для данного типа соглашения сокеты управления ключами сообщение SADB_ACQUIRE, в расширениях которого содержатся предлагаемые ядром алгоритмы и длины ключей. Предложение может представлять собой комбинацию поддерживаемых системой средств безопасности и политики, ограничивающей набор средств для конкретного собеседника. Алгоритмы, длины ключей и времена жизни объединяются в список в порядке предпочтительности использования. Когда демон-ключник получает сообщение SADB_ACQUIRE, он выполняет действия, необходимые для выбора ключа, удовлетворяющего одной из предложенных ядром комбинаций, и устанавливает этот ключ в ядро. Для выбора SPI из нужного диапазона демон отправляет ядру сообщение SADB_GETSPI. В ответ на это сообщение ядро создает соглашение о безопасности в состоянии SADB_SASTATE_LARVAL. Затем демон согласовывает параметры безопасности с удаленным собеседником, используя предоставленный ядром SPI, после чего отправляет ядру сообщение SADB_UPDATE для завершения создания соглашения и перевода его в рабочее состояние (SADB_SASTATE_MATURE). Динамически создаваемые соглашения обычно снабжаются гибким и жестким ограничениями на время жизни. Когда истекает один из этих сроков, ядро отправляет сообщение SADB_EXPIRE, в котором указывается, какое именно достигнуто ограничение. По достижении гибкого ограничения соглашение переходит в состояние SADB_SASTATE_DYING, в котором оно еще может использоваться, однако процессу следует получить новое соглашение. Если же достигнуто жесткое ограничение, соглашение переходит в состояние SADB_SASTATE_DEAD, в котором оно больше не может использоваться для обеспечения безопасности и должно быть удалено из базы данных.