241
Chapter 10. Advanced Programming Topics
We have explained quite a bit about using the OpenSSL library. Often, tasks such as certificate management are most easily accomplished with the command-line tool. For other tasks, such as
SSL communications, we must flex our knowledge of the API. By this point it should be clear, though we have not explicitly stated it, that the command-line utilities all use various parts of the
OpenSSL API, some of which we have not yet discussed in any detail.
In this chapter, we tackle some of the more advanced topics of programming with OpenSSL, including the programmatic interfaces to some features weve discussed only when using the
command-line tool. In addition, well cover the interface for reading program variables at runtime. Using the details in this chapter, we will investigate how OpenSSL provides for a variety of other
tasks, such as creating SMIME secure email, importing certificates into common web browsers, and hooking into certificates to access public key components for more primitive cryptographic
functions.
10.1 Object Stacks
OpenSSL has a large number of macros for dealing with stacks of typed objects. The API can perform only a small number of operations on a stack; however, there are a large number of
macros to ensure type safety for objects on the stacks. For instance, if we had a stack of
X509
objects and a generic push method for adding an object to the stack, nothing would prevent us from accidentally pushing a non-
X509
object onto the stack. To alleviate this problem, OpenSSL provides type-specific macros on top of the generic operations. When manipulating stacks, the
type-specific macros should always be used instead of the generic routines. Since the actual operations for a single type have the same behavior as the operations for any type, we will look at
them generically. See Example 10-1
.
Example 10-1. Stack manipulation functions in generic form
STACK_OFTYPE sk_TYPE_new_nullvoid; void sk_TYPE_freeSTACK_OFTYPE st;
void sk_TYPE_pop_freeSTACK_OFTYPE st, void free_funcTYPE ; void sk_TYPE_zeroSTACK_OFTYPE st;
STACK_OFTYPE sk_TYPE_dupSTACK_OFTYPE st; int sk_TYPE_pushSTACK_OFTYPE st, TYPE val;
TYPE sk_TYPE_popSTACK_OFTYPE st; int sk_TYPE_unshiftSTACK_OFTYPE st, TYPE val;
TYPE sk_TYPE_shiftSTACK_OFTYPE st; int sk_TYPE_numSTACK_OFTYPE st;
TYPE sk_TYPE_valueSTACK_OFTYPE st, int i; TYPE sk_TYPE_setSTACK_OFTYPE st, int i, TYPE val;
TYPE sk_TYPE_deleteSTACK_OFTYPE st, int i; TYPE sk_TYPE_delete_ptrSTACK_OFTYPE st, TYPE ptr;
int sk_TYPE_insertSTACK_OFTYPE st, TYPE val, int i;
Example 10-1 shows the prototypes for some of the generic stack functions in OpenSSL. The type
of a stack is implemented through the macro
STACK_OF
. Stacks are opaque types; an application should not check or set members directly. By replacing the
TYPE
placeholder used by the sample declarations in
Example 10-1 with a specific object type, we get a good look at the prototypes of
the actual stack manipulation calls for that type.
242
The functions shown in Example 10-1
, like many members of the OpenSSL API, are implemented via macros. Thus, it should be obvious
that function pointer manipulation is not possible. In general, applications should use the API directly since the underlying implementation is subject
to change in future versions.
The operations on the stack should be self-explanatory; well cover them briefly. The
sk_TYPE_new_null
function simply creates an empty stack, while the
sk_TYPE_free
function frees a stack; the latter frees only the stack, not the objects contained in the stack. To free a stack and all its members, the
sk_TYPE_pop_free
function should be used; we must pass in a function pointer to the free method for this to work correctly. The last of the general manipulation
functions are
sk_TYPE_zero
to empty a stack and
sk_TYPE_dup
to copy a stack object. There are also the general functions
sk_TYPE_push
and
sk_TYPE_pop
that we would expect in a stack implementation. Two that are less likely are
sk_TYPE_unshift
and
sk_TYPE_shift
; the former pushes an element to the bottom of the stack, and the latter pops the bottom item off the
stack. The functions that add elements
sk_TYPE_push
and
sk_TYPE_unshift
return the total number of elements in the stack, and the other two functions return the item that was
removed from the stack. The last group of macros is a set of nontypical functions for a stack implementation; they add
functionality that is more commonly found in lists. The first,
sk_TYPE_num
, returns the total number of items in the stack. To retrieve an item by index number if the bottom item is zero
without changing the stack, we should use
sk_TYPE_value
. In order to set an item in the stack explicitly, the function
sk_TYPE_set
will replace the
i
th item with the item passed to the call. The delete functions delete a single item from the stack. The item to delete can be selected by
index or pointer value; the stack is shifted to fill the space left by the removed item. Finally,
sk_TYPE_insert
adds the indicated item to the
i
th position in the stack and moves all the items above it, including the
i
th item before the call, up one position. As well see when we move into further topics of this chapter, proper stack handling is critical for
setting up some data structures. While well probably put only a subset of this simple interface to use, we now have the tools to do more complex tasks.
10.2 Configuration Files