ssld - routines useful for SSL servers
These routines are intended for use by SSL based daemons. Routines which are shared between clients and servers are documented in sslfd(3).
A server (such as SSLrshd) typically needs to call:
ssld_init(cert_file, key_file, cipher_list, verify_flag, init_flags);
To change any of the defaults for these arguments and tell SSLeay which verify callback function to use. If command line args have been handled by ssl_setopt(3), and the application is using ssld_start(), then the call to ssld_init() may not be needed.
To establish the SSL protocol, the server must call one of:
ssl_start(sock, log_lev, active)
ssl_start_cb(sock, log_lev, active, verify_cb, verify_flag)
ssld_start(sock,
log_lev, active, verify_cb, verify_flag,
reply)
with active = 1 or 0. The end with active = 0 will call SSL_accept() and must always provide a certificate. For applications where client to server authentication is most important, it makes sense to reverse the accept/connect roles at the SSL level.
ssld_start() is different to the others in that if verify_flag inlcudes the SSL_VERIFY_FAIL_IF_NO_PEER_CERT bit, it will not be passed to SSL. Instead, if there is an error during setup (such as client cert has expired or been revoked), reply(error_msg) is called to inform the client of the reason for failure, before the SSL session is terminated. If verify_cb is NULL, the default which checks the issuer's CRL for revoked certificates is used. Most servers (except ftpd) should probably call ssld_start(), and almost never use a verify callback other than the default one in this module.
Although originally written for SSLrshd which is the server for ssl_rcmd(3), servers can call:
ssld_auth(socket, remuser, key)
to determine if the client certificate provides authorization to access some resource identified by key. In the case of SSLrshd key is the requested local user id.
ssld_auth() determines the remote hostname. If the connection came from the loopback address, then gethostname(2) is used otherwise getpeername(2). Normally, hostname is only used for logging purposes and we do not care where the connection comes from. However, if the certificate is a host cert (/CN is a domain name that we can find in the DNS), then we most certainly do care where the connection came from. Also, we now support a host list appended to an entry in the auth files, such that a matching cert will only be accepted from the listed hosts. For these reasons we always verify the hostname via the DNS and check that the calling address is listed. If not, we use the remote hostname ``unknown''.
ssld_auth() calls get_x509_name(0, 0) to extract the common name (/CN) field from the client's certificate. If the name contains any ``.'' it is compared against the remote hostname using domaincmp(3) and if that fails, we confirm that the cert name is either a wildcard host cert or can be found in the DNS via gethostbyname(2). If the cert is indeed a host cert and domaincmp(3) failed, we reject the cert.
If not already rejected, ssld_auth() calls:
ssl_cert_ok(key, ssl_auth_cert, hostname)
To lookup ssl_auth_cert in the auth file(s). If certcmp() indicates a match, and either key or root is listed as a valid target, permission is granted, otherwise it is denied. If the target deny is found in the same record the certificate is denied access.
The format of the auth files is:
user_list:[-e ]cert[:host_list]
Which is backwards compatible with Tim Hudson's ssl.users file which is included in the default list of auth files (/etc/ssl.deny:/etc/ssl.root:/etc/ssl.local: /etc/ssl.users:/etc/ssl.global) and the search logic is very similar. If host_list is supplied the matching cert will only be accepted from the listed hosts or domains. This is useful when cert contains a wildcard, or the -e option is present in which case cert is treated as a regular expression by certcmp(). If the POSIX regexec(3) is available it is used and cert may be an extended regular (case insensitive), otherwise if re_comp(3) is available cert must be a basic regexp. If user_list contains entries like /CN=, then the appropriate field is extracted from the cert. This is only useful if cert was a regexp. Note that a field value of ``root'' will be skipped to ensure privileged access is not granted accidentally. Certs to be granted ``root'' access must be explicitly listed.
sslc(3), ssl_rcmd(3), ssl(3), netio(3).
The current version of SSLeay can be obtained from: ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.xx.tar.gz
The SSLeay FAQ by Tim Hudson <tjh@mincom.oz.au> can be found at http://www.psy.uq.oz.au/~ftp/Crypto
The ftp protocol is such that ssld_start() cannot be used. The ftp client either does not display the reason why the session is being dropped or worse, just gets out of sync and hangs. You can only take generic facilities so far...
Simon J. Gerraty <sjg@crufty.net>