web-dev-qa-db-fra.com

Comment créer un socket de domaine Unix avec des autorisations spécifiques en C?

J'ai un code simple, comme:

sockaddr_un address;
address.Sun_family = AF_UNIX;
strcpy(address.Sun_path, path);
unlink(path);

int fd = socket(AF_UNIX, SOCK_STREAM, 0);
bind(fd, (sockaddr*)(&address), sizeof(address));
listen(fd, 100);

Je veux atomiquement créer le fichier de socket de domaine Unix avec des autorisations spécifiques, par exemple: 0777. Le manuel ne dit rien sur les permissions des fichiers socket en ce qui concerne umask ou autre. Même si le umask affecte le fichier de socket, ce n'est pas une manière atomique - dans un programme multi-thread.

J'espère qu'il existe un moyen d'atteindre mon objectif sans utiliser la synchronisation des appels umask().

29
abyss.7

Une autre solution consiste à créer un répertoire avec les autorisations souhaitées, puis à créer le socket à l'intérieur (exemple de code sans aucun égard pour la vérification des erreurs et les débordements de tampon):

// Create a directory with the proper permissions
mkdir(path, 0700);
// Append the name of the socket
strcat(path, "/socket_name");

// Create the socket normally
sockaddr_un address;
address.Sun_family = AF_UNIX;
strcpy(address.Sun_path, path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
bind(fd, (sockaddr*)(&address), sizeof(address));
listen(fd, 100);
21
Elias Mårtenson

J'ai eu la meilleure chance d'utiliser chmod () (PAS fchmod) en utilisant le nom de fichier pour la socket de domaine unix après avoir appelé socket (), bind (), mais avant d'appeler listen ().

  int return_value;
  const char *sock_path;
  struct sockaddr_un local;

  sock_path = "/tmp/mysocket";

  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
  if (sockfd == -1)
  {
    perror("socket");
    exit(-1);
  }

  local.Sun_family = AF_UNIX; 
  strcpy(local.Sun_path, sock_path);
  unlink(local.Sun_path);
  len = strlen(local.Sun_path) + sizeof(local.Sun_family);
  bind(sockfd, (struct sockaddr *)&local, len);

  chmod(sock_path, 0777);

  retval = listen(sockfd, BACKLOG);
  if (retval == -1)
  {
    perror("listen");
    exit(-1);
  }

. . . . .

12
Don Carr

Forker, utiliser umask et renvoyer le fd est la seule façon portable à laquelle je peux penser. Avoir un répertoire pour le socket est mieux dans tous les cas, par exemple, personne ne peut supprimer le socket si le répertoire n'a pas les autorisations appropriées, et la création de répertoires peut se faire de manière atomique.

Le plus gros problème est que le recours aux autorisations n'est pas portable - de nombreuses piles de sockets dérivées de BSD ignorent simplement les autorisations de placer des répertoires et/ou le socket lui-même.

Sur les systèmes GNU/Linux, vous pouvez le faire en appelant fchmod sur le socket fd après socket () et avant bind ()

5
Anonymous