LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hx509 - keyset.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 149 290 51.4 %
Date: 2024-01-11 09:59:51 Functions: 16 25 64.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "hx_locl.h"
      37             : 
      38             : /**
      39             :  * @page page_keyset Certificate store operations
      40             :  *
      41             :  * Type of certificates store:
      42             :  * - MEMORY
      43             :  *   In memory based format. Doesn't support storing.
      44             :  * - FILE
      45             :  *   FILE supports raw DER certicates and PEM certicates. When PEM is
      46             :  *   used the file can contain may certificates and match private
      47             :  *   keys. Support storing the certificates. DER format only supports
      48             :  *   on certificate and no private key.
      49             :  * - PEM-FILE
      50             :  *   Same as FILE, defaulting to PEM encoded certificates.
      51             :  * - PEM-FILE
      52             :  *   Same as FILE, defaulting to DER encoded certificates.
      53             :  * - PKCS11
      54             :  * - PKCS12
      55             :  * - DIR
      56             :  * - KEYCHAIN
      57             :  *   Apple Mac OS X KeyChain backed keychain object.
      58             :  *
      59             :  * See the library functions here: @ref hx509_keyset
      60             :  */
      61             : 
      62             : struct hx509_certs_data {
      63             :     unsigned int ref;
      64             :     struct hx509_keyset_ops *ops;
      65             :     void *ops_data;
      66             :     int flags;
      67             : };
      68             : 
      69             : struct hx509_keyset_ops *
      70     5533035 : _hx509_ks_type(hx509_context context, const char *type)
      71             : {
      72      136608 :     int i;
      73             : 
      74    22128416 :     for (i = 0; i < context->ks_num_ops; i++)
      75    16597387 :         if (strcasecmp(type, context->ks_ops[i]->name) == 0)
      76        2006 :             return context->ks_ops[i];
      77             : 
      78     5394501 :     return NULL;
      79             : }
      80             : 
      81             : HX509_LIB_FUNCTION void HX509_LIB_CALL
      82     5531029 : _hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops)
      83             : {
      84      136528 :     struct hx509_keyset_ops **val;
      85             : 
      86     5531029 :     if (_hx509_ks_type(context, ops->name))
      87           0 :         return;
      88             : 
      89     5531029 :     val = realloc(context->ks_ops,
      90     5531029 :                   (context->ks_num_ops + 1) * sizeof(context->ks_ops[0]));
      91     5531029 :     if (val == NULL)
      92           0 :         return;
      93     5531029 :     val[context->ks_num_ops] = ops;
      94     5531029 :     context->ks_ops = val;
      95     5531029 :     context->ks_num_ops++;
      96             : }
      97             : 
      98             : /**
      99             :  * Open or creates a new hx509 certificate store.
     100             :  *
     101             :  * @param context A hx509 context
     102             :  * @param name name of the store, format is TYPE:type-specific-string,
     103             :  * if NULL is used the MEMORY store is used.
     104             :  * @param flags list of flags:
     105             :  * - HX509_CERTS_CREATE create a new keystore of the specific TYPE.
     106             :  * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted.
     107             :  * - HX509_CERTS_NO_PRIVATE_KEYS does not load or permit adding private keys
     108             :  * @param lock a lock that unlocks the certificates store, use NULL to
     109             :  * select no password/certifictes/prompt lock (see @ref page_lock).
     110             :  * @param certs return pointer, free with hx509_certs_free().
     111             :  *
     112             :  * @return Returns an hx509 error code.
     113             :  *
     114             :  * @ingroup hx509_keyset
     115             :  */
     116             : 
     117             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     118        2006 : hx509_certs_init(hx509_context context,
     119             :                  const char *name, int flags,
     120             :                  hx509_lock lock, hx509_certs *certs)
     121             : {
     122          80 :     struct hx509_keyset_ops *ops;
     123          80 :     const char *residue;
     124          80 :     hx509_certs c;
     125          80 :     char *type;
     126          80 :     int ret;
     127             : 
     128        2006 :     *certs = NULL;
     129             : 
     130        2006 :     if (name == NULL)
     131           3 :         name = "";
     132             : 
     133        2006 :     residue = strchr(name, ':');
     134        2006 :     if (residue) {
     135        2003 :         type = malloc(residue - name + 1);
     136        2003 :         if (type)
     137        2003 :             strlcpy(type, name, residue - name + 1);
     138        2003 :         residue++;
     139        2003 :         if (residue[0] == '\0')
     140           0 :             residue = NULL;
     141             :     } else {
     142           3 :         type = strdup("MEMORY");
     143           3 :         residue = name;
     144             :     }
     145        2006 :     if (type == NULL) {
     146           0 :         hx509_clear_error_string(context);
     147           0 :         return ENOMEM;
     148             :     }
     149             : 
     150        2006 :     ops = _hx509_ks_type(context, type);
     151        2006 :     if (ops == NULL) {
     152           0 :         hx509_set_error_string(context, 0, ENOENT,
     153             :                                "Keyset type %s is not supported", type);
     154           0 :         free(type);
     155           0 :         return ENOENT;
     156             :     }
     157        2006 :     free(type);
     158        2006 :     c = calloc(1, sizeof(*c));
     159        2006 :     if (c == NULL) {
     160           0 :         hx509_clear_error_string(context);
     161           0 :         return ENOMEM;
     162             :     }
     163        2006 :     c->flags = flags;
     164        2006 :     c->ops = ops;
     165        2006 :     c->ref = 1;
     166             : 
     167        2006 :     ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
     168        2006 :     if (ret) {
     169          39 :         free(c);
     170          39 :         return ret;
     171             :     }
     172             : 
     173        1967 :     *certs = c;
     174        1967 :     return 0;
     175             : }
     176             : 
     177             : /**
     178             :  * Destroys and frees a hx509 certificate store.
     179             :  *
     180             :  * @param context A hx509 context
     181             :  * @param certs A store to destroy
     182             :  *
     183             :  * @return Returns an hx509 error code.
     184             :  *
     185             :  * @ingroup hx509_keyset
     186             :  */
     187             : 
     188             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     189           0 : hx509_certs_destroy(hx509_context context,
     190             :                     hx509_certs *certs)
     191             : {
     192           0 :     int ret = 0;
     193             : 
     194           0 :     if (*certs) {
     195           0 :         if ((*certs)->ops->destroy)
     196           0 :             ret = ((*certs)->ops->destroy)(context, *certs, (*certs)->ops_data);
     197             :         else
     198           0 :             ret = ENOTSUP;
     199             :     }
     200           0 :     hx509_certs_free(certs);
     201           0 :     return ret;
     202             : }
     203             : 
     204             : /**
     205             :  * Write the certificate store to stable storage.
     206             :  *
     207             :  * Use the HX509_CERTS_STORE_NO_PRIVATE_KEYS flag to ensure that no private
     208             :  * keys are stored, even if added.
     209             :  *
     210             :  * @param context A hx509 context.
     211             :  * @param certs a certificate store to store.
     212             :  * @param flags currently one flag is defined: HX509_CERTS_STORE_NO_PRIVATE_KEYS
     213             :  * @param lock a lock that unlocks the certificates store, use NULL to
     214             :  * select no password/certifictes/prompt lock (see @ref page_lock).
     215             :  *
     216             :  * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if
     217             :  * the certificate store doesn't support the store operation.
     218             :  *
     219             :  * @ingroup hx509_keyset
     220             :  */
     221             : 
     222             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     223           0 : hx509_certs_store(hx509_context context,
     224             :                   hx509_certs certs,
     225             :                   int flags,
     226             :                   hx509_lock lock)
     227             : {
     228           0 :     if (certs->ops->store == NULL) {
     229           0 :         hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
     230             :                                "keystore if type %s doesn't support "
     231             :                                "store operation",
     232           0 :                                certs->ops->name);
     233           0 :         return HX509_UNSUPPORTED_OPERATION;
     234             :     }
     235             : 
     236           0 :     return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock);
     237             : }
     238             : 
     239             : 
     240             : HX509_LIB_FUNCTION hx509_certs HX509_LIB_CALL
     241         325 : hx509_certs_ref(hx509_certs certs)
     242             : {
     243         325 :     if (certs == NULL)
     244           0 :         return NULL;
     245         325 :     if (certs->ref == 0)
     246           0 :         _hx509_abort("certs refcount == 0 on ref");
     247         325 :     if (certs->ref == UINT_MAX)
     248           0 :         _hx509_abort("certs refcount == UINT_MAX on ref");
     249         325 :     certs->ref++;
     250         325 :     return certs;
     251             : }
     252             : 
     253             : /**
     254             :  * Free a certificate store.
     255             :  *
     256             :  * @param certs certificate store to free.
     257             :  *
     258             :  * @ingroup hx509_keyset
     259             :  */
     260             : 
     261             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     262      754026 : hx509_certs_free(hx509_certs *certs)
     263             : {
     264      754026 :     if (*certs) {
     265        1968 :         if ((*certs)->ref == 0)
     266           0 :             _hx509_abort("cert refcount == 0 on free");
     267        1968 :         if (--(*certs)->ref > 0)
     268         271 :             return;
     269             : 
     270        1697 :         (*(*certs)->ops->free)(*certs, (*certs)->ops_data);
     271        1697 :         free(*certs);
     272        1697 :         *certs = NULL;
     273             :     }
     274             : }
     275             : 
     276             : /**
     277             :  * Start the integration
     278             :  *
     279             :  * @param context a hx509 context.
     280             :  * @param certs certificate store to iterate over
     281             :  * @param cursor cursor that will keep track of progress, free with
     282             :  * hx509_certs_end_seq().
     283             :  *
     284             :  * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is
     285             :  * returned if the certificate store doesn't support the iteration
     286             :  * operation.
     287             :  *
     288             :  * @ingroup hx509_keyset
     289             :  */
     290             : 
     291             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     292        1899 : hx509_certs_start_seq(hx509_context context,
     293             :                       hx509_certs certs,
     294             :                       hx509_cursor *cursor)
     295             : {
     296          40 :     int ret;
     297             : 
     298        1899 :     if (certs->ops->iter_start == NULL) {
     299           0 :         hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
     300             :                                "Keyset type %s doesn't support iteration",
     301           0 :                                certs->ops->name);
     302           0 :         return HX509_UNSUPPORTED_OPERATION;
     303             :     }
     304             : 
     305        1899 :     ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor);
     306        1899 :     if (ret)
     307           0 :         return ret;
     308             : 
     309        1859 :     return 0;
     310             : }
     311             : 
     312             : /**
     313             :  * Get next ceritificate from the certificate keystore pointed out by
     314             :  * cursor.
     315             :  *
     316             :  * @param context a hx509 context.
     317             :  * @param certs certificate store to iterate over.
     318             :  * @param cursor cursor that keeps track of progress.
     319             :  * @param cert return certificate next in store, NULL if the store
     320             :  * contains no more certificates. Free with hx509_cert_free().
     321             :  *
     322             :  * @return Returns an hx509 error code.
     323             :  *
     324             :  * @ingroup hx509_keyset
     325             :  */
     326             : 
     327             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     328        2946 : hx509_certs_next_cert(hx509_context context,
     329             :                       hx509_certs certs,
     330             :                       hx509_cursor cursor,
     331             :                       hx509_cert *cert)
     332             : {
     333        2946 :     *cert = NULL;
     334        2946 :     return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert);
     335             : }
     336             : 
     337             : /**
     338             :  * End the iteration over certificates.
     339             :  *
     340             :  * @param context a hx509 context.
     341             :  * @param certs certificate store to iterate over.
     342             :  * @param cursor cursor that will keep track of progress, freed.
     343             :  *
     344             :  * @return Returns an hx509 error code.
     345             :  *
     346             :  * @ingroup hx509_keyset
     347             :  */
     348             : 
     349             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     350        1899 : hx509_certs_end_seq(hx509_context context,
     351             :                     hx509_certs certs,
     352             :                     hx509_cursor cursor)
     353             : {
     354        1899 :     (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor);
     355        1899 :     return 0;
     356             : }
     357             : 
     358             : /**
     359             :  * Iterate over all certificates in a keystore and call a function
     360             :  * for each of them.
     361             :  *
     362             :  * @param context a hx509 context.
     363             :  * @param certs certificate store to iterate over.
     364             :  * @param func function to call for each certificate. The function
     365             :  * should return non-zero to abort the iteration, that value is passed
     366             :  * back to the caller of hx509_certs_iter_f().
     367             :  * @param ctx context variable that will passed to the function.
     368             :  *
     369             :  * @return Returns an hx509 error code.
     370             :  *
     371             :  * @ingroup hx509_keyset
     372             :  */
     373             : 
     374             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     375         783 : hx509_certs_iter_f(hx509_context context,
     376             :                    hx509_certs certs,
     377             :                    int (HX509_LIB_CALL *func)(hx509_context, void *, hx509_cert),
     378             :                    void *ctx)
     379             : {
     380          16 :     hx509_cursor cursor;
     381          16 :     hx509_cert c;
     382          16 :     int ret;
     383             : 
     384         783 :     ret = hx509_certs_start_seq(context, certs, &cursor);
     385         783 :     if (ret)
     386           0 :         return ret;
     387             : 
     388          32 :     while (1) {
     389        1389 :         ret = hx509_certs_next_cert(context, certs, cursor, &c);
     390        1389 :         if (ret)
     391           0 :             break;
     392        1389 :         if (c == NULL) {
     393         767 :             ret = 0;
     394         767 :             break;
     395             :         }
     396         606 :         ret = (*func)(context, ctx, c);
     397         606 :         hx509_cert_free(c);
     398         606 :         if (ret)
     399           0 :             break;
     400             :     }
     401             : 
     402         783 :     hx509_certs_end_seq(context, certs, cursor);
     403             : 
     404         783 :     return ret;
     405             : }
     406             : 
     407             : #ifdef __BLOCKS__
     408             : 
     409             : static int
     410             : certs_iter(hx509_context context, void *ctx, hx509_cert cert)
     411             : {
     412             :     int (^func)(hx509_cert) = ctx;
     413             :     return func(cert);
     414             : }
     415             : 
     416             : /**
     417             :  * Iterate over all certificates in a keystore and call a block
     418             :  * for each of them.
     419             :  *
     420             :  * @param context a hx509 context.
     421             :  * @param certs certificate store to iterate over.
     422             :  * @param func block to call for each certificate. The function
     423             :  * should return non-zero to abort the iteration, that value is passed
     424             :  * back to the caller of hx509_certs_iter().
     425             :  *
     426             :  * @return Returns an hx509 error code.
     427             :  *
     428             :  * @ingroup hx509_keyset
     429             :  */
     430             : 
     431             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     432             : hx509_certs_iter(hx509_context context,
     433             :                  hx509_certs certs,
     434             :                  int (^func)(hx509_cert))
     435             : {
     436             :     return hx509_certs_iter_f(context, certs, certs_iter, func);
     437             : }
     438             : #endif
     439             : 
     440             : 
     441             : /**
     442             :  * Function to use to hx509_certs_iter_f() as a function argument, the
     443             :  * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor.
     444             :  *
     445             :  * @param context a hx509 context.
     446             :  * @param ctx used by hx509_certs_iter_f().
     447             :  * @param c a certificate
     448             :  *
     449             :  * @return Returns an hx509 error code.
     450             :  *
     451             :  * @ingroup hx509_keyset
     452             :  */
     453             : 
     454             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     455           0 : hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c)
     456             : {
     457           0 :     Certificate *cert;
     458           0 :     hx509_name n;
     459           0 :     char *s, *i;
     460             : 
     461           0 :     cert = _hx509_get_cert(c);
     462             : 
     463           0 :     _hx509_name_from_Name(&cert->tbsCertificate.subject, &n);
     464           0 :     hx509_name_to_string(n, &s);
     465           0 :     hx509_name_free(&n);
     466           0 :     _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n);
     467           0 :     hx509_name_to_string(n, &i);
     468           0 :     hx509_name_free(&n);
     469           0 :     fprintf(ctx, "subject: %s\nissuer: %s\n", s, i);
     470           0 :     free(s);
     471           0 :     free(i);
     472           0 :     return 0;
     473             : }
     474             : 
     475             : /**
     476             :  * Add a certificate to the certificiate store.
     477             :  *
     478             :  * The receiving keyset certs will either increase reference counter
     479             :  * of the cert or make a deep copy, either way, the caller needs to
     480             :  * free the cert itself.
     481             :  *
     482             :  * @param context a hx509 context.
     483             :  * @param certs certificate store to add the certificate to.
     484             :  * @param cert certificate to add.
     485             :  *
     486             :  * @return Returns an hx509 error code.
     487             :  *
     488             :  * @ingroup hx509_keyset
     489             :  */
     490             : 
     491             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     492        1090 : hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)
     493             : {
     494        1090 :     hx509_cert copy = NULL;
     495          32 :     int ret;
     496             : 
     497        1090 :     if (certs->ops->add == NULL) {
     498           0 :         hx509_set_error_string(context, 0, ENOENT,
     499             :                                "Keyset type %s doesn't support add operation",
     500           0 :                                certs->ops->name);
     501           0 :         return ENOENT;
     502             :     }
     503             : 
     504        1090 :     if ((certs->flags & HX509_CERTS_NO_PRIVATE_KEYS) &&
     505           0 :         hx509_cert_have_private_key(cert)) {
     506           0 :         if ((copy = hx509_cert_copy_no_private_key(context, cert,
     507             :                                                    NULL)) == NULL) {
     508           0 :             hx509_set_error_string(context, 0, ENOMEM,
     509             :                                    "Could not add certificate to store");
     510           0 :             return ENOMEM;
     511             :         }
     512           0 :         cert = copy;
     513             :     }
     514             : 
     515        1090 :     ret = (*certs->ops->add)(context, certs, certs->ops_data, cert);
     516        1090 :     hx509_cert_free(copy);
     517        1090 :     return ret;
     518             : }
     519             : 
     520             : /**
     521             :  * Find a certificate matching the query.
     522             :  *
     523             :  * @param context a hx509 context.
     524             :  * @param certs certificate store to search.
     525             :  * @param q query allocated with @ref hx509_query functions.
     526             :  * @param r return certificate (or NULL on error), should be freed
     527             :  * with hx509_cert_free().
     528             :  *
     529             :  * @return Returns an hx509 error code.
     530             :  *
     531             :  * @ingroup hx509_keyset
     532             :  */
     533             : 
     534             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     535         587 : hx509_certs_find(hx509_context context,
     536             :                  hx509_certs certs,
     537             :                  const hx509_query *q,
     538             :                  hx509_cert *r)
     539             : {
     540           8 :     hx509_cursor cursor;
     541           8 :     hx509_cert c;
     542           8 :     int ret;
     543             : 
     544         587 :     *r = NULL;
     545             : 
     546         587 :     _hx509_query_statistic(context, 0, q);
     547             : 
     548         587 :     if (certs->ops->query)
     549           0 :         return (*certs->ops->query)(context, certs, certs->ops_data, q, r);
     550             : 
     551         587 :     ret = hx509_certs_start_seq(context, certs, &cursor);
     552         587 :     if (ret)
     553           0 :         return ret;
     554             : 
     555         587 :     c = NULL;
     556           8 :     while (1) {
     557         782 :         ret = hx509_certs_next_cert(context, certs, cursor, &c);
     558         782 :         if (ret)
     559           0 :             break;
     560         782 :         if (c == NULL)
     561         262 :             break;
     562         520 :         if (_hx509_query_match_cert(context, q, c)) {
     563         325 :             *r = c;
     564         325 :             c = NULL;
     565         325 :             break;
     566             :         }
     567         195 :         hx509_cert_free(c);
     568         195 :         c = NULL;
     569             :     }
     570             : 
     571         587 :     hx509_cert_free(c);
     572         587 :     hx509_certs_end_seq(context, certs, cursor);
     573         587 :     if (ret)
     574           0 :         return ret;
     575             :     /**
     576             :      * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
     577             :      * the query.
     578             :      */
     579         587 :     if (*r == NULL) {
     580         262 :         hx509_clear_error_string(context);
     581         262 :         return HX509_CERT_NOT_FOUND;
     582             :     }
     583             : 
     584         317 :     return 0;
     585             : }
     586             : 
     587             : /**
     588             :  * Filter certificate matching the query.
     589             :  *
     590             :  * @param context a hx509 context.
     591             :  * @param certs certificate store to search.
     592             :  * @param q query allocated with @ref hx509_query functions.
     593             :  * @param result the filtered certificate store, caller must free with
     594             :  *        hx509_certs_free().
     595             :  *
     596             :  * @return Returns an hx509 error code.
     597             :  *
     598             :  * @ingroup hx509_keyset
     599             :  */
     600             : 
     601             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     602           0 : hx509_certs_filter(hx509_context context,
     603             :                    hx509_certs certs,
     604             :                    const hx509_query *q,
     605             :                    hx509_certs *result)
     606             : {
     607           0 :     hx509_cursor cursor;
     608           0 :     hx509_cert c;
     609           0 :     int ret, found = 0;
     610             : 
     611           0 :     _hx509_query_statistic(context, 0, q);
     612             : 
     613           0 :     ret = hx509_certs_init(context, "MEMORY:filter-certs", 0,
     614             :                            NULL, result);
     615           0 :     if (ret)
     616           0 :         return ret;
     617             : 
     618           0 :     ret = hx509_certs_start_seq(context, certs, &cursor);
     619           0 :     if (ret) {
     620           0 :         hx509_certs_free(result);
     621           0 :         return ret;
     622             :     }
     623             : 
     624           0 :     c = NULL;
     625           0 :     while (1) {
     626           0 :         ret = hx509_certs_next_cert(context, certs, cursor, &c);
     627           0 :         if (ret)
     628           0 :             break;
     629           0 :         if (c == NULL)
     630           0 :             break;
     631           0 :         if (_hx509_query_match_cert(context, q, c)) {
     632           0 :             hx509_certs_add(context, *result, c);
     633           0 :             found = 1;
     634             :         }
     635           0 :         hx509_cert_free(c);
     636             :     }
     637             : 
     638           0 :     hx509_certs_end_seq(context, certs, cursor);
     639           0 :     if (ret) {
     640           0 :         hx509_certs_free(result);
     641           0 :         return ret;
     642             :     }
     643             : 
     644             :     /**
     645             :      * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
     646             :      * the query.
     647             :      */
     648           0 :     if (!found) {
     649           0 :         hx509_certs_free(result);
     650           0 :         hx509_clear_error_string(context);
     651           0 :         return HX509_CERT_NOT_FOUND;
     652             :     }
     653             : 
     654           0 :     return 0;
     655             : }
     656             : 
     657             : 
     658             : static int HX509_LIB_CALL
     659         363 : certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
     660             : {
     661         363 :     return hx509_certs_add(context, (hx509_certs)ctx, c);
     662             : }
     663             : 
     664             : /**
     665             :  * Merge one certificate store into another. The from store is kept intact.
     666             :  *
     667             :  * @param context a hx509 context.
     668             :  * @param to the store to merge into.
     669             :  * @param from the store to copy the object from.
     670             :  *
     671             :  * @return Returns an hx509 error code.
     672             :  *
     673             :  * @ingroup hx509_keyset
     674             :  */
     675             : 
     676             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     677         433 : hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from)
     678             : {
     679         433 :     if (from == NULL)
     680           0 :         return 0;
     681         433 :     return hx509_certs_iter_f(context, from, certs_merge_func, to);
     682             : }
     683             : 
     684             : /**
     685             :  * Same a hx509_certs_merge() but use a lock and name to describe the
     686             :  * from source.
     687             :  *
     688             :  * @param context a hx509 context.
     689             :  * @param to the store to merge into.
     690             :  * @param lock a lock that unlocks the certificates store, use NULL to
     691             :  * select no password/certifictes/prompt lock (see @ref page_lock).
     692             :  * @param name name of the source store
     693             :  *
     694             :  * @return Returns an hx509 error code.
     695             :  *
     696             :  * @ingroup hx509_keyset
     697             :  */
     698             : 
     699             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     700           0 : hx509_certs_append(hx509_context context,
     701             :                    hx509_certs to,
     702             :                    hx509_lock lock,
     703             :                    const char *name)
     704             : {
     705           0 :     hx509_certs s;
     706           0 :     int ret;
     707             : 
     708           0 :     ret = hx509_certs_init(context, name, 0, lock, &s);
     709           0 :     if (ret)
     710           0 :         return ret;
     711           0 :     ret = hx509_certs_merge(context, to, s);
     712           0 :     hx509_certs_free(&s);
     713           0 :     return ret;
     714             : }
     715             : 
     716             : /**
     717             :  * Get one random certificate from the certificate store.
     718             :  *
     719             :  * @param context a hx509 context.
     720             :  * @param certs a certificate store to get the certificate from.
     721             :  * @param c return certificate, should be freed with hx509_cert_free().
     722             :  *
     723             :  * @return Returns an hx509 error code.
     724             :  *
     725             :  * @ingroup hx509_keyset
     726             :  */
     727             : 
     728             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     729          68 : hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c)
     730             : {
     731           0 :     hx509_cursor cursor;
     732           0 :     int ret;
     733             : 
     734          68 :     *c = NULL;
     735             : 
     736          68 :     ret = hx509_certs_start_seq(context, certs, &cursor);
     737          68 :     if (ret)
     738           0 :         return ret;
     739             : 
     740          68 :     ret = hx509_certs_next_cert(context, certs, cursor, c);
     741          68 :     if (ret)
     742           0 :         return ret;
     743             : 
     744          68 :     hx509_certs_end_seq(context, certs, cursor);
     745          68 :     return 0;
     746             : }
     747             : 
     748             : static int
     749           0 : certs_info_stdio(void *ctx, const char *str)
     750             : {
     751           0 :     FILE *f = ctx;
     752           0 :     fprintf(f, "%s\n", str);
     753           0 :     return 0;
     754             : }
     755             : 
     756             : /**
     757             :  * Print some info about the certificate store.
     758             :  *
     759             :  * @param context a hx509 context.
     760             :  * @param certs certificate store to print information about.
     761             :  * @param func function that will get each line of the information, if
     762             :  * NULL is used the data is printed on a FILE descriptor that should
     763             :  * be passed in ctx, if ctx also is NULL, stdout is used.
     764             :  * @param ctx parameter to func.
     765             :  *
     766             :  * @return Returns an hx509 error code.
     767             :  *
     768             :  * @ingroup hx509_keyset
     769             :  */
     770             : 
     771             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     772           0 : hx509_certs_info(hx509_context context,
     773             :                  hx509_certs certs,
     774             :                  int (*func)(void *, const char *),
     775             :                  void *ctx)
     776             : {
     777           0 :     if (func == NULL) {
     778           0 :         func = certs_info_stdio;
     779           0 :         if (ctx == NULL)
     780           0 :             ctx = stdout;
     781             :     }
     782           0 :     if (certs->ops->printinfo == NULL) {
     783           0 :         (*func)(ctx, "No info function for certs");
     784           0 :         return 0;
     785             :     }
     786           0 :     return (*certs->ops->printinfo)(context, certs, certs->ops_data,
     787             :                                     func, ctx);
     788             : }
     789             : 
     790             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     791           0 : _hx509_pi_printf(int (*func)(void *, const char *), void *ctx,
     792             :                  const char *fmt, ...)
     793             : {
     794           0 :     va_list ap;
     795           0 :     char *str;
     796           0 :     int ret;
     797             : 
     798           0 :     va_start(ap, fmt);
     799           0 :     ret = vasprintf(&str, fmt, ap);
     800           0 :     va_end(ap);
     801           0 :     if (ret == -1 || str == NULL)
     802           0 :         return;
     803           0 :     (*func)(ctx, str);
     804           0 :     free(str);
     805             : }
     806             : 
     807             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     808           0 : _hx509_certs_keys_get(hx509_context context,
     809             :                       hx509_certs certs,
     810             :                       hx509_private_key **keys)
     811             : {
     812           0 :     if (certs->ops->getkeys == NULL) {
     813           0 :         *keys = NULL;
     814           0 :         return 0;
     815             :     }
     816           0 :     return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys);
     817             : }
     818             : 
     819             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     820          74 : _hx509_certs_keys_add(hx509_context context,
     821             :                       hx509_certs certs,
     822             :                       hx509_private_key key)
     823             : {
     824          74 :     if (certs->ops->addkey == NULL) {
     825           0 :         hx509_set_error_string(context, 0, EINVAL,
     826             :                                "keystore if type %s doesn't support "
     827             :                                "key add operation",
     828           0 :                                certs->ops->name);
     829           0 :         return EINVAL;
     830             :     }
     831          74 :     return (*certs->ops->addkey)(context, certs, certs->ops_data, key);
     832             : }
     833             : 
     834             : 
     835             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     836         249 : _hx509_certs_keys_free(hx509_context context,
     837             :                        hx509_private_key *keys)
     838             : {
     839          16 :     size_t i;
     840             : 
     841         249 :     if (keys == NULL)
     842           0 :         return;
     843         323 :     for (i = 0; keys[i]; i++)
     844          74 :         hx509_private_key_free(&keys[i]);
     845         249 :     free(keys);
     846             : }

Generated by: LCOV version 1.14