bool SystemKeychainKey::update()
{
    // if we checked recently, just assume it's okay
    if (mValid && mUpdateThreshold > Time::now())
        return mValid;

    // check the file
    struct stat st;
    if (::stat(mPath.c_str(), &st)) {
        // something wrong with the file; can't use it
        mUpdateThreshold = Time::now() + Time::Interval(checkDelay);
        return mValid = false;
    }
    if (mValid && Time::Absolute(st.st_mtimespec) == mCachedDate)
        return true;
    mUpdateThreshold = Time::now() + Time::Interval(checkDelay);

    try {
        secnotice("syskc", "reading system unlock record from %s", mPath.c_str());
        UnixPlusPlus::AutoFileDesc fd(mPath, O_RDONLY);
        if (fd.read(mBlob) != sizeof(mBlob))
            return false;
        if (mBlob.isValid()) {
            mCachedDate = st.st_mtimespec;
            return mValid = true;
        } else
            return mValid = false;
    } catch (...) {
        secnotice("syskc", "system unlock record not available");
        return false;
    }
}
// Start OTR negotiation if we haven't already done so.
SOSCoderStatus
SOSCoderStart(SOSCoderRef coder, CFErrorRef *error) {
    CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0);
    CFStringRef beginState = NULL;
    SOSCoderStatus result = kSOSCoderFailure;
    CFMutableDataRef startPacket = NULL;

    require_action_quiet(coder->sessRef, coderFailure, CFStringAppend(action, CFSTR("*** no otr session ***")));
    beginState = CFCopyDescription(coder->sessRef);
    require_action_quiet(!coder->waitingForDataPacket, negotiatingOut, CFStringAppend(action, CFSTR("waiting for peer to send first data packet")));
    require_action_quiet(!SecOTRSGetIsReadyForMessages(coder->sessRef), coderFailure, CFStringAppend(action, CFSTR("otr session ready"));
                         result = kSOSCoderDataReturned);
    require_action_quiet(SecOTRSGetIsIdle(coder->sessRef), negotiatingOut, CFStringAppend(action, CFSTR("otr negotiating already")));
    require_action_quiet(startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0), coderFailure, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("alloc failed"), NULL, error));
    require_quiet(SOSOTRSAppendStartPacket(coder->sessRef, startPacket, error), coderFailure);
    CFRetainAssign(coder->pendingResponse, startPacket);

negotiatingOut:
    result = kSOSCoderNegotiating;
coderFailure:
    // Uber state log
    if (result == kSOSCoderFailure && error && *error)
        CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error);
    secnotice("coder", "%@ %s %@ %@ returned %s", beginState,
              SecOTRPacketTypeString(startPacket), action, coder->sessRef, SOSCoderString(result));
    CFReleaseNull(startPacket);
    CFReleaseSafe(beginState);
    CFRelease(action);

    return result;

}
// Convert from securityd error codes to OSStatus for legacy API.
OSStatus SecErrorGetOSStatus(CFErrorRef error) {
    OSStatus status;
    if (error == NULL) {
        status = errSecSuccess;
    } else {
        CFStringRef domain = CFErrorGetDomain(error);
        if (domain == NULL) {
            secerror("No error domain for error: %@", error);
            status = errSecInternal;
        } else if (CFEqual(kSecErrorDomain, domain)) {
            status = (OSStatus)CFErrorGetCode(error);
        } else if (CFEqual(kSecDbErrorDomain, domain)) {
            status = osstatus_for_s3e((int)CFErrorGetCode(error));
        } else if (CFEqual(kSecErrnoDomain, domain)) {
            status = (OSStatus)CFErrorGetCode(error);
        } else if (CFEqual(kSecKernDomain, domain)) {
            status = osstatus_for_kern_return(CFErrorGetCode(error));
        } else if (CFEqual(sSecXPCErrorDomain, domain)) {
            status = osstatus_for_xpc_error(CFErrorGetCode(error));
        } else if (CFEqual(sSecDERErrorDomain, domain)) {
            status = osstatus_for_der_error(CFErrorGetCode(error));
        } else {
            secnotice("securityd", "unknown error domain: %@ for error: %@", domain, error);
            status = errSecInternal;
        }
    }
    return status;
}
//
// Construct a Process object.
//
Process::Process(TaskPort taskPort,	const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
 :  mTaskPort(taskPort), mByteFlipped(false), mPid(mTaskPort.pid()), mUid(0), mGid(0)
{
	StLock<Mutex> _(*this);
	
	// set parent session
	parent(Session::find(audit.sessionId(), true));

    // let's take a look at our wannabe client...
	if (mTaskPort.pid() != mPid) {
		secnotice("SS", "Task/pid setup mismatch pid=%d task=%d(%d)",
			mPid, mTaskPort.port(), mTaskPort.pid());
		CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED);	// you lied!
	}

	setup(info);
	ClientIdentification::setup(this->pid());

    // NB: ServerChild::find() should only be used to determine
    // *existence*.  Don't use the returned Child object for anything else, 
    // as it is not protected against its underlying process's destruction.  
	if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction
        || ServerChild::find<ServerChild>(this->pid()))   // securityd's child; do not mark this txn dirty
		VProc::Transaction::deactivate();

    secinfo("SS", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(),
             (char *)codePath(this->processCode()).c_str(), taskPort.port(), mUid, mGid);
}
CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) {
    size_t saltlen = SALTMAX;
    uint8_t salt[saltlen];

    size_t iterations = ITERATIONMIN;
    size_t keysize = 256;

    if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) {
        SOSCreateError(kSOSErrorProcessingFailure, CFSTR("CCRandomCopyBytes failed"), NULL, error);
        return NULL;
    }

    CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0);
    CFDataSetLength(result, der_sizeof_pbkdf2_params(saltlen, salt, iterations, keysize));

    uint8_t * encode = der_encode_pbkdf2_params(saltlen, salt, iterations, keysize,
                                                CFDataGetBytePtr(result),
                                                CFDataGetMutableBytePtr(result) + CFDataGetLength(result));

    if (!encode)
        CFReleaseNull(result);

    if (result) {
        secnotice("keygen", "Created new parameters: iterations %zd, keysize %zd: %@", iterations, keysize, result);
    }

    return result;
}
static void asynchttp_timer_proc(asynchttp_t *http) {
    CFStringRef req_meth = http->request ? CFHTTPMessageCopyRequestMethod(http->request) : NULL;
    CFURLRef req_url = http->request ? CFHTTPMessageCopyRequestURL(http->request) : NULL;
    secnotice("http", "Timeout during %@ %@.", req_meth, req_url);
    CFReleaseSafe(req_url);
    CFReleaseSafe(req_meth);
    asynchttp_complete(http);
}
Exemple #7
0
void UnixDb::close()
{
	if (mDb) {
		secnotice("unixdb", "close(%p)", mDb);
		mDb->close(mDb);
		mDb = NULL;
		setFd(invalidFd);
	}
}
static xpc_connection_t swca_create_connection(const char *name) {
    if (!name)
        name = kSWCAXPCServiceName;
    xpc_connection_t connection;
    connection = xpc_connection_create_mach_service(name, NULL, 0);
    xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
        const char *description = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
        secnotice("xpc", "got event: %s", description);
    });
Exemple #9
0
void UnixDb::open(const char *path, int flags, int mode, DBTYPE type)
{
	if (DB* newDb = ::dbopen(path, flags, mode, type, NULL)) {
		close();
		mDb = newDb;
		setFd(mDb->fd(mDb));
		secnotice("unixdb", "open(%s,0x%x,0x%x,type=%d)=%p", path, flags, mode, type, mDb);
	} else
		UnixError::throwMe();
}
static CFDataRef SOSKeychainCopySavedAccountData()
{
    CFErrorRef error = NULL;
    CFDataRef accountData = SOSItemCopy(kSOSAccountLabel, &error);
    if (!accountData)
        secnotice("account", "Failed to load account: %@", error);
    CFReleaseNull(error);

    return accountData;
}
Exemple #11
0
bool UnixDb::put(const CssmData &key, const CssmData &value, int flags)
{
	Data dKey(key);
	Data dValue(value);
	int rc = mDb->put(mDb, &dKey, &dValue, flags);
	secnotice("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d",
		mDb, key.length(), value.length(), flags, rc);
	checkError(rc);
	return !rc;
}
//
// Screen a process setup request for an existing process.
// This means the client has requested intialization even though we remember having
// talked to it in the past. This could either be an exec(2), or the client could just
// have forgotten all about its securityd client state. Or it could be an attack...
//
void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
{
	StLock<Mutex> _(*this);
	if (taskPort != mTaskPort) {
		secnotice("SS", "Process %p(%d) reset mismatch (tp %d-%d)",
			this, pid(), taskPort.port(), mTaskPort.port());
		//@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE);		// liar
	}
	setup(info);
	CFCopyRef<SecCodeRef> oldCode = processCode();

	ClientIdentification::setup(this->pid());	// re-constructs processCode()
	if (CFEqual(oldCode, processCode())) {
        secnotice("SS", "%p Client reset amnesia", this);
	} else {
        secnotice("SS", "%p Client reset full", this);
		CodeSigningHost::reset();
	}
}
SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error) {        
    CFAllocatorRef allocator = CFGetAllocator(peerInfo);
    
    SOSCoderRef coder = calloc(1, sizeof(struct __OpaqueSOSCoder));
    CFErrorRef localError = NULL;

    SecOTRFullIdentityRef myRef = NULL;
    SecOTRPublicIdentityRef peerRef = NULL;
    SecKeyRef privateKey = NULL;
    SecKeyRef publicKey = NULL;

    if (myPeerInfo && peerInfo) {
        privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError);
        require_quiet(privateKey, errOut);

        myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError);
        require_quiet(myRef, errOut);
        
        CFReleaseNull(privateKey);
    
        publicKey = SOSPeerInfoCopyPubKey(peerInfo);
        
        peerRef = SecOTRPublicIdentityCreateFromSecKeyRef(allocator, publicKey, &localError);
        require_quiet(peerRef, errOut);
        
        coder->sessRef = SecOTRSessionCreateFromID(allocator, myRef, peerRef);

        require(coder->sessRef, errOut);
        
        coder->waitingForDataPacket = false;
        coder->pendingResponse = NULL;
        
        CFReleaseNull(publicKey);
        CFReleaseNull(privateKey);
        CFReleaseNull(myRef);
        CFReleaseNull(peerRef);
    } else {
        secnotice("coder", "NULL Coder requested, no transport security");
    }

    SOSCoderStart(coder, NULL);

    return coder;

errOut:
    secerror("Coder create failed: %@\n", localError ? localError : (CFTypeRef)CFSTR("No local error in SOSCoderCreate"));
    secerror("Coder create failed: %@\n", error ? *error : (CFTypeRef)CFSTR("WTF NULL?"));
    CFReleaseNull(myRef);
    CFReleaseNull(peerRef);
    CFReleaseNull(publicKey);
    CFReleaseNull(privateKey);

    free(coder);
    return NULL;
}
void debugDumpUserParameters(CFStringRef message, CFDataRef parameters)
{
    size_t saltlen = 0;
    const uint8_t *salt = NULL;
    
    size_t iterations = 0;
    size_t keysize = 0;
    
    const uint8_t *der = CFDataGetBytePtr(parameters);
    const uint8_t *der_end = der + CFDataGetLength(parameters);
    
    der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);
    if (der == NULL) {
        secnotice("keygen", "failed to decode pbkdf2 params");
        return;
    }
    
    BufferPerformWithHexString(salt, saltlen, ^(CFStringRef saltHex) {
        CFDataPerformWithHexString(parameters, ^(CFStringRef parametersHex) {
            secnotice("keygen", "%@ <Params: count: %zd, keysize: %zd, salt: %@, raw: %@>]", message, iterations, keysize, saltHex, parametersHex);
        });
SOSCoderStatus
SOSCoderResendDH(SOSCoderRef coder, CFErrorRef *error) {
    if(coder->sessRef == NULL) return kSOSCoderDataReturned;
    CFMutableDataRef startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
    SOSCoderStatus result = kSOSCoderFailure;
    require_noerr_quiet(SecOTRSAppendRestartPacket(coder->sessRef, startPacket), exit);
    secnotice("coder", "Resending OTR Start %@", startPacket);
    CFRetainAssign(coder->pendingResponse, startPacket);
    result = kSOSCoderNegotiating;
exit:
    CFReleaseNull(startPacket);
    return result;
}
Exemple #16
0
uint32 CommonBlob::getCurrentVersionForDb(const char* dbName) {
    // Currently, the scheme is as follows:
    //   in ~/Library/Keychains:
    //     version_partition
    //   Elsewhere:
    //     version_MacOS_10_0`

    if(pathInHomeLibraryKeychains(dbName)) {
        return CommonBlob::getCurrentVersion();
    }

    secnotice("integrity", "outside ~/Library/Keychains/; creating a old-style keychain");
    return version_MacOS_10_0;
}
Exemple #17
0
uint32 CommonBlob::getCurrentVersion() {
    uint32 ret = version_MacOS_10_0;
    // If the integrity protections are turned on, use version_partition.
    // else, use version_MacOS_10_0.
    CFTypeRef integrity = (CFNumberRef)CFPreferencesCopyValue(CFSTR("KeychainIntegrity"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
    if (integrity && CFGetTypeID(integrity) == CFBooleanGetTypeID()) {
        bool integrityProtections = CFBooleanGetValue((CFBooleanRef)integrity);

        if(integrityProtections) {
            secnotice("integrity", "creating a partition keychain; global is on");
            ret = version_partition;
        } else {
            secnotice("integrity", "creating a old-style keychain; global is off");
            ret = version_MacOS_10_0;
        }
    } else {
        secnotice("integrity", "global integrity not set, defaulting to on");
        ret = version_partition;
    }
    CFReleaseSafe(integrity);

    return ret;
}
Exemple #18
0
bool UnixDb::get(const CssmData &key, CssmData &value, int flags) const
{
	Data dKey(key);
	Data val;
	int rc = mDb->get(mDb, &dKey, &val, flags);
	secnotice("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]",
		mDb, key.length(), flags, rc, value.length());
	checkError(rc);
	if (!rc) {
		value = val;
		return true;
	} else
		return false;
}
SOSCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error) {
    CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0);
    SOSCoderStatus result = kSOSCoderDataReturned;
    CFStringRef beginState = NULL;
    CFMutableDataRef encoded = NULL;
    OSStatus otrStatus = 0;

    require_action_quiet(coder->sessRef, errOut,
                         CFStringAppend(action, CFSTR("*** using null coder ***"));
                         result = nullCoder(message, codedMessage));
    beginState = CFCopyDescription(coder->sessRef);
    require_action_quiet(SecOTRSGetIsReadyForMessages(coder->sessRef), errOut,
                         CFStringAppend(action, CFSTR("not ready"));
                         result = kSOSCoderNegotiating);
    require_action_quiet(!coder->waitingForDataPacket, errOut,
                         CFStringAppend(action, CFSTR("waiting for peer to send data packet first"));
                         result = kSOSCoderNegotiating);
    require_action_quiet(encoded = CFDataCreateMutable(kCFAllocatorDefault, 0), errOut,
                         SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, NULL, CFSTR("%@ alloc failed"), clientId);
                         result = kSOSCoderFailure);
    require_noerr_action_quiet(otrStatus = SecOTRSSignAndProtectMessage(coder->sessRef, message, encoded), errOut,
                               SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ cannot protect message: %" PRIdOSStatus), clientId, otrStatus);
                               CFReleaseNull(encoded);
                               result = kSOSCoderFailure);
    *codedMessage = encoded;

errOut:
    // Uber state log
    if (result == kSOSCoderFailure && error && *error)
        CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error);
    secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState,
              SecOTRPacketTypeString(encoded), action, coder->sessRef, SOSCoderString(result));
    CFReleaseSafe(beginState);
    CFRelease(action);

    return result;
}
Exemple #20
0
//
// Main driver
//
int main(int argc, char *argv[])
{
	// clear the umask - we know what we're doing
	secnotice("SS", "starting umask was 0%o", ::umask(0));
	::umask(0);

	// tell the keychain (client) layer to turn off the server interface
	SecKeychainSetServerMode();
	
	// program arguments (preset to defaults)
	bool debugMode = false;
	const char *bootstrapName = NULL;
	const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName;
	bool doFork = false;
	bool reExecute = false;
	int workerTimeout = 0;
	int maxThreads = 0;
	bool waitForClients = true;
    bool mdsIsInstalled = false;
	const char *tokenCacheDir = "/var/db/TokenCache";
	const char *smartCardOptions = getenv("SMARTCARDS");
	uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
	unsigned int verbose = 0;
	
	// check for the Installation-DVD environment and modify some default arguments if found
	if (access("/etc/rc.cdrom", F_OK) == 0) {	// /etc/rc.cdrom exists
        secnotice("SS", "starting in installmode");
		smartCardOptions = "off";	// needs writable directories that aren't
	}

	// parse command line arguments
	extern char *optarg;
	extern int optind;
	int arg;
	while ((arg = getopt(argc, argv, "c:dE:imN:s:t:T:uvWX")) != -1) {
		switch (arg) {
		case 'c':
			tokenCacheDir = optarg;
			break;
		case 'd':
			debugMode = true;
			break;
        case 'E':
            /* was entropyFile, kept to preserve ABI */
            break;
		case 'i':
			keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID;
			break;
        case 'm':
            mdsIsInstalled = true;
            break;
		case 'N':
			bootstrapName = optarg;
			break;
		case 's':
			smartCardOptions = optarg;
			break;
		case 't':
			if ((maxThreads = atoi(optarg)) < 0)
				maxThreads = 0;
			break;
		case 'T':
			if ((workerTimeout = atoi(optarg)) < 0)
				workerTimeout = 0;
			break;
		case 'W':
			waitForClients = false;
			break;
		case 'u':
			keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
			break;
		case 'v':
			verbose++;
			break;
		case 'X':
			doFork = true;
			reExecute = true;
			break;
		default:
			usage(argv[0]);
		}
	}
	
	// take no non-option arguments
	if (optind < argc)
		usage(argv[0]);
	
	// figure out the bootstrap name
    if (!bootstrapName) {
		bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV);
		if (!bootstrapName)
		{
			bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME;
		}
		else
		{
			messagingName = bootstrapName;
		}
	}
	else
	{
		messagingName = bootstrapName;
	}
	
	// configure logging first
	if (debugMode) {
		Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR);
		Syslog::notice("%s started in debug mode", argv[0]);
	} else {
		Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS);
	}
    
    // if we're not running as root in production mode, fail
    // in debug mode, issue a warning
    if (uid_t uid = getuid()) {
#if defined(NDEBUG)
        Syslog::alert("Tried to run securityd as user %d: aborted", uid);
        fprintf(stderr, "You are not allowed to run securityd\n");
        exit(1);
#else
        fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid);
#endif //NDEBUG
    }
    
    // turn into a properly diabolical daemon unless debugMode is on
    if (!debugMode && getppid() != 1) {
		if (!Daemon::incarnate(doFork))
			exit(1);	// can't daemonize
		
		if (reExecute && !Daemon::executeSelf(argv))
			exit(1);	// can't self-execute
	}
        
    // arm signal handlers; code below may generate signals we want to see
    if (signal(SIGCHLD, handleSignals) == SIG_ERR
		|| signal(SIGINT, handleSignals) == SIG_ERR
		|| signal(SIGTERM, handleSignals) == SIG_ERR
		|| signal(SIGPIPE, handleSignals) == SIG_ERR
#if !defined(NDEBUG)
		|| signal(SIGUSR1, handleSignals) == SIG_ERR
#endif //NDEBUG
		|| signal(SIGUSR2, handleSignals) == SIG_ERR) {
		perror("signal");
		exit(1);
	}

	// introduce all supported ACL subject types
	new AnyAclSubject::Maker();
	new PasswordAclSubject::Maker();
    new ProtectedPasswordAclSubject::Maker();
    new PromptedAclSubject::Maker();
	new ThresholdAclSubject::Maker();
	new CommentAclSubject::Maker();
 	new ProcessAclSubject::Maker();
	new CodeSignatureAclSubject::Maker();
	new KeychainPromptAclSubject::Maker(keychainAclDefault);
	new PartitionAclSubject::Maker();
	new PreAuthorizationAcls::OriginMaker();
    new PreAuthorizationAcls::SourceMaker();

    // establish the code equivalents database
    CodeSignatures codeSignatures;

    // create the main server object and register it
 	Server server(codeSignatures, bootstrapName);

    // Remember the primary service port to send signal events to
    gMainServerPort = server.primaryServicePort();

    // set server configuration from arguments, if specified
	if (workerTimeout)
		server.timeout(workerTimeout);
	if (maxThreads)
		server.maxThreads(maxThreads);
	server.floatingThread(true);
	server.waitForClients(waitForClients);
	server.verbosity(verbose);
    
	// create a smartcard monitor to manage external token devices
	gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions));
    
    // create the RootSession object (if -d, give it graphics and tty attributes)
    RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server);
	
	// create a monitor thread to watch for audit session events
	AuditMonitor audits(gMainServerPort);
	audits.run();
    
    // install MDS (if needed) and initialize the local CSSM
    server.loadCssm(mdsIsInstalled);
    
	// create the shared memory notification hub
#ifndef __clang_analyzer__
	new SharedMemoryListener(messagingName, kSharedMemoryPoolSize);
#endif // __clang_analyzer__

	// okay, we're ready to roll
    secnotice("SS", "Entering service as %s", (char*)bootstrapName);
	Syslog::notice("Entering service");
    
	// go
	server.run();
	
	// fell out of runloop (should not happen)
	Syslog::alert("Aborting");
    return 1;
}
Exemple #21
0
//
// Handle signals.
// We send ourselves a message (through the "self" service), so actual
// actions happen on the normal event loop path. Note that another thread
// may be picking up the message immediately.
//
static void handleSignals(int sig)
{
    secnotice("SS", "signal received: %d", sig);
	if (kern_return_t rc = self_client_handleSignal(gMainServerPort, mach_task_self(), sig))
		Syslog::error("self-send failed (mach error %d)", rc);
}
//
// Change the session of a process.
// This is the result of SessionCreate from a known process client.
//
void Process::changeSession(Session::SessionId sessionId)
{
	// re-parent
	parent(Session::find(sessionId, true));
    secnotice("SS", "%p client change session to %d", this, this->session().sessionId());
}
SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutableDataRef *message,
                              CFStringRef clientId, CFErrorRef *error) {
    if(codedMessage == NULL) return kSOSCoderDataReturned;
    if(coder->sessRef == NULL) return nullCoder(codedMessage, message);
    CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0);
    /* This should be the "normal" case.  We just use OTR to unwrap the received message. */
    SOSCoderStatus result = kSOSCoderFailure;

    CFStringRef beginState = CFCopyDescription(coder->sessRef);
    enum SecOTRSMessageKind kind = SecOTRSGetMessageKind(coder->sessRef, codedMessage);

    switch (kind) {
        case kOTRNegotiationPacket: {
            /* If we're in here we haven't completed negotiating a session.  Use SecOTRSProcessPacket() to go through
             the negotiation steps and immediately send a reply back if necessary using the sendBlock.  This
             assumes the sendBlock is still available.
             */
            CFMutableDataRef response = CFDataCreateMutable(kCFAllocatorDefault, 0);
            OSStatus ppstatus = errSecSuccess;
            if (response) {
                switch (ppstatus = SecOTRSProcessPacket(coder->sessRef, codedMessage, response)) {
                    case errSecSuccess:
                        if (CFDataGetLength(response) > 1) {
                            CFStringAppendFormat(action, NULL, CFSTR("Sending OTR Response %s"), SecOTRPacketTypeString(response));
                            CFRetainAssign(coder->pendingResponse, response);
                            result = kSOSCoderNegotiating;
                            if (SecOTRSGetIsReadyForMessages(coder->sessRef)) {
                                CFStringAppend(action, CFSTR(" begin waiting for data packet"));
                                coder->waitingForDataPacket = true;
                            }
                        } else if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) {
                            CFStringAppend(action, CFSTR("stuck?"));
                            result = kSOSCoderNegotiating;
                        } else {
                            CFStringAppend(action, CFSTR("completed negotiation"));
                            result = kSOSCoderNegotiationCompleted;
                            coder->waitingForDataPacket = false;
                        }
                        break;
                    case errSecDecode:
                        CFStringAppend(action, CFSTR("resending dh"));
                        result = SOSCoderResendDH(coder, error);
                        break;
                    default:
                        SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus);
                        result = kSOSCoderFailure;
                        break;
                };
            } else {
                SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot allocate CFData"), clientId);
                result = kSOSCoderFailure;
            }
            
            CFReleaseNull(response);
            
            break;
        }

        case kOTRDataPacket:
            if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) {
                CFStringAppend(action, CFSTR("not ready, resending DH packet"));
				SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1);
                CFStringAppend(action, CFSTR("not ready for data; resending dh"));
                result = SOSCoderResendDH(coder, error);
            } else {
                if (coder->waitingForDataPacket) {
                    CFStringAppend(action, CFSTR("got data packet we were waiting for "));
                    coder->waitingForDataPacket = false;
                }
                CFMutableDataRef exposed = CFDataCreateMutable(0, 0);
                OSStatus otrResult = SecOTRSVerifyAndExposeMessage(coder->sessRef, codedMessage, exposed);
                CFStringAppend(action, CFSTR("verify and expose message"));
                if (otrResult) {
                    if (otrResult == errSecOTRTooOld) {
                        CFStringAppend(action, CFSTR(" too old"));
                        result = kSOSCoderStaleEvent;
                    } else {
                        SecError(otrResult, error, CFSTR("%@ Cannot expose message: %" PRIdOSStatus), clientId, otrResult);
                        secerror("%@ Decode OTR Protected Packet: %@", clientId, error ? *error : NULL);
                        result = kSOSCoderFailure;
                    }
                } else {
                    CFStringAppend(action, CFSTR("decoded OTR protected packet"));
                    *message = exposed;
                    exposed = NULL;
                    result = kSOSCoderDataReturned;
                }
                CFReleaseNull(exposed);
            }
            break;

        default:
            secerror("%@ Unknown packet type: %@", clientId, codedMessage);
            SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Unknown packet type"), (error != NULL) ? *error : NULL, error);
            result = kSOSCoderFailure;
            break;
    };

    // Uber state log
    if (result == kSOSCoderFailure && error && *error)
        CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error);
    secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState,
              SecOTRPacketTypeString(codedMessage), action, coder->sessRef, SOSCoderString(result));
    CFReleaseSafe(beginState);
    CFRelease(action);

    return result;
}
Exemple #24
0
void UnixDb::erase(const CssmData &key, int flags)
{
	Data dKey(key);
	secnotice("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags);
	checkError(mDb->del(mDb, &dKey, flags));
}
SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error)
{
    size_t saltlen;
    const uint8_t *salt = NULL;

    size_t iterations = 0;
    size_t keysize = 0;

    const uint8_t *der = CFDataGetBytePtr(parameters);
    const uint8_t *der_end = der + CFDataGetLength(parameters);

    der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end);

    if (der == NULL) {
        SOSCreateErrorWithFormat(kSOSErrorDecodeFailure, NULL, error, NULL,
                                 CFSTR("Bad paramter encoding, got: %@"), parameters);
        return NULL;
    }
    if (keysize != 256) {
        SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
                                 CFSTR("Key size not supported, requested %zd."), keysize);
        return NULL;
    }
    if (saltlen < 4) {
        SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
                                 CFSTR("Salt length not supported, requested %zd."), saltlen);
        return NULL;
    }
    if (iterations < ITERATIONMIN) {
        SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL,
                                 CFSTR("Too few iterations, params suggested %zd."), iterations);
        return NULL;
    }

    const uint8_t *password_bytes = CFDataGetBytePtr(password);
    size_t password_length = CFDataGetLength(password);

    const size_t maxbytes = 128;

    ccec_const_cp_t cp = ccec_get_cp(keysize);
    struct ccrng_pbkdf2_prng_state pbkdf2_prng;

    ccec_full_ctx_decl_cp(cp, tmpkey);

    secnotice("keygen", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters);

    if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes,
                                password_length, password_bytes,
                                saltlen, salt,
                                iterations)) {
        SOSCreateError(kSOSErrorProcessingFailure, CFSTR("prng init failed"), NULL, error);
        return NULL;
    }

    if (ccec_generate_key(cp, (struct ccrng_state *)&pbkdf2_prng, tmpkey)) {
        SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Keygen failed"), NULL, error);
        return NULL;
    }


    return ccec2SecKey(tmpkey);
}