Skip Navigation Links | |
Exit Print View | |
![]() |
Developer's Guide to Oracle Solaris 10 Security Oracle Solaris 10 1/13 Information Library |
1. Oracle Solaris Security for Developers (Overview)
2. Developing Privileged Applications
3. Writing PAM Applications and Services
4. Writing Applications That Use GSS-API
7. Writing Applications That Use SASL
Important Structures for SASL Plug-ins
User Canonicalization Plug-ins
Auxiliary Property (auxprop) Plug-ins
SASL Plug-in Development Guidelines
Error Reporting in SASL Plug-ins
Memory Allocation in SASL Plug-ins
Setting the SASL Negotiation Sequence
8. Introduction to the Oracle Solaris Cryptographic Framework
9. Writing User-Level Cryptographic Applications and Providers
10. Using the Smart Card Framework
A. Sample C-Based GSS-API Programs
D. Source Code for SASL Example
SASL provides developers of applications and shared libraries with mechanisms for authentication, data integrity-checking, and encryption. SASL enables the developer to code to a generic API. This approach avoids dependencies on specific mechanisms. SASL is particularly appropriate for applications that use the IMAP, SMTP, ACAP, and LDAP protocols, as these protocols all support SASL. SASL is described in RFC 2222.
The SASL library is called libsasl. libsasl is a framework that allows properly written SASL consumer applications to use any SASL plug-ins that are available on the system. The term plug-in refers to objects that provide services for SASL. Plug-ins are external to libsasl. SASL plug-ins can be used for authentication and security, canonicalization of names, and lookup of auxiliary properties, such as passwords. Cryptographic algorithms are stored in plug-ins rather than in libsasl.
libsasl provides an application programming interface (API) for consumer applications and libraries. A service provider interface (SPI) is provided for plug-ins to supply services to libsasl. libsasl is not aware of the network or the protocol. Accordingly, the application must take responsibility for sending and receiving data between the client and server.
SASL uses two important identifiers for users. The authentication ID (authid) is the user ID for authenticating the user. The authentication ID grants the user access to a system. The authorization ID (userid) is used to check whether the user is allowed to use a particular option.
The SASL client application and SASL server application negotiate a common SASL mechanism and security level. Typically, the SASL server application sends its list of acceptable authentication mechanisms to the client. The SASL client application can then decide which authentication mechanism best satisfies its requirements. After this point, the authentication takes place using the agreed-upon authentication mechanism as a series of client-server exchanges of the SASL supplied authentication data. This exchange continues until the authentication successfully completes, fails, or is aborted by the client or the server.
In the process of authentication, the SASL authentication mechanism can negotiate a security layer. If a security layer is selected, that layer must be used for the duration of the SASL session.
The following figure shows the basic SASL architecture.
Figure 7-1 SASL Architecture
Client and server applications make calls to their local copies of libsasl through the SASL API. libsasl communicates with the SASL mechanisms through the SASL service provider interface (SPI).
Security mechanism plug-ins provide security services to libsasl. Some typical functions that are provided by security mechanisms follow:
Authentication on the client side
Authentication on the server side
Integrity, that is, checking that transmitted data is intact
Confidentiality, that is, encrypting and decrypting transmitted data
SSF, the security strength factor, indicates the strength of the SASL protection. If the mechanism supports a security layer, the client and server negotiate the SSF. The value of the SSF is based on the security properties that were specified before the SASL negotiation. If a non-zero SSF is negotiated, both client and server need to use the mechanism's security layer when the authentication has completed. SSF is represented by an integer with one of the following values:
0 – No protection.
1 – Integrity checking only.
>1 – Supports authentication, integrity and confidentiality. The number represents the encryption key length.
The confidentiality and integrity operations are performed by the security mechanism. libsasl coordinates these requests.
Note - In the negotiation, the SASL client selects the mechanism with the maximum SSF. However, the actual SASL mechanism that is chosen might subsequently negotiate a lower SSF.
Applications communicate with libsasl through the libsasl API. libsasl can request additional information by means of callbacks that are registered by the application. Applications do not call plug-ins directly, only through libsasl. Plug-ins generally call the libsasl framework's plug-ins, which then call the application's callbacks. SASL plug-ins can also call the application directly, although the application does not know whether the call came from a plug-in or from libsasl.
Callbacks are useful in multiple areas, as follows.
libsasl can use callbacks to get information that is needed to complete authentication.
libsasl consumer applications can use callbacks to change search paths for plug-ins and configuration data, to verify files, and to change various default behaviors.
Servers can use callbacks to change authorization policies, to supply different password verification methods, and to get password change information.
Clients and servers can use callbacks to specify the language for error messages.
Applications register two sorts of callbacks: global and session. Additionally, libsasl defines a number of callback identifiers that are used to register for different sorts of callbacks. If a given type of callback is not registered, libsasl takes default action.
Session callbacks override global callbacks. If a session callback is specified for a given ID, the global callback is not called for that session. Some callbacks must be global, because these callbacks occur outside of sessions. The following instances require global callbacks:
Determination of search paths for plug-ins to load
Verification of plug-ins
Location of configuration data
The logging of error messages
Other global configuration of libsasl or its plug-ins
A SASL callback can be registered with a NULL callback function for a given SASL callback ID. The NULL callback function indicates that the client is equipped to supply the needed data. All SASL callback IDs start with the prefix SASL_CB_.
SASL provides the following callbacks for use by either a client or a server:
Gets a SASL option. Options modify the behavior of libsasl(3LIB) and related plug-ins. Can be used by either a client or a server.
Sets the logging function for libsasl and its plug-ins. The default behavior is to use syslog.
Gets the colon-separated list of SASL plug-in search paths. The default paths depend on the architecture as follows:
32-bit SPARC architecture: /usr/lib/sasl
32-bit x86 architecture: /usr/lib/sasl
64-bit SPARC architecture: /usr/lib/sasl/sparcv9
x64 architecture: /usr/lib/sasl/amd64
Gets the path to the SASL server's configuration directory. The default is /etc/sasl.
Specifies a comma-separated list of RFC 1766 language codes in order of preference, for client and server error messages and for client prompts. The default is i-default.
SASL provides the following callbacks for use by clients only:
Gets the client user name. The user name is the same as the authorization ID. The LOGNAME environment variable is the default.
Gets the result for a given challenge prompt. The input from the client can be echoed.
Gets the result for a given challenge prompt. The input from the client should not be echoed.
SASL provides the following callbacks for use by servers only:
Checks that an authenticated user is authorized to act on behalf of the specified user. If this callback is not registered, then the authenticated user and the user to be authorized must be the same. If these IDs are not the same, then the authentication fails. Use the server application to take care of nonstandard authorization policies.
Verifies a plain text password against the caller-supplied user database.
Calls an application-supplied user canonicalization function.
When the SASL library is first initialized, the server and client declare any necessary global callbacks. The global callbacks are available prior to and during the SASL sessions. Prior to initialization, callbacks perform such tasks as loading plug-ins, logging data, and reading configuration files. At the start of a SASL session, additional callbacks can be declared. Such callbacks can override global callbacks if necessary.
libsasl uses a SASL connection context to maintain the state of each SASL session for both SASL clients and SASL servers. Each context can be used for only one authentication and security session at a time. The maintained state includes the following information:
Connection information, such as service, naming and address information, and protocol flags
Callbacks specific to the connection
Security properties for negotiating the SASL SSF
State of the authentication along with security layer information
The following diagram shows steps in the SASL life cycle. The client actions are shown on the left of the diagram and the server actions on the right side. The arrows in the middle show interactions between the client and server over an external connection.
Figure 7-2 SASL Life Cycle
The sections that follow illustrate the steps in the life cycle.
The client calls sasl_client_init() to initialize libsasl for the client's use. The server calls sasl_server_init() to initialize libsasl for server use.
When sasl_client_init() is run, the SASL client, the client's mechanisms and the client's canonicalization plug-in are loaded. Similarly, when sasl_server_init() is called, the SASL server, the server's mechanisms, the server's canonicalization plug-in, and the server's auxprop plug-in are loaded. After sasl_client_init() has been called, additional client plug-ins can be added by using sasl_client_add_plugin() and sasl_canonuser_add_plugin(). On the server side, after sasl_server_init() has been called, additional server plug-ins can be added through sasl_server_add_plugin(), sasl_canonuser_add_plugin(), and sasl_auxprop_add_plugin(). SASL mechanisms are provided in the Solaris software in the following directories according to the architecture:
32-bit SPARC architecture: /usr/lib/sasl
32-bit x86 architecture: /usr/lib/sasl
64-bit SPARC architecture: /usr/lib/sasl/sparcv9
x64 architecture: /usr/lib/sasl/amd64
The SASL_CB_GETPATH callback can be used to override the default location.
At this point, any required global callbacks are set. SASL clients and servers might include the following callbacks:
SASL_CB_GETOPT
SASL_CB_LOG
SASL_CB_GETPATH
SASL_CB_VERIFYFILE
A SASL server might additionally include the SASL_CB_GETCONF callback.
The server and client use establish the connection through the protocol. To use SASL for authentication, the server and client create SASL connection contexts by using sasl_server_new() and sasl_client_new() respectively. The SASL client and server can use sasl_setprop() to set properties that impose security restrictions on mechanisms. This approach enables a SASL consumer application to decide the minimum SSF, the maximum SSF, and the security properties for the specified SASL connection context.
#define SASL_SEC_NOPLAINTEXT 0x0001 #define SASL_SEC_NOACTIVE 0x0002 #define SASL_SEC_NODICTIONARY 0x0004 #define SASL_SEC_FORWARD_SECRECY 0x0008 #define SASL_SEC_NOANONYMOUS 0x0010 #define SASL_SEC_PASS_CREDENTIALS 0x0020 #define SASL_SEC_MUTUAL_AUTH 0x0040
Note - Authentication and a security layer can be provided by the client-server protocol or by some other mechanism that is external to libsasl. In such a case, sasl_setprop() can be used to set the external authentication ID or the external SSF. For example, consider the case in which the protocol uses SSL with client authentication to the server. In this case, the external authentication identity can be the client's subject name. The external SSF can be the key size.
For the server, libsasl determines the available SASL mechanisms according to the security properties and the external SSF. The client obtains the available SASL mechanisms from the SASL server through the protocol.
For a SASL server to create a SASL connection context, the server should call sasl_server_new(). An existing SASL connection context that is no longer in use can be reused. However, the following parameters might need to be reset:
#define SASL_DEFUSERREALM 3 /* default realm passed to server_new or set with setprop */ #define SASL_IPLOCALPORT 8 /* iplocalport string passed to server_new */ #define SASL_IPREMOTEPORT 9 /* ipremoteport string passed to server_new */ #define SASL_SERVICE 12 /* service passed to sasl_*_new */ #define SASL_SERVERFQDN 13 /* serverFQDN passed to sasl_*_new */
You can modify any of the parameters to sasl_client_new() and sasl_server_new() except the callbacks and protocol flags.
The server and client can also establish security policy and set connection specific parameters by using sasl_setprop() to specify the following properties:
#define SASL_SSF_EXTERNAL 100 /* external SSF active (sasl_ssf_t *) */ #define SASL_SEC_PROPS 101 /* sasl_security_properties_t */ #define SASL_AUTH_EXTERNAL 102 /* external authentication ID (const char *) */
SASL_SSF_EXTERNAL – For setting the strength factor, that is, the number of bits in the key
SASL_SEC_PROPS – For defining security policy
SASL_AUTH_EXTERNAL – The external authentication ID
The server can call sasl_listmech() to get a list of the available SASL mechanisms that satisfy the security policy. The client can generally get the list of available mechanisms from the server in a protocol-dependent way.
The initialization of a SASL session is illustrated in the following diagram. In this diagram and subsequent diagrams, data checks after transmission over the protocol have been omitted for the sake of simplicity.
Figure 7-3 SASL Session Initialization
Authentication takes a variable number of client and server steps depending on the security mechanism that is used. The SASL client calls sasl_client_start() with a list of security mechanisms to use. This list typically comes from the server. libsasl selects the best mechanism to use for this SASL session, according to the available mechanisms and the client's security policy. The client's security policy controls which mechanisms are permitted. The selected mechanism is returned by sasl_client_start(). Sometimes the security mechanism for the client sometimes needs additional information for authentication. For registered callbacks, libsasl calls the specified callback unless the callback function is NULL. If the callback function is NULL, libsasl returns SASL_INTERACT and a request for needed information. If SASL_INTERACT is returned, then sasl_client_start() should be called with the requested information.
If sasl_client_start() returns SASL_CONTINUE or SASL_OK, the client should send the selected mechanism with any resulting authentication data to the server. If any other value is returned, an error has occurred. For example, no mechanism might be available.
The server receives the mechanism that has been selected by the client, along with any authentication data. The server then calls sasl_server_start() to initialize the mechanism data for this session. sasl_server_start() also processes any authentication data. If sasl_server_start() returns SASL_CONTINUE or SASL_OK, the server sends authentication data. If sasl_server_start() returns any other value, an error has occurred such as an unacceptable mechanism or an authentication failure. The authentication must be aborted. The SASL context should be either freed or reused.
This part of the authentication process is illustrated in the following diagram.
Figure 7-4 SASL Authentication: Sending Client Data
If the server call to sasl_server_start() returns SASL_CONTINUE, the server continues to communicate with the client to get all the necessary authentication information. The number of subsequent steps depends on the mechanism. If needed, the client calls sasl_client_step() to process the authentication data from the server and to generate a reply. Similarly, the server can call sasl_server_step() to process the authentication from the client and to generate a reply in turn. This exchange continues until the authentication is complete or until an error has occurred. SASL_OK is returned to indicate that the authentication has successfully completed for the client or server. The SASL mechanism might still have additional data to send to the other side so the other side can complete authentication. When authentication has been achieved on both sides, the server and client can inquire about each other's properties.
The following diagram shows the interactions between the server and client to transfer the additional authentication data.
Figure 7-5 SASL Authentication: Processing Server Data
To check for a security layer, use the sasl_getprop(3SASL) function to see if the security strength factor (SSF) has a value that is greater than 0. If a security layer has been negotiated, the client and server must use the resulting SSF after successful authentication. Data is exchanged between the client and server in a similar fashion to authentication. sasl_encode() is applied to data before the data is sent by the protocol to the client or server. On the receiving end, data is decoded by sasl_decode(). If a security layer has not been negotiated, the SASL connection context is not needed. The context can then be disposed of or reused.
A SASL connection context should only be freed when the session is not to be reused. sasl_dispose() frees the SASL connection context and all associated resources and mechanisms. The SASL connection contexts must be disposed before calling sasl_done(). sasl_done() is not responsible for releasing context resources for the SASL connection. See libsasl Cleanup.
When a SASL session is freed, the associated mechanisms are informed that all state can be freed. A SASL session should only be freed when the session is not to be reused. Otherwise, the SASL state can be reused by another session. Both the client and server use sasl_dispose() to free the SASL connection context.
This step releases all the resources in the SASL library and the plug-ins. The client and server call sasl_done() to release libsasl() resources and to unload all the SASL plug-ins. sasl_done() does not release SASL connection contexts. Note that if an application is both a SASL client and a SASL server, sasl_done() releases both the SASL client and SASL server resources. You cannot release the resources for just the client or the server.
![]() | Caution - Libraries should not call sasl_done(). Applications should exercise caution when calling sasl_done() to avoid interference with any libraries that might be using libsasl. |