¿Cómo permite macOS a los usuarios estándar hacer ping?

2

Aquí tengo una pregunta bastante profunda que espero que alguien pueda responder. En macOS, los usuarios regulares pueden hacer ping así como root. Normalmente, se requiere acceso a la raíz para abrir el socket en bruto necesario para ejecutar ping. He notado en Linux que esto generalmente se logra agregando atributos extendidos al archivo de programa de ping para permitir el acceso de nivel raíz para abrir sockets sin formato (en el pasado, esto se hacía simplemente estableciendo el bit setuid en el programa de ping, permitiéndole hacer cualquier cosa en su programación como root).

He mirado / sbin / ping en macOS (High Sierra, específicamente), y no se han establecido tales atributos, y ninguno de ellos es setuid. Entonces, ¿qué está haciendo macOS para permitir que los usuarios estándar (no root) hagan ping? ¿Están enviando paquetes ICMP sobre TCP o UDP? Si es así (o si hay otro mecanismo que me falta por completo), ¿puede indicarme algunos documentos? Cualquier ayuda sería apreciada.

    
pregunta le_jawa 19.01.2018 - 20:33

1 respuesta

4

Echemos un vistazo al código fuente para la implementación ping de Apple. En particular, vemos esto:

if (getuid())
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
else
    s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
sockerrno = errno;

getuid devuelve 0 si es root. Así que este código dice "abre el socket en DGRAM (modo de datagrama) si somos no root. Si somos root, abre como raw".

Por lo tanto, un socket en bruto solo se usa cuando eres root. Un paquete de ping IMCP es un paquete DGRAM estándar y no requiere sockets sin procesar.

Sin embargo, hay algunos indicadores que pueden pasarse a ping que requieren una raíz, y para ellos obtendrá una "Operación no permitida". Por ejemplo:

>ping -f
ping: -f flag: Operation not permitted

Cuando se ejecuta como root, no consigo la operación no permitida. Por lo tanto, la implementación de Apple le permitirá realizar operaciones de ping estándar que no requieren root, pero requieren que se ejecute como root para ciertos indicadores y operaciones.

Dependiendo de si eres root, puede establecer algunas opciones de socket adicionales:

if (uid == 0)
    (void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold,
        sizeof(hold));
    
respondido por el vcsjones 19.01.2018 - 21:04

Lea otras preguntas en las etiquetas