KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Уильям Стивенс, "UNIX: разработка сетевых приложений" бесплатно, без регистрации.
Перейти на страницу:

 u_int16_t sadb_address_reserved;  /* зарезервирован для послед. использования */

};

/* далее следует структура sockaddr соответствующего семейства */

Завершают список обязательных расширений сообщения SADB_ADD ключи аутентификации и шифрования — расширения SADB_EXT_KEY_AUTH и SADB_EXT_KEY_ENCRYPT, описываемые структурой sadb_key (листинг 19.5). Поле sadb_key_exttype определяет тип ключа (ключ аутентификации или шифрования), поле sadb_key_bits задает длину ключа в битах, а сам ключ следует за структурой sadb_key.

Листинг 19.5. Структура sadb_key

struct sadb_key {

 u_int16_t sadb_key_len;      /* длина расширения с ключом / 8 */

 u_int16_t sadb_key_exttype;  /* SADB_EXT_KEY_{AUTH,ENCRYPT} */

 u_int16_t sadb_key_bits;     /* # битов в ключе */

 u_int16_t sadb_key_reserved; /* зарезервировано для расширения */

};

/* далее следуют данные о самом ключе */

Программа, добавляющая статическую запись в базу данных безопасности, представлена в листинге 19.6.

Листинг 19.6. Программа, использующая команду SADB_ADD

//key/add с

 33 void

 34 sadb_add(struct sockaddr *src, struct sockaddr *dst, int type, int alg,

 35  int spi, int keybits, unsigned char *keydata)

 36  {

 37  int s;

 38  char buf[4096], *p; /* XXX */

 39  struct sadb_msg *msg;

 40  struct sadb_sa *saext;

 41  struct sadb_address *addrext;

 42  struct sadb_key *keyext;

 43  int len;

 44  int mypid;


 45  s = Socket(PF_KEY, SOCK_RAW, PF_KEY_V2);


 46  mypid = getpid();


 47  /* Формирование и запись запроса SADB_ADD */

 48  bzero(&buf, sizeof(buf));

 49  p = buf;

 50  msg = (struct sadb_msg*)p;

 51  msg->sadb_msg_version = PF_KEY_V2;

 52  msg->sadb_msg_type = SADB_ADD;

 53  msg->sadb_msg_satype = type;

 54  msg->sadb_msg_pid = getpid();

 55  len = sizeof(*msg);

 56  p += sizeof(*msg);


 57  saext = (struct sadb_sa*)p;

 58  saext->sadb_sa_len = sizeof(*saext) / 8;

 59  saext->sadb_sa_exttype = SADB_EXT_SA;

 60  saext->sadb_sa_spi = htonl(spi);

 61  saext->sadb_sa_replay = 0; /* статические ключи не защищают от повтора */

 62  saext->sadb_sa_state = SADB_SASTATE_MATURE;

 63  saext->sadb_sa_auth = alg;

 64  saext->sadb_sa_encrypt = SADB_EALG_NONE;

 65  saext->sadb_sa_flags = 0;

 66  len += saext->sadb_sa_len * 8;

 67  p += saext->sadb_sa_len * 8;


 68  addrext = (struct sadb_address*)p;

 69  addrext->sadb_address_len = (sizeof(*addrext) + salen(src) + 7) / 8;

 70  addrext->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;

 71  addrext->sadb_address_proto = 0; /* any protocol */

 72  addrext->sadb_address_prefixlen = prefix_all(src);

 73  addrext->sadb_address_reserved = 0;

 74  memcpy(addrext + 1, src, salen(src));

 75  len += addrext->sadb_address_len * 8,

 76  p += addrext->sadb_address_len * 8;


 77  addrext = (struct sadb_address*)p;

 78  addrext->sadb_address_len = (sizeof(*addrext) + salen(dst) + 7) / 8;

 79  addrext->sadb_address_exttype = SADB_EXT_ADDRESS_DST;

 80  addrext->sadb_address_proto = 0; /* any protocol */

 81  addrext->sadb_address_prefixlen = prefix_all(dst);

 82  addrext->sadb_address_reserved = 0;

 83  memcpy(addrext + 1, dst, salen(dst));

 84  len += addrext->sadb_address_len * 8;

 85  p += addrext->sadb_address_len * 8;


 86  keyext = (struct sadb_key*)p;

 87  /* обеспечивает выравнивание */

 88  keyext->sadb_key_len = (sizeof(*keyext) + (keybits / 8) + 7) / 8;

 89  keyext->sadb_key_exttype = SADB_EXT_KEY_AUTH;

 90  keyext->sadb_key_bits = keybits;

 91  keyext->sadb_key_reserved = 0;

 92  memcpy(keyext + 1, keydata, keybits / 8);

 93  len += keyext->sadb_key_len * 8;

 94  p += keyext->sadb_key_len * 8;


 95  msg->sadb_msg_len = len / 8;

 96  printf("Sending add message:n");

 97  print_sadb_msg(buf, len);

 98  Write(s, buf, len);


 99  printf("nReply returned:n");

100  /* считывание и вывод ответа SADB_ADD, игнорируя любые другие */

101  for (;;) {

102   int msglen;

103   struct sadb_msg *msgp;


104   msglen = Read(s, &buf, sizeof(buf));

105   msgp = (struct sadb_msg*)&buf;

106   if (msgp->sadb_msg_pid == mypid &&

107    msgp->sadb_msg_type == SADB_ADD) {

108    print_sadb_msg(msgp, msglen);

109    break;

110   }

111  }

112  close(s);

113 }

Открытие сокета PF_KEY и сохранение PID

55-56 Как и в предыдущей программе, мы открываем сокет PF_KEY и сохраняем идентификатор нашего процесса для последующего его использования.

Формирование общего заголовка сообщений

47-56 Мы формируем заголовок сообщения SADB_ADD. Поле sadb_msg_len устанавливается непосредственно перед отправкой сообщения, поскольку оно должно соответствовать истинной его длине. В переменной len хранится текущая длина сообщения, а указатель р всегда указывает на первый неиспользуемый байт буфера.

Добавление расширения SA

57-67 Мы добавляем обязательное расширение SA (см. листинг 19.3). Поле sadb_sa_spi должно иметь сетевой порядок байтов, поэтому нам приходится применять функцию htonl к значению в порядке байтов узла. Мы отключаем защиту от повторов и устанавливаем состояние SA равным SADB_SASTATE_MATURE (см. табл. 19.4). Алгоритм аутентификации выбирается в соответствии с аргументом командной строки, а шифрование отключается при помощи константы SADB_EALG_NONE.

Добавление адреса отправителя

68-76 К сообщению добавляется расширение SADB_EXT_ADDRESS_SRC, содержащее адрес отправителя для соглашения о безопасности.

Значение протокола устанавливается равным нулю, что подразумевает действительность соглашения для всех протоколов. Длина префикса устанавливается равной соответствующей длине версии IP (то есть 32 разряда для IPv4 и 128 разрядов для IPv6). При расчете значения поля длины мы добавляем к реальному значению число 7 перед делением на 8, что гарантирует выравнивание по 64-разрядной границе, обязательное для всех расширений, передаваемых через сокеты PF_KEY. Структура sockaddr копируется в буфер после заголовка расширения.

Добавление адреса получателя

77-85 Адрес получателя добавляется в сообщение SADB_EXT_ADDRESS_DST. Процедура в точности совпадает с описанной выше.

Добавление ключа

86-94 К сообщению добавляется расширение SADB_EXT_KEY_AUTH, содержащее ключ авторизации. Расчет поля длины производится точно так же, как и для обоих адресов. Ключ переменной длины требует соответствующего количества дополняющих нулей. Мы устанавливаем значение количества битов и копируем ключ вслед за заголовком расширения.

Запись сообщения в сокет

95-98 Мы выводим сообщение на экран вызовом функции print_sadb_msg, после чего записываем его в сокет.

Считывание ответа

99-111 Мы считываем все сообщения из сокета до тех пор, пока не будет получено сообщение, адресованное нашему процессу (проверяется по PID) и имеющее тип SADB_ADD. Это сообщение выводится на экран функций print_sadb_msg, после чего программа завершает работу.

Пример

Мы запускаем программу, требуя от нее установки соглашения о безопасности, касающегося трафика между узлами 127.0.0.1 и 127.0.0.1 (то есть локального трафика):

macosx % add 127.0.0.1 127.0.0.1 HMAC-SHA-1-96 160

 0123456789abcdef0123456789abcdef01234567

Sending add message:

SADB Message Add, errno 0, satype IPsec AH, seq 0, pid 6246

SA: SPI=39030 Replay Window=0 State=Mature

Authentication Algorithm: HMAC-SHA-1

Encryption Algorithm: None

Source address: 127.0.0.1/32

Dest address: 127.0.0.1/32

Authentication key. 160 bits: 0x0123456789abcdef0123456789abcdef01234567

Reply returned:

SADB Message Add, errno 0, satype IPsec AH, seq 0, pid 6246

SA: SPI=39030 Replay Window=0 State=Mature

Authentication Algorithm: HMAC-SHA-1

Encryption Algorithm: None

Source address: 127.0.0.1/32

Dest address: 127.0.0.1/32

Обратите внимание, что в ответе системы отсутствует ключ. Дело в том; что ответ направляется на все сокеты PF_KEY, которые, однако, могут принадлежать к разным доменам, а данные о ключах не должны передаваться между доменами. После добавления записи в базу данных мы даем команду ping 127.0.0.1, чтобы проверить, задействуется ли соглашение о безопасности, после чего запрашиваем дамп базы данных и смотрим, что в ней изменилось.

macosx % dump

Sending dump message:

SADB Message Dump, errno 0, satype Unspecified, seq 0, pid 6283

Messages returned:

SADB Message Dump, errno 0, satype IPsec AH, seq 0, pid 6283

SA: SPI=39030 Replay Window=0 State=Mature

Authentication Algorithm: HMAC-SHA-1

Encryption Algorithm: None

[unknown extension 19]

Current lifetime:

36 allocations. 0 bytes

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*