miércoles, 13 de abril de 2011

Altas de usuario en Linux con Perl

¡Buf! Cuarto está resultando bastante más difícil de lo que nos habían hecho creer, y aunque en los exámenes no haya diferencia respecto a los años anteriores, nos están cosiendo a prácticas, reduciendo nuestra vida social a un porcentaje que podríamos denominar como... 0 (como dirían en Los Simpsons, "0 es un porcentaje"). En una de ellas sin ir más lejos, debemos programar en Perl un servidor Unix. En el apartado de alta de usuario me he encontrado con que la documentación disponible por Internet es prácticamente nula. Apenas hay uno o dos códigos de ejemplo y vagamente explicados (y en inglés, lo cual da bastante más pereza xD). Así pues, intentaré explicar aquí un poco el cómo funciona o cómo se puede hacer, si a alguien le sirve de ayuda genial, y si no, si alguna vez tengo que volver a hacerlo ya sé dónde tendré los "apuntes" jeje.


Lo primero de todo, es decir que se puede hacer de 2 maneras: Utilizando la orden useradd de Linux directamente o a pedal. En mi caso al final me he visto obligado a usar el useradd debido a que de la otra forma, bien porque no he sabido hacerlo o bien porque se le va la pelota a Linux a veces.

El script en concreto sería como sigue:

#!/usr/bin/perl

# Script que permite dar de alta un usuario.

# Author: Víctor Parra [parra@usal.es]

# AVISO: Requiere permisos de root
# Es necesrio instalar el File::Copy y el Linux::usermod
# ># perl -MCPAN -e 'install File::Copy::Recursive'
# ># perl -MCPAN -e 'install Linux::usermod'

# Parámetros:
# - [nombre_del_usuario] -> Nombre del nuevo usuario
# - [password]  -> Contraseña del nuevo usuario

$args=@ARGV;

if ($args < 2)
{
 print "\n";
 print "Uso: $0 [nombre_del_usuario] [password]\n";
 print "\n";
 print "\n";
 die "Abortando";
}

$ruta="/home/" . $ARGV[0] . "/";

$usuario=$ARGV[0];
use Linux::usermod;
use File::Copy;

print "La ruta /home es: $ruta \n";

my $pass=$ARGV[1];

mkdir $ruta;
chmod(0770, $ruta) || print $!;

Linux::usermod->add($usuario,$pass,'',100,'',$ruta,"/bin/bash") || print "USERADD: $! \n";
$user=Linux::usermod->new($usuario);
chown($user->get(uid), $user->get(gid), $ruta) || print "CHOWN USER: $! \n";

copy("/etc/skel/.bash_logout", $ruta . ".bash_logout");
copy("/etc/skel/.bashrc", $ruta . ".bashrc");
copy("/etc/skel/.profile", $ruta . ".profile");

$subruta = $ruta . "/" . "public_html";
mkdir $subruta;
chown($user->get(uid), $user->get(gid), $subruta) || print "CHOWN: $! \n";

`setquota -u $usuario 0 5120 0 0 -a $ruta`;

print "\nUsuario $usuario creado con éxito\n";
print "\n";
exit;

Lo que hacemos es lo siguiente:

- Debemos ejecutar el script pasándole como parámetros un nombre de usuario y la contraseña.
- En $ruta almacenamos el directorio HOME que tendrá el usuario concatenando la cadena "/home" con el nombre del usuario (almacenado en $ARGV[0]) mediante el operador . (punto)
- Indicamos que vamos a usar las librerías CPAN Linux::usermod y File::Copy mediante el comando use.
- Creamos la carpeta home y le modificamos los permisos.
- Creamos el usuario mediante el comando Linux::usermod->add pasándole como parámetros:
  • El nombre del usuario.
  • La contraseña.
  • El UID (lo dejamos en blanco para que asigne el correspondiente). OJO, hay que usar COMILLAS SIMPLES.
  • El GID (en nuestro caso 100, que se corresponde con el grupo "users" de Debian.
  • Los comentarios sobre el usuario (teléfono, nombre completo... etc.) También los dejamos en blanco mediante el uso de COMILLAS SIMPLES.
  • Obtenemos el usuario mediante Linux::usermod->new y lo almacenamos en la variable $user.
  • Modificamos el propietario y el grupo de la carpeta HOME del usuario mediante el comando chown pasándole como parámetros el UID del usuario (obtenido mediante $user->get(uid) ), el GID del grupo al que pertenece el usuario ($user->get(gid) ) y la ruta del directorio HOME.
  • Copiamos en dicho directorio los archivos del skel. El comando copy (obtenido de la librería File::Copy) tiene 2 parámetros: el primero que es la ruta por defecto donde están estos archivos, y el segundo el nombre del archivo donde lo queremos pegar (en nuestro caso es el directorio HOME concatenado con el nombre del archivo, de nuevo mediante el uso del operador .
- Una vez hecho esto creamos una subcarpeta en el directorio HOME llamada public_html (que en mi práctica era necesaria para guardar los archivos de la página web del usuario). NO es obligatorio crearla, pero si necesitáis crear una subcarpeta (o varias) sería seguir esos pasos, cambiando obviamente el nombre de la carpeta por el que quisiérais.

Finalmente le damos permisos de quota al usuario de 5Mb (tamaño que me exigían en la práctica) ejecutando el comando setquota a pedal (acotándolo entre acentos graves `). Este comando se puede omitir si en vuestro script no vais a usar quotas. En caso de que sí fuera, los parámetros pasados son:
  • $usuario -> Le indicamos el usuario al que le vamos a asignar los permisos (con la opción -u delante).
  • Límite soft de bloque -> Espacio en bloques que el usuario no deberá sobrepasar si no quiere recibir un aviso.
  • Límite hard de bloque -> Espacio en bloques que el usuario NO podrá superar.
  • Límite soft de inodos -> Número máximo de inodos que podrá tener el usuario antes de recibir avisos de que se excede su quota.
  • Límite hard de inodos -> Número máximo de inodos que el usuario podrá tener en esa partición del sistema.
  • $ruta -> Ruta en la cual se aplicarán las quotas (en nuestro caso, se trata del directorio HOME del usuario, del que no podrá salir. Se especifica mediante la opción -a).
Y nada más, espero que os sirva, si tenéis alguna duda, no os funciona, o sí os ha servido, podéis dejar un comentario que prometo responder :P

8 comentarios:

  1. Es menos peligroso que mezclar cosas en los laboratorios de Químicas xD (o eso espero :P).

    ResponderEliminar
  2. Hola! he probado tu script y funciona desde la shel perfectamente. El problema viene cuando lo llamo desde un formulario html que aparece un error en el mkdir (No such file or directory) si pongo otra ruta deja crear directorios xo en no home no hay forma. He pensado que desde consola soy root y pudeo hacerlo pero desde apache no soy root. ¿Hay que configurar algo de apache para que funcione correctamente?

    ResponderEliminar
    Respuestas
    1. Mmmmm... eso suena a que al ejecutarlo como root desde la shell, o como usuario en tu carpeta personal, como tienes permisos de escritura te deja, pero al ejecutarlo desde web, el usuario que intenta escribir es (o suele ser por defecto) el usuario www-data, y muy probablemente no tenga la carpeta donde intentas escribir, permisos de escritura para otros usuarios. Prueba una cosa:

      Crea una carpeta y cámbiale el usuario con el comando chown www-data:www-data (con esto lo que haces es convertir al usuario www-data en propietario de es carpeta) y después un chmod 755 .

      Después haz que tu formulario haga el mkdir dentro de esa carpeta, a ver si te deja escribir. Si es así, ya sabes cómo solucionarlo :).

      Eliminar
  3. Hola, estoy haciendo esta parte del mismo trabajo que hiciste en su día, básicamente tengo lo mismo que tu hecho, el problema es que tengo algunas dudas, y quería ver si podías resolvermelas.
    El caso es que tras varios intentos tratando de que el apache registre al usuario en /home/usuario (porque el que me ejecuta el codigo perl de esto es www-data) me he dado cuenta de que quizás el que tenga que ejecutar esto sea el usuario root. ¿Como puedo hacer esto? Llevo una semana atascado en esta parte y no puedo permitirme mas tiempo atascado aquí, ni siquiera se si este blog sigue activo, pero la verdad que necesito un empujoncito.

    ResponderEliminar
  4. Tengo el mismo problema que tu.
    ¿Has conseguido solucionarlo?
    Si fuese así te agradecería una ayuda.
    Gracias . Un saludo

    ResponderEliminar
  5. Gracias por tu aporte, todavía a estas alturas seguimos teniendo esa misma práctica en la carrera. Nos ha servido de mucha ayuda ya que no nos explican como programar en perl y luego nos lo exigen. Si sigues por Zamora, te invitamos a unas cañas.

    ResponderEliminar
    Respuestas
    1. ¡Muchas gracias!

      Por desgracia ya no estoy por allí, aunque sigo yendo cada poco :). Hace tiempo que dejé este blog (de hecho, me ha sorprendido el mail de nuevo comentario) para empezar un proyecto nuevo, ¡pero me alegra de que siga siendo útil esto!

      Apenas recuerdo nada de Perl (creo que desde la carrera no volví a tocarlo), pero sobre el propio script puede que aún pueda mantenerlo si hace falta... ¡por el precio de unas cañas qué menos!

      Eliminar

Las "disonancias gramaticales" no son bien recibidas en este blog así que, por favor, respeta la ortografía.
Nuestros ojos lo agradecerán.