Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

martes, 29 de noviembre de 2016

Cómo crear nuestros propios repositorios en Debian

Los repositorios tienen un valor incalculable en cualquier sistema Linux; especialmente en aquellos servidores en los que queremos tener las últimas actualizaciones de seguridad. Lo más normal es que no haya impedimento alguno para usar éstos, pero que sea lo más normal no implica que tenga que ocurrir siempre, ya sea debido a políticas de seguridad , a que el repositorio está caído o a que simplemente el equipo no tiene acceso a Internet... La ausencia de este recurso puede resultar fatal en muchos casos, con lo que es bueno contar siempre con un recurso que nos ayude a evadir ese escollo; un recurso que si bien a nivel doméstico no es muy práctico, es perfectamente aplicable en entornos empresariales o en entornos en los que hayan servidores.  Se trataría de tener estos repositorios almacenados en un equipo nuestro al cual sí que sería fácil acceder por el resto de equipos que estén dentro de la misma red; es decir, de tener estos repositorios en local. En este caso veríamos un caso aplicado a Debian, pero para sistemas parecidos tales como Ubuntu no deberíais experimentar problema alguno.

Debian_portada

Esta operación la única "pega" que puede llegar a tener es el hecho de que es necesario tener abundante espacio libre en el disco duro, pero quitando ese detalle, puede sernos una solución realmente útil, con lo que vamos a ello.

Para crear este repositorio, necesitaremos tener dos herramientas instaladas; una de ellas, muy conocida por muchos, sería apache2, mientras que la otra que es bastante menos conocida, sería apt-mirror, con lo que lo primero que haremos será instalarlos desde los repositorios oficiales del sistema (que todavía no serían locales) tal y como hacemos habitualmente.

apt-get install apache2 apt-mirror

La instalación es automática, si bien está instalación no hace que tengamos automáticamente los repositorios en local... Lo primero que necesitamos hacer es bajarnos toda la información, paquetes y otros datos de los repositorios que nosotros queramos en local, si bien para ello lo primero que habría que hacer sería configurar el archivo de configuración de apt-mirror, que se encontraría en /etc/apt/mirror.list. El fichero estaría compuesta por tres secciones: Configuración, repositorios a obtener, repositorios a limpiar. La parte más importante sería la de configuración, ya que es la que determina donde guardar los repositorios, la arquitectura en la que queremos que se descarguen los repositorios, etc... Un fichero de configuración real basado en un Debian 8 con arquitectura amd64 sería el siguiente:

  1. ############# config ##################
  2. #
  3.  set base_path    /var/spool/apt-mirror
  4. #
  5.  set mirror_path  $base_path/mirror
  6.  set skel_path    $base_path/skel
  7.  set var_path     $base_path/var
  8. # set cleanscript $var_path/clean.sh
  9. set defaultarch amd64
  10. # set postmirror_script $var_path/postmirror.sh
  11. # set run_postmirror 0
  12. set nthreads     20
  13. set _tilde 0
  14. #
  15. ############# end config ##############
  16. deb http://ftp.es.debian.org/debian/ jessie main contrib non-free
  17. deb-src http://ftp.es.debian.org/debian/ jessie main contrib non-free
  18. deb http://ftp.es.debian.org/debian/ jessie-updates main contrib non-free
  19. deb-src http://ftp.es.debian.org/debian/ jessie-updates main contrib non-free
  20. clean http://ftp.es.debian.org/debian

Gracias a esta configuración podríamos descargarnos los repositorios "estándar" de Debian 8 (Jessie) dentro del directorio /var/spool/apt-mirror, dentro del cual habrían tres carpetas: La carpeta mirror, la carpeta skel y la carpeta var.

Con los cambios guardados, únicamente habría que ejecutar el comando:

apt-mirror

Este comando hará que se creen las carpetas mirror, skel y var dentro del directorio /var/spool/apt-mirror y que se descargue toda la información de los repositorios en éstos; y al decir toda sería TODA. Es decir que nos estaríamos descargando la información necesaria para que nuestro equipo se pueda convertir en un repositorio.

El tamaño de la información descargada variaría dependiendo de la cantidad de repositorios que nos queramos descargar, pero por ejemplo, en mi caso en particular la descarga sería de 47 GB; una descarga que tomará MUCHO tiempo. También podríamos escoger menos repositorios con el fin de que sea de menor tamaño, pero a nivel conceptual este sería el proceso. Imaginemos que tenemos descargado todo el contenido... Éste estaría descargado, pero eso no significaría que fuese accesible por el resto de equipos; de ahí la necesidad de tener apache2 instalado. Ahora mismo el directorio /var/spool/apt-mirror/mirror tendría que tener la siguiente estructura en su interior:

Arbol_directorios

Queremos ser capaces de acceder vía web a los repositorios, tal y como haríamos con un repositorio real, pero en una red local... Con lo que tendríamos que hacer que dicho contenido pueda ser accedido desde la carpeta /var/www; mover el contenido a dicha carpeta sería engorroso y además cualquier futura actualización se bajaría de nuevo dentro del directorio /var/spool/apt-mirror, con lo que lo más limpio y práctico sería realizar un enlace simbólico desde /var/www a los directorios deseados; que en este caso sería únicamente el directorio Debian con lo que el enlace simbólico que haríamos sería el siguiente:

ln -s /var/spool/apt-mirror/mirror/ftp.es.debian.org/debian/ /var/www/debian

Ahora, para acceder a los repositorios de esta máquina, supongamos que ésta tiene la ip 192.168.1.10, para acceder a los repositorios de aquí en la red local, pondríamos estas líneas dentro del fichero /etc/apt/sources.list


  1. deb http://192.168.1.10/debian/ jessie main contrib non-free
  2. deb-src http://192.168.1.10/debian/ jessie main contrib non-free
  3. deb http://192.168.1.10/debian/ jessie-updates main contrib non-free
  4. deb-src http://192.168.1.10/debian/ jessie-updates main contrib non-free

Con esto podríamos acceder a unos repositorios que se hallen en la red local sin necesidad de acceder a Intenet.

Espero que os haya resultado útil.

Saludos.

martes, 22 de noviembre de 2016

Procesos zombie en Linux; qué son y cómo "matarlos"

Cualquiera que haya tratado con terminales Linux con cierta regularidad, se ha encontrado alguna vez en su vida con procesos "especiales" que no importa lo que hagan con ellos que no son capaz de "morir"; son procesos que están ahí "muertos" y que no consumen memoria RAM ni CPU, pero que el sistema todavía reconoce como existentes y que no importa lo que se haga con ellos que se resisten a desaparecer... Dichos procesos son llamados procesos zombie y si bien no tienen que causar problemas de rendimiento, su sola aparición hace que pensemos que dicho proceso está activo y pueden dar lugar a confusiones; es por eso que lo ideal es que ninguno de dichos zombies pululen por nuestro sistema operativo, por muy inofensivos que éstos sean.

Zombie_proceso

Los procesos zombie siempre son procesos dependientes de un proceso "padre" que no ha sido capaz de finalizar correctamente sus procesos "hijo", haciendo que estos sigan existiendo en el sistema aún cuando no consuman recursos... Este fenómeno es fácilmente comprobable en cualquier consola de Linux; pero antes, para asegurarnos que efectivamente va a existir un proceso zombie, crearemos varios "zombies" nosotros mismos a modo de prueba de concepto. Para ello tendríamos que crear un pequeño programa escrito en c llamado, por ejemplo, zombiegen.c cuyo contenido sería:

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. int main() {
  4.         pid_t pid;
  5.         int i=0;
  6.         while (1)  {
  7.                 pid = fork();
  8.                 if (pid > 0) {
  9.                         // Proceso padre
  10.                         printf("Padre %d\n",+ 1);
  11.                         sleep(1);
  12.                 } else {
  13.                         // Proceso hijo
  14.                         printf("Zombie %d\n",+ 1);
  15.                         exit(0);
  16.                 }
  17.         i++;
  18.         }
  19.         return 0;
  20. }

Después habría que compilar el programa mediante gcc tal que así:

gcc zombie.c -o zombie

Con esto haríamos que se creasen constantemente procesos zombie hasta que decidiésemos parar el programa. ¿Cómo podemos saber si el sistema tiene algún proceso zombie actualmente? Mediante el siguiente comando:

ps aux |grep defunct |grep -v grep

Al ser un bucle que crea procesos zombie constantemente podemos encontrarnos con algo como esto:

Lista_procesos_zombie

Si os fijáis bien en la línea en cuestión, veréis que una de sus columnas tiene una única letra; Z. Dicha Z significaría que dicho proceso tiene la etiqueta zombie, y que si bien no está operativo, dicho proceso en sí sigue existiendo en el sistema. Además veríamos también que todos los procesos finalizan con <defunct> que significaría que el proceso está parado, pero que todavía existe.

Ahora bien, ¿Cómo nos libramos de los zombies?  Tan simple como matando al padre de todos éstos, con lo que lo primero que tendríamos que ver es... ¿Quien es el padre de todos estos? Si conociésemos el PID (process ID) del padre, podríamos "matar" este para así automáticamente acabar con sus hijos... Esto puede parecer complejo pero es tan sencillo como hacer:

ps -eo pid,ppid,command | grep defunct |grep -v grep

Con esto listaríamos el numero de proceso de cada zombie, seguido del número de proceso de aquel que ha "creado" el zombie, junto con el comando.

En mi caso en particular me aparecería esto:

Padre_zombies

Si nos fijamos bien, veremos que todos comparten el mismo PPID (Parent Process ID) ... Es decir que todos dependen de dicho proceso para seguir existiendo así que únicamente tendríamos que acabar con éste proceso mediante un simple kill. En este caso tendríamos que detener el proceso con PID 4636.

kill -9 4636

Tras lo cual únicamente tendríamos que volver a ejecutar nuestro anterior comando para ver que efectivamente hemos acabado con todos ellos.

ps_sin_zombies

Como veis, el encontrar y acabar con estos procesos es muy sencillo; solamente hay que buscar procesos "defunct" y acabar con el proceso que los está generando... Obviamente para acabar con la raíz del problema habría que ver qué error de programación hay en el proceso padre, pero esto puede servirnos como una solución temporal para limpiar los procesos zombie hasta encontrar el verdadero origen de esta situación.

Espero que os haya resultado útil.

Saludos.

martes, 15 de noviembre de 2016

Cómo crear nuestro propio segundo factor de autenticación Linux

Anteriormente ya he hablado con respecto al concepto del segundo factor de autenticación, en concreto con la aplicada en las conexiones SSH.  Esta medida de seguridad ha ido ganando mucha relevancia durante los últimos años, y con razón pues añade una importante capa de seguridad extra a nuestros entornos... La cuestión está en que usando únicamente un segundo factor de autenticación en las conexiones SSH, hacemos que cualquiera que se loguee a nivel local no tenga restricciones para acceder al equipo, lo que puede resultar cómodo por un lado, pero inseguro por otro... Es por eso que hoy vamos a preparar un segundo factor de autenticación para cualquier login que se realice en Linux, ya sea local o remotamente. En concreto realizaremos un segundo factor de autenticación casero programado en Bash que, en mi opinión, le puede resultar útil a más de uno.

2fa_portada

Para ello lo primero que tenemos que tener en cuenta es donde podemos "interponer" nuestro segundo factor de autenticación... Es decir en qué parte del sistema podemos aplicar nuestro programa para que tanto los logins locales como remotos se vean afectados... El lugar más apropiado sería el fichero .bashrc alojado en la carpeta "home" de cada usuario, pues sabemos con toda seguridad que cualquier inicio de sesión ejecutará dicho programa y que dicho fichero es fácilmente editable... En mi caso en particular he aplicado el segundo factor de autenticación en el fichero /home/ivan/.bashrc; fichero al que le habría añadido está línea al final:

/usr/bin/2fa.sh

Esta línea simplemente significaría que, tras realizar todas las tareas correspondientes, ejecute el script 2fa.sh, script que de momento no existe (o que no debería existir) ya que dicho fichero va a ser fabricación nuestra. Empecemos a construir nuestro script paso a paso... Lo primero que tenemos que hacer es generar un código aleatorio que podamos usar en nuestra "nueva" autenticación... Con un código numérico tendría que ser suficiente, así que vamos a comenzar nuestro script con una pequeña función que genere un número aleatorio de 6 dígitos, si bien podemos hacer que dicho número sea mayor en caso de verlo necesario. Podemos escribir nuestro script con el editor que más cómodo nos sea, vi, nano, emacs... Lo importante sería que dicho script se llamase 2fa.sh y se alojase en /usr/bin. Además dicho script tendría que ser creado como root. Nuestro comienzo sería el siguiente:

  1. #!/bin/bash
  2. #VARIABLES
  3. CLAVE=""
  4. #GENERADOR NUMERO ALEATORIO
  5. function generador_clave()
  6. {
  7.         for i in `seq 1 6`;
  8.         do
  9.                 rand=$(( $RANDOM % 10 ))
  10.                 CLAVE="${CLAVE}${rand}"
  11.         done
  12. }
  13. generador_clave

Este comienzo como podéis ver es tan simple como crear una variable "vacía" llamada CLAVE. Luego crearíamos una función que asignaría 6 dígitos aleatorios a dicha variable y por último llamaríamos a la función. Algo muy sencillo y que de momento no entraña ninguna dificultad...

Esta clave sería la que luego tendríamos que usarla para autenticarnos con lo que es importante hacérnosla llegar... Aquí podemos pensar en diferentes métodos; algunos más laboriosos que otros, tales como el uso de un router GSM que nos envíe mensajes a nuestro móvil... Pero en este caso lo que queremos es una opción sencilla y que no requiera ningún tipo de inversión o de aparato "especial", con lo que en mi caso en particular me he decantado por enviar la clave por correo electrónico. Para ello habría que usar la aplicación sendemail; aplicación que no viene instalada por defecto en el sistema con lo que en caso de no tenerla instalada habría que instalarla vía consola mediante el comando:

apt-get install sendemail

Con esta aplicación instalada, antes de usarla en nuestro script es importante entender su funcionamiento... Esta aplicación lo que hace es que nos conectemos a una cuenta de correo mediante el protocolo SMTP, para después desde dicha cuenta de correo enviar una mail a un destinatario; acción para lo cual se usaría la siguiente sintaxis:

sendemail -f mail_origen -t mail_destino -xu "mail_origen" -xp "contraseña" -m "Contenido_mensaje" -s servidor_smtp:puerto -o tls=yes -u "Título_mail" 

Aquí lo único "especial" sería el servidor SMTP y el puerto a usar, ya que ambos datos variarían dependiendo de si el servidor es de un dominio u otro. Los correos más populares serían gmail y hotmail así que he aquí a continuación la lista de servidores SMTP de dichos servicios de correo.

Hotmail

Servidor: smtp.live.com
Puerto: 25

Gmail

Servidor: smtp.gmail.com
Puerto: 465

A sabiendas del comando y de la información de los servidores SMTP, podemos ahora darle más forma a nuestro script y darle la funcionalidad de enviarnos por correo la clave previamente generada, haciendo que tome el siguiente aspecto:

  1. #!/bin/bash
  2. #VARIABLES
  3. CLAVE=""
  4. #ACTIVACION TRAP
  5. trap '' 2 3 9 15
  6. #GENERADOR NUMERO ALEATORIO
  7. function generador_clave()
  8. {
  9.         for i in `seq 1 6`;
  10.         do
  11.                 rand=$(( $RANDOM % 10 ))
  12.                 CLAVE="${CLAVE}${rand}"
  13.         done
  14. }
  15. #ENVIADOR CORREO
  16. function enviador_mail()
  17. {
  18.     sendemail -f usuario@gmail.com -t destino@hotmail.com -xu "usuario@gmail.com" -xp "Contraseña" -m "${CLAVE}" -s smtp.gmail.com:465 -o tls=yes -u "2FA" > /dev/null
  19. }
  20. #LLAMADA FUNCIONES
  21. generador_clave
  22. enviador_mail

Con lo que tenemos ahora ya estaríamos mandando una clave aleatoria de 6 dígitos desde un correo de origen a un destino... Lo cual esta muy bien y se va acercando a lo que buscamos, pero que todavía no se trata de lo que buscamos, pues no se hace nada con dicha clave...

Ahora llegaría el turno de hacer que el usuario pueda introducir una clave manualmente y que ésta sea comparada con la clave que hemos enviado por correo. Aquí podemos optar por diferentes métodos de introducción de contraseña dependiendo de cómo nos logueemos; no es lo mismo loguearnos por consola que vía entorno gráfico, con lo que tendremos que hacer un script que se pueda adaptar a la situación dependiendo de nuestras necesidades. Para este script en concreto haremos que se pueda introducir la clave tanto por consola, como en entornos gráficos Gnome y KDE. Eso significaría que usaríamos 3 métodos de introducción de datos distintos:

  • Usaríamos el comando read para leer el dato introducido desde la consola. El comando sería read PASS (PASS el nombre de la variable que usaríamos para almacenar la contraseña).
  • Para la introducción de la contraseña mediante una interfaz gráfica, primero habría que ver si el entorno gráfico es gnome o KDE. En caso de ser KDE habría que usar la herramienta kdialog que usaría la sintaxis:
PASS=$(kdialog --title "PASSWORD" --inputbox "Introduce la contraseña")
  • Mientras que en Gnome la herramienta sería zenity, y la sintaxis sería esta:
PASS=$(zenity --entry --title "PASSWORD" --text "Introduce la contraseña")

Con estas introducciones haríamos que la variable PASS tuviese el valor introducido; variable que compararíamos con la clave. Obviamente haríamos que estas introducciones apareciesen constantemente hasta que la clave introducida coincida con la clave.

Con lo que recién acabamos de comentar, el script tomaría el siguiente aspecto, el cual como podéis ver, es mucho más completo. Un script que con lo que aparece a continuación ya sería funcional:

  1. #!/bin/bash
  2. #VARIABLES
  3. CLAVE=""
  4. PASS=""
  5. #GENERADOR NUMERO ALEATORIO
  6. function generador_clave()
  7. {
  8.         for i in `seq 1 6`;
  9.         do
  10.                 rand=$(( $RANDOM % 10 ))
  11.                 CLAVE="${CLAVE}${rand}"
  12.         done
  13. }
  14. #ENVIADOR CORREO
  15. function enviador_mail()
  16. {
  17.     sendemail -f usuario@gmail.com -t destino@hotmail.com -xu "usuario@gmail.com" -xp "Contraseña" -m "${CLAVE}" -s smtp.gmail.com:465 -o tls=yes -u "2FA" > /dev/null
  18. }
  19. #LLAMADA FUNCIONES
  20. generador_clave
  21. enviador_mail
  22. #DIALOGS PARA ENTORNO GRAFICO
  23. if [[ "$(env |grep DISPLAY)" = "DISPLAY=:0" ]]then
  24.     while [ "${CLAVE}" !"${PASS}" ]do
  25.         if [[ "$(env |grep XDG_CURRENT_DESKTOP)" = "KDE" ]]then #DIALOG PARA KDE
  26.             PASS=$(kdialog --title "PASSWORD" --inputbox "Introduce la contraseña")
  27.         else #DIALOG PARA GNOME
  28.             PASS=$(zenity --entry --title="PASSWORD" --text="Introduce la contraseña")
  29.         fi
  30.     done
  31. #TEXTO PLANO PARA CONSOLA
  32. else
  33.     while [ "${CLAVE}" !"${PASS}" ]do
  34.         echo 'Introduce la contraseña'
  35.         read PASS
  36.     done
  37. fi

Gracias a este script compararíamos la contraseña introducida (ya sea por consola o por interfaz gráfica) y haríamos que no dejase de pedir la contraseña hasta que sea la correcta... Es decir que el script en sí cumpliría su función, si bien todavía habría que mejorarlo un poco más, pues tiene pequeñas carencias...

La primera de ellas sería que cada vez que un usuario se loguee para lo que sea, pedirán el segundo factor de autenticación, aún cuando sea el mismo y simplemente haya abierto otra consola... Lo suyo sería que durante el tiempo que el equipo estuviese encendido, no volviese a pedir el segundo factor de autenticación, pues sino a la mínima tendríamos al sistema pidiéndonos una nueva clave de forma innecesaria, pues se da por hecho que si has pasado exitosamente la primera vez por dicho método, no hay necesidad de repetir dicha autenticación. Para ello simplemente habría que crear un fichero en el directorio temporal /tmp (que sabemos que vacía su contenido al reiniciar el equipo) cuya existencia se comprobaría dentro del fichero .bashrc para así saber si ejecutar el script o no. En mi caso he denominado a estos ficheros temporales token_${UID}, donde $UID sería el identificador del usuario. Por defecto dicho fichero no existiría, con lo que la primera vez siempre habría que crear dicho fichero mediante el script. Es por eso que en el fichero .bashrc haríamos que el script se ejecutase si el fichero NO existiese, lo cual ser haría modificando la última línea del dicho fichero para que tenga este aspecto:

  1. if [ ! -f /tmp/token_${UID}] ; then
  2.     /usr/bin/2fa.sh
  3. fi

Además, en el estado actual el script es bastante vulnerable; un simple ctrl + c en un login por consola lo detendría y haría que se saltasen este paso sin problemas... Es por ello que además del cambio atrás mencionado vamos a "atrapar" algunas señales para evitar esta situación mediante el comando trap; en concreto las señales 2 3 9 y 15. Obviamente, al finalizar el script deshabilitaríamos dicho "atrape".

Ambas modificaciones, tanto la evasión de la repetición, como la captura de ciertas señales harían que el script 2fa.sh tomase este aspecto:

  1. #!/bin/bash
  2. #VARIABLES
  3. CLAVE=""
  4. PASS=""
  5. #ACTIVACION TRAP
  6. trap '' 2 3 9 15
  7. #GENERADOR NUMERO ALEATORIO
  8. function generador_clave()
  9. {
  10.         for i in `seq 1 6`;
  11.         do
  12.                 rand=$(( $RANDOM % 10 ))
  13.                 CLAVE="${CLAVE}${rand}"
  14.         done
  15. }
  16. #ENVIADOR CORREO
  17. function enviador_mail()
  18. {
  19.     sendemail -f usuario@gmail.com -t destino@hotmail.com -xu "usuario@gmail.com" -xp "Contraseña" -m "${CLAVE}" -s smtp.gmail.com:465 -o tls=yes -u "2FA" > /dev/null
  20. }
  21. #LLAMADA FUNCIONES
  22. generador_clave
  23. enviador_mail
  24. #DIALOGS PARA ENTORNO GRAFICO
  25. if [[ "$(env |grep DISPLAY)" = "DISPLAY=:0" ]]then
  26.     while [ "${CLAVE}" !"${PASS}" ]do
  27.         if [[ "$(env |grep XDG_CURRENT_DESKTOP)" = "KDE" ]]then #DIALOG PARA KDE
  28.             PASS=$(kdialog --title "PASSWORD" --inputbox "Introduce la contraseña")
  29.         else #DIALOG PARA GNOME
  30.             PASS=$(zenity --entry --title="PASSWORD" --text="Introduce la contraseña")
  31.         fi
  32.     done
  33. #TEXTO PLANO PARA CONSOLA
  34. else
  35.     while [ "${CLAVE}" !"${PASS}" ]do
  36.         echo 'Introduce la contraseña'
  37.         read PASS
  38.     done
  39. fi
  40. #EVITAR REPETICION 2FA PARA UN MISMO USUARIO HASTA REINICIO
  41. if [ "${CLAVE}" = "${PASS}" ]then
  42.     touch /tmp/token_${UID}
  43.     chmod 400 /tmp/token_${UID}
  44. fi
  45. #DESACTIVACION TRAP
  46. trap - 2 3 9 15

Ahora sí que tendríamos un script que no solo es funcional, sino que también puede usarse en situaciones reales... Un script que añadiría una capa de seguridad adicional a nuestro sistema y que únicamente requiere añadir la llamada al script /usr/bin/2fa.sh en el fichero .bashrc de cada usuario que queremos que tenga doble seguridad. Solo quedaría por hacer una cosa más en nuestro script, que sería opcional y dependería de si tenemos varios usuarios usando el mismo equipo (con diferentes cuentas de usuario, se entiende). Este script requiere especificar a mano todos los datos de mail, el origen, el destino, usuario, contraseña... Al ser un binario que va a ser usado por todos los usuarios, tendríamos que ver si nos merece la pena o no poner o no diferentes configuraciones de correo dependiendo del usuario...

En caso de querer tener flexibilidad con dicho dato, el cual es bastante personal y que no queremos que el resto de usuarios vea... Podemos hacer que cada usuario tenga una configuración especial y que en caso de que no haya configuración especial alguna para dicho usuario, se use un correo genérico. Esto se podría lograr gracias a la privacidad que nos ofrece la carpeta home. Cada usuario tiene una carpeta /home/nombre_usuario a la que solamente pueden acceder ellos y root con lo que podemos crear un fichero con un nombre y una estructura determinada que sirva para extraer los datos de allí y usarlos. Por ejemplo podríamos crear un fichero llamado llamado User2fa dentro de nuestro directorio home (por ejemplo dentro de /home/ivan en mi caso) que tuviese la estructura:

  1. DE: usuario@gmail.com
  2. A: destino@hotmail.com
  3. USUARIO: "usuario@gmail.com"
  4. PWD: "Contraseña"
  5. SERVIDOR: smtp.gmail.com
  6. PUERTO: 465

Con estos datos, simplemente habría que recorrer el fichero y recoger los valores para luego ponerlos en la posición indicada del script... Algo tan sencillo como editar la función enviador_mail y hacer que el aspecto final sea este:

  1. #!/bin/bash
  2. #VARIABLES
  3. CLAVE=""
  4. PASS=""
  5. #ACTIVACION TRAP
  6. trap '' 2 3 9 15
  7. #GENERADOR NUMERO ALEATORIO
  8. function generador_clave()
  9. {
  10.         for i in `seq 1 6`;
  11.         do
  12.                 rand=$(( $RANDOM % 10 ))
  13.                 CLAVE="${CLAVE}${rand}"
  14.         done
  15. }
  16. #ENVIADOR CORREO
  17. function enviador_mail()
  18. {
  19.     # SI EXISTE EL fichero User2fa, usamos los datos de este
  20.     if [ -f ~/User2fa ]then
  21.         i=1
  22.         while [ ${i} -le 6 ]do
  23.             VAR[${i}]="$(head -n ${i} ~/User2fa |tail -n -1 |awk '{print $2}')"
  24.             i=$(($i + 1))
  25.         done
  26.         sendemail -f ${VAR[1]} -t ${VAR[2]} -xu "${VAR[3]}" -xp "${VAR[4]}" -m "${CLAVE}" -s ${VAR[5]}:${VAR[6]} -o tls=yes -u "2FA" >/dev/null
  27.     else # EN CASO CONTRARIO, USAMOS UNOS DATOS GENERICOS
  28.         sendemail -f usuario@gmail.com -t destino@hotmail.com -xu "usuario@gmail.com" -xp "Contraseña" -m "${CLAVE}" -s smtp.gmail.com:465 -otls=yes -u "2FA" > /dev/null
  29.     fi
  30. }
  31. #LLAMADA FUNCIONES
  32. generador_clave
  33. enviador_mail
  34. #DIALOGS PARA ENTORNO GRAFICO
  35. if [[ "$(env |grep DISPLAY)" = "DISPLAY=:0" ]]then
  36.     while [ "${CLAVE}" !"${PASS}" ]do
  37.         if [[ "$(env |grep XDG_CURRENT_DESKTOP)" = "KDE" ]]then #DIALOG PARA KDE
  38.             PASS=$(kdialog --title "PASSWORD" --inputbox "Introduce la contraseña")
  39.         else #DIALOG PARA GNOME
  40.             PASS=$(zenity --entry --title="PASSWORD" --text="Introduce la contraseña")
  41.         fi
  42.     done
  43. #TEXTO PLANO PARA CONSOLA
  44. else
  45.     while [ "${CLAVE}" !"${PASS}" ]do
  46.         echo 'Introduce la contraseña'
  47.         read PASS
  48.     done
  49. fi
  50. #EVITAR REPETICION 2FA PARA UN MISMO USUARIO HASTA REINICIO
  51. if [ "${CLAVE}" = "${PASS}" ]then
  52.     touch /tmp/token_${UID}
  53.     chmod 400 /tmp/token_${UID}
  54. fi
  55. #DESACTIVACION TRAP
  56. trap - 2 3 9 15

Gracias a estos cambios finales realizados no solo tendríamos un segundo factor de autenticación sino que además tendríamos unos datos de mail adaptados a las necesidades de cada usuario, ofreciendo la flexibilidad de que cada usuario que use el segundo factor de autenticación pueda escoger el mail de origen y de destino a su completo gusto.

Espero que os haya resultado útil.

Saludos.