smbclient Security for Windows Printing and File Transfer

Printer Script

The script below uses a number of shell features to transmit print jobs. It bundles a mechanism for prompting and setting environment variables, prompting for a password without character echo and using a named pipe (fifo) to transmit both credentials and reformatted text:


#!/bin/sh

function chkv {  # $1:var              $2:default_value    $3:prompt
 [[ -z "$(eval echo \$$1))" ]] && if [[ -z "$2" ]]
                                  then echo -n "$3"; eval read $1
                                  else eval $1=$2; fi;
}
chkv               W_DOM               YOUR_WIN_DOMAIN     ''
chkv               W_SERVER            dc.yourcompany.com  ''
chkv               W_PRINTER           office_laser        ''
chkv               W_USER              ''                  'NT Uname: '

if [[ -z "${W_PASS}" ]]
then echo -n 'NT Pass: '; stty -echo; read W_PASS; stty echo; echo ''; fi

W=$(mktemp -dt W-XXXXXX); mkfifo -m 600 "$W/fifo"

for x
do (echo -e "username=${W_USER}\npassword=${W_PASS}\ndomain=${W_DOM}" > \
    "$W/fifo"; awk 'BEGIN{ORS="\r\n"}; {print}' < "${x}" > "$W/fifo") &

   smbclient "//${W_SERVER}/${W_PRINTER}" -A "$W/fifo" \
             -c "put $W/fifo $(basename ${x}).txt"

done; rm -f "$W/fifo"; rmdir "$W"
Below is an example of a run of the script:

$ export W_USER=$LOGNAME W_SERVER=winserv.foo.com
$ export W_PRINTER=a_laser W_DOM=DFOO

$ ./winprint /etc/passwd /etc/group

NT Pass:

   Domain=[DFOO] OS=[Windows Server 2008 R2 Standard 7601 Service Pack 1]
                             Server=[Windows Server 2008 R2 Standard 6.1]
   putting file /tmp/W-s14793/fifo as \passwd.txt (130.1 kb/s)
                                          (average 130.1 kb/s)...

A few specific observations about the script:

  • The chkv function above allows settings for the credentials, server and printer to arrive from the environment, a script default, or by prompt from the user at runtime.

  • The stty calls above allow the password to be entered from the keyboard into a shell variable without an on-screen echo. It also allows the password to arrive by an environment variable, which may be a security concern for some—the /proc/self/environ file is visible to root, and many children of the parent shell might present a password that is (to them) irrelevant. For optimum security of the Windows password, remove the if/then/fi control structure and force a password prompt for every run to ensure that it never appears in /proc/self/environ. In general, some caution should be exercised in exporting environment variables with sensitive content.

  • A fifo, or "named pipe", is safely created, and this fifo serves two purposes. First, the user name/password/domain are written to it, and the fifo is closed. Next, the text file is written to the same fifo, and a "carriage return" (ASCII code 13) is added to each line as an end-of-line marker. This pair of activities is collectively launched as background processes in a subshell.

    The credentials also may be passed to smbclient on the command line with the -Uuser%password and -W domain options. This is unsafe on some platforms, as these arguments will appear in the process list (ps -ef)—one popular solution for hiding program arguments is Oracle's hide.c, but the script implements a fifo with the -A option to smbclient instead. Note that smbclient under Oracle Linux 7 scrubs the password from what is seen in ps -ef, but Oracle Linux 5 does not. For greater safety on all platforms, the credentials are passed over the fifo.

    The laser printers tested for this script did not return to the left margin when printing UNIX-style text files with only line feeds (ASCII code 10) as the end-of-line marker—a carriage return is also required for normal printing. This can be achieved without the need of a temporary disk file by passing the content over the fifo with the added CR. The awk utility was chosen for this function as it has the best POSIX portability coverage for dealing with carriage returns (this script was tested on HP-UX with minimal changes).

  • This script does not define a formal printer queue (that is, CUPS, lpd or lp), but it will allow any non-privileged user to inject content into Windows network printer queues to which they have access. Formal UNIX printer queues that accept SMB credentials are doing something similar to what is done here.

  • The script uses the default NT1 variant of SMB1—there might be cause to alter this, which is addressed in the next section.

  • Finally, this script can be just as easily used to transfer text files to a disk share with the correct DOS-style line endings (that is, the "ASCII" mode in FTP).

It would be possible to improve the efficiency of the script by launching smbclient as a "coprocess", authenticating only once, then issuing multiple puts without exiting the client. The Korn shell's long-known coprocess syntax was disregarded in the newly introduced Bash coprocesses, so such a pursuit of efficiency would require differing syntax depending upon the branch of the Bourne shell tree.

______________________

Charles Fisher has an electrical engineering degree from the University of Iowa and works as a systems and database administrator for a Fortune 500 mining and manufacturing corporation.