Example #1
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
static Boolean
hasEntitlement(audit_token_t audit_token, CFStringRef entitlement, CFStringRef vpntype)
{
	Boolean		hasEntitlement	= FALSE;
	SecTaskRef	task;

	/* Create the security task from the audit token. */
	task = SecTaskCreateWithAuditToken(NULL, audit_token);
	if (task != NULL) {
		CFErrorRef	error	= NULL;
		CFTypeRef	value;

		/* Get the value for the entitlement. */
		value = SecTaskCopyValueForEntitlement(task, entitlement, &error);
		if (value != NULL) {
			if (isA_CFBoolean(value)) {
				if (CFBooleanGetValue(value)) {
					/* if client DOES have entitlement */
					hasEntitlement = TRUE;
				}
			} else if (isA_CFArray(value)){
				if (vpntype == NULL){
					/* we don't care about subtype */
					hasEntitlement = TRUE;
				}else {
					if (CFArrayContainsValue(value,
											 CFRangeMake(0, CFArrayGetCount(value)),
											 vpntype)) {
						// if client DOES have entitlement
						hasEntitlement = TRUE;
					}
				}
			} else {
				SCLog(TRUE, LOG_ERR,
				      CFSTR("SCNC Controller: entitlement not valid: %@"),
				      entitlement);
			}

			CFRelease(value);
		} else if (error != NULL) {
			SCLog(TRUE, LOG_ERR,
			      CFSTR("SCNC Controller: SecTaskCopyValueForEntitlement() failed, error=%@: %@"),
			      error,
			      entitlement);
			CFRelease(error);
		}

		CFRelease(task);
	} else {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("SCNC Controller: SecTaskCreateWithAuditToken() failed: %@"),
		      entitlement);
	}

	return hasEntitlement;
}
int sectask_11_sectask_audittoken(int argc, char *const *argv)
{
    SecTaskRef task=NULL;
    CFStringRef appId=NULL;
    CFStringRef signingIdentifier=NULL;

    plan_tests(6);

    init_self_audittoken();

    ok(task=SecTaskCreateWithAuditToken(kCFAllocatorDefault, g_self_audittoken), "SecTaskCreateFromAuditToken");
    require(task, out);

    /* TODO: remove the todo once xcode signs simulator binaries */
SKIP: {
#if TARGET_IPHONE_SIMULATOR
    todo("no entitlements in the simulator binaries yet, until <rdar://problem/12194625>");
#endif
    ok(appId=SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL), "SecTaskCopyValueForEntitlement");
    skip("appId is NULL", 1, appId);
    ok(CFEqual(appId, CFSTR("com.apple.security.regressions")), "Application Identifier match");
    ok(signingIdentifier=SecTaskCopySigningIdentifier(task, NULL), "SecTaskCopySigningIdentifier");
    ok(CFEqual(signingIdentifier, CFBundleGetIdentifier(CFBundleGetMainBundle())), "CodeSigning Identifier match");
}

    pid_t pid = getpid();
    CFStringRef name = copyProcName(pid);
    CFStringRef pidstr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("[%d]"), pid);
    CFStringRef desc = CFCopyDescription(task);

    ok(CFStringFind(desc, name, 0).location != kCFNotFound, "didn't find name: %@ vs %@", desc, name);
    ok(CFStringFind(desc, pidstr, 0).location != kCFNotFound, "didn't find pidstr: %@ vs %@", desc, pidstr);

    CFReleaseSafe(name);
    CFReleaseSafe(desc);
    CFReleaseSafe(pidstr);

out:
    CFReleaseSafe(task);
    CFReleaseSafe(appId);
    CFReleaseSafe(signingIdentifier);

    return 0;
}
Example #3
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;
}