2016-07-26 12 views
0

expectを使用してpasswdに$ PASSWORD変数の内容を渡そうとしています。これは動作するように見えますが、ユーザを追加しますが、ユーザの一人とsshでログインしようとすると、うまく動作しません。私が手動でパスワードを設定しても、うまくいきます。expectはbashスクリプトのpasswdに入力を渡しません

以前にこの問題が発生しましたか?

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、環境変数名(したがって名前空間を共有するシェル変数の名前)に関するPOSIXの規則については、http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.htmlを参照してください。 - すべて大文字の名前はシェルまたはオペレーティングシステムに意味を持つ変数によって使用され、少なくとも1つの小文字の名前は、アプリケーション使用のために予約されています。したがって、誤ってOSに意味のある変数を上書きしないように、 'PASSWORD'ではなく' password'を考慮してください。 –

+0

@CharlesDuffy - 私は知っている、これは無知の中で一時間の結果です!もっと良くしようとしているIm – Detnon

答えて

0

は全く期待して必要があります:私は必要とされているいくつかの引用符を追加しました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チェックを簡略化しました。

また、「useradd」および「passwd」機能をアトミックに実行する場合は、おそらく簡単です。newusers

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 

私はnewusersが/ etc/skelからホームディレクトリに移入するとは思わないと思います。

0

まず:ほとんどの当面の問題は、あなたが\rを入力するときは、バックスラッシュリテラルをエスケープしていないので、これらは単なるexpect側のr秒に変更されていることです。問題を解決するために見える可能性のある最小限の変更は、それらを\\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" 

また、同じようにうまく動作(およびbashので採択されたkshの拡張です<()構文、への依存を避ける)ことになる、ファイルに問題のリテラルテキストを保存し、expect -f passwd.expect -- "$i" "$PASSWORD"を実行することができます。あなたはcon't

+0

私はUnexpect_edの方法でExpectを使用しているかもしれません... [lindex $ argv 0]の部分が必要であると仮定して正しいですか?私はスクリプトの冒頭で議論を使用していた場合、これが必要だと思いましたか? – Detnon

+0

だから、 '[lindex $ argv 0]'の部分は、コマンドラインから変数をawkに引き出すことです。 (最後に、 '--'の後にawkのコマンドラインにシェル変数を置いてください;' set username'と 'set password'はそれらのコマンドラインパラメータをとり、awk変数を作りますそのうちの)。 –

+0

awkスクリプトに値を直接代入するのではなく、驚くべきまたは悪意のあるユーザー名またはパスワードによる注入攻撃を避けることです。これがあなたを守る攻撃と同等のSQLの簡単な紹介については、https://xkcd.com/327/を参照してください。データがコードに挿入されないようにする最善の方法は、ここからやっているコード*からあなたのデータをアウトオブバンドで渡すことです。 –

関連する問題