Skip Navigation Links | |
Exit Print View | |
Developer's Guide to Oracle Solaris 11 Security Oracle Solaris 11.1 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
GSSAPI Server Example Overview
GSSAPI Server Example Structure
Running the GSSAPI Server Example
GSSAPI Server Example: main() Function
Signing and Returning the Message
Using the test_import_export_context() Function
Cleanup in the GSSAPI Server Example
7. Writing Applications That Use SASL
8. Introduction to the Oracle Solaris Cryptographic Framework
9. Writing User-Level Cryptographic Applications
10. Introduction to the Oracle Solaris Key Management Framework
A. Secure Coding Guidelines for Developers
B. Sample C-Based GSS-API Programs
Credentials are created by the underlying mechanisms rather than by the client application, server application, or GSS-API. A client program often has credentials that are obtained at login. A server always needs to acquire credentials explicitly.
The gss-server program has a function, server_acquire_creds(), to get the credentials for the service to be provided. The server_acquire_creds() function takes as input the name of the service and the security mechanism to be used. The server_acquire_creds() function then returns the credentials for the service. The server_acquire_creds() function uses the GSS-API function gss_acquire_cred() to get the credentials for the service that the server provides.
Before server_acquire_creds() accesses gss_acquire_cred(), server_acquire_creds() must complete the following two tasks:
Checking for a list of mechanisms and reducing the list to a single mechanism for the purpose of getting a credential.
If a single credential can be shared by multiple mechanisms, the gss_acquire_cred() function returns credentials for all those mechanisms. Therefore, gss_acquire_cred() takes as input a set of mechanisms. (See Working With Credentials in GSS-API.) In most cases, however, including this one, a single credential might not work for multiple mechanisms. In the gss-server program, either a single mechanism is specified on the command line or else the default mechanism is used. Therefore, the first task is to make sure that the set of mechanisms that was passed to gss_acquire_cred() contains a single mechanism, default or otherwise, as follows:
if (mechOid != GSS_C_NULL_OID) { desiredMechs = &mechOidSet; mechOidSet.count = 1; mechOidSet.elements = mechOid; } else desiredMechs = GSS_C_NULL_OID_SET;
GSS_C_NULL_OID_SET indicates that the default mechanism should be used.
Translating the service name into GSS-API format.
Because gss_acquire_cred() takes the service name in the form of a gss_name_t structure, the name of the service must be imported into that format. The gss_import_name() function performs this translation. Because this function, like all GSS-API functions, requires arguments to be GSS-API types, the service name has to be copied to a GSS-API buffer first, as follows:
name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; maj_stat = gss_import_name(&min_stat, &name_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (maj_stat != GSS_S_COMPLETE) { display_status("importing name", maj_stat, min_stat); if (mechOid != GSS_C_NO_OID) gss_release_oid(&min_stat, &mechOid); return -1; }
Note again the use of the nonstandard function gss_release_oid().
The input is the service name as a string in name_buf. The output is the pointer to a gss_name_t structure, server_name. The third argument, GSS_C_NT_HOSTBASED_SERVICE, is the name type for the string in name_buf. In this case, the name type indicates that the string should be interpreted as a service of the format service@host.
After these tasks have been performed, the server program can call gss_acquire_cred():
maj_stat = gss_acquire_cred(&min_stat, server_name, 0, desiredMechs, GSS_C_ACCEPT, server_creds, NULL, NULL);
min_stat is the error code returned by the function.
server_name is the name of the server.
0 indicates that the program does not need to know the maximum lifetime of the credential.
desiredMechs is the set of mechanisms for which this credential applies.
GSS_C_ACCEPT means that the credential can be used only to accept security contexts.
server_creds is the credential handle to be returned by the function.
NULL, NULL indicates that the program does not need to know either the specific mechanism being employed or the amount of time that the credential will be valid.
The following source code illustrates the server_acquire_creds() function.
Note - The source code for this example is also available through the Oracle download center. See http://www.oracle.com/technetwork/indexes/downloads/sdlc-decommission-333274.html.
Example 6-2 Sample Code for server_acquire_creds() Function
/* * Function: server_acquire_creds * * Purpose: imports a service name and acquires credentials for it * * Arguments: * * service_name (r) the ASCII service name mechType (r) the mechanism type to use * server_creds (w) the GSS-API service credentials * * Returns: 0 on success, -1 on failure * * Effects: * * The service name is imported with gss_import_name, and service * credentials are acquired with gss_acquire_cred. If either operation * fails, an error message is displayed and -1 is returned; otherwise, * 0 is returned. */ int server_acquire_creds(service_name, mechOid, server_creds) char *service_name; gss_OID mechOid; gss_cred_id_t *server_creds; { gss_buffer_desc name_buf; gss_name_t server_name; OM_uint32 maj_stat, min_stat; gss_OID_set_desc mechOidSet; gss_OID_set desiredMechs = GSS_C_NULL_OID_SET; if (mechOid != GSS_C_NULL_OID) { desiredMechs = &mechOidSet; mechOidSet.count = 1; mechOidSet.elements = mechOid; } else desiredMechs = GSS_C_NULL_OID_SET; name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; maj_stat = gss_import_name(&min_stat, &name_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (maj_stat != GSS_S_COMPLETE) { display_status("importing name", maj_stat, min_stat); if (mechOid != GSS_C_NO_OID) gss_release_oid(&min_stat, &mechOid); return -1; } maj_stat = gss_acquire_cred(&min_stat, server_name, 0, desiredMechs, GSS_C_ACCEPT, server_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { display_status("acquiring credentials", maj_stat, min_stat); return -1; } (void) gss_release_name(&min_stat, &server_name); return 0; }