Elmord's Magic Valley

Software, lingüística e rock'n'roll. Às vezes em Português, sometimes in English.

inf.ufrgs.br, PHP, e outros infortúnios

2013-03-10 22:26 -0300. Tags: comp, life, php, rant, em-portugues

Com este post tenho o objetivo único e exclusivo de reclamar da vida. É improvável que haja qualquer informação proveitosa contida aqui. You have been warned.

Quando eu entrei para a Inf, os Sioux possuíam o mundo as páginas pessoais dos alunos eram contidas no diretório home de seus usuários (especificamente, em ~/public_html). O camarada podia acessar a portal.inf.ufrgs.br por SSH e editar as páginas remotamente com o Vim. Outra vantagem é que se podia rodar scripts remotamente para gerar páginas ou fazer algum procedimento de manutenção. Bem, mais ou menos. O home da portal é montado sem permissão de execução, o que significa que só dá para rodar os binários que já estão lá (e.g., bash, perl), e para poder rodar os scripts que eu tinha no ~/bin sem ter que digitar bash nome-do-script toda vez eu tinha que fazer uma gambiarra no ~/.bashrc para criar uma função com o mesmo nome do script para cada script presente no ~/bin. Mas ok, dava pra tolerar.

Em algum momento da história do mundo, as páginas pessoais foram levadas para um servidor separado, "por motivos de segurança". Conseqüentemente, não dava mais para alterar as páginas via portal. Montar o diretório das páginas por sshfs? Claro que não, a portal não tem sshfs e não executa binários do home. Solicitar à administração da rede para instalarem o sshfs na portal? Não faremos isso, por motivos de segurança. Well, dá pra montar o sshfs usando a máquina de casa, e se divertir com a latência do 3G. Heh.

Um dia me contaram que dava para acessar a portal, e de lá se logar nas máquinas dos laboratórios da graduação, de onde se pode rodar sshfs e tudo o mais que se queira. Hmm, boa! O camarada tem que se logar três vezes (uma na portal, uma nos labs, e uma no sshfs), mas ainda vale a pena. Se o 3G cai meu Vim fica parado lá me esperando e eu não corro o risco de ter salvo meio arquivo no home.

No semestre passado, atualizaram o OS das máquinas dos labs, e agora não é mais possível fazer o login remoto. Yay! Bom, sobrou o sshfs de casa. Felizmente, agora o meu 3G é um pouquinho melhor, com uma latência normalmente abaixo do 1 segundo (vs. os 4 da Tim), e a coisa é pelo menos utilizável.

O servidor das páginas pessoais também monta os homes sem permissão de execução, o que significa que só dá para usar as linguagens de script que já estão lá, i.e., PHP. PHP é uma linguagem/implementação notavelmente medonha, mas ok, é o que temos. Eu quero um blog, e eu quero agora, e eu quero escrever meus posts no Vim e salvar um txt somewhere para postá-los e ser feliz. Let's do it.

O PHP tem uma (so-called) "feature" chamada "magic quotes". A idéia é: programadores são incompetentes e esquecem de escapar as aspas antes de montar uma query de SQL, então vamos escapar automaticamente qualquer entrada que venha de um formulário. (A noção de montar queries de SQL na mão e escapar strings na mão é uma coisa que strikes me as fundamentally wrong, but I digress.) Acontece que o PHP só faz isso se ele estiver configurado para fazer isso no php.ini. E como (pelo que eu entendo) ele faz o escaping antes de rodar o script, o script não tem a oportunidade de desativar as magic quotes. Conclusão? Eu tenho uma função no blog cujo único propósito é receber uma string e remover os escapes se as magic quotes estiverem ativas, ou retornar a string intacta caso contrário. Lindo, hein?

E as closures. Em JavaScript (é, eu vou usar JavaScript, outra linguagem linda, como exemplo, mas acho que assim será mais compreensível do que o Common Lisp que eu ia usar) podemos fazer coisas do tipo:

function menores_que(n, lista) {
    return lista.filter(function(x) { return x<n; });
}

menores_que(5, [2,3,5,7,11]);   // Retorna [2,3].

Aqui, passamos uma função anônima para o método filter, que seleciona os elementos da lista que satisfazem o predicado passado como argumento. (Esse método só existe no JavaScript da Mozilla, eu acho.) Note que a subfunção usa o n definido fora dela. Em PHP 5.3 foi introduzida uma feature similar. Porém, na versão PHP, você tem que declarar explicitamente quais variáveis externas serão capturadas pela closure. WTF? Isso é tão ridículo que não sei quem mais poderia ter a mesma idéia. Oh, well. (Pelo menos em C++11 há a opção de dizer "captura tudo e não enche".)

Ok, ok. Eu sobrevivi. 753 linhas de PHP. Até que ficou pequeninho para a quantidade de coisas que o blog faz. O problema é que o código ficou todo gambiarrento, e sempre que eu vou adicionar uma feature é um trabalho medonho, e sempre que eu penso em reescrever do zero (coisa que uma hora ou outra eu vou acabar fazendo, já que eu não consigo ficar cinco minutos editando o código atual sem ranger os dentes) eu lembro que terei que fazer isso em PHP (o que produzirá uma quantidade equiparável de ranger de dentes) e abandono a idéia. Mas terá que ser feito, porque PHP é a única coisa que roda na Inf (e muitos outros lugares). Very well. (Actually, not.)

A última coisa que eu quis adicionar no blog foi uma feature de "Comentários recentes" na barra lateral. A idéia original era simplíssima: quando um leitor posta um comentário, além de criar o arquivinho de comentário no diretório apropriado, criamos também um symlink para o arquivinho em um diretório recent_comments da vida. Se o número de links exceder uma quantidade x, removem-se os links mais antigos. Simples, hã? Só que se eu tento usar a função symlink(), ela simplesmente retorna FALSE e nada acontece. What gives?

Acontece que o tal do Suhosin bloqueia a função symlink() do PHP se a opção base_opendir do PHP estiver ativada. Essa opção serve para limitar de que diretórios os scripts podem abrir arquivos. A idéia é que se o usuário puder usar a symlink(), ele poderia em tese despistar a base_opendir criando um link no diretório local para um lugar de onde o script não teria acesso (e.g., /etc/passwd). Porque o PHP não poderia primeiro resolver o symlink e depois testar se o arquivo está dentro dos diretórios permitidos antes de abri-lo, right? Nem a symlink() poderia verificar se o alvo do link está dentro dos diretórios permitidos e criar ou não o link dependendo do caso, right?

Acontece que aparentemete o PHP verifica o caminho resolvido antes de abrir o arquivo. You see, embora o PHP não possa criar symlinks, eu mesmo posso, por sshfs. Quer dizer que qualquer vulnerabilidade que links arbitrários pudessem causar ainda poderiam ser provocadas por mim. Mas eu testei criar um symlink local para o /etc/passwd, e o PHP se recusa a abri-lo, alegando violação da base_opendir. Quer dizer que mesmo que a symlink() estivesse ativa ainda não haveria vulnerabilidade. Mas ela não está, e isso impede gratuitamente minha implementação simples da feature de comentários recentes. Eu poderia entrar em contato com a administração da rede da Inf e pedir para eles habilitarem a feature. Eu não farei isso por duas razões: (1) a admrede vai me dizer que não vai habilitar nada "por motivos de segurança"; (2) um dos princípios por trás deste blog system é rodar em qualquer lugar que tenha um servidor com PHP, sem depender nem de bibliotecas non-standard nem da boa-vontade de sysadmins, e como o symlink() desativado é o padrão do Suhosin, não posso contar com a utilizabilidade dessa função. Tudo bem, o Unix original não tinha symlinks. Vamos brincar de anos setenta.

Comentários / Comments (8)

Bug, 2013-03-11 11:19:43 -0300 #

O PHP eu nem comento muito porque eu já tive minha cota(quota?) de problemas com ele. Mas o que eu acho mais hilário é não instalarem o sshfs por "questões de segurança". Really, mostre-me qual o problema então! LOL

E se nada mais der certo, sempre há 2 opções: 1) pagar uma hospedagem baratinha, ou 2) usar um pc velho como host do blog (com 3G vai ficar bonito :P).


Vítor De Araújo, 2013-03-11 19:02:37 -0300 #

sshfs é uma ferramenta de haquers do mal. Não se deixe enganar!

E por enquanto eu vou ter que me contentar com a Inf mesmo. Hospedagem baratinha é uma boa opção futura, mas por enquanto eu não preciso dela (e quanto menos eu precisar gastar agora melhor :P), e o 3G da Oi bloqueia as portas para entrada (aparentemente porque eles fazem um NAT brabo e dão o mesmo IP pra uma galera). Mas que pôr o 486 atrás de um 3G como servidor ia ficar bonito, ia :P


Bug, 2013-03-11 19:15:26 -0300 #

De fato, quanto menos precisar gastar, melhor!

Ah, aqui o 3G também tem NAT.. tanto que a gente diz que baixar torrent no 3G é +/- "não rastreável", já que é um IP pra toda uma região (pra um conjunto de antenas, se não me engano).

E sim, eu tava pensando justamente nesse 486.... mwhahahhaha >D


Marcus Aurelius, 2013-03-12 23:51:55 -0300 #

Sempre dizem que PHP é tosco, e eu não duvido porque nunca programei em PHP.
Mas consegue ser pior que Perl?

Muitas críticas ao PHP me parecem simplesmente amadorismo na criação da linguagem, enquanto que Perl foi realmente projetado para ser excêntrico.

Perl tem a variável implícita $_ por design (não, ela não surgiu sozinha), orientação a objetos bizarríssima por design, sintaxe ambígua por design, variáveis com nomes que são só pontuação por design, etc.

PHP consegue ser pior?


Vítor De Araújo, 2013-03-13 08:33:54 -0300 #

@Marcus Aurelius: mad design > broken design. :P Mas nunca usei muito Perl, então não sei dizer. Pelo menos Perl tem operadores de comparação de string separados dos de comparação numérica. E Perl tem funções anônimas não-ridículas. :P


Vítor De Araújo, 2013-03-13 08:46:29 -0300 #

Por outro lado Perl não tem declaração de parâmetros de função. :(

(PHP não verifica se os parâmetros casam com os argumentos na chamada, mas já é um "avanço". :P)


Vítor De Araújo, 2013-03-13 08:47:54 -0300 #

Oh, and the list/scalar context. Yes, now I remember. Argrhgrhrgrrhghr!! :P


Marcus Aurelius, 2013-03-13 13:06:02 -0300 #

É, a falta de nomes de parâmetros nas funções e os contextos são outras coisas que eu odeio (só não quis deixar a lista de reclamações tão grande, haha).

Desempacotar as coisas a partir do parâmetro caolho @_ já é ruim, mas como se não bastasse isso, também dá pra pegar um-por-um usando a função shift... Ou pode acessar diretamente $_[0], $_[1]. Ou pode passar todos os argumentos adiante com alguma sintaxe de chamada usando & (não sei bem qual).

E, claro, o pogramador tem que saber todos os jeitos, senão não consegue ler um código básico escrito por outra pessoa! Hnf.

Eu costumava ler as man pages do Perl e achar interessante. Até que eu parei e pensei: “Por que eu estou lendo esse monte de blá-blá-blá sobre coisas que deveriam ser triviais? Foda-se Perl, tem muitas outras linguagens que me permitem fazer coisas mais legais sem precisar me tornar um especialista no uso da sintaxe de objeto indireto (termo do Perl)...”


Deixe um comentário / Leave a comment

Main menu

Posts recentes

Comentários recentes

Tags

em-portugues (213) comp (137) prog (68) in-english (50) life (47) pldesign (35) unix (34) lang (32) random (28) about (27) mind (25) lisp (23) mundane (22) fenius (20) ramble (17) web (17) img (13) rant (12) hel (12) privacy (10) scheme (10) freedom (8) copyright (7) bash (7) music (7) academia (7) lash (7) esperanto (7) home (6) mestrado (6) shell (6) conlang (5) emacs (5) misc (5) latex (4) editor (4) book (4) php (4) worldly (4) android (4) politics (4) etymology (4) wrong (3) security (3) tour-de-scheme (3) kbd (3) c (3) film (3) network (3) cook (2) poem (2) physics (2) wm (2) treta (2) philosophy (2) comic (2) lows (2) llvm (2) perl (1) en-esperanto (1) audio (1) old-chinese (1) kindle (1) german (1) pointless (1) translation (1)

Elsewhere

Quod vide


Copyright © 2010-2020 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.

Powered by Blognir.