blob: 91aa0cc1df39455dcad5b793f3734c9ca31488f1 (
plain)
1 #!/usr/bin/env bash
2 #
3 # Automatically types the username and password from the pass entry specified
4 # as argument one. The required password-store backend is pass, the standard
5 # unix password manager.
6 #
7 # A simple workflow for this may be to go to a website requiring a username and
8 # password. Select the username field, open a program launcher such as rofi or
9 # dmenu, then execute 'quicktype password-name'.
10 #
11 # Note that for this to work, each pass entry must match the following criteria
12 # * The password is on the first line (this is the pass standard)
13 # * The username can be anywhere in the file, but the line must look like
14 # 'username: <password>'
15 #
16 # Depends on: pass xdotool
17 #
18
19
20 export PASSWORD_STORE_DIR=~/.password-store
21
22
23 #
24 # Writes log output to terminal and notification daemon, if one is present.
25 #
26 function log {
27 local msg="${@}"
28
29 if [[ $(type -p notify-send) != '' ]]; then
30 notify-send "$(basename ${0}):" "${msg}"
31 fi
32 echo ${msg}
33 }
34
35
36 #
37 # Ensures required tools are available, returning code 1 and log if any of them
38 # are not.
39 #
40 function check_env {
41 # Verify pass is installed and in the PATH.
42 if [[ $(type -p pass) == '' ]]; then
43 log "Error: Could not find pass." && return 1
44 fi
45
46 # Verify xdotool is installed and in the path
47 if [[ $(type -p xdotool) == '' ]]; then
48 log "Error: Could not find xdotool." && return 1
49 fi
50
51 # Verify /dev/null is a character device, on the off chance someone with root
52 # access is trying to capture output redirected there.
53 local devstat=$(ls -l /dev/null)
54 if [[ ${devstat:0:1} != 'c' ]]; then
55 log "Error: /dev/null is not a character device."
56 return 1
57 fi
58
59 return 0
60 }
61
62
63 #
64 # Gets a field's value from the specified [multiline] string, using the
65 # specified delimiter.
66 #
67 # @param content Content to extract field value from
68 # @param delim Delimiter seperating fields and values
69 # @param field Field name to get value for
70 #
71 getfield() {
72 local _content="${1:-}"
73 local _delim="${2:-}"
74 local _field="${3:-}"
75
76 printf "${_content}" \
77 | sed -n "s/${_field}${_delim} *\(.*\)/\1/p" \
78 | head -n 1
79 }
80
81
82 function main {
83 local _passentry # Contents of the requested pass entry
84 local _passpassword # Password from the pass entry
85 local _passusername # Username field from the pass entry
86 local _passdelim # UI Field delimiter (Tab, Return), from the pass entry
87 local _passsubmit # Boolean submit (1,y,yes...), from the pass entry
88
89 local _delim=Tab # Default delimiter if not specified in pass entry
90 local _submit=0 # Default submit value if not specified in pass entry
91
92 # Exit failure if no password was specified
93 [[ -z ${1} ]] && log "Please specify a password to be typed" && exit 1
94
95 check_env || exit 0
96
97 # Check if the password exists in the store
98 # Also, copy the contents into a variable if it exists
99 _passentry=$(pass ${@} 2>/dev/null)
100 [[ $? -gt 0 ]] && log "Error: '${@}' is not in the password store" && exit 1
101
102 # Parse pass output into appropriate variables
103 _passpassword=$(printf "${_passentry}" | head -n1)
104 _passusername=$(getfield "${_passentry}" ':' username)
105 _passdelim=$(getfield "${_passentry}" ':' delim)
106 _passsubmit=$(getfield "${_passentry}" ':' submit)
107
108 # If any of the known 'submit' values are specified, set submit to 1
109 if [ "${_passsubmit}" = '1' ] \
110 || [ "${_passsubmit}" = 'y' ] \
111 || [ "${_passsubmit}" = 'yes' ]; then
112 _submit=1
113 fi
114
115 # Type the password
116 xdotool type --delay 15 "${_passusername}"
117 xdotool key "${_delim}"
118 xdotool type --delay 15 "${_passpassword}"
119
120 [ "${_submit}" = 1 ] && xdotool key Return
121 }
122
123 main ${@}
|