JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Developer's Guide to Oracle Solaris Security     Oracle Solaris 11 Express 11/10
search filter icon
search icon

Document Information


1.  Oracle Solaris Security for Developers (Overview)

2.  Developing Privileged Applications

3.  Writing PAM Applications and Services

4.  Writing Applications That Use GSS-API

5.  GSS-API Client Example

GSSAPI Client Example Overview

GSSAPI Client Example Structure

Running the GSSAPI Client Example

GSSAPI Client Example: main() Function

Opening a Connection With the Server

Establishing a Security Context With the Server

Translating a Service Name into GSS-API Format

Establishing a Security Context for GSS-API

Miscellaneous GSSAPI Context Operations on the Client Side

Wrapping and Sending a Message

Reading and Verifying a Signature Block From a GSS-API Client

Deleting the Security Context

6.  GSS-API Server Example

7.  Writing Applications That Use SASL

8.  Introduction to the Oracle Solaris Cryptographic Framework

9.  Writing User-Level Cryptographic Applications and Providers

10.  Introduction to the Oracle Solaris Key Management Framework

A.  Sample C-Based GSS-API Programs

B.  GSS-API Reference

C.  Specifying an OID

D.  Source Code for SASL Example

E.  SASL Reference Tables

F.  Packaging and Signing Cryptographic Providers



Establishing a Security Context With the Server

After the connection is made, call_server() uses the function client_establish_context() to create the security context, as follows:

if (client_establish_context(s, service-name, deleg-flag, oid, &context,
                                  &ret-flags) < 0) {
          (void) close(s);
          return -1;

The client_establish_context() performs the following tasks:

Translating a Service Name into GSS-API Format

The first task that client_establish_context() performs is to translate the service name string to internal GSS-API format by using gss_import_name().

Example 5-3 client_establish_context() – Translate Service Name

     * Import the name into target_name.  Use send_tok to save
     * local variable space.

     send_tok.value = service_name;
     send_tok.length = strlen(service_name) + 1;
     maj_stat = gss_import_name(&min_stat, &send_tok,
                        (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &target_name);
     if (maj_stat != GSS_S_COMPLETE) {
          display_status("parsing name", maj_stat, min_stat);
          return -1;

gss_import_name() takes the name of the service, which is stored in an opaque GSS_API buffer send_tok, and converts the string to the GSS_API internal name target_name. send_tok is used to save space instead of declaring a new gss_buffer_desc. The third argument is a gss_OID type that indicates the send_tok name format. This example uses GSS_C_NT_HOSTBASED_SERVICE, which means a service of the format service@host. See Name Types for other possible values for this argument.

Establishing a Security Context for GSS-API

Once the service has been translated to GSS-API internal format, the context can be established. To maximize portability, establishing context should always be performed as a loop.

Before entering the loop, client_establish_context() initializes the context and the token_ptr parameter. There is a choice in the use of token_ptr. token_ptr can point either to send_tok, the token to be sent to the server, or to recv_tok, the token that is sent back by the server.

Inside the loop, two items are checked:

The following pseudocode describes the loop:

do gss_init_sec_context() if no context was created exit with error; if the status is neither "complete" nor "in process" release the service namespace and exit with error; if there is a token to send to the server, that is, the size is nonzero send the token; if sending the token fails, release the token and service namespaces. Exit with error; release the namespace for the token that was just sent; if the context is not completely set up receive a token from the server; while the context is not complete

The loop starts with a call to gss_init_sec_context(), which takes the following arguments:

Note - The client does not need to acquire credentials before initiating a context. On the client side, credential management is handled transparently by the GSS-API. That is, the GSS-API knows how to get credentials that are created by this mechanism for this principal. As a result, the application can pass gss_init_sec_context() a default credential. On the server side, however, a server application must explicitly acquire credentials for a service before accepting a context. See Acquiring Credentials.

After checking that a context or part of one exists and that gss_init_sec_context() is returning valid status, connect_to_server() checks that gss_init_sec_context() has provided a token to send to the server. If no token is present, the server has signalled that no other tokens are needed. If a token has been provided, then that token must be sent to the server. If sending the token fails, the namespaces for the token and service cannot be determined, and connect_to_server() exits. The following algorithm checks for the presence of a token by looking at the length:

if (send_tok_length != 0) {
     if (send_token(s, &send_tok) < 0) {
          (void) gss_release_buffer(&min_stat, &send_tok);
          (void) gss_release_name(&min_stat, &target_name);
          return -1;

send_token() is not a GSS-API function and needs to be written by the user. The send_token() function writes a token to the file descriptor. send_token() returns 0 on success and –1 on failure. GSS-API does not send or receive tokens itself. The calling applications are responsible for sending and receiving any tokens that have been created by GSS-API.

The source code for the context establishment loop is provided below.

Note - The source code for this example is also available through the Sun download center. See

Example 5-4 Loop for Establishing Contexts

 * Perform the context establishment loop.
 * On each pass through the loop, token_ptr points to the token
 * to send to the server (or GSS_C_NO_BUFFER on the first pass).
 * Every generated token is stored in send_tok which is then
 * transmitted to the server; every received token is stored in
 * recv_tok, which token_ptr is then set to, to be processed by
 * the next call to gss_init_sec_context.
 * GSS-API guarantees that send_tok's length will be non-zero
 * if and only if the server is expecting another token from us,
 * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
 * and only if the server has another token to send us.

token_ptr = GSS_C_NO_BUFFER;
*gss_context = GSS_C_NO_CONTEXT;

do {
    maj_stat =
        gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, 
        gss_context, target_name, oid, 
        GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | deleg_flag,
        0, NULL,                      /* no channel bindings */
        token_ptr, NULL,              /* ignore mech type */
        &send_tok, ret_flags, NULL);  /* ignore time_rec */
    if (gss_context == NULL){
        printf("Cannot create context\n");
        return GSS_S_NO_CONTEXT;
    if (token_ptr != GSS_C_NO_BUFFER)
        (void) gss_release_buffer(&min_stat, &recv_tok);
    if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
        display_status("initializing context", maj_stat, min_stat);
        (void) gss_release_name(&min_stat, &target_name);
        return -1;

    if (send_tok.length != 0){
        fprintf(stdout, "Sending init_sec_context token (size=%ld)...",
        if (send_token(s, &send_tok) < 0) {
            (void) gss_release_buffer(&min_stat, &send_tok);
            (void) gss_release_name(&min_stat, &target_name);
            return -1;
    (void) gss_release_buffer(&min_stat, &send_tok);

    if (maj_stat == GSS_S_CONTINUE_NEEDED) {
        fprintf(stdout, "continue needed...");
        if (recv_token(s, &recv_tok) < 0) {
            (void) gss_release_name(&min_stat, &target_name);
            return -1;
        token_ptr = &recv_tok;
} while (maj_stat == GSS_S_CONTINUE_NEEDED);

For more information on how send_token() and recv_token() work, see Miscellaneous GSS-API Sample Functions.