De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Expect

Colaboração: Rodolfo Broco Manin

Data de Publicação: 26 de Novembro de 2001

O Expect (http://expect.nist.gov/) é uma ferramenta para automatizacao de aplicacoes interativas. Ele implementa uma linguagem de scripting similar ao tcl, porem com comandos adicionais para interagir com os aplicativos "no lugar do usuario", i.e.: "ler" prompts e mensagens de certos programas, tomar decisoes baseadas nelas e "digitar" os comandos necessarios.

Encontrei esse utilitario quando estava desenvolvendo uma pagina para troca de senha via web, e precisei de um metodo para fazer a troca nao-interativa da senha do usuario. Passwd, chpass & cia nao funcionam com pipes (eles utilizam a funcao getpass(), que só le a senha da entrada padrao se /dev/tty nao estiver disponivel).

Estou enviando em attach o script que fiz (estah sendo chamado via popen(), de uma pagina experimental com php). Ele le da entrada padrao o login, a senha atual e a nova senha do usuario (nessa ordem), efetua um telnet para a maquina local e executa o passwd. O script troca a senha de contas expiradas tambem (quando o proprio login chama o passwd), e tem a vantagem de ser "suid-free" :). Se alguem quiser usar, é só dar uma revisada, para compatibiliza-lo com as mensagens do passwd, o prompt do shell do sistema, etc.

  #!/usr/local/bin/expect -f
  ##############################################################################
  #                   Script para troca nao-interativa de senhas               #
  #                         Rodolfo Broco Manin - 14/09/2001                   #
  #----------------------------------------------------------------------------#
  # Codigos de erro:                                                           #
  #  - Referentes ao login inicial via telnet:                                 #
  #    110 - Login ou Senha incorreta                                          #
  #    198 - Timeout                                                           #
  #    199 - Finalizacao inesperada                                            #
  #  - Referentes aa troca de senha                                            #
  #    210 - Senha nova invalida                                               #
  #    220 - Impossivel trocar a senha (erro generico)                         #
  #    298 - Timeout                                                           #
  #    299 - Finalizacao inesperada                                            #
  ##############################################################################
  
  # --- Variaveis configuraveis ---
  # Linha de comando para o 'telnet'
  set telnet_cmd "/usr/bin/telnet"
  
  # Linha de comando para o 'passwd'
  set passwd_cmd "/usr/bin/passwd"
  
  # Host a ser contactado pelo 'telnet' (em geral, o proprio 'localhost')
  set login_host "localhost"
  # -------------------------------
  
  
  # --- Parametros da sessao ---
  set timeout 10
  
  # Parece que funciona melhor assim...
  set stty_init -nottycopy
  
  # Soh para garantir
  set env(TERM) vt100
  
  # Nao mostra ao usuario as respostas dos comandos
  log_user 0
  
  # Exibe mensagem de ajuda, caso o usuario informe algum parametro na linha de comandos
  if [ expr $argc > 0 ] then {
     send_user "\n$argv0: Script para troca nao-interativa de senhas.\
               \n   Execute este script sem parametros, e infrome o login do usuario,\
               \n   sua senha atual e uma nova senha (nessa ordem, via entrada padrao).\n\n"
     exit
  }
  
  # Obtem os dados da conta do usuario da entrada padrao
  gets stdin login
  gets stdin old_password
  gets stdin new_password
  
  # Inicia a sessao com um cabecalho informativo, proprio para ser redirecionado
  # para um arquivo de log
  set timestr [clock format [clock seconds] -format "%d/%m/%Y - %T (%Z)"]
  send_user "\n----------= Iniciando sessao para troca de senha  =----------\n"
  send_user " * Usuario: $login   -----   $timestr\n\n"
  
  send_user "Iniciando sessao telnet (host: $login_host)...\n"
  
  spawn $telnet_cmd $login_host
  
  # Um breve delay para aguardar pela conexao
  sleep 2
  
  # Efetua o login
  expect {
     "ogin:" {
     send_user " * Enviando login...\n"
     send "$login\r"
  
     # Sessao finalizada por timeout (ex.: servidor NIS ou NFS fora do ar)
     } timeout {
        send_user " - Timeout durante a conexao.\n"
        exit 198
  
     # Sessao abortada inesperadamente (ex.: expect e telnet nao conseguiram se entender)
     } eof {
        send_user " - Finalizacao inesperada durante a conexao.\n"
        exit 199
     }
  }
  
  
  # Finalizacao do login / interacao com o 'passwd'
  expect {
     # Espera prompt para senha de login
     "Password:" {
        send_user " * Enviando senha...\n"
        send "$old_password\r"
        exp_continue
  
     # Erros diversos que impedem a troca de senha (ex.: senha nova vazia)
     # (deve estar antes das linhas que testas os prompts do shell e do 'passwd)
     } "unchanged" {
        send_user " - Nao foi possivel efetuar a troca de senha.\n"
        exit 220
  
     # Informa a senha antiga, solicitada apos a execucao do 'passwd'
     # ou logo apos o login, caso a senha esteja expirada
     } "Old" {
        send_user "\nEfetuando troca de senha:\n * Informando a senha antiga...\n"
        send "$old_password\r"
        exp_continue
  
     # Trata respostas do sistema a senhas novas invalidas
     # (deve estar antes da linha que testa o prompt 'New password')
     } "Please" {
        send_user " - Senha nova invalida.\n"
        exit 210
  
     # Informa a senha nova
     } -r "New|Retype" {
        send_user " * Informando a senha nova / Confirmacao...\n"
        send "$new_password\r"
        exp_continue
  
     # Concluiu a troca de senha
     # (deve estar antes da linha que testa o prompt do shell)
     } "done" {
        send_user " + Troca de senha efetuada!\n"
        exit 0
  
     # Executa 'passwd' caso obtenha-se o prompt do shell
     } "$login@" {
        send_user " + Login concluido.\n"
        send "$passwd_cmd\r"
        exp_continue
  
     # Testa login invalido
     } "ogin incorrect" {
        send_user " - Login ou Senha atual incorreta.\n"
        exit 110
  
     # Timeout e eof em geral nao acontecem aqui, mas...
     } timeout {
        send_user " - Timeout durante a troca de senha.\n"
        exit 298
  
     } eof {
        send_user " - Finalizacao inesperada durante a troca de senha.\n"
        exit 299
     }
  }

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Rodolfo Broco Manin