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;
}
// 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;
}
SharedMemoryListener::SharedMemoryListener(const char* segmentName, SegmentOffsetType segmentSize, uid_t uid, gid_t gid) :
	Listener (kNotificationDomainAll, kNotificationAllEvents),
	SharedMemoryServer (segmentName, segmentSize, uid, gid),
	mActive (false)
{
	if (segmentName == NULL)
	{
		secerror("Attempted to start securityd with a NULL segmentName");
        abort();
	}
}
示例#4
0
bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) {
    
    SOSEnginePeerMessageSentBlock sent = NULL;
    CFDataRef message_to_send = NULL;
    bool ok = false;
    SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id);
    CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id);
    require(coderData, fail);
    
    SOSCoderRef coder = SOSCoderCreateFromData(coderData, error);
    require(coder, fail);
    SOSPeerSetCoder(peer, coder);
    
    ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circle_id, peer_id, &sent, error);
    coder = SOSPeerGetCoder(peer);
    
    if (message_to_send)    {
        CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                                 peer_id, message_to_send,
                                                                 NULL);
        CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                                    circle_id, peer_dict,
                                                                    NULL);
        
        ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error);
        
        SOSPeerCoderConsume(&sent, ok);
        
        CFReleaseSafe(peer_dict);
        CFReleaseSafe(circle_peers);
    }
    
    
    Block_release(sent);
    
    
    CFReleaseSafe(message_to_send);
    
    coderData = SOSCoderCopyDER(coder, error);
    
    if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error)){
        secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state");
    }
    CFReleaseNull(coderData);
    
    if (coder)
        SOSCoderDispose(coder);
    
fail:
    CFReleaseNull(peer);
    return ok;
}
static const char * get_host_uuid()
{
    static uuid_string_t hostuuid = {};
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        struct timespec timeout = {30, 0};
        uuid_t uuid = {};
        if (gethostuuid(uuid, &timeout) == 0) {
            uuid_unparse(uuid, hostuuid);
        } else {
            secerror("failed to get host uuid");
        }
    });
static bool postIDTimestamp(dispatch_queue_t theq, dispatch_group_t dgroup)
{
    bool result = false;
    CFStringRef macaddr = myMacAddress();
    CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
    const char *nowstr = cfabsoluteTimeToStringLocal(now);
    CFStringRef cfidstr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@: %@  %s"), kTestKeyIDTimestamp, macaddr ,nowstr);
    secerror("Setting %@ key: %@", kTestKeyIDTimestamp, cfidstr);
    result = testPostGet(kTestKeyIDTimestamp, cfidstr, theq, dgroup);

    if (nowstr)
        free((void *)nowstr);
    CFReleaseSafe(cfidstr);
    return result;
}
static void handle_server_response(CFReadStreamRef stream,
    CFStreamEventType type, void *info) {
    asynchttp_t *http = (asynchttp_t *)info;
    if (!http->stream) {
        secerror("Avoiding crash due to CFReadStream invoking us after we called CFReadStreamSetDispatchQueue(stream, NULL) on a different block on our serial queue");
        return;
    }

    switch (type) {
    case kCFStreamEventHasBytesAvailable:
    {
        UInt8 buffer[POST_BUFSIZE];
        CFIndex length;
        do {
#if 1
            length = CFReadStreamRead(stream, buffer, sizeof(buffer));
#else
            const UInt8 *buffer = CFReadStreamGetBuffer(stream, -1, &length);
#endif
            secdebug("http",
                "stream: %@ kCFStreamEventHasBytesAvailable read: %lu bytes",
                stream, length);
            if (length < 0) {
                /* Negative length == error */
                asynchttp_complete(http);
                break;
            } else if (length > 0) {
                //CFHTTPMessageAppendBytes(http->response, buffer, length);
                CFDataAppendBytes(http->data, buffer, length);
            } else {
                /* Read 0 bytes, are we are done or do we wait for
                   kCFStreamEventEndEncountered? */
                asynchttp_complete(http);
                break;
            }
        } while (CFReadStreamHasBytesAvailable(stream));
        break;
    }
    case kCFStreamEventErrorOccurred:
    {
        CFStreamError error = CFReadStreamGetError(stream);

        secdebug("http",
            "stream: %@ kCFStreamEventErrorOccurred domain: %ld error: %ld",
            stream, error.domain, (long) error.error);

        if (error.domain == kCFStreamErrorDomainPOSIX) {
            ocspdErrorLog("CFReadStream posix: %s", strerror(error.error));
        } else if (error.domain == kCFStreamErrorDomainMacOSStatus) {
            ocspdErrorLog("CFReadStream osstatus: %"PRIstatus, error.error);
        } else {
            ocspdErrorLog("CFReadStream domain: %ld error: %"PRIstatus,
                error.domain, error.error);
        }
        asynchttp_complete(http);
        break;
    }
    case kCFStreamEventEndEncountered:
    {
        http->response = (CFHTTPMessageRef)CFReadStreamCopyProperty(
            stream, kCFStreamPropertyHTTPResponseHeader);
        secdebug("http", "stream: %@ kCFStreamEventEndEncountered hdr: %@",
            stream, http->response);
        CFHTTPMessageSetBody(http->response, http->data);
        asynchttp_complete(http);
        break;
    }
    default:
        ocspdErrorLog("handle_server_response unexpected event type: %lu",
            type);
        break;
    }
}
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;
}