Entonces tengo este servidor:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind('/tmp/sock.sock')
sock.listen(1)
while True:
    conn, ca = sock.accept()
    print(conn.recv(1024))

Y esta cliente:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect('/tmp/sock.sock')
sock.send('Hello, World')

El envío y la recepción reales es un poco más complejo, pero funciona perfectamente, siempre que tanto el servidor como el cliente se ejecuten desde la raíz. También funciona cuando el cliente se ejecuta como root y el servidor lo ejecuta un usuario normal. Pero cuando intento ejecutar el servidor con root y cliente por usuario normal, obtengo esto:

$ python3 client.py
connecting to /tmp/sock.sock
[Errno 13] Permission denied

¿Como puedo resolver esto? El servidor debe ejecutarse como root y el cliente como un usuario sin privilegios.

He entendido tanto que tiene que ver con los permisos de archivo para el archivo socket, pero no puedo ver cómo debo solucionarlo. No pude ver ninguna opción para pasar al constructor de socket que solucionaría esto.

2
klutt 8 oct. 2019 a las 10:34

3 respuestas

La mejor respuesta

Cambie el modo de archivo para permitir que cualquiera pueda acceder a él. Agregue estas líneas en su servidor

import os
os.chmod("/tmp/sock.sock", 0o777)
1
klutt 8 oct. 2019 a las 07:54

Gracias a P.Dmitry por señalarme en la dirección correcta. Terminé con esta modificación de la misma idea, que se adapta un poco mejor a mis necesidades:

import pwd
import grp
...
# Change the owner of the socket
os.chown('/tmp/sock.sock', 
         pwd.getpwnam('user').pw_uid, 
         grp.getgrnam('group').gr_gid)
# Restrict access to only this user (and root of course)
os.chmod('/tmp/sock.sock', 0o600)

Nota:

0o es el prefijo octal en Python3. En Python2 es solo 0 como en C.

0
klutt 8 oct. 2019 a las 08:28

Esta no es una buena idea, si tiene todo su servidor diseñado para ejecutarse como root, hay un error de diseño en alguna parte.

Lo que sucede aquí es que el usuario raíz crea el archivo /tmp/sock.sock con sus propios privilegios, y ese archivo es accesible solo para el usuario que lo creó.

El problema es que incluso si el método bind en Linux (¡pero no en Mac OS!) Ha sido parcheado para no seguir enlaces simbólicos, todavía está creando un problema de seguridad. Suponga que el archivo no está allí y el servidor no se está ejecutando. Un usuario normal puede crear un enlace simbólico de /tmp/sock.sock a /etc/passwd y cuando el servidor intenta iniciar, intentará enlazar, establecer los permisos y luego fallar debido al enlace simbólico, pero los permisos serán conjunto. Entonces tendrá su archivo passwd configurado como grabable.

Incluso si no hubo problemas de permisos, suponga que alguien envía una gran cantidad de datos y llena el disco haciendo que el servidor se bloquee. Si ejecuta el servidor con un usuario normal, puede establecer una cuota máxima, pero no desea establecerla en la raíz.

Mi sugerencia es: crear un nuevo usuario cuya única tarea sea ejecutar el servidor y el cliente y tenga el conjunto mínimo de permisos requerido.

0
ChatterOne 8 oct. 2019 a las 08:35
58281963