/********************************************************
 *********** SecUserAnchorSource object ************
 ********************************************************/
static bool SecUserAnchorSourceCopyParents(
	SecCertificateSourceRef source, SecCertificateRef certificate,
        void *context, SecCertificateSourceParents callback) {
    CFArrayRef parents = SecTrustStoreCopyParents(
        SecTrustStoreForDomain(kSecTrustStoreDomainUser), certificate);
    callback(context, parents);
    CFReleaseSafe(parents);
    return true;
}
static void tests(void)
{
	SecCertificateRef cert0;
	isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)),
		NULL, "create cert0");
    SecTrustStoreRef user_store;
    isnt(user_store = SecTrustStoreForDomain(kSecTrustStoreDomainUser),
        NULL, "get user trust settings store handle");
    ok(!SecTrustStoreContains(user_store, cert0),
        "cert0 is not yet present");
    ok_status(SecTrustStoreSetTrustSettings(user_store, cert0, NULL),
        "make cert0 trusted for anything");
    ok(SecTrustStoreContains(user_store, cert0),
        "cert0 is present");
    ok_status(SecTrustStoreSetTrustSettings(user_store, cert0, NULL),
        "make cert0 trusted for anything - again, should update now");
    ok(SecTrustStoreContains(user_store, cert0),
        "cert0 is still present");
    ok_status(SecTrustStoreRemoveCertificate(user_store, cert0),
        "removing cert0");
    ok(!SecTrustStoreContains(user_store, cert0),
        "cert0 is no longer present");

    /* Adding again...*/
    ok_status(SecTrustStoreSetTrustSettings(user_store, cert0, NULL),
        "make cert0 trusted for anything");
    ok(SecTrustStoreContains(user_store, cert0),
       "cert0 is present");

    /* Remove it */
    ok_status(SecTrustStoreRemoveCertificate(user_store, cert0),
              "removing cert0");
    ok(!SecTrustStoreContains(user_store, cert0),
       "cert0 is no longer present");

	CFReleaseSafe(cert0);
}
static bool SecUserAnchorSourceContains(SecCertificateSourceRef source,
	SecCertificateRef certificate) {
    return SecTrustStoreContains(
        SecTrustStoreForDomain(kSecTrustStoreDomainUser), certificate);
}
Example #4
0
/* AUDIT[securityd](done):
   receiver (unused) is a mach_port owned by this process.
   reply (checked by mig) is a caller provided mach_port.
   auditToken (ok) is a kernel provided audit token.
   request_id (checked by mig) is caller provided value, that matches the
       mig entry for this function.
   msg_id (ok) is caller provided value.
   msg_data (ok) is a caller provided data of length:
   msg_length (ok).
 */
kern_return_t securityd_server_request(mach_port_t receiver, mach_port_t reply,
        audit_token_t auditToken,
        uint32_t request_id, uint32_t msg_id, uint8_t *msg_data,
        mach_msg_type_number_t msg_length)
{
    CFTypeRef args_in = NULL;
    CFTypeRef args_out = NULL;
    bool sendResponse = true;
    const char *op_name;

    request_begin();

    if (msg_length) {
        CFDataRef data_in = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
            msg_data, msg_length, kCFAllocatorNull);
        if (data_in) {
            args_in = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
                data_in, kCFPropertyListImmutable, NULL);
            CFRelease(data_in);
        }
    }

#if 0
    static int crash_counter = 0;
    if (crash_counter++) {
        secdebug("server", "crash test");
        exit(1);
    }
#endif

    SecTaskRef clientTask = 
#if CHECK_ENTITLEMENTS
    SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
#else 
    NULL;
#endif
    CFArrayRef groups = SecTaskCopyAccessGroups(clientTask);
    SecAccessGroupsSetCurrent(groups);
    OSStatus status = errSecParam;
    switch(msg_id) {
        case sec_item_add_id:
            op_name = "SecItemAdd";
            if (isDictionary(args_in))
                status = _SecItemAdd(args_in, &args_out, groups);
            break;
        case sec_item_copy_matching_id:
            op_name = "SecItemCopyMatching";
            if (isDictionary(args_in))
                status = _SecItemCopyMatching(args_in, &args_out, groups);
            break;
        case sec_item_delete_id:
            op_name = "SecItemDelete";
            if (isDictionary(args_in))
                status = _SecItemDelete(args_in, groups);
            break;
        case sec_item_update_id:
            op_name = "SecItemUpdate";
            if (isArrayOfLength(args_in, 2)) {
                CFDictionaryRef
                    in0 = (CFDictionaryRef)CFArrayGetValueAtIndex(args_in, 0),
                    in1 = (CFDictionaryRef)CFArrayGetValueAtIndex(args_in, 1);
                if (isDictionary(in0) && isDictionary(in1))
                    status = _SecItemUpdate(in0, in1, groups);
            }
            break;
        case sec_trust_store_contains_id:
        {
            op_name = "SecTrustStoreContains";
            if (!isArray(args_in))
                break;
            CFIndex argc_in = CFArrayGetCount(args_in);
            if (argc_in != 2)
                break;
            CFStringRef domainName = CFArrayGetValueAtIndex(args_in, 0);
            CFDataRef digest = CFArrayGetValueAtIndex(args_in, 1);
            if (!isString(domainName) || !isData(digest))
                break;

            SecTrustStoreRef ts = SecTrustStoreForDomainName(domainName);
            status = !SecTrustStoreContainsCertificateWithDigest(ts, digest);
            break;
        }
        case sec_trust_store_set_trust_settings_id:
        {
            op_name = "SecTrustStoreSetTrustSettings";
            /* Open the trust store unconditially so we can abuse this method
               even in clients that just want to read from the truststore,
               and this call will force it to be created. */
            SecTrustStoreRef ts = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
            if (!isArray(args_in))
                break;
            CFIndex argc_in = CFArrayGetCount(args_in);
            if (argc_in != 1 && argc_in != 2)
                break;
            if (!SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementModifyAnchorCertificates)) {
                status = errSecMissingEntitlement;
                break;
            }
            CFDataRef certificateData = (CFDataRef)CFArrayGetValueAtIndex(args_in, 0);
            if (!isData(certificateData))
                break;
            SecCertificateRef certificate = SecCertificateCreateWithData(NULL, certificateData);
            if (certificate) {
                CFTypeRef trustSettingsDictOrArray;
                if (argc_in < 2) {
                    trustSettingsDictOrArray = NULL;
                } else {
                    trustSettingsDictOrArray = CFArrayGetValueAtIndex(args_in, 1);
                    if (trustSettingsDictOrArray) {
                        CFTypeID tst = CFGetTypeID(trustSettingsDictOrArray);
                        if (tst != CFArrayGetTypeID() && tst != CFDictionaryGetTypeID()) {
                            CFRelease(certificate);
                            break;
                        }
                    }
                }
                status = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray);
                CFRelease(certificate);
            }
            break;
        }
        case sec_trust_store_remove_certificate_id:
            op_name = "SecTrustStoreRemoveCertificate";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementModifyAnchorCertificates)) {
                SecTrustStoreRef ts = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
                if (isData(args_in)) {
                    status = SecTrustStoreRemoveCertificateWithDigest(ts, args_in);
                }
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_delete_all_id:
            op_name = "SecDeleteAll";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementWipeDevice)) {
                status = SecItemDeleteAll();
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_trust_evaluate_id:
            op_name = "SecTrustEvaluate";
            if (isDictionary(args_in)) {
                struct securityd_server_trust_evaluation_context *tec = malloc(sizeof(*tec));
                tec->reply = reply;
                tec->request_id = request_id;
                status = SecTrustServerEvaluateAsync(args_in,
                    securityd_server_trust_evaluate_done, tec);
                if (status == noErr || status == errSecWaitForCallback) {
                    sendResponse = false;
                } else {
                    free(tec);
                }
            }
            break;
        case sec_restore_keychain_id:
            op_name = "SecRestoreKeychain";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementRestoreKeychain)) {
                status = _SecServerRestoreKeychain();
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_migrate_keychain_id:
            op_name = "SecMigrateKeychain";
            if (isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementMigrateKeychain)) {
                    status = _SecServerMigrateKeychain(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        case sec_keychain_backup_id:
            op_name = "SecKeychainBackup";
            if (!args_in || isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementRestoreKeychain)) {
                    status = _SecServerKeychainBackup(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        case sec_keychain_restore_id:
            op_name = "SecKeychainRestore";
            if (isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementRestoreKeychain)) {
                    status = _SecServerKeychainRestore(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        default:
            op_name = "invalid_operation";
            status = errSecParam;
            break;
    }

    const char *proc_name;
#ifdef NDEBUG
    if (status == errSecMissingEntitlement) {
#endif
        pid_t pid;
        audit_token_to_au32(auditToken, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
        int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
        struct kinfo_proc kp;
        size_t len = sizeof(kp);
        if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0)
            proc_name = strerror(errno);
        else
            proc_name = kp.kp_proc.p_comm;

#ifndef NDEBUG
    if (status == errSecMissingEntitlement) {
#endif
        asl_log(NULL, NULL, ASL_LEVEL_ERR,
            "%s[%u] %s: missing entitlement", proc_name, pid, op_name);
        /* Remap errSecMissingEntitlement -> errSecInteractionNotAllowed. */
        status = errSecInteractionNotAllowed;
    }

    secdebug("ipc", "%s[%u] %s: returning: %d", proc_name, pid, op_name,
        status);

    CFReleaseSafe(groups);
    CFReleaseSafe(clientTask);
    SecAccessGroupsSetCurrent(NULL);

    kern_return_t err = 0;
    if (sendResponse)
        err = securityd_server_send_reply(reply, request_id, status, args_out);

    CFReleaseSafe(args_in);

    return err;
}

extern boolean_t securityd_request_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);

union max_msg_size_union {
    union __RequestUnion__securityd_client_securityd_reply_subsystem reply;
};

static uint8_t reply_buffer[sizeof(union max_msg_size_union) + MAX_TRAILER_SIZE];

static void *handle_message(void *msg, CFIndex size,
        CFAllocatorRef allocator, void *info)
{
    mach_msg_header_t *message = (mach_msg_header_t *)msg;
    mach_msg_header_t *reply = (mach_msg_header_t *)reply_buffer;

    securityd_request_server(message, reply);

    return NULL;
}