Bem diz o ditado que a necessidade é a mãe da invenção do conhecimento … Hoje, precisei fazer um programinha que, fornecido um usuário e senha, este retornava “OK.” se a senha estivesse correta ou “ERR.” caso ela estivesse errada (semelhante ao ncsa_auth, porém autenticando no shadow ao invés de um arquivo próprio). Para isso usei a funcão crypt(3). Como ela é um pouco “estranha” para usar e não contém nenhum exemplo decente, vou demonstrar rápidamente a sua utilização
Primeiro você precisa obter a senha criptografada. Ex.:
char *get_passwd(char *username) {
struct spwd *userdata = NULL;if (!username) {
return NULL;
}/*
Obtém a estrutura contendo os dados do shadow e, uma vez
que obtenha sucesso na execução retorna a senha criptografada
*/
userdata = getspnam(username);
if (!userdata) {
return NULL;
}return userdata->sp_pwdp;
}
Depois disso é preciso obter o “salt”. O salt é uma string utilizada para perturbar o algoritmo gerador da senha. Dessa maneira podemos casar a senha fornecida + o salt da senha atual, por fim gerando a senha existente no sistema. No exemplo abaixo, salt_size é o tamanho da string de salt. Nos testes executados aqui, eu obtive sucesso usando o valor 11.
char *get_salt(char *full_passwd, int salt_size) {
char *salt = (char *)malloc(salt_size);if (!full_passwd) {
return NULL;
}/* A partir da senha cryptografada, obtém o salt (o salt é
utilizado para “perturbar” o algoritmo gerador da senha).
*/
strncpy(salt, full_passwd, salt_size);
return salt;
}
Por fim, basta gerar a senha criptografada e casa-la com a senha existente. Eesta função de exemplo recebe a senha do usuário sem estar criptografa (usr_passwd), a senha do usuário criptografada (sys_passwd) e o salt (salt).
int match(char *usr_passwd, char *sys_passwd, char *salt) {
char *usr_crypt_passwd = NULL;if (!usr_passwd || !sys_passwd) {
return EXIT_FAILURE;
}/*
Criptografa a senha fornecida, e compara ela com a senha
existente no sistema.
*/
usr_crypt_passwd = crypt(usr_passwd, salt);
if (!usr_crypt_passwd) {
return EXIT_FAILURE;
}if (strcmp(sys_passwd, usr_crypt_passwd) == 0) {
return EXIT_SUCCESS;
}return EXIT_FAILURE;
}
Por fim é isso. Agora basta testar o valor de retorno da função match e pronto 🙂