Esta es una publicación que no comienza como cabría esperar o ver todos los días, aquí está mi contraseña de root: :4\g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
Difícil de recordar, ¿verdad? Bueno, ese no es el problema. Y antes de que me grites, sí, lo cambié. Ahora tengo un dummy_root
usuario con esa contraseña para las pruebas.
TL;DR
Rompí zsh al pasar esta contraseña a sudo en stdin
Versión (muy) larga
Así que esto es lo que está mal: lo uso sudo
con la targetpw
bandera, lo que significa que la contraseña solicitada por sudo es la contraseña del usuario objetivo, no la mía. Yo uso el pass
administrador de contraseñas (sitio) para todo, incluida la contraseña de root de todas mis computadoras/servidores. Por razones obvias de seguridad, esta contraseña se genera aleatoriamente mediante un pase de 128 caracteres (porque por qué no). Como persona vaga (estoy seguro de que tú también lo eres), quiero usar el siguiente alias:
alias sudo='pass mydomain.tld/hostname/users/root/password | sudo --stdin'
Para aquellos de ustedes que no están familiarizados con pass, básicamente cifra las contraseñas en un árbol de directorios con GnuPG y, al invocarlo, pass directory/subdirectory/password
descifra la contraseña y la imprime en la salida estándar (por supuesto, los directorios son opcionales, puede almacenar todo en desorden en la raíz). sin embargo, eso no se recomienda). El objetivo del alias es evitar hacer esto decenas de veces al día:
$ pass --clip root_password #Copy root password to clipboard
$ sudo command
[sudo] password for root: paste
#command output (if the password is right of course)
Pero al probar el comando alias, esto sucede:
$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$
Aquí, el %
signo tiene el color invertido: mi terminal tiene texto blanco sobre fondo negro, es %
negro sobre fondo blanco, está resaltado en blanco y se imprime después de descifrar la contraseña. Entre la impresión de [sudo] password for root:
y la impresión de este %
, GPG solicita mi contraseña de clave privada. Ya me di cuenta en alguna ocasión del signo de porcentaje invertido, y de dónde y cuándo lo vi, creo que es para imprimir EOF
(ojo, no estoy nada seguro de esto, mira al final del post un método para imprimir esto %
). Fíjate que después de esta extraña señal, no soy root, pero echo $?
vuelve 0
...
Así que descarté hexadecimalmente el resultado de pass root_password
para ver si puedo obtener más información sobre ese personaje. Aquí está el resultado:
$ pass root_password
:4\?g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
$ pass root_password | hexdump -C
00000000 3a 34 5c 3f 67 26 38 6e 3a 36 5f 46 5b 60 39 54 |:4\?g&8n:6_F[`9T|
00000010 6f 75 63 38 4c 73 2b 4c 27 38 29 3e 36 21 33 2c |ouc8Ls+L'8)>6!3,|
00000020 6e 4e 6d 55 7a 52 26 55 62 7e 77 37 4e 54 64 27 |nNmUzR&Ub~w7NTd'|
00000030 5e 4c 62 30 5d 60 30 60 2e 22 75 3e 74 50 5c 3e |^Lb0]`0`."u>tP\>|
00000040 58 41 73 70 4d 4c 54 74 21 40 7d 3d 46 36 43 50 |XAspMLTt!@}=F6CP|
00000050 29 4e 73 53 4d 59 59 37 2a 78 6d 27 41 21 37 60 |)NsSMYY7*xm'A!7`|
00000060 21 6e 27 74 6d 41 61 47 57 6f 42 68 53 7c 75 34 |!n'tmAaGWoBhS|u4|
00000070 7b 6b 24 2a 76 2f 6f 7c 27 25 29 6d 62 58 4d 77 |{k$*v/o|'%)mbXMw|
00000080 0a |.|
00000081
0a
es NL
según man ascii
. Puede notar aquí que el %
signo no está aquí y que el carácter de nueva línea que necesita sudo (ver man sudo
) está aquí.
Pero espera, ahora comienza la diversión: cuando ejecuto el comando dos veces en una ventana terminadora o tty recién iniciada, esto es lo que sucede:
$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$
Y a partir de entonces, zsh parece estar roto. Parece que quiere ejecutar el resultado del primer comando, pero solo sudo
es el segundo comando. A continuación se muestran algunos ejemplos con este shell "roto":
$ echo testpw | sudo --stdin --shell
zsh: command not found: testpw
$ echo testpw | cat
testpw
$ echo testpw | wc --bytes
11
$ echo anothertestpw | sudo --stdin --shell
zsh: command not found: anothertestpw
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$ exec zsh
$ echo testpw | sudo --stdin --shell
zsh: command not found:testpw
¿Que esta pasando aqui? Como se muestra, incluso reemplazar la instancia zsh con otra ( exec zsh
) no soluciona este problema. ¿Qué es lo que realmente está roto aquí? pasar, zsh o sudo?
Así que continuemos, probemos más, hagamos otro volcado hexadecimal en una nueva ventana de terminal (porque obviamente no sé cómo devolver zsh a su estado "normal"):
$ pass root_password | sudo --stdin --shell 2>&1 | hexdump -C
00000000 5b 73 75 64 6f 5d 20 70 61 73 73 77 6f 72 64 20 |[sudo] password |
00000010 66 6f 72 20 72 6f 6f 74 3a 20 |for root: |
0000001a
$
¿A dónde se fue este signo de porcentaje? Ni idea. Simplemente no está aquí y todavía no soy root, pero el shell ahora está en su estado roto (definitivamente no sé cómo nombrar correctamente este "estado roto"). Al ejecutar el pass root_password | sudo --stdin --shell
comando después de este, aparece el mismo mensaje de error que antes. Cabe señalar que todo es igual en un tty y en terminator, incluso este %
personaje malvado.
Aquí está toda la información que se me ocurre y que podría necesitar para ayudarme. Estoy en Arch Linux y todos los paquetes mencionados están actualizados a partir de hoy (2017-04-16 o 15, dependiendo de dónde se encuentre en el planeta, actualmente a las 4 a. m. en Francia), lo que significa ( pacman -Q
salida):
- núcleo: 4.10.9-1
- zsh: 5.3.1-2
- sudo: 1.8.19.p2-1
- pasar: 1.7.1-1
- grupo: 2.1.20-1
- terminador: 1,91-5
Aquí hay unenlacea mi .zshrc, también podría ayudar.
Y como prometí, aquí hay algunos pasos para eliminar este %
signo malicioso pass
. Simplemente cree una contraseña de varias líneas y presione Ctrl+ Dpara finalizar la contraseña sin agregar una nueva línea al final, se imprimirá este carácter. Noto aquí que presionar Ctrl+ Dno es suficiente al final de una línea con texto, hay que hacerlo dos veces. Pero si agrega una línea final a esta contraseña de varias líneas, presionarla una vez finalizará la entrada de la contraseña sin mostrarla.
$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barCtrl+DCtrl+D%
Ahí está !
Pero con una línea final, no aparece y recuperamos nuestro mensaje al presionar Ctrl+ Dsolo una vez.
$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barReturn
Ctrl+D
$
Entonces la pregunta primordial es: ¿cómo hacer que mi alias funcione? Para aquellos que se lo preguntan, acabo de escribir un script de una línea en mi directorio de scripts personalizados invocando pass root_password
y configurando la variable de entorno SUDO_ASKPASS
para pasar este script en mi .zshrc
archivo. Otra pregunta puede ser: ¿qué diablos está pasando con zsh y sudo aquí?
Editar 2017-04-16: Solución
Gracias amiguel homeroElegí esta solución para mi problema:
- Escriba un script de una línea llamado
askpass-sudo
que invoquepass root_password
- Establezca la
SUDO_ASKPASS
variable de entorno en my.zprofile
en la ruta de este script - Agregué la línea
alias sudo='sudo -A'
a mi.zshrc
¡Y voilá! La invocación sudo command
ahora solicita, como quería, mi frase de contraseña de clave GnuPG para descifrar la contraseña de root, y sudo --shell
obtengo correctamente un shell de root.
Respuesta1
pass root_password | sudo --stdin --shell
tuvo éxito. pass
imprimió la contraseña, sudo
la leyó e inició un shell; la salida de pass
terminó, lo que significa que la secuencia utilizada para la salida pass
y la entrada del shell estaba cerrada; el shell salió exitosamente en EOF.
Ejecuciones posteriores dentro delsudo
ventana de tiempo de esperano requería autenticación, por lo que el shell recibió la contraseña e intentó ejecutarla como un comando, dando ese error.
Su alias no puede funcionar si desea un shell o ejecutar alguna lectura de comandos desde la entrada estándar (pero sí lo hace para los comandos que no lo hacen). Puede configurar un alias que se ejecute pass root_password | sudo --stdin true
si lo desea y luego confiar en el tiempo de espera para ejecutar comandos sin contraseña.
También podría crear algún tipo de ayuda de Askpass que le brinde el comportamiento que desea. Proporcionaría la contraseña a través de pass
cuandopreguntópara ello por sudo
.