diff options
| -rw-r--r-- | doc/Makefile.am | 2 | ||||
| -rw-r--r-- | doc/p11-kit-docs.sgml | 1 | ||||
| -rw-r--r-- | doc/p11-kit-sections.txt | 19 | ||||
| -rw-r--r-- | p11-kit/pin.c | 328 | ||||
| -rw-r--r-- | p11-kit/pin.h | 4 | ||||
| -rw-r--r-- | tests/pin-test.c | 18 | 
6 files changed, 295 insertions, 77 deletions
| diff --git a/doc/Makefile.am b/doc/Makefile.am index 904de7b..40d9279 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -42,7 +42,7 @@ CFILE_GLOB=$(top_srcdir)/p11-kit/*.c  # Header files to ignore when scanning.  # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h -IGNORE_HFILES= p11-kit-private.h pkcs11.h conf.h debug.h hash.h util.h +IGNORE_HFILES= p11-kit-private.h pkcs11.h conf.h debug.h hash.h util.h ptr-array.h  # Images to copy into HTML directory.  # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png diff --git a/doc/p11-kit-docs.sgml b/doc/p11-kit-docs.sgml index f0b95bf..1bfb571 100644 --- a/doc/p11-kit-docs.sgml +++ b/doc/p11-kit-docs.sgml @@ -18,6 +18,7 @@  		<title>Reference</title>  		<xi:include href="xml/p11-kit.xml"/>  		<xi:include href="xml/p11-kit-uri.xml"/> +		<xi:include href="xml/p11-kit-pin.xml"/>  		<xi:include href="xml/p11-kit-util.xml"/>  		<xi:include href="xml/p11-kit-future.xml"/>  	</chapter> diff --git a/doc/p11-kit-sections.txt b/doc/p11-kit-sections.txt index 36b9de2..ab672c4 100644 --- a/doc/p11-kit-sections.txt +++ b/doc/p11-kit-sections.txt @@ -28,6 +28,25 @@ p11_kit_uri_message  </SECTION>  <SECTION> +<FILE>p11-kit-pin</FILE> +P11KitPin +p11_kit_pin_new +p11_kit_pin_new_for_buffer +p11_kit_pin_new_for_string +p11_kit_pin_get_value +p11_kit_pin_ref +p11_kit_pin_unref +P11KitPinFlags +P11_KIT_PIN_FALLBACK +p11_kit_pin_register_callback +p11_kit_pin_unregister_callback +p11_kit_pin_callback +p11_kit_pin_request +p11_kit_pin_destroy_func +p11_kit_pin_file_callback +</SECTION> + +<SECTION>  <FILE>p11-kit</FILE>  p11_kit_initialize_registered  p11_kit_finalize_registered diff --git a/p11-kit/pin.c b/p11-kit/pin.c index 879b6b7..5ede97a 100644 --- a/p11-kit/pin.c +++ b/p11-kit/pin.c @@ -52,88 +52,85 @@  #include <unistd.h>  /** - * SECTION:p11-pin + * SECTION:p11-kit-pin   * @title: PIN Callbacks   * @short_description: PIN Callbacks   * - * Applications can register a callback which will be called to provide a password - * associated with a given pin file. - * PKCS\#11 URIs can be used in configuration files or applications to represent - * PKCS\#11 modules, tokens or objects. An example of a URI might be: + * Applications can register a callback which will be called to provide a + * password associated with a given pin file. + * + * PKCS\#11 URIs can contain a 'pinfile' attribute. The value of this attribute + * is application dependent, but often references a file containing a PIN to + * use. + * + * Using these functions, an applications or libraries can register a + * callback with p11_kit_pin_register_callback() to be called when a given + * 'pinfile' attribute value is requested. The application can then prompt + * the user or retrieve a PIN for the given context. These registered + * callbacks are only relevant and valid within the current process. + * + * A fallback callback can be registered by passing the %P11_KIT_PIN_FALLBACK + * value to p11_kit_pin_register_callback(). This fallback callback will be + * called for every 'pinfile' attribute request for which no callback has been + * directly registered. + * + * To request a PIN for a given 'pinfile' attribute, use the + * p11_kit_pin_request() function. If this function returns %NULL then either + * no callbacks were registered or none of them could handle the request. + * + * If multiple callbacks are registered for the same pinfile, then they are + * called in last-registered-first-called order. They are called in turn until + * one of them can handle the request. Fallback callbacks are not called if + * a callback was registered specifically for a requested 'pinfile' attribute. + * + * PINs themselves are handled inside of P11KitPin structures. These are thread + * safe and allow the callback to specify how the PIN is stored in memory + * and freed. A callback can use p11_kit_pin_new_for_string() or related + * functions to create a PIN to be returned. + * + * For example in order to handle the following PKCS\#11 URI with a 'pinfile' + * attribute   *   * <code><literallayout> - *      pkcs11:token=The\%20Software\%20PKCS\#11\%20softtoken; - *          manufacturer=Snake\%20Oil,\%20Inc.;serial=;object=my-certificate; - *          model=1.0;objecttype=cert;id=\%69\%95\%3e\%5c\%f4\%bd\%ec\%91 + *      pkcs11:id=\%69\%95\%3e\%5c\%f4\%bd\%ec\%91;pinfile=my-application   * </literallayout></code>   * - * You can use p11_kit_uri_parse() to parse such a URI, and p11_kit_uri_format() - * to build one. URIs are represented by the #P11KitUri structure. You can match - * a parsed URI against PKCS\#11 tokens with p11_kit_uri_match_token_info() - * or attributes with p11_kit_uri_match_attributes(). + * an application could register a callback like this:   * - * Since URIs can represent different sorts of things, when parsing or formatting - * a URI a 'context' can be used to indicate which sort of URI is expected. + * <informalexample><programlisting> + * static P11KitPin* + * my_application_pin_callback (const char *pinfile, P11KitUri *pin_uri, + *                              const char *pin_description, P11KitPinFlags pin_flags, + *                              void *callback_data) + * { + *     return p11_kit_pin_new_from_string ("pin-value"); + * }   * - * URIs have an <code>unrecognized</code> flag. This flag is set during parsing - * if any parts of the URI are not recognized. This may be because the part is - * from a newer version of the PKCS\#11 spec or because that part was not valid - * inside of the desired context used when parsing. + * p11_kit_pin_register_callback ("my-application", my_application_pin_callback, + *                                NULL, NULL); + * </programlisting></informalexample>   */  /** - * P11KitUri: + * P11KitPinFlags: + * @P11_KIT_PIN_FLAGS_USER_LOGIN: The PIN is for a PKCS\#11 user type login. + * @P11_KIT_PIN_FLAGS_SO_LOGIN: The PIN is for a PKCS\#11 security officer type login. + * @P11_KIT_PIN_FLAGS_CONTEXT_LOGIN: The PIN is for a PKCS\#11 contect specific type login. + * @P11_KIT_PIN_FLAGS_RETRY: The PIN is being requested again, due to an invalid previous PIN. + * @P11_KIT_PIN_FLAGS_MANY_TRIES: The PIN has failed too many times, and few tries are left. + * @P11_KIT_PIN_FLAGS_FINAL_TRY: The PIN has failed too many times, and this is the last try.   * - * A structure representing a PKCS\#11 URI. There are no public fields - * visible in this structure. Use the various accessor functions. - */ - -/** - * P11KitUriType: - * @P11_KIT_URI_FOR_OBJECT: The URI represents one or more objects - * @P11_KIT_URI_FOR_TOKEN: The URI represents one or more tokens - * @P11_KIT_URI_FOR_MODULE: The URI represents one or more modules - * @P11_KIT_URI_FOR_MODULE_WITH_VERSION: The URI represents a module with - *     a specific version. - * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN: The URI represents one or more objects - *     that are present on a specific token. - * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE: The URI represents one or more - *     objects that are present on a specific token, being used with a certain - *     module. - * @P11_KIT_URI_FOR_ANY: The URI can represent anything - * - * A PKCS\#11 URI can represent different kinds of things. This flag is used by - * p11_kit_uri_parse() to denote in what context the URI will be used. - * - * The various types can be combined. + * Flags that are passed to p11_kit_pin_request() and registered callbacks.   */  /** - * P11KitUriResult: - * @P11_KIT_URI_OK: Success - * @P11_KIT_URI_NO_MEMORY: Memory allocation failed - * @P11_KIT_URI_BAD_SCHEME: The URI had a bad scheme - * @P11_KIT_URI_BAD_ENCODING: The URI had a bad encoding - * @P11_KIT_URI_BAD_SYNTAX: The URI had a bad syntax - * @P11_KIT_URI_BAD_VERSION: The URI contained a bad version number - * @P11_KIT_URI_NOT_FOUND: A requested part of the URI was not found - * - * Error codes returned by various functions. The functions each clearly state - * which error codes they are capable of returning. - */ - -/** - * P11_KIT_URI_SCHEME: + * P11_KIT_PIN_FALLBACK:   * + * Used with p11_kit_pin_register_callback() to register a fallback callback. + * This callback will be called if no other   * String of URI scheme for PKCS\#11 URIs.   */ -/** - * P11_KIT_URI_SCHEME_LEN: - * - * Length of %P11_KIT_URI_SCHEME. - */ -  typedef struct _PinfileCallback {  	/* Only used/modified within the lock */  	int refs; @@ -174,6 +171,25 @@ unref_pinfile_callback (void *pointer)  	}  } +/** + * p11_kit_pin_register_callback: + * @pinfile: the 'pinfile' attribute this this callback is for + * @callback: the callback function + * @callback_data: data that will be passed to the callback + * @callback_destroy: a function that will be called with @callback_data when + *     the callback is unregistered. + * + * Register a callback to handle PIN requests for a given 'pinfile' attribute. + * If @pinfile is set to P11_KIT_PIN_FALLBACK then this will be a fallback + * callback and will be called for requests for which no other callback has + * been specifically registered. + * + * If multiple callbacks are registered for the same @pinfile value, then + * the last registered callback will be the first to be called. + * + * Returns: Returns negative if registering fails. This can only happen if + *     memory cannot be allocated. + */  int  p11_kit_pin_register_callback (const char *pinfile, p11_kit_pin_callback callback,                                 void *callback_data, p11_kit_pin_destroy_func callback_destroy) @@ -251,6 +267,17 @@ p11_kit_pin_register_callback (const char *pinfile, p11_kit_pin_callback callbac  	return ret;  } +/** + * p11_kit_pin_unregister_callback: + * @pinfile: the 'pinfile' attribute the callback was registered for + * @callback: the callback function that was registered + * @callback_data: data that was registered for the callback + * + * Unregister a callback that was previously registered with the + * p11_kit_pin_register_callback() function. If more than one registered + * callback matches the given arguments, then only one of those will be + * removed. + */  void  p11_kit_pin_unregister_callback (const char *pinfile, p11_kit_pin_callback callback,                                   void *callback_data) @@ -286,9 +313,40 @@ p11_kit_pin_unregister_callback (const char *pinfile, p11_kit_pin_callback callb  	_p11_unlock ();  } +/** + * p11_kit_pin_request: + * @pinfile: the 'pinfile' attribute that is being requested + * @pin_uri: a PKCS\#11 URI that the PIN is being requested for, optionally %NULL. + * @pin_description: a description of what the PIN is for, must not be %NULL. + * @pin_flags: various flags for this request + * + * Request a PIN for a given 'pinfile' attribute. The result depends on the + * registered callbacks. + * + * If not %NULL, then the @pin_uri attribute should point to the thing that the + * PIN is being requested for. In most use cases this should be a PKCS\#11 URI + * pointing to a token. + * + * The @pin_description should always be specified. It is a string describing + * what the PIN is for. For example this would be the token label, if the PIN + * is for a token. + * + * If more than one callback is registered for the @pinfile, then the latest + * registered one will be called first. If that callback does not return a + * PIN, then the next will be called in turn. + * + * If no callback is registered for @pinfile, then the fallback callbacks will + * be invoked in the same way. The fallback callbacks will not be called if any + * callback has been registered specifically for @pinfile. + * + * The PIN returned should be released with p11_kit_pin_unref(). + * + * Returns: the PIN which should be released with p11_kit_pin_unref(), or %NULL + *     if no callback was registered or could proivde a PIN + */  P11KitPin* -p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri, -                      const char *pin_description, P11KitPinFlags flags) +p11_kit_pin_request (const char *pinfile, P11KitUri *pin_uri, +                     const char *pin_description, P11KitPinFlags pin_flags)  {  	PinfileCallback **snapshot = NULL;  	unsigned int snapshot_count = 0; @@ -320,7 +378,7 @@ p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri,  		return NULL;  	for (pin = NULL, i = snapshot_count; pin == NULL && i > 0; i--) { -		pin = (snapshot[i - 1]->func) (pinfile, pin_uri, pin_description, flags, +		pin = (snapshot[i - 1]->func) (pinfile, pin_uri, pin_description, pin_flags,  		                               snapshot[i - 1]->user_data);  	} @@ -333,6 +391,59 @@ p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri,  	return pin;  } +/** + * p11_kit_pin_callback: + * @pinfile: a 'pinfile' attribute string + * @pin_uri: a PKCS\#11 URI that the PIN is for, or %NULL + * @pin_description: a descrption of what the PIN is for + * @pin_flags: flags describing the PIN request + * @callback_data: data that was provided when registering this callback + * + * Represents a PIN callback function. + * + * The various arguments are the same as the ones passed to + * p11_kit_pin_request(). The @callback_data argument was the one passed to + * p11_kit_pin_register_callback() when registering this callback. + * + * The function should return %NULL if it could not provide a PIN, either + * because of an error or a user cancellation. + * + * If a PIN is returned, it will be unreferenced by the caller. So it should be + * either newly allocated, or referenced before returning. + * + * Returns: A PIN or %NULL + */ + +/** + * p11_kit_pin_destroy_func: + * @data: the data to destroy + * + * A function called to free or cleanup @data. + */ + +/** + * p11_kit_pin_file_callback: + * @pinfile: a 'pinfile' attribute string + * @pin_uri: a PKCS\#11 URI that the PIN is for, or %NULL + * @pin_description: a descrption of what the PIN is for + * @pin_flags: flags describing the PIN request + * @callback_data: unused, should be %NULL + * + * This is a PIN callback function that looks up the 'pinfile' attribute in + * a file with that name. This can be used to enable the normal PKCS\#11 URI + * behavior described in the RFC. + * + * This callback is not registered by default. To register it use code like + * the following: + * + * <informalexample><programlisting> + * p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback, + *                                NULL, NULL); + * </programlisting></informalexample> + * + * Returns: A referenced PIN with the pinfile contents, or %NULL if the file + *    could not be read. + */  P11KitPin*  p11_kit_pin_file_callback (const char *pinfile,                             P11KitUri *pin_uri, @@ -392,6 +503,12 @@ p11_kit_pin_file_callback (const char *pinfile,  	return p11_kit_pin_new_for_buffer (buffer, used, free);  } +/** + * P11KitPin: + * + * A structure representing a PKCS\#11 PIN. There are no public fields + * visible in this structure. Use the various accessor functions. + */  struct _P11KitPin {  	int ref_count;  	unsigned char *buffer; @@ -399,6 +516,20 @@ struct _P11KitPin {  	p11_kit_pin_destroy_func destroy;  }; +/** + * p11_kit_pin_new: + * @value: the value of the PIN + * @length: the length of @value + * + * Create a new P11KitPin with the given PIN value. The exactly @length bytes + * from @value are used. Null terminated strings, or encodings are not + * considered. + * + * A copy of the @value will be made. + * + * Returns: The newly allocated P11KitPin, which should be freed with + *     p11_kit_pin_unref() when no longer needed. + */  P11KitPin*  p11_kit_pin_new (const unsigned char *value, size_t length)  { @@ -416,12 +547,48 @@ p11_kit_pin_new (const unsigned char *value, size_t length)  	return pin;  } +/** + * p11_kit_pin_new_for_string: + * @value: the value of the PIN + * + * Create a new P11KitPin for the given null-terminated string, such as a + * password. The PIN will consist of the string not including the null terminator. + * String encoding is not considered. + * + * A copy of the @value will be made. + * + * Returns: The newly allocated P11KitPin, which should be freed with + *     p11_kit_pin_unref() when no longer needed. + */  P11KitPin*  p11_kit_pin_new_for_string (const char *value)  {  	return p11_kit_pin_new ((const unsigned char *)value, strlen (value));  } +/** + * p11_kit_pin_new_for_buffer: + * @buffer: the value of the PIN + * @length: the length of @buffer + * @destroy: if not %NULL, then called when PIN is destroyed. + * + * Create a new P11KitPin which will use @buffer for the PIN value. The buffer + * will not be copied. String encodings and null characters are not considered. + * + * When the last reference to this PIN is lost, then the @destroy callback + * function will be called passing @buffer as an argument. This allows the + * caller to use a buffer as a PIN without copying it. + * + * <informalexample><programlisting> + * char *buffer = malloc (128); + * P11KitPin *pin; + *  .... + * pin = p11_kit_pin_new_for_buffer (buffer, 128, free); + * </programlisting></informalexample> + * + * Returns: The newly allocated P11KitPin, which should be freed with + *     p11_kit_pin_unref() when no longer needed. + */  P11KitPin*  p11_kit_pin_new_for_buffer (unsigned char *buffer, size_t length,                              p11_kit_pin_destroy_func destroy) @@ -440,6 +607,20 @@ p11_kit_pin_new_for_buffer (unsigned char *buffer, size_t length,  	return pin;  } +/** + * p11_kit_pin_get_value: + * @pin: the P11KitPin + * @length: a location to return the value length + * + * Get the PIN value from a P11KitPin. @length will be set to the + * length of the value. + * + * The value returned is owned by the P11KitPin and should not be modified. + * It remains valid as long as a reference to the PIN is held. The PIN value + * will contain an extra null-terminator character. + * + * Returns: the value for the PIN. + */  const unsigned char*  p11_kit_pin_get_value (P11KitPin *pin, size_t *length)  { @@ -448,6 +629,16 @@ p11_kit_pin_get_value (P11KitPin *pin, size_t *length)  	return pin->buffer;  } +/** + * p11_kit_pin_ref: + * @pin: the P11KitPin + * + * Add a reference to a P11KitPin. This should be matched with a later call + * to p11_kit_pin_unref(). As long as at least one reference is held, the PIN + * will remain valid and in memory. + * + * Returns: the @pin pointer, for convenience sake. + */  P11KitPin*  p11_kit_pin_ref (P11KitPin *pin)  { @@ -460,6 +651,13 @@ p11_kit_pin_ref (P11KitPin *pin)  	return pin;  } +/** + * p11_kit_pin_unref: + * @pin: the P11KitPin + * + * Remove a reference from a P11KitPin. When all references have been removed + * then the PIN will be freed and will no longer be in memory. + */  void  p11_kit_pin_unref (P11KitPin *pin)  { diff --git a/p11-kit/pin.h b/p11-kit/pin.h index 532aa54..9d05331 100644 --- a/p11-kit/pin.h +++ b/p11-kit/pin.h @@ -54,7 +54,7 @@ typedef enum {  #define P11_KIT_PIN_FALLBACK "" -typedef void        (*p11_kit_pin_destroy_func)             (void *callback_data); +typedef void        (*p11_kit_pin_destroy_func)             (void *data);  P11KitPin*            p11_kit_pin_new                       (const unsigned char *value,                                                               size_t length); @@ -87,7 +87,7 @@ void                  p11_kit_pin_unregister_callback       (const char *pinfile                                                               p11_kit_pin_callback callback,                                                               void *callback_data); -P11KitPin*            p11_kit_pin_retrieve                  (const char *pinfile, +P11KitPin*            p11_kit_pin_request                   (const char *pinfile,                                                               P11KitUri *pin_uri,                                                               const char *pin_description,                                                               P11KitPinFlags pin_flags); diff --git a/tests/pin-test.c b/tests/pin-test.c index 086f892..6431857 100644 --- a/tests/pin-test.c +++ b/tests/pin-test.c @@ -94,7 +94,7 @@ test_pin_read (CuTest *tc)  	                               &data, destroy_data);  	uri = p11_kit_uri_new (); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	p11_kit_uri_free (uri); @@ -117,7 +117,7 @@ test_pin_read_no_match (CuTest *tc)  	P11KitPin *pin;  	uri = p11_kit_uri_new (); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	p11_kit_uri_free (uri); @@ -142,7 +142,7 @@ test_pin_register_duplicate (CuTest *tc)  	p11_kit_pin_register_callback ("/the/pinfile", callback_other,  	                               value, NULL); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrNotNull (tc, pin); @@ -154,7 +154,7 @@ test_pin_register_duplicate (CuTest *tc)  	p11_kit_pin_unregister_callback ("/the/pinfile", callback_other,  	                                 value); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrNotNull (tc, pin); @@ -166,7 +166,7 @@ test_pin_register_duplicate (CuTest *tc)  	p11_kit_pin_unregister_callback ("/the/pinfile", callback_one,  	                                 &data); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrEquals (tc, NULL, pin); @@ -189,7 +189,7 @@ test_pin_register_fallback (CuTest *tc)  	p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, callback_one,  	                               &data, destroy_data); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrNotNull (tc, pin); @@ -201,7 +201,7 @@ test_pin_register_fallback (CuTest *tc)  	p11_kit_pin_register_callback ("/the/pinfile", callback_other,  	                               value, NULL); -	pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", +	pin = p11_kit_pin_request ("/the/pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrNotNull (tc, pin); @@ -232,7 +232,7 @@ test_pin_file (CuTest *tc)  	p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback,  	                               NULL, NULL); -	pin = p11_kit_pin_retrieve (SRCDIR "/files/test-pinfile", uri, "The token", +	pin = p11_kit_pin_request (SRCDIR "/files/test-pinfile", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrNotNull (tc, pin); @@ -241,7 +241,7 @@ test_pin_file (CuTest *tc)  	CuAssertTrue (tc, memcmp (ptr, "yogabbagabba", length) == 0);  	p11_kit_pin_unref (pin); -	pin = p11_kit_pin_retrieve (SRCDIR "/files/nonexistant", uri, "The token", +	pin = p11_kit_pin_request (SRCDIR "/files/nonexistant", uri, "The token",  	                            P11_KIT_PIN_FLAGS_USER_LOGIN);  	CuAssertPtrEquals (tc, NULL, pin); | 
