#+title: instalador-firma.sh #+property: header-args :tangle instalador-firma.sh Script de instalación de firma digital. Busca ser compatible con el estándar de shell de POSIX a nivel de sintaxis, pero su funcionalidad está limitada a Linux y macOS. *Probado en estas distribuciones:* - [X] Debian 12 - [ ] Fedora 40 - [ ] Arch Linux [date] * TODO [0/4] - [ ] Configurar opciones como variables e.g. definir previamente =$MENU= para utilizar la terminal como menu en lugar de la opción disponible como zenity o kdialog - [ ] Permitir instalación no interactiva e.g. Si se tiene todo para proceder (con variables), no pedir nada. - [ ] Funciones =reinstall_certs=, =uninstall_certs= *Nota:* Mantener el uso de =$PROMPT...= en =Main= - [ ] Menu instalar/desinstalar/salir *Nota:* Mantener el uso de =$PROMPT...= en =Main= - [ ] Función =is_installed= =0= dispara el menu, =1= dispara la instalación, =2= dispara el menu con aviso de instalación previa fallida. * Script ** Shebang #+begin_src shell #!/bin/sh #+end_src ** Utilidades *** =pseudo= ``Pseudo sudo'' facilidad para ejecutar comandos como administrador. #+begin_src shell alias pseudo='printf "%s" "$SUDO_PASSWORD" | sudo -Skp ""' #+end_src *** =echo_debug= Notificaciones del estado del script. Uso: =echo_debug "Mensaje"= #+begin_src shell echo_debug() { printf '\033[1mDEBUG:\033[0m \033[2m%s...\033[0m\n' "$1" } #+end_src *** =urlencode= Función para convertir texto al formato correcto de URL, existen programas externos o quizás se pueda lograr solamente con =sed= pero esta forma es más robusta. También es menos portable, pero el script depende de =curl= de todas formas. Uso: =printf 'hól#a' | urlencode=, output: =h%c3%b3l%23a= #+begin_src shell urlencode() { ENCODEDURL="$(curl -Gs -w '%{url_effective}' --data-urlencode @- ./ ||: )" printf '%s' "$ENCODEDURL" | sed 's/%0[aA]$//;s/^.*[?]//' # %0a al final de la línea es } # un comportamiento no deseado. #+end_src *** =get_asp_var= Esta función requiere de una variable =$RESPONSE= que sería el html respuesta de un request, a partir de esto, devuelve la string de data que tiene retorna al servicio en un request posterior. #+begin_src shell get_asp_var() { i=0 for VAR in __VIEWSTATE __VIEWSTATEGENERATOR __EVENTVALIDATION ; do VAL="$(printf '%s' "$RESPONSE" | grep "id=\"$VAR\"" | cut -d '"' -f 8 | urlencode)" [ "$i" != 0 ] && printf '&' printf '%s=%s' "$VAR" "$VAL" i=+1 done } #+end_src *** =set_version= Sin ninguna dependiencia, solamente funciones incluidas en el estándar POSIX, determina la variable =$VERSION= que será utilizada para seleccionar automáticamente el fichero que debe descargar en =get_archive=. Nota: Se desactiva el error de =SC1090=, ya que es una limitación de =shellcheck= y es una funcionalidad válida dentro del estándar POSIX. #+begin_src shell set_version() { # shellcheck disable=SC1090 for os in /etc/os-release /usr/lib/os-release; do [ -f $os ] && . $os && break done case "$ID" in centos) [ -n "$VERSION_ID" ] && [ "$VERSION_ID" -ge 9 ] && ID="fedora" ;; *suse*|sles|sled) ID="suse" ;; debian|ubuntu) ID="debian" ;; fedora|rhel) ID="fedora" ;; arch|manjaro) ID="arch" ;; *) ID="${ID_LIKE%% *}" ;; esac [ "$ID" = "ubuntu" ] && ID="debian" [ "$ID" = "rhel" ] && ID="fedora" [ -f /System/Library/CoreServices/SystemVersion.plist ] && ID="macos" case "$ID" in debian) VERSION="Usuarios Linux (DEB 64bits)" ;; fedora) VERSION="Usuarios Linux (RPM 64bits)" ;; suse) VERSION="Usuarios Linux (RPM 64bits)" ;; arch) VERSION="Usuarios Linux (RPM 64bits)" ;; centos) VERSION="Usuarios Linux RPM (CentOS 7)" ;; macos) VERSION="Usuarios MAC" ;; *) return 1 ;; esac } #+end_src *** =get_archive= Utiliza =urlencode= y =get_asp_var= para realizar el procedimiento de descarga. Necesita que =$VERSION= esté definida (después de ejecutar =set_version=) ya que utilizará este parámetro para consultar en el servicio el instalador que debe descargar (el más actualizado de y correspondiente al sistema). #+begin_src shell get_archive() { URL="https://soportefirmadigital.com/sfdj/dl.aspx" VERSION="$(printf '%s' "$VERSION" | urlencode)" RESPONSE="$(curl -s --compressed "$URL" -o -)" ASP_VARS="$(get_asp_var)" FILE="$(curl -s "$URL" --data-raw "$ASP_VARS" --data-raw "ctl00%24certContents%24ddlInstaladores=$VERSION" | grep 'hiddenISO.*value="' | sed 's/^.*value="//g;s/".*$//g')" [ -z "$FILE" ] && return 1 TEMPKEY="$(curl -s --compressed "$URL" --data-raw "$ASP_VARS" \ --data-raw "__EVENTTARGET=ctl00%24certContents%24LinkButton3" \ --data-raw "ctl00%24certContents%24hiddenISO=$FILE" \ --data-raw "ctl00%24certContents%24txtSerialNumber=$SERIAL" \ --data-raw "ctl00%24certContents%24chkConfirmo=on" \ -o - | sed '/tempkey/!d;s/.*tempkey=//g;s/".*$//g')" [ -z "$TEMPKEY" ] && return 1 printf '%s %s' "$FILE" "$TEMPKEY" } #+end_src *** =set_menu= (revisar) (No creo que este sea necesario) #+begin_src shell set_menu() { if [ -z "$MENU" ] ; then command -v zenity > /dev/null && MENU="zenity" && return 0 command -v kdialog > /dev/null && MENU="kdialog" && return 0 MENU="term" fi } #+end_src *** =menu= Esto más que nada es una forma de abreviar los comandos y de mantener consistente la ejecución principal, de manera que se llama a esta función y determina desde un lugar cómo proceder con la notificación y entrada del usuario. Nota: =SC2034= se desactiva porque a pesar de que =$nil= es una variable sin utilizar, permite la portabilidad del script con otras implementaciones. #+begin_src shell menu() { MODE="$1" PROMPT="$2" if [ "$MENU" = "zenity" ] ; then echo_debug "MENU: $MENU MODE: $MODE PROMPT: $PROMPT" > /dev/stderr [ "$MODE" = "info" ] && zenity --title "$TITLE" --text "$PROMPT" --info [ "$MODE" = "error" ] && zenity --title "$TITLE" --text "$PROMPT" --error > /dev/stderr [ "$MODE" = "entry" ] && zenity --title "$TITLE" --text "$PROMPT" --entry [ "$MODE" = "pass" ] && zenity --title "$TITLE" --password elif [ "$MENU" = "term" ] ; then # shellcheck disable=SC2034 [ "$MODE" = "info" ] && printf '\n\033[1m\033[34m=== %s ===\033[0m\n%s ENTER' "$TITLE" "$PROMPT" >/dev/stdin && read -r nil [ "$MODE" = "error" ] && printf '\n\033[1m\033[31m=== %s ===\033[0m\n%s\n' "$TITLE" "$PROMPT" >/dev/stderr [ "$MODE" = "entry" ] && printf '\n\033[1m\033[34m=== %s ===\033[0m\n%s\n -> ' "$TITLE" "$PROMPT" >/dev/stdin && IFS= read -r entry && printf '%s' "$entry" [ "$MODE" = "pass" ] && printf '\n\033[1m\033[34m=== %s ===\033[0m\n%s\n -> ' "$TITLE" "$PROMPT" >/dev/stdin && IFS= read -r passwd && printf '%s' "$passwd" fi } #+end_src ** Lenguaje =/etc/default/locale= contiene información del lenguage por defecto, obtiene el lenguaje de esta locación si no está previamente definido (por el sistema o por el usuario utilizando, por ejemplo, =LANG=es=). Utiliza español por defecto si logra definir el lenguaje. #+begin_src shell set_lang() { # See: /var/lib/AccountsService/users/ ! [ "$LANG" ] && [ -f "/etc/default/locale" ] && . /etc/default/locale SLANG="${LANG%%_*}" [ -z "$SLANG" ] && SLANG="es" if [ "$SLANG" = "es" ] ; then TITLE="Instalador firma digital" PROMPT_WELCOME="Bienvenido al asistente de instalación de certificados para firma digial." PROMPT_ERR_DEPS="Error, la instalación requiere de los siguientes programas no presentes: " PROMPT_SERIAL="Ingrese el número serial impreso al reverso de la tarjeta." PROMPT_ERR_SERIAL="Error al obtener el número serial de la tarjeta, abortando." PROMPT_DOWNLOAD="Descargando desde Centro de Soporte Firma Digital..." PROMPT_DEPS_INSTALL="Instalando dependencias y otros complementos..." PROMPT_PASS_DEPS_INSTALL="Ingrese la contraseña del equipo para instalar los componentes" PROMPT_ERR_DEPS_INSTALL="Error instalando dependencias." PROMPT_ERR_DOWNLOAD="Error al descargar el fichero, abortando." PROMPT_END_SUCCESS="El instalador ha concluido." elif [ "$SLANG" = "en" ] ; then TITLE="Digital signature installer" PROMPT_WELCOME="Welcome to the digital signing certificate installation wizard." PROMPT_ERR_DEPS="Error, installation requires the following programs not present: " PROMPT_SERIAL="Enter the serial number printed on the back of the card." PROMPT_ERR_SERIAL="Error obtaining the card serial number, aborting." PROMPT_DOWNLOAD="Downloading from the Digital Signature Support Center..." PROMPT_DEPS_INSTALL="Installing dependencies and other components..." PROMPT_PASS_DEPS_INSTALL="Enter your computer password to install components" PROMPT_ERR_DEPS_INSTALL="Error installing dependencies." PROMPT_ERR_DOWNLOAD="Error downloading file, aborting." PROMPT_END_SUCCESS="The installer has completed." elif [ "$SLANG" = "fr" ] ; then TITLE="Installation de signature" PROMPT_WELCOME="Bienvenue dans l'assistant d'installation du certificat de signature." PROMPT_ERR_DEPS="Erreur, l'installation requise des programmes suivants ne présente pas: " PROMPT_SERIAL="Entrez le numéro de série imprimé au dos de la carte." PROMPT_ERR_SERIAL="Erreur d'obtention du numéro de série de la carte, abandon." PROMPT_DOWNLOAD="Téléchargement du fichier depuis le Centre de support des signatures numériques..." PROMPT_DEPS_INSTALL="Installation des dépendances et d'autres composants..." PROMPT_PASS_DEPS_INSTALL="Entrez le mot de passe de votre ordinateur pour installer les composants" PROMPT_ERR_DEPS_INSTALL="Erreur lors de l'installation des dépendances." PROMPT_ERR_DOWNLOAD="Erreur de téléchargement du fichier, abandon." PROMPT_END_SUCCESS="Le programme d'installation est terminé." fi } #+end_src ** Instalación Proceso de instalación para dependiendo de su base, ya sea con el =$ID= o =$ID_LIKE=, esto se define en =get_version=. Se deshabilita =SC2016= ya que esta parte debe correr sin expandir las variables. *** Debian #+begin_src shell debian_install_certs() { # Source: https://fran.cr/instalar-firma-digital-costa-rica-gnu-linux-ubuntu-debian/ echo_debug "Instalando dependencias" pseudo apt-get install -y unzip binutils p11-kit pcscd bubblewrap icedtea-netx > /dev/null || return 1 echo_debug "Extraer fichero" [ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1 (cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null) || return 1 echo_debug "Copiar certificados" for cert in "$(find "$SAVE_DIR" -name "Certificados")"/* ; do certname="${cert##*/}" pseudo cp "$cert" /usr/local/share/ca-certificates/"${certname%.cer}.crt" done echo_debug "Extraer módulo privativo" PACKAGE="$(find "$SAVE_DIR" -name "idprotectclient[-_]*.deb")" PACKAGE_DIR="${PACKAGE%/*}" PACKAGE="${PACKAGE##*/}" [ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1 (cd "$PACKAGE_DIR" && ar p "$PACKAGE" data.tar.gz | tar zx ./usr/lib/x64-athena/libASEP11.so) pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib/x86_64-linux-gnu/ echo_debug "Symlinks y componentes..." # shellcheck disable=SC2016 pseudo sh -c ' # --- Certificados --- for file in /usr/local/share/ca-certificates/*.crt ; do openssl x509 -inform DER -in "$file" -out "$file.tmp" 2> /dev/null ; done find /usr/local/share/ca-certificates/ -type f -empty -delete for i in /usr/local/share/ca-certificates/*.tmp ; do mv "$i" "${i%.tmp}" ; done update-ca-certificates --fresh > /dev/null # --- Instalación del módulo PKCS#11 --- mkdir -p /usr/lib/x64-athena mkdir -p /Firma_Digital/LIBRERIAS ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/x64-athena/ ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/ ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/local/lib/ ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /Firma_Digital/LIBRERIAS/ ln -sf /usr/local/share/ca-certificates /Firma_Digital/CERTIFICADOS systemctl enable --now pcscd.socket > /dev/null ' echo_debug "Configurando IDPClientDB" pseudo sh -c " mkdir -p /etc/Athena echo \" 3BDC00FF8091FE1FC38073C821106600000000000000 FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000 3BEA00008131FE450031C173C840000090007A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \" > /etc/Athena/IDPClientDB.xml " echo_debug "Configurando p11-kit/modules" pseudo sh -c " mkdir -p /usr/share/p11-kit/modules echo 'remote: |bwrap --unshare-all --dir /tmp --ro-bind /etc/Athena /etc/Athena --proc /proc --dev /dev --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /var/run/pcscd /var/run/pcscd --ro-bind /run/pcscd /run/pcscd p11-kit remote /usr/lib/x86_64-linux-gnu/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module " echo_debug "Configurando p11-kit update symlinks" pseudo sh -c " mkdir -p /usr/local/sbin echo \"#!/bin/sh FIREFOX_LIB=/usr/lib/firefox/libnssckbi.so FIREFOX_ESR_LIB=/usr/lib/firefox-esr/libnssckbi.so THUNDERBIRD_LIB=/usr/lib/thunderbird/libnssckbi.so NSS_LIB=/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so if [ -e \"\$FIREFOX_LIB\" ] then if ! [ -L \"\$FIREFOX_LIB\" ] then echo \"Firefox libnssckbi.so is not a symlink. Fixing...\" mv -f \"\$FIREFOX_LIB\" \"\$FIREFOX_LIB\".bak ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$FIREFOX_LIB\" fi fi if [ -e \"\$FIREFOX_ESR_LIB\" ] then if ! [ -L \"\$FIREFOX_ESR_LIB\" ] then echo \"Firefox ESR libnssckbi.so is not a symlink. Fixing...\" mv -f \"\$FIREFOX_ESR_LIB\" \"\$FIREFOX_ESR_LIB\".bak ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$FIREFOX_ESR_LIB\" fi fi if [ -e \"\$THUNDERBIRD_LIB\" ] then if ! [ -L \"\$THUNDERBIRD_LIB\" ] then echo \"Thunderbird libnssckbi.so is not a symlink. Fixing...\" mv -f \"\$THUNDERBIRD_LIB\" \"\$THUNDERBIRD_LIB\".bak ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$THUNDERBIRD_LIB\" fi fi if [ -e \"\$NSS_LIB\" ] then if ! [ -L \"\$NSS_LIB\" ] then echo \"NSS libnssckbi.so is not a symlink. Fixing...\" mv -f \"\$NSS_LIB\" \"\$NSS_LIB\".bak ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$NSS_LIB\" fi fi\" > /usr/local/sbin/update-p11-kit-symlinks chmod +x /usr/local/sbin/update-p11-kit-symlinks " echo_debug "Configurando módulo mantenimiento systemd" pseudo sh -c " mkdir -p /etc/systemd/system echo \"[Unit] Description=mantenimiento de enlaces a p11-kit-proxy [Service] Type=oneshot ExecStart=/usr/local/sbin/update-p11-kit-symlinks [Install] WantedBy=multi-user.target \" > /etc/systemd/system/p11-kit-proxy-updater.service systemctl enable --now p11-kit-proxy-updater.service > /dev/null " echo_debug "Instalando trust module pk11" pseudo sh -c " mkdir -p /etc/pkcs11/modules echo 'disable-in:' > /etc/pkcs11/modules/p11-kit-trust.module " } #+end_src *** Fedora #+begin_src shell fedora_install_certs() { # Source: https://fran.cr/instalar-firma-digital-costa-rica-gnu-linux-fedora/ echo_debug "Instalando dependencias" pseudo dnf -y install unzip pcsc-lite icedtea-web > /dev/null || return 1 echo_debug "Extraer fichero" [ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1 (cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null) || return 1 echo_debug "Copiar certificados" pseudo cp -p "$(find "$SAVE_DIR" -name "Certificados")"/* /usr/share/pki/ca-trust-source/anchors/ pseudo update-ca-trust echo_debug "Extraer módulo privativo" PACKAGE="$(find "$SAVE_DIR" -name "idprotectclient[-_]*.rpm")" PACKAGE_DIR="${PACKAGE%/*}" PACKAGE="${PACKAGE##*/}" [ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1 (cd "$PACKAGE_DIR" && rm -r ./usr/lib/x64-athena/libASEP11.so rpm2cpio "$PACKAGE" | cpio -dim ./usr/lib/x64-athena/libASEP11.so) || return 1 pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib64/ echo_debug "Symlinks y componentes..." pseudo sh -c ' mkdir -p /usr/lib/x64-athena/ mkdir -p /Firma_Digital/LIBRERIAS/ ln -sf /usr/lib64/libASEP11.so /usr/lib/x64-athena/ ln -sf /usr/lib64/libASEP11.so /usr/lib/ ln -sf /usr/lib64/libASEP11.so /usr/local/lib/ ln -sf /usr/lib64/libASEP11.so /Firma_Digital/LIBRERIAS/ ln -sf /usr/share/pki/ca-trust-source/anchors /Firma_Digital/CERTIFICADOS systemctl enable --now pcscd.socket > /dev/null ' echo_debug "Configurando IDPClientDB" pseudo sh -c " mkdir -p /etc/Athena echo \" 3BDC00FF8091FE1FC38073C821106600000000000000 FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000 3BEA00008131FE450031C173C840000090007A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \" > /etc/Athena/IDPClientDB.xml " echo_debug "Configurando p11-kit/modules" pseudo sh -c " mkdir -p /usr/share/p11-kit/modules echo 'remote: |bwrap --unshare-all --dir /tmp --proc /proc --dev /dev --ro-bind /etc/Athena /etc/Athena --ro-bind /usr /usr --ro-bind /var/run/pcscd /var/run/pcscd --ro-bind /run/pcscd /run/pcscd --symlink /usr/lib64 /lib64 p11-kit remote /usr/lib64/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module " } #+end_src *** Arch Linux #+begin_src shell arch_install_certs() { echo_debug "Instalando dependencias" pseudo pacman -S --noconfirm --needed unzip cpio rpm-tools pcsclite ccid jre8-openjdk icedtea-web > /dev/null || return 1 echo_debug "Extraer fichero" [ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1 (cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null) echo_debug "Copiar certificados" pseudo cp -p "$(find "$SAVE_DIR" -name "Certificados")"/* /usr/share/ca-certificates/trust-source/anchors/ pseudo update-ca-trust echo_debug "Extraer módulo privativo" [ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1 (cd "$PACKAGE_DIR" && rpm2cpio "$PACKAGE" | cpio -dim ./usr/lib/x64-athena/libASEP11.so) pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib/ echo_debug "Symlinks y componentes..." pseudo sh -c ' mkdir -p /usr/lib/x64-athena/ mkdir -p /Firma_Digital/LIBRERIAS/ ln -sf /usr/lib/libASEP11.so /usr/lib/x64-athena/ ln -sf /usr/lib/libASEP11.so /usr/local/lib/ ln -sf /usr/lib/libASEP11.so /Firma_Digital/LIBRERIAS/ ln -sf /usr/share/ca-certificates/trust-source/anchors /Firma_Digital/CERTIFICADOS ln -sf /usr/lib/p11-kit-proxy.so /usr/lib/firefox/libosclientcerts.so systemctl enable --now pcscd.socket > /dev/null ' echo_debug "Configurando IDPClientDB" pseudo sh -c " mkdir -p /etc/Athena echo \" 3BDC00FF8091FE1FC38073C821106600000000000000 FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000 3BEA00008131FE450031C173C840000090007A FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \" > /etc/Athena/IDPClientDB.xml " echo_debug "Configurando p11-kit/modules" pseudo sh -c " mkdir -p /usr/share/p11-kit/modules echo 'remote: |bwrap --unshare-all --dir /tmp --proc /proc --dev /dev --ro-bind /etc/Athena /etc/Athena --ro-bind /usr /usr --ro-bind /lib64 /lib64 --ro-bind /run/pcscd /run/pcscd p11-kit remote /usr/lib/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module " } #+end_src *** Función wrapper Encargarse de la instalación simplemente llamando =install_certs=. #+begin_src shell install_certs() { [ -z "$SUDO_PASSWORD" ] && return 1 [ -z "$SAVE_FILE" ] && return 1 SAVE_DIR="${SAVE_FILE%/*}" if [ "$ID" = "macos" ] ; then open "$SAVE_FILE" || return 1 elif [ "$ID" = "debian" ] ; then debian_install_certs || return 1 elif [ "$ID" = "fedora" ] ; then fedora_install_certs || return 1 elif [ "$ID" = "arch" ] ; then arch_install_certs || return 1 elif [ "$ID" = "centos" ] ; then echo || return 1 fi } #+end_src ** Main *** TODO Inicializar [0/2] - [ ] Tirar =exit 1= en caso de no poder seleccionar una versión o un menu. - [ ] Agregar otras dependencias mínimas, o que no conviene instalarlas en el script (sudo) #+begin_src shell set_lang set_version set_menu if ! command -v curl > /dev/null ; then menu error "$PROMPT_ERR_DEPS curl" exit 1 fi menu info "$PROMPT_WELCOME" #+end_src *** No. Serial #+begin_src shell SERIAL="${SERIAL:=$(menu entry "$PROMPT_SERIAL")}" if [ -z "$SERIAL" ] ; then menu error "$PROMPT_ERR_SERIAL" exit 1 fi #+end_src *** Proceso de descarga **** Obtener URL e información del fichero #+begin_src shell ARCHIVE="$(get_archive)" TEMPKEY="${ARCHIVE##* }" FILE="${ARCHIVE%% *}" DOWNLOAD_URL="$( printf 'https://soportefirmadigital.com/sfdj/getiso.aspx?tempkey=%s' \ "$TEMPKEY" )" SIZE="$(curl -sI "$DOWNLOAD_URL" | sed '/[Cc]ontent-[Ll]ength/!d;s/^.*: //g' | awk '{$1/=1024;printf "%d",$1}' )" if [ "$SIZE" -lt 500 ] || [ -z "$FILE" ] ; then menu error "$PROMPT_ERR_DOWNLOAD" exit 1 fi #+end_src **** Descarga Se desactiva =SC2009= para asegurarse de tener el ID correcto, ya que terminará el proceso en caso de seguir activo. #+begin_src shell SAVE_DIR="/tmp/soportefirmadigital" SAVE_FILE="$SAVE_DIR/$FILE" mkdir -p "$SAVE_DIR" if [ "$MENU" = "zenity" ] ; then (curl -sL "$DOWNLOAD_URL" -o "$SAVE_FILE") & while true ; do sleep 0.5 DOWN="$(du "$SAVE_FILE" 2>/dev/null | awk '{print $1}')" [ -z "$DOWN" ] && DOWN=0 r=$(((DOWN*10000)/SIZE)) printf '%d\n' ${r%??} done | zenity --title "$TITLE" --text "$PROMPT_DOWNLOAD" --progress --auto-close elif [ "$MENU" = "term" ] ; then menu info "$PROMPT_DOWNLOAD" && echo curl "$DOWNLOAD_URL" -o "$SAVE_FILE" --progress-bar fi # shellcheck disable=SC2009 ACTIVE="$(ps -t | grep 'curl.*soportefirmadigital' | sed '/grep/d')" ACTIVE="${ACTIVE# }" ACTIVEID="${ACTIVE%% *}" if [ -n "$ACTIVE" ] ; then menu error "$PROMPT_ERR_DOWNLOAD" echo_debug "Killing process ID: $ACTIVEID from: $ACTIVE" # DEBUG kill "$ACTIVEID" exit 1 fi #+end_src *** Proceso de instalación **** Permisos elevados #+begin_src shell SUDO_PASSWORD="${SUDO_PASSWORD:=$(menu pass "$PROMPT_PASS_DEPS_INSTALL")}" if [ -z "$SUDO_PASSWORD" ] || ! pseudo whoami >/dev/null 2>&1 ; then menu error "$PROMPT_ERR_DEPS_INSTALL" exit 1 fi #+end_src **** Instalación #+begin_src shell if [ "$MENU" = "zenity" ] ; then # Attempt to install, forward output to program # but keep exit code of install function ( ( ( (install_certs; echo $? >&3) | zenity --title "$TITLE" --text "$PROMPT_DEPS_INSTALL" --progress --pulsate --auto-close >&4) 3>&1 ) | (read -r xs; exit "$xs") ) 4>&1 #install_certs # Just run this instead to see debug info # DEBUG # Ignore as this is needed for this "workaround" # shellcheck disable=SC2181 if [ "$?" != "0" ] ; then menu error "$PROMPT_ERR_DEPS_INSTALL" exit 1 fi elif [ "$MENU" = "term" ] ; then menu info "$PROMPT_DEPS_INSTALL" && echo ! install_certs && menu error "$PROMPT_ERR_DEPS_INSTALL" && exit 1 fi #+end_src ** Finalización #+begin_src shell menu info "$PROMPT_END_SUCCESS\n" exit 0 #+end_src