A veces es necesario escribir un programa en C que lea de /etc/passwd y/o /etc/shadow para hacer login. Para este propósito, UNIX ofrece las funciones getpwnam() y getspnam() que permiten acceder a /etc/passwd y /etc/shadow respectivamente. Cada una de estas funciones retorna una estructura con los datos del usuario a partir de su nombre. Las estructuras son las siguientes:
/* Para /etc/passwd usando getpwnam() */ struct passwd { char *pw_name; /* user name */ char *pw_passwd; /* user password */ uid_t pw_uid; /* user ID */ gid_t pw_gid; /* group ID */ char *pw_gecos; /* real name */ char *pw_dir; /* home directory */ char *pw_shell; /* shell program */ }; /* Para /etc/shadow usando getspnam() */ struct spwd { char *sp_namp; /* Login name */ char *sp_pwdp; /* Encrypted password */ long sp_lstchg; /* Date of last change */ long sp_min; /* Min #days between changes */ long sp_max; /* Max #days between changes */ long sp_warn; /* #days before pwd expires to warn user to change it */ long sp_inact; /* #days after pwd expires until account is disabled */ long sp_expire; /* #days since 1970-01-01 until account is disabled */ unsigned long sp_flag; /* Reserved */ };
A continuación pego unas funciones de ejemplo que permiten hacer login. Con ellas se puede verificar un par user/pass de forma muy simple.
... if(auth_is_valid_user(user, pass)) login_ok = 1; ...
Para las siguientes funciones es necesario incluir las cabeceras pwd.h, shadow.h y crypt.h. Para compilar, es necesaria la librería crypt (ej: gcc test.c -lcrypt).
int auth_check_pass(const char *clear_pass, const char *encrypted_pass) { char *encrypted = crypt(clear_pass, encrypted_pass); if (strcmp(encrypted, encrypted_pass) == 0) return 1; else return 0; } int auth_is_valid_user(const char *user, const char* pass) { struct passwd *pw = getpwnam(user); if(pw==NULL) return 0; // password in /etc/shadow if(strcmp(pw->pw_passwd, "x")==0) { /* Solo root puede leer /etc/shadow por lo que esta parte no funcionara a menos que la ejecute root o el archivo este setuidado */ struct spwd *sp = getspnam(user); if(sp==NULL) return 0; if(auth_check_pass(pass, sp->sp_pwdp)) return 1; } // password in /etc/passwd else { if(auth_check_pass(pass, pw->pw_passwd)) return 1; } return 0; }
No hay comentarios:
Publicar un comentario