Developer's Guide to Oracle® Solaris 11 Security

Exit Print View

Updated: July 2014

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 status that is returned by gss_init_sec_context()

    The return status catches any errors that might require the loop to be aborted. gss_init_sec_context() returns GSS_S_CONTINUE_NEEDED if and only if the server has another token to send.

  • The size of token to be sent to the server, which is generated by gss_init_sec_context()

    A token size of zero indicates that no more information exists that can be sent to the server and that the loop can be exited. The token size is determined from token_ptr.

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:

  • The status code to be set by the underlying mechanism.

  • The credential handle. The example uses GSS_C_NO_CREDENTIAL to act as a default principal.

  • gss-context, which represents the context handle to be created.

  • target-name of the service, as a GSS_API internal name.

  • oid, the ID for the mechanism.

  • Request flags. In this case, the client requests that the server authenticate itself, that message-duplication be turned on, and that the server act as a proxy if requested.

  • No time limit for the context.

  • No request for channel bindings.

  • token_ptr, which points to the token to be received from the server.

  • The mechanism actually used by the server. The mechanism is set to NULL here because the application does not use this value.

  • &send_tok, which is the token that gss_init_sec_context() creates to send to the server.

  • Return flags. Set to NULL because they are ignored in this example.

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 Oracle 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.