the djb way

services, services!


pwdgend


Protocol: TCP
Standard Port: 129

A few months ago we read a column by Dru Lavigne about Improving User Passwords with apg. It describes the use of Adel Mirzashanov's apg --"a password generator"-- utility, for coming up with good passwords.

The article goes on to mention a client/server protocol, defined by RFC 972 and titled "Password Generator Protocol". It's a tiny protocol, completely described as follows:

A server listens for TCP connections on port 129. When a connection is established, six CRLF-delimited words are generated and sent to the client, and the connection is closed. No dialog is used or required.

Hey, that almost sounds like the protocol for the "howdy" daemon! In other words, a pretty good candidate for a daemontools service.

The apg package includes options to build an apgd daemon, which is generated from the same source file as the apg command-line utility. The difference is that apgd is designed to run from inetd, with additional source code #ifdef'd in to provide logging via syslog.

But since we prefer multilog to syslog, it's better just to use the apg command-line program as the "daemon" to run under tcpserver. For protocol sticklers, we can run apg with the ucspi-tcp fixcrio utility, to get the CRLF delimiters according to the spec.

Here's the whole setup. First, make the local service directories for the service:

# mkdir -p /var/svc.d/pwdgend/log

This "run" script for the service in /var/svc.d/pwdgend/run:


#!/bin/sh
# pwdgend/run
# password generator service
# ===
CONLIMIT=13
POLICY="-M CLN -m8 -x8"
APG="/usr/local/bin/apg ${POLICY}" 

exec 2>&1
echo "*** Starting pwdgend..."
echo "*** >> using policy: ${POLICY}"
exec envuidgid pwdgend softlimit -m3000000 \
  tcpserver -v -RH \
  -U \
  -c ${CONLIMIT} \
  -x /etc/tcprules/pwdgen.cdb \
  0 129 \
    /usr/local/bin/fixcrio ${APG}

### that's all, folks!

We run the service with the envuidgid utility, using an unpriveleged user account named "pwdgend" (group "nofiles", nonexistent home, nologin shell). This sets up for the -U option to tcpserver, to drop priveleges before running apg. The script also shows apg running under control of fixcrio, providing the necessary fixup for CRLF delimiters according to the RFC 972 specification.

For simplicity, the $POLICY variable is defined within the run script to set the command-line options used for the apg utility. The options defined here make apg generate 8-character passwords, all including at least one character from each of the sets upper-case, lower-case, and number. Read the apg(1) manpage for all the other possible options, and then define the POLICY for your own site.

As always, make sure the run script is executable, chmod 755. Then the familiar multilogger:


#!/bin/sh
# pwdgend/log/run
# multilogger for pwdgend service
# ===
exec setuidgid multilog multilog t /var/multilog/pwdgend

### that's all, folks!

Make sure this run script is executable, then make the multilog directory:

# mkdir /var/multilog/pwdgend
# chown multilog /var/multilog/pwdgend

The service run script uses the -x option with tcpserver, to define tcprules for the service. Enter the access rules you want in /etc/tcprules/pwdgen.rules, for example:


# pwdgen.rules
127.:allow
192.:allow
10.:allow
:deny

Then "compile" the rules into cdb format:

# (cd /etc/tcpules; make pwdgen.cdb)

All set to link into /service:

# ln -s /var/svc.d/pwdgend /service/pwdgend

Give it a quick check with the ucspi-tcp tcpcat utility:

$ tcpcat "" 129
thadMaw0
Whiehol3
Nommyej1
yudBoop0
OydFiUt6
Cosckig8

Invisible in this output here, but each entry is terminated by a CRLF, according to the protocol specification. To create a "custom" command-line client for a Unix platform, removing the unwanted CRs from the output, make a pwdgenc script something like this:


#!/bin/sh
# pwdgenc
# tcpclient for pwdgend service
# ===
exec /usr/local/bin/tcpclient -RHl0 -- \
  "${1:-0}" "${2:-129}" sh -c 'exec cat <&6 |/usr/local/bin/delcr'

### that's all, folks!

This utility uses port 129 by default, so just enter the hostname of the password server:

$ pwdgenc apg.example.org
cagMouj7
6Bloiphi
Cairril5
egourEk1
Nimgeeg5
VeOfhev3

Of course, even without any special client, users can always telnet to port 129. Another way to do it is to put up a web interface, with a simple CGI script.

By using this simple pwdgend server, you will always be able to pull off some decent passwords, anywhere on your network, and consistently generated according to a local policy. What a concept!


Copyright © 2002, 2003, 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.04.13, wcm.