[ Adopted from: http://www.sendmail.org/~ca/email/cyrus/sysadmin.html, Cyrus SASL docs, and 2 O’Reilly SASL articles. ]
SASL, the Simple Authentication and Security Layer (RFC–2222) is a generic mechanism for protocols to accomplish authentication. SASL allows clients and servers to negotiate which authentication and encryption mechanisms to use. With SASL, any program that uses the SASL libraries is an application, including both clients and servers.
The first thing to realize is that there is a difference between SASL, the protocol, and Cyrus SASL, the library. The first is a specification that describes how authentication mechanisms can be plugged into an application protocol on the wire. The later is an implementation that aims to make this easier for application developers to integrate authentication mechanisms into their application in a generic way. The Cyrus SASL library includes a server program saslauthd, used for some of the mechanisms. The library is sometimes referred to as the “glue layer”. Gnu also provides a SASL library, which is newer and not (yet) as popular.
It is quite possible to have an application that uses SASL (the specification) without using any SASL libraries (the implementation). However, since protocols such as SMTP, IMAP, and LDAP use SASL, it makes sense to have a single, shared SASL library many applications can use. Some notable applications that use SASL include Sendmail and imapd. You can use ldd program |grep sasl to see if some application is compiled to use the SASL library.
Applications use the SASL library to accomplish the SASL protocol exchange, and to learn what the results were. SASL is only a framework: specific SASL mechanisms govern the exact protocol exchange. With a SASL library the mechanisms need only be written once, and they’ll work with all servers that use it.
If there are n protocols and m different ways of authenticating then a developer would have to implement each of the m authentication mechanisms, once per protocol (SMTP, HTTP, IMAP, LMTP, ...), for m times n. SASL attempts to make it so each of the n protocols can use any of the m different mechanisms, which need to be implemented only once.
For each SASL application you need to specify which mechanisms will be supported, and in what preference order you’d like to use them, and other configuration parameters for each.
Cyrus SASL is the common (and default) implementation of SASL used. It currently is in version 2 (since 2002), and most commands start with “sasl2”. The documentation is found at /usr/share/doc/cyrus-sasl*/index.html.
Note that SASL is not the only framework in use for security mechanisms. GSSAPI (Generic Security Services API) may become common. Currently it only supports the Kerberos mechanism, but that is very popular (Windows Active Domains are an implementation of this.) SASL supports GSSAPI for Kerberos.
The Cyrus SASL Library (the “glue” layer)
As an administrator you need to configure the SASL libraries by providing plug-ins for the various mechanisms all your SASL applications on that host use. Next each application must be configured to list what authentication and encryption mechanisms it will use. This can be done in an application-specific way, usually by editing the application configuration files. However the Cyrus SASL library will also look for configuration files in /usr/lib/sasl2/Application-name.conf if the application fails to provide the configuration information.
The available mechanisms for SASL are registered with the IANA (www.iana.org/assignments/sasl-mechanisms), however a given implementation may not support all of these.
<![if !supportLists]>· <![endif]>Ascertaining necessary security properties from the application to aid in the choice of mechanism (or to limit the available mechanisms)
<![if !supportLists]>· <![endif]>Loading of any needed plugins
<![if !supportLists]>· <![endif]>Listing of available plugins to the application (mostly used on the server side)
<![if !supportLists]>· <![endif]>Choosing the “best” mechanism from a list of available mechanisms for a particular authentication attempt (mostly used on the client-side)
<![if !supportLists]>· <![endif]>Providing information about the SASL negotiation back to the application (authenticated user, requested authorization identity, security strength of any negotiated security layer, and so on).
<![if !supportLists]>· <![endif]>Routing the authentication (and in the case of a mechanism with a security layer, encrypted) data packets between the application and the chosen mechanism
The glue code allows the mechanisms and applications access to two special types of plugins, auxiliary property or “auxprop” plugins, which provide a simple database interface and can return properties about the user such as password, home directory, or mail routing address, and username canonicalization, which might provide site-specific ways to canonicalize a username or perform other tasks.
In the Cyrus SASL implementation the glue code is entirely contained within libsasl2.so (or libsasl2.a).
The Application’s Configuration File
By default the SASL library reads it’s options from /usr/lib/sasl2/App.conf (where “App” is the application-defined name of the application). For instance Sendmail reads it’s configuration from “/usr/lib/sasl2/Sendmail.conf” and the sample server application included with the library looks in “/usr/lib/sasl2/sample.conf”.
A standard Cyrus SASL configuration file might look like:
For Kerberos you would also add a line similar to:
Applications can redefine where the SASL library looks for configuration information. For instance Cyrus imapd reads its SASL options from it’s own configuration file, /etc/imapd.conf, by prepending all SASL options with “sasl_”. So the SASL option pwcheck_method is set by changing sasl_pwcheck_option in /etc/imapd.conf. Check your application’s documentation for more information.
Example SASL Application: MTA
S: 220 example.com ESMTP
C: EHLO rubble.com
S: 250-example.com Howdy!
S: 250-AUTH ANONYMOUS
CRAM-MD5 DIGEST-MD5 OTP
S: 250 HELP
When the client (C:) establishes a TCP connection to the server (S:), the server sends the 220 greeting. The client then asks the server to list the SMTP extensions that it supports (EHLO). The server supports SASL with four mechanisms (AUTH ...), TLS (STARTTLS), and the help command. The AUTH extension indicates that the server supports SASL, and remaining parameters on that line indicate which SASL mechanisms are available on the server.
The next step is that the client must tell the server to start a particular mechanism, and then both must be able to exchange information to initialize the mechanism, possibly indicating success or failure. Here’s how SMTP uses OTP (and no TLS):
C: AUTH OTP AGJsb2NrbWFzdGVy
S: 334 b3RwLXNoYTEgOTk5NyBwaXh5bWlzYXM4NTgwNSBleHQ=
Here the client asks the server to start the OTP mechanism and supplies an initial argument, which identifies the user to be authenticated. The server decides to start the mechanism (code 334), and generates a challenge. The client sends a response, and the server decides it’s valid (code 235 means authentication success). Because the arbitrary binary data may be sent during the SASL negotiation, it is always base64 encoded when sent via SMTP.
Other possibilities include first using STARTTLS to begin encryption (and use certificates to have the server identify itself to the client, and possibly vice-versa). If so, your program tells the server to start TLS, and ultimately your program gets back another 220 greeting, and sends another EHLO. (Check out RFC-3207 for all the details.) Then you can use AUTH PLAIN or some other mechanism for authentication, using the encrypted channel.
Authentication ID versus Authorization ID
SASL supports the idea of proxy authentication. The authentication ID (authid) is the userid being verified. Typically a password or public-key is used. Additionally an authorization ID (userid) can be supplied, which means userid is to be a proxy for the authorization ID. (If wpollock logs in using wpollock’s password and an authorization ID of hpiffl, then wpollock may be allow to read Hymie Piffl’s email.)
In other words the authentication identity is the username you login as, and the authorization identity is the username you want to act on behalf of. In Cyrus SASL, these are referred to as the authid and authzid, respectively.
Applications can set their own proxy policies. By default the SASL library will only allow the same user to act for another (that is, userid must equal authid).
The Cyrus SASL library supports the concept of “realms”. A realm is an abstract set of users, and a set of specified mechanisms authenticate users in a given realm. In the simplest case (a single server on a single machine), the realm might be the fully-qualified domain name of the server. If applications don’t specify a realm to SASL, most mechanisms will default to this. For example “Hymie@foobar.com” means user Hymie and the realm foobar.com.
Before using Cyrus SASL in your server, you need to think about how each SASL plug-in is going to validate the authentication information provided by a remote user. Instead of requiring that the network administrator write a customized callback procedure, Cyrus SASL provides a couple of easy options.
To begin with, you probably have some kind of a password system already running in your enterprise. For example if you’re already running Kerberos version 4 or 5, then the right thing just happens — providing, of course, that the client requests the use of the KERBEROS_V4 or GSSAPI mechanism.
Otherwise you probably have something that takes a username and a password and comes back with either a “yes” or “no”. Cyrus SASL comes with a program called saslauthd that knows about several different mechanisms, such as password files, shadow password files, DCE, PAM, SIA, and so on. (The reason Cyrus SASL provides this as a separate program is so that your servers don’t have to run as root; instead, they talk to saslauthd using a named pipe.)
Finally, Cyrus SASL has its own authentication database. There are a couple of reasons why you might want to use this rather than some other more standard DB:
<![if !supportLists]>· <![endif]>You want to support a shared secret mechanism (e.g., CRAM-MD5 or DIGEST-MD5), which requires either the actual passphrase or a mechanism-specific hashed-format
<![if !supportLists]>· <![endif]>You want to use a mechanism that requires arbitrary authentication information (e.g., seed and sequence information for the OTP mechanism)
<![if !supportLists]>· <![endif]>You want to have a namespace for SASL users that’s separate from what’s provided by your operating system — you don’t have to create a UNIX login for each user of the service.
Cyrus SASL provides another program, saslpasswd, that lets the administrator create, modify, or remove SASL-login accounts.
There are several types of mechanisms:
<![if !supportLists]>· <![endif]>Password Verification Mechanisms – For example, PLAIN. These receive a raw password from the remote application and then pass it into the glue code for verification by a password verifier. These require the existence of an outside security layer (encryption) to hide the otherwise plaintext password from people who might be snooping on the wire. These mechanisms do not require that the server have access to a plaintext (or plaintext-equivalent) version of the password; SASL can use PAM and other mechanisms to check the password.
<![if !supportLists]>· <![endif]>Shared Secret Mechanisms – For mechanisms such as CRAM-MD5, DIGEST-MD5 (successor to CRAM-MD5), and others, there is a shared secret between the server and client (e.g. a password or key). However, in this case the password itself does not travel across the network. Instead the client passes a server a token (a challenge) that proves that it knows the secret (without actually sending the secret across the network). For these mechanisms, the server generally needs a plaintext equivalent of the secret to be in local storage (not true for SRP).
<![if !supportLists]>· <![endif]>Kerberos Mechanisms – Kerberos mechanisms use a trusted third party to authenticate the client. These mechanisms don't require the server to share any secret information with the client, it is all performed through the Kerberos protocol.
SASL defines which mechanisms to use (i.e., which the server will accept, and which the client will try to use) by defining the minimum (and/or maximum) strength of the mechanisms to use. You tell Cyrus SASL the actual and desired security level of the connection, expressed as an integer. Typical values are 0 (nothing), 1 (integrity-checking only, e.g., MD5 checksum), 56, 112, and 128. Excluding zero and one, it’s easiest to think of this as the number of bits in the session key being used for privacy.
Available Mechanisms: PLAIN
The PLAIN mechanism is not a secure method of authentication by itself. It is intended for connections that are being encrypted by another level. (For example, the IMAP command “STARTTLS” creates an encrypted connection over which PLAIN might be used.) The PLAIN mechanism works by transmitting a userid, an authentication id and a password to the server, and the server then determines whether that is an allowable triple.
You can configure which password repository to use for PLAIN mechanisms. man saslauthd lists all the choices; here is a shorter list of some common ones:
<![if !supportLists]>· <![endif]>passwd – /etc/passwd is supported innately in the library. Simply set the configuration option “pwcheck_method” to “passwd”.
<![if !supportLists]>· <![endif]>shadow – /etc/shadow is somewhat trickier. If the servers that use SASL run as root (such as Sendmail) there's no problem: just set the pwcheck_method option to “shadow”. However, many daemons do not run as root for additional security, such as Cyrus imapd. In order for these servers to check passwords, they either need a helper program that runs as root, or need special privileges to read /etc/shadow. The easiest way is to give the server the rights to read /etc/shadow by, for instance, adding the cyrus user to the “shadow” group and then setting pwcheck_method to “shadow”. It is also possible to write a special PAM module that has the required privileges; default PAM setups do not (to my knowledge) come with this.
<![if !supportLists]>· <![endif]>kerberos_v4 – Kerberos v4, if found by the configuration script at compile time, can be enabled for plaintext password checking by setting pwcheck_method to “kerberos_v4”. This is different from the KERBEROS_V4 mechanism discussed below—this configuration option merely specifies how to check plaintext passwords on the server.
<![endif]>PAM – PAM, the pluggable authentication
module, is the default way of authenticating users on Solaris and Linux. It can be configured to check passwords in
many different ways: through Radius, through
The PAM authentication for SASL only affects the plaintext authentication it does. It has no effect on the other mechanisms, so it is incorrect to try to use PAM to enforce additional restrictions beyond correct password on an application that uses SASL for authentication.
<![if !supportLists]>· <![endif]>sasldb – This stores passwords in the SASL secrets database (/etc/sasldb2), the same database that stores the secrets for shared secret methods. Its principal advantage is that it means that the passwords used by the shared secrets mechanisms will be in sync with the plaintext password mechanisms. However, system built-in routines will not use sasldb.
Note that to set plaintext passwords in sasldb, you need to configure “saslpasswd” to do so. The saslpasswd uses the same configuration files like any SASL server. Make /usr/lib/sasl/saslpasswd.conf contain the line “pwcheck_method: sasldb” to instruct saslpasswd to create plaintext secrets in addition to the normal secrets.
NTLM – Undocumented but provided for compatibility with MS applications.
<![if !supportLists]>· <![endif]>write your own – Last, but not least, the most flexible method of authentication for PLAIN is to write your own. If you do so, any application that calls the “sasl_checkpass()” routine or uses PLAIN will invoke your code.
Available Mechanisms: Shared secrets
The Cyrus SASL library also supports some shared secret authentication methods such as CRAM-MD5 and it’s successor DIGEST-MD5, and OTP (and OPIE). These methods rely on the client and the server sharing a secret, usually a password. The server generates a challenge and the client a response proving that it knows the shared secret. This is much more secure than simply sending the secret over the wire proving that the client knows it.
OTP is more secure than the other shared secret mechanisms in that the secret is used to generate a sequence of one-time (single use) passwords which prevents reply attacks, and that secret need not be stored on the system. These one-time passwords are stored in the /etc/sasldb2 database.
Cyrus SASL can be configured to use OPIE instead of using its own database and server-side routines. OPIE uses its own “opiekeys” database for storing the data necessary for generating the server challenges. The location of the opiekeys file is configurable in SASL; by default it is /etc/opiekeys, but this is modifiable by the “opiekeys” option.
There’s a downside to using shared-secret mechanisms. In order to verify responses the server must keep password equivalents in a database. If this database is compromised, it is the same as if every user’s password for that realm is compromised. Additionally saslauthd can’t be used to access this DB of secrets. It could if it were run SUID root but you should never do that! Instead each application user id should have the required read (or read-write) access to whatever DB it uses. It is often a better approach to use saslauthd and PAM.
The Cyrus SASL library stores shared secrets by default in the /etc/sasldb2 database. Depending on the exact database type used (gdbm, ndbm, or db) the file may have different suffixes or may even be split into two different files (e.g., sasldb.dir and sasldb.pag). It is also possible for a server to define it’s own way of storing authentication secrets.
The Cyrus SASL library also comes with two mechanisms that make use of Kerberos: KERBEROS_V4, which should be able to use any Kerberos v4 implementation, and GSSAPI (tested against MIT Kerberos 5 and Heimdal Kerberos 5). These mechanisms make use of the kerberos infrastructure and thus have no password database.
Available Mechanisms: Kerberos
Applications that wish to use a Kerberos mechanism will need access to a service key, stored either in a “srvtab” file (Kerberos 4) or a “keytab” file (Kerberos 5). Currently, the keytab file location is not configurable and defaults to the system default (probably /etc/krb5.keytab). The Kerberos 4 srvtab file location is configurable; by default it is /etc/srvtab, but this is modifiable by the “srvtab” option. Different SASL applications can thus use different srvtab files.
Password Verification Services
The password verifiers take a username and plaintext password, and say either “yes” or “no”. It is not possible to use them to verify hashes that might be provided by the shared secret mechanisms.
Password verifiers are selected using the “pwcheck_method” SASL option. There are two main password verifiers provided with Cyrus SASL:
<![if !supportLists]>· <![endif]>saslauthd – saslauthd is the server process which handles plaintext authentication requests on behalf of the Cyrus SASL library.
The saslauthd daemon has a number of modules of its own, which allow it to do verification of passwords in a variety of ways, including PAM, LDAP, against a Kerberos database, and so on. This is how you would want to, for example, use the data contained in /etc/shadow to authenticate users.
saslauthd listens in on a socket for requests and responds to them. Use the command sasl2-shared-mechlist to see the list of installed shared-secret mechanisms on your system.
<![if !supportLists]>· <![endif]>auxprop – This uses an auxprop plugin to fetch the password and then compares it with the client-provided copy to make the determination. Auxiliary Property (or auxprop) plugins provide a database service for the glue layer (and through it, to the mechanisms and application).
Cyrus SASL ships with two auxprop plugins: SASLdb and SQL. Auxprop plugins are mostly only used by shared secret mechanisms (or by the auxprop password verify) to access the “userPassword” attribute of some database containing user name and password info. This provides a plaintext copy of the password that allows for authentication to take place.
(Non-plain text mechanisms used to use a different server, auxpropd. But in sasl2 the library mechanisms’ code directly accesses the various databases.)
Installing a mechanism is a matter of putting a plug-in in the correct location, /usr/lib/sasl2. (You also find application configuration files here by default.)
SASL mechanisms are generally defined by the IETF standards process, and thus have RFCs available. However not all supported mechanisms are standardized this way.