AVISO

AVISO: ESTE É MEU ANTIGO BLOG, QUE NÃO É MAIS ESCRITO DESDE 2011. O CONTEÚDO AQUI EXPRESSO PODE NÃO REPRESENTAR MEUS PENSAMENTOS E OPINIÕES DE IDADE ADULTA. PARA CONTEÚDOS NOVOS E RELEVANTES ACESSE BLOG.BRUNO.TODAY




quinta-feira, 23 de outubro de 2008

DICA: Instalando Programas Em Servidores Web Sem Ter Senha de Root

Palavras-chave: Linux, CGI, Edição de Binários

Fica a dica para quem tiver alguma necessidade parecida...

Comecei a escrever um CGI, bem simplesinho, em Bash[1]. Ele é muito simples(outra hora eu posto ele pra vocês), e rodava, entre outras coisas, o executável do enscript. Só tinha um pequeno porém: eu precisava saber se o servidor web do meu webhost tinha o enscript. E lá vou eu, com o seguinte teste:



#!/bin/sh

echo -e "Content-type: text/html\r\n"

if [ ! -f sample.cpp ]; then
echo "
#include <iostream>

using namespace std;

int main()
{
cout << \"Ola Mundo\" << endl;
exit(0);
return 0;
}
" > sample.cpp
fi

if [ ! -f sample.cpp.htm ]; then
echo "Enscript..."
enscript --color --language=html -Ecpp -o sample.cpp.htm sample.cpp
fi

cat sample.cpp.htm


Enfim... Descobri que não tinha o dito cara instalado!! E agora?? Bom, vamos usar um pouco do nosso "censo de improviso"!! O sistema do servidor tem tudo para ser um RH Enterprise ou semelhante(eu supus). Infelizmente eu não tenho acesso ao shell via SSH.

Utilizei uma máquina com o CentOS e peguei o binário. Executei um ldd nele, e só tinha a libc linkada. Aí muito feliz, joguei ele no diretório cgi-bin do meu servidor web. Mudei o script, para executar "./enscript" em vez de "enscript"(executar do diretório local). Tentei rodar meu CGI e nada.

Estava 1 x 0 para meu servidor web, mas eu não me entrego. Coloquei no meu CGI uma mensagem com a saída de erros(adicionei um 2>&1 no final da linha de comando). E lá estava a mensagem: "/usr/share/enscript/enscript.cfg: no such file or directory". E então eu me lembrei: bah, lembrei do binário mas não lembrei dos arquivos de configuração e outros que ele possa ler!

Eis então o cenário: eu não tenho permissão de escrita no /usr/share. O binário do enscript depende desse diretório 'enscript' que está lá. Logo, eu não poderei rodar o enscript lá!

Mentira!! Como eu não me entrego nunca, acessei minha máquina virtual com o CentOS novamente. Análisei o binário com o comando 'strings'. Ele tem uma string com o diretório e uma com o nome do arquivo. Então, meu diretório no servidor é '/home/bruno', e o diretório daonde ele lê atualmente é '/usr/share/enscript'. Então lá vou eu:

$ cat /usr/bin/enscript | sed 's/\/usr\/share\/enscript/\/home\/bruno\/nscript/g' > enscript.new

Então tinhamos um 'novo enscript'. Antes que perguntem porque mudei o caminho para '/home/bruno/nscript' e não para '/home/bruno/enscript', eu já aviso: conte os caracteres e entenderás!!

Ok, as coisas estavam se encaminhando. Antes de criar o diretório 'nscript' no meu diretório home, eu resolvi fazer um teste. Ainda na máquina com o Centos, criei o diretório no meu home dali, e rodei um strace:

chmod 755 enscript.new
strace ./enscript.new --color --language=html -Ecpp -o sample.cpp.htm sample.cpp 2>strace.out
grep 'open(' strace.out


E então a surpresa: ele ainda estava executando 'opens' no diretório /usr/share/enscript. E mais, ele na verdade lia o enscript.cfg do /etc, e não do /usr/share/enscript. E agora?? 2 x 0 pro servidor web!!

Mas eu não desisto. Supus que ele tivesse uma lista de caminhos para procurar o enscript.cfg. Removi ele experimentalmente do /etc e confirmei minha suspeita: ele deu a mesma mensagem que no servidor web. Então foi simples, criei ele em '/home/bruno/nscript'. 2 x 1 pro webserver, nessa eu fui melhor. Mas ainda havia o outro problema que tinhamos detectado: ele lia alguns arquivos do antigo caminho. E agora?? Havia um fantasma do binário antigo nele??

Dando uma "fuçada" percebi que era do arquivo de configuração que ele tirava aquele caminho. Finalmente, coloquei no servidor web os arquivos de configuração com o caminho novo, e executei denovo o CGI: mais problemas!! Agora ele não achava um executável chamado 'states'.

Primeiro rodei um 'strings' denovo no 'enscript', e filtrei 'states' na saída. Nada foi encontrado. Mas como assim?? Suspeitei direto do arquivo de configuração, e "BINGO!!". Estava definido lá o caminho do states. Aí, para minha sorte, o 'states' só dependia da libc também. Lá vamos nós, rodando um strace, agora com -f, no enscript. O -f segue forks, fazendo o trace dos processos filho também, e não apenas do processo principal.

Ao confirmar que ele não lia arquivo algum, postei na hora o executável, atualizei o parâmetro do caminho dele no arquivo de configuração do enscript, e fui lá testar. Funcionou.

Quem nunca fez uma gambiarra?? Chuck Norris deve estar morrendo de inveja de mim agora!!

[1] Para os que não são do "mundo Unix", Bash é um shell. Eu escrevi um Shell Script, semelhante aos '.bat' do DOS, porém com muito mais flexibilidade e utilidade. Sim, Shell Script também pode ser usado como CGI!

Classificação do conteúdo: SÉRIO
Sobre Bruno Moreira Guedes:
Curriculum Vitae
Site Pessoal

4 comentários:

brunOld disse...

Faça um "blogueiro" feliz!! Comente!!

Sua opinião é muito importante!

teste disse...

legal o post, legal o blog, mas você não pensou em compilar o enscript ajustando o --prefix?

brunOld disse...

Andreyev,

Bom, você venceu rsrsrs... Digamos que eu deveria ter pensado!!

O que acontece é que na hora que eu pensei em fazer eu imaginei que seria só alterar o caminho do binario. Já compilando ele eu teria que saber com que opções ele foi compilado, por exemplo(eu nunca compilei o enscript, nem levantei a informação antes).

Além do que, como a minha instalação do CentOS é uma instalação em produção, eu não possuo ferramentas de desenvolvimento nela

Mas se eu tivesse previsto isso realmente compilaria novamente que seria menos trabalhoso!!

teste disse...

Hehehe... poderia ser menos trabalhoso compilar o enscript novamente, mas aposto que também seria menos divertido! ;-)

Sobre Bruno Moreira Guedes