A Walk-Through of the Sample GSS-API Programs
This chapter describes two sample GSS-API application programs. This chapter provides the following information:
Introduction to the Sample Programs
The source code for two C-language applications that make use of the GSS-API is provided in Appendix A, Sample C-Based GSS-API Programs. One sample application is for a client and the other for a server. This chapter guides you through those applications, step-by-step; it is intended to be read while referring to the cource code. It does not attempt to explain every facet of the applications in detail. Rather, it focuses on the aspects that relate to using the GSS-API.
Caution - Because the GSS_API does not automatically clean up after itself, applications and functions using the GSS-API must do so themselves. This means that functions that use GSS-API buffers or GSS-API namespaces, for example, should call GSS-API functions such as gss_release_buffer() and gss_release_name() when they are finished.
To save space and avoid repetition, we have generally not included such cleanup in the following code walk-through. Be aware that it must be performed. However; refer to Appendix A, Sample C-Based GSS-API Programs to see the sample programs in full if you are unsure how or when to use the cleanup functions.
Client-Side GSS-API: gss-client
The sample client-side program, gss-client, creates a security context with a server, establishes security parameters, and sends a string (the "message") to the server. It uses a simple TCP-based sockets connection to make its connection.
gss-client takes this form on the command line:
gss-client [-port port] [-d] [-mech mech] host service [-f] msg
Specifically, gss-client does the following:
Parses the command line.
Creates an OID (object ID) for a mechanism, if specified.
Creates a connection to the server.
Establishes a context.
Wraps the message.
Sends the message.
Verifies that the message has been "signed" correctly by the server.
Following is a step-by-step description of how gss-client works. Because it is a sample program designed to show off functionality, the parts of the program that do not closely relate to the steps above are skipped. Some features, such as importing and exporting contexts, or getting a wrap size, are discussed elsewhere in this manual.
Overview: main() (Client)
As with all C programs, the outer shell of the program is contained in the entry-point function, main(). main() performs four functions:
It parses command-line arguments, assigning them to variables:
If specified, port is the port number for making the connection to the remote machine specified by host.
If the -d flag is set, security credentials should be delegated to the server. Specifically, the deleg_flag variable is set to the GSS-API value GSS_C_DELEG_FLAG; otherwise deleg_flag is set to zero.
mech is the (optional) name of the security mechanism, such as Kerberos v5 or X.509, to use. If no mechanism is specified, the GSS-API will use a default mechanism.
The name of the network service requested by the client (such as telnet, ftp, or login service) is assigned to service_name.
Finally, msg is the string to send to the server as protected data. If the -f option is specified, then msg is the name of a file from which to read the string.
An example command line might look like this:
% gss-client -port 8080 -d -mech kerberos_v5 erebos.eng nfs "ls"
This command line specifies neither mechanism nor port, and does not use delegation:
% gss-client erebos.eng nfs "ls"
It calls parse_oid() to create a GSS-API OID (object identifier) from the name of a security mechanism (if such a name has been provided on the command line):
where mechanism is the string to translate and g_mechOid is a pointer to a gss_OID object for the mechanism. See Appendix C, Specifying an OID for more about specifying a non-default mechanism.
if (mechanism) parse_oid(mechanism, &g_mechOid);
It calls call_server(), which does the actual work of creating a context and sending data.
if (call_server(hostname, port, g_mechOid, service_name, deleg_flag, msg, use_file) < 0) exit(1);
It releases the storage space for the OID if it has not been released yet.
if (g_mechOID != GSS_C_NULL_OID) (void) gss_release_oid(&min_stat, &g_mechoid);
Note that gss_release_oid(), while supported by the Sun implementation of the GSS-API, is not supported by all GSS-API implementations and is considered nonstandard. Since applications should if possible use the default mechanism provided by the GSS-API instead of allocating one (with gss_str_to_oid()), the gss_release_oid() command generally should not be used.
Specifying a Non-Default Mechanism
As a general rule, any application using the GSS-API should not attempt to specify a particular mechanism, but instead use the default mechanism provided by the GSS-API implementation. The default mechanism is specified by setting the gss_OID representing the mechanism to the value GSS_C_NULL_OID.
Because setting a non-default mechanism is not recommended, this part of the program does not cover it here. Interested readers can see how the client application parses the user-input mechanism name by looking at the code in "parse_oid()" and by looking at Appendix C, Specifying an OID, which explains how to using non-default OIDs.
Calling the Server
After the mechanism has been put in the form of a gss_OID, you can do the actual work, so main() now calls the function call_server() with much the same arguments as on the command line.
call_server(hostname, port, g_mechOid, service_name, deleg_flag, msg, use_file);
(use_file is a flag indicating whether the message to be sent is contained in a file or not.)