lunes, 12 de noviembre de 2007

Capitulo 6: Entrada y Salida

Conceptos de Entrada y Salida
Comandos asociados con la salida
Pipes o tuberías
Otras utilidades de E/S en el Shell
More y less
Comandos útiles del less
stderr y otras redirecciones


Conceptos de Entrada y Salida

Es posible que ya hayas visto en algún sitio los terminos entrada y salida aplicados al mundo de la informática (quizás como I/O -input/output- o bien E/S -entrada/salida-).

En realidad es algo más simple de lo que pueda parecer, como vamos a ver mediante ejemplos sencillos. Cuando estamos dentro del sistema usando la terminal bash, generalmente tecleamos comandos para que sean ejecutados. El hecho de que estemos simplemente presionando el teclado implica que estamos entrando datos al sistema mediante el teclado. Cuando en ejemplos anteriores hemos usado el comando ls , ha aparecido en pantalla un listado de archivos y directorios, claramente el sistema ha producido salida de datos mediante el monitor.

Hemos puesto dos ejemplos, el teclado como vía para entrar datos al sistema (o bien a un programa, como ya vimos con vim), y el monitor como vía de salida de los datos. Pero no son, ni mucho menos, las únicas posibilidades. Los distintos puertos físicos del ordenador pueden ser vía de entrada o de salida de datos, igualmente con la tarjeta de sonido, módem, tarjeta de red...

Aunque lo que nos interesa en esta sección, es manejar la entrada y la salida de datos de y entre ciertos programas. Preguntas como... ¿y qué puedo hacer con el listado que me da el comando ls además de mostrarlo por pantalla? o ¿qué otras formas de pasar datos y opciones a los programas existen además del teclado? A todo esto y a algunos detalles más daremos respuesta en este capítulo.

Los sistemas UNIX (y por ello también los Linux), son especialmente conocidos por su facilidad y eficiencia para pasar datos entre programas y programas o entre programas y dispositivos, siendo esta una de sus múltiples ventajas.

Otros conceptos importantes dentro de estos son los de entrada estándar y salida estándar (stdin y stdout respectivamente). Por defecto, stdin apunta al teclado (los datos, se toman generalmente por defecto del teclado), y stdout apunta a la pantalla (por defecto los programas suelen enviar la salida por pantalla).


Comandos asociados con la Salida

Son, principalmente echo, cat.

En primer lugar, echemos un vistazo al comando echo. Este comando nos permite "imprimir" cosas en la pantalla.

Veamos algunos ejemplos:

usuario@maquina ~ $ echo "Hola, usuario de Linux"
Hola, usuario de Linux

Como ves, por defecto el comando echo recibe las cadenas de texto entre comillas (simples o dobles), y saca por defecto a la pantalla lo que le pasamos como argumento; aunque puede enviar la salida a otros sitios, como podrás comprobar más adelante.

Adelantándonos un poco, el shell puede hacer operaciones aritméticas básicas, y podemos aprovecharlas con el comando echo:

usuario@maquina ~ $ echo $[5*3]
15

Cambiemos de comando, vamos a aprender ahora el comando cat. Es un comando útil que será nuestro amigo a partir de ahora.

cat tiene asociada la entrada al teclado por defecto, y la salida a la pantalla. Asi que si lo llamamos sin argumentos, simplemente tecleando cat, tecleamos y pulsamos INTRO, volverá a imprimir en pantalla cada línea que nosotros tecleemos:

usuario@maquina ~ $ cat
Escribo esto
Escribo esto
Y escribo esto otro
Y escribo esto otro

Continuará hasta que le mandemos detenerse manteniendo pulsada la tecla CONTROL y presionando a la vez la tecla C. Puede parecernos poco útil el funcionamiento por defecto del comando cat. Pero observemos ahora el funcionamiento más común de este comando, que es mostrar el contenido de un fichero:

usuario@maquina ~ $ cat directorio/mifichero
Esto es el contenido del fichero
mifichero que se encuentra en ~/directorio.

Este es el uso más frecuente para el comando cat, tomar como entrada un fichero y sacar su contenido por la salida. Por defecto es por la pantalla, pero descubriremos después que puede enviar el contenido de un fichero por otras vías.

Como ya habrás imaginado, los ficheros de disco pueden ser objeto de entrada (leer su contenido) o de salida (escribir la salida de un determinado comando a un fichero). El comando siguiente, touch nos da la posibilidad de crear un fichero vacío con el nombre que nosotros le especifiquemos:

usuario@maquina ~ $ touch minuevofichero

Así crearemos un fichero nuevo vacío al que podremos posteriormente enviar la salida de nuestros comandos. Si listas el fichero con ls -l minuevofichero verás como efectivamente su tamaño es cero. No obstante, touch puede hacer alguna otra cosa, como explicaremos en secciones posteriores.

Otro comando útil es el comando grep. Este comando por defecto lee de stdin (la entrada estándar), y envía los datos a la salida estándar (stdout). El objetivo primordial del comando grep es, "devolver" las líneas que contienen la cadena de texto que le pasamos al principio. Por ejemplo:

$ grep hola
Esta frase no contiene la palabra, por lo tanto no la repetirá
Esta frase contiene la palabra hola, por lo que la repetirá
Esta frase contiene la palabra hola, por lo que la repetirá

Como ves, el comando grep ha identificado las líneas que contenian la palabra que le pasamos como primer argumento.


Pipes o tuberías

Hasta ahora hemos estado practicando de dónde toman los datos algunas de las utilidades más comunes, y hacia dónde envían su salida. Lo siguiente que tenemos que plantearnos sería... ¿no podríamos "conectar" de alguna forma la salida de un programa y hacer que otro programa lea de ella?

Efectivamente, podemos conseguir esto. El caracter | nos permite crear estas conexiones entre programas en el shell. Ejemplo:

$ cat mifichero | grep gato

Lo que este comando hará será lo siguiente: La primera parte antes de la barra vertical, conseguirá el contenido del fichero mifichero, y con la barra vertical, en lugar de sacarlo por la pantalla, lo enviará a la entrada estándar (stdin) de tal forma que el programa grep leerá desde stdin el contenido del fichero mifichero. El concepto del efecto que esto produce es fácil de entender: el comando que va detrás de la barra lee de la salida que dió el comando anterior. Es obvio que lo que obtendremos serán las líneas del fichero mifichero que contienen la palabra "gato" por la pantalla (stdout).

Como ves, no estamos pasando ninguna opción ni al comando cat ni al comando grep. Esto es porque el primero (cat) envía la salida por defecto a stdout, y grep, si recuerdas, lee por defecto de stdin (que al usar la barra vertical, hemos hecho que stdin sea la salida del primer comando y no las líneas que tecleemos a continuación como hicimos anteriormente). Pero los pipes con la barra vertical podremos emplearlos con otros programas que no tengan este comportamiento por defecto, esto es, que su salida no apunte por defecto a stdout (podría apuntar, por ejemplo, a un fichero) o que no lean por defecto de stdin. Podremos hacer que tengan este comportamiento pasándoles determinadas opciones si disponen de ellas. Es muy común la opción - (un solo guión) para hacer que un programa lea de stdin o escriba a stdout si tiene esta funcionalidad; seguro que te encuentras algun comando que tenga esta posibilidad más adelante.

Otros caracteres que nos permiten crear "pipes", son < y >. Generalmente, este par de caracter trabajan con un fichero a un lado y un comando a otro. Me explico; veamos primero el caracter <:

$ grep gato <>

Esta línea es equivalente a la del ejemplo anterior. El contenido del fichero que ponemos a la derecha del signo se va a la entrada estándar de la que lee el comando que ponemos a su izquierda, por lo tanto esta línea conseguiría exactamente el mismo efecto que la del ejemplo anterior.

Ahora el signo contrario. A la izquierda del signo > ponemos un comando, y a la derecha el nombre del fichero al que queremos que se escriba la salida del comando. Por ejemplo:

$ ls -la > listado

La lista del contenido del directorio actual que el comando ls sacaría normalmente por pantalla, en vez de eso se ha escrito en el fichero listado. Si el fichero no existía, se ha creado, y si existía y tenía contenido, ha sido sobreescrito, asi que tengamos cuidado.

El uso de los signos >> juntos, tiene una funcionalidad similar al uso de un signo solamente, y puede sernos útil muchas veces:

$ echo "Esta es otra línea" >> texto

Vemos en qué es similar a lo anterior; la línea "Esta es otra línea se ha escrito al fichero texto. Si el fichero no existía, ha sido creado, y la diferencia, si existía y tenía contenido, la línea se ha escrito al final del fichero, debajo del contenido que ya tenía. Este comportamiento nos puede ser muy útil de cara a ir añadiendo líneas a un archivo sin necesidad de tener que abrirlo con un editor.


Otras utilidades de E/S en el Shell

Aunque es adelantar un poquito, vamos a ver cómo la entrada estándar, la salida estándar y alguna cosa más "están" en el sistema de archivos.

La entrada estándar (stdin) está enlazada mediante el dispositivo (sobre lo que se hablará más adelante) /dev/stdin:

$ echo "hola" | cat /dev/stdin
hola

Con el comando echo, escribimos la palabra "hola" a la salida estándar, que con la barra vertical, se pasa a la entrada estándar, pero como le estamos pasando un argumento a cat, lee de /dev/stdin que... ¡sorpresa! ha resultado ser la entrada estándar. Si hubiesemos escrito el mismo comando quitando /dev/stdin, el resultado habría sido el mismo, puesto que si a cat no le pasamos ningún argumento, lee desde stdin. No te preocupes si no puedes comprender del todo lo que hace este ejemplo, simplemente tú asocia /dev/stdin con la entrada estándar que es accesible desde el sistema de ficheros.

La salida estándar está asociada a /dev/stdout:

$ cat fichero > /dev/stdout
--contenido de fichero--

Aquí, estamos enviando el contenido de fichero a /dev/stdout que, curiosamente, igual que en el caso anterior, ha resultado "conectar" con la salida estándar, esto es, la pantalla.

Por último, os presentaremos a nuestro basurero particular :-) , que es /dev/null. Nos puede ser útil para cuando queramos despreciar la salida de un comando, que ni salga por pantalla ni que se quede escrito en un fichero, simplemente que se pierda:

$ cat mimayorfichero > /dev/null

Una ventaja de /dev/null con respecto a los basureros físicos es que nunca se llena ;-) , podemos "arrojarle" toda salida que queramos despreciar.


more y less

more y less son dos comandos útiles a la hora de paginar. Paginar es ver un archivo o una salida larga por partes (o páginas), puesto que de otra forma sólo podríamos ver el final de esta salida larga. Pongamos por ejemplo que quisiésemos leer un archivo largo. Como ya sabes, esto podrías hacerlo con el editor vim, pero también podrías hacerlo con cat y la ayuda de estos dos comandos:

$ cat archivolargo | more
$ more <>
$ more archivolargo

Como ya sabemos, los dos primeros comandos son exactamente equivalentes. Pero el tercero tiene una pequeña diferencia con respecto a los anteriores. Si introducimos uno de los dos primeros con un archivo largo, entonces veremos que el programa more nos indica en la parte inferior "Más" o "More", y nada más; mientras que si introducimos el tercer comando, en la parte inferior de la terminal nos aparecerá "More (15%)", esto es, el porcentaje del fichero que estamos mostrando. La diferencia pues entre estos comandos es que en los dos primeros, more no conoce la longitud de los datos que vienen por la stdin, simplemente los procesa conforme el usuario se lo pide; mientras que en el tercer caso, el funcionamiento de more es conocer la longitud del fichero que se le pasa como primer argumento, y después paginarlo igual que hacía con los datos de stdin. Esto es importante; en UNIX y en Linux podemos trabajar con la stdin y stdout conforme vayamos necesitando sus datos, sin necesidad de saber cuál es su longitud o sin miedo de que estos vayan a perderse.

En lo que respecta al comando more, podemos seguir paginando hacia abajo con la barra espaciadora, hasta llegar al final del fichero o de los datos de entrada; o bien presionar la tecla q en cualquier momento para abandonar el programa.

El comando less es un "more" de GNU mejorado. Si recuerdas, con more sólo podíamos paginar hacia abajo, y bajar página por página. Con less podemos hacer algunas cosas más, como volver arriba o abajo, o bajar o subir línea por línea. Se puede usar igual que los ejemplos anteriores del comando more, con la diferencia de que una vez que estemos viendo la entrada paginada, además de poder bajar con la barra espaciadora, podemos subir y bajar con las flechas de dirección, o bien con las teclas de "avanzar página" y "retroceder página" de nuestro teclado. En el momento de salir, lo haremos igualmente presionando la tecla q.


Comandos útiles de less

Frente a more, less nos ofrece algunos comandos que nos ayudan a buscar cadenas y patrones dentro del buffer que less esté visualizando. Como ya es costumbre en este manual os proporcionamos una tabla con los comandos más utilizados en less, por supuesto hay muchos más, pero la idea no es reproducir la página del manual.

Para invocar a less podemos hacerlo con un pipe o directamente así:

$ less fichero1 fichero2 fichero3

Tabla 6.1. Órdenes más comunes de less

ComandoDescripciónEjemplo de uso si aplica
:n Examina el siguiente fichero en la lista de argumentos de less --
:p Examina el fichero anterior en la lista de argumentos de less --
:e fichero Examina el fichero pasado como argumento :e /etc/xml/docbook/catalog
:x N Examina el primer fichero de la lista si N no ha sido especificado, en caso contrario examina el fichero que esté en la posición N de la lista. :x 6
:d Elimina el fichero que se está examinando de la lista --
= o ^G o ^F Da información adicional sobre el fichero incluyendo el nombre, el número de línea el %... =
!comando Nos permite ejecutar el comando como si estuvieramos en una shell. !! ejecutará el último comando ejecutado. Si se incluye en el comando el símbolo % será reemplazado por el fichero que se está examinando en ese momento, y # por el ultimo fichero examinado. Si no se especifica un comando devolverá una shell que se tomará de la variable de entorno SHELL. !xmllint --valid --noout %
/patrón Se busca en el fichero la cadena especificada por patrón. Si no se especifica ningun patrón se utilizará el último patrón buscado. Si el primer caracter de patrón es un * se buscará el patrón en todos los ficheros de la lista. La búsqueda es siempre hacia posiciones posteriores al cursor, es decir, hacia adelante. /*gfdl
?patrón Idéntico en todo a / pero la búsqueda se hace hacia atrás. ?fdisk
s fichero Si el buffer que se está visualizando no es un fichero sino información leida de un pipe podemos guardar el buffer en fichero s ~/temp/log


Nota: Una letra precedida de ^ significa que hay que pulsar primero la tecla Ctrl de forma que ^G es lo mismo que decir: Ctrl-G

Nota: Es muy util ajustar la variable de entorno PAGER a less (export PAGER=/usr/bin/less) dado que así las páginas del manual se mostrarán con less y podrás utilizar sus funciones de búsqueda de patrones.


Recuerda que puedes utilizar more y less con otros comandos distintos que produzcan mucha salida, y usarlos para ver la salida detalladamente.

Otro pequeño truco, es que si estás en una terminal, puedes ver las líneas anteriores (que ya no se muestran en pantalla) manteniendo pulsada la tecla de las mayúsculas (no el bloqueo de mayúsculas) y a continuación presionando las teclas "avanzar página" y "retrocer página" de tu teclado para moverte por líneas anteriores de tu sesión en una terminal.


stderr y otras redirecciones

Hemos visto stdin y stdout, entrada y salida estándar, respectivamente. Sabemos que el siguiente ejemplo listará los contenidos del directorio actual y despreciará ese listado, enviándolo a /dev/null:

$ ls ./ > /dev/null
$ ls directorio_inexistente/ > /dev/null
ls: directorio_inexistente: No existe el fichero o el directorio.

En el primer caso, todo fue como esperábamos, la salida del listado fue simplemente despreciada. Pero... ¿qué ha pasado en el segundo caso? Con el signo > le decíamos que enviase la salida estándar, en este caso, a /dev/null. Y, como no te hemos mentido, la salida estándar fue a /dev/null. Lo que ha pasado es que el mensaje de error no ha ido a stdout; porque de haber sido así habría sido despreciado. ¿Dónde ha ido entonces el mensaje de error? Es sencillo, a stderr. La mayoría de los programas imprimen stderr por pantalla; aunque podrían (como hacen algunos), escribir los mensajes de error a un fichero, o por qué no, despreciarlos.

Algunos programas hacen estas cosas con stderr; cosas que ya hemos aprendido nosotros a hacer con stdout. Una solución posible sería que stderr fuese a stdout, y a partir de ahí, nosotros ya pudiésemos redirigir stdout como sabemos. Conseguir esto no es difícil, se hace con el operador >& :

$ ls directorio_inexistente/ > /dev/null 2>&1

Ahora sí será despreciada stderr; pero analicemos este comando por partes, y entendámoslo bien. Debemos saber que en él, "2" representa a stderr, y que "1" representa a stdout. Más cosas; este comando tiene dos partes. La primera es ls directorio_inexistente/ > /dev/null y la segunda es 2>&1. En las redirecciones de salida complejas, como es esta, el shell las interpreta "al revés", esto es, de derecha a izquierda. Primero interpreta lo que hemos dicho que es el segundo comando, y luego interpreta el primero. Lo que ocurre entonces es lo siguiente: primero, stderr va a stdout por el segundo comando que se procesa en primer lugar, y luego stdout (que ya "contiene" a stderr) se va a /dev/null. Entonces conseguimos el efecto deseado, despreciar tanto stdout como stderr; aunque podríamos haber hecho otras cosas con ellas, lo importante es que ambas "salidas" habrían ido al mismo sitio.

Pero puede ocurrirte (y de hecho te ocurrirá), que desees tratar por separado stdout y stderr. Si se entendió el ejemplo anterior esto no debería causar problemas. Vamos a poner, como caso práctico, que vamos a listar una serie de archivos o directorios; los que existan se escribirán sus detalles en un fichero, y los que no obtendremos el error en otro fichero distinto:

$ ls -l fichero1 fichero2 fichero3 > existentes 2>inexistentes
$ ls -l fichero1 fichero2 fichero3 1>existentes 2>inexistentes

Estos dos comandos son absolutamente equivalentes. Recordemos que este tipo de comandos son interpretados de derecha a izquierda. En el primero de ellos, al principio stderr se escribirá al fichero inexistentes, y después el resto (o sea, stdout) se escribirá al fichero existentes. En el segundo, primero 2 (stderr) se escribirá a inexistentes, y después 1 (stdout) se escribirá a existentes. Usando cualquiera de ellos, al final tendremos en el fichero existentes los detalles de los ficheros existentes y en el fichero inexistentes el error producido por los ficheros (o directorios) que no existen. Este ejemplo es bastante ilustrativo de cómo podemos tratar separadamente stderr y stdout.

viernes, 9 de noviembre de 2007

Capitulo 5: Usuarios y Grupos. Permisos

V Usuarios y Grupos. Permisos
Usuarios
Administración de usuarios
Grupos
Administración de grupos
Permisos y dueños
Comando su
SUID
Sudo

Usuarios

Linux es un sistema multiusuario por lo que es necesario la administración (segura) de los distintos usuarios que van a hacer uso de los recursos del sistema. De momento no vamos a dar grandes nociones de seguridad, pero sí una introducción a los tipos de usuarios y qué privilegios deben tener.

Dentro de un sistema existen al menos 3 tipos de usuarios.

  • Usuarios normales con más o menos privilegios que harán uso de los recursos del sistema. Son generalmente inexpertos y propensos a causar problemas. Simplemente deben poder usar algunos programas y disponer de un directorio de trabajo.

  • Usuarios de Sistema son aquellos encargados de los demonios del sistema, recordemos que para Linux todo es un fichero, el cual tiene un dueño y ese dueño tiene privilegios sobre él. Así, es necesario que algún usuario del sistema posea los procesos de los demonios, como veremos más adelante.

    Resumiendo, es necesario que para algunos servicios del sistema se creen usuarios (generalmente para demonios). Como puede ser el caso de Mail, irc... Estos usuarios tendrán los privilegios necesarios para poder hacer su tarea, gestionar estos usuarios es de gran importancia. No obstante, este tipo de usuarios no necesita que se le asigne un shell, puesto que simplemente poseerán los demonios, pero no será necesario que hagan login en el sistema.

  • ROOT Este es dios ;-) Como ya habéis leido en capítulos anteriores cuidado con lo que se hace al entrar en el sistema como root. Él lo puede todo, en principio no hay restricciones para ÉL (aunque algunos programas nos avisarán de que estamos haciendo una auténtica burrada desde el punto de vista de la seguridad).

Además del criterio anterior, existe un criterio secundario para clasificar a los usuarios de un sistema. Ya vamos conociendo la tendencia de los UNIX y Linux, primero, por hacer que casi todo sea un fichero, y segundo, por hacer que absolutamente todo tenga un dueño (como iremos descubriendo a medida que usamos el sistema, nada se deja al azar en este aspecto), incluidos los procesos que se están ejecutando en el sistema. Otro concepto que lleva a esta segunda clasificación es, el de los usuarios de los servicios del host. Este tipo de usuarios simplemente accede remotamente a algunos servicios de nuestra máquina, tales como correo-electrónico o FTP. Esto nos lleva a definir:

  • Usuarios de login. Estos primeros, pueden hacer login en el sistema y usar una shell en él. Es decir, tienen una shell válida de inicio (como se indica más abajo), generalmente, /bin/bash.

  • Usuarios sin login. Este tipo de usuarios, bien son usuarios de sistema, o bien usuarios de los servicios del host. En ambos casos no pueden hacer login en el sistema directamente ni usar un shell. En otras palabras, no tienen asignado un shell válido. Su misión, es "poseer" algunos archivos y directorios del sistema, y manejarlos restringidamente a través de algunos programas (el servidor FTP, el servidor de correo electrónico, etc. darán a los usuarios de los servicios del host los privilegios suficientes: almacenar mensajes, etc.). En el caso de los usuarios de sistema, poseerán además algunos procesos (en el capítulo de procesos aprenderemos más acerca de este sub-tipo especial de usuarios).


Administración de Usuarios.

La administración de usuarios se realiza en todas las distribuciones de manera muy parecida, dada la herencia UNIX, aunque en el fondo todas hacen lo mismo. Según la política que lleven lo pueden realizar de una manera u otra, por lo que aquí veremos la forma la forma interna de trabajar de los programas a la hora de añadir o quitar usuarios, y al final expondremos ejemplos concretos de las distros más conocidas.

¿Cómo añadir un usuario al sistema? Hay que seguir una serie de pasos que relatamos a continuación. Pero antes veremos la estructura de los archivos que vamos a tocar.

  • /etc/password - Archivo que mantiene la base de datos de los usuarios del sistema y tiene la siguiente forma:

    nombre_de_usuario:password(si es shadow será x):uid:gid:comentario:home_del_usuario:shell

    Estos campos son:

    • Nombre de Usuario - Es el nombre con el que entrará en el sistema.

    • Password - La palabra de paso necesaria para entrar (cifrada). Si nuestro sistema usa shadow (explicado después), este campo será una x

    • UID - (User ID) Número que lo identifica en el sistema, recordemos que los ordenadores se llevan mejor con los números.

    • GID - (Group ID) Número que identifica al grupo principal al que pertenece el usuario.

    • Comentario - Opcional, si es necesario aclarar algo, esto solo es para el administrador, pues el sistema no lo usa.

    • home_del_usuario - Ruta absoluta del directorio de trabajo del usuario.

    • Shell - Intérprete de comandos del usuario, que será el que use inmediatamente después de entrar en el sistema, por defecto es /bin/bash. Para usuarios sin login, aunque puede que ahora no lo necesites, la shell no válida típica para poner en este campo es /bin/false.

  • /etc/group - Archivo de los grupos del sistema; de su administración y uso hablaremos en el siguiente apartado. El archivo tiene la siguiente estructura:

    nombre_grupo:password:GID:lista_usuarios

    • Nombre del Grupo - Por defecto con los comandos habituales se crea un grupo con el mismo nombre que el usuario creado, aunque pueden existir otros grupos con nombres específicos.

    • password - Se usa para dar a una serie de individuos un mismo directorio con una cuenta común.

    • GID - (Group ID) Número de Identificación en el Sistema del grupo.

    • lista de usuarios que pertenecen al grupo, separados por comas.

  • /etc/shadow - Para sistemas que usen shadow, que no es más que una medida de seguridad. Los sistemas que no usan shadow guardan el password en /etc/passwd pero este archivo tiene la peculiaridad de que debe ser legible por todo el mundo, si no, no podría ni hacerse un ls. Este archivo podría caer en manos de un usario ilegítimo y este ejercer técnicas de crackeo sobre las claves. Como solución del problema lo que se hace es almacenar todos los datos de los usuarios en el /etc/password menos sus contraseñas; que se almacenan en /etc/shadow, el cual sí tiene restringidos los permisos y no es accesible por los usuarios normales.

    usuario:password:días del último cambio: dias antes del cambio:Dias despues del cambio: tiempo de aviso:dias antes de la inhabilitacion: perido que lleva caducado:reservado:

    • Usuario - Nombre del usuario

    • password - Aquí sí, es el password cifrado.

    • Tiempo del último cambio de password - Pero el tiempo cuenta desde el 1 de enero de 1970, comienzo de la era UNIX.

    • Días antes del cambio - Periodo (en días) donde el password debe ser cambiado.

    • Dias despues del cambio - En los días después donde debe ser cambiado.

    • Tiempo del aviso - Periodo en el que el sistema tiene que avisar de la necesidad del cambio.

    • Inhabilitación - Días antes de la inhabilitacion de la cuenta.

    • Perido caducado - Días desde el 1 de enero de 1970 en el que la cuenta está deshabilitada.

    • Campo reservado

Bien ahora, ya que conocemos la estructura de los archivos, creemos un nuevo usuario, sólo tendremos que usar un editor, que por razones de seguridad son vipw para el archivo /etc/passwd y vigr para editar /etc/group; ambos usan como editor el que esté en la variable $EDITOR del sistema, y passwd para crear el password. Sigamos los siguientes pasos:

  1. Lo primero es entrar como root

    $ su -
    password:
    # vipw /etc/passwd
  2. Antes de nada, el comando su se explica al final de este capítulo. Ya estamos editando el fichero /etc/passwd, ahí estarán las lineas de otros usuarios que ya estén creados. Esto que sigue es un ejemplo.

    prueba:x:1005:1005::/home/prueba:/bin/bash

    Hemos escrito un nombre cualquiera (prueba), el password le ponemos x dado que es un sistema con shadow. Si queremos crear una cuenta sin contraseña, en este campo en vez de la x no pondremos nada. ADVERTENCIA: Esto es un considerable riesgo de seguridad. Incluso una cuenta de usuario puede usarse para hallar información útil para posteriormente poder atacar un sistema.

  3. Ahora hay que tocar en /etc/group para crear el grupo del usuario (todo usuario tiene un grupo principal), le damos el mismo nombre que al usuario, y el GID que hemos puesto antes, el 1005. Por supuesto, tanto los UID como los GID no pueden estar repetidos, así que nos aseguramos de coger uno que no esté ya cogido. Entonces, hacemos:

    # vigr /etc/group
    prueba:x:1005:
  4. Editamos /etc/shadow :

    prueba:!:12173:0:99999:7:::

    Bueno lo peor será calcular la fecha de creación pero sino randomized() :-). Notad que en el campo password le hemos puesto ! porque ahora le daremos un password con passwd.

  5. # passwd prueba 1
    Enter new UNIX password: 2
    Retype new UNIX password: 3
    1

    Ejecutamos passwd y pasamos el nombre del usuario como argumento.

    2

    Introducimos el password para ese usuario, hay que darse cuenta de que a medida que escribimos, por razones obvias de seguridad no se irá escribiendo nada.

    3

    Repetimos la password

    Si no hay error, listo.

  6. Ahora le tenemos que crear el directorio de trabajo, por convenio los directorios de trabajo de los usuarios normales están bajo /home, y suelen ser /home/usuario.

    # mkdir /home/prueba
  7. Copiamos los archivos de inicio desde /etc/skel , que contiene principalmente archivos de configuración por defecto.

    # cp /etc/skel/.* /home/prueba
  8. Y por último, hay que hacer que tome posesión de lo que es suyo:

    # chown prueba.prueba -R  /home/prueba

    Este último comando se explica más adelante. Ahora sólo falta hacer:

    # su - prueba
    $

    También, en vez de usar su, podemos hacer login en el shell directamente con el nuevo usuario creado para comprobar que lo hemos hecho correctamente.

Esto es lo que hace cualquier Linux para crear una cuenta. La forma de borrar un usuario es igual de fácil, borrándolo en /etc/passwd, /etc/group y en /etc/shadow. Cualquier rastro del usuario debería también ser eliminado, además de que sería bastante recomendable (si no necesario) hacer una busqueda de los archivos que el usuario mantiene. Esta búsqueda podría ser:

# find / -uid uid_del_usuario > archivos_del_usuario

De esta manera los podemos guardar, revisar y hacer lo conveniente con los archivos. Más sobre find en secciones posteriores.

A continuación veremos los comandos que hacen esto mismo y alguna diferencia entre las distintas distribuciones.


Comandos de Administración

Estos comandos nos permitirán crear, borrar y modificar las cuentas de usuarios en el sistema.

adduser y useradd son dos comandos que hacen prácticamente lo mismo. Nota que el estándar es useradd, adduser puede, en algunas distribuciones ser un simple enlace a useradd, o simplemente no existir. El comportamiento por defecto de useradd es muy subjetivo dependiendo de la distribución de Linux que estemos usando. Así, mientras que en algunas distribuciones hará casi todos los pasos anteriores por nosotros, en otras sólo añadirá el usuario a /etc/password y /etc/shadow, teniendo que realizar nosotros los pasos restantes. Aun así, las opciones que recibe useradd responden igual en todas las distros. Como ya hemos hecho con algún otro comando, puedes ver las opciones de useradd mediante man useradd, moverte con las teclas de dirección y volver al shell pulsando la tecla Q.

Las opciones más comunes para useradd son:

# useradd -g users -d /home/usuario -s /bin/bash -m -k /etc/skel usuario
  • -g Indica cuál es el grupo principal al que pertenece el usuario; en este caso, users

  • -d Establece el que será el directorio de trabajo del usuario, por convenio para usuarios normales, es /home/nombre_de_usuario

  • -s Es la shell por defecto que podrá usar el usuario después de hacer login. Lo normal es que sea /bin/bash, esto es, el shell bash.

  • -m -k Estas dos opciones se complementan. La primera, hace que se cree el directorio de trabajo del usuario en el caso de que este no exista. La segunda, copia los ficheros del directorio especificado al que se ha creado del usuario.

  • usuario Por último, usuario es el nombre del usuario que estamos creando.

  • -G Aunque esta opción no está en el comando de ejemplo que hemos puesto arriba, es muy útil, puesto que permite especificar la lista de grupos a la que también pertenecerá el usuario aparte del grupo principal. Por ejemplo -G audio,cdrom,dip añadido en el comando anterior haría que usuario perteneciese a estos grupos además de al suyo principal.

Siempre podemos matizar detalles en la creación de usuarios editando los ficheros de configuración que ya conocemos.

La cuenta del usuario no estará activada hasta que no le asignemos un password. Esto lo podemos hacer vía password nombre_de_usuario (para cambiar el password procederíamos exactamente de la misma forma). Cualquier usuario normal puede cambiar su password cuando haya entrado al sistema, bastando en este caso con escribir el comando password sin argumentos ni opciones.

Para desactivar una cuenta de usuario sin necesidad de borrala del sistema, podemos editar /etc/passwd y cambiar la x por un ! en el campo del password. La cuenta se habilitaría asignando un password con password o bien volviendo a poner la x que había, quedando la cuenta entonces con el mismo password que tenía antes de deshabilitarla.

Podríamos, si nuestra distro dispone de ellas, utilizar las herramientas interactivas para crear usuarios (a veces incluso existen interfaces gráficas de ventanas para gestionar usuarios y grupos, solo accesibles por root); generalmente adduser. Aunque pueden resultar más cómodas, siempre es conveniente saber el método general de creación de usuarios, de tal forma que esos conocimientos nos servirán para cualquier distribución de Linux que vayamos a usar.

En algún momento podríamos necesitar editar una cuenta de usuario creada, o borrarla. Existen también comandos de administración estándares para esto; son usermod y userdel. Puedes ver sus páginas del manual con man. Aunque, una vez más, editando los ficheros de configuración no necesitarás memorizar opciones para efectuar esos cambios.

El comando whoami muestra el nombre de usuario que está dentro del sistema usando el shell desde el que se le llama.


Grupos

En la administración de grupos no vamos a gastar muchas energías ya que no es, en un nivel básico, algo excesivamente complejo.

Los grupos es una manera en los sistemas multiusuario como Linux de otorgar una serie de privilegios a un conjunto de usuarios sin tener que dárselo de forma indivial a cada uno.

El fichero encargado de mantener los grupos del sistema es /etc/group y también hemos visto su estructura. Por lo que veremos los comandos que añaden, quitan y modifican los grupos; así como notas generales en la gestión de grupos.

Hemos dicho que todo usuario tiene siempre un grupo principal al que pertenece. Hay dos posibilidades para los usuarios normales: que todos tengan el mismo grupo principal (generalmente users) o que cada usuario tenga un grupo principal específico (casi siempre del mismo nombre que el usuario). Esto responde a las necesidades de cada sistema. En el primer caso, los directorios de trabajo de los usuarios suelen ser accesibles por el resto de usuarios (no es lo más común); mientras que en el caso de que cada usuario tenga un grupo principal, lo normal es que los directorios de trabajo de cada usuario sean sólo accesibles por ese usuario (que sí es lo más común).

La utilidad del grupo principal de un usuario se entenderá mejor cuando lleguemos a los permisos.

Además, en el sistema hay más grupos que los principales de cada usuario. La misión de estos otros grupos es la de otorgar unos permisos similares al conjunto de usuarios que forman parte de él ante un directorio, un archivo, un dispositivo, etc.

Es muy común la necesidad de dar a unos cuantos usuarios permisos para que puedan, por ejemplo, leer los documentos de un directorio determinado (por ejemplo, informes de una empresa), al tiempo que al resto de usuarios no. Así, podríamos crear un grupo llamado contables, y agregar los usuarios que son contables a este grupo. Después, haríamos pertenecer (como veremos en Permisos) el directorio mencionado a este grupo, y le daríamos permisos de lectura para el grupo.

Además de para compartir archivos o directorios entre varios usuarios, existen grupos como audio, cdrom, y similares. Dispositivos como la tarjeta de sonido, el grabador de CDs, etc. tienen como usuario "dueño" a root, y como grupo "dueño" a uno de estos grupos. Así, para cada usuario que queramos que pueda usar la tarjeta de sonido, debemos añadirlo al grupo audio.


Administración de grupos

Ya hemos aprendido cómo establecer el grupo principal de un usuario, y cómo hacer a la hora de su creación que pertenezca a otros grupos adicionales; así como el fichero /etc/group. Así que ya no queda mucho en este aspecto.

Para añadir un usuario a un grupo de forma manual, todo lo que hay que hacer es editar /etc/group y añadir al usuario a la lista del último campo. Si ya hay usuarios, éstos se separan con comas.

Si lo que queremos es crear un nuevo grupo de forma manual, la cosa es igual de sencilla. Al igual que ya hicimos agregando el usuario prueba de forma manual, añadiremos otra entrada a este fichero con el nombre del grupo, la x en el password, un GID que no esté siendo usado y la lista de usuarios detrás.

También tenemos comandos que hacen esto mismo: groupadd , groupdel y groupmod.

groupadd sirve para crear un nuevo grupo:

# groupadd -g gid grupo

La opción -g va seguida del Group ID (numérico) que asignaremos al grupo, y grupo es el nombre del grupo creado. Si no indicamos la opción -g, el sistema seleccionará por nosotros un número GID que no esté siendo usado.

Lo mismo que sabemos ya sobre la edicición y borrado de usuarios es aplicable a los grupos. Lo más fácil es editar el fichero /etc/group directamente; recordando que si quitamos un grupo, ningún usuario podrá tener ese grupo como su grupo principal; y además que tendremos que cambiar los permisos (después más en esto) de los archivos que perteneciesen a este grupo pues de no hacerlo los estaríamos dejando asignados a un GID inexistente para el sistema, y esto no es recomendable.

Un comando curioso es groups, que mostrará una lista de grupos a los que el usuario actual pertenece.


Permisos y dueños

Todos y cada uno de los elementos del sistema / de Linux tienen dueño, ya sean ficheros, directorios, o enlaces a dispositivos. Por un lado, tienen un usuario dueño, y por otro, un grupo dueño. El usuario y el grupo que son dueños de un elemento no tienen por qué guardar una relación del tipo que el usuario debería estar dentro del grupo o cosas por el estilo. Son totalmente independientes. Así, puede existir un fichero que tenga como usuario propietario a username, un usuario normal, y tener como grupo propietario al grupo root.

Cuando se trabaja en el sistema, los programas "hacen dueños" de los ficheros creados durante la sesión al usuario de esta sesión y a su grupo principal por defecto; aunque esto puede cambiarse. Es lógico, que los ficheros que estén bajo el directorio de trabajo de un usuario le pertenezcan.

Siempre que tratemos con permisos y con dueños de elementos, debemos tener siempre presente el hecho de que el sistema de ficheros de Linux es jerárquico; esto implica que los cambios que hagamos, por ejemplo, en un directorio, pueden influir en el resto de elementos que están contenidos en un nivel inferior a éste (los archivos que contiene, los directorios que contiene, lo que contienen esos otros directorios, y así sucesivamente).

Con un simple ls -l en cualquier parte del sistema, podemos ver en la forma usuario grupo los dueños de cada elemento que sale en el listado largo. Entonces ya sabemos cómo comprobar esto.

El comando chown (CHange OWNer - cambiar propietario) permite cambiar el propietario de los elementos del sistema de archivos. Pero es lógico que si somos un usuario normal no podremos cambiar de propietario los elementos que pertenecen a root o a otros usuarios. En cambio, como root podremos cambiar el propietario de cualquier cosa. Aquí describimos las opciones más usadas de este comando, pero puedes ir mirando su página del manual del sistema.

# chown usuario elemento(s)
# chown usuario.grupo elemento(s)

En el primero de los dos comandos anteriores, el usuario dueño de elementos(s) será cambiado a usuario. El grupo deuño de elemento(s) se conservará el que estuviera antes de introducir este comando.

Con respecto al segundo comando, actúa exactamente igual que el anterior, con la pequeña diferencia que también cambiará el grupo dueño de elemento(s) pasando a ser grupo. Si sólo queremos cambiar el grupo de un elemento o lista de ellos, podemos usar el comando chgrp.

# chgrp grupo elemento(s)

elemento(s) puede ser una lista de archivos y directorios, o simplemente uno de ellos. Podemos usar los wildcards conocidos (como por ejemplo el asterisco: * para indicar varios archivos con una sola expresión. La importante opción -R permite cambiar dueños de directorios y de todo lo que tengan debajo, es decir, recursivamente:

# chown -R usuario.grupo directorio/

Este comando cambiará el usuario y grupo dueños tanto de directorio/ como de todo lo que contenga hasta cualquier nivel, es decir, todo lo que esté "debajo" de directorio, y el directorio mismo cambiarán de dueño.

¿Y para qué todo esto de los dueños de archivos y directorios? Para poder asignar permisos adecuadamente.

Un archivo tiene distintos niveles de permisos: lectura, escritura y ejecución. Los permisos sobre un archivo (o directorio) pueden ser distintos para el usuario dueño, para los usuarios pertenecientes al grupo dueño, y por último para el resto de los usuarios del sistema. Así, podemos hacer que el usuario dueño puede leer, escribir, y ejecutar un fichero; que el grupo dueño solo pueda leerlo, y que el resto de usuarios del sistema no tengan ningún permiso sobre él, por ejemplo.

Una buena asignación de dueños de elementos junto con una política adecuada de permisos sobre estos elementos, permiten obtener dos cosas: un sistema multiusuario, y un sistema seguro.

Si haces un ls -l en un directorio que tenga algunas cosas verás algo como:

$ ls -la bin/

drwxr-xr-x 2 root root 4096 Apr 16 17:19 .
drwxr-xr-x 21 root root 4096 May 23 20:34 ..
-rwxr-xr-x 1 root root 2872 Jun 24 2002 arch
-rwxr-xr-x 1 root root 94364 Jun 25 2001 ash
-rwxr-xr-x 1 root root 472492 Jun 25 2001 ash.static
-rwxr-xr-x 1 root root 10524 Jul 19 2001 aumix-minimal
lrwxrwxrwx 1 root root 4 Feb 4 2002 awk -> gawk

Fíjate en el campo de más a la izquierda del listado. Podemos ver como cuatro grupos. El primero es de un caracter solamente. Este caracter es una d si el elemento listado es un directorio, una l si el elemento es un enlace, y un guión - si el elemento es un archivo normal.

A continuación hay tres grupos. Cada uno de estos grupos tiene tres letras, pudiendo ser estas rwx o pudiendo ser sustituidas en algún caso por un guión. El primero de estos grupos indica los permisos que tiene sobre el elemento listado su usuario dueño; el segundo grupo indica los permisos que tienen sobre el elemento los usuarios que pertenezcan al grupo dueño, y el tercer grupo indica los permisos que tienen sobre el elemento el resto de usuarios del sistema.

En el caso de un archivo o un enlace (sobre los que hablaremos posteriormente), la r en cualquiera de estos "grupos" indica que se tienen permisos de lectura sobre el elemento. La w indica que se tienen permisos de escritura sobre el elemento, y la x indica que se tienen permisos de ejecución sobre el elemento. Un guión sustituyendo a cualquiera de estas letras indica que no se tiene el permiso al que está sustituyendo. Así, veamos algún ejemplo del listado anterior:

-rwxr-xr-x   1 root     root         2872 Jun 24  2002 arch

Es un archivo porque su primer caracter es un guión. Su usuario dueño es root, y su grupo dueño es el grupo root también. root tiene todos los permisos sobre él: rwx, esto quiere decir que puede leer el archivo arch, escribir en él y ejecutarlo. El grupo root sólo lo puede leer y ejecutar, y el resto de usuarios del sistema, también sólo pueden leerlo y ejecutarlo.

El caso de los directorios es un poco distinto. Los permisos rwx para un directorio, indican: la r y la x para el caso de un directorio difícilmente se entienden separadas. Son necesarias para que un usuario pueda "examinar" ese directorio, ver lo que tiene y navegar por él. La w indica que el usuario que posea este permiso puede colocar nuevos archivos en este directorio; así como también borrarlo.

Lo más común es que los directorios que deban poder ser "examinados" por todos los usuarios tengan permisos r-x en el tercer grupo de permisos. Pero con estos permisos no podrán colocar nada dentro de ese directorio, aunque sí podrán hacerlo dentro de un directorio de nivel inferior en el que sí tengan permisos de escritura. Ten en cuenta que si tenemos por ejemplo un directorio llamado superior/ y dentro de éste tenemos un directorio llamado personal/, y que un usuario tienen permisos de escritura en este segundo directorio, que es de nivel inferior, para poder acceder a él y escribir, debe este usuario poseer, como mínimo, permisos r-x en el de nivel superior, esto es, en superior/. Por otra parte, esto es absolutamente lógico: ¿cómo va a poder escribir un usuario en un directorio si no puede llegar hasta él? Esto mismo también se aplica para la lectura. Por ejemplo, el servidor web no podrá servir un directorio a la Internet si no dispone de permisos r-x para los directorios superiores a él.

Para cambiar los permisos de los elementos del sistema de ficheros, usamos el comando chmod.

# chmod -R ABC elemento

La opción -R es opcional, y cumple exactamente la misma función que en el comando chown. A B y C son un número de una cifra respectivamente. El primer número representa los permisos que estamos asignando al usuario dueño , el segundo los del grupo dueño, y el tercero los del resto de usuarios. Cada una de las cifras posibles corresponde con los permisos del usuario en binario; aunque es más fácil aprenderse qué hace cada cifra que pasar la cifra a binario cada vez que queramos cambiar los permisos a algo. Algunos ejemplos:

  • El 4 en binario es 100, por tanto, los permisos que otorga son r--, esto es, sólo lectura.

  • El 5 en binario es 101, por tanto, los permisos que otorga son r-x, lectura y ejecución.

  • El 6 en binario es 110, por tanto, los permisos que otorga son rw-, lectura y escritura.

  • El 7 en binario es 111, por tanto, los permisos que otorga son rwx, lectura, escritura y ejecución.

Los permisos de ejecución sólo se otorgarán a programas o scripts (con los que trataremos después); ya que hacerlo a los archivos normales carece por completo de sentido. Así, un comando de ejemplo podría ser:

$ chmod 640 mitexto

Este comando asignaría permisos de lectura y de escritura al usuario propietario, y permisos de lectura a los usuarios del grupo dueño, y ningún permiso al resto de usuarios para el archivo mitexto. Puedes ir haciendo pruebas combinando los distintos números y ver los permisos que otorgan mediante ls -l. Recuerda que los directorios que quieras que puedan ser "examinados", debe tener permisos de "ejecución" por parte de los usuarios que quieras que puedan acceder a ellos, por ejemplo podrías asignarlos con el número 5. A los que además quieras que puedan crear archivos en ese directorio, podrías darle esos permisos mediante el número 7. Con la opción -R puedes hacer que los permisos se asignen de modo recursivo a un directorio y a todo lo que hay debajo de él.

Un modo muy común para los directorios que deban ser accesibles por todo el mundo es 755, de forma que el usuario dueño pueda además escribir. Los directorios /home/usuario suelen tener permisos 750 para que el resto de usuarios no puedan acceder al directorio de trabajo de un usuario.

Aviso: Una mala asignación de permisos puede dar lugar a ataques locales, si dejamos a algunos usuarios permisos para modificar partes importantes del sistema de ficheros.

Ten cuidado cuando cambies permisos, sobre todo si eres root.


Un modo muy común de añadir permisos de ejecución a un archivo (generalmente un script) para todos los usuarios del sistema, sin tener que estar recordando qué números otorgan permisos de ejecución, es usar la opción +x de chmod, por ejemplo:

$ chmod +x mi_script.sh

Esta forma de asignar permisos es extensible, y según los casos, más sencilla que la de los números. En general es así:

$ chmod ABC fichero

Donde A es u (usuario), g (grupo) o bien a (todos). Cuando es a, se puede omitir.

B es + o bien - , indicando el primero añadir un cierto permiso y el segundo quitarlo.

C es r (lectura), w (escritura) o bien x (ejecución).

Ejemplos:

$ chmod g+w fichero
$ chmod -r fichero
$ chmod u+x fichero

El primer comando otorga permisos de escritura sobre fichero a los usuarios del grupo al que el fichero pertenece.

El segundo comando elimina los permisos de lectura sobre fichero a todo el mundo.

El tercer comando da al usuario dueño de fichero permisos de ejecución.


Comando su

El comando su (Set User) está relacionado con el login en el sistema y con los permisos. El uso principal de este comando es que un usuario normal adquiera los permisos de otro usuario del sistema (incluido root) siempre y cuando sepa su password.

Es muy común que, si somos nosotros el "dueño" de la contraseña de root, y por tanto la persona encargada de la administración del sistema, trabajemos normalmente como usuario normal por motivos de seguridad. Pero podemos necesitar convertirnos en root para alguna tarea específica: reiniciar el servidor web, modificar la configuración del sistema... para después volver a "ser" nuestro usuario normal.

$ su
Password: [ Escribimos el password de root ]
#

su llamado "a secas" como en el ejemplo anterior asume que el usuario actual quiere adquirir los permisos de root. Si proporcionamos el password adecuado ya los tendremos. Podemos ahora hacer las tareas de administración que necesitemos. Escribiendo exit volveremos a "ser" nuestro usuario normal.

Hay gente que considera útil tener siempre "en segundo plano" una shell con permisos de root. Esto se puede conseguir con los comandos suspend, fg y jobs. Por ejemplo:

$ su
Password: [ Password de root ]
# suspend 1
[1]+ Stopped su 2
$
$ fg %1 3
#
1

Detenemos la shell con permisos de root y la dejamos "esperando".

2

Nos informa de que se detuvo, y le asigna el número de referencia 1 para recuperarla posteriormente.

3

Recuperamos la shell con permisos de root.

Mediante suspend podemos detener la shell con permisos de root que arrancamos antes mediante su y recuperarla cada vez que necesitemos permisos de root sin necesidad de teclear el password de nuevo. Escribiendo exit en la shell con permisos de root podríamos abandonarla definitivamente.

su nos permite también adquirir los permisos de otros usuarios del sistema siempre que tengamos su password:

usuario@maquina $ su otrousuario
Password: [ Password de "otrousuario" ]
otrousuario@maquina $
otrousuario@maquina $ exit
usuario@maquina $

La diferencia entre su usuario y su - usuario es, que mientras que con el primer comando simplemente adquirimos los permisos de usuario, con el segundo comando es como si estuviésemos haciendo login desde el principio con usuario, así, todas las variables de entorno y demás serán cargadas igual que si hubiésemos hecho login realmente. Esto también se aplica para root (su -). La shell que se arranca mediante la segunda forma se llama shell de login, y como puedes comprobar, no se puede suspender como hicimos anteriormente. Salimos de ellas también con exit.

El usuario root puede usar su o bien su - sin necesidad de introducir ningún password para adquirir en un shell los permisos de cualquier usuario del sistema.


SUID

Existe un atributo especial en los permisos para que los archivos ejecutables puedan ser ejecutados con los permisos de su dueño, independientemente de quién sea el usuario que lo ejecute. Esto es considerado por algunos como una bondad de los sistemas UNIX, mientras que por otros se considera uno de sus pocos fallos. Al margen de ese debate, a nosotros, como usuarios normales, nos otorga una cierta comodidad de cara a aplicaciones como las que acceden directamente al grabador de CDs por ejemplo, que necesitan muchas veces permisos de root.

Así, en este ejemplo de las aplicaciones que graban CDs, asignaríamos su dueño a root. Poniendo el atributo SUID a estas aplicaciones, cualquier usuario que las ejecutase, lo haría con permisos de root (ya que en este caso sería el dueño del archivo ejecutable).

En casos como este, aplicar los atributos SUID a algunos programas resulta útil. Pero cuidado, aunque esto es una posibilidad en Linux, es algo que debe evitarse siempre que sea posible. Es muy peligroso desde el punto de vista de la seguridad del sistema. A la hora de ejecutar un usuario normal una aplicación que tenga el atributo SUID establecido, ejecuta ese proceso virtualmente como root. Si todo va bien, no tienen por qué existir problemas. Pero si la aplicación tuviese un fallo durante su ejecución, y retornase inesperadamente al shell por ejemplo, ¡el usuario normal habría adquirido permisos de root! sin necesidad de conocer su contraseña, y con esto podrá causar daños en el sistema y leer nuestra información confidencial.

Cuando hacemos un ls -l en un directorio donde exista un programa que sea SUID, en la columna donde se muestran los permisos, en vez de tener una x representando los permisos de ejecución, tendría una s indicando que ese programa es SUID, y que para los apartados (propietario, grupo propietario o resto de usuarios) donde esté esa "s", será posible ejecutarlo con los permisos del usuario propietario.

La forma de asignar el atributo SUID a los archivos ejectuables es la siguiente:

# chmod +s /usr/bin/miprograma

Recuerda que es mejor eludir este método por razones de seguridad.


Sudo

sudo (SUperuser DO) es una herramieta que permite otorgar a un usuario o grupos de usuarios normales, permisos para ejecutar algunos comandos como root (o como otros usuarios) sin necesidad de conocer su password. Es posible que no esté instalado en tu distribución de Linux y tengas que instalarlo tú. En capítulos posteriores tienes información sobre cómo instalar software adicional en el sistema.

El fundamento de sudo reside en su fichero de configuración, el fichero /etc/sudoers. Este fichero tiene, en los casos más sencillos, dos partes: una parte de alias y otra parte de reglas. La parte de alias, lo que hace es "agrupar" de alguna manera listas de usuarios y listas de aplicaciones (incluso listas de máquinas de una red, pero esto es más específico y no lo explicaremos aquí). La parte de reglas define qué grupos de usuarios pueden usar qué grupos de programas con permisos distintos de los suyos y en qué condiciones pueden hacerlo. Un fichero sencillo que nos podría servir podría ser como:

#
# Parte de alias
#

Cmnd_Alias GRABAR = /usr/bin/cdrecord, /usr/bin/cdrdao
Cmnd_Alias APAGAR = /sbin/halt, /sbin/reboot

User_Alias USERSGRAB = usuario1, usuario2

#
# Parte de reglas
#

USERSGRAB ALL = NOPASSWD: GRABAR

%cdrom ALL = NOPASSWD: GRABAR
%apagar ALL = NOPASSWD: APAGAR

Esto con respecto al fichero /etc/sudoers. En la parte de alias, Cmnd_Alias indica una lista de comandos (programas) que serán luego referidos mediante el nombre que le demos (asginar alias aquí tiene similitud con asignar variables de entorno en el shell). User_Alias agrupa a una lista de usuarios bajo un mismo nombre (en nuestro caso USERSGRAB).

En cuanto a la parte de reglas, primero se especifican los usuarios (puede ser un alias definido anteriormente como en el primer caso, o bien puede ser un grupo de usuarios del sistema, precediendo su nombre por %), el ALL que sigue hace referencia a en qué máquinas podrán hacer esto, y el NOPASSWD: indica que lo harán con permisos de root y sin necesidad de teclear su password. Después viene el alias con los comandos que podrán ejecutar en las condiciones que hemos dado.

Recuerda que el fichero /etc/sudoers se edita con el comando visudo, por razones de seguridad, y como root. sudo no altera la estructura de permisos del sistema de ficheros de Linux, es decir, por muchos cambios que hagamos en el fichero de configuración de sudo, los permisos de los programas seguirán siendo los mismos. La diferencia está en que estos "permisos especiales" que estamos otorgando a algunos usuarios se aplican cuando el programa que se quiere ejecutar se llama mediante sudo; así, un usuario que quiera ejectar el programa cdrdao con estos permisos especiales deberá hacerlo así:

$ sudo cdrdao [opciones]

Esto es lo más básico que necesitas saber sobre sudo para ejecutar algunos comandos cómodamente como usuario normal al tiempo que mantienes la seguridad del sistema. sudo es una herramienta que permite configuraciones mucho más complejas que las que hemos visto aquí; siempre puedes leer sus páginas del manual del sistema (man sudo y man sudoers), o visitar http://www.courtesan.com/sudo/.