diff options
Diffstat (limited to 'lib/hx509/keyset.c')
| -rw-r--r-- | lib/hx509/keyset.c | 252 | 
1 files changed, 188 insertions, 64 deletions
diff --git a/lib/hx509/keyset.c b/lib/hx509/keyset.c index 2fcff7b03b35..c0275d949d06 100644 --- a/lib/hx509/keyset.c +++ b/lib/hx509/keyset.c @@ -1,38 +1,39 @@  /* - * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden).  - * All rights reserved.  - * - * Redistribution and use in source and binary forms, with or without  - * modification, are permitted provided that the following conditions  - * are met:  - * - * 1. Redistributions of source code must retain the above copyright  - *    notice, this list of conditions and the following disclaimer.  - * - * 2. Redistributions in binary form must reproduce the above copyright  - *    notice, this list of conditions and the following disclaimer in the  - *    documentation and/or other materials provided with the distribution.  - * - * 3. Neither the name of the Institute nor the names of its contributors  - *    may be used to endorse or promote products derived from this software  - *    without specific prior written permission.  - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  - * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  - * SUCH DAMAGE.  + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE.   */  #include "hx_locl.h" -RCSID("$Id: keyset.c 22466 2008-01-16 14:26:35Z lha $");  /**   * @page page_keyset Certificate store operations @@ -40,7 +41,7 @@ RCSID("$Id: keyset.c 22466 2008-01-16 14:26:35Z lha $");   * Type of certificates store:   * - MEMORY   *   In memory based format. Doesnt support storing. - * - FILE  + * - FILE   *   FILE supports raw DER certicates and PEM certicates. When PEM is   *   used the file can contain may certificates and match private   *   keys. Support storing the certificates. DER format only supports @@ -59,7 +60,7 @@ RCSID("$Id: keyset.c 22466 2008-01-16 14:26:35Z lha $");   */  struct hx509_certs_data { -    int ref; +    unsigned int ref;      struct hx509_keyset_ops *ops;      void *ops_data;  }; @@ -84,7 +85,7 @@ _hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops)      if (_hx509_ks_type(context, ops->name))  	return; -    val = realloc(context->ks_ops,  +    val = realloc(context->ks_ops,  		  (context->ks_num_ops + 1) * sizeof(context->ks_ops[0]));      if (val == NULL)  	return; @@ -138,10 +139,10 @@ hx509_certs_init(hx509_context context,  	hx509_clear_error_string(context);  	return ENOMEM;      } -     +      ops = _hx509_ks_type(context, type);      if (ops == NULL) { -	hx509_set_error_string(context, 0, ENOENT,  +	hx509_set_error_string(context, 0, ENOENT,  			       "Keyset type %s is not supported", type);  	free(type);  	return ENOENT; @@ -199,15 +200,15 @@ hx509_certs_store(hx509_context context,  hx509_certs -_hx509_certs_ref(hx509_certs certs) +hx509_certs_ref(hx509_certs certs)  {      if (certs == NULL)  	return NULL; -    if (certs->ref <= 0) -	_hx509_abort("certs refcount <= 0"); -    certs->ref++;      if (certs->ref == 0) -	_hx509_abort("certs refcount == 0"); +	_hx509_abort("certs refcount == 0 on ref"); +    if (certs->ref == UINT_MAX) +	_hx509_abort("certs refcount == UINT_MAX on ref"); +    certs->ref++;      return certs;  } @@ -223,8 +224,8 @@ void  hx509_certs_free(hx509_certs *certs)  {      if (*certs) { -	if ((*certs)->ref <= 0) -	    _hx509_abort("refcount <= 0"); +	if ((*certs)->ref == 0) +	    _hx509_abort("cert refcount == 0 on free");  	if (--(*certs)->ref > 0)  	    return; @@ -257,8 +258,8 @@ hx509_certs_start_seq(hx509_context context,      int ret;      if (certs->ops->iter_start == NULL) { -	hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,  -			       "Keyset type %s doesn't support iteration",  +	hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, +			       "Keyset type %s doesn't support iteration",  			       certs->ops->name);  	return HX509_UNSUPPORTED_OPERATION;      } @@ -324,7 +325,7 @@ hx509_certs_end_seq(hx509_context context,   * @param certs certificate store to iterate over.   * @param func function to call for each certificate. The function   * should return non-zero to abort the iteration, that value is passed - * back to te caller of hx509_certs_iter(). + * back to the caller of hx509_certs_iter_f().   * @param ctx context variable that will passed to the function.   *   * @return Returns an hx509 error code. @@ -333,10 +334,10 @@ hx509_certs_end_seq(hx509_context context,   */  int -hx509_certs_iter(hx509_context context,  -		 hx509_certs certs,  -		 int (*func)(hx509_context, void *, hx509_cert), -		 void *ctx) +hx509_certs_iter_f(hx509_context context, +		   hx509_certs certs, +		   int (*func)(hx509_context, void *, hx509_cert), +		   void *ctx)  {      hx509_cursor cursor;      hx509_cert c; @@ -345,7 +346,7 @@ hx509_certs_iter(hx509_context context,      ret = hx509_certs_start_seq(context, certs, &cursor);      if (ret)  	return ret; -     +      while (1) {  	ret = hx509_certs_next_cert(context, certs, cursor, &c);  	if (ret) @@ -365,13 +366,61 @@ hx509_certs_iter(hx509_context context,      return ret;  } +/** + * Iterate over all certificates in a keystore and call an function + * for each fo them. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param func function to call for each certificate. The function + * should return non-zero to abort the iteration, that value is passed + * back to the caller of hx509_certs_iter(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +#ifdef __BLOCKS__ + +static int +certs_iter(hx509_context context, void *ctx, hx509_cert cert) +{ +    int (^func)(hx509_cert) = ctx; +    return func(cert); +} + +/** + * Iterate over all certificates in a keystore and call an block + * for each fo them. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param func block to call for each certificate. The function + * should return non-zero to abort the iteration, that value is passed + * back to the caller of hx509_certs_iter(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +int +hx509_certs_iter(hx509_context context, +		 hx509_certs certs, +		 int (^func)(hx509_cert)) +{ +    return hx509_certs_iter_f(context, certs, certs_iter, func); +} +#endif +  /** - * Function to use to hx509_certs_iter() as a function argument, the - * ctx variable to hx509_certs_iter() should be a FILE file descriptor. + * Function to use to hx509_certs_iter_f() as a function argument, the + * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor.   *   * @param context a hx509 context. - * @param ctx used by hx509_certs_iter(). + * @param ctx used by hx509_certs_iter_f().   * @param c a certificate   *   * @return Returns an hx509 error code. @@ -420,8 +469,8 @@ int  hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)  {      if (certs->ops->add == NULL) { -	hx509_set_error_string(context, 0, ENOENT,  -			       "Keyset type %s doesn't support add operation",  +	hx509_set_error_string(context, 0, ENOENT, +			       "Keyset type %s doesn't support add operation",  			       certs->ops->name);  	return ENOENT;      } @@ -445,7 +494,7 @@ hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)  int  hx509_certs_find(hx509_context context, -		 hx509_certs certs,  +		 hx509_certs certs,  		 const hx509_query *q,  		 hx509_cert *r)  { @@ -481,6 +530,10 @@ hx509_certs_find(hx509_context context,      hx509_certs_end_seq(context, certs, cursor);      if (ret)  	return ret; +    /** +     * Return HX509_CERT_NOT_FOUND if no certificate in certs matched +     * the query. +     */      if (c == NULL) {  	hx509_clear_error_string(context);  	return HX509_CERT_NOT_FOUND; @@ -489,6 +542,77 @@ hx509_certs_find(hx509_context context,      return 0;  } +/** + * Filter certificate matching the query. + * + * @param context a hx509 context. + * @param certs certificate store to search. + * @param q query allocated with @ref hx509_query functions. + * @param result the filtered certificate store, caller must free with + *        hx509_certs_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +int +hx509_certs_filter(hx509_context context, +		   hx509_certs certs, +		   const hx509_query *q, +		   hx509_certs *result) +{ +    hx509_cursor cursor; +    hx509_cert c; +    int ret, found = 0; + +    _hx509_query_statistic(context, 0, q); + +    ret = hx509_certs_init(context, "MEMORY:filter-certs", 0, +			   NULL, result); +    if (ret) +	return ret; + +    ret = hx509_certs_start_seq(context, certs, &cursor); +    if (ret) { +	hx509_certs_free(result); +	return ret; +    } + +    c = NULL; +    while (1) { +	ret = hx509_certs_next_cert(context, certs, cursor, &c); +	if (ret) +	    break; +	if (c == NULL) +	    break; +	if (_hx509_query_match_cert(context, q, c)) { +	    hx509_certs_add(context, *result, c); +	    found = 1; +	} +	hx509_cert_free(c); +    } + +    hx509_certs_end_seq(context, certs, cursor); +    if (ret) { +	hx509_certs_free(result); +	return ret; +    } + +    /** +     * Return HX509_CERT_NOT_FOUND if no certificate in certs matched +     * the query. +     */ +    if (!found) { +	hx509_certs_free(result); +	hx509_clear_error_string(context); +	return HX509_CERT_NOT_FOUND; +    } + +    return 0; +} + +  static int  certs_merge_func(hx509_context context, void *ctx, hx509_cert c)  { @@ -513,7 +637,7 @@ hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from)  {      if (from == NULL)  	return 0; -    return hx509_certs_iter(context, from, certs_merge_func, to); +    return hx509_certs_iter_f(context, from, certs_merge_func, to);  }  /** @@ -604,7 +728,7 @@ certs_info_stdio(void *ctx, const char *str)   */  int -hx509_certs_info(hx509_context context,  +hx509_certs_info(hx509_context context,  		 hx509_certs certs,  		 int (*func)(void *, const char *),  		 void *ctx) @@ -639,8 +763,8 @@ _hx509_pi_printf(int (*func)(void *, const char *), void *ctx,  }  int -_hx509_certs_keys_get(hx509_context context,  -		      hx509_certs certs,  +_hx509_certs_keys_get(hx509_context context, +		      hx509_certs certs,  		      hx509_private_key **keys)  {      if (certs->ops->getkeys == NULL) { @@ -651,8 +775,8 @@ _hx509_certs_keys_get(hx509_context context,  }  int -_hx509_certs_keys_add(hx509_context context,  -		      hx509_certs certs,  +_hx509_certs_keys_add(hx509_context context, +		      hx509_certs certs,  		      hx509_private_key key)  {      if (certs->ops->addkey == NULL) { @@ -672,6 +796,6 @@ _hx509_certs_keys_free(hx509_context context,  {      int i;      for (i = 0; keys[i]; i++) -	_hx509_private_key_free(&keys[i]); +	hx509_private_key_free(&keys[i]);      free(keys);  }  | 
