Литмир - Электронная Библиотека
Содержание  
A
A

struct fcred {

 uid_t fc_ruid;            /* действующий идентификатор пользователя */

 gid_t fc_rgid;            /* действующий групповой идентификатор */

 char  fc_login[MAXLOGNAME]; /* имя setlogin() */

 uid_t fc_uid;             /* идентификатор пользователя */

 short fc_ngroups;         /* количество групп */

 gid_t fc_groups[NGROUPS]; /* дополнительные групповые идентификаторы */

};

#define fc_gid fc_groups[0] /* групповой идентификатор */

Обычно

MAXLONGNAME
и
NGROUPS
имеют значение 16. Значение
fc_ngroups
равно как минимум 1, а первым элементом массива является идентификатор группы.

Эта информация всегда доступна через доменный сокет Unix, хотя отправителю часто приходится принимать дополнительные меры для обеспечения ее отправки вместе с данными, и получателю также приходится выполнять некоторые действия (например, устанавливать параметры сокета). В системе FreeBSD получатель может обойтись вызовом

recvmsg
с достаточно большим буфером для вспомогательных данных, чтобы туда поместились идентифицирующие данные (листинг 15.12). Однако отправитель обязан включить структуру
cmsgcred
при отправке данных посредством
sendmsg
. Хотя включение структуры осуществляется отправителем, заполняется она ядром. Благодаря этому передача идентифицирующих данных через доменный сокет Unix является надежным способом проверки клиента.

Пример

В качестве примера передачи идентифицирующих данных мы изменим наш потоковый доменный сервер Unix, так чтобы он запрашивал идентифицирующие данные клиента. В листинге 15.12 показана новая функция,

read_cred
, аналогичная функции
read
, но возвращающая также структуру
fcred
, содержащую идентифицирующие данные отправителя.

Листинг 15.12. Функция read_cred: чтение и возвращение идентифицирующих данных отправителя

//unixdomain/readcred.c

 1 #include "unp.h"

 2 #define CONTROL_LEN (sizeof(struct cmsghdr) + sizeof(struct cmsgcred))

 3 ssize_t

 4 read_cred(int fd, void *ptr, size_t nbytes, struct cmsgcred *cmsgcredptr)

 5 {

 6  struct msghdr msg;

 7  struct iovec iov[1];

 8  char control[CONTROL_LEN];

 9  int n;

10  msg.msg_name = NULL;

11  msg.msg_namelen = 0;

12  iov[0].iov_base = ptr;

13  iov[0].iov_len = nbytes;

14  msg.msg_iov = iov;

15  msg.msg_iovlen = 1;

16  msg.msg_control = control;

17  msg.msg_controllen = sizeof(control);

18  msg.msg_flags = 0;

19  if ((n = recvmsg(fd, &msg, 0)) < 0)

20   return(n);

21  cmsgcredptr->cmcred_ngroups = 0; /* идентифицирующие данные не получены */

22  if (cmsgcredptr && msg.msg_controllen > 0) {

23   struct cmsghdr *cmptr = (struct cmsghdr*)control;

24   if (cmptr->cmsg_len < CONTROL_LEN)

25    err_quit("control length = %d", cmptr->cmsg_len);

26   if (cmptr->cmsg_level != SOL_SOCKET)

27    err_quit("control level != SOL_SOCKET");

28   if (cmptr->cmsg_type != SCM_CREDS)

29    err_quit("control type != SCM_CREDS");

30   memcpy(cmsgcredptr, CMSG_DATA(cmptr), sizeof(struct cmsgcred));

31  }

32  return(n);

33 }

3-4
 Первые три аргумента идентичны аргументам функции
read
, а четвертый аргумент — это указатель на структуру
cmsgcred
, которая будет заполнена.

22-31
 Если данные были переданы, проверяются длина, уровень и тип вспомогательных данных, и результирующая структура копируется обратно вызывающему процессу. Если никаких идентифицирующих данных не было передано, мы обнуляем структуру. Поскольку число групп (
cmcred_ngroups
) всегда равно 1 или больше, нулевое значение указывает вызывающему процессу, что ядро не возвратило никаких идентифицирующих данных.

Функция

main
для нашего эхо-сервера (см. листинг 15.3) остается неизменной. В листинге 15.13 показана новая версия функции
str_echo
, полученная путем модификации листинга 5.2. Эта функция вызывается дочерним процессом после того, как родительский процесс принял новое клиентское соединение и вызвал функцию
fork
.

Листинг 15.13. Функция str_echo, запрашивающая идентифицирующие данные клиента

//unixdomain/strecho.c

 1 #include "unp.h"

 2 ssize_t read_cred(int, void*, size_t, struct cmsgcred*);

 3 void

 4 str_echo(int sockfd)

 5 {

 6  ssize_t n;

 7  int i;

 8  char buf[MAXLINE];

 9  struct cmsgcred cred;

10 again:

11  while ((n = read_cred(sockfd, buf, MAXLINE, &cred)) > 0) {

175
{"b":"225366","o":1}