Password-free secure but universal ssh access for FreeBSD

Suppose you have a compiled binary /bin/prog that reads from standard in and writes to standard out, that is, a typical Unix filter program. You wish to allow anyone on the internet to process files through this program with a minimum of fuss at their end. In particular, they shouldn't need to do any programing, install any software or respond to prompts. They will already have software of their own choosing that is scriptable and can shell out to the OS on their system.

In our case the program calculates tax liability from demographic and income information, but there are many potential uses, such file format conversions, statistical processing, etc. This type of service is usually provided via a webpage, but common browsers require substantial knowledge to script, and we want our tax calculator to be callable from within the users favorite statistical analysis program.

Notice that by secure, we mean in the sense that a public water fountain can be secure (against damage or misuse) without excluding any person from taking a drink. So we have no interest in using certificates to bypass passwords.

Choosing a protocol

We should pick a protocol that is scriptable, widely available, and routinely allowed through firewalls. "Available" means available by default as many ptotential users are prohibited by security policies from installing software. The windows ftp client is scriptable, but institutional firewalls often block the only connection type provided by Windows ftp. None of the browsers are scriptable except by very knowledgable programmers.

We note that all Linux and OSX computers, and the Windows 10/11 OS since August 2nd, 2016 come with a functioning ssh client, (openssh) so we use that for the network connection.

We suppose that the filter program is prog and the userid for clients to use is proguser. We will use /bin/prog as the shell for that login, and publicize that login id. ssh conveniently will pass input redirected from a file to the specified shell. However, if users are to embed the process in scripts sshd will need to avoid prompting the user for a password, certificat authorization or printing a gratuitous hello message. So merely publishing the password with the login id is insufficient. Instead we modify several host configuration files.

Preparing FreeBSD

Starting with a default FreeBSD installation, with sshd enabled, the following changes are required to allow password free, prompt free access to /bin/prog with loginid proguser:
  1. Add /bin/prog to /etc/shells
  2. Run the adduser program to add user proguser accepting all defaults except PermitEmptyPasswords should be yes and shell should be "proguser". Leave "Use password authentication as "yes".
  3. Examine /etc/master.passwd to confirm that the password hash for proguser is empty and the shell is /bin/prog. I had to remove the asterisk from the password field. A correct record would like this:

    proguser::1001:1001::0:0:Example User:/home/proguser:/bin/prog

  4. Run pw usermod proguser -w none
  5. Run pwd_mkdb -p /etc/master.passwd
  6. Edit /etc/pam.d/sshd to add option nullok to the pam_unix.so line, giving:
    auth required pam_unix.so no_warn try_first_pass nullok
  7. Modify /etc/ssh/sshd_config to uncomment PermitEmptyPasswords and change no to yes
  8. You may also wish to uncomment and change to "no" AllowAgentForwarding Allow X11 forwarding and AllowTCPForwarding depending on your site security requirements.
  9. You might also want to add
    port 22
    port 80
    port 443
    to sshd_config so that users behind ultra-strict firewalls could use the traditional http ports, which are almost never restricted. Of course that means you can't run a webserver on the same machine.
  10. Remove /etc/motd or create /home/proguser/.hushlogin to remove the login message of the day.
  11. Reboot.
At this point any remote user can submit file.foo with a one line command:

ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null proguser@example.com < file.foo

The first option disables host key checking where there is no entry for the host, and the second option disables it for the case where there is already an entry for the host. Those actions would otherwise cause user prompts. Note that there may be an ECDSA warning, but it goes to standard error so that it won't disturb standard out.

It is of course quite a security hole if prog allows user to start a shell, or has any buffer overflow bugs. In our case the program was a fortran program that reads lists of integers, and it does not call any external programs. We could be sure that no input could cause problems. sshd uses the user's default shell to execute any passed commands, so that is not a way to bypass prog.

Rationale

We find that many users have very limited control of their computing environment and are not sophisticated with respect to modern computing patterns. In many cases it would take years to obtain permission to install a binary, and many users do not have access to compilers. Asking a non-computing professional to deal with certificates is a major obstacle to adoption and would not suppress all prompts. Of course, everyone can upload from a browser, but we wanted users to be able to embed the calculations in a script written by us, or by themselves. Netcat would solve many of our problems, but is not part of the default install in any widely used system. Using ssh meets nearly everyone's needs.

This has been tested on Freebsd 11.2,12.1 and 13.0. I don't see why essentially the same thing shouldn't work in Linux (subject to differences in the pam.d file names), but I haven't tried it. Nor have I tried using pam_exec(8). Comments and suggestions are welcome.

Widoch blogs knowledgably on this topic for Linux systems. See also this on FreeBSD .

Daniel Feenberg
feenberg@nber.org
27 April 2023