Esempio n. 1
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
__private_extern__
kern_return_t
_pppcontroller_iscontrolled(mach_port_t server,
				int * result,
				audit_token_t *audit_token)
{
    pid_t                pid = 0;
	struct service		*serv;

	audit_token_to_au32(*audit_token,
			    NULL,			// auidp
			    NULL,			// euid
			    NULL,			// egid
			    NULL,			// ruid
			    NULL,			// rgid
			    &pid,			// pid
			    NULL,			// asid
			    NULL);			// tid

	if ((serv = findbypid(pid)) == 0)
		*result = kSCStatusInvalidArgument;
	else 
		*result = kSCStatusOK;

    return (KERN_SUCCESS);
}
Esempio n. 2
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
__private_extern__
kern_return_t
_pppcontroller_bootstrap(mach_port_t server,
		mach_port_t *bootstrap,
		int * result,
		audit_token_t *audit_token)
{
    int                 pid;
	struct service		*serv;

	audit_token_to_au32(*audit_token,
			    NULL,			// auidp
			    NULL,			// euid
			    NULL,			// egid
			    NULL,			// ruid
			    NULL,			// rgid
			    &pid,			// pid
			    NULL,			// asid
			    NULL);			// tid

	if ((serv = findbypid(pid)) == 0) {
		*result = kSCStatusInvalidArgument;
		goto failed;
	}

	*bootstrap = serv->bootstrap;
	*result = kSCStatusOK;

    return (KERN_SUCCESS);
	
failed:
    return (KERN_SUCCESS);
}
Esempio n. 3
0
static CFStringRef SecTaskCopyDebugDescription(CFTypeRef cfTask)
{
    SecTaskRef task = (SecTaskRef) cfTask;
    pid_t pid;
    if (task->pid_self==-1) {
        audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
    } else {
        pid = task->pid_self;
    }

#if USE_LIBPROC
#define MAX_PROCNAME 32
    char task_name[MAX_PROCNAME + 1] = {};
    proc_name(pid, task_name, MAX_PROCNAME);
#else
    const char *task_name;
    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)
        task_name = strerror(errno);
    else
        task_name = kp.kp_proc.p_comm;
#endif

    return CFStringCreateWithFormat(CFGetAllocator(task), NULL, CFSTR("%s[%" PRIdPID "]/%d#%d LF=%d"), task_name, pid,
									task->entitlementsLoaded, task->entitlements ? (int)CFDictionaryGetCount(task->entitlements) : -1, task->lastFailure);
}
Esempio n. 4
0
/*
 * kern_return_t
 * bootstrap_create_server(mach_port_t bootstrap_port,
 *	 cmd_t server_cmd,
 *	 integer_t server_uid,
 *	 boolean_t on_demand,
 *	 mach_port_t *server_portp)
 *
 * Returns send rights to server_port of service.  At this point, the
 * server appears active, so nothing will try to launch it.  The server_port
 * can be used to delare services associated with this server by calling
 * bootstrap_create_service() and passing server_port as the bootstrap port.
 *
 * Errors:	Returns appropriate kernel errors on rpc failure.
 *		Returns BOOTSTRAP_NOT_PRIVILEGED, if bootstrap port invalid.
 */
kern_return_t
x_bootstrap_create_server(
	mach_port_t bootstrap_port,
	cmd_t server_cmd,
	int server_uid,
	boolean_t on_demand,
	audit_token_t client_audit_token,
	mach_port_t *server_portp)
{
	server_t *serverp;
	struct auditinfo audit_info;
	bootstrap_info_t *bootstrap;

	uid_t client_euid;
	
	bootstrap = lookup_bootstrap_by_port(bootstrap_port);
	debug("Server create attempt: \"%s\" bootstrap %x",
	      server_cmd, bootstrap_port);

	/* No forwarding allowed for this call - security risk (we run as root) */
	if (!bootstrap || !active_bootstrap(bootstrap)) {
		debug("Server create: \"%s\": invalid bootstrap %x",
			server_cmd, bootstrap_port);
		return BOOTSTRAP_NOT_PRIVILEGED;
	}

	/* get the identity of the requestor and set up audit_info of server */
	audit_token_to_au32(client_audit_token,
			    &audit_info.ai_auid,
			    &client_euid,
			    NULL /* egid */,
			    NULL /* ruid */,
			    NULL /* rgid */,
			    NULL /* pid */,
			    &audit_info.ai_asid,
			    &audit_info.ai_termid);

	if (client_euid != 0 && client_euid != server_uid) {
		notice("Server create: \"%s\": insufficient privilege for specified uid (euid-%d != requested-%d)",
			server_cmd, client_euid, server_uid);
		return BOOTSTRAP_NOT_PRIVILEGED;
	}

	serverp = new_server(
					bootstrap,
					server_cmd,
					server_uid,
					(on_demand) ? DEMAND : RESTARTABLE,
					audit_info);
	setup_server(serverp);

	info("New server %x in bootstrap %x: \"%s\"",
					serverp->port, bootstrap_port, server_cmd);
	*server_portp = serverp->port;
	return BOOTSTRAP_SUCCESS;
}
void 
AuditLogger::setClientInfo(const audit_token_t *srcToken)
{
    assert(srcToken);
    audit_token_to_au32(*srcToken, &mAuditId, &mEuid, &mEgid, &mRuid, &mRgid, &mPid, &mAuditSessionId, &mOldTerminalId);

    mTerminalId.at_type = AU_IPv4;
    mTerminalId.at_addr[0] = mOldTerminalId.machine;
    mTerminalId.at_port = mOldTerminalId.port;
    
    mClientInfoSet = true;
}
Esempio n. 6
0
static int
csops_task(SecTaskRef task, int ops, void *blob, size_t size)
{
	int rc;
    if (task->pid_self==-1) {
        pid_t pid;
        audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
        rc = csops_audittoken(pid, ops, blob, size, &task->token);
    }
    else
        rc = csops(task->pid_self, ops, blob, size);
	task->lastFailure = (rc == -1) ? errno : 0;
	return rc;
}
Esempio n. 7
0
kern_return_t
_io_pm_cancel_repeat_events
(
    mach_port_t             server __unused,
    audit_token_t           token,
    int                     *return_code
)
{

    SCPreferencesRef    prefs = 0;
    uid_t               callerEUID;
    CFStringRef         offType, onType;

    *return_code = kIOReturnSuccess;

    audit_token_to_au32(token, NULL, &callerEUID, NULL, NULL, NULL, NULL, NULL, NULL);

    if((*return_code = createSCSession(&prefs, callerEUID, 1)) != kIOReturnSuccess)
        goto exit;


    /* Need to take a retain on these strings as these dictionaries get release below */
    offType = getRepeatingDictionaryType(repeatingPowerOff); CFRetain(offType);
    onType = getRepeatingDictionaryType(repeatingPowerOn); CFRetain(onType);

    if (repeatingPowerOff && isA_CFDictionary(repeatingPowerOff))
        CFRelease(repeatingPowerOff); 
    if (repeatingPowerOn && isA_CFDictionary(repeatingPowerOn))
        CFRelease(repeatingPowerOn); 

    repeatingPowerOff = repeatingPowerOn = NULL;

    if ((*return_code = updateRepeatEventsOnDisk(prefs)) != kIOReturnSuccess)
        goto exit;

    schedulePowerEventType(offType);
    schedulePowerEventType(onType);

exit:

    if (offType)
        CFRelease(offType);
    if (onType)
        CFRelease(onType);
    destroySCSession(prefs, 1);

    return KERN_SUCCESS;
}
Esempio n. 8
0
__private_extern__
kern_return_t
_pppcontroller_attach(mach_port_t server,
					  xmlData_t nameRef,		/* raw XML bytes */
					  mach_msg_type_number_t nameLen,
					  mach_port_t bootstrap,
					  mach_port_t notify,
					  mach_port_t au_session,
					  mach_port_t *session,
					  int * result,
					  audit_token_t audit_token)
{
	kern_return_t	kr;
	uid_t			euid	= -1;
	gid_t			egid	= -1;
	pid_t			pid		= -1;
	
	audit_token_to_au32(audit_token,
						NULL,			// auidp
						&euid,			// euid
						&egid,			// egid
						NULL,			// ruid
						NULL,			// rgid
						&pid,			// pid
						NULL,			// asid
						NULL);			// tid
	
	kr = _pppcontroller_attach_proxy(server,
									 nameRef,
									 nameLen,
									 bootstrap,
									 notify,
									 au_session,
									 euid,
									 egid,
									 pid,
									 session,
									 result,
									 audit_token);
	return kr;
}
Esempio n. 9
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;
}
Esempio n. 10
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
__private_extern__
kern_return_t
_pppcontroller_attach_proxy(mach_port_t server,
							xmlData_t nameRef,		/* raw XML bytes */
							mach_msg_type_number_t nameLen,
							mach_port_t bootstrap,
							mach_port_t notify,
							mach_port_t au_session,
							int uid,
							int gid,
							int pid,
							mach_port_t *session,
							int * result,
							audit_token_t audit_token)
{
	CFStringRef			serviceID = NULL;
	CFMachPortRef		port = NULL;
	CFRunLoopSourceRef  rls = NULL;
	struct client		*client = NULL;
	mach_port_t			oldport;
	uid_t				audit_euid = -1;
	gid_t				audit_egid = -1;
	pid_t				audit_pid = -1;
	
	*session = MACH_PORT_NULL;
	/* un-serialize the serviceID */
	if (!_SCUnserializeString(&serviceID, NULL, (void *)nameRef, nameLen)) {
		*result = kSCStatusFailed;
		goto failed;
	}

	if (!isA_CFString(serviceID)) {
		*result = kSCStatusInvalidArgument;
		goto failed;
	}

	/* only allow "root" callers to change the client uid/gid/pid */
	audit_token_to_au32(audit_token,
						NULL,			// auidp
						&audit_euid,	// euid
						&audit_egid,	// egid
						NULL,			// ruid
						NULL,			// rgid
						&audit_pid,		// pid
						NULL,			// asid
						NULL);			// tid

    if ((audit_euid != 0) &&
        ((uid != audit_euid) || (gid != audit_egid) || (pid != audit_pid))) {
        /*
         * the caller is NOT "root" and is trying to masquerade
         * as some other user/process.
         */
        
        /* does caller has the right entitlement */
        if (!(hasEntitlement(audit_token, kSCVPNConnectionEntitlementName, NULL))){
           *result = kSCStatusAccessError;
            goto failed;
        }
    }
    
	
	//if ((findbyserviceID(serviceID)) == 0) {
	//	*result = kSCStatusInvalidArgument;
	//	goto failed;
	//}

	/* allocate session port */
	(void) mach_port_allocate(mach_task_self(),
							  MACH_PORT_RIGHT_RECEIVE,
							  session);

    /*
     * Note: we create the CFMachPort *before* we insert a send
     *       right present to ensure that CF does not establish
     *       it's dead name notification.
     */
	port = _SC_CFMachPortCreateWithPort("PPPController/PPP", *session, server_handle_request, NULL);

    /* insert send right that will be moved to the client */
	(void) mach_port_insert_right(mach_task_self(),
								  *session,
								  *session,
								  MACH_MSG_TYPE_MAKE_SEND);

	/* Request a notification when/if the client dies */
	(void) mach_port_request_notification(mach_task_self(),
										  *session,
										  MACH_NOTIFY_NO_SENDERS,
										  1,
										  *session,
										  MACH_MSG_TYPE_MAKE_SEND_ONCE,
										  &oldport);

	/* add to runloop */
	rls = CFMachPortCreateRunLoopSource(NULL, port, 0);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);

	if (au_session != MACH_PORT_NULL) {
		if ((audit_session_join(au_session)) == AU_DEFAUDITSID) {
			SCLog(TRUE, LOG_ERR, CFSTR("_pppcontroller_attach audit_session_join fails"));
		}
	}else {
		SCLog(TRUE, LOG_ERR, CFSTR("_pppcontroller_attach au_session == NULL"));
	}

	client = client_new_mach(port, rls, serviceID, uid, gid, pid, bootstrap, notify, au_session);
	if (client == 0) {
		*result = kSCStatusFailed;
		goto failed;
	}

	*result = kSCStatusOK;
	
	my_CFRelease(&serviceID);
	my_CFRelease(&port);
	my_CFRelease(&rls);
    return KERN_SUCCESS;
	
 failed:
	my_CFRelease(&serviceID);
	if (port) {
		CFMachPortInvalidate(port);
		my_CFRelease(&port);
	}
	if (rls) {
		CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
		my_CFRelease(&rls);
	}
	if (*session != MACH_PORT_NULL) {
		mach_port_mod_refs(mach_task_self(), *session, MACH_PORT_RIGHT_SEND   , -1);
		mach_port_mod_refs(mach_task_self(), *session, MACH_PORT_RIGHT_RECEIVE, -1);
		*session = MACH_PORT_NULL;
	}
	if (client) {
		client_dispose(client);
	} else {
		if (bootstrap != MACH_PORT_NULL)
			mach_port_deallocate(mach_task_self(), bootstrap);
		if (notify != MACH_PORT_NULL)
			mach_port_deallocate(mach_task_self(), notify);
	}
    return KERN_SUCCESS;
}
Esempio n. 11
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
__private_extern__
kern_return_t
_pppcontroller_copyprivoptions(mach_port_t server,
		int options_type,
		xmlDataOut_t * options, 
		mach_msg_type_number_t * options_len,
		int * result,
		audit_token_t *audit_token)
{
    int                 pid;
	struct service		*serv;
	void				*reply = 0;
	u_int16_t			replylen = 0;
	
	audit_token_to_au32(*audit_token,
			    NULL,			// auidp
			    NULL,			// euid
			    NULL,			// egid
			    NULL,			// ruid
			    NULL,			// rgid
			    &pid,			// pid
			    NULL,			// asid
			    NULL);			// tid

	if ((serv = findbypid(pid)) == 0) {
		*result = kSCStatusInvalidArgument;
		goto failed;
	}

	switch (options_type) {
	
		/* system options */
		case 0:
			if (scnc_getconnectsystemdata(serv, &reply, &replylen)) {
				*result = kSCStatusFailed;
				goto failed;
			}
			break;

		/* user options */
		case 1:

			if (scnc_getconnectdata(serv, &reply, &replylen, 1)) {
				*result = kSCStatusFailed;
				goto failed;
			}
			break;
	}

	*options = reply;
	*options_len = replylen;

	*result = kSCStatusOK;

    return (KERN_SUCCESS);
	
failed:
	*options = 0;
	*options_len = 0;
    return (KERN_SUCCESS);
}
Esempio n. 12
0
kern_return_t
_io_pm_schedule_repeat_event
(
    mach_port_t             server __unused,
    audit_token_t           token,
    vm_offset_t             flatPackage,
    mach_msg_type_number_t  packageLen,
    int                     action,
    int                     *return_code
)
{
    CFDictionaryRef     events = NULL;
    CFDictionaryRef     offEvents = NULL;
    CFDictionaryRef     onEvents = NULL;
    CFDataRef           dataRef = NULL;
    uid_t               callerEUID;
    SCPreferencesRef    prefs = 0;
    CFStringRef         prevOffType = NULL;
    CFStringRef         prevOnType = NULL;
    CFStringRef         newOffType = NULL;
    CFStringRef         newOnType = NULL;


    *return_code = kIOReturnSuccess;

    audit_token_to_au32(token, NULL, &callerEUID, NULL, NULL, NULL, NULL, NULL, NULL);

    dataRef = CFDataCreate(0, (const UInt8 *)flatPackage, packageLen);
    if (dataRef) {
        events = (CFDictionaryRef)CFPropertyListCreateWithData(0, dataRef, 0, NULL, NULL); 
    }

    if (!events) {
        *return_code = kIOReturnBadArgument;
        goto exit;
    }
    offEvents = isA_CFDictionary(CFDictionaryGetValue(
                                events, 
                                CFSTR(kIOPMRepeatingPowerOffKey)));
    onEvents = isA_CFDictionary(CFDictionaryGetValue(
                                events, 
                                CFSTR(kIOPMRepeatingPowerOnKey)));

    if( !is_valid_repeating_dictionary(offEvents) 
     || !is_valid_repeating_dictionary(onEvents) )
    {
        syslog(LOG_INFO, "PMCFGD: Invalid formatted repeating power event dictionary\n");
        *return_code = kIOReturnBadArgument;
        goto exit;
    }

    if((*return_code = createSCSession(&prefs, callerEUID, 1)) != kIOReturnSuccess)
        goto exit;


    /* Need to take a retain on these strings as these dictionaries get released below */
    prevOffType =  getRepeatingDictionaryType(repeatingPowerOff); CFRetain(prevOffType);
    prevOnType = getRepeatingDictionaryType(repeatingPowerOn); CFRetain(prevOnType);

    /*
     * Remove both off & on events first. If off or on event is not set thru this request,
     * then it is assumed that user is requesting to delete it.
     */
    if (repeatingPowerOff && isA_CFDictionary(repeatingPowerOff))
        CFRelease(repeatingPowerOff); 
    if (repeatingPowerOn && isA_CFDictionary(repeatingPowerOn))
        CFRelease(repeatingPowerOn); 

    repeatingPowerOff = repeatingPowerOn = NULL;


    if (offEvents) {
        repeatingPowerOff = CFDictionaryCreateMutableCopy(0,0,offEvents);
    }
    if (onEvents) {
        repeatingPowerOn = CFDictionaryCreateMutableCopy(0,0,onEvents);
    }


    if ((*return_code = updateRepeatEventsOnDisk(prefs)) != kIOReturnSuccess)
        goto exit;

    newOffType = getRepeatingDictionaryType(repeatingPowerOff);
    newOnType = getRepeatingDictionaryType(repeatingPowerOn);


    /* 
     * Re-schedule the modified event types in case these new events are earlier
     * than previously scheduled ones
     */
    schedulePowerEventType(prevOffType);
    schedulePowerEventType(prevOnType);

    if (!CFEqual(prevOffType, newOffType))
        schedulePowerEventType(newOffType);

    if (!CFEqual(prevOnType, newOnType))
        schedulePowerEventType(newOnType);


exit:
    if (prevOffType)
        CFRelease(prevOffType);
    if (prevOnType)
        CFRelease(prevOnType);

    if (dataRef)
        CFRelease(dataRef);
    if (events)
        CFRelease(events);
    destroySCSession(prefs, 1);

    vm_deallocate(mach_task_self(), flatPackage, packageLen);

    return KERN_SUCCESS;
}
Esempio n. 13
0
__private_extern__ kern_return_t _io_pm_hid_event_report_activity(
    mach_port_t server,
    audit_token_t token,                                                        
    int         _action)
{
    pid_t                               callerPID;
    CFNumberRef                         appPID = NULL;
    int                                 _app_pid_;
    CFMutableDictionaryRef              foundDictionary = NULL;
    CFMutableArrayRef                   bucketsArray = NULL;
    CFDataRef                           dataEvent = NULL;
    IOPMHIDPostEventActivityWindow      *ev = NULL;
    CFAbsoluteTime                      timeNow = CFAbsoluteTimeGetCurrent();
    int                                 arrayCount = 0;
    int                                 i = 0;
    
    // Unwrapping big data structure...
    if (!gHIDEventHistory) {
        gHIDEventHistory = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks);
    }
    if (!gHIDEventHistory) {
        goto exit;
    }
    
    audit_token_to_au32(token, NULL, NULL, NULL, NULL, NULL, &callerPID, NULL, NULL);

    if (0 !=(arrayCount = CFArrayGetCount(gHIDEventHistory)))
    {
        // Scan through the array to find an existing dictionary for the given pid
        for (i=0; i<arrayCount; i++)
        {
            CFMutableDictionaryRef dictionaryForApp = NULL;
            dictionaryForApp = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(gHIDEventHistory, i);
            if (!dictionaryForApp) {
                break;
            }
            appPID = CFDictionaryGetValue(dictionaryForApp, kIOPMHIDAppPIDKey);
            if (appPID) {
                CFNumberGetValue(appPID, kCFNumberIntType, &_app_pid_);
                if (callerPID == _app_pid_) {
                    foundDictionary = dictionaryForApp;
                    break;
                }
            }
        }
    }
    
    // Unwrapping big data structure...
    if (!foundDictionary) {
        foundDictionary = CFDictionaryCreateMutable(0, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        CFArrayAppendValue(gHIDEventHistory, foundDictionary);
        CFRelease(foundDictionary);
        
        /* Tag our pid */
        appPID = CFNumberCreate(0, kCFNumberIntType, &callerPID);
        if (appPID) {
            CFDictionarySetValue(foundDictionary, kIOPMHIDAppPIDKey, appPID);
            CFRelease(appPID);
        }

        /* Tag the process name */
        CFStringRef appName = NULL;
        char    appBuf[MAXPATHLEN];
        int     len = proc_name(callerPID, appBuf, MAXPATHLEN);
        if (0 != len) {
            appName = CFStringCreateWithCString(0, appBuf, kCFStringEncodingMacRoman);
            if (appName) {
                CFDictionarySetValue(foundDictionary, kIOPMHIDAppPathKey, appName);
                CFRelease(appName);
            }
        }
    }

    if (!foundDictionary)
        goto exit;

    // Unwrapping big data structure...
    bucketsArray = (CFMutableArrayRef)CFDictionaryGetValue(foundDictionary, kIOPMHIDHistoryArrayKey);
    if (!bucketsArray) {
        bucketsArray = CFArrayCreateMutable(0, 1, &kCFTypeArrayCallBacks);
        CFDictionarySetValue(foundDictionary, kIOPMHIDHistoryArrayKey, bucketsArray);
        CFRelease(bucketsArray);
    }
    if (!bucketsArray) 
        goto exit;

    // Check last HID event bucket timestamp - is it more than 5 minutes old?
    bool foundWindowForEvent = false;
    if (0 < CFArrayGetCount(bucketsArray)) {
        dataEvent = (CFDataRef)CFArrayGetValueAtIndex(bucketsArray, 0);
    }
    if (dataEvent) {
        ev = (IOPMHIDPostEventActivityWindow *)CFDataGetBytePtr(dataEvent);
        if (timeNow < (ev->eventWindowStart + kFiveMinutesInSeconds))
        {
            // This HID event gets dropped into this existing 5 minute bucket.
            // We bump the count for HID activity!
            if (__NX_NULL_EVENT == _action) {
                ev->nullEventCount++;
            } else {
                ev->hidEventCount++;
            }
            foundWindowForEvent = true;
        }
    }

    if (!foundWindowForEvent) {
        IOPMHIDPostEventActivityWindow  newv;

        // We align the starts of our windows with 5 minute intervals
        newv.eventWindowStart = ((int)timeNow / (int)kFiveMinutesInSeconds) * kFiveMinutesInSeconds;
        newv.nullEventCount = newv.hidEventCount = 0;
        if (__NX_NULL_EVENT == _action) {
            newv.nullEventCount++;
        } else {
            newv.hidEventCount++;
        }
    
        dataEvent = CFDataCreate(0, (const UInt8 *)&newv, sizeof(IOPMHIDPostEventActivityWindow));
        if (dataEvent) {
            CFArrayInsertValueAtIndex(bucketsArray, 0, dataEvent);
            CFRelease(dataEvent);
        }
        
        // If we've recorded more than kMaxFiveMinutesWindowsCount activity windows for this process, delete the old ones.
        while (kMaxFiveMinutesWindowsCount < CFArrayGetCount(bucketsArray)) {
            CFArrayRemoveValueAtIndex(bucketsArray, CFArrayGetCount(bucketsArray) - 1);
        }
        
    }

exit:
    return KERN_SUCCESS;
}