Substantial rewrite; try to use keychain on Linux
[einar-bin] / addfollowmeprint.sh
1 #!/bin/bash
2 # This script installs the FollowMe print queue at NTNU on Linux (and possibly Mac) systems.
3 # The targeted and tested distros are: Debian, Ubuntu (and derivates), Fedora, CentOS, OpenSUSE and Mint
4 # Copyright © 2017-2019 einar.haraldseid@ntnu.no
5
6 # Documentation
7 function usage {
8 echo "Usage: ./$(basename "${0}") [OPTIONS]"
9 echo "Options:"
10 echo " -m, --model {ricoh|generic} Printer model to install (default: generic)"
11 echo " -d, --driver {pcl,postscript} Printer driver to use (default: postscript)"
12 echo " -f, --force Force running script as if on Linux systems"
13 echo " -p, --plaintext Store credentials as plaintext in /etc/cups/printers.conf (Linux only)"
14 echo " -h, --help Display this help text"
15 }
16
17 # Print errors to STDERR
18 function printerror() {
19 echo "${*}" 1>&2
20 }
21
22 # Test for root
23 if [ ${UID} -ne 0 ] ; then
24 echo "This script must be run as root, relaunching with sudo:"
25 sudo bash "$0" "$@"
26 exit $?
27 fi
28
29 # Set default options that may be overridden by passed options below
30 Model="generic"
31 Driver="postscript"
32
33 # Set other default options
34 PrintServer="followprint.win.ntnu.no"
35 PrintFile="ntnuprint-ricoh"
36 Workgroup="WIN-NTNU-NO"
37 QueueName="FollowMe"
38
39 while [[ $# -gt 0 ]]; do
40 Key="${1}"
41
42 case ${Key} in
43 -m|--model)
44 Model=$(echo "${2}" | tr "[:upper:]" "[:lower:]")
45 if [ "${Model}" != "ricoh" ] && [ "${Model}" != "generic" ]; then
46 printerror "Unknown model ${Model}, please choose one of ricoh or generic"
47 exit 1
48 fi
49 shift # Jump to next argument
50 ;;
51 -f|--force)
52 Force="YES"
53 shift # Jump to next argument
54 ;;
55 -d|--driver)
56 Driver=$(echo "${2}" | tr "[:upper:]" "[:lower:]")
57 if [ "${Driver}" != "postscript" ] && [ "${Driver}" != "pcl" ]; then
58 printerror "Unknown driver ${Driver}, plase choose one of postscript or pcl"
59 exit 1
60 fi
61 shift # Jump to next argument
62 ;;
63 -p|--plaintext)
64 Plaintext="YES"
65 shift # Jump to next argument
66 ;;
67 -h|--help)
68 usage
69 exit 0
70 ;;
71 *)
72 # Unknown argument
73 echo "Unknown argument: ${Key}"
74 exit 1
75 ;;
76 esac
77
78 shift # past argument or value
79 done
80
81 # Test for supported OS
82 Uname=$(uname | tr "[:upper:]" "[:lower:]")
83 if [ "${Uname}" != "darwin" ] && [ "${Uname}" != "linux" ] && [ "${Force}" != "YES" ]; then
84 printerror "I don't think I can run on ${Uname}, but if you insist, please use -f to force Linux detection. This may not work, though."
85 exit 1
86 fi
87
88 # Set Uname to linux if we are forcing running the script
89 if [ "${Force}" = "YES" ]; then
90 Uname="linux"
91 fi
92
93 # Set printer driver path based on driver (we will override these if we're specific distros
94 if [ "${Driver}" = "postscript" ]; then
95 DriverPath="drv:///sample.drv/generic.ppd"
96 else
97 DriverPath="drv:///sample.drv/generpcl.ppd"
98 fi
99
100 # Test for CUPS
101 if ! command -v lpadmin > /dev/null 2>&1; then
102 printerror "You must have CUPS installed to add printers. Please install CUPS."
103 exit 1
104 fi
105
106 # Tests for Linux systems
107 if [ "${Uname}" = "linux" ]; then
108 # Test if smbclient is installed
109 if ! command -v smbclient >/dev/null 2>&1; then
110 printerror "You must have smbclient installed to print to NTNU followprint. Please install smbclient."
111 exit 1
112 fi
113
114 # Test if secret-tool is installed
115 if ! command -v secret-tool >/dev/null 2>&1; then
116 printerror "You must have secret-tool installed for this script to work. Please install libsecret-tools (Debian-systems) or secret-tool (Fedora/CentOS)."
117 exit 1
118 fi
119
120 # Try to determine if the necessary printer drivers are installed, and set correct driver paths
121
122 # This should match OpenSUSE, and probably SUSE Enterprise, and other derivates that use zypper as the primary package manager
123 if command -v zypper >/dev/null 2>&1; then
124 if [ "${Driver}" = "postscript" ]; then
125 if [ "${Model}" = "ricoh" ]; then
126 if ! rpm -q OpenPrintingPPDs-postscript >/dev/null 2>&1; then
127 printerror "You don't seem to have the correct printer drivers installed, please run:"
128 printerror " sudo zypper install OpenPrintingPPDs-postscript"
129 printerror "first, or use the generic driver instead."
130 exit 1
131 else
132 DriverPath="OpenPrintingPPDs/postscript/Ricoh-MP_C6003.Postscript-Ricoh.ppd.gz"
133 fi
134 else
135 DriverPath="Postscript.ppd.gz"
136 fi
137 else
138 if ! rpm -q OpenPrintingPPDs-ghostscript >/dev/null 2>&1; then
139 printerror "You don't seem to have the correct printer drivers installed, please run:"
140 printerror " sudo zypper install OpenPrintingPPDs-ghostscript"
141 printerror "first, or use the generic driver instead."
142 exit 1
143 else
144 if [ "${Model}" = "ricoh" ]; then
145 DriverPath="OpenPrintingPPDs/ghostscript/Ricoh-MP_C6003.pxlcolor-Ricoh.ppd.gz"
146 else
147 DriverPath="OpenPrintingPPDs/ghostscript/Generic-PCL_6_PCL_XL_Printer.pxlcolor.ppd.gz"
148 fi
149 fi
150 fi
151 else
152 # The rest of the systems can use drv:/// paths for the generic drivers, but we need to detect various distros for advice on installing Ricoh drivers
153 if [ "${Model}" = "ricoh" ]; then
154 # This should match Fedora and other modern rpm based systems that have dnf as the primary package manager
155 if command -v dnf >/dev/null 2>&1; then
156 if ! rpm -q foomatic-db-ppds 2>&1; then
157 printerror "You don't seem to have the correct printer drivers installed, please run:"
158 printerror " sudo dnf install foomatic-db-ppds"
159 printerror "first, or use the generic driver instead."
160 exit 1
161 else
162 if [ "${Driver}" = "postscript" ]; then
163 DriverPath="foomatic-db-ppds/Ricoh/PS/Ricoh-MP_C6003_PS.ppd.gz"
164 else
165 DriverPath="foomatic-db-ppds/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd.gz"
166 fi
167 fi
168 fi
169 # This should match CentOS, RHEL and other RHEL based distros that have yum as the primary package manager
170 if command -v yum >/dev/null 2>&1; then
171 if ! rpm -q foomatic-db-ppds >/dev/null 2>&1; then
172 printerror "You don't seem to have the correct printer drivers installed, please run:"
173 printerror " sudo yum install foomatic-db-ppds"
174 printerror "first, or use the generic driver instead."
175 exit 1
176 else
177 if [ "${Driver}" = "postscript" ]; then
178 DriverPath="foomatic-db-ppds/Ricoh/PS/Ricoh-MP_C6003_PS.ppd.gz"
179 else
180 DriverPath="foomatic-db-ppds/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd.gz"
181 fi
182 fi
183 fi
184 # This should match Debian, Ubuntu and most if not all derivates that use dpkg as the primary package manager
185 if command -v dpkg >/dev/null 2>&1; then
186 if ! dpkg -s openprinting-ppds > /dev/null 2>&1; then
187 printerror "You must have the correct printer drivers installed, please run:"
188 printerror " sudo apt-get install openprinting-ppds"
189 printerror "first, or use the generic driver instead."
190 exit 1
191 else
192 if [ "${Driver}" = "postscript" ]; then
193 DriverPath="openprinting-ppds:0/ppd/openprinting/Ricoh/PS/Ricoh-MP_C6003_PS.ppd"
194 else
195 DriverPath="openprinting-ppds:0/ppd/openprinting/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd"
196 fi
197 fi
198 fi
199 fi
200 fi
201 fi
202
203 echo "This script will add a new printer called ${QueueName}, connecting to the
204 print server ${PrintServer} using your user name and password from NTNU."
205
206 # Get username and password
207 printf "User name: "
208 read -r Username
209 printf "Password: "
210 Settings=$(stty -g)
211 stty -echo
212 read -r Password
213 stty "${Settings}"
214
215 echo ""
216
217 # Some further tests for Linux systems
218 if [ "${Uname}" = "linux" ]; then
219 # Test for valid username and password
220 # Bonus: find out if the print share is actually available
221 PrintServerIP=$(getent ahostsv4 ${PrintServer} | head -n 1 | cut -d " " -f 1)
222 if ! smbclient -U "${Workgroup}/${Username}%${Password}" -L "//${PrintServer}" -I "${PrintServerIP}" > /dev/null 2>&1; then
223 printerror "User name or password incorrect, or no contact with the print server ${PrintServer}."
224 exit 1
225 fi
226 ShareFound=$(smbclient -U "${Workgroup}/${Username}%${Password}" -L "//${PrintServer}" -I "${PrintServerIP}" -g 2>/dev/null | grep ${PrintFile} | cut -d "|" -f 1)
227 if [ "${ShareFound}" != "Printer" ]; then
228 printerror "Could not find printer share called ${PrintFile} on the server"
229 printerror "This script must be broken or outdated. Please contact orakel@ntnu.no for further assistance."
230 exit 1
231 fi
232 fi
233
234 # Similar tests for OSX
235 if [ "${Uname}" = "darwin" ]; then
236 if ! smbutil view -A "//${Workgroup};${Username}:${Password}@${PrintServer}" > /dev/null 2>&1; then
237 printerror "User name or password incorrect, or no contact with the print server ${PrintServer}."
238 exit 1
239 fi
240 ShareFound=$(smbutil view "//${Workgroup};${Username}:${Password}@${PrintServer}" 2>/dev/null | grep ${PrintFile} | cut -d " " -f 1)
241 if [ "${ShareFound}" != "${PrintFile}" ]; then
242 printerror "Could not find printer share called ${PrintFile} on the server"
243 printerror "This script must be broken or outdated. Please contact orakel@ntnu.no for further assistance."
244 exit 1
245 fi
246 fi
247
248 # Finally we can add the printer, let's remove any existing printer share with the same name first
249 lpadmin -x ${QueueName} > /dev/null 2&>1
250
251 # The Linux way
252 if [ "${Uname}" = "linux" ]; then
253 if [ "${Plaintext}" = "YES" ]; then
254 PrinterShare="smb://${Username}:${Password}@${Workgroup}/${PrintServer}/${PrintFile}"
255 AuthInfo="none"
256 echo -e "\nNOTE: Your credentials will be stored in plaintext in /etc/cups/printers.conf.\nThis is usually only necessary on headless systems or on systems that don't run a dbus-daemon and/or a keyring that can provide the org.freedesktop.secrets service.\nNeedless to say, this is not a good idea on multi-user systems.\n"
257 else
258 PrinterShare="smb://${Workgroup}/${PrintServer}/${PrintFile}"
259 AuthInfo="username,password"
260 fi
261 if ! lpadmin -p ${QueueName} \
262 -D "FollowMe print queue at NTNU" \
263 -v "${PrinterShare}" \
264 -m "${DriverPath}" \
265 -o auth-info-required="$AuthInfo" \
266 -u allow:all -E; then
267 printerror "Could not connect to printer share. See above error for details."
268 exit 1
269 fi
270 if [ "${Plaintext}" != "YES" ]; then
271 # Add credentials to the keyring
272 if ! echo -n "${Password}" | secret-tool store \
273 --label "ipp://localhost:631/printers/$QueueName" \
274 uri "ipp://localhost:631/printers/${QueueName}" \
275 user "${Username}"; then
276 printerror "Could not store credentials to the keyring, see above error for details. A workaround can be to use the option --plaintext"
277 fi
278 fi
279 fi
280
281 # The OSX way
282 if [ "${Uname}" = "darwin" ]; then
283 if ! lpadmin -p ${QueueName} \
284 -D "FollowMe print queue at NTNU" \
285 -v "smb://${PrintServer}/${PrintFile}" \
286 -m "${DriverPath}" \
287 -o printer-is-shared=false -o printer-op-policy=authenticated \
288 -u allow:all -E; then
289 printerror "Could not connect to printer share. See above error for details."
290 exit 1
291 fi
292
293 cupsenable "${QueueName}"
294 cupsaccept "${QueueName}"
295
296 # Add credentials to the keychain if they are missing
297 # Shamelessly stolen^W^WBorrowed from https://github.com/Orakeltjenesten/scripts/blob/33abfb353524f449f0bbdee27adb2f1f0a9756a2/print/ntnuprint-mac.sh
298 # TODO: Since we should have a known-good username and password at this stage it's unwise to re-use the existing credentials, can we simply drop the test?
299 if ! security find-internet-password -s ${PrintServer} >/dev/null 2>&1; then
300 security -v add-internet-password -a "${Workgroup}\\${Username}" -s ${PrintServer} \
301 -w "${Password}" -D "Network Password" -r "smb " -l "${QueueName}" \
302 -T /System/Library/CoreServices/NetAuthAgent.app -T 'group://NetAuth' \
303 -T /System/Library/CoreServices/NetAuthAgent.app/Contents/MacOS/NetAuthSysAgent >/dev/null 2>&1
304 fi
305 fi
306
307 # Set correct paper size and enable the duplexer option
308 if ! lpadmin -p ${QueueName} -o PageSize=A4 -o Option1=True; then
309 printerror "Could not set default options on the print queue ${QueueName}. See above error for details."
310 exit 1
311 fi
312
313 # Set as default
314 if ! lpadmin -d ${QueueName}; then
315 printerror "Could not set the print queue ${QueueName} as default printer. See above error for details."
316 exit 1
317 fi
318
319 echo "Printer successfully installed. You may need to restart cups for the changes to take effect."