c - tengo - Quitar privilegios de raíz
quitar permisos de administrador windows 7 (3)
Esto era lo que podía hacer mejor:
#define _GNU_SOURCE // for secure_getenv()
int drop_root_privileges(void) { // returns 0 on success and -1 on failure
gid_t gid;
uid_t uid;
// no need to "drop" the privileges that you don''t have in the first place!
if (getuid() != 0) {
return 0;
}
// when your program is invoked with sudo, getuid() will return 0 and you
// won''t be able to drop your privileges
if ((uid = getuid()) == 0) {
const char *sudo_uid = secure_getenv("SUDO_UID");
if (sudo_uid == NULL) {
printf("environment variable `SUDO_UID` not found/n");
return -1;
}
errno = 0;
uid = (uid_t) strtoll(sudo_uid, NULL, 10);
if (errno != 0) {
perror("under-/over-flow in converting `SUDO_UID` to integer");
return -1;
}
}
// again, in case your program is invoked using sudo
if ((gid = getgid()) == 0) {
const char *sudo_gid = secure_getenv("SUDO_GID");
if (sudo_gid == NULL) {
printf("environment variable `SUDO_GID` not found/n");
return -1;
}
errno = 0;
gid = (gid_t) strtoll(sudo_gid, NULL, 10);
if (errno != 0) {
perror("under-/over-flow in converting `SUDO_GID` to integer");
return -1;
}
}
if (setgid(gid) != 0) {
perror("setgid");
return -1;
}
if (setuid(uid) != 0) {
perror("setgid");
return -1;
}
// change your directory to somewhere else, just in case if you are in a
// root-owned one (e.g. /root)
if (chdir("/") != 0) {
perror("chdir");
return -1;
}
// check if we successfully dropped the root privileges
if (setuid(0) == 0 || seteuid(0) == 0) {
printf("could not drop root privileges!/n");
return -1;
}
return 0;
}
Tengo un daemon que se inicia como root (por lo que puede vincularse a puertos bajos). Después de la inicialización, me gustaría que deje caer los privilegios de root por razones de seguridad.
¿Puede alguien señalarme una pieza de código correcta conocida en C que hará esto?
He leído las páginas man, he visto varias implementaciones de esto en diferentes aplicaciones, y todas son diferentes, y algunas de ellas son realmente complejas. Este es un código relacionado con la seguridad, y realmente no quiero reinventar los mismos errores que otras personas están cometiendo. Lo que estoy buscando es una mejor práctica, una buena biblioteca portátil conocida que pueda usar sabiendo que lo hará bien. ¿Existe tal cosa?
Como referencia: estoy comenzando como root; Necesito cambiar para ejecutar bajo otro uid y gid; Necesito tener los grupos suplementarios configurados correctamente; No necesito volver a privilegios de root después.
Usted está buscando este artículo:
POS36-C. Observe la orden de revocación correcta mientras renuncia a los privilegios
No estoy seguro de cómo poner mejor información allí sin duplicar el contenido de esa página ...
Para descartar todos los privilegios (usuario y grupo), debe soltar el grupo antes que el usuario. Dado que userid
y groupid
contiene los ID del usuario y el grupo al que desea soltar, y suponiendo que los ID efectivos también son raíz, esto se logra llamando a setuid() y setgid() :
if (getuid() == 0) {
/* process is running as root, drop privileges */
if (setgid(groupid) != 0)
fatal("setgid: Unable to drop group privileges: %s", strerror(errno));
if (setuid(userid) != 0)
fatal("setuid: Unable to drop user privileges: %S", strerror(errno));
}
Si eres paranoico, puedes intentar recuperar tus privilegios de root, lo que debería fallar. Si no falla, rescates:
if (setuid(0) != -1)
fatal("ERROR: Managed to regain root privileges?");
Además, si todavía está paranoico, puede querer seteuid() y setegid() también, pero no debería ser necesario, ya que setuid () y setgid () ya configuran todos los ID si el proceso es propiedad de root.
La lista de grupos suplementarios es un problema, porque no hay una función POSIX para establecer grupos suplementarios (hay getgroups() , pero no setgroups ()). Hay una BSD y Linux setgroups() extensión setgroups() que puede usar, esto le concierne.
También debe chdir("/")
o a cualquier otro directorio, para que el proceso no permanezca en un directorio propiedad de la raíz.
Como su pregunta es sobre Unix en general, este es el enfoque general. Tenga en cuenta que en Linux este ya no es el enfoque preferido. En las versiones actuales de Linux, debe establecer la capacidad CAP_NET_BIND_SERVICE
en el ejecutable y ejecutarlo como un usuario normal. No se necesita acceso a la raíz.