Lab de Processos¶
Em um Sistema Operacional, por razões de segurança, as senhas dos usuários não são armazenadas em texto simples e sim o seu hash. Quando um usuário tenta fazer login a senha digitada é criptografada (gerando um hash) para ser comparado com o hash armazenado. Dessa forma, não há necessidade de armazenar sua senha real.
Caso o usuário tenha utilizado letras maiúsculas e minúsculas, caracteres especiais e numeros é praticamente impossível reconstruir a senha a partir do hash. No entanto, se a senha for simples, e estivermos dispostos a gastar algum tempo de CPU, é possível tentar todas as combinações de caracteres possíveis em uma senha (ataque de força bruta) até gerar um hash igual ao hash armazenado.
Nesse lab você deve implementar o programa recupera_senha.c
que recupera a(s) senha(s) perdida(s) de usuário(s) a partir de uma parte conhecida da senha. Para tanto, utilizaremos a ferramenta criptInsper
que é um executável de linha de comando, que tem como entrada um hash e a parte de uma senha, em seguida, a ferramenta tenta recuperar a senha original. Abaixo um exemplo de chamada do criptInsper
:
$./criptInsper xxC4UjY9eNri6 hello...
"xxsczBXm6z4zA"
, associado a uma senha, e a parte conhecida da senha "hello"
seguida de pontos .
, representando os caracteres desconhecidos. O programa criptInsper
tentar gerar um hash igual ao informado, a partir de várias combinações de caracteres, começando com a parte conhecida. Para a entrada acima o criptInsper
tem a seguinte saída no terminal.
./criptInsper: senha [helloaac] recuperada.
criptInsper
salva a senha recuperada no arquivo com do hash informado xxC4UjY9eNri6.txt
e retorna 0
para o terminal. O executável pode ter outros valores como retorno em sua execução:
-
Quando a quantidade de parâmetros está incorreta ou errada, o executável retorna -2;
-
Quando não é possível quebrar a senha a partir do hash informado, o executável retorna -1; e
-
Quando consegue recuperar a senha, o executável retorna 0.
Ultimamente o executável criptInsper
está um pouco instável, com um comportamento estranho, culpa talvez do último programador que deu manutenção no código. Essa manutenção fez com que, as vezes, a ferramenta demore um tempo excessivo para recuperar a senha ou seja finalizado por conta de acesso indevido a memória (segmentation fault).
O programador que fez a manutenção disse que quando o criptInsper
falhar por acesso à memória, o usuário pode executar novamente a ferramenta informando o número da tentiva, incrementando esse número a cada nova tentativa, até que a recuperação da senha seja bem sucedida, e acreditem, essa gambiarra funciona. Veja um exemplo desse tipo de erro:
$./criptInsper xxq5aBqiB66j2 xz....
Falha de segmentação (imagem do núcleo gravada)
1
no último parâmetro da chamada do criptInsper
, o executável consegue recurar a senha:
$./criptInsper xxq5aBqiB66j2 xz.... 1
./criptInsper: senha [xzzzzy] recuperada.
Restrições¶
Esta atividade serve como avaliação dos conceitos vistos na disciplina. Portanto, algumas restrições serão aplicadas ao código de vocês:
- todo trabalho com arquivos deverá ser feito usando as APIs POSIX vistas em aula. Não é permitido o uso de funções da
Standard I/O
para manipulação de arquivos, como por exemplofopen()
,fdopen()
,fread()
efclose()
. - se você usar algum trecho de código da documentação (ou de outra fonte), coloque uma atribuição em um comentário no código.
- Fica proibido o uso de ferramentas de geração de código automático por IA, como por exemplo o ChatGPT.
O não atendimento dessas restrições resultarão em atribuição da nota zero para esse lab.
Entrega¶
Você deverá colocar o programa fonte recupera_senha.c
na pasta lab/02-lab-processos
em seu repositório de atividades (github), na branch principal, e fazer upload (push) do arquivo fonte no seu repositório, não precisa soltar tag. Além disso, grave um vídeo mostrando a tela do funcionamento do seu programa apresentando cada uma das fases desenvolvidas, e por fim, preencha o arquivo README.md
informando até qual fase você conseguiu chegar e o link do vídeo do funcionamento da sua entrega. Lembre-se de se atentar ao prazo de entrega definido aqui!.
Avaliação¶
O programa recupera_senha.c
será avaliado de forma manual usando uma rubrica que descreve as funcionalidades implementadas. Quanto maior o número de funcionalidades maior será a nota.
Fase 0¶
- O programa
recupera_senha.c
não compila - Não preencheu o arquivo
README.md
- O programa não implementa algum dos requisitos da rubrica da fase 1.
NOTA desta fase: 0.0
Fase 1¶
- Preencheu o arquivo
README.md
- O programa
recupera_senha.c
compila com warnings. -
O programa roda na linha de comando como abaixo:
$./recupera_senha fabio xxC4UjY9eNri6 hello...
-
Para recuperar a senha do usuário
fabio
o seu programarecupera_senha.c
deve fazer uma chamada do excutávelcriptInsper
utilizando a funçãoexec
conforme visto em aula, você não pode, por exemplo, usar a chamada da função system. -
Caso o
criptInsper
tenha sucesso, ou seja, retorne 0 ao seu programa, você deverá mostrar, obrigatoriamente, a mensagem abaixo:Se a recuperacao falhar o seu programa deverá mostrar a mensagem:senha do usuario {fabio} recuperada {helloaac}
- Para inibir os prints gerados pelo executávelfalha na recuperacao da senha do usuario {fabio}
criptInsper
, você pode utilizar o trecho de código abaixo antes da chamada da funçãoexec
.//descarte padrão linux, dados enviados para o arquivo são completamente descartados int fd_null = open("/dev/null", O_WRONLY); //Redireciona a saida padrao (stdout) para /dev/null dup2(fd_null, STDOUT_FILENO); close(fd_null); execvp(prog, args);
NOTA desta fase: 2.5
Fase 2¶
- O programa
recupera_senha.c
compila sem warnings. - Não entregou o video explicando o funcionamento do programa.
- O programa
recupera_senha.c
recebe uma flag-f
seguida pelo nome de um arquivo de senhas. Seu programa deverá ler o arquivo e recuperar as senhas dos usuários armazenados dentro do arquivo. -
Nessa fase cada linha do arquivo deve ser tratado como um processo independente, e a recuperação das senhas pode ser realizada de forma sequencial, assim seu programa pode ler uma linha do arquivo de entrada, chamar o executável
criptInsper
, receber a resposta e imprimir no terminal. Cada linha do arquivo conterá:- Nome de usuário (1 a 8 caracteres)
- Hash de senha (13 caracteres)
- Parte conhecida da senha (mais pontos que representam caracteres desconhecidos) (1 a 8 caracteres, contém de 0 a 8 letras minúsculas seguidas de 0 a 8 pontos)
-
Esses três campos são separados por um único espaço. Não se preocupe com nomes de usuário duplicados ou prefixos duplicados. Todas as informações que fornecemos estão garantidas neste formato. Exemplo de arquivo de entrada (
senhas1.in
):Abaixo um exemplo da chamada do seu programa com o flatfabio xxC4UjY9eNri6 hello... ana xxq5aBqiB66j2 xz.... diego xxhx0AsVpMTMU sysx.... jose xxGGPN89YLcGY cham....
-f
para o arquivosenhas1.in
com a respectiva saída.
$./recupera_senha -f senhas1.in Processo 1: recuperando senha de {fabio} Processo 1: senha do usuario {fabio} recuperada {helloaac} Processo 2: recuperando senha de {ana} Processo 2: falha na recuperacao da senha do usuario {ana} Processo 3: recuperando senha de {diego} Processo 3: senha do usuario {diego} recuperada {sysxpert} Processo 4: recuperando senha de {jose} Processo 4: falha na recuperacao da senha do usuario {jose} 2 senhas recuperadas, 2 falhas.
NOTA desta fase: 5.0
Fase 3¶
- Entregou video explicando e mostrando a execução do programa.
- Programa
recupera_senha.c
roda sem erros no valgrind. - Nessa fase cada linha do arquivo deve ser tratado como um processo independente, e a recuperação das senhas deve ser realizada em paralelo. Assim no início da execução o seu programa deverá carregar todos os processos do executável
criptInsper
, e somente depois aguardar a finalização dos processos criados. -
Se o executável
criptInsper
finalizar por segmentation fault, o seu programa deve realizar pelo menos mais duas tentativas de chamadas do executávelcriptInper
, informando o número da tentativa na chamada do executável. A cada nova tentativa deve ser informado se conseguiu ou não recuperar a senha. -
Abaixo um exemplo da chamada do seu programa para o arquivo
senhas1.in
com uma possível saída.
$./recupera_senha -f senhas1.in Processo 1: recuperando senha de {fabio} Processo 2: recuperando senha de {ana} Processo 3: recuperando senha de {diego} Processo 4: recuperando senha de {jose} Processo 1: senha do usuario {fabio} recuperada {helloaac} Processo 2: falha na recuperacao da senha do usuario {ana} Processo 3: senha do usuario {diego} recuperada {sysxpert} Processo 4: falha na recuperacao da senha do usuario {jose} Processo 5: recuperando senha de {ana} Processo 5: senha do usuario {ana} recuperada {xzzzzy} 3 senhas recuperadas, 1 falhas.
NOTA desta fase: 7.5
Fase 4¶
-
O programa
recupera_senha.c
abre atéN
processos do executávelcriptInsper
em paralelo para recuperar as senhas no arquivo de entrada. Considere que nos testes sempre utilizaremos um arquivo com número de linhas maior queN
. Esse valor é passado pela linha de comando via flag-N
, conforme abaixo:./recurera_senha -f senhas1.in -N 2
Se nada for passado assuma
N=4
, por exemplo:./recurera_senha -f senhas1.in -N
-
E por fim, ao apertar
Ctrl+C
no terminal, o programarecupera_senha.c
finaliza os processos docriptInsper
que ainda estão executando e apaga todos os arquivos de senhas que foram geradas.
NOTA desta fase: 10.0
IMPORTANTE: Considere as fases como cumulativas, ou seja, cada versão deve manter as funcionalidades da fase anterior e acrescentar novas. Por exemplo, a versão da Fase 2, além de ler o arquivo com várias senhas, também deve ser possível recuperar uma senha passada por linha de comando (sem -f arquivo
).
Caso você não implemente alguma funcionalidade de uma determinada fase a nota atribuída será a da fase anterior.