2015-07-25 14 views
14

Mentre si lavora su un progetto che legge da /dev/urandom per generare byte casuali, è stato suggerito di controllare che lo /dev/urandom sia un dispositivo non solo un file.Come garantire che un file specificato sia un dispositivo su BSD/Linux da PHP?

Il modo più diretto sembra essere qualcosa di simile:

/** 
* 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; 
} 

La mia domanda è duplice:

  1. È questo il modo migliore per controllare che questo file è un dispositivo?
  2. Ci sono circostanze in cui questo controllo $stat['rdev'] !== 0 può fallire?

Importante: La soluzione che ho bisogno devono essere in PHP senza dipendere da alcun PECL estensioni o personalizzato C codice. Il progetto è a pure PHP 5 polyfill of PHP 7's random_bytes() and random_int() functions ed è concepito per essere installabile in qualsiasi progetto PHP 5 di Composer.

+0

[Hai visto questo?] (Http://insanecoding.blogspot.com/2014/05/a-good-idea-with-bad-usage-devurandom.html) –

+0

La mia attuale posizione non ufficiale è "TOCTOU i problemi e gli attacchi di esaurimento dei descrittori di file sono fuori ambito. Se il tuo filesystem è pwnato, non c'è nulla che la tua app web PHP possa fare per salvarti. " –

risposta

4

bene, è possibile utilizzare filetype().

se si fa un ll veloce su urandom, si vedrà:

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

che 'c' alla beginnng significa che è un tipo di file "carattere". è possibile controllare tutti i diversi tipi di file qui:

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

questo significa che se si esegue

filetype("/dev/urandom"); 

otterrete "char" indietro, che significa carattere tipo di file. che dovrebbe fare il trucco.

+1

"dovresti avere il tempo di investigare su openssl_random_pseudo_bytes()." [Questa non è la prima scelta che consiglierei a chiunque] (https://github.com/paragonie/random_compat/blob/master/ERRATA.md). Il progetto in questione è un polyfill per le funzioni 'random_bytes()' e 'random_int()' di PHP 7. –

2

Aggiornamento

La mia soluzione originale si è rivelata solo una reimplementazione di filetype($filepath) === 'char', così filetype() sembra essere l'unica cosa che serve.


in base alla risposta di @ Frymaster ...

ho guardato come funziona la funzione di PHP stat(), alla ricerca di "char" e hanno trovato this.

In combinazione con la (2) Manuale stat sia per Linux e FreeBSD, così come un comment on PHP's manual for stat(), mi si avvicinò con il seguente:

 
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)); 
} 

lavori sul mio sistema Linux.

Update (per risolvere la seconda questione)

Sì, stat($file)['rdev'] !== 0 può non. Da quello che ho trovato, potrebbe restituire -1 se non supportato dal sistema operativo, mentre anche un valore positivo potrebbe puntare a un diverso tipo di dispositivo.Anche i suoi valori sembrano essere dipendenti dal SO.

+0

Sembra che libsodum faccia qualcosa di molto simile: https://github.com/jedisct1/libsodium/blob/024b74c84995e68c804868b1189d75f571794ad7/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c#L118 –

+2

E questo si è rivelato essere 'filetype () 'fa per restituire 'char'. :) Ho appena aggiornato la risposta ... che ora è molto simile a ciò che ha detto @frymaster. – Narf

+1

ho imparato le cose da questo! grazie! – frymaster

Problemi correlati