2015-07-25 1 views
14

Tout en travaillant sur un projet qui lit à partir de /dev/urandom pour générer des octets aléatoires, il a été suggéré que je vérifie pour s'assurer que /dev/urandom est un périphérique pas simplement un fichier.Comment garantir qu'un fichier spécifié est un périphérique sur BSD/Linux de PHP?

La façon la plus simple semble être quelque chose comme:

/** 
* Is the given file a device? 
* 
* @param string|resource $file 
* @return boolean 
*/ 
function is_device($file) 
{ 
    if (is_resource($file)) { 
     $stat = fstat($file);    
    } elseif (is_readable($file) && !is_link($file)) { 
     $stat = stat($file); 
    } else { 
     return false; 
    } 
    return $stat['rdev'] !== 0; 
} 

Ma question est double:

  1. Est-ce la meilleure façon de vérifier que ce fichier est un périphérique?
  2. Y a-t-il des cas où ce contrôle $stat['rdev'] !== 0 peut échouer?

Important: La solution que je besoin doit être en PHP sans dépendre de toutes les extensions PECL ou le code C personnalisé. Le projet est a pure PHP 5 polyfill of PHP 7's random_bytes() and random_int() functions et est destiné à être installé dans les projets PHP 5 de quelqu'un d'autre par Composer.

+0

[Avez-vous vu ceci?] (Http://insanecoding.blogspot.com/2014/05/a-good-idea-with-bad-usage-devurandom.html) –

+0

Ma position non officielle actuelle est "TOCTOU les problèmes et les attaques d'épuisement des descripteurs de fichiers sont hors de portée.Si votre système de fichiers est pwned, il n'y a rien que votre application web PHP peut faire pour vous sauver. " –

Répondre

4

bien, vous pouvez utiliser filetype().

si vous faites un ll rapide sur urandom, vous verrez:

ll /dev/urandom 
crw-rw-rw- 1 root root 1, 9 Jul 26 17:38 /dev/urandom 

que « c » au beginnng signifie qu'il est un type de fichier « caractère ». vous pouvez consulter tous les différents types de fichiers ici:

https://en.wikipedia.org/wiki/Unix_file_types

cela signifie que si vous exécutez

filetype("/dev/urandom"); 

vous obtiendrez « char » de retour, ce qui signifie caractère filetype. que devrait faire l'affaire.

+1

"vous devriez prendre le temps d'enquêter sur openssl_random_pseudo_bytes()." [Ce n'est pas le premier choix que je recommanderais à tout le monde] (https://github.com/paragonie/random_compat/blob/master/ERRATA.md). Le projet en question est un polyfill pour les fonctions 'random_bytes()' et 'random_int()' de PHP 7. –

2

Mise à jour

Ma solution originale se révèle être juste une réimplantation de filetype($filepath) === 'char', donc filetype() semble être la seule chose dont vous avez besoin.


Sur la base de la réponse de @ Frymaster ...

Je regardai comment la fonction stat() de PHP fonctionne, à la recherche de "char" et trouvé this.

manuel Combiné avec la stat (2) pour les deux Linux et FreeBSD, ainsi qu'un comment on PHP's manual for stat(), je suis venu avec les éléments suivants:

 
function is_device($filepath) 
{ 
     if (! file_exists($filepath) OR (stripos(PHP_OS, 'Linux') === false && stripos(PHP_OS, 'BSD') === false)) 
     { 
       return false; 
     } 

     $mode = stat($filepath)['mode']; 
     return (020000 === ($mode & 0170000)); 
} 

Travaux sur mon système Linux.

Mise à jour (pour répondre à la deuxième question)

Oui, stat($file)['rdev'] !== 0 peut échouer. D'après ce que j'ai trouvé, il peut retourner -1 s'il n'est pas supporté par le système d'exploitation, alors même qu'une valeur positive peut pointer sur un type d'appareil différent.Ses valeurs semblent également être dépendantes du système d'exploitation.

+0

Il semble que libsodum fait quelque chose de très similaire: https://github.com/jedisct1/libsodium/blob/024b74c84995e68c804868b1189d75f571794ad7/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c#L118 –

+2

Et cela s'est avéré être ce filetype () 'fait pour retourner 'char'. :) Juste mis à jour la réponse ... qui est maintenant très semblable à ce que @frymaster a dit. – Narf

+1

J'ai appris des choses de cela! Je vous remercie! – frymaster