// ids.c: imprime los IDs real y efectivo, intenta abrir un archivo,
// suelta los privilegios y vuelve a intentar.
// Se instala como setuid root para ver la diferencia entre uid y euid:
//   chown root ids && chmod u+s ids
//   uso: ./ids archivo
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void show(const char *when, const char *path) {
    printf("%-14s uid=%d euid=%d  ", when, (int)getuid(), (int)geteuid());
    int fd = open(path, O_RDONLY);
    if (fd < 0) {
        printf("open(%s): no se puede\n", path);
        return;
    }
    printf("open(%s): ok\n", path);
    close(fd);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "uso: %s archivo\n", argv[0]);
        exit(1);
    }
    show("al empezar:", argv[1]);

    // Mínimo privilegio: si ya no se necesita, se suelta para siempre.
    // setuid(getuid()) siendo euid 0 cambia real, efectivo y guardado.
    if (setuid(getuid()) < 0) {
        perror("setuid");
        exit(1);
    }
    show("tras soltar:", argv[1]);

    // Ya no hay vuelta atrás: volver a euid 0 debe fallar.
    if (geteuid() != 0 && seteuid(0) < 0)
        printf("%-14s seteuid(0) falla: los privilegios se perdieron\n", "volver:");
    return 0;
}
