Annotation of embedaddon/strongswan/src/libstrongswan/plugins/keychain/keychain_creds.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Martin Willi
                      3:  * Copyright (C) 2013 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "keychain_creds.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: #include <credentials/sets/mem_cred.h>
                     20: #include <processing/jobs/callback_job.h>
                     21: 
                     22: #include <Security/Security.h>
                     23: 
                     24: /**
                     25:  * System Roots keychain
                     26:  */
                     27: #define SYSTEM_ROOTS "/System/Library/Keychains/SystemRootCertificates.keychain"
                     28: 
                     29: /**
                     30:  * System keychain
                     31:  */
                     32: #define SYSTEM "/Library/Keychains/System.keychain"
                     33: 
                     34: typedef struct private_keychain_creds_t private_keychain_creds_t;
                     35: 
                     36: /**
                     37:  * Private data of an keychain_creds_t object.
                     38:  */
                     39: struct private_keychain_creds_t {
                     40: 
                     41:        /**
                     42:         * Public keychain_creds_t interface.
                     43:         */
                     44:        keychain_creds_t public;
                     45: 
                     46:        /**
                     47:         * Active in-memory credential set
                     48:         */
                     49:        mem_cred_t *set;
                     50: 
                     51:        /**
                     52:         * System roots credential set
                     53:         */
                     54:        mem_cred_t *roots;
                     55: 
                     56:        /**
                     57:         * Run loop of event monitoring thread
                     58:         */
                     59:        CFRunLoopRef loop;
                     60: };
                     61: 
                     62: /**
                     63:  * Load a credential sets with certificates from a keychain path
                     64:  */
                     65: static mem_cred_t* load_certs(private_keychain_creds_t *this, char *path)
                     66: {
                     67:        SecKeychainRef keychain;
                     68:        SecKeychainSearchRef search;
                     69:        SecKeychainItemRef item;
                     70:        mem_cred_t *set;
                     71:        OSStatus status;
                     72:        int loaded = 0;
                     73: 
                     74:        set = mem_cred_create();
                     75: 
                     76:        DBG2(DBG_CFG, "loading certificates from %s:", path);
                     77:        status = SecKeychainOpen(path, &keychain);
                     78:        if (status == errSecSuccess)
                     79:        {
                     80:                status = SecKeychainSearchCreateFromAttributes(keychain,
                     81:                                                                        kSecCertificateItemClass, NULL, &search);
                     82:                if (status == errSecSuccess)
                     83:                {
                     84:                        while (SecKeychainSearchCopyNext(search, &item) == errSecSuccess)
                     85:                        {
                     86:                                certificate_t *cert;
                     87:                                UInt32 len;
                     88:                                void *data;
                     89: 
                     90:                                if (SecKeychainItemCopyAttributesAndData(item, NULL, NULL, NULL,
                     91:                                                                                                &len, &data) == errSecSuccess)
                     92:                                {
                     93:                                        cert = lib->creds->create(lib->creds,
                     94:                                                                CRED_CERTIFICATE, CERT_X509,
                     95:                                                                BUILD_BLOB_ASN1_DER, chunk_create(data, len),
                     96:                                                                BUILD_END);
                     97:                                        if (cert)
                     98:                                        {
                     99:                                                DBG2(DBG_CFG, "  loaded '%Y'", cert->get_subject(cert));
                    100:                                                set->add_cert(set, TRUE, cert);
                    101:                                                loaded++;
                    102:                                        }
                    103:                                        SecKeychainItemFreeAttributesAndData(NULL, data);
                    104:                                }
                    105:                                CFRelease(item);
                    106:                        }
                    107:                        CFRelease(search);
                    108:                }
                    109:                CFRelease(keychain);
                    110:        }
                    111:        DBG1(DBG_CFG, "loaded %d certificates from %s", loaded, path);
                    112:        return set;
                    113: }
                    114: 
                    115: /**
                    116:  * Callback function reloading keychain on changes
                    117:  */
                    118: static OSStatus keychain_cb(SecKeychainEvent keychainEvent,
                    119:                                                        SecKeychainCallbackInfo *info,
                    120:                                                        private_keychain_creds_t *this)
                    121: {
                    122:        mem_cred_t *new;
                    123: 
                    124:        DBG1(DBG_CFG, "received keychain event, reloading credentials");
                    125: 
                    126:        /* register new before removing old */
                    127:        new = load_certs(this, SYSTEM);
                    128:        lib->credmgr->add_set(lib->credmgr, &new->set);
                    129:        lib->credmgr->remove_set(lib->credmgr, &this->set->set);
                    130: 
                    131:        lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
                    132: 
                    133:        this->set->destroy(this->set);
                    134:        this->set = new;
                    135: 
                    136:        return errSecSuccess;
                    137: }
                    138: 
                    139: /**
                    140:  * Wait for changes in the keychain and handle them
                    141:  */
                    142: static job_requeue_t monitor_changes(private_keychain_creds_t *this)
                    143: {
                    144:        if (SecKeychainAddCallback((SecKeychainCallback)keychain_cb,
                    145:                                                kSecAddEventMask | kSecDeleteEventMask |
                    146:                                                kSecUpdateEventMask | kSecTrustSettingsChangedEventMask,
                    147:                                                this) == errSecSuccess)
                    148:        {
                    149:                this->loop = CFRunLoopGetCurrent();
                    150: 
                    151:                /* does not return until cancelled */
                    152:                CFRunLoopRun();
                    153: 
                    154:                this->loop = NULL;
                    155:                SecKeychainRemoveCallback((SecKeychainCallback)keychain_cb);
                    156:        }
                    157:        return JOB_REQUEUE_NONE;
                    158: }
                    159: 
                    160: /**
                    161:  * Cancel the monitoring thread in its RunLoop
                    162:  */
                    163: static bool cancel_monitor(private_keychain_creds_t *this)
                    164: {
                    165:        if (this->loop)
                    166:        {
                    167:                CFRunLoopStop(this->loop);
                    168:        }
                    169:        return TRUE;
                    170: }
                    171: 
                    172: METHOD(keychain_creds_t, destroy, void,
                    173:        private_keychain_creds_t *this)
                    174: {
                    175:        lib->credmgr->remove_set(lib->credmgr, &this->set->set);
                    176:        lib->credmgr->remove_set(lib->credmgr, &this->roots->set);
                    177:        this->set->destroy(this->set);
                    178:        this->roots->destroy(this->roots);
                    179:        free(this);
                    180: }
                    181: 
                    182: /**
                    183:  * See header
                    184:  */
                    185: keychain_creds_t *keychain_creds_create()
                    186: {
                    187:        private_keychain_creds_t *this;
                    188: 
                    189:        INIT(this,
                    190:                .public = {
                    191:                        .destroy = _destroy,
                    192:                },
                    193:        );
                    194: 
                    195:        this->roots = load_certs(this, SYSTEM_ROOTS);
                    196:        this->set = load_certs(this, SYSTEM);
                    197: 
                    198:        lib->credmgr->add_set(lib->credmgr, &this->roots->set);
                    199:        lib->credmgr->add_set(lib->credmgr, &this->set->set);
                    200: 
                    201:        lib->processor->queue_job(lib->processor,
                    202:                        (job_t*)callback_job_create_with_prio((void*)monitor_changes,
                    203:                                        this, NULL, (void*)cancel_monitor, JOB_PRIO_CRITICAL));
                    204: 
                    205:        return &this->public;
                    206: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>