keyset.c revision 256281
190075Sobrien/* 290075Sobrien * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan 3169689Skan * (Royal Institute of Technology, Stockholm, Sweden). 490075Sobrien * All rights reserved. 590075Sobrien * 690075Sobrien * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 790075Sobrien * 890075Sobrien * Redistribution and use in source and binary forms, with or without 990075Sobrien * modification, are permitted provided that the following conditions 1090075Sobrien * are met: 1190075Sobrien * 1290075Sobrien * 1. Redistributions of source code must retain the above copyright 1390075Sobrien * notice, this list of conditions and the following disclaimer. 1490075Sobrien * 1590075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1690075Sobrien * notice, this list of conditions and the following disclaimer in the 1790075Sobrien * documentation and/or other materials provided with the distribution. 1890075Sobrien * 19169689Skan * 3. Neither the name of the Institute nor the names of its contributors 20169689Skan * may be used to endorse or promote products derived from this software 2190075Sobrien * without specific prior written permission. 2290075Sobrien * 2390075Sobrien * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2490075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2590075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2690075Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2790075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2890075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2990075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3090075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3290075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3390075Sobrien * SUCH DAMAGE. 3490075Sobrien */ 35132718Skan 36132718Skan#include "hx_locl.h" 3790075Sobrien 3890075Sobrien/** 3990075Sobrien * @page page_keyset Certificate store operations 4090075Sobrien * 4190075Sobrien * Type of certificates store: 4290075Sobrien * - MEMORY 4390075Sobrien * In memory based format. Doesnt support storing. 4490075Sobrien * - FILE 4590075Sobrien * FILE supports raw DER certicates and PEM certicates. When PEM is 4690075Sobrien * used the file can contain may certificates and match private 4790075Sobrien * keys. Support storing the certificates. DER format only supports 4890075Sobrien * on certificate and no private key. 49132718Skan * - PEM-FILE 50132718Skan * Same as FILE, defaulting to PEM encoded certificates. 51169689Skan * - PEM-FILE 52169689Skan * Same as FILE, defaulting to DER encoded certificates. 53132718Skan * - PKCS11 54132718Skan * - PKCS12 5590075Sobrien * - DIR 5690075Sobrien * - KEYCHAIN 5790075Sobrien * Apple Mac OS X KeyChain backed keychain object. 5890075Sobrien * 59132718Skan * See the library functions here: @ref hx509_keyset 60132718Skan */ 6190075Sobrien 6290075Sobrienstruct hx509_certs_data { 6390075Sobrien unsigned int ref; 6490075Sobrien struct hx509_keyset_ops *ops; 6590075Sobrien void *ops_data; 6690075Sobrien}; 67169689Skan 6890075Sobrienstatic struct hx509_keyset_ops * 6990075Sobrien_hx509_ks_type(hx509_context context, const char *type) 7090075Sobrien{ 7190075Sobrien int i; 7290075Sobrien 7390075Sobrien for (i = 0; i < context->ks_num_ops; i++) 7490075Sobrien if (strcasecmp(type, context->ks_ops[i]->name) == 0) 7590075Sobrien return context->ks_ops[i]; 7690075Sobrien 7790075Sobrien return NULL; 7890075Sobrien} 7990075Sobrien 8090075Sobrienvoid 8190075Sobrien_hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops) 8290075Sobrien{ 8390075Sobrien struct hx509_keyset_ops **val; 84169689Skan 8590075Sobrien if (_hx509_ks_type(context, ops->name)) 8690075Sobrien return; 8790075Sobrien 8890075Sobrien val = realloc(context->ks_ops, 8990075Sobrien (context->ks_num_ops + 1) * sizeof(context->ks_ops[0])); 9090075Sobrien if (val == NULL) 91110611Skan return; 92132718Skan val[context->ks_num_ops] = ops; 9390075Sobrien context->ks_ops = val; 9490075Sobrien context->ks_num_ops++; 9590075Sobrien} 9690075Sobrien 9790075Sobrien/** 98117395Skan * Open or creates a new hx509 certificate store. 99117395Skan * 100117395Skan * @param context A hx509 context 10190075Sobrien * @param name name of the store, format is TYPE:type-specific-string, 102117395Skan * if NULL is used the MEMORY store is used. 103117395Skan * @param flags list of flags: 104117395Skan * - HX509_CERTS_CREATE create a new keystore of the specific TYPE. 105117395Skan * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted. 10690075Sobrien * @param lock a lock that unlocks the certificates store, use NULL to 107117395Skan * select no password/certifictes/prompt lock (see @ref page_lock). 108169689Skan * @param certs return pointer, free with hx509_certs_free(). 109169689Skan * 110169689Skan * @ingroup hx509_keyset 111169689Skan */ 112169689Skan 113169689Skanint 114117395Skanhx509_certs_init(hx509_context context, 115117395Skan const char *name, int flags, 116117395Skan hx509_lock lock, hx509_certs *certs) 117117395Skan{ 118117395Skan struct hx509_keyset_ops *ops; 119117395Skan const char *residue; 120117395Skan hx509_certs c; 12190075Sobrien char *type; 122117395Skan int ret; 123169689Skan 124169689Skan *certs = NULL; 125169689Skan 126169689Skan residue = strchr(name, ':'); 127169689Skan if (residue) { 128117395Skan type = malloc(residue - name + 1); 12990075Sobrien if (type) 130117395Skan strlcpy(type, name, residue - name + 1); 131132718Skan residue++; 132169689Skan if (residue[0] == '\0') 133169689Skan residue = NULL; 134117395Skan } else { 13590075Sobrien type = strdup("MEMORY"); 136117395Skan residue = name; 137169689Skan } 13890075Sobrien if (type == NULL) { 13990075Sobrien hx509_clear_error_string(context); 14090075Sobrien return ENOMEM; 14190075Sobrien } 14290075Sobrien 14390075Sobrien ops = _hx509_ks_type(context, type); 144132718Skan if (ops == NULL) { 14590075Sobrien hx509_set_error_string(context, 0, ENOENT, 146169689Skan "Keyset type %s is not supported", type); 14790075Sobrien free(type); 14890075Sobrien return ENOENT; 14990075Sobrien } 15090075Sobrien free(type); 15190075Sobrien c = calloc(1, sizeof(*c)); 152132718Skan if (c == NULL) { 153169689Skan hx509_clear_error_string(context); 154169689Skan return ENOMEM; 15590075Sobrien } 15690075Sobrien c->ops = ops; 15790075Sobrien c->ref = 1; 15890075Sobrien 15990075Sobrien ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock); 16090075Sobrien if (ret) { 16190075Sobrien free(c); 16290075Sobrien return ret; 16390075Sobrien } 16490075Sobrien 16590075Sobrien *certs = c; 16690075Sobrien return 0; 16790075Sobrien} 16890075Sobrien 16990075Sobrien/** 17090075Sobrien * Write the certificate store to stable storage. 17190075Sobrien * 172169689Skan * @param context A hx509 context. 17390075Sobrien * @param certs a certificate store to store. 17490075Sobrien * @param flags currently unused, use 0. 175169689Skan * @param lock a lock that unlocks the certificates store, use NULL to 17690075Sobrien * select no password/certifictes/prompt lock (see @ref page_lock). 17790075Sobrien * 17890075Sobrien * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if 17990075Sobrien * the certificate store doesn't support the store operation. 18090075Sobrien * 18190075Sobrien * @ingroup hx509_keyset 18290075Sobrien */ 18390075Sobrien 18490075Sobrienint 18590075Sobrienhx509_certs_store(hx509_context context, 18690075Sobrien hx509_certs certs, 187169689Skan int flags, 18890075Sobrien hx509_lock lock) 189169689Skan{ 19090075Sobrien if (certs->ops->store == NULL) { 19190075Sobrien hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 19290075Sobrien "keystore if type %s doesn't support " 19390075Sobrien "store operation", 19490075Sobrien certs->ops->name); 19590075Sobrien return HX509_UNSUPPORTED_OPERATION; 19690075Sobrien } 19790075Sobrien 19890075Sobrien return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock); 19990075Sobrien} 20090075Sobrien 20190075Sobrien 20290075Sobrienhx509_certs 20390075Sobrienhx509_certs_ref(hx509_certs certs) 204169689Skan{ 205169689Skan if (certs == NULL) 20690075Sobrien return NULL; 207169689Skan if (certs->ref == 0) 20890075Sobrien _hx509_abort("certs refcount == 0 on ref"); 20990075Sobrien if (certs->ref == UINT_MAX) 21090075Sobrien _hx509_abort("certs refcount == UINT_MAX on ref"); 21190075Sobrien certs->ref++; 21290075Sobrien return certs; 21390075Sobrien} 21490075Sobrien 21590075Sobrien/** 21690075Sobrien * Free a certificate store. 21790075Sobrien * 21890075Sobrien * @param certs certificate store to free. 219169689Skan * 220169689Skan * @ingroup hx509_keyset 221169689Skan */ 222169689Skan 223169689Skanvoid 224169689Skanhx509_certs_free(hx509_certs *certs) 22590075Sobrien{ 226169689Skan if (*certs) { 227169689Skan if ((*certs)->ref == 0) 228169689Skan _hx509_abort("cert refcount == 0 on free"); 229169689Skan if (--(*certs)->ref > 0) 23090075Sobrien return; 231169689Skan 232169689Skan (*(*certs)->ops->free)(*certs, (*certs)->ops_data); 233169689Skan free(*certs); 234169689Skan *certs = NULL; 235169689Skan } 23690075Sobrien} 237169689Skan 238169689Skan/** 239169689Skan * Start the integration 240169689Skan * 241169689Skan * @param context a hx509 context. 242169689Skan * @param certs certificate store to iterate over 243169689Skan * @param cursor cursor that will keep track of progress, free with 244169689Skan * hx509_certs_end_seq(). 245169689Skan * 246169689Skan * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is 247169689Skan * returned if the certificate store doesn't support the iteration 248169689Skan * operation. 249169689Skan * 250169689Skan * @ingroup hx509_keyset 25190075Sobrien */ 252169689Skan 25390075Sobrienint 254117395Skanhx509_certs_start_seq(hx509_context context, 255169689Skan hx509_certs certs, 25690075Sobrien hx509_cursor *cursor) 25790075Sobrien{ 25890075Sobrien int ret; 25990075Sobrien 260169689Skan if (certs->ops->iter_start == NULL) { 261169689Skan hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 26290075Sobrien "Keyset type %s doesn't support iteration", 263117395Skan certs->ops->name); 264117395Skan return HX509_UNSUPPORTED_OPERATION; 265117395Skan } 266169689Skan 26790075Sobrien ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor); 268117395Skan if (ret) 26990075Sobrien return ret; 27090075Sobrien 27190075Sobrien return 0; 272169689Skan} 273169689Skan 27490075Sobrien/** 275169689Skan * Get next ceritificate from the certificate keystore pointed out by 276169689Skan * cursor. 277169689Skan * 278169689Skan * @param context a hx509 context. 279169689Skan * @param certs certificate store to iterate over. 280169689Skan * @param cursor cursor that keeps track of progress. 281169689Skan * @param cert return certificate next in store, NULL if the store 282169689Skan * contains no more certificates. Free with hx509_cert_free(). 283169689Skan * 284169689Skan * @return Returns an hx509 error code. 285169689Skan * 286169689Skan * @ingroup hx509_keyset 287169689Skan */ 288169689Skan 289169689Skanint 290169689Skanhx509_certs_next_cert(hx509_context context, 291132718Skan hx509_certs certs, 29290075Sobrien hx509_cursor cursor, 29390075Sobrien hx509_cert *cert) 29490075Sobrien{ 29590075Sobrien *cert = NULL; 29690075Sobrien return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert); 297132718Skan} 29890075Sobrien 29990075Sobrien/** 30090075Sobrien * End the iteration over certificates. 30190075Sobrien * 30290075Sobrien * @param context a hx509 context. 30390075Sobrien * @param certs certificate store to iterate over. 30490075Sobrien * @param cursor cursor that will keep track of progress, freed. 30590075Sobrien * 30690075Sobrien * @return Returns an hx509 error code. 307169689Skan * 30890075Sobrien * @ingroup hx509_keyset 30990075Sobrien */ 31090075Sobrien 31190075Sobrienint 31290075Sobrienhx509_certs_end_seq(hx509_context context, 31390075Sobrien hx509_certs certs, 314132718Skan hx509_cursor cursor) 315132718Skan{ 31690075Sobrien (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor); 31790075Sobrien return 0; 31890075Sobrien} 31990075Sobrien 32090075Sobrien/** 32190075Sobrien * Iterate over all certificates in a keystore and call an function 32290075Sobrien * for each fo them. 32390075Sobrien * 32490075Sobrien * @param context a hx509 context. 32590075Sobrien * @param certs certificate store to iterate over. 32690075Sobrien * @param func function to call for each certificate. The function 32790075Sobrien * should return non-zero to abort the iteration, that value is passed 32890075Sobrien * back to the caller of hx509_certs_iter_f(). 32990075Sobrien * @param ctx context variable that will passed to the function. 33090075Sobrien * 33190075Sobrien * @return Returns an hx509 error code. 33290075Sobrien * 33390075Sobrien * @ingroup hx509_keyset 33490075Sobrien */ 33590075Sobrien 33690075Sobrienint 33790075Sobrienhx509_certs_iter_f(hx509_context context, 33890075Sobrien hx509_certs certs, 33990075Sobrien int (*func)(hx509_context, void *, hx509_cert), 34090075Sobrien void *ctx) 341169689Skan{ 34290075Sobrien hx509_cursor cursor; 34390075Sobrien hx509_cert c; 34490075Sobrien int ret; 34590075Sobrien 34690075Sobrien ret = hx509_certs_start_seq(context, certs, &cursor); 34790075Sobrien if (ret) 34890075Sobrien return ret; 34990075Sobrien 35090075Sobrien while (1) { 35190075Sobrien ret = hx509_certs_next_cert(context, certs, cursor, &c); 35290075Sobrien if (ret) 35390075Sobrien break; 35490075Sobrien if (c == NULL) { 355169689Skan ret = 0; 35690075Sobrien break; 35790075Sobrien } 35890075Sobrien ret = (*func)(context, ctx, c); 35990075Sobrien hx509_cert_free(c); 36090075Sobrien if (ret) 36190075Sobrien break; 36290075Sobrien } 36390075Sobrien 36490075Sobrien hx509_certs_end_seq(context, certs, cursor); 36590075Sobrien 366132718Skan return ret; 36790075Sobrien} 36890075Sobrien 36990075Sobrien/** 37090075Sobrien * Iterate over all certificates in a keystore and call an function 37190075Sobrien * for each fo them. 37290075Sobrien * 37390075Sobrien * @param context a hx509 context. 37490075Sobrien * @param certs certificate store to iterate over. 375169689Skan * @param func function to call for each certificate. The function 37690075Sobrien * should return non-zero to abort the iteration, that value is passed 37790075Sobrien * back to the caller of hx509_certs_iter(). 37890075Sobrien * 37990075Sobrien * @return Returns an hx509 error code. 38090075Sobrien * 38190075Sobrien * @ingroup hx509_keyset 38290075Sobrien */ 38390075Sobrien 38490075Sobrien#ifdef __BLOCKS__ 38590075Sobrien 38690075Sobrienstatic int 38790075Sobriencerts_iter(hx509_context context, void *ctx, hx509_cert cert) 38890075Sobrien{ 38990075Sobrien int (^func)(hx509_cert) = ctx; 39090075Sobrien return func(cert); 39190075Sobrien} 39290075Sobrien 39390075Sobrien/** 39490075Sobrien * Iterate over all certificates in a keystore and call an block 39590075Sobrien * for each fo them. 39690075Sobrien * 39790075Sobrien * @param context a hx509 context. 398132718Skan * @param certs certificate store to iterate over. 399169689Skan * @param func block to call for each certificate. The function 400169689Skan * should return non-zero to abort the iteration, that value is passed 401169689Skan * back to the caller of hx509_certs_iter(). 402169689Skan * 403132718Skan * @return Returns an hx509 error code. 404169689Skan * 405132718Skan * @ingroup hx509_keyset 406132718Skan */ 407132718Skan 408169689Skanint 40990075Sobrienhx509_certs_iter(hx509_context context, 410117395Skan hx509_certs certs, 41190075Sobrien int (^func)(hx509_cert)) 412169689Skan{ 413117395Skan return hx509_certs_iter_f(context, certs, certs_iter, func); 41490075Sobrien} 41590075Sobrien#endif 41690075Sobrien 41790075Sobrien 41890075Sobrien/** 41990075Sobrien * Function to use to hx509_certs_iter_f() as a function argument, the 42090075Sobrien * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor. 42190075Sobrien * 42290075Sobrien * @param context a hx509 context. 42390075Sobrien * @param ctx used by hx509_certs_iter_f(). 42490075Sobrien * @param c a certificate 42590075Sobrien * 42690075Sobrien * @return Returns an hx509 error code. 427132718Skan * 42890075Sobrien * @ingroup hx509_keyset 42990075Sobrien */ 43090075Sobrien 43190075Sobrienint 43290075Sobrienhx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c) 433117395Skan{ 43490075Sobrien Certificate *cert; 43590075Sobrien hx509_name n; 43690075Sobrien char *s, *i; 43790075Sobrien 43890075Sobrien cert = _hx509_get_cert(c); 43990075Sobrien 44090075Sobrien _hx509_name_from_Name(&cert->tbsCertificate.subject, &n); 44190075Sobrien hx509_name_to_string(n, &s); 44290075Sobrien hx509_name_free(&n); 44390075Sobrien _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n); 44490075Sobrien hx509_name_to_string(n, &i); 44590075Sobrien hx509_name_free(&n); 44690075Sobrien fprintf(ctx, "subject: %s\nissuer: %s\n", s, i); 447169689Skan free(s); 44890075Sobrien free(i); 44990075Sobrien return 0; 450117395Skan} 45190075Sobrien 45290075Sobrien/** 45390075Sobrien * Add a certificate to the certificiate store. 45490075Sobrien * 45590075Sobrien * The receiving keyset certs will either increase reference counter 45690075Sobrien * of the cert or make a deep copy, either way, the caller needs to 45790075Sobrien * free the cert itself. 45890075Sobrien * 45990075Sobrien * @param context a hx509 context. 46090075Sobrien * @param certs certificate store to add the certificate to. 46190075Sobrien * @param cert certificate to add. 46290075Sobrien * 46390075Sobrien * @return Returns an hx509 error code. 464117395Skan * 46590075Sobrien * @ingroup hx509_keyset 46690075Sobrien */ 46790075Sobrien 46890075Sobrienint 46990075Sobrienhx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert) 47090075Sobrien{ 47190075Sobrien if (certs->ops->add == NULL) { 47290075Sobrien hx509_set_error_string(context, 0, ENOENT, 47390075Sobrien "Keyset type %s doesn't support add operation", 47490075Sobrien certs->ops->name); 47590075Sobrien return ENOENT; 47690075Sobrien } 47790075Sobrien 47890075Sobrien return (*certs->ops->add)(context, certs, certs->ops_data, cert); 47990075Sobrien} 48090075Sobrien 48190075Sobrien/** 48290075Sobrien * Find a certificate matching the query. 48390075Sobrien * 48490075Sobrien * @param context a hx509 context. 48590075Sobrien * @param certs certificate store to search. 48690075Sobrien * @param q query allocated with @ref hx509_query functions. 48790075Sobrien * @param r return certificate (or NULL on error), should be freed 48890075Sobrien * with hx509_cert_free(). 48990075Sobrien * 49090075Sobrien * @return Returns an hx509 error code. 491169689Skan * 49290075Sobrien * @ingroup hx509_keyset 49390075Sobrien */ 49490075Sobrien 49590075Sobrienint 49690075Sobrienhx509_certs_find(hx509_context context, 497169689Skan hx509_certs certs, 49890075Sobrien const hx509_query *q, 49990075Sobrien hx509_cert *r) 50090075Sobrien{ 50190075Sobrien hx509_cursor cursor; 502117395Skan hx509_cert c; 50390075Sobrien int ret; 50490075Sobrien 50590075Sobrien *r = NULL; 506169689Skan 50790075Sobrien _hx509_query_statistic(context, 0, q); 508117395Skan 50990075Sobrien if (certs->ops->query) 51090075Sobrien return (*certs->ops->query)(context, certs, certs->ops_data, q, r); 51190075Sobrien 51290075Sobrien ret = hx509_certs_start_seq(context, certs, &cursor); 513169689Skan if (ret) 51490075Sobrien return ret; 51590075Sobrien 516169689Skan c = NULL; 51790075Sobrien while (1) { 518117395Skan ret = hx509_certs_next_cert(context, certs, cursor, &c); 519117395Skan if (ret) 52090075Sobrien break; 52190075Sobrien if (c == NULL) 52290075Sobrien break; 52390075Sobrien if (_hx509_query_match_cert(context, q, c)) { 52490075Sobrien *r = c; 52590075Sobrien break; 52690075Sobrien } 52790075Sobrien hx509_cert_free(c); 52890075Sobrien } 52990075Sobrien 530117395Skan hx509_certs_end_seq(context, certs, cursor); 531132718Skan if (ret) 53290075Sobrien return ret; 533169689Skan /** 53490075Sobrien * Return HX509_CERT_NOT_FOUND if no certificate in certs matched 53590075Sobrien * the query. 53690075Sobrien */ 537169689Skan if (c == NULL) { 538117395Skan hx509_clear_error_string(context); 539117395Skan return HX509_CERT_NOT_FOUND; 54090075Sobrien } 541169689Skan 54290075Sobrien return 0; 54390075Sobrien} 54490075Sobrien 54590075Sobrien/** 54690075Sobrien * Filter certificate matching the query. 54790075Sobrien * 54890075Sobrien * @param context a hx509 context. 54990075Sobrien * @param certs certificate store to search. 550169689Skan * @param q query allocated with @ref hx509_query functions. 551169689Skan * @param result the filtered certificate store, caller must free with 552169689Skan * hx509_certs_free(). 553169689Skan * 554169689Skan * @return Returns an hx509 error code. 555169689Skan * 55690075Sobrien * @ingroup hx509_keyset 55790075Sobrien */ 55890075Sobrien 559169689Skanint 560169689Skanhx509_certs_filter(hx509_context context, 561169689Skan hx509_certs certs, 562169689Skan const hx509_query *q, 563169689Skan hx509_certs *result) 564169689Skan{ 56590075Sobrien hx509_cursor cursor; 566169689Skan hx509_cert c; 56790075Sobrien int ret, found = 0; 56890075Sobrien 56990075Sobrien _hx509_query_statistic(context, 0, q); 57090075Sobrien 57190075Sobrien ret = hx509_certs_init(context, "MEMORY:filter-certs", 0, 57290075Sobrien NULL, result); 57390075Sobrien if (ret) 57490075Sobrien return ret; 57590075Sobrien 57690075Sobrien ret = hx509_certs_start_seq(context, certs, &cursor); 57790075Sobrien if (ret) { 578169689Skan hx509_certs_free(result); 579169689Skan return ret; 580169689Skan } 581169689Skan 58290075Sobrien c = NULL; 583169689Skan while (1) { 584169689Skan ret = hx509_certs_next_cert(context, certs, cursor, &c); 585169689Skan if (ret) 586169689Skan break; 587169689Skan if (c == NULL) 588169689Skan break; 589169689Skan if (_hx509_query_match_cert(context, q, c)) { 59090075Sobrien hx509_certs_add(context, *result, c); 591169689Skan found = 1; 592169689Skan } 593169689Skan hx509_cert_free(c); 594169689Skan } 595169689Skan 596169689Skan hx509_certs_end_seq(context, certs, cursor); 597169689Skan if (ret) { 598169689Skan hx509_certs_free(result); 599169689Skan return ret; 600169689Skan } 601169689Skan 602169689Skan /** 603169689Skan * Return HX509_CERT_NOT_FOUND if no certificate in certs matched 604169689Skan * the query. 605169689Skan */ 606169689Skan if (!found) { 607169689Skan hx509_certs_free(result); 608169689Skan hx509_clear_error_string(context); 609169689Skan return HX509_CERT_NOT_FOUND; 610169689Skan } 611169689Skan 612169689Skan return 0; 613169689Skan} 614169689Skan 615169689Skan 616169689Skanstatic int 617169689Skancerts_merge_func(hx509_context context, void *ctx, hx509_cert c) 618169689Skan{ 619169689Skan return hx509_certs_add(context, (hx509_certs)ctx, c); 620169689Skan} 621169689Skan 622169689Skan/** 623169689Skan * Merge a certificate store into another. The from store is keep 624169689Skan * intact. 625169689Skan * 626169689Skan * @param context a hx509 context. 627169689Skan * @param to the store to merge into. 628169689Skan * @param from the store to copy the object from. 629169689Skan * 630169689Skan * @return Returns an hx509 error code. 63190075Sobrien * 63290075Sobrien * @ingroup hx509_keyset 63390075Sobrien */ 63490075Sobrien 635132718Skanint 63690075Sobrienhx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) 637169689Skan{ 638132718Skan if (from == NULL) 639132718Skan return 0; 640169689Skan return hx509_certs_iter_f(context, from, certs_merge_func, to); 64190075Sobrien} 64290075Sobrien 64390075Sobrien/** 644132718Skan * Same a hx509_certs_merge() but use a lock and name to describe the 64590075Sobrien * from source. 64690075Sobrien * 647169689Skan * @param context a hx509 context. 64890075Sobrien * @param to the store to merge into. 64990075Sobrien * @param lock a lock that unlocks the certificates store, use NULL to 65090075Sobrien * select no password/certifictes/prompt lock (see @ref page_lock). 65190075Sobrien * @param name name of the source store 65290075Sobrien * 65390075Sobrien * @return Returns an hx509 error code. 65490075Sobrien * 65590075Sobrien * @ingroup hx509_keyset 65690075Sobrien */ 65790075Sobrien 65890075Sobrienint 65990075Sobrienhx509_certs_append(hx509_context context, 660132718Skan hx509_certs to, 66190075Sobrien hx509_lock lock, 66290075Sobrien const char *name) 66390075Sobrien{ 66490075Sobrien hx509_certs s; 665117395Skan int ret; 66690075Sobrien 66790075Sobrien ret = hx509_certs_init(context, name, 0, lock, &s); 66890075Sobrien if (ret) 66990075Sobrien return ret; 67090075Sobrien ret = hx509_certs_merge(context, to, s); 67190075Sobrien hx509_certs_free(&s); 67290075Sobrien return ret; 67390075Sobrien} 674132718Skan 67590075Sobrien/** 67690075Sobrien * Get one random certificate from the certificate store. 67790075Sobrien * 67890075Sobrien * @param context a hx509 context. 67990075Sobrien * @param certs a certificate store to get the certificate from. 68090075Sobrien * @param c return certificate, should be freed with hx509_cert_free(). 68190075Sobrien * 68290075Sobrien * @return Returns an hx509 error code. 68390075Sobrien * 68490075Sobrien * @ingroup hx509_keyset 68590075Sobrien */ 68690075Sobrien 68790075Sobrienint 68890075Sobrienhx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c) 68990075Sobrien{ 69090075Sobrien hx509_cursor cursor; 691132718Skan int ret; 69290075Sobrien 69390075Sobrien *c = NULL; 69490075Sobrien 69590075Sobrien ret = hx509_certs_start_seq(context, certs, &cursor); 69690075Sobrien if (ret) 697169689Skan return ret; 698169689Skan 699169689Skan ret = hx509_certs_next_cert(context, certs, cursor, c); 700169689Skan if (ret) 701169689Skan return ret; 70290075Sobrien 70390075Sobrien hx509_certs_end_seq(context, certs, cursor); 70490075Sobrien return 0; 70590075Sobrien} 70690075Sobrien 70790075Sobrienstatic int 708132718Skancerts_info_stdio(void *ctx, const char *str) 70990075Sobrien{ 71090075Sobrien FILE *f = ctx; 711169689Skan fprintf(f, "%s\n", str); 71290075Sobrien return 0; 713169689Skan} 71490075Sobrien 715132718Skan/** 71690075Sobrien * Print some info about the certificate store. 71790075Sobrien * 718169689Skan * @param context a hx509 context. 719169689Skan * @param certs certificate store to print information about. 720169689Skan * @param func function that will get each line of the information, if 721169689Skan * NULL is used the data is printed on a FILE descriptor that should 722169689Skan * be passed in ctx, if ctx also is NULL, stdout is used. 723169689Skan * @param ctx parameter to func. 724169689Skan * 725169689Skan * @return Returns an hx509 error code. 726169689Skan * 727169689Skan * @ingroup hx509_keyset 728169689Skan */ 729169689Skan 73090075Sobrienint 73190075Sobrienhx509_certs_info(hx509_context context, 732169689Skan hx509_certs certs, 73390075Sobrien int (*func)(void *, const char *), 734169689Skan void *ctx) 73590075Sobrien{ 73690075Sobrien if (func == NULL) { 737169689Skan func = certs_info_stdio; 73890075Sobrien if (ctx == NULL) 739169689Skan ctx = stdout; 740169689Skan } 741169689Skan if (certs->ops->printinfo == NULL) { 742169689Skan (*func)(ctx, "No info function for certs"); 743169689Skan return 0; 74490075Sobrien } 74590075Sobrien return (*certs->ops->printinfo)(context, certs, certs->ops_data, 746169689Skan func, ctx); 747169689Skan} 748169689Skan 74990075Sobrienvoid 75090075Sobrien_hx509_pi_printf(int (*func)(void *, const char *), void *ctx, 751132718Skan const char *fmt, ...) 75290075Sobrien{ 753117395Skan va_list ap; 75490075Sobrien char *str; 755117395Skan 756117395Skan va_start(ap, fmt); 757117395Skan vasprintf(&str, fmt, ap); 75890075Sobrien va_end(ap); 759117395Skan if (str == NULL) 760117395Skan return; 761117395Skan (*func)(ctx, str); 76290075Sobrien free(str); 763117395Skan} 764117395Skan 76590075Sobrienint 76690075Sobrien_hx509_certs_keys_get(hx509_context context, 767117395Skan hx509_certs certs, 768117395Skan hx509_private_key **keys) 769117395Skan{ 770117395Skan if (certs->ops->getkeys == NULL) { 77190075Sobrien *keys = NULL; 77290075Sobrien return 0; 77390075Sobrien } 774169689Skan return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys); 77590075Sobrien} 77690075Sobrien 77790075Sobrienint 778169689Skan_hx509_certs_keys_add(hx509_context context, 779169689Skan hx509_certs certs, 780169689Skan hx509_private_key key) 781169689Skan{ 782169689Skan if (certs->ops->addkey == NULL) { 78390075Sobrien hx509_set_error_string(context, 0, EINVAL, 784169689Skan "keystore if type %s doesn't support " 785169689Skan "key add operation", 786169689Skan certs->ops->name); 787169689Skan return EINVAL; 788169689Skan } 789169689Skan return (*certs->ops->addkey)(context, certs, certs->ops_data, key); 790169689Skan} 791169689Skan 792169689Skan 793169689Skanvoid 794169689Skan_hx509_certs_keys_free(hx509_context context, 795169689Skan hx509_private_key *keys) 79690075Sobrien{ 797169689Skan int i; 798169689Skan for (i = 0; keys[i]; i++) 79990075Sobrien hx509_private_key_free(&keys[i]); 800117395Skan free(keys); 801117395Skan} 80290075Sobrien