Object Stacks Advanced Programming Topics

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