Artigo

Verificando a senha do usuário no sistema

Bem diz o ditado que a necessidade é a mãe da invenção do conhecimento ...

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 rapidamente 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. Esta 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 :)