2016-07-26 3 views
0

Я пытаюсь передать содержимое переменной $ PASSWORD в passwd, используя expect. Это, похоже, работает, добавив пользователей, но как только вы попытаетесь войти в систему через ssh с одним из пользователей, это не сработает. Если я задаю пароль вручную, это будет хорошо.Ожидание не передает ввод passwd в сценарии bash

Неужели кто-нибудь столкнулся с этой проблемой раньше?

USERS=(user1 user2 user3) 



generatePassword() 
{ 
     pwgen 16 -N 1 
} 

# Check if user is root 
if [ $(whoami) != 'root' ]; then 
     echo "Must be root to run $0" 
     exit 1; 
fi 

# Check if pwgen is installed: 
if [[ $(dpkg -s pwgen > /dev/null 2>&1; echo ${PIPESTATUS}) != '0' ]]; then 
     echo -e "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n" 
     exit 1; 
    else 
     echo -e "Starting Script...\n\n" 
fi 

# Iterate through users and add them with a password 
for i in ${USERS[@]}; do 
     PASSWORD=$(generatePassword) 
     echo "$i $PASSWORD" >> passwords 

     useradd -m "${i}" 

     echo -e "Adding $i with a password of '$PASSWORD'\n" 

     expect -c " 
      spawn passwd ${i} 

      expect \"Enter new UNIX password:\" 
      send -- \"$PASSWORD\r\" 
      send -- \"\r\" 
      expect \"Retype new UNIX password:\" 
      send -- \"$PASSWORD\r\" 
      send -- \"\r\" 
      " 
      echo -e "\nADDED $i with a password of '$PASSWORD'\n" 
done 
+0

Ewww. Вы выполняете замену строк в содержимом, которое предполагается использовать для анализа в качестве кода? Это значительный запах кода - если пользователям когда-либо разрешалось устанавливать свои собственные пароли, это можно было бы использовать как произвольную уязвимость при введении команд. –

+0

BTW, см. Http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html для соглашений POSIX об именах переменных среды (и, следовательно, имена переменных оболочки, которые используют пространство имен) - имена всех шапок используемые переменными со значением для оболочки или операционной системы, а имена с хотя бы одним строчным символом зарезервированы для использования приложения; таким образом, рассмотрите 'password' вместо' PASSWORD', чтобы избежать перезаписи переменной со значением в ОС по ошибке. –

+0

@CharlesDuffy - Я знаю, это результат часа шатания в невежестве! Im пытается стать лучше – Detnon

ответ

0

Вы con't нужно ожидать на все: использовать chpasswd вместо passwd

#!/bin/bash 
users=(user1 user2 user3) 

# Check if user is root 
if [[ "$(id -un)" != 'root' ]]; then 
    echo "Must be root to run $0" 
    exit 1 
fi 

# Check if pwgen is installed: 
if ! dpkg -s pwgen > /dev/null 2>&1; then 
    printf "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n" 
    exit 1 
else 
    printf "Starting Script...\n\n" 
fi 

# Iterate through users and create a password 
passwords=() 
for user in "${users[@]}"; do 
    useradd -m "$user" 
    password="$user:$(pwgen 16 -N 1)" 
    passwords+=("$password") 
    echo "Adding user '$user' with '$password'" 
done 

printf "%s\n" "${passwords[@]}" | chpasswd 

Я добавил несколько цитат, которые необходимы.
Я упростил проверку dpkg.

Или, возможно, проще, newusers для выполнения функций «useradd» и «passwd» атомарно.

for user in "${users[@]}"; do 
    password="$user:$(pwgen 16 -N 1)" 
    password=${password//:/-}   # replace all colon with hyphen 
    printf "%s:%s::::/home/%s:/bin/bash\n" "$user" "${password//:/-}" "$user" 
done | newusers 

Я не думаю, что новые пользователи заполняют домашний каталог из/etc/skel.

0

Первое: Наиболее насущной проблемой является то, что вы не спасаясь от обратной косой черты литералов при вводе \r, поэтому они просто превратились в r с на expect стороне; наименьшее возможное изменение, которое, по-видимому, устранит проблему, - это изменить их на \\r.


Однако - не делать это таким образом: В expect, как и другие языки, строки должны быть переданы в качестве литералов, не подставляются в код.

expect -f <(printf '%s\n' ' 
set username [lindex $argv 0]; 
set password [lindex $argv 1]; 
spawn passwd $username 

expect "Enter new UNIX password:" 
send -- "$password\r" 
send -- "\r" 
expect "Retype new UNIX password:" 
send -- "$password\r" 
send -- "\r" 
') -- "$i" "$PASSWORD" 

Вы также можете сохранить буквальный текст вопроса в файл, и запустить expect -f passwd.expect -- "$i" "$PASSWORD", который будет работать так же хорошо (и избежать зависимости от <() синтаксиса, который является продолжением КШ, принятой Баш).

+0

Возможно, я использую Expect в Un_expect_ ed порядке ... Правильно ли я предполагаю, что мне нужны [lindex $ argv 0] части? Я думал, что это необходимо, если я использовал аргументы в начале моего скрипта? – Detnon

+0

Итак, re: части '[lindex $ argv 0]', то, что это делает, вытаскивает переменные из командной строки в awk. (См. В конце, после '-', где мы помещаем переменные оболочки в командной строке awk: 'set username' и' set password' - это где мы берем эти параметры командной строки и делаем awk-переменные из них). –

+0

Целью этого, а не подставлять значения непосредственно в awk-скрипт, является избежание инъекционных атак с помощью удивительного или злонамеренного имени пользователя или пароля. См. Https://xkcd.com/327/ для быстрого ознакомления с эквивалентом SQL атаки, который защищает вас; лучший способ удержания данных от ввода содержимого в код - это * передача данных вне диапазона из кода *, что здесь делается. –

Смежные вопросы