Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
1.  The GSS-API: An Overview Some Introductory Concepts Principals  Previous   Contents   Next 
   
 

GSS-API Data Types

The following sections explain the more important and visible GSS-API data types; see "GSS-API Data Types and Values" for more information.


Caution - It is the responsibility of the calling application to free all data space that has been allocated.


Integers

Because the size of an int can vary from platform to platform, the GSS-API provides the following integer data type:

OM_uint32

which is a 32-bit unsigned integer.

Strings and Similar Data

Since the GSS-API handles all data in internal formats, strings must be converted to a GSS-API format before being passed to GSS-API functions. The GSS-API handles strings with the gss_buffer_desc structure; gss_buffer_t is a pointer to such a structure.
typedef struct gss_buffer_desc_struct {
     size_t     length;
     void       *value;
}  gss_buffer_desc *gss_buffer_t;

Therefore, strings must be put into a gss_buffer_desc structure before being passed to functions that use them. Consider a generic GSS-API function that takes a message and processes it in some way (for example, applies protection to it before it is transmitted), as follows:


Example 1-1 Using Strings

char *message_string;
gss_buffer_desc input_msg_buffer;

input_msg_buffer.value = message_string;
input_msg_buffer.length = strlen(input_msg_buffer.value) + 1;

gss_generic_function(arg1, &input_msg_buffer, arg2...);

gss_release_buffer(input_msg_buffer);

Note that input_msg_buffer must be deallocated with gss_release_buffer() when you are finished with it.

The gss_buffer_desc object is not just for character strings; for example, tokens are manipulated as gss_buffer_desc objects. (See "GSS-API Tokens".)

Names

A name refers to a principal -- that is, a person, a machine, or an application, such as joe@company or nfs@machinename. In the GSS-API, names are stored as a gss_name_t object, which is opaque to the application. Names are converted from gss_buffer_t objects to the gss_name_t form by the gss_import_name() function. Every imported name has an associated name type, which indicates what kind of format the name is in. (See under "OIDs" for more about name types, and see "Name Types" for a list of valid name types).

gss_import_name() looks like this:
OM_uint32 gss_import_name (
       OM_uint32          *minor_status,
       const gss_buffer_t input_name_buffer,
       const gss_OID      input_name_type,
       gss_name_t         *output_name)

minor_status

Status code returned by the underlying mechanism. (See "Status Codes".)

input_name_buffer

The gss_buffer_desc structure containing the name to be imported. The application must allocate this explicitly (see "Strings and Similar Data" as well as Example 1-2.) This argument must be deallocated with gss_release_buffer() when the application is finished with it.

input_name_type

A gss_OID that specifies the format that the input_name_buffer is in. (See "Name Types"; also, "Name Types" contains a table of valid name types.)

output_name

The gss_name_t structure to receive the name.

Slightly modifying the generic example shown in Example 1-1, here is how you can use gss_import_name(). First, the regular string is inserted into a gss_buffer_desc structure, and then gss_import_name() places it into a gss_name_t structure.


Example 1-2 Using gss_import_name()

char *name_string;
gss_buffer_desc input_name_buffer;
gss_name_t      output_name_buffer;

input_name_buffer.value = name_string;
input_name_buffer.length = strlen(input_name_buffer.value) + 1;

gss_import_name(&minor_status, input_name_buffer, 
                    GSS_C_NT_HOSTBASED_SERVICE, &output_name);

gss_release_buffer(input_name_buffer);

An imported name can be put back into a gss_buffer_t object for display in human-readable form with gss_display_name(); however, gss_display_name() does not guarantee that the resulting string will be the same as the original, because of the way the underlying mechanisms store names. The GSS-API includes several other functions for manipulating names; see "GSS-API Functions".

A gss_name_t structure can contain several versions of a single name -- one version produced for each mechanism supported by the GSS-API. That is, a gss_name_t structure for "joe@company" might contain one version of that name as rendered by Kerberos v5, another version as given by a different mechanism, and so on. The GSS-API provides a function, gss_canonicalize_name(), that takes as its input an internal name (that is, a gss_name_t structure) and a mechanism and yields a second internal name (also a gss_name_t) that contains only a single version of the name, specific to that mechanism.

Such a mechanism-specific name is called a Mechanism Name (MN). "Mechanism Name" is a slightly confusing label, since it refers not to the name of a mechanism, but to the name of a principal as produced by a given mechanism. This process is illustrated by Figure 1-3.

Figure 1-3 Internal Names and Mechanism Names

Comparing Names

Why is such a function useful? Consider the case where a server has received a name from a client and wants to look up that name in an Access Control List. (An Access Control List, or ACL, is a list of principals with particular access permissions.) One way to do this would be as follows:

  1. Import the client name into GSS-API internal format with gss_import_name(), if it hasn't already been imported.

    In some cases, the server will receive a name in internal format, so this step will not be necessary -- in particular, if the server is looking up the client's own name. (During context initiation, the client's own name is passed in internal format.)

  2. Import each name in the ACL with gss_import_name().

  3. Compare each imported ACL name with the imported client's name, using gss_compare_name().

This process is shown in Figure 1-4; in this case, we assume that Step 1 is needed.

Figure 1-4 Comparing Names (Slow)

That procedure is fine if you only need to compare the client's name with a few names. However, it is a very slow way to check a large list! Running gss_import_name() and gss_compare_name() for every name in the ACL might require a lot of CPU cycles. This is a better way:

  1. Import the client's name with gss_import_name() (if it hasn't already been imported).

    As with the previous method of comparing names, in some cases the server receives a name in internal format and so this step is not necessary.

  2. Use gss_canonicalize_name() to produce an MN of the client's name.

  3. Use gss_export_name() to produce an "exported name," a contiguous-string version of the client's name.

  4. Compare the exported client's name with each name in the ACL by using memcmp(), which is a fast, low-overhead function.

This process is shown in Figure 1-5; again, assume the server needs to import the name received from the client.

Figure 1-5 Comparing Names (Fast)

Because gss_export_name() expects a Mechanism Name (MN), you must run gss_canonicalize_name() on the client's name first.

See the gss_canonicalize_name(3GSS), gss_export_name(3GSS), and gss_import_name(3GSS) man pages for more information.

 
 
 
  Previous   Contents   Next