web-dev-qa-db-fra.com

comment créer une chaîne de regex où vous ne savez pas quoi échapper

J'ai un fichier passwd avec la ligne contenant la racine étant:

root:6UZSjeWUui3JQ:0:0:root:/root:/bin/sh

Je veux que cette ligne soit changée en:

root:$1$dog$cNv/OuAd7CMNdrhWsHXAR.:0:0:root:/root:/bin/sh

Ce mot de passe généré à l'aide de:

hash=$(openssl passwd -1 -salt $salt angus)

qui a un/caractère incorporé. Donc, cela signifie que je ne peux pas utiliser ce sed:

sed -e "s/root:.*:0:0:/root:$hash:0:0:/" './test/etc/passwd'

Je dois changer pour:

sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'

sinon je reçois cette erreur cryptique:

sed -e expression #1, char 32: unknown option to `s'

Mais que se passe-t-il si le hachage généré a un | personnage? Comment pourrais-je rendre ce script robuste pour gérer n'importe quel hachage?

Voici mon script actuellement qui échouera si un hachage a un | personnage.

par exemple, si vous appelez comme ceci:

Sudo ./justsed.sh angus dog

Scénario:

#!/bin/bash

if [[ ! $1 || ! $2 ]]; then
    echo "Usage: justsed.sh <password> <salt>"
    exit 0
fi

# change salt to random chars for real use
salt=$2

# example: $1$dog$cNv/OuAd7CMNdrhWsHXAR.
hash=$(openssl passwd -1 -salt $salt $1)

printf "using the following hash: %s, updating file: %s\n" $hash "./test/etc/passwd"

echo "sed command with escaped /"
# this line works
sed -e 's/root:.*:0:0:/root:$1$dog$cNv\/OuAd7CMNdrhWsHXAR.:0:0:/' './test/etc/passwd'

echo "sed replace text"
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'
2
arcomber

Il suffit d’échapper avant d’appeler sed:

hash=$(openssl passwd -1 -salt $salt $1 | sed 's|/|\\/|g')
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'

Mais cela cassera si votre hachage contient ", ou \, ainsi que s'il contient & puisque sed lira cela comme "tout ce qui a été mis en correspondance" lorsque & est présent sur le côté droit de l'opérateur de substitution. Donc, vous devrez également échapper à ceux-ci:

hash=$(openssl passwd -1 -salt $salt $1 | sed -E 's|(["/\@])|\\\1|g')
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'

Enfin, si votre hachage contient :, tout cela sera cassé, car cela ne peut pas être échappé, étant donné que c'est un séparateur dans le fichier passwd. J'ajouterais donc un test pour cela:

if [[ "$hash" =~ /:/ ]];
then
    echo "Invalid password! Choose another"
    exit
fi
2
terdon