10

I am developing a automated mounting script for Windows shares. I have finished the script and it works just fine, but is it possible to add Gnome Keyring to the bash so once user writes hes/hers password then it will be saved to Gnome Keyring and later will be taken from there. Also my Windows AD users passwords have to be changed each month and is it possible to make the script so once a month has passed then the script asks for password again?

Example:

User logs in to Ubuntu and the mount script starts at login. User writes hes/hers password and the script sends it to Gnome Keyring to be saved. Next time he/she will login then password will be taken from Gnome Keyring, but if its 1st of June for example the user has to write the password again.

Code:

    #!/bin/bash
MOUNTDIR=Public
DIRNAME=Shares
DOMAIN=AD_Domain
SERVER=server.local.lan
SHARE=shared_folder

# create mountpoint for mounting
if [ ! -d ${HOME}/${DIRNAME} ]; then
        mkdir ${HOME}/${DIRNAME}
fi

# define a function that launched the zenity username dialog
get_username(){
    zenity --entry --width=300 --title="Mount $MOUNTDIR" --text="Username:"
}
# define a function that launched the zenity password dialog
get_password(){
    zenity --entry --width=300 --title="Mount $MOUNTDIR" --text="Password:" --hide-text
}

# attempt to get the username and exit if cancel was pressed.
wUsername=$(get_username) || exit

# if the username is empty or matches only whitespace.
while [ "$(expr match "$wUsername" '.')" -lt "1" ]; do
    zenity --error --title="Error in username!" --text="Please check your username! Username field can not be empty!"  || exit
    wUsername=$(get_username) || exit
done

# if the password is empty or matches only whitespace.
wPassword=$(get_password) || exit

while [ "$(expr match "$wPassword" '.')" -lt "1" ]; do
    zenity --error --title="Error in password!" --text="Please check your password! Password field can not be empty!" || exit
    wPassword=$(get_password) || exit
done

# mount windows share to mountpoint
sudo mount -t cifs //$SERVER/$SHARE ${HOME}/${DIRNAME} -o username=${wUsername},password=${wPassword},domain=${DOMAIN}

# show if mounting was OK or failed
if [ $? -eq 0 ]; then
        zenity --info --title="Mounting public share succeeded!" --text="Location Documents/Shares/public!"
else
        zenity --error --title="Mounting public did not succed!" --text="Please contact system administrator!"
fi
cr0c
  • 277
  • 2
  • 12
  • Looked in to gnome keyring manual and seems like it only supports C programs :( – cr0c May 19 '14 at 08:12
  • 2
    Did you read this [Command-line access to GNOME keyring](http://kparal.wordpress.com/2009/09/29/command-line-access-to-gnome-keyring/) ? – TuKsn May 21 '14 at 09:00

3 Answers3

9

According to this answer you can use secret-tool:

# store password
secret-tool store --label='MyLabel' server myserver user myuser key password

# retrieve password
secret-tool lookup server myserver user myuser key password
Nicolas
  • 223
  • 3
  • 6
  • It would be better in the password was NOT put on the command line. – anthony Mar 13 '19 at 05:26
  • @anthony, you can add a space at the beginning of the command to not store it in the history. – Nicolas Mar 13 '19 at 10:00
  • First... can you remember to put a space in front of a command? But that is not the only issue. It is also becomes visible in the process list! The ONLY time a passwd can be put on the command line is on a bash built in (like "echo") as that does not appear in the process list! – anthony Mar 14 '19 at 23:19
  • 2
    However I retract my comment, as 'password' in this case is not THE password, but an attribute, saying the 'secret' being stored is a password. "secret-tool" always prompts (no-echo) for the 'secret', or reads from standard-input. It just wasn't clear in the example shown, or even in the manual. – anthony Mar 14 '19 at 23:22
  • 1
    echo 'secret' | secret-tool store --label='English Description' attr value [attr value]... – anthony Mar 14 '19 at 23:24
  • I have made notes about it, (and the in-memory 'kernel keyring' which is better for temporary caching (like when editing files), in http://www.ict.griffith.edu.au/anthony/info/crypto/passwd_caching.txt – anthony Mar 14 '19 at 23:56
4

While searching for the same thing, I came across this question and as there was no up-to-date answer (the only answer is in a comment), here is mine:

Check out this. It can be used easily for scripting

python -c "import keyring; print(keyring.get_password('name', 'username'))"
python -c "import keyring; keyring.set_password('name', 'username', '$PASSWORD')"

and in theory should work with many keyring daemons.

Ivaylo Petrov
  • 149
  • 1
  • 4
  • The OP is mainly asking on how to use GNOME keyring in Bash script, and *not* Python. Unless you can show that the Python script could be integrated or linked from a Bash script, this answer may be downvoted. –  Nov 25 '15 at 16:56
  • The python code can be run from a bash script, suppose it counts IF it can interface with *gnome keyring* – Wilf Nov 25 '15 at 17:53
  • 1
    The code snippet that I have provided can be put directly in a bash script. For example, you can have `PASSWORD=$(zenity --password)` and then `python -c "import keyring; keyring.set_password('wifi_work_password', 'ipetrov', '$PASSWORD')"` or `PASSWORD=$(python -c "import keyring; print(keyring.get_password('name', 'username'))")` (this will return None if no password is found, which might be bad for you, but for me it's ok). – Ivaylo Petrov Nov 27 '15 at 22:58
  • Putting the password ON the command line is NOT a good idea! – anthony Mar 13 '19 at 05:25
0

Because I really like the python answer ( although it does create a Python dependency, but who doesn't have python installed these days ) But the python answer doesn't elaborate that much, and my example is too big for the comments, here is how I used it.

#!/usr/bin/env bash

check_keyring() {
   [[ $( python3 -c "import keyring" >/dev/null; echo $?) -eq 1 ]] &&
    pip3 --upgrade keyring
}

keyring_get() {
  local key
  key="${1}"
  check_keyring
  python3 -c "import keyring; print(keyring.get_password('myscript', '${key}'))"
}

keyring_isset() {
  local key res
  key="${1}"
  check_keyring
  res=$(python3 -c "import keyring; print(keyring.get_password('myscript', '${key}'))")
  [[ "${res}" == "None" ]] && echo 1 || echo 0
}

keyring_set() {
  local key val
  key="${1}"
  val="${2}"
  check_keyring
  python3 -c "import keyring; print(keyring.set_password('myscript', '${key}', '${val}'))" > /dev/null 2>&1
}


DB_KEY="127.0.0.1|mydb|myuser"
DB_PASSWD=""
if [[ "$(keyring_isset "${DB_KEY}")" -eq 1 ]]; then
  echo -n "PG password for ${DB_KEY}:\n"
  read -sp "" DB_PASSWD
  keyring_set "${DB_KEY}" "${DB_PASSWD}"
else
  DB_PASSWD="$(keyring_get "${DB_KEY}")"
fi

PGPASSWORD="${DB_PASSWD}" psql -h 127.0.0.1 -p 5432 -d mydb -U myuser


This is just an example, obviously this the isset doesn't work if you value is actually set to "None" and it does check if keyring is installed every time, which could create some latency, but it is a hands off dependency that way

DarkMukke
  • 101
  • 3