]> git.saurik.com Git - apple/security.git/blobdiff - sec/securityd/SecTrustStoreServer.c
Security-57031.1.35.tar.gz
[apple/security.git] / sec / securityd / SecTrustStoreServer.c
diff --git a/sec/securityd/SecTrustStoreServer.c b/sec/securityd/SecTrustStoreServer.c
deleted file mode 100644 (file)
index 18a1e48..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * SecTrustStoreServer.c - CertificateSource API to a system root certificate store
- */
-#include "SecTrustStoreServer.h"
-
-#include <Security/SecCertificateInternal.h>
-#include <Security/SecFramework.h>
-#include <errno.h>
-#include <limits.h>
-#include <dispatch/dispatch.h>
-#include <sqlite3.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <CoreFoundation/CFData.h>
-#include <CoreFoundation/CFPropertyList.h>
-#include <CoreFoundation/CFURL.h>
-#include <AssertMacros.h>
-#include <utilities/debugging.h>
-#include "SecBasePriv.h"
-#include <Security/SecInternal.h>
-#include "securityd_client.h"
-#include <securityd/SecTrustStoreServer.h>
-#include "utilities/sqlutils.h"
-#include "utilities/SecDb.h"
-#include <utilities/SecCFError.h>
-#include "utilities/SecFileLocations.h"
-#include <utilities/SecDispatchRelease.h>
-
-/* uid of the _securityd user. */
-#define SECURTYD_UID 64
-
-static dispatch_once_t kSecTrustStoreUserOnce;
-static SecTrustStoreRef kSecTrustStoreUser = NULL;
-
-static const char copyParentsSQL[] = "SELECT data FROM tsettings WHERE subj=?";
-static const char containsSQL[] = "SELECT tset FROM tsettings WHERE sha1=?";
-static const char insertSQL[] = "INSERT INTO tsettings(sha1,subj,tset,data)VALUES(?,?,?,?)";
-static const char updateSQL[] = "UPDATE tsettings SET tset=? WHERE sha1=?";
-static const char deleteSQL[] = "DELETE FROM tsettings WHERE sha1=?";
-static const char deleteAllSQL[] = "BEGIN EXCLUSIVE TRANSACTION; DELETE from tsettings; COMMIT TRANSACTION; VACUUM;";
-
-#define kSecTrustStoreName CFSTR("TrustStore")
-#define kSecTrustStoreDbExtension CFSTR("sqlite3")
-
-#define kTrustStoreFileName CFSTR("TrustStore.sqlite3")
-
-
-struct __SecTrustStore {
-    dispatch_queue_t queue;
-       sqlite3 *s3h;
-       sqlite3_stmt *copyParents;
-       sqlite3_stmt *contains;
-       bool readOnly;
-};
-
-static int sec_create_path(const char *path)
-{
-       char pathbuf[PATH_MAX];
-       size_t pos, len = strlen(path);
-       if (len == 0 || len > PATH_MAX)
-               return SQLITE_CANTOPEN;
-       memcpy(pathbuf, path, len);
-       for (pos = len-1; pos > 0; --pos)
-       {
-               /* Search backwards for trailing '/'. */
-               if (pathbuf[pos] == '/')
-               {
-                       pathbuf[pos] = '\0';
-                       /* Attempt to create parent directories of the database. */
-                       if (!mkdir(pathbuf, 0777))
-                               break;
-                       else
-                       {
-                               int err = errno;
-                               if (err == EEXIST)
-                                       return 0;
-                               if (err == ENOTDIR)
-                                       return SQLITE_CANTOPEN;
-                               if (err == EROFS)
-                                       return SQLITE_READONLY;
-                               if (err == EACCES)
-                                       return SQLITE_PERM;
-                               if (err == ENOSPC || err == EDQUOT)
-                                       return SQLITE_FULL;
-                               if (err == EIO)
-                                       return SQLITE_IOERR;
-
-                               /* EFAULT || ELOOP | ENAMETOOLONG || something else */
-                               return SQLITE_INTERNAL;
-                       }
-               }
-       }
-       return SQLITE_OK;
-}
-
-static int sec_sqlite3_open(const char *db_name, sqlite3 **s3h,
-       bool create_path)
-{
-       int s3e;
-       s3e = sqlite3_open(db_name, s3h);
-       if (s3e == SQLITE_CANTOPEN && create_path) {
-               /* Make sure the path to db_name exists and is writable, then
-                  try again. */
-               s3e = sec_create_path(db_name);
-               if (!s3e)
-                       s3e = sqlite3_open(db_name, s3h);
-       }
-
-       return s3e;
-}
-
-static SecTrustStoreRef SecTrustStoreCreate(const char *db_name,
-       bool create) {
-       SecTrustStoreRef ts;
-       int s3e;
-
-       require(ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)), errOut);
-    ts->queue = dispatch_queue_create("truststore", DISPATCH_QUEUE_SERIAL);
-       require_noerr(s3e = sec_sqlite3_open(db_name, &ts->s3h, create), errOut);
-
-       s3e = sqlite3_prepare(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL),
-               &ts->copyParents, NULL);
-       if (create && s3e == SQLITE_ERROR) {
-               /* sqlite3_prepare returns SQLITE_ERROR if the table we are
-                  compiling this statement for doesn't exist. */
-               char *errmsg = NULL;
-               s3e = sqlite3_exec(ts->s3h,
-                       "CREATE TABLE tsettings("
-                       "sha1 BLOB NOT NULL DEFAULT '',"
-                       "subj BLOB NOT NULL DEFAULT '',"
-                       "tset BLOB,"
-                       "data BLOB,"
-                       "PRIMARY KEY(sha1)"
-                       ");"
-                       "CREATE INDEX isubj ON tsettings(subj);"
-                       , NULL, NULL, &errmsg);
-               if (errmsg) {
-                       secwarning("CREATE TABLE cert: %s", errmsg);
-                       sqlite3_free(errmsg);
-               }
-               require_noerr(s3e, errOut);
-               s3e = sqlite3_prepare(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL),
-                       &ts->copyParents, NULL);
-       }
-       require_noerr(s3e, errOut);
-       require_noerr(s3e = sqlite3_prepare(ts->s3h, containsSQL, sizeof(containsSQL),
-               &ts->contains, NULL), errOut);
-
-       return ts;
-
-errOut:
-       if (ts) {
-               sqlite3_close(ts->s3h);
-        dispatch_release_safe(ts->queue);
-               free(ts);
-       }
-
-       return NULL;
-}
-
-static bool SecExtractFilesystemPathForKeychainFile(CFStringRef file, UInt8 *buffer, CFIndex maxBufLen)
-{
-    bool translated = false;
-    CFURLRef fileURL = SecCopyURLForFileInKeychainDirectory(file);
-    
-    if (fileURL && CFURLGetFileSystemRepresentation(fileURL, false, buffer, maxBufLen))
-        translated = true;
-    CFReleaseSafe(fileURL);
-    
-    return translated;
-}
-
-static void SecTrustStoreInitUser(void) {
-       const char path[MAXPATHLEN];
-    
-    if (SecExtractFilesystemPathForKeychainFile(kTrustStoreFileName, (UInt8*) path, (CFIndex) sizeof(path)))
-    {
-        kSecTrustStoreUser = SecTrustStoreCreate(path, true);
-        if (kSecTrustStoreUser)
-            kSecTrustStoreUser->readOnly = false;
-    }    
-}
-
-/* AUDIT[securityd](done):
-   domainName (ok) is a caller provided string of any length (might be 0), only
-       its cf type has been checked.
- */
-SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) {
-       if (CFEqual(CFSTR("user"), domainName)) {
-               dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); });
-               return kSecTrustStoreUser;
-       } else {
-        SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName);
-               return NULL;
-       }
-}
-
-/* AUDIT[securityd](done):
-   ts (ok) might be NULL.
-   certificate (ok) is a valid SecCertificateRef.
-   trustSettingsDictOrArray (checked by CFPropertyListCreateXMLData) is either
-   NULL, a dictionary or an array, but its contents have not been checked.
- */
-bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
-       SecCertificateRef certificate,
-    CFTypeRef tsdoa, CFErrorRef *error) {
-    __block bool ok;
-       require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("truststore is NULL")));
-    require_action_quiet(!ts->readOnly, errOutNotLocked, ok = SecError(errSecReadOnly, error, CFSTR("truststore is readOnly")));
-    dispatch_sync(ts->queue, ^{
-        CFTypeRef trustSettingsDictOrArray = tsdoa;
-        sqlite3_stmt *insert = NULL, *update = NULL;
-        CFDataRef xmlData = NULL;
-        CFArrayRef array = NULL;
-
-        CFDataRef subject;
-        require_action_quiet(subject = SecCertificateGetNormalizedSubjectContent(certificate),
-                             errOut, ok = SecError(errSecParam, error, CFSTR("get normalized subject failed")));
-        CFDataRef digest;
-        require_action_quiet(digest = SecCertificateGetSHA1Digest(certificate), errOut, ok = SecError(errSecParam, error, CFSTR("get sha1 digest failed")));
-
-        /* Do some basic checks on the trust settings passed in. */
-        if (trustSettingsDictOrArray == NULL) {
-            require_action_quiet(array = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks), errOut, ok = SecError(errSecAllocate, error, CFSTR("CFArrayCreate failed")));
-            trustSettingsDictOrArray = array;
-        }
-        else if(CFGetTypeID(trustSettingsDictOrArray) == CFDictionaryGetTypeID()) {
-            /* array-ize it */
-            array = CFArrayCreate(NULL, &trustSettingsDictOrArray, 1,
-                                  &kCFTypeArrayCallBacks);
-            trustSettingsDictOrArray = array;
-        }
-        else {
-            require_action_quiet(CFGetTypeID(trustSettingsDictOrArray) == CFArrayGetTypeID(), errOut, ok = SecError(errSecParam, error, CFSTR("trustSettingsDictOrArray neither dict nor array")));
-        }
-
-        require_action_quiet(xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
-                                                                   trustSettingsDictOrArray), errOut, ok = SecError(errSecParam, error, CFSTR("xml encode failed")));
-
-        int s3e = sqlite3_exec(ts->s3h, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL);
-        require_action_quiet(s3e == SQLITE_OK, errOut, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-
-        /* Parameter order is sha1,subj,tset,data. */
-        require_noerr_action_quiet(sqlite3_prepare(ts->s3h, insertSQL, sizeof(insertSQL),
-                                                   &insert, NULL), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-        require_noerr_action_quiet(sqlite3_bind_blob_wrapper(insert, 1,
-                                                             CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
-                                   errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-        require_noerr_action_quiet(sqlite3_bind_blob_wrapper(insert, 2,
-                                                             CFDataGetBytePtr(subject), CFDataGetLength(subject),
-                                                             SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-        require_noerr_action_quiet(sqlite3_bind_blob_wrapper(insert, 3,
-                                                             CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData),
-                                                             SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-        require_noerr_action_quiet(sqlite3_bind_blob_wrapper(insert, 4,
-                                                             SecCertificateGetBytePtr(certificate),
-                                                             SecCertificateGetLength(certificate), SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-        s3e = sqlite3_step(insert);
-        if (s3e == SQLITE_DONE) {
-            /* Great the insert worked. */
-            ok = true;
-        } else if (s3e == SQLITE_ERROR) {
-            /* Try update. */
-            require_noerr_action_quiet(s3e = sqlite3_prepare(ts->s3h, updateSQL, sizeof(updateSQL),
-                                                             &update, NULL), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-            require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(update, 1,
-                                                                       CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData),
-                                                                       SQLITE_STATIC), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-            require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(update, 2,
-                                                                       CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
-                                       errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-            s3e = sqlite3_step(update);
-            require_action_quiet(s3e == SQLITE_DONE, errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-            s3e = SQLITE_OK;
-            ok = true;
-        } else {
-            require_noerr_action_quiet(s3e, errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e));
-            ok = true;
-        }
-
-    errOutSql:
-        if (insert)
-            s3e = sqlite3_finalize(insert);
-        if (update)
-            s3e = sqlite3_finalize(update);
-
-        if (ok && s3e == SQLITE_OK)
-            s3e = sqlite3_exec(ts->s3h, "COMMIT TRANSACTION", NULL, NULL, NULL);
-
-        if (!ok || s3e != SQLITE_OK) {
-            sqlite3_exec(ts->s3h, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
-            if (ok) {
-                ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e);
-            }
-        }
-
-    errOut:
-        CFReleaseSafe(xmlData);
-        CFReleaseSafe(array);
-    });
-errOutNotLocked:
-       return ok;
-}
-
-/* AUDIT[securityd](done):
-   ts (ok) might be NULL.
-   digest (ok) is a data of any length (might be 0).
- */
-bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts,
-    CFDataRef digest, CFErrorRef *error) {
-       require_quiet(ts, errOutNotLocked);
-       require(!ts->readOnly, errOutNotLocked);
-    dispatch_sync(ts->queue, ^{
-        sqlite3_stmt *deleteStmt = NULL;
-        require_noerr(sqlite3_prepare(ts->s3h, deleteSQL, sizeof(deleteSQL),
-                                      &deleteStmt, NULL), errOut);
-        require_noerr(sqlite3_bind_blob_wrapper(deleteStmt, 1,
-                                                CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
-                      errOut);
-        sqlite3_step(deleteStmt);
-
-    errOut:
-        if (deleteStmt) {
-            verify_noerr(sqlite3_finalize(deleteStmt));
-        }
-    });
-errOutNotLocked:
-       return true;
-}
-
-bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error)
-{
-    __block bool removed_all = false;
-       require(ts, errOutNotLocked);
-       require(!ts->readOnly, errOutNotLocked);
-    dispatch_sync(ts->queue, ^{
-        if (SQLITE_OK == sqlite3_exec(ts->s3h, deleteAllSQL, NULL, NULL, NULL))
-            removed_all = true;
-
-        /* prepared statements become unusable after deleteAllSQL, reset them */
-        if (ts->copyParents)
-            sqlite3_finalize(ts->copyParents);
-        sqlite3_prepare(ts->s3h, copyParentsSQL, sizeof(copyParentsSQL),
-                        &ts->copyParents, NULL);
-        if (ts->contains)
-            sqlite3_finalize(ts->contains);
-        sqlite3_prepare(ts->s3h, containsSQL, sizeof(containsSQL),
-                        &ts->contains, NULL);
-    });
-errOutNotLocked:
-       return removed_all;
-}
-
-CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts,
-       SecCertificateRef certificate, CFErrorRef *error) {
-       __block CFMutableArrayRef parents = NULL;
-       require(ts, errOutNotLocked);
-    dispatch_sync(ts->queue, ^{
-        CFDataRef issuer;
-        require(issuer = SecCertificateGetNormalizedIssuerContent(certificate),
-            errOut);
-        /* @@@ Might have to use SQLITE_TRANSIENT */
-        require_noerr(sqlite3_bind_blob_wrapper(ts->copyParents, 1,
-            CFDataGetBytePtr(issuer), CFDataGetLength(issuer),
-            SQLITE_STATIC), errOut);
-
-        require(parents = CFArrayCreateMutable(kCFAllocatorDefault, 0,
-            &kCFTypeArrayCallBacks), errOut);
-        for (;;) {
-            int s3e = sqlite3_step(ts->copyParents);
-            if (s3e == SQLITE_ROW) {
-                SecCertificateRef cert;
-                require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault,
-                    sqlite3_column_blob(ts->copyParents, 0),
-                    sqlite3_column_bytes(ts->copyParents, 0)), errOut);
-                CFArrayAppendValue(parents, cert);
-                CFRelease(cert);
-            } else {
-                require(s3e == SQLITE_DONE, errOut);
-                break;
-            }
-        }
-
-        goto ok;
-    errOut:
-        if (parents) {
-            CFRelease(parents);
-            parents = NULL;
-        }
-    ok:
-        verify_noerr(sqlite3_reset(ts->copyParents));
-        verify_noerr(sqlite3_clear_bindings(ts->copyParents));
-    });
-errOutNotLocked:
-       return parents;
-}
-
-/* AUDIT[securityd](done):
-   ts (ok) might be NULL.
-   digest (ok) is a data of any length (might be 0), only its cf type has
-   been checked.
-*/
-bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts,
-       CFDataRef digest, bool *contains, CFErrorRef *error) {
-    if (contains)
-        *contains = false;
-    __block bool ok = true;
-       require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("ts is NULL")));
-    dispatch_sync(ts->queue, ^{
-        int s3e;
-        require_noerr_action(s3e = sqlite3_bind_blob_wrapper(ts->contains, 1,
-            CFDataGetBytePtr(digest), CFDataGetLength(digest), SQLITE_STATIC),
-            errOut, ok = SecDbErrorWithStmt(s3e, ts->contains, error, CFSTR("sqlite3_bind_blob failed")));
-        s3e = sqlite3_step(ts->contains);
-        if (s3e == SQLITE_ROW) {
-            if (contains)
-                *contains = true;
-        } else {
-            require_action(s3e == SQLITE_DONE, errOut, ok = SecDbErrorWithStmt(s3e, ts->contains, error, CFSTR("sqlite3_step failed")));
-        }
-
-    errOut:
-        verify_noerr(sqlite3_reset(ts->contains));
-        verify_noerr(sqlite3_clear_bindings(ts->contains));
-    });
-errOutNotLocked:
-       return ok;
-}