Administração de sistemas Unix

André Moreira (andre@dei.isep.ipp.pt)
Professor Adjunto do Departamento de Engenharia Informática do ISEP

Introdução

Os sistemas Unix sempre representaram uma opção importante quando se pretende fiabilidade e eficiência, embora existam muitas implementações especificas de determinados fabricantes (HP UX, IBM AIX, Digital ULTRIX, Digital UNIX, Novell UnixWare, SCO Unix, ...) todas elas mantêm um elevado grau de compatibilidade baseada no compilador de linguagem C, um conjunto de bibliotecas compativeis e um núcleo de sistema operativo (kernel) com conceitos que caracterizam os sistemas operativos tipo Unix.

Embora não exista compatibilidade binária entre os diversos sistemas tipo Unix, existe compatibilidade de código fonte, isto significa que o "software" desenvolvido em linguagem C para uma dada plataforma Unix pode ser "compilado" em qualquer outra plataforma Unix. Mais recentemente o projecto aberto Linux tem-se assumido como uma alternativa de enorme importância, com um núcleo desenvolvido de forma aberta ("open source"), encontra-se disponível de forma mais ou menos gratuita, através de diversas distribuíções. Estas distribuíções Linux, além do núcleo, incluem todo o "software" adicional e ficheiros necessários para o funcionamento do sistema, a maioria deste "software" adicional é também desenvolvido em "open source". Sem tomar qualquer partido, algumas das distribuições mais tradicionais são: Slackware, Redhat e Suse.

Administração de sistemas Linux

Dada a sua importancia actual, a maioria da informação constante neste documento baseia-se em Linux, contudo a administração de outros sistemas Unix não difere quase nada da administração de sistema Linux.

Com o seu carácter "open source", o sistema operativo Linux recebe as mais diversas contribuições e é actualmente a implementação Unix mais versátil, suportando as mais diversas possibilidades de configuração e integração. Administrar sistemas Linux pode ser um desafio significativo, normalmente os projectos "open source" produzem dois tipos de produto, "versão estável" e "versão em desenvolvimento/instavel", se o administrador se restringir à utilização das versões estáveis, tem certas garantias de uma existência pacífica, se pelo contrário tentar utilizar versões em desnvolvimento, corre riscos de instabilidade no respectivo sistema e possívelmente acabará a colaborar no desenvolvimento desses projectos.

Por uma questão de metodologia, a administração de um sistema operatvo pode ser dividida em várias áreas distintas:

  • Administração de utilizadores - criar e modificar as definições relacionadas com os utilizadores do sistema: identificação interna; nome de utilizador; chave de acesso; grupos a que pertence; etc.
  • Administração de sistemas de ficheiros - gerir o sistema de ficheiros, integrando diversos suportes físicos e gerir as permissões dos utilizadores sobre os ficheiros.
  • Administração de "software" - gerir as aplicações disponíveis no sistema, a maioria das aplicações destinam-se aos utilizadores, mas por exemplo, podem também servir para a implementação de serviços.
  • Administração de serviços - gerir serviços, com especial destaque para os serviços de rede.

Na realidade todas estas áreas estão intimamente relacionadas entre sí

Administração de utilizadores

Qualquer sistema multi-utilizador tem de manter uma base de dados de utilizadores, nesta base de dados, geralmente de tipo relacional, existe um registo para cada utilizador. Cada utilizador tem diversas propriedades associadas a sí, para gerir os utilizadores e todo o sistema em geral existe um "super-utilizador" ou administrador, nos sistemas Unix existe um único administrador que tem o nome "root".

Nos sistemas tipo Unix os utilizadores estão definidos no ficheiro /etc/passwd, neste ficheiro de texto, cada linha corresponde a um utilizador, constando uma sequencia de campos, separados por dois pontos, todos os campos são obrigatórios, mas alguns podem estar vazios.

O exemplo seguinte ilustra um extracto de 8 linhas (8 utilizadores) de um ficheiro /etc/passwd:

root:BeDyr8qulmhZ2:0:0:root:/root:/bin/bash
daemon:*:2:2:daemon:/sbin:/bin/bash
bin:*:1:1:bin:/bin:/bin/bash
postgres:*:26:2:Postgres Database Admin:/var/lib/pgsql:/bin/bash
wwwrun:*:30:65534:Daemon user for apache:/tmp:/bin/bash
empress:*:35:2:Empress Database Admin:/usr/empress:/bin/bash
guest:a28HqK3Yamh7t:1001:102:Utilizador nosso convidado:/home/guest:/bin/csh
user:uHr5fg6RtEw23:1002:102:Utilizador local:/home/user:/bin/bash
+

Os campos são, ordenadamente, os seguintes:

  • "Login Name" ou "Username" - é o nome que o utilizador usa para se identificar perante o sistema, logo deve ser único no sistema.
  • SALT+HASH(SALT+PASSWORD) - é o resultado da aplicação de uma função de "hash" à password do utilizador (em conjunto com o SALT que introduz um factor aleatório). É usado para autenticação do utilizador, para o efeito o utilizador fornece o seu "Username" e respectiva PASSWORD, o sistema calcula então HASH(SALT+PASSWORD) e verifica se coincide com o que está no ficheiro /etc/passwd. Neste campo, separados por virgulas podem ainda constar diversos valores referentes à validade da password, ver o ficheiro /etc/shadow.
  • User Identifier (UID) - é um número inteiro usado para identificar o utilizador no interior do sistema, tal como o "Username" deve ser único, contudo ao contrário do "Username" que apenas consta no ficheiro /etc/passwd e é usado apenas para a identificação inicial perante o sistema, o UID é intensivamente usado nas operações internas pós-login. Como se pode observar o UID do utilizador "root" é zero, e deverá existir em todos os sistemas tipo Unix.
  • Group Identifier (GID) - número inteiro que identifica o grupo primário a que o utilizador pertence, em Unix os grupos de utizadores estão definidos no ficheiro /etc/group, sendo que cada grupo possui um número de identificação único, o GID.
  • Nome completo do utilizador
  • Localização do directório de trabalho - trata-se do nome do directório de trabalho a atribuir após a entrada no sistema, tipicamente é um directório pessoal no qual apenas esse utilizador tem permissões, tem habitualmente a designação de HOME.
  • Nome da shell inicial - quando o utilizador entra no sistema (depois da autenticação) o controlo da sessão tem de ser transferido para um programa que será executado já com as permissões desse utilizador, tipicamente é um programa interactivo interpretador de comandos em modo de texto, que tem a designação de "shell".

Grupos de utilizadores

A definição de grupos de utilizadores é muito vantajosa sob o ponto de vista de administração porque quando se pretende atribuir a muitos utilizadores um dado direito (permissão) é possível atribuir esse direito ao grupo, tendo como efeito que todos os utilizadores que são membros do grupo passam também a usufruir desse direito.

Nos sistemas Unix os grupos estão definidos no ficheiro /etc/group, este ficheiro tem uma estrutura semalhante à do /etc/passwd, os campos são os seguintes:

  • O 1º campo define o nome do grupo, tal como para utilizadores este campo tem de ter um valor único.
  • Normalmente não se usam passwords para grupos, por isso o 2º campo tem um "*" ou um "x".
  • O 3º campo contém o GID, tal como acontecia no /etc/passwd para os UID, os GID tem de ser únicos no sistema.
  • O 4º e último campo possui uma lista de utilizadores (separados por virgula) que pertencem ao grupo, isto apenas é necessário para os utilizadores que não têm o grupo mencionado como grupo primário no /etc/passwd.

A seguir apresenta-se um extracto de um ficheiro /etc/group:

root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:
users:x:102:
nogroup:x:65534:root

Pode observar-se que apesar do grupo "users" não ter membros definidos, na realidade, por cruzamento com o exemplo /etc/passwd anterior, os utilizadores "guest" e "user" são membros.

Outro aspecto a destacar é a existência de um grupo chamado "root", se forem colocados utilizadores neste grupo, eles passarão a ter muitos dos direitos que o administrador possui sobre objectos do sistema, já que este é o grupo primário do administrador.

Shadow passwd

Um dos problemas suscitados pelo ficheiro /etc/passwd é o facto de ter de ser legivel para todos os utilizadores. Uma vez que o HASH da password consta no ficheiro, torna-se possível tentar "adivinhar" uma "password" que gera esse HASH, possivelmente não será a mesma "password" que o utilizador usa, mas servirá como autenticação. Quebrar desta forma o mecanismo de autenticação é extremamente difícil e moroso, a abordagem que é usada na prática consiste em usar um programa gerador de "passwords", baseado por exemplo num dicionário e tentar essas "passwords".

Seja como for o acesso aos "hash" das "passwords" dos utilizadores é claramente um ponto fraco, o processo de tentativa de autenticação que deveria ser controlado pelo sistema (controlando o número máximo de tentativas e o atraso entre tentativas) pode ser simulado em outro sistema, basta para isso que o "hash" que consta no /etc/passwd seja copiado.

Para resolver este problema de segurança, existe a possibilidade de utilizar um ficheiro sombra para armazenar os hash das "passwords", este ficheiro é /etc/shadow, mas ao contrário do ficheiro /etc/passwd apenas é legivel pelo utilizador "root". A designação "shadow" (sombra) deve-se ao facto de conter exactamente os mesmos registos do /etc/passwd.

O ficheiro /etc/shadow tem uma estrutura semelhante ao /etc/passwd, mas os campos são os previstos para o campo da password no ficheiro /etc/passwd. Os campos, ordenadamente, são os seguintes:

  • "Login Name" ou "Username" - é o nome que o utilizador exactamente igual ao que se encontra no ficheiro /etc/passwd.
  • SALT+HASH(SALT+PASSWORD) - é o resultado da aplicação de uma função de "hash" à password do utilizador, tal como foi descrito para o ficheiro /etc/passwd, a respectiva entrada no ficheiro /etc/passwd passa agora a conter um "x".
  • Data da última mudança de password - especificada em número de dias, desde 01/01/1970.
  • Número de dias que faltam para o utilizador poder mudar a password.
  • Número de dias que faltam para o utilizador ser obrigado a mudar a password (a password expira).
  • Número de dias antes de ser obrigado a mudar a password em que o utilizador começa a ser avisado.
  • Número de dias decorridos depois da a password expirar em que a conta é desactivada.
  • Data em que a conta foi desactivada - especificada em número de dias, desde 01/01/1970.
  • Campo não especificado, reservado para uso futuro.

Gestão das bases de dados de utilizadores Unix

Existem diversos programas que podem ser usados para gerir os utilizadores, aqui vou apenas referir os programas básicos, que devem estar disponíveis em todos os tipos de sistema Unix, existem depois muitos outros programas que usam os primeiros e que são especificos de cada sistema em particular, muitos deles com interface gráfica.

Na realidade para administrar utilizadores em Unix basta um editor de texto, de preferência o "vi", o único campo que não pode ser editado directamente é o "hash" da password, para isso é necessário recorrer ao programa "passwd".

Em sistemas onde se usa "shadow passwords", depois de modificar manualmente o /etc/passwd é necessário ainda invocar o programa "pwconv". O "pwconv" cria no directório corrente um ficheiro "npasswd" e um "nshadow" que correspondem às novas versões dos ficheiros /etc/passwd e /etc/shadow depois de realizada a junção da informação.

Os utilizadores podem alterar alguns aspectos da sua conta, o administrador pode alterar qualquer conta, para o efeito os programas seguintes verificam se quem os está a executar é o administrador ou não:

  • passwd - permite alterar a password do utilizador, permite ainda ao administrador gerir os parâmetros suplementares do ficheiro /etc/shadow.
  • chfn ("Change full-name") - permite alterar o nome completo do utilizador.
  • chsh ("Change shell") - permite alterar o programa inicial do utilizador.

Geralmente todos os sistemas dispõem de programas mais sofisticados para manipular utlizadores, a utilização destes programas está geralmente reservada ao administrador:

  • useradd - permite adicionar novos utilizadores, procura automáticamente um UID não usado e cria a "home directory", os utilizadores são criados segundo um "template", ou especificando as diversas caracteristicas na linha de comando.
  • userdel - permite remover um utilizador e pode também remover a "home directory".
  • usermod - permite alterar qualquer dado relacionado com um utilizador, incluindo o "username" e mesmo o UID, bem como grupos a que pertence.
  • groupadd - criação de novos grupos de utilizadores.
  • groupmod - modificação de grupos de utilizadores (nome do grupo e GID).
  • groupdel - eliminação de grupos de utilizadores.

A utilização de programas especificos é mais razoável do que a edição manual, estes programas especificos garante a exclusão mútua para escrita, isto é garantem que nunca existem dois programas a alterar simultaneamente as bases de dados dos utilizadores, com os resultados imprevisiveis que daí podem resultar, por outro lado a edição manual pode, por erro do administrador levar a que os ficheiros não respeitem a formatação ou não sejam coerentes. Tratando-se da base de dados dos utilizadores estes erros podem ser muito graves.

Bases de dados de utilizadores centralizadas - NIS

Com a rápida evoluçãao das redes de computadores, em grande parte impulsionadas pelos sistemas operativos Unix, tornou-se absolutamente necessário criar sistemas centralizados para estas bases de dados que evitassem uma gestão independente para cada máquina de uma rede, o mais tradicional em ambiente Unix é o sistema conhecido por "Yellow Pages" (yp) ou NIS ("Network Information Service").

Este sistema é composto por um servidor "ypserv", instalado numa máquina central por clientes "ypbind" instalados nas outras máquinas. Os vários clientes (ypbind) contactam o servidor para obterem mapas, que não são mais do que equivalentes dos conteúdos habituais dos ficheiros /etc/passwd, /etc/group e outros, como por exemplo o /etc/hosts ou o /etc/services.

O servidor (ypserv) não usa directamente os ficheiros locais para responder aos clientes, existem programas (geralmente invocados através do comando "make" no directório /var/yp) que convertem a informação residente nos ficheiros locais (aqui vistos como ficheiros fonte) para um formato adequado ao servidor.

Os ficheiros fonte podem ou não ser as versões em uso local no servidor (localizadas no directório /etc), se forem usadas como fonte as versões locais existe a grande vantagem de poderem ser usados os programas de gestão de utilizadores atrás referidos, apenas é necessário não esquecer de, após as alterações, invocar o comando "make" no directório /var/yp para actualizar a base de dados NIS. A desvantagem desta opção é que os utilizadores de sistema, tais como root, daemon, field, ... também vão ser colocados na base de dados.

A opção por ficheiros separados como fonte NIS (noutro directório que não /etc) implica a necessidade de se usar programas especificos para gestão de utilizadores que permitam a manipulação dos ficheiros noutros directórios, estes programas não abundam.

Os clientes NIS utilizam o programa ypbind direccionado para o servidor NIS, para que na autenticação dos utilizadores o servidor NIS seja consultado é necessário que a última linha dos ficheiros locais (/etc/passwd, /etc/group e /etc/shadow) contenha o sinal "+", que significa adicionar toda a informação do servidor NIS (também é possivel adicionar utilizadores NIS individuais, usando linhas contendo "+username". Nos clientes NIS é ainda possível usar vários comandos tais como o "ypcat" para consultar os vários mapas disponibilizados pelo servidor NIS, ou o "ypmatch" para pesquisar os mapas.

O servidor NIS (ypserv) é apenas de leitura, para que os utilizadores possam alterar os seus dados "password/shell/nome-completo" recorre-se a um serviço separado, assim conjuntamente como o "ypserv" instala-se um outro servidor, o "yppasswdd" no lado do cliente NIS utiliza-se agora os comandos yppasswd, ypchsh e ypchfn que contactam o yppasswdd no servidor NIS.

Suporte a multiplas origens de dados - nsswitch

Com a introdução do NIS passaram a existir nos clientes duas origens para as definições de utilizadores, as bases de dados locais (no directório /etc) e as bases de dados NIS.

A forma como se sinaliza tal facto é através da colocação de sinais "+" nas versões locais, tal significa que naquele ponto da pesquisa local deve ser realizada uma pesquisa no servidor NIS.

Para o caso da resolução de nomes de máquinas podemos ter mesmo 3 origens diferentes para os dados: local (/etc/hosts), NIS ou DNS, os sistemas que são usados e em que ordem estão especificados no ficheiro /etc/host.conf.

Os sistema Linux mais recentes expandem significativamente esta ideia, generalizando o suporte a multiplas origens para a informação de sistema, nomeadamente quanto a utilizadores. O sistema NSS ("Name Service Switch"), usa a informação constante no ficheiro /etc/nsswitch.conf para definir para cada tipo de informação, quais as origens a pesquisar e em que ordem.

O NSS permite distinguir os seguintes tipos de informação de sistema: aliases, ethers, group, hosts, netgroup, network, passwd, protocols, publickey, rpc, services e shadow. Para cada um dos tipos de informação podem ser definidas as origens a pesquisar e a ordem que são pesquisadas.

As origens possíveis para a pesquisa são definidas de forma modular, para cada tipo de origem deve ser instalada a biblioteca apropriada, geralmente com designação do tipo libnss_SERVICE.so, onde SERVICE é substituido pela designação do tipo de base da dados que pode posteriormente ser usada no /etc/nsswitch.conf. Alguns exemplos são:

  • libnss_files.so - bases de dados locais (/etc)
  • libnss_compat.so - bases de dados locais ou NIS (compatibilidade com sistemas anteriores)
  • libnss_nis.so - servidores NIS
  • libnss_dns.so - servidores DNS
  • libnss_ldap.so - servidores LDAP (X.500)
  • libnss_winbind.so - servidores Microsoft (NT/2000) - Samba suite

O NSS permite um acesso transparente a diversas fontes de informação de sistema, contudo quando se trata de informaçãao referente a autenticação tudo se complica, no caso do NIS, as passwords são armazenadas exactamente da mesma forma que nas versões locais, mas se queremos generalizar para outros tipos de bases de dados de sistema, certamente que vai ser necessário suportar outros formatos. Recorde-se que mesmo para o NIS foi necessário criar um serviço separado (yppasswdd) para permitir a alteração de passwords.

Para resolver o problema da autenticação com diversos tipos de bases de dados foi criado o conceito de "Pluggable Authentication Module" (PAM), trata-se de um sistema modular que por adição das bibliotecas apropriadas, geralmente residentes no directório /lib/security, permite aos programas usar os diversos sistemas de autenticação. Os ficheiros de configuração residentes no directório /etc/pam.d/ permitem definir para cada aplicação quais os modulos de autenticação a usar, tais como pam_ldap, pam_winbind, etc.

Administração de sistemas de ficheiros

O sistema operativo Unix utiliza uma árvore de directórios única, isto é, no acesso aos ficheiros não existe o conceito de dispositivo de armazenamento (ex.: letras de drive), todos os dispositivos de armazenamemnto são integrados numa única árvore de directórios.

Apesar disso são suportados um grande número de diferentes tipos de sistemas de ficheiros residentes nos mais diversos tipos de dispositivo de armazenamento ou servidores de ficheiros, que são depois integrados numa mesma árvore de directórios.

A operação de integração de sistemas de ficheiros residentes em dispositivos distintos é conseguida à custa do conceito de "montagem".

O sistema de ficheiros integrado começa a ser constituido através da montagem do directório RAIZ, simbolizado por "/", este é sempre o primeiro passo, geralmente o dispositivo que é usado para este efeito é um disco local, mas para máquinas "diskless" também pode ser um directório residente num servidor de ficheiros, ou um disco de RAM.

Uma vez montada a raiz (/) podem ser acrescentados é estrutura outros sistemas de ficheiros residentes em outros dispositivos ou servidores de rede, para o efeito basta que na estrutura que já está montada exista um directório vazio, a montagem consiste na associação do directorio vazio ao dispositivo em questão. Depois de realizada a montagem o ponto inicial do sistema de ficheiros residente no dispositivo/servidor passa a coincidir com o que antes era o directório vazio, isto é o directório deixa de estár vazio e passa a conter a informação que se encontra no dispositivo/servidor.

As montagens são permanentes até que sejam "desfeitas" (desmontagem), ficando disponíveis para todos os utilizadores e aplicações do sistema, estas operações apenas podem ser realizadas pelo administrador (root).

O comando "mount" permite, montar um sistema de ficheiros, a sua sintaxe básica é a seguinte:

mount   dispositivo   ponto-de-montagem

A especificação do dispositivo varia de acordo com o seu tipo, os dispositivos locais estão definidos no directório /dev, por exemplo numa máquina equipada com dois controladores IDE, os discos serão:

  • /dev/hda - disco MASTER do controlador 1 (ou primário)
  • /dev/hdb - disco SLAVE do controlador 1 (ou primário)
  • /dev/hdc - disco MASTER do controlador 2 (ou secundário)
  • /dev/hdd - disco SLAVE do controlador 2 (ou secundário)

A maioria das formatações para os discos exige a definição de partições, mesmo que seja uma única que ocupa todo o disco, as partições sõo identificadas por números inteiros que se acrescentam é identificação do disco, a primeira partição é a 1, a segunda a 2 e assim sucessivamente, deste modo, por exemplo a terceira partição do disco MASTER do controlador secundário é identificada por /dev/hdc3.

Para o caso de controladores de discos SCSI, que ao contrários dos controladores IDE não estão limitados a dois discos, as identificações dos discos são /dev/sda, /dev/sdb, /dev/sdc, ... . Novamente, caso existam partições nos discos, estas serão númeradas e identificadas da mesma forma que foi descrita para os discos IDE. Os drives de disquete são identificados por /dev/fd(n), onde (n) é substituido por um número, o equivalente ao drive A: é /dev/fd0, o drive B: será /dev/fd1.

O comando mount sem argumentos devolve uma listagem das montagens correntes, esta informação é mantida no ficheiro /etc/mtab, o exemplo seguinte mostra um resultado da invocação do comando mount, sem argumentos.

/dev/hda3 on / type ext2 (rw)
proc on /proc type proc (rw)
/dev/hda1 on /boot type ext2 (rw)
/dev/hdb on /cdrom1 type iso9660 (ro)
/dev/hdc1 on /usr/local2 type ext2 (rw)
/dev/fd0 on /disquete type msdos (ro)
//winbox/c on /mnt/doshdd type smbfs (0)
linuxbox:/usr on /usr2 type nfs (rw,addr=192.168.0.2)

A informação apresentada consiste na identificação do dispositivo, ponto de montagem, tipo de sistema de ficheiros e opções de montagem, por exemplo rw=leitura/escrita e ro=leitura-apenas.

Podemos verificar que a raiz do sistema de ficheiros é a terceira partição do disco MASTER do controlador IDE primário, enquanto a primeira partição do mesmo disco se encontra acessivel no directório /boot.

O nome "proc" não corresponde a nenhum dispositivo, é usado pelo núcleo do sistema operativo para guardar diversa informação sobre o seu estado e deve estár sempre montado no directório /proc.

De destacar ainda o /dev/hdb montado no directório /cdrom1, não se trata de um disco, mas sim de um leitor de CD-ROM, o facto de os CD's não terem partições justifica o facto de não existir qualquer numeração na identificação do dispositivo, o tipo de sistema de ficheiros mais comum para os CD-ROM's é o ISO9660, note-se ainda que esta montagem é apenas de leitura (ro). Pode também observar-se que a disquete correspondente ao drive A: está montada no directório /disquete.

As duas últimas linhas apresentadas correspondem a directórios de servidores de rede, nestes casos a forma de definir o dispositivo depende do tipo de servidor, no caso, //winbox/c corresponde a uma partilha com o nome "C", por um PC Windows/98, chamado "WINBOX", o protocolo usado é o SMB (tipo de sistema de ficheiros é "smbfs"), este sistema de ficheiros remoto fica acessível no directório /mnt/doshdd. A última linha corresponde à montagem do directório /usr, exportado por uma máquina chamada "LINUXBOX", usando o protocolo NFS, este sistema de ficheiros remoto fica acessível em /usr2.

O sistema operativo Unix usa intensivamente "caching" nos acessos aos sistemas de ficheiros que estão montados, para termos a certeza de que todas as alterações sobre um sistema de ficheiros são colocadas no dispositivo, este tem de ser desmontado. Para desmontar um sistema de ficheiros usa-se o comando "umount" que recebe como argumento o nome do directório onde o dispositivo está montado. Isto é valido por exemplo para dispositivos amoviveis, especialmente se montados no modo "leitura-escrita", por exemplo para usar uma disquete temos de realizar as operações na seguinte ordem: COLOCAR DISQUETE - MONTAR DISPOSITIVO - UTILIZAR - DESMONTAR DISPOSITIVO - RETIRAR DISQUETE.

Em fases iniciais de desenvolvimento do suporte de alguns tipos de dispositivo, em especial para dispositivos correspondentes a servidores de ficheiros, pode ser necessário recorrer a programas separados para realizar as operações de montagem, posteriormente esse suporte é integrado no sistema e pode ser usado o comando mount. O ficheiro /proc/filesystems contém a lista de tipos de sistemas de ficheiros suportados pelo núcleo do sistema operativo e que por isso podem ser montados com o comando "mount".

Embora os sistemas mais recentes já possuam o suporte de "smbfs" (acesso a servidores MicroSoft) integrado, podendo ser usado o comando mount, em sistemas Linux mais antigos, ou em que o suporte de "smbfs" não foi incluido ao compilar o núcleo do sistema operativo, pode ser necessário usar o comando smbmount. Embora não exemplificado acima, outro tipo de servidor suportado são os servidores Novell Netware, sendo nesse caso o tipo de sistema de ficheiros ncpfs, também neste caso, em versões mais antigas do Linux pode ser necessário recorrer ao programa "ncpmount". Embora existam também equivalentes smbumount e ncpumount, o comando umount permite desmontar qualquer tipo de sistemas de ficheiros.

Quando se realiza uma montagem, com recurso ao comando mount, podemos especificar o tipo de sistema de ficheiros, usando a sintaxe
mount [-t tipo-fs] dispositivo directório-de-montagem, se o tipo é omitido o comando tenta "adivinhar", para isso pode recorrer à forma como "dispositivo" está especificado, ou simplesmente tentar ler do dispositivo essa informação.

Alguns tipos vulgarmente suportados em Linix são:

  • minix - primeiro sistema para o Linux, ainda é usado para disquetes e discos de RAM.
  • ext - versão melhorada do minix, que foi actualmente substituida pelo ext2.
  • ext2 - versão actualmente usada na maioria dos sistemas Linux.
  • hpfs - usado pelo OS/2, em linux apenas é possível o acesso de leitura.
  • msdos - usado pelo MS-DOS e Windows 3.xx.
  • umsdos - sistema com suporte dos atributos necessários ao Unix, implementada sobre uma formatação msdos.
  • vfat - msdos com suporte de nomes longos, usada pelo Windows/95/98.
  • proc - sistema interno, usado como interface com o núcleo do sistema operativo.
  • nfs - acesso por rede a servidores NFS.
  • iso9660 - usado pelos CD-ROM.
  • smbfs - acesso por rede a servidores SMB (Samba; Windows/95/98; Windows NT; Windows 2000; ...)
  • ncpfs - acesso por rede a servidores NCP (Novell; ...)
  • affs- acesso por rede a servidores AMIGA.
  • sysv - usado por outros sistemas operativos tipo Unix.

    Durante o arranque ("boot") de um sistema Unix existe um conjunto de dispositivos que deve ser "montado" no sistema de ficheiros automaticamente. O ficheiro /etc/fstab contém a lista de todos os dispositivos que devem ser montados no arranque da máquina (e devem ser desmontados no encerramento da mesma). Eis um exemplo:

    /dev/hda3       /              ext2            defaults   1   1
    /dev/hda2       swap           swap            defaults   0   0
    /dev/hda1       /boot          ext2            defaults   1   2
    /dev/hdb        /cdrom1        iso9660         ro         0   0
    /dev/hdc1       /usr/local2    ext2            defaults   1   1
    none            /proc          proc            defaults   0   0
    

    A partição /dev/hda2 é usada para SWAP (memória virtual), sendo formatada de forma apropriada para esse efeito. Embora para as partições de SWAP não exista o conceito de montagem porque essas partições não são directamente acessiveis, nem fazem parte do sistema de ficheiros, devem ser activadas durante o arranque e para isso são registadas no ficheiro /etc/fstab.

    Os sistemas de ficheiros em Unix, para serem completamente funcionais, necessitam de um conjunto de caracteristicas importantes em termos de caracterização de cada entrada existente (ficheiro, directório, ... ). Estas caracteristicas (atributos) que devem estár associadas a cada entrada (i-node), algumas das mais importantes e visíveis são:

    • Nomes com até 255 caracteres c/ suporte de qualquer caractere e distinção maiusculas/minusculas.
    • MODO, permissões/flags (16 bits)
    • UID, identificação do propriétário (16 bits)
    • GID, identificação do grupo (16 bits)
    • ATIME, data/hora do último acesso (32 bits)
    • CTIME, data/hora em que foi criado (32 bits)
    • MTIME, data/hora da última modificação (32 bits)

    Nem todos os sistemas de ficheiros suportados pelo Linux obdecem a estas caracteriscas, sendo nessas situaçãoes realizadas adaptações de modo a que as diferenças que transpareçam sejam minimas, por exemplo se o sistema de ficheiros não suporta permissões ou outras propriedades, estes atributos serão definidos de um modo fixo no acto de montagem e o sistema montado aparenta ter esses atributos.

    Cada entrada num sistema de ficheiros Unix possui associada a sí uma identificação de utilizador (UID) e uma identificação de grupo (GID). Quando um utilizador cria uma nova entrada (ex.: ficheiro) o UID desse utilizador fica associado ao ficheiro, bem como o GID do grupo primário desse utilizador. O UID associado a uma entrada indica quem é o proprietário do ficheiro.

    Cada entrada num sistema de ficheiros Unix deve suportar o atributo MODO com capacidade para 16 bits, do bit mais significativo para o menos significativo, eles são usados da seguinte forma:


    • 4 bits usados pelo sistema para definir o tipo de entrada no sistema de ficheiros. Em linux, adoptando a notação decimal os valores usados são:
      • 1 - FIFO (PIPE)
      • 2 - DEVICE (char)
      • 4 - Directório
      • 6 - DEVICE (block)
      • 8 - Ficheiro
      • 10 - Ligação Simbólica
      • 12 - Socket
      Estes quatro bits são manuseados apenas pelo sistema operativo.
    • SETUID - Alteração do UID para ficheiros executáveis.
    • SETGID - Alteração do GID para ficheiros executáveis.
    • STICKY - Utilização especial, depende do tipo de entrada e do tipo de sistema.
    • OWNER READ PERMISSION - Acesso de leitura para o proprietário.
    • OWNER WRITE PERMISSION - Acesso de escrita para o proprietário.
    • OWNER EXECUTE PERMISSION - Autorização de execução para o proprietário.
    • GROUP READ PERMISSION - Acesso de leitura para os membros do grupo.
    • GROUP WRITE PERMISSION - Acesso de escrita para os membros do grupo.
    • GROUP EXECUTE PERMISSION - Autorização de execução para os membros do grupo.
    • OTHERS READ PERMISSION - Acesso de leitura para todos os utilizadores.
    • OTHERS WRITE PERMISSION - Acesso de escrita para todos os utilizadores.
    • OTHERS EXECUTE PERMISSION - Autorização de execução para todos os utilizadores.

    Como foi referido os 4 bits mais significativos são reservados para o sistema e nunca são manuseados directamente, os 3 bits seguintes definem permissões especiais que se abordará mais tarde, seguem-se 3 grupos de 3 bits que definem as permissões para 3 entidades, respectivamente o proprietário da entrada (UID), o grupo associado à entrada (GID) e todos os utilizadores.

    Como se pode observar existem 3 direitos básicos (permissões) LEITURA, ESCRITA e EXECUÇÃO. O significado que estas permissões assumem dependem do tipo de entrada, para os dois tipos mais comuns de entrada no sistema de ficheiros, o significado é o seguinte:

    • FICHEIROS / LEITURA - permite vizualizar o conteudo do ficheiro.
    • FICHEIROS / ESCRITA - permite alterar o conteudo do ficheiro.
    • FICHEIROS / EXECUÇÃO - permite executar o ficheiro, isto é interpretar o seu conteúdo com sendo executável e criar um processo correspondente.
    • DIRECTÓRIOS / LEITURA - permite vizualizar o conteudo do directório (entradas).
    • DIRECTÓRIOS / ESCRITA - permite alterar o conteudo do directório (entradas). Por exemplo remover ficheiros ou alterar o respectivo nome.
    • DIRECTÓRIOS / EXECUÇÃO - permite tornar o directório o directório corrente/de trabalho.

    Para manter a segurança eficaz existem ainda as seguintes restrições:

    • Apenas o proprietário (ou root) pode alterar as permissões.
    • Apenas o administrador (root) pode alterar o proprietário.
    • Apenas o proprietário pode alterar o grupo, mas só se pertencer a esse novo grupo.

    As permissões básicas READ/WRITE/EXECUTE são habitualmente representadas através de um digito que correspondem à representação decimal dos 3 bits, deste modo EXECUTE corresponde ao valor 1 (1º bit), WRITE corresponde ao valor 2 (2º bit) e READ corresponde ao valor 4 (3º bit).

    Exemplos: 7 representa todos os bits com valor 1, ou seja todas as permissõ:es; 4 representa permissão de leitura apenas; 5 representa permissão de execução e de leitura.

    Representando na forma decimal os 3 grupos de permissões, para proprietário, grupo e outros forma-se uma sequencia de 3 digitos. Exemplos:

    • 644 - READ e WRITE para o proprietário, READ para o grupo e READ para outros.
    • 750 - READ, WRITE e EXECUTE para o proprietário, READ e EXECUTE para o grupo e nenhuma permissão para os outros.

    Este tipo de representação é vulgarmente usado no comando "chmod" que permite alterar as permissões sobre uma entrada do sistema de ficheiros.

    A permissões podem facilmente ser visualizadas através do comando "ls" com output longo (ls -l), eis um exemplo de uma listagem deste tipo de um directório /etc:

    total 1318
    -rw-r--r--   1 root     root            9 Dec 10  1999 HOSTNAME
    drwxr-xr-x   2 root     root         1024 Mar 10  2001 SuSEconfig
    -rw-r--r--   1 root     root        40458 Oct  9 18:50 TextConfig
    lrwxrwxrwx   1 root     root           23 Oct 14 01:23 X -> /usr/local/deix/SVGA_16
    -r--r--r--   1 root     root        12758 Jan 28  2000 apsfilterrc
    -rw-------   1 root     root          608 Nov 14 09:41 crontab
    drwxr-xr-x   2 root     root         1024 Oct  9  1999 default
    -rwxr-xr-x   1 root     root          106 Sep 22  2000 hostOff
    -rw-r--r--   1 root     root         3139 Sep 22  2000 hostOff.log
    -rw-r--r--   1 root     root        10137 Nov 16 15:52 hosts
    -rw-------   1 root     root          457 Jul 27 00:04 lilo.conf
    lrwxrwxrwx   1 root     root           28 Mar 14  2001 lmhosts.rpmorig -> /usr/local/samba/lib/lmhosts
    -rw-rw-r--   1 root     root        32768 Oct  9  1999 psdevtab
    -rw-r-----   1 root     shadow        879 Oct 19 11:31 shadow-
    -rw-------   1 root     root          340 Oct 20 12:07 ypgroup
    -rw-r--r--   1 root     root          107 Oct  8  1998 ytalkrc
    lrwxrwxrwx   1 root     root            7 Oct  9  1999 zshrc -> profile
    

    Na coluna da esquerda são representas as permissões/modo, primeira letra indica o tipo de entrada:

    • (-) Ficheiro Normal
    • (d) Directório
    • (l) Ligação simbólica
    • (c) Device (char)
    • (b) Device (block)
    • (p) FIFO (pipe)
    • (s) Socket

    As 9 letras seguintes representam as permissões para proprietário, grupo e outros (3 letras para cada).

    Quando um utilizador cria um ficheiro ou directório, as permissões com que este é criado são definidas através da FILE CREATION MASK, esta máscara está definida no formato décimal acima descrito, nesta máscara devem estar activos os bits que se pretende forçar a zero nos novos ficheiros e directórios.

    Os utilizadores podem alterar a sua mascara de criação de ficheiros, geralmente o valor inicial (definido pelo sistema) é 022, que significa não dar permissão de escrita para o grupo nem para os outros. O valor desta máscara pode ser alterado usando o comando "umask". Alguns sistema Unix podem guardar mascaras individuais para cada utilizador (usando o campo de comentários do /etc/passwd), a maioria dos sistema Linux não o faz e por isso as alterações da mascara têm efeito apenas durante a sessão.

    Quando um utilizador possui direitos de execução sobre um ficheiro, tal significa que se trata de um programa que pode ser transformado num processo em execução. Quando um utilizador transforma um destes ficheiros num processo (invoca o executável) o processo possui sobre o sistema as mesmas permissões do utilizador que o invocou, isso acontece porque os processos ficam com um UID/GID associado correspondentes ao utilizador que os cria.

    Em muitas situações torna-se conveniente dar aos utilizadores permissões especiais, mas apenas para executar determinadas tarefas bem definidas que não comprometam a segurança. Para o conseguir, em Unix, é possível associar a um ficheiro executável o modo SETUID ou SETGID, se o ficheiro executável possúi um destes modos, o processo fica autorizado a alterar respectivamente o seu UID ou GID para os correspondentes aos do ficheiro. Observe-se os exemplos seguintes:

    -rwsr-xr-x   1 root     shadow      34936 Sep 12  1998 /usr/bin/passwd
    -r-sr-sr-x   1 root     root        20704 Sep 12  1998 /usr/bin/lpr
    

    Podemos observar que o programa /usr/bin/passwd tem activo o modo "s" nas permissões de proprietário, logo tem a possibilidade de adquirir o UID de root, e as suas permissões, diz-se que é um programa SETUID ROOT. Na segunda linha está listado o programa /usr/bin/lpr que é SETUID ROOT e SETGID ROOT.

    Os programas SETUID devem ser vistos sempre com desconfiança pois permitem a um utilizador qualquer adquirir as permissões do proprietário. Estas permissões especiais apenas devem ser associadas a programas de inteira confiança e muito bem testados, se eventualmente um utilizador conseguir alterar o comportamento normal de um destes programas as consequencias podem ser extremamente graves. Como medida de segurança adicional, em alguns sistemas, os bits SETUID e SETGID podem ser automaticamente desactivados sempre que se realiza uma operação de escrita sobre o ficheiro.

    Finalmente falta referir a utilização do bit STICKY (representado pela letra "t"), este bit pode ter diferentes significados em diferentes sistemas Unix, por exemplo para directórios o significado mais habitual é impedir a remoção de entradas a outros utilizadores além do proprietário dessas entradas, neste contexto é habitual estár associado aos directórios temporários partilhados, nos quais se pretende que todos os utilizadores possam criar novas entradas, mas não se pretende que uns possam remover/alterar as entradas dos outros:

    drwxrwxrwt   5 root     root         5120 Nov 19 00:01 tmp
    

    Recorde-se que o direito de remover/mover entradas num sistema de ficheiros Unix, não é ditado pelas permissões sobre essas entradas, mas sim pelas permissões sobre o directório onde as entradas se encontram.

    Uma outra utilização comum do STICKY bit é em ficheiros executáveis, para evitar que fiquem bloqueados quando existem processos respectivos em execução, se o STICKY bit está activo, o ficheiro binário é colocado no dispositivo de SWAP para ser usado de forma privada pelo processo em execução. Em alguns sistema apenas o administrador pode activar o STICKY bit.

    Ligações Simbólicas

    De entre os vários tipos de entrada num sistema de ficheiros Unix vulgarmente manuseados directamente pelos utilizadores, além dos ficheiros e directórios, destacam-se ainda as ligações simbólicas. As ligações simbólicas são um conceito simples, mas com enorme utilizade para os utilizadores em geral e muito em especial para o administrador. Trata-se de entradas no sistema de ficheiros que apontam para outra entrada noutro ponto do sistema de ficheiros.

    Na listagem exemplo do directório /etc anteriormente apresentada podem observar-se 3 ligações simbólicas. Para todos os efeitos as propriedadas de uma ligação simbólica são as propriedades do "apontado", tipo de entrada (ficheiro, directório, etc), modo (permissões, etc), UID/GID. A única diferença entre o apontador (ligação simbólica) e o apontado está no nome, que pode ou não ser igual, e na localização.

    Para criar uma ligação simbólica pode ser usado o comando:

    ln -s   {apontado(entrada já existente)}   {apontador(ligação simbólica a criar)}

    As utilizações são as mais diversas. De um modo geral as ligações simbólicas são úteis sempre que pretendemos que algo aparente existir onde não existe ou/e que algo aparente ter um nome que não tem.

    Administração de "Software"

    A instalação de "software" num sistema Unix pode ser realizada por diversas vias, uma das caracteristicas importantes deste tipo de sistema é a possibilidade de as actividades da administraçõo seram realizadas a diversos níveis de acordo com as necessidades particulares e nível de conhecimento do administrador sobre os detalhes de funcionamento considerados de baixo nível.

    Gestores de aplicações instaladas

    Com o progressivo desenvolvimento do sistema operativo Linux começam a ser cada vez mais comum "software" de gestão de aplicações instaladas. Estes programas de gestão do "software" instalado mantêm uma base de dados onde são registados todos os programas que estão instalados no sistema, os ficheiros pelos quais cada um dos programas é composto e ainda as relações de dependendecia entre o diverso "software".

    A sua utilização é extremamente vantajosa e simplifica de forma muito significativa o trabalho do administrador. Remover, actualizar e instalar "software" torna-se muito mais simples. A instalação de um dado "software" com estes sistemas exige desde logo a obtenção de um ficheiro de instalação do "software" apropriado ao gestor em uso. Estes ficheiros de instalação (normalmente designados por "packages"), além dos ficheiros pelos quais é constituida a aplicação, contêm diversa informação quanto a pré-requesitos a serem verificados, tais como o tipo de plataforma exigido e as dependencias que definem que outros "packages" devem estár previamente instalados no sistema.

    As dependências são também importantes no que se refere à remoção ou actualização de "software" já que este tipo de operação pode ter consequencias sobre outro "software" instalado que é dependente do primeiro.

    O sucesso deste tipo de gestores depende em larga medida da sua aceitação geral. Um dos mais conhecidos é o RPM ("Red Hat Package Manager"), incluido em muitas distribuições Linux tais como "Red Hat" ,"Suse", "Mandrake", ... .

    Infelizmente, nem sempre se encontram disponíveis os "packages" que pretendemos, para a nossa plataforma, para facilitar esta tarefa, o RPM pode usar "packages" em formato "source", ou seja "software" sob a forma de código fonte, sem compilar, o RPM pode depois ser usado para proceder à compilação do código fonte, produzindo um "package" binário pronto a instalar.

    Os "packages" em formato de código fonte, no caso do RPM são habitualmente conhecidos por SRC-RPM e a sua grande vantagem é poderem ser usados em qualquer plataforma, constituindo-se como alternativa quando não existe uma versão RPM (pré-compilada) disponível para uma dada plataforma, o seu inconveniente é que para efectuar a compilação (BUILD) é geralmente necessário instalar "software" adicional que não é necessário para usar as versões pré-compiladas.

    Software Comercial

    A maioria do software comercial, por razões obvias, é fornecido sob a forma pré-compilada e geralmente não utilizam os gestores de "software" existentes, em seu lugar disponibilizam um programa de instalação que se encarrega de verificar se a plataforma obdece aos requesitos pré-estabelecidos, estas verificações tentam determinar, por observação do sistema de ficheiros e realização de diversos testes se os pré-requesitos são atingidos. Algum deste "software" pré-compilado, de menor qualidade, pode mesmo não realizar verificações, deixando estas a cargo do administrador. Em certos casos, a instalação pode mesmo ser manual, obrigando o administrador a copiar os ficheiros da aplicação para os locais indicados.

    A utilização destes programas de instalação tem o inconveniente, na maioria dos casos, de não actualizar a base de dados do gestor de "software", logo para o gestor esse "software" não existe no sistema, como consequencia a remoção ou actualização de programas do qual este "software" comercial depende vai ser permitida.

    Software em código fonte

    A maioria do "software" "open-source" encontra-se disponível sob a forma de código fonte simples, geralmente sob a forma de um arquivo em formato TAR, este arquivo contém um directório base dentro do qual se encontra uma árvore de directórios contendo as várias partes do código fonte. O "software" distribuído desta forma, pode em principio, ser instalado em qualquer tipo de sistema Unix, contudo trata-se de um processo um pouco mais moroso que envolve a compilação do código fonte.

    Depois de extraidos os ficheiros do arquivo (para arquivos simples, com extensão [.tar] pode ser usado o comando tar xf, para arquivos comprimidos usando o gzip, geralmente com extensaão [.tgz] ou [.tag.gz], é necessária a opção z) obtem-se um directório de base no qual deve existir um programa de configuração, geralmente com o nome "configure".

    O programa de configuração destina-se a verificar requesitos do sistema e adaptar o código fonte às particularidades do sistema, uma vez executado com sucesso, o "software" encontra-se pronto a ser compilado. O processo de compilação inicia-se com o comando "make" e pode ser algo moroso. Uma vez concluida a compilação com sucesso, geralmente é suportada o comando "make install" que vai copiar os ficheiros binários e outros para os locais apropriados e desta forma instalar a aplicação.

    Embora o processo descrito acima seja quase "standard", nunca deve ser iniciado sem antes ler a documentação que acompanha o código fonte (geralmente ficheiros README ou INSTALL no interior do directório de base).

    Instalação manual de "software"

    Embora a instalação manual de "software" não seja actualmente muito conveniente, o conhecimento dos procedimentos envolvidos é muito importante porque permite ao administrador resolver problemas resultantes de instalações deficientes.

    Em Unix para a instalação de aplicações é usado um conjunto de nomes de directório "standard" que é obrigatório conhecer, cada um destes directórios tem uma finalidade a respeitar:

    • bin - destina-se a armazenar ficheiros executáveis (transformáveis em processos) por todos os utilizadores.
    • sbin - destina-se a armazenar ficheiros executáveis (transformáveis em processos), mas não se pretende que sejam usados vulgarmente pelos utilizadores, destinam-se ao administrador e ao sistema.
    • lib - contém bibliotecas dinâmicas que são carregadas pelos programas de acordo com as suas necessidades. Também pode ser usado para guardar ficheiros de configuração e mesmo de dados.
    • etc - contém ficheiros de configuração das aplicações.
    • var - contém ficheiros de dados das aplicações.
    • man - contém manuais de utilização e configuração das aplicações, em formato apropriado ao programa man.
    • info - contém manuais de utilização e configuração das aplicações, em formato apropriado ao programa info.

    Este conjunto de directórios (ou parte deles) pode existir em vários pontos do sistema de ficheiros, esses pontos são o directório de base de instalação da aplicação, a instalação consiste basicamente na cópia de ficheiros para os subdirectórios apropriados do directório base:

    • / (raiz) - os directórios da raiz são usados pelo "software" de base do sistema, as aplicações instaladas posteriormente não utilizam normalmente estes directórios, as excepções são os directórios /etc e /var que são usados por algumas aplicações para armazenar resepectivamente ficheiros de configuração e ficheiros de dados.
    • /usr - este directório é muito utilizado como base de instalação para muitas aplicações, sendo por isso os respectivos executáveis colocados em /usr/bin e as bibliotecas em /usr/lib, os ficheiros de configuração deveriam ser colocados em /usr/etc, mas isso nem sempre acontece e por vezes é usado o directório /etc, o mesmo se passando para os dados relativamente ao directório var.
    • /usr/local - esta é outra base de instalação muito usada, aplicando-se também o que foi dito para o directório de base /usr.
    • Directórios exclusivos - uma aplicação também pode ser instalada num directório de base próprio, criado exclusivamente para a aplicação. Os locais mais habituais para estes directórios serem criados são /opt /usr/local e /usr/lib.

    Muitas aplicações também criam ficheiros de configuração/dados nos directórios dos utilizadores, quando estes usam as aplicações pela primeira vez, isto permite uma personalização da configuração individual para cada utilizador.

    A aplicação, uma vez instalada num dado directório base vai usar esse directório como base para encontrar os ficheiros de que necessita, nomeadamente de dados e de configuração. Se a aplicação sabe desde logo onde procurar os seus ficheiros, o mesmo não se pode dizer do sistema operativo. Neste aspecto existem 3 situações onde a interacção entre a aplicação e o sistema operativo pode ser afectada:

    • Pesquisa de ficheiros executáveis

      Para criar um novo programa em execução é necessário criar um novo processo (fork) e de seguida usar uma função "exec" para substituir o nove processo por um ficheiro binário. Para usar a função "exec", ou é especificado o caminho completo até ao ficheiro binário, ou então usa-se uma das funções "exec" que pesquisam a variável de ambiente PATH (exec?p). Este processo é normalmente levado a cabo pela "shell" do utilizador.

      Quando um comando é invocado é normalmente pesquisada a variável PATH que contém uma sequência de directórios onde se pode encontrar ficheiros binários, um habitual para esta variável é "/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin". O conteúdo desta variável pode ser facilmente alterado pelo administrador através dos ficheiros /etc/profile, para a "shell" normal (sh/bash) e dos ficheiros /etc/csh.cshrc e /etc/csh.login, para a csh/tcsh. Deste modo quando se instala um novo programa, cujo executável não se encontra nos directórios habituais da variável PATH, basta editar estes ficheiros de configuração para adicionar o novo directório, onde se encontra o ficheiro executável, por exemplo "/usr/local/netscape/".

      O problema é que as variaveis de ambiente podem ser alteradas pelo utilizador, por outro lado a variável PATH tende a crescer rápidamente com o aumento das aplicações instaladas. Uma alternativa, viável quando o directório contém um número reduzido de executáveis é criar uma ligação simbólica num directório que está na PATH, por exemplo "ln -s   /usr/local/netscape/netscape   /usr/local/bin/netscape".

    • Carregamento de bibliotecas ligadas dinamicamente

      A maioria dos programas compilados são incompletos, durante a operação de compilação a inserção de código contido em bibliotecas (linking) não é realizada, em seu lugar a, durante a execução do programa, as bibliotecas são carregadas em memória e usadas pelo programa. Este processo é conhecido por "dynamic linking" e é usado intensivamente nos sistemas operativos modernos como o MS-Windows, com as DLL, ou o Linux com as bibliotecas partilhadas ("Shared Libraries"), as bibliotecas partilhadas devem estár disponíveis para os programas quando estes são executados. O programa "ldd" permite saber a que bibliotecas está dinamicamente ligado um dado executável ligado, no exemplo seguinte pode ver-se o resultado dessa verificação sobre o executável /usr/local/netscape/netscape num dado sistema:

      ldd /usr/local/netscape/netscape
      	libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x4000c000)
      	libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x4004e000)
      	libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x40057000)
      	libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x4006c000)
      	libXpm.so.4 => /usr/X11R6/lib/libXpm.so.4 (0x4007e000)
      	libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x4008c000)
      	libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40097000)
      	libdl.so.1 => /lib/libdl.so.1 (0x40137000)
      	libc.so.5 => /lib/libc.so.5 (0x4013a000)
      	libg++.so.27 => /usr/lib/libg++.so.27 (0x401f6000)
      	libstdc++.so.27 => /usr/lib/libstdc++.so.27 (0x4022e000)
      	libm.so.5 => /lib/libm.so.5 (0x4025f000)
      

      Do lado esquerdo pode observar-se os nomes das bibliotecas de que o programa necessita e do lado direito, onde foram encontradas no sistema de ficheiros. Como se pode observar os nomes destas bibliotecas são geralmente da forma [libNOME.so.NUMERO] quando usado, o número indica a versão da biblioteca. Por exemplo a biblioteca X11 encontra-se no directório /usr/X11R6/lib:

      -rw-r--r--   1 root     root      1085674 Jan 31  2001 /usr/X11R6/lib/libX11.a
      lrwxrwxrwx   1 root     root           13 Nov 30 15:43 /usr/X11R6/lib/libX11.so -> libX11.so.6.1
      lrwxrwxrwx   1 root     root           13 Feb 22  2001 /usr/X11R6/lib/libX11.so.6 -> libX11.so.6.1
      -rwxr-xr-x   1 root     root       663320 Jan 31  2001 /usr/X11R6/lib/libX11.so.6.1
      

      No caso podemos observar a existência de 4 entradas com a designação libX11, a entrada com extensõo .a destina-se a ser usada durante a compilação de programas ("static linking"), no final encontra-se a versão partilhada que será carregada pelo "netscape", embora o netscape deseje a versão 6, vai receber a versão 6.1, isso é conseguido usando uma ligação simbólica. As bibliotecas possuem normalmente dois números de versão, o primeiro ("major") é o mais significativo, sendo mantida a compatibilidade dentro de todas as sub-versões, por isso os programas são normalmente ligados apenas ao número de versão mais significativo.

      A forma como as bibliotecas são procuradas é ligeiramente mais complexa do que o que acontece para os executáveis, as bibliotecas partilhadas são procuradas na seguinte ordem:

      1. Nos directórios definidos na variável de ambiente LD_LIBRARY_PATH, por razões de segurança obvias (...) para os programas SETUID/SETGID isto é ignorado.
      2. Na lista de bibliotecas contida no ficheiro /etc/ld.so.cache
      3. No directório /usr/lib
      4. No directório /lib

      A lista de bibliotecas definida no ficheiro ld.so.cache não é manualmente editável porque não é um ficheiro de texto este ficheiro é usado pelo sistema para manter informação sobre as bibliotecas partilhadas que vão sendo usadas de forma a acelerar o processo de carregamento em futuras utilizações. A actualização deste ficheiro pode ser forçada com o comando "ldconfig". O comando ldconfig procura bibliotecas dinâmicas nos seguintes directórios:

      • lista de directórios especificados na linha de comando (opcional)
      • lista de directórios contidos no ficheiro /etc/ld.so.conf (um directório por linha)
      • directórios /lib e /usr/lib

      Além de actualizar a cache de bibliotecas que acelera o carregamento destas, o ldconfig também se encarrega de actualizar/corrigir as ligações simbólicas de acordo com os números de versão disponíveis. O programa "ldconfig" deve ser sempre invocado durante o arranque da máquina.

      Quando se instala um programa que contém bibliotecas partilhadas, estas terão de estar acessiveis para o programa poder funcionar, se a base de instalação é o directório /usr, não existe qualquer problema, igualmente, se a base é /usr/local tal não apresenta grande problema porque o directório /usr/local/lib é um dos que está normalmente registado no ficheiro /etc/ld.so.conf, por isso basta executar o comando "ldconfig" para actualizar a "cache".

      Se o programa se instala num directório particular, por exemplo /usr/local/kde, a melhor solução é adicionar o directório que contém as respectivas bibliotecas ao ficheiro /etc/ld.so.conf e de seguida actualizar a "cache" com o comando ldconfig.

    • Pesquisa de manuais pelos comandos do sistema (ex.: man, info)

      O comando "man" utiliza procedimentos semelhantes aos usados para as bibliotecas dinâmicas, o sistema mantém uma "cache" das localização das páginas dos manuais usadas recentemente, o comando "mandb" actualiza essa informação em moldes semelhantes aos do comando "ldconfig", a lista de directórios a pesquisar está definida no ficheiro /etc/man_db.config, além disso o comando "man" também procura os manuais nos directórios definidos na variável de ambiente "MANPATH". O comando "manpath" pode ser usado pelos utilizadores para definir a variável PATH de acordo com a informação existente no ficheiro /etc/man_db.conf.

      O comando "info" (e também o emacs) utiliza as variáveis de ambiente INFOPATH e INFODIR para procurar os documentos tipo "info", normalmente estas variáveis devem conter "/usr/info:/usr/local/info". Para estes documentos não existe "cache", quando um programa não tem como base de instalação /usr ou /usr/local pode ser necessário adicionar o novo directório às variáveis de ambiente, para isso será necessário editar os ficheiros /etc/profile e /etc/csh.cshrc.

    Administração de Serviços

    Os serviços de um sistema são um conjunto de meios que permitem um acesso organizado aos recursos, a maioria dos serviços destinam-se a acesso externo (via rede) o acesso interno (apartir da "shell") é muito mais directo e simples (acesso ao sistema de ficheiros, execução de comandos, ...) pelo que normalmente não é necessário recorrer a este conceito.

    Um serviço de rede, que pretende facultar acesso a determinados recursos partindo do exterior do sistema tem de se preocupar com várias questões, tais como tipo de protocolo de comunicação usado, autenticação de utilizadores e filtragem de origens dos pedidos.

    Os serviços de rede usam protocolos de rede para transporte de dados, em Unix os protocolos de eleição são o TCP e o UDP que por sua vez usam o IP ("Internet Protocol"), mas especialmente quando se fala de Linux existe um grande número de protocolos suportados, tais como o IPX ou o Appletalk. Os serviços locais utilizam mecanismos internos de comunicação (IPC) tais como "Sockets Unix", "Filas de Mensagens", "Pipes" (FIFOs) e memória partilhada.

    Embora o Unix, e em particular o Linux, suportem outros protocolos de rede/transporte, existe uma clara ligação entre o Unix e a pilha TCP/IP, tal deve-se ao facto de o Unix ter sido a plataforma usada para o desenvolvimento do TPC/IP. Por sua vez o TCP/IP foi sempre a pilha mais usada pelo Unix, muitas implementações Unix apenas suportam TCP/IP e praticamente todos os sistemas operativos Unix suportam TCP/IP.

    Os serviços são quase todos implementados segundo o modelo "Cliente-Servidor", neste modelo o servidor é uma aplicação passiva que aguarda o contacto de um cliente, quando tal acontece "acorda" e presta o serviço pedido. O suporte de multiplas comunicações independentes com processos no interior de uma dada máquina é assegurado através da multiplexagem da interface-de-rede/endereço-de-máquina através dos números de porto ou porta ("port number").

    Consultar o documento Redes, endereços, nomes e serviços - introdução.

    Na pilha TCP/IP existem dois protocolos disponíveis para a implementação de serviços, o UDP e o TCP:

    • UDP - O "User Datagram Protocol" é um protocolo sem ligação que se destina à troca de blocos isolados de informação, é um protocolo não fiável, isto é não se garante que os dados chegam ao destino e só em algumas situações é que o emissor tem conhecimento de que os dados não chegaram ao destino. Dadas estas caracteristicas o UDP apenas é adquado a serviços simples, sem sessão/ligação, com volumes muito reduzidos de dados e sem grandes exigencias de fiabilidade.
    • TCP - O "Transmission Control Protocol" é um protocolo fiável com controlo de fluxo e erros, com ligação, uma vez estabelecida a ligação as comunicações entre os dois processos envolvidos funcionam sobre um canal lógico dedicado, não acessível a outros processos. O TCP é o protocolo escolhido sempre que o serviço implica a definição de uma sessão/ligação. Mesmo que o serviço não implique o estabelecimento de ligação/sessão, se os volumes de dados são elevados o UDP coloca dificuldades e deverá optar-se pelo TCP.

    Uma das caracteristicas que um serviço deve ter é estar permanentemente disponível, independentemente do número de clientes que estãao a ser atendidos. A implementação das aplicações servidoras tem de atender a este aspecto e às caracteristicas do protocolo usado:

    • Servidores UDP - para cada porta de destino (serviço), com o protocolo UDP apenas é possível distinguir um processo servidor de destino no interior da máquina, isso significa que um único processo servidor vai ter de atender todos os clientes. Este facto introduz limitações no serviço porque o servidor deverá ser do tipo sem-estado ("stateless"), ou seja cada pedido deve ser autonomo e não depender de outros pedidos anteriores.

      Esta limitação é muito importante porque para usar UDP com serviços onde existe o conceito de sessão essa funcionalidade terá de ser totalmente implementada nas aplicações servidora e cliente e o servidor torna-se extremamente complexo porque tem de manter multiplas sessões de diversos clientes num único processo. Mais importante ainda esta limitação dificulta a transferência de grandes quantidades de dados, se a quantidade de dados é superior à permitida para um "datagrama" UDP, terão de ser usados vários "datagramas", mas estes terão de constituir pedidos totalmente independentes. A disponibilidade permanente do serviço é aparente, enquanto o servidor está a atender um cliente, outros pedidos, de outros clientes são armazenados em fila de espera ("buffer"), quando o servidor acaba de processar um pedido lê o seguinte do "buffer".

      Por estas razões o UDP apenas é normalmente usado para serviços muito simples que consistem no envio de apenas um pedido e recepção de uma resposta, ambos de reduzida dimensão. Um exemplo não típico é o serviço TFTP ("Trivial File Transfer Protocol") que é um serviço de acesso a ficheiros, normalmente em modo de leitura-apenas que é muito usado para o arranque de postos de trabalho sem disco. O TFTP usa o protocolo UDP, para o conseguir, os ficheiros são divididos em blocos 512 bytes (para "caberem" num "datagrama" UDP), o cliente envia pedidos isolados ao servidor contendo o nome do ficheiro e número do bloco pretendido, todo o controlo fica a cargo do cliente, por exemplo se um bloco não é recebido o cliente terá de efectuar novamente o pedido.

    • Servidores TCP - o protocolo TCP é muito mais elaborado, com o TCP é possível distinguir vários processos servidores de destino no interior da máquina, essa distinção baseia-se no porto/endereço-de-origem dos dados. Quando um processo servidor TCP recebe um pedido de ligação de um cliente gera-se um novo descritor que representa a ligação estabelecida, neste descritor todos os dados recebidos vem do cliente ligado e todos os dados emitidos serão recebidos apenas pelo cliente ligado, esta caracteristica permite definir este protocolo como sendo do tipo "com-ligação", os dados não são enviados em blocos como no UDP, mas sim em fluxo contínuo. Além deste aspecto o TCP é fiável porque implementa mecanismos de controlo de fluxo e erros baseado no protocolo de janela deslizante orientado a caractere.

      Estas caracteristicas do protocolo TCP tornam muito simples a implementação de serviços com sessão, quando o processo servidor recebe um pedido de ligação gera-se um novo descritor ligado ao novo cliente, neste momento o servidor cria um novo processo ("fork") que usa apenas o novo descritor para atender em exclusivo o novo cliente, o processo pai continua a atender pedidos de ligação. O tempo de indisponibilidade do serviço é muito menor, limitando-se ao tempo necessário para criar um novo processo.

      Em TCP a questão da quantidade de dados a transferir não se coloca porque os dados são transmitidos em fluxo continuo, sem qualquer espécie de limitação.

    Podemos então considerar dois tipos de servidor básico, os servidores UPD asseguram serviços simples sem ligação, são constituidos por um único processo que atende todos os pedidos de todos os clientes, quando existe um grande número de clientes, o tempo de resposta é afectado segundo o modelo das filas de espera M/D/1.

    Os servidores TCP proporcionam serviços fiáveis, com ligação, o servidor TCP é constituido por um processo que recebe os pedidos de ligação dos clientes, quando recebe um pedido cria um novo processo que trabalha em exclusivo para o novo cliente, os tempos de resposta sob pressão de um grande número clientes não são significativos porque existem processos servidores dedicados a cada cliente. Para serviços simples, os servidores UDP são mais eficientes em tempo de resposta porque não necessitam de criar um novo processo.

    Os sistemas tipo Unix são adequados a muitas finalidade, mas a sua eficiência e fiabilidade tornaram-nos a primeira escolha como plataforma para a implementação de serviços. Os serviços devem estár disponíveis imediatamente depois do arranque do sistema, os processos servidores são criados apartir dos "scripts" de boot de sistema, de acordo como o que está definido no ficheiro /etc/inittab, geralmente estes "scripts" encontram-se dentro do directório /sbin/init.d/, o exemplo seguinte mostra parte do ficheiro /sbin/init.d/apache :

    case "$1" in
        start)
    	if test -x /usr/sbin/httpd ; then
    	echo "Starting WWW-Server apache."
        	/usr/sbin/httpd -f /etc/httpd/httpd.conf 
    	fi
        ;;
        stop)
        if [ -f  /var/run/httpd.pid ] ; then
           echo -n "Shutting down Apache HTTP server"
           kill `cat /var/run/httpd.pid`
           rm -f /var/run/httpd.pid
        else 
           echo -n "Apache not running?"
        fi
    	echo
        ;;
        restart)
            if [ -f  /var/run/httpd.pid ] ; then
               echo -n "Reload Apache configuration"
               kill -1 `cat /var/run/httpd.pid`
            else
               echo -n "Apache not running?"
           fi
    	    echo
        ;;
        *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
    esac
    

    Este script é automaticamente executado durante o arranque do sistema, com o argumento "start", pode observar-se que o processo servidor é criado por invocação do binário /usr/sbin/httpd que trata de criar o processo servidor.

    O "Internet Super-Server" (inetd)

    É comum um sistema Unix prestar dezenas ou centenas de serviços distintos, em principio seria necessário ter em execução outros tantos processos servidores. Embora um processo servidor não apresente grande consumo de capacidade de processamento quando não está a atender clientes, usa alguma memória central, e mesmo que tal não seja muito significativo pode considerar-se um despedicio de recursos porque são processos que até existir algum cliente "não fazem nada".

    O "Internet Super-Server" (inetd) resolve esta situação, a ideia é ter um único processo que assegure o atendimento de todos os diversos tipos de serviço necessários no sistema. É claro que o "inetd" não possui as funcionalidades dos diversos tipos de serviço, para isso recorre a programas externos. O "inetd" limita-se a escutar as várias portas de serviço, quando chega um pedido "passa a batata quente" a um programa externo específico para esse serviço.

    O programa "inetd" consulta o ficheiro de configuração /etc/inetd.conf, neste ficheiro encontram-se definidos os serviços que devem ser assegurados pelo "inetd", um serviço por linha, cada linha contém os seguintes campos separados por espaços:

    • Nome do serviço - representa na realidade o número de porto, o "Nome de serviço" deve estar definido no ficheiro /etc/services.
    • Tipo de serviço - define o tipo de serviço, este valor está directamente relacionado com o protocolo e corresponde aos valores estabelecidos para a "system-call" "socket". Os valores mais usados são "stream" para serviços TCP com ligação ou o valor "dgram" para o serviço de "datagramas" UDP.
    • Protocolo - trata-se da designação do protocolo usado, estes nomes estão registados no ficheiro /etc/protocols, os valores mais usados são "tcp" e "udp".
    • Modo - este campo pode ter os valores "wait" ou "nowait", está relacionado com o funcionamento interno do "inetd" que será abordado a seguir.
    • Nome de Utilizador - identifica o nome do utilizador com que o serviço será prestado (executado), normalmente é "root", mas para serviços que não necessitam de acessos especiais ao sistema pode ser usado um nome de utilizador sem direitos especiais tal como "nobody". O nome de utilizador pode ser seguido de um nome de grupo (separado por um ponto).
    • Programa servidor e argumentos - trata-se do nome do programa que o "inetd" invocará para prestar o serviço, este campo é constiuido por uma sequência de argumentos em formato apropriado para a função "execl", ou seja o nome do executável com o caminho completo até ele, novamente o nome do executável, e depois os argumentos.

    O exemplo seguinte apresenta um extracto de um ficheiro /etc/inetd.conf:

    echo	dgram	udp	wait		root	internal
    daytime	dgram	udp	wait		root	internal
    time	stream	tcp	nowait		root	internal
    ftp	stream	tcp	nowait		root	/usr/sbin/tcpd		in.ftpd
    telnet	stream  tcp     nowait  	root    /usr/sbin/tcpd		in.telnetd
    smtp	stream  tcp     nowait  	root    /usr/sbin/sendmail	sendmail -bs
    shell	stream	tcp	nowait		root	/usr/sbin/tcpd		in.rshd -L
    pop3	stream	tcp	nowait		root	/usr/sbin/popper	popper -s
    tftp    dgram   udp     wait.400   	root    /usr/sbin/tcpd          in.tftpd /tftpboot
    bootps	dgram	udp	wait		root	/usr/sbin/bootpd	bootpd -d4 -c /usr/local2/tftpboot
    finger	stream	tcp	nowait		nobody	/usr/local/libexec/in.xfingerd	in.xfingerd -b dc=pt
    systat	stream	tcp	nowait		nobody	/bin/ps			ps -auwwx
    netstat	stream	tcp	nowait		root	/bin/netstat		netstat -a
    
    netbios-ssn	stream	tcp	nowait	root	/usr/sbin/smbd  smbd -s /etc/smb.conf
    netbios-ns	dgram	udp	wait	root	/usr/sbin/nmbd  nmbd
    # End.
    

    O "inetd" assegura alguns serviços básicos sem recurso a programas externos, nesses casos (3 primeiras linhas do exemplo) usa-se a palavra "internal" em lugar do nome do executável externo. O programa "tcpd" é um auxiliar que realiza algumas validações da proveniencia dos pedidos e será abordado adiante. O funcionamento do "inetd" pode ser descrito do seguinte modo:

    1. O ficheiro de configuração /etc/inetd.conf é lido, o ficheiro é lido novamente sempre que o processo "inetd" recebe o sinal "HUP".
    2. São abertos os "sockets" apropriados a cada serviço e associados ao respectivo número de porto.
    3. É utilizada a "system-call" "select" para saber se chegou um "datagrama" (dgram/udp) ou um pedido de ligação (stream/tcp) em qualquer dos portos de serviço.
    4. Quando chegam dados, é criado um novo processo, no novo processo:
      1. o UID/GID é alterado para corresponder ao que está definido para esse serviço.
      2. os descritores "standard" de entrada e saída de dados são fechados (close(0);close(1);) e o "socket" é duplicado (dup2) para esses descritores.
      3. é usada a função "execl" para substitui o processo pelo executável, tal como está especificado para esse serviço.
    5. No processo original (inetd) a "system-call" "select" é novamente invocada para detectar novos pedidos nos "sockets". Se o serviço está definido como sendo em modo "nowait", então o "socket" correspondente ao serviço também vai ser monitorizado, se o modo é "wait" o "socket" fica suspenso e não é monitorizado. Neste último caso o "socket" só volta a ser monitorizado quando o processo que foi criado para atender o pedido anterior terminar.

    Os serviços com ligação (stream/tcp) podem ser sempre do tipo "nowait" porque para cada cliente é criado um "socket" independente ("system-call" "accept"), assim o "inetd" pode atender imediatamente novos pedidos para esse serviço. Pelo contrário, para os serviços sem ligação deverá ser sempre usado o modo "wait" porque só existe um "socket" e consequentemente não podem existir dois processo a usa-lo, apenas quando o novo processo termina é possível o "inetd" voltar a receber pedidos desse serviço. Por esta razão os servidores UDP devem ter tempos de execução o mais curtos possíveis, além disso se um destes servidores "encrava", o serviço fica bloqueado.

    Imediatamente a seguir ao modo wait/nowait pode ser colocado um número, separado por um ponto que indica o número máximo de processos que podem ser criados por minuto para atender o serviço, se nada for indicado o valor usado pelo "inetd" é normalmente de 40.

    Os servidores executáveis, invocados pelo "inetd" para prestar os serviços utilizam a entrada "standard" para receber dados do cliente (STDIN/Descritor 0) e a saída "standard" para enviar dados ao cliente (STDOUT/Descritor 1). Isto significa que os servidores invocados pelo "inetd" não necessitam de ser aplicações especificamente desenvolvidas para trabalhar em rede, no exemplo acima pode observar-se que as linhas correspondentes aos serviços "systat" e "netstat" utilizam comandos habitualmente usados na "shell", por exemplo, quando o comando "ps" é invocado escreve o seu resultado no descritor 1, como o "inetd" duplicou o descritor do "sochet" de rede para o descritor 1, o resultado é enviado ao cliente, no caso através de um "datagrama" UDP.

    O "xinetd" é uma versão melhorada do "inetd", utiliza o ficheiro de configuração /etc/xinetd.conf, mas pode ser realizada a inclusão de outros ficheiros de configuração, geralmente usa-se um directório /etc/xinetd.d/ para esse efeito, o "xinetd" é semelhante ao "inetd", o formato dos ficheiros de configuração é diferente, mas o conteúdo essencialmente o mesmo, ao contrário do "inetd", o "xinetd" permite filtrar os endereços de origem dos pedidos, para se conseguir isso com o "inetd" é necessário recorrer a um programa auxiliar, o "tcpd".

    Os sistemas Linux possuem uma biblioteca para implementação de filtragem de pedidos, essa biblioteca "libwrap.a" ("Access Control Library) define funções para realizar diversos tipos de validação, a validação (para cada serviço) pode basear-se em "nome do cliente", "endereço do cliente", "nome do utilizador", "nome do processo servidor", "nome do servidor", "endereço do servidor" e utiliza dois ficheiros de configuração: /etc/hosts.allow e /etc/hosts.deny. Estes ficheiros usam mascaras para identificar os clientes. Primeiro é verificado se o cliente se ajusta a alguma definição no /etc/hosts.allow, se isso acontecer o acesso é imediatamente autorizado. Se não, então será verificado se o cliente está abrangido pelo /etc/hosts.deny, se isso acontece o acesso é negado, caso contrário é autorizado.

    O programa "tcpd" ("TCP/IP Daemon Wrapper Program") destina-se a servir de intermediário entre o "inetd" e servidores que não suportam esta biblioteca de controlo de acesso. O "inetd" invoca o "tcpd" em lugar do servidor, o "tcpd" determina o número de porto/serviço a que estão associados os descritores (0/1) ("system-call" "getsockname") e valida o acesso usando a "libwrap", se o acesso é válido utiliza uma função "exec" para se substituir pelo verdadeiro servidor. Como se pode observar no exemplo anterior, o "tcpd" não necessita de uma especificação do executável servidor ao estilo função "exec", basta o nome do executável e os respectivos argumentos, o "tcpd" permite que o nome do executável seja especificado sem caminho, nesse caso o executável será procurado num directório pré-definido, normalmente /usr/bin/.

    Em termos de validação de acessos, a utilização do "xinetd" é vantajosa porque apesar de não ter tantas possibilidades de configuração como a "libwrap" usada pelo "tcpd" garante uma negação de acesso mais directa. A combinação "inetd/tcpd" obriga a criar um novo processo mesmo que depois o cliente não seja autorizado. Isso pode facilitar ataques de negação de serviço (saturação de pedidos).

    Confiança entre sistemas Unix

    A relação de confiança entre certos servidores é um conceito actualmente suportado por quase todos os sistemas operativos com pretenções a servirem de plataforma a servidores. Estas relações de confiança, geralmente definidas entre sistemas com administração comum visam aumentar a cooperação entre servidores, permitindo uma melhor distribuíção dos serviços e facilitando a administração. No limite o conjunto de servidores cooperantes pode funcionar como um todo e apresentar neste ponto de vista capacidade impossíveis de atingir com um único sistema.

    A cooperação entre sistemas envolve a existência de comunicações entre eles, na maioria dos casos sob a forma de prestação de serviços, o problema é que grande parte destes serviços são sensiveis sob o ponto de vista de segurança e por isso é necessário utilizar mecanismos de autenticação que tornam as operações mais pesadas.

    Os sistemas Unix utilizam um mecanismo muito simples que dispensa a utilização de processos pesados de autenticação, este mecanismo baseia-se apenas nos protocolos de comunicação e aproveita o facto de apenas o administrador poder usar portos UDP/TCP com valores inferiores a 1024, conhecidos normalmente por "portos reservados".

    No sistema que presta o serviço (servidor) definem-se estaticamente, os endereços de rede (IP) dos clientes de confiança, quando o servidor recebe um pedido consulta esta informação e compara o endereço de origem para saber se o cliente é de confiança. Em sistemas multi-utilizador esta verificação é insuficiente, é necessário saber se foi o utilizador "root" que emitiu o pedido, para isso o cliente tem de usar um porto inferior a 1024, assim o servidor além de verificar se o endereço de origem corresponde a uma máquina de confiança tem também de verificar se o porto de origem é inferior a 1024, nessas condiçõo o servidor sabe que o pedido provém do utilizador "root" na "máquina de confiança".

    Por ser extremamente simples este mecanismo é muito eficiênte, mas baseia toda a validação no endereço de origem o que pode não ser totalmente seguro.

    Este mecanismo é usado por vários serviços tais como "Remote Shell/Remote Copy" (rcp/rsh/rshd), "Remote Login" (rlogin/rlogind) e "Line Printer" (lpr/.../lpd), todos estes servidores usam o ficheiro de configuração /etc/hosts.equiv onde se encontram definidos os nomes/endereços dos "clientes de confiança". Muitos destes comandos destinam-se a ser invocados directamente pelo utilizidor, para conseguirem abrir um porto reservado (<1024) são SETUID "root".

    Uma outra aplicação importante do conceito de "sistema de confiança" é no NFS ("Network File System"), este sistema de servidores de ficheiros foi desenvolvido especificamente no contexto Unix e é radicalmente diferente dos outros servidores de ficheiros mais comuns.

    Enquanto os servidores de ficheiros mais conhecidos como Windows (SMB) e NetWare (NCP) baseiam este tipo de serviço no estabelecimento prévio de uma sessão de utilizador (geralmente autenticada por "username/password"), os servidores NFS disponibilizam ficheiros a máquinas clientes e não a utilizadores em particular. A configuração de um servidor NFS (mountd/nfsd) baseia-se no ficheiro /etc/exports, neste ficheiro são definidos os directórios a exportar (sub-directórios automaticamente incluidos) e uma lista de clientes (máquinas/endereços) que podem usar cada um dos directórios, para este efeito os clientes referênciados aqui são considerados de confiança. Para cada cliente é possível ainda especificar diversas opções relativas ao modo como o directório é exportado, o extracto seguinte apresenta um ficheiro /etc/exports:

    # This file contains a list of all directories exported to other computers.
    # It is used by rpc.nfsd and rpc.mountd.
    /tftpboot/192.168.0.1	linuxbox(rw,no_root_squash)
    /usr/local		*(ro) newhost(rw)
    /cdrom1			*(ro)
    

    Neste exemplo pode observar-se que os directórios /usr/local e /cdrom1 são exportados para todos os clientes (*), em modo de leitura apenas (ro), sendo um acesso apenas de leitura e não sendo a informação confidencial, permite-se deste modo um acesso público a estes directíorios. O cliente "newhost" tem no entanto acesso de escrita (rw) ao directório /usr/local.

    O directório /tftpboot/192.168.0.1 é exportado em modo "read-write" para o cliente "linuxbox", é usada ainda a opcão "no_root_squash". Os pedidos envidos ao servidor NFS transportam sempre o UID/GID do utilizador que os desencadeou no cliente, no servidor esse UID/GID é usado no acesso ao directório local, por esta razão é conveniente que os UID/GID sejam os mesmos no cliente e no servidor, para isso basta centralizar a base de dados de utilizadores, por exemplo recorrendo a um servidor NIS.

    A utilização no servidor NFS do UID na máquina cliente tem uma excepção, por razões de segurança quando o servidor NFS recebe um pedido do UID=0 (root) não usa esse UID no servidor, em seu lugar usa o utilizador "nobody", esta medida de segurança pode ser desactivada usando a opção "no_root_squash", tal como se pode observar no exemplo acima. O operação se alteração de UID entre cliente e servidor é conhecida por "squashing" e sendo automática para o UID=0 pode ser forçada para outros UIDs.

    O servidor NFS apenas aceita pedidos provenientes de portas reservadas (<1024), o cliente NFS está integrado no núclo do sistema operativo da máquina cliente, o acesso ao servidor estabelecido pelo administrador usando o comando "mount", geralmente é colocada uma entrada no /etc/fstab para que seja realizado durante o arranque do sistema.

    Na máquina cliente, a forma como os utilizadores acedem ao sistema de ficheiros é de total responsabilidade da administração local, uma vez montado, o directório remoto torna-se acessível localmente como qualquer outro sistema de ficheiros.

    Uma das grandes vantagens dos servidores NFS é que não têm estado ("stateless"), apenas facultam operações deleitura e escrita, não disponibilizando as operações de abertura e encerramento do ficheiro, por esta razaão se um servidor NFS é reinicializado, os clientes não perdem informação, apenas existe uma indisponibilidade temporária.

    Segurança da confiança baseada em endereços

    O mecanismo de confiança entre máquinas baseado nos endereços de origem dos pedidos tem a grande vantagem de ser muito ligeiro e logo muito eficiênte sob o ponto de vista de performance, contudo a sua aplicação deve ter em consideração que se um intruso conseguir forjar o endereço de uma máquina de confiança, tudo está perdido. Desde logo este mecanismo só deve ser usado sob endereços de rede que são geridos pelo mesmo administrador dos sistemas, geralmente todos pertencentes a uma mesma rede.

    Embora se trate de forjar o endereço de origem do pedido, o intruso tem também de se assegurar que recebe os dados de resposta, isto complica bastante a tarefa, considerando que as máquinas de confiança se encontram todas numa mesma rede local, a menos que o servidor verdadeiro esteja inactivo, é impossível realizar o ataque porque ao existirem duas máquinas com o mesmo endereço torna-se imprevisivel a qual das máquinas vão ser entregues os dados que de qualquer forma não serã legiveis porque são apenas fragmentos.

    Uma abordagem possível seria desencadear um ataque duplo, por um lado bloquear o servidor verdadeiro com um ataque de negação de serviço (inundação de pedidos) e simultaneamente usar outra máquina para simular o endereço do servidor verdadeiro.

    O ataque descrito é possível se os servidores usarem ARP dinâmico (situação usual). Para fazer os dados chegar ao destino dentro de uma rede local, o endereço IP não é suficiente porque a infra-estrutura de comunicação usada (ex: ethernet) usa outro formato de endereços conhecidos por endereços físicos ou endereços MAC. Assim cada sistema Unix mantém uma tabela de equivalencias entre endereços IP locais e endereços MAC locais que lhe permite fazer chegar os dados ao destino correcto dentro de uma rede local.

    Para evitar a definição estática das tabelas MAC é usado um protocolo auxiliar, o ARP ("Address Resolution Protocol") que permite determinar quando necessário, qual o endereço MAC correspondente a um dado endereço IP. Para evitar o recurso sistemático a este protocolo, as equivalencias IP/MAC são guardadas numa tabela interna (tabela ARP), quando determinadas via protocolo ARP, as entradas nesta tabala são temporárias e são eliminadas depois de estarem algum tempo sem serem usadas. O problema do protocolo ARP é que não tem qualquer segurança, explicado de forma simples funciona do seguinte modo: é enviado a todos os nós da rede ("broadcast") um pedido para que o detentor do endereço IP do qual se pretende o MAC responda, ao obter a resposta fica-se a conhecer o endereço MAC.

    Como é obvio qualquer nó da rede que diga ser o detentor desse endereço IP vai ser aceite. A alternativa é utilizar uma tabela ARP estática, isso obriga o administrador a inserir com a ajuda do comando "arp" entradas na tabela, inseridas deste modo estas entradas são permanentes e o protocolo ARP nunca será usado para elas.

    As tabelas ARP estáticas aumentam um pouco a segurança, e inviabilizam a maioria dos ataques, embora afectem o funcionamento do sistema verdadeiro, não será possível ao intruso realizar operações sobre os sistemas aproveitando o estatuto de confiança. Com ARP estático o intruso é obrigado é obrigado a simular não apenas o endereço IP, mas também o endereço MAC, a maioria das interfaces de rede e respectivos "device drivers" actuais permitem que o endereço MAC seja alterado. Os efeitos da existência de dois nós com o mesmo endereço MAC numa mesma rede inviabilizam na maioria dos casos a comunicação, os efeitos exactos dependem da infra-estrutura de comunicação, por exemplo se se trata de um meio de "broadcast" simples ou de uma rede com comutação.

    Na eventualidade de o sistema verdadeiro estar inactivo (sem comunicações), a tarefa do intruso fica muito facilitada, se for usado ARP dinâmico, basta usar na máquina intrusa o mesmo IP do sistema verdadeiro, se for usado ARP estático terá também de ser simulado o enderço MAC.

    Para resolver o problema só existe uma via segura: evitar o acesso físico à rede onde se encontram os servidores. Esta configuração corresponde aliás ao modelo mais aconselhado para implementação de "intranets" com ligação á "internet". Aconselha-se vivamente que a rede onde se encontram os sistemas servidores esteja isolada e não seja a mesma rede onde os utilizadores trabalham, este tipo de rede isolada, exclusiva para servidores corresponde ao que se designa vulgarmente por rede desmilitarizada (DMZ - "DeMilitarized Zone"). A ligação desta rede à "internet" e à "intranet" é assegurada por um ou mais "routers"/"firewalls".