Using SASL: Pluggable Securityby Marshall T. Rose, author of BEEP: The Definitive Guide
The Simple Authentication and Security Layer (SASL) allows administrators to configure just the right amount of security for the networked applications in their environments. BEEP is a SASL- friendly framework for writing application protocols. This first article explains SASL; in the follow-up article, we'll see how to program with SASL using an open source API.
Programmers are usually pretty good at dealing with concrete concepts -- e.g., "I need to copy this file from here to there." What few of us are good at is being able to generalize with uncertainty -- "And while most of the time it should be secure, every now and then the user will want to optimize for throughput instead."
The plain fact is that no matter how well you understand your security requirements today, they're going to evolve over time; further, if you build something that's useful, then it will be used in environments with different requirements. In other words, requirements change over space and time.
I've been designing application protocols since 1983, and until recently, every time I tried to build a protocol with that kind of security generality, I got it wrong. The cost of getting it wrong is sometimes painful -- you have to deploy another version of the protocol on a different port, with little or no configuration reuse, and lots of opportunities for version skew and remote debugging.
Although I'd like to think that over time I learned from my mistakes, what really happened is that someone else figured out a really good solution to the problem that works for most application protocols. The idea, in hindsight, is fairly simple: the network security portion of your protocol should behave like a dynamically-loaded module:
- the server needs to figure out what modules it has available;
- the client has to negotiate which one to use; and,
- when one of the modules in in use, both the server and client have to call it in order to encrypt or decrypt the data.
These rules are defined by SASL -- the Simple Authentication and Security Layer (no relationship to SSL). Now, if you're a right-brain kind of programmer, you're probably thinking, "Wait a minute, this really sounds like SSL -- why not just use that?"
You could, but you're missing the finer points of the problem. It may be that SSL is OK for the administrator's needs. But, there may be something available that's better. For example, if the application is running in a Kerberos environment, it would be better to "kerberize" the application and reuse the Kerberos infrastructure.
So what we have is a situation where we can get a really big improvement if we're willing to take a step back and just slightly generalize the way our protocol works.
If you're familiar with reading either protocol or API specifications, the SASL document is a little bit different. (Helpful hint: think of the SASL specification as a "meta API.") Rather than explain the details, let's look at the concepts from an administrator's perspective. The basic idea is that someone writes a SASL API, which is used by two kinds of people:
- security folks, who implement security mechanisms -- these are the modules that get used by the application; and,
- application writers who write the programs that "do" the protocol and load the modules.
Normally, the API will also provide the administrator with some kind of management interface. In the simplest case, there may be a configuration file for each application that indicates which mechanisms are acceptable under what circumstances. This kind of configurability is key. Both the mechanisms and the applications should be "policy free" -- it's up to the administrator to decide which applications get to offer what mechanisms.
What's a SASL mechanism look like? Well, one thing to keep in mind is that a SASL mechanism can perform authentication only, or it can also provide integrity checking, and possibly encryption as well. Some mechanisms let you negotiate which ones you want; with others it's a take-it-or-leave-it scenario.
Anyway, the Internet Assigned Numbers Authority (IANA) maintains a registry of SASL mechanisms. Let's look at a few of them.
At one end of the spectrum, the "PLAIN" mechanism is your basic username/password response. You can use something like this if you've already got encryption (e.g., in a VPN), and you have a "legacy UNIX" password system (something that stores a username and its hashed password).
Of course, we'd all prefer to avoid sending passwords over the network (even if the transport is encrypted), so with the "CRAM-MD5" mechanism the client sends a username, the server sends back a challenge, and the client sends a response, which is successful only if the client knows the password associated with the username. Although the "CRAM-MD5" mechanism is the entry-level way to avoid replay attacks, it has the drawback that the password has to be available in plain text on the server -- on the other hand, you're not sending the password over the network, so it's a trade-off.
Perhaps you're in an environment where you don't trust either the client (it's a kiosk) or the server. In that case you can use OTP, the one-time response mechanism. It's harder to configure and takes more cycles to run, but OTP has the advantage that the server can authenticate the client without either knowing the actual password.
Perhaps the thing you care about the most is fast authentication that avoids replay attacks, and maybe you want integrity checking, or perhaps encryption instead. Then you probably want the "DIGEST-MD5" mechanism, designed to minimize the burden on the server and still allow you to exchange key information to prevent data tampering or disclosure.
Once again, the administrator gets to select the level of protection. If you don't need to encrypt, but want to make sure the traffic is authenticated, doing integrity checking only is a lot faster.
Or perhaps you've already deployed Kerberos or SecureID(tm). Well, there are SASL mechanisms that interface directly with them. Or, perhaps ...well, you get the idea.
To put this in perspective, let's look at a figure from BEEP: The Definitive Guide, which uses SASL:
+========================================================================+ | | | mechanism basic idea Speed Ease Secure | | --------- ------------------------- ------- -------- ------ | | ANONYMOUS anonymous FTP fastest simplest n/a | | | | PLAIN leverage legacy passwords fastest simplest weakest | | | | CRAM-MD5 basic challenge/response fast simple good | | DIGEST-MD5 | | | | OTP one-time password good hard good | | SECURID | | | | KERBEROS_V4 trusted third-party fast harder stronger | | GSSAPI | | | | TLS+EXTERNAL public-key infrastructure slow hardest best | | | +========================================================================+
This figure shows an informal taxonomy of SASL mechanisms, originally developed by Chris Newman. Obviously, this is a rough distillation -- a single column labeled "Secure" is clearly over-simplified.
Actually, this figure shows something new: mixing SSL and SASL (TLS is basically SSLv3). In other words, the administrator may decide to start with TLS to provide privacy, and then use SASL for authentication. The EXTERNAL mechanism is SASL's null layer -- it says to use whatever authentication was provided by the layer below. So in the figure, TLS+EXTERNAL says to perform TLS with mutual-authentication, and then use the client-side certificate as the client's identity. Alternatively, TLS+PLAIN says to perform TLS (probably with only a server-side certificate), and then do a username/password exchange.
It turns out that it's easy to define a protocol that uses SASL -- it just has to support a couple of simple functions, and it doesn't need to know anything about any particular mechanism.
The first requirement is that servers must be able to tell the client what mechanisms are available. Typically this is done when the server sends a greeting to the client, telling it what options it supports.
Here's how SMTP does it:
S: 220 example.com ESMTP server ready C: EHLO rubble.com S: 250-example.com yabba, dabba, doo! S: 250-AUTH ANONYMOUS CRAM-MD5 DIGEST-MD5 OTP S: 250 HELP
The way to read this is pretty simple: when the client (C:) establishes a TCP connection to the server (S:), the server sends the time-honored 220 greeting. The client then asks the server to list the SMTP extensions that it supports (EHLO). The server supports two (AUTH and HELP). The AUTH extension indicates that the server supports SASL, and remaining parameters on that line indicate the SASL mechanisms available.
Here's how BEEP, an entirely different protocol, does it:
S: RPY 0 0 . 0 289 S: Content-Type: application/beep+xml S: S: <greeting> S: <profile uri='http://iana.org/beep/sasl/ANONYMOUS' /> S: <profile uri='http://iana.org/beep/sasl/CRAM-MD5' /> S: <profile uri='http://iana.org/beep/sasl/DIGEST-MD5' /> S: <profile uri='http://iana.org/beep/sasl/OTP' /> S: </greeting> S: END
In this example the server sends a greeting as soon as the initiator connects to it. Each of the profiles starting with ".../sasl/" indicates a SASL mechanism available to the initiator.
The second requirement is that clients must be able to tell the server to start a particular mechanism, and then both must be able to exchange "blobs" of information to initialize the mechanism, possibly indicating success or failure.
Here's how SMTP does it:
C: AUTH OTP AGJsb2NrbWFzdGVy S: 334 b3RwLXNoYTEgOTk5NyBwaXh5bWlzYXM4NTgwNSBleHQ= C: d29yZDpmZXJuIGhhbmcgYnJvdyBib25nIGhlcmQgdG9n S: 235
The way to read this is that the client asks 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). Because the arbitrary binary data may be sent during the SASL negotiation, it is always base64-encoded when sent via SMTP.
Note that depending on how complex the initialization is, you might have several exchanges between the client and the server before success (or failure) is declared.
Here's how BEEP does it:
C: MSG 0 1 . 52 183 C: Content-Type: application/beep+xml C: C: <start number='1'> C: <profile uri='http://iana.org/beep/SASL/OTP'> C: <![CDATA[<blob>AGJsb2NrbWFzdGVy</blob>]]> C: </profile> C: </start> C: END S: RPY 0 1 . 221 289 S: Content-Type: application/beep+xml S: S: <profile uri='http://iana.org/beep/SASL/OTP'> S: <![CDATA[<blob>b3RwLXNoYTEgOTk5NyBwaXh5bWlzYXM4NTgwNSBleHQ=</blob>]]> S: </profile> S: END C: MSG 1 0 . 0 97 C: Content-Type: application/beep+xml C: C: <blob>d29yZDpmZXJuIGhhbmcgYnJvdyBib25nIGhlcmQgdG9n</blob> C: END S: RPY 1 0 . 0 66 S: Content-Type: application/beep+xml S: S: <blob status='complete' /> S: END
Although superficially more verbose, the exact same kind of things are happening here. The only non-obvious change is that the "blob" elements sent by the server are examined for success (status=complete), or continuation (no status attribute).
The final requirement is that on success both the client and the server call a routine to filter traffic to/from the network. If the mechanism is doing any kind of cryptography, this routine will transparently handle it for the application.
One of the cool things about SASL is that even though the administrator has a lot of flexibility in configuring which mechanisms are available, this doesn't translate into a lot of complexity.
Let's look at some fragments from a client-side implementation written in a scripting language that uses SASL:
-mechanism anonymous -username ...
- anonymous login and no privacy
-mechanism otp -username ...
- use a one-time password to authenticate, but no privacy
- use TLS for privacy, but don't authenticate
-signed true -username ...
- authenticate using any SASL mechanism supporting messaging integrity,
but no privacy
-mechanism any -username ...
- use any SASL mechanism to authenticate, negotiating the strongest privacy possible (which may be none)
-privacy optional -username ...
- authenticate using any SASL mechanism, and negotiate privacy if available
-privacy strong -certfile ... -mechanism external
- use TLS for privacy, and authenticate using a client-side certificate
(the username is automatically derived from the certificate)
-privacy strong -mechanism plain -username ...
- use TLS for privacy, and then authenticate using a user/pass exchange
My two favorites are the
-signed true and
-mechanism any examples, which basically tell the client "I really don't care which mechanisms are available, just use something that has this functionality."
In the next article, we'll look at how to use SASL with the CMU Cyrus SASL implementation. For more information on BEEP, get a copy of my book, BEEP: The Definitive Guide.
Marshall T. Rose is the prime mover of the BEEP Protocol. In his former position as the Internet Engineering Task Force (IETF) area director for network management, he was one of a dozen individuals who oversaw the Internet's standardization process.
Return to the O'Reilly Network.