#+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. #+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 # DEBUG [ "$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