Пример #1
0
    void TCPStream_CFNetwork::secure() {
        if (state != Stream::State::Open) {
            return;
        }

        state = Stream::State::OpenAndSecuring;

        OSStatus status = noErr;

        secureLayerContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);

        status = SSLSetConnection(secureLayerContext, reinterpret_cast<SSLConnectionRef>(this));
        if (status != noErr) {
            handleSecuringFailedEvent();
            return;
        }

        status = SSLSetIOFuncs(secureLayerContext,
                                        TCPStream_CFNetwork::secureTransportReadCallback,
                                        TCPStream_CFNetwork::secureTransportWriteCallback);
        if (status != noErr) {
            handleSecuringFailedEvent();
            return;
        }

        status = SSLSetPeerDomainName(secureLayerContext, domainName.c_str(), domainName.size());
        if (status != noErr) {
            handleSecuringFailedEvent();
            return;
        }

        do {
            status = SSLHandshake(secureLayerContext);
        } while (status == errSSLWouldBlock);

        switch (status) {
            default:
                //TODO: Log this!
                handleSecuringFailedEvent();
                return;
            case errSSLFatalAlert:
                handleSecuringFailedEvent();
                return;
            case errSSLUnknownRootCert:
            case errSSLNoRootCert:
            case errSSLCertExpired:
            case errSSLXCertChainInvalid:
                //TODO: The UI (if any) should probably ask what to do instead of simply failing.
                handleSecuringFailedEvent();
                return;
            case errSSLClientCertRequested:
                //TODO: The App should supply this.  Add an event handler.
                handleSecuringFailedEvent();
                return;
            case noErr:
                state = Stream::State::OpenAndSecured;
                handleSecuredEvent();
                return;
        }
    }
Пример #2
0
BOOL schan_imp_create_session(schan_imp_session *session, BOOL is_server,
                              schan_imp_certificate_credentials cred)
{
    struct mac_session *s;
    OSStatus status;

    TRACE("(%p, %d)\n", session, is_server);

    s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
    if (!s)
        return FALSE;

    status = SSLNewContext(is_server, &s->context);
    if (status != noErr)
    {
        ERR("Failed to create session context: %ld\n", (long)status);
        goto fail;
    }

    status = SSLSetConnection(s->context, s);
    if (status != noErr)
    {
        ERR("Failed to set session connection: %ld\n", (long)status);
        goto fail;
    }

    status = SSLSetEnableCertVerify(s->context, FALSE);
    if (status != noErr)
    {
        ERR("Failed to disable certificate verification: %ld\n", (long)status);
        goto fail;
    }

    status = SSLSetProtocolVersionEnabled(s->context, kSSLProtocol2, FALSE);
    if (status != noErr)
    {
        ERR("Failed to disable SSL version 2: %ld\n", (long)status);
        goto fail;
    }

    status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
    if (status != noErr)
    {
        ERR("Failed to set session I/O funcs: %ld\n", (long)status);
        goto fail;
    }

    TRACE("    -> %p/%p\n", s, s->context);

    *session = (schan_imp_session)s;
    return TRUE;

fail:
    HeapFree(GetProcessHeap(), 0, s);
    return FALSE;
}
Пример #3
0
int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
{
	stransport_stream *st;
	int error;
	OSStatus ret;

	assert(out && host);

	st = git__calloc(1, sizeof(stransport_stream));
	GITERR_CHECK_ALLOC(st);

#ifdef GIT_CURL
	error = git_curl_stream_new(&st->io, host, port);
#else
	error = git_socket_stream_new(&st->io, host, port);
#endif

	if (error < 0){
		git__free(st);
		return error;
	}

	st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
	if (!st->ctx) {
		giterr_set(GITERR_NET, "failed to create SSL context");
		git__free(st);
		return -1;
	}

	if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr ||
	    (ret = SSLSetConnection(st->ctx, st->io)) != noErr ||
	    (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr ||
	    (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr ||
	    (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr ||
	    (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
		CFRelease(st->ctx);
		git__free(st);
		return stransport_error(ret);
	}

	st->parent.version = GIT_STREAM_VERSION;
	st->parent.encrypted = 1;
	st->parent.proxy_support = git_stream_supports_proxy(st->io);
	st->parent.connect = stransport_connect;
	st->parent.certificate = stransport_certificate;
	st->parent.set_proxy = stransport_set_proxy;
	st->parent.read = stransport_read;
	st->parent.write = stransport_write;
	st->parent.close = stransport_close;
	st->parent.free = stransport_free;

	*out = (git_stream *) st;
	return 0;
}
static SSLContextRef make_ssl_ref(bool server, int sock, CFArrayRef certs)
{
    SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType);
    require(ctx, out);

    require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
    require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
    require_noerr(SSLSetCertificate(ctx, certs), out);

    return ctx;
out:
    if (ctx)
        CFRelease(ctx);
    return NULL;
}
static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, Boolean false_start)
{
    SSLContextRef ctx = NULL;

    require_noerr(SSLNewContext(false, &ctx), out);
    require_noerr(SSLSetIOFuncs(ctx,
                                (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
    require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);

    require_noerr(SSLSetSessionOption(ctx,
                                      kSSLSessionOptionBreakOnServerAuth, true), out);
    
    require_noerr(SSLSetSessionOption(ctx,
                                      kSSLSessionOptionFalseStart, false_start), out);

    require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);

    return ctx;
out:
    if (ctx)
        SSLDisposeContext(ctx);
    return NULL;
}
static int test_GetEnabledCiphers(SSLContextRef ssl)
{
    size_t max_ciphers = 0;
    int fail=1;
    SSLCipherSuite *ciphers = NULL;
    OSStatus err;

    err=SSLSetIOFuncs(ssl, &SocketRead, &SocketWrite);
    err=SSLSetConnection(ssl, NULL);
    err=SSLHandshake(ssl);

    require_noerr(SSLGetNumberEnabledCiphers(ssl, &max_ciphers), out);

    size_t size = max_ciphers * sizeof (SSLCipherSuite);
    ciphers = (SSLCipherSuite *) malloc(size);

    require_string(ciphers, out, "out of memory");
    memset(ciphers, 0xff, size);

    size_t num_ciphers = max_ciphers;
    require_noerr(SSLGetEnabledCiphers(ssl, ciphers, &num_ciphers), out);

    for (size_t i = 0; i < num_ciphers; i++) {
        char csname[256];
        snprintf(csname, 256, "(%04x) %s", ciphers[i], ciphersuite_name(ciphers[i]));
        /* Uncomment the next line if you want to list the default enabled ciphers */
        //printf("%s\n", csname);
        require_string(allowed_default_ciphers(ciphers[i]), out, csname);
    }

    /* Success! */
    fail=0;

out:
    if(ciphers) free(ciphers);
    return fail;
}
Пример #7
0
/**
 * Initializes a client-side TLS session.
 */
static int st_ClientSessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session,
                                 int fd, const char *hostname) {
    msg_Dbg(session, "open TLS session for %s", hostname);

    vlc_tls_sys_t *sys = malloc (sizeof (*session->sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    sys->p_cred = crd->sys;
    sys->i_fd = fd;
    sys->b_handshaked = false;
    sys->b_blocking_send = false;
    sys->i_send_buffered_bytes = 0;

    session->sys = sys;
    session->sock.p_sys = session;
    session->sock.pf_send = st_Send;
    session->sock.pf_recv = st_Recv;
    session->handshake = st_Handshake;

    SSLContextRef p_context = NULL;
#if TARGET_OS_IPHONE
    p_context = SSLCreateContext (NULL, kSSLClientSide, kSSLStreamType);
    if(p_context == NULL) {
        msg_Err(session, "cannot create ssl context");
        goto error;
    }
#else
    if (SSLNewContext (false, &p_context) != noErr) {
        msg_Err(session, "error calling SSLNewContext");
        goto error;
    }
#endif

    sys->p_context = p_context;

    OSStatus ret = SSLSetIOFuncs (p_context, st_SocketReadFunc, st_SocketWriteFunc);
    if(ret != noErr) {
        msg_Err(session, "cannot set io functions");
        goto error;
    }

    ret = SSLSetConnection (p_context, session);
    if(ret != noErr) {
        msg_Err(session, "cannot set connection");
        goto error;
    }

    ret = SSLSetPeerDomainName (p_context, hostname, strlen(hostname));
    if(ret != noErr) {
        msg_Err(session, "cannot set peer domain name");
        goto error;
    }

    /* disable automatic validation. We do so manually to also handle invalid
       certificates */

    /* this has effect only on iOS 5 and OSX 10.8 or later ... */
    SSLSetSessionOption (sys->p_context, kSSLSessionOptionBreakOnServerAuth, true);
#if !TARGET_OS_IPHONE
    /* ... thus calling this for earlier osx versions, which is not available on iOS in turn */
    SSLSetEnableCertVerify (sys->p_context, false);
#endif

    return VLC_SUCCESS;

error:
    st_ClientSessionClose(crd, session);
    return VLC_EGENERIC;
}
Пример #8
0
static OSStatus sslServe(
	otSocket				listenSock,
	SSLProtocol				tryVersion,
	const char				*hostName,			// e.g., "www.amazon.com"
	CFArrayRef				serverCerts,		// required
	CFArrayRef				encryptServerCerts,	// optional
	CSSM_BOOL				allowExpired,
	CSSM_BOOL				allowAnyRoot,
	char					cipherRestrict,		// '2', 'd'. etc...'\0' for no
												//   restriction
	SSLAuthenticate			authenticate,
	CSSM_BOOL				resumableEnable,
	CSSM_BOOL				silent,				// no stdout
	CSSM_BOOL				pause,
	SSLProtocol				*negVersion,		// RETURNED
	SSLCipherSuite			*negCipher,			// RETURNED
	CFArrayRef				*peerCerts)			// mallocd & RETURNED
{
	otSocket			acceptSock;
    PeerSpec            peerId;
    OSStatus            ortn;
    SSLContextRef       ctx = NULL;
    UInt32              length;
    uint8               rcvBuf[RCV_BUF_SIZE];
	char *outMsg = SERVER_MESSAGE;
	
    *negVersion = kSSLProtocolUnknown;
    *negCipher = SSL_NULL_WITH_NULL_NULL;
    *peerCerts = NULL;
    
	#if IGNORE_SIGPIPE
	signal(SIGPIPE, sigpipe);
	#endif
	
	/* first wait for a connection */
	if(!silent) {
		printf("Waiting for client connection...");
		fflush(stdout);
	}
	ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId);
    if(ortn) {
    	printf("AcceptClientConnection returned %d; aborting\n", ortn);
    	return ortn;
    }

	/* 
	 * Set up a SecureTransport session.
	 * First the standard calls.
	 */
	ortn = SSLNewContext(true, &ctx);
	if(ortn) {
		printSslErrStr("SSLNewContext", ortn);
		goto cleanup;
	} 
	ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
	if(ortn) {
		printSslErrStr("SSLSetIOFuncs", ortn);
		goto cleanup;
	} 
	ortn = SSLSetProtocolVersion(ctx, tryVersion);
	if(ortn) {
		printSslErrStr("SSLSetProtocolVersion", ortn);
		goto cleanup;
	} 
	ortn = SSLSetConnection(ctx, acceptSock);
	if(ortn) {
		printSslErrStr("SSLSetConnection", ortn);
		goto cleanup;
	}
	ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1);
	if(ortn) {
		printSslErrStr("SSLSetPeerDomainName", ortn);
		goto cleanup;
	}
	
	/* have to do these options befor setting server certs */
	if(allowExpired) {
		ortn = SSLSetAllowsExpiredCerts(ctx, true);
		if(ortn) {
			printSslErrStr("SSLSetAllowExpiredCerts", ortn);
			goto cleanup;
		}
	}
	if(allowAnyRoot) {
		ortn = SSLSetAllowsAnyRoot(ctx, true);
		if(ortn) {
			printSslErrStr("SSLSetAllowAnyRoot", ortn);
			goto cleanup;
		}
	}

	ortn = SSLSetCertificate(ctx, serverCerts);
	if(ortn) {
		printSslErrStr("SSLSetCertificate", ortn);
		goto cleanup;
	}
	if(encryptServerCerts) {
		ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts);
		if(ortn) {
			printSslErrStr("SSLSetEncryptionCertificate", ortn);
			goto cleanup;
		}
	}
	
	/* 
	 * SecureTransport options.
	 */ 
	if(resumableEnable) {
		ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
		if(ortn) {
			printSslErrStr("SSLSetPeerID", ortn);
			goto cleanup;
		}
	}
	if(cipherRestrict != '\0') {
		ortn = setCipherRestrictions(ctx, cipherRestrict);
		if(ortn) {
			goto cleanup;
		}
	}
	#if AUTHENTICATE_ENABLE
	if(authenticate != kNeverAuthenticate) {
		ortn = SSLSetClientSideAuthenticate(ctx, authenticate);
		if(ortn) {
			printSslErrStr("SSLSetClientSideAuthenticate", ortn);
			goto cleanup;
		}
	}
	#endif
	if(pause) {
		doPause("SSLContext initialized");
	}
	
	/* Perform SSL/TLS handshake */
    do
    {   ortn = SSLHandshake(ctx);
	    if((ortn == errSSLWouldBlock) && !silent) {
	    	/* keep UI responsive */ 
	    	outputDot();
	    }
    } while (ortn == errSSLWouldBlock);
	
	/* this works even if handshake failed due to cert chain invalid */
	copyPeerCerts(ctx, peerCerts);

	SSLGetNegotiatedCipher(ctx, negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, negVersion);
	
	if(!silent) {
		printf("\n");
	}
    if(ortn) {
    	goto cleanup;
    }
	if(pause) {
		doPause("SSLContext handshake complete");
	}

	/* wait for one complete line or user says they've had enough */
	while(ortn == noErr) {
	    length = sizeof(rcvBuf);
	    ortn = SSLRead(ctx, rcvBuf, length, &length);
	    if(length == 0) {
	    	/* keep UI responsive */ 
	    	outputDot();
	    }
	    else {
	    	/* print what we have */
	    	printf("client request: ");
	    	dumpAscii(rcvBuf, length);
	    }
	    if(pause) {
	    	/* allow user to bail */
	    	char resp;
	    	
			fpurge(stdin);
	    	printf("\nMore client request (y/anything): ");
	    	resp = getchar();
	    	if(resp != 'y') {
	    		break;
	    	}
	    }
	    
	    /* poor person's line completion scan */
	    for(unsigned i=0; i<length; i++) {
	    	if((rcvBuf[i] == '\n') || (rcvBuf[i] == '\r')) {
	    		/* a labelled break would be nice here.... */
	    		goto serverResp;
	    	}
	    }
	    if (ortn == errSSLWouldBlock) {
	        ortn = noErr;
	    }
	}
	
serverResp:
	if(pause) {
		doPause("Client GET msg received");
	}

	/* send out canned response */
	length = strlen(outMsg);
 	ortn = SSLWrite(ctx, outMsg, length, &length);
 	if(ortn) {
 		printSslErrStr("SSLWrite", ortn);
 	}
	if(pause) {
		doPause("Server response sent");
	}
    if (ortn == noErr) {
        ortn = SSLClose(ctx);
	}
cleanup:
	if(acceptSock) {
		endpointShutdown(acceptSock);
	}
	if(ctx) {
	    SSLDisposeContext(ctx);  
	}    
	/* FIXME - dispose of serverCerts */
	return ortn;
}
static OSStatus sslServe(
	otSocket				listenSock,
	unsigned short			portNum,
	SSLProtocol				tryVersion,			// only used if acceptedProts NULL
	const char				*acceptedProts,
	CFArrayRef				serverCerts,		// required
	char					*password,			// optional
	CFArrayRef				encryptServerCerts,	// optional
	bool				allowExpired,
	bool				allowAnyRoot,
	bool				allowExpiredRoot,
	bool				disableCertVerify,
	char					*anchorFile,
	bool				replaceAnchors,
	char					cipherRestrict,		// '2', 'd'. etc...'\0' for no
												//   restriction
	SSLAuthenticate			authenticate,
	unsigned char			*dhParams,			// optional D-H parameters	
	unsigned				dhParamsLen,
	CFArrayRef				acceptableDNList,	// optional 
	bool				resumableEnable,
	uint32_t					sessionCacheTimeout,// optional
	bool				disableAnonCiphers,
	bool				silent,				// no stdout
	bool				pause,
	SSLProtocol				*negVersion,		// RETURNED
	SSLCipherSuite			*negCipher,			// RETURNED
	SSLClientCertificateState *certState,		// RETURNED
	Boolean					*sessionWasResumed,	// RETURNED
	unsigned char			*sessionID,			// mallocd by caller, RETURNED
	size_t					*sessionIDLength,	// RETURNED
	CFArrayRef				*peerCerts,			// mallocd & RETURNED
	char					**argv)
{
	otSocket			acceptSock;
    PeerSpec            peerId;
    OSStatus            ortn;
    SSLContextRef       ctx = NULL;
    size_t              length;
    uint8_t             rcvBuf[RCV_BUF_SIZE];
	const char *outMsg = SERVER_MESSAGE;
	
    *negVersion = kSSLProtocolUnknown;
    *negCipher = SSL_NULL_WITH_NULL_NULL;
    *peerCerts = NULL;
    
	#if IGNORE_SIGPIPE
	signal(SIGPIPE, sigpipe);
	#endif
	
	/* first wait for a connection */
	if(!silent) {
		printf("Waiting for client connection on port %u...", portNum);
		fflush(stdout);
	}
	ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId);
    if(ortn) {
    	printf("AcceptClientConnection returned %d; aborting\n", (int)ortn);
    	return ortn;
    }

	/* 
	 * Set up a SecureTransport session.
	 * First the standard calls.
	 */
	ortn = SSLNewContext(true, &ctx);
	if(ortn) {
		printSslErrStr("SSLNewContext", ortn);
		goto cleanup;
	} 
	ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
	if(ortn) {
		printSslErrStr("SSLSetIOFuncs", ortn);
		goto cleanup;
	} 
	ortn = SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)acceptSock);
	if(ortn) {
		printSslErrStr("SSLSetConnection", ortn);
		goto cleanup;
	}
	
	/* have to do these options befor setting server certs */
	if(allowExpired) {
		ortn = SSLSetAllowsExpiredCerts(ctx, true);
		if(ortn) {
			printSslErrStr("SSLSetAllowExpiredCerts", ortn);
			goto cleanup;
		}
	}
	if(allowAnyRoot) {
		ortn = SSLSetAllowsAnyRoot(ctx, true);
		if(ortn) {
			printSslErrStr("SSLSetAllowAnyRoot", ortn);
			goto cleanup;
		}
	}

	if(anchorFile) {
		ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors);
		if(ortn) {
			printf("***Error obtaining anchor file %s\n", anchorFile);
			goto cleanup;
		}
	}
	if(serverCerts != NULL) {
		if(anchorFile == NULL) {
			/* no specific anchors, so assume we want to trust this one */
			ortn = addIdentityAsTrustedRoot(ctx, serverCerts);
			if(ortn) {
				goto cleanup;
			}
		}
		ortn = SSLSetCertificate(ctx, serverCerts);
		if(ortn) {
			printSslErrStr("SSLSetCertificate", ortn);
			goto cleanup;
		}
	}
	if(encryptServerCerts) {
		ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts);
		if(ortn) {
			printSslErrStr("SSLSetEncryptionCertificate", ortn);
			goto cleanup;
		}
	}
	if(allowExpiredRoot) {
		ortn = SSLSetAllowsExpiredRoots(ctx, true);
		if(ortn) {
			printSslErrStr("SSLSetAllowsExpiredRoots", ortn);
			goto cleanup;
		}
	}
	if(disableCertVerify) {
		ortn = SSLSetEnableCertVerify(ctx, false);
		if(ortn) {
			printSslErrStr("SSLSetEnableCertVerify", ortn);
			goto cleanup;
		}
	}
	
	/* 
	 * SecureTransport options.
	 */ 
	if(acceptedProts) {
		ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
		if(ortn) {
			printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
			goto cleanup;
		}
		for(const char *cp = acceptedProts; *cp; cp++) {
			SSLProtocol prot = kSSLProtocolUnknown;
			switch(*cp) {
				case '2':
					prot = kSSLProtocol2;
					break;
				case '3':
					prot = kSSLProtocol3;
					break;
				case 't':
					prot = kTLSProtocol1;
					break;
				default:
					usage(argv);
			}
			ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
			if(ortn) {
				printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
				goto cleanup;
			}
		}
	}
	else {
		ortn = SSLSetProtocolVersion(ctx, tryVersion);
		if(ortn) {
			printSslErrStr("SSLSetProtocolVersion", ortn);
			goto cleanup;
		} 
	}
	if(resumableEnable) {
		ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
		if(ortn) {
			printSslErrStr("SSLSetPeerID", ortn);
			goto cleanup;
		}
	}
	if(cipherRestrict != '\0') {
		ortn = sslSetCipherRestrictions(ctx, cipherRestrict);
		if(ortn) {
			goto cleanup;
		}
	}
	if(authenticate != kNeverAuthenticate) {
		ortn = SSLSetClientSideAuthenticate(ctx, authenticate);
		if(ortn) {
			printSslErrStr("SSLSetClientSideAuthenticate", ortn);
			goto cleanup;
		}
	}
	if(dhParams) {
		ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen);
		if(ortn) {
			printSslErrStr("SSLSetDiffieHellmanParams", ortn);
			goto cleanup;
		}
	}
	if(sessionCacheTimeout) {
		ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout);
		if(ortn) {
			printSslErrStr("SSLSetSessionCacheTimeout", ortn);
			goto cleanup;
		}
	}
	if(disableAnonCiphers) {
		ortn = SSLSetAllowAnonymousCiphers(ctx, false);
		if(ortn) {
			printSslErrStr("SSLSetAllowAnonymousCiphers", ortn);
			goto cleanup;
		}
		/* quickie test of the getter */
		Boolean e;
		ortn = SSLGetAllowAnonymousCiphers(ctx, &e);
		if(ortn) {
			printSslErrStr("SSLGetAllowAnonymousCiphers", ortn);
			goto cleanup;
		}
		if(e) {
			printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n");
			ortn = errSecIO;
			goto cleanup;
		}
	}
/* XXX/cs
	if(acceptableDNList) {
		ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE);
		if(ortn) {
			printSslErrStr("SSLSetCertificateAuthorities", ortn);
			goto cleanup;
		}
	}
*/
	/* end options */

	if(pause) {
		doPause("SSLContext initialized");
	}
	
	/* Perform SSL/TLS handshake */
    do
    {   ortn = SSLHandshake(ctx);
	    if((ortn == errSSLWouldBlock) && !silent) {
	    	/* keep UI responsive */ 
	    	sslOutputDot();
	    }
    } while (ortn == errSSLWouldBlock);
	
	/* this works even if handshake failed due to cert chain invalid */
	copyPeerCerts(ctx, peerCerts);

	SSLGetClientCertificateState(ctx, certState);
	SSLGetNegotiatedCipher(ctx, negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, negVersion);
	*sessionIDLength = MAX_SESSION_ID_LENGTH;
	SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID,
		sessionIDLength);
	
	if(!silent) {
		printf("\n");
	}
    if(ortn) {
    	goto cleanup;
    }
	if(pause) {
		doPause("SSLContext handshake complete");
	}

	/* wait for one complete line or user says they've had enough */
	while(ortn == errSecSuccess) {
	    length = sizeof(rcvBuf);
	    ortn = SSLRead(ctx, rcvBuf, length, &length);
	    if(length == 0) {
	    	/* keep UI responsive */ 
	    	sslOutputDot();
	    }
	    else {
	    	/* print what we have */
	    	printf("client request: ");
	    	dumpAscii(rcvBuf, length);
	    }
	    if(pause) {
	    	/* allow user to bail */
	    	char resp;
	    	
			fpurge(stdin);
	    	printf("\nMore client request (y/anything): ");
	    	resp = getchar();
	    	if(resp != 'y') {
	    		break;
	    	}
	    }
	    
	    /* poor person's line completion scan */
	    for(unsigned i=0; i<length; i++) {
	    	if((rcvBuf[i] == '\n') || (rcvBuf[i] == '\r')) {
	    		/* a labelled break would be nice here.... */
	    		goto serverResp;
	    	}
	    }
	    if (ortn == errSSLWouldBlock) {
	        ortn = errSecSuccess;
	    }
	}
	
serverResp:
	if(pause) {
		doPause("Client GET msg received");
	}

	/* send out canned response */
	length = strlen(outMsg);
 	ortn = SSLWrite(ctx, outMsg, length, &length);
 	if(ortn) {
 		printSslErrStr("SSLWrite", ortn);
 	}
	if(pause) {
		doPause("Server response sent");
	}
cleanup:
	/*
	 * always do close, even on error - to flush outgoing write queue 
	 */
	OSStatus cerr = SSLClose(ctx);
	if(ortn == errSecSuccess) {
		ortn = cerr;
	}
	if(acceptSock) {
		endpointShutdown(acceptSock);
	}
	if(ctx) {
	    SSLDisposeContext(ctx);  
	}    
	/* FIXME - dispose of serverCerts */
	return ortn;
}
Пример #10
0
/*
 * params->lock is held for us by runSession() - we use it as a semapahore by
 * unlocking it when we've created a port to listen on. 
 * This is generally run from a thread via sslRunSession() and 
 * sslServerThread() in sslAppUtils.cpp. 
 */
OSStatus sslAppServe(
	SslAppTestParams	*params)
{
	otSocket			listenSock = 0;
	otSocket			acceptSock = 0;
    PeerSpec            peerId;
    OSStatus            ortn;
    SSLContextRef       ctx = NULL;
	SecKeychainRef		serverKc = nil;
	CFArrayRef			serverCerts = nil;
	
	sslThrDebug("Server", "starting");
    params->negVersion = kSSLProtocolUnknown;
    params->negCipher = SSL_NULL_WITH_NULL_NULL;
	params->ortn = noHardwareErr;
    
	/* set up a socket on which to listen */
	for(unsigned retry=0; retry<BIND_RETRIES; retry++) {
		ortn = ListenForClients(params->port, params->nonBlocking,
			&listenSock);
		switch(ortn) {
			case errSecSuccess:
				break;
			case errSecOpWr:
				/* port already in use - try another */
				params->port++;
				if(params->verbose || THREADING_DEBUG) {
					printf("...retrying ListenForClients at port %d\n",
						params->port);
				}
				break;
			default:
				break;
		}
		if(ortn != errSecOpWr) {
			break;
		}
	}
	
	/* let main thread know a socket is ready */
	if(pthread_mutex_lock(&params->pthreadMutex)) {
		printf("***Error acquiring server lock; aborting.\n");
		return -1;
	}
	params->serverReady = true;
	if(pthread_cond_broadcast(&params->pthreadCond)) {
		printf("***Error waking main thread; aborting.\n");
		return -1;
	}
	if(pthread_mutex_unlock(&params->pthreadMutex)) {
		printf("***Error acquiring server lock; aborting.\n");
		return -1;
	}

	if(ortn) {
		printf("ListenForClients returned %d; aborting\n", (int)ortn);
		return ortn;
	}

	/* wait for a connection */
	if(params->verbose) {
		printf("Waiting for client connection...");
		fflush(stdout);
	}
	ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId);
    if(ortn) {
    	printf("AcceptClientConnection returned %d; aborting\n", (int)ortn);
    	return ortn;
    }

	/* 
	 * Set up a SecureTransport session.
	 */
	ortn = SSLNewContext(true, &ctx);
	if(ortn) {
		printSslErrStr("SSLNewContext", ortn);
		goto cleanup;
	} 
	ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
	if(ortn) {
		printSslErrStr("SSLSetIOFuncs", ortn);
		goto cleanup;
	} 
	ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock);
	if(ortn) {
		printSslErrStr("SSLSetConnection", ortn);
		goto cleanup;
	}
	
	if(params->anchorFile) {
		ortn = sslAddTrustedRoot(ctx, params->anchorFile, 
			params->replaceAnchors);
		if(ortn) {
			goto cleanup;
		}
	}
	if(params->myCertKcName != NULL) {
		/* if not, better be trying anonymous diff-hellman... :-) */
		serverCerts = getSslCerts(params->myCertKcName, false, false, NULL,
			&serverKc);
		if(serverCerts == nil) {
			exit(1);
		}
		if(params->password) {
			ortn = SecKeychainUnlock(serverKc, strlen(params->password), 
					(void *)params->password, true);
			if(ortn) {
				printf("SecKeychainUnlock returned %d\n", (int)ortn);
				/* oh well */
			}
		}
		if(params->idIsTrustedRoot) {
			/* assume this is a root we want to implicitly trust */
			ortn = addIdentityAsTrustedRoot(ctx, serverCerts);
			if(ortn) {
				goto cleanup;
			}
		}
		ortn = SSLSetCertificate(ctx, serverCerts);
		if(ortn) {
			printSslErrStr("SSLSetCertificate", ortn);
			goto cleanup;
		}
	}
	
	if(params->disableCertVerify) {
		ortn = SSLSetEnableCertVerify(ctx, false);
		if(ortn) {
			printSslErrStr("SSLSetEnableCertVerify", ortn);
			goto cleanup;
		}
	}
	ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion);
	if(ortn) {
		goto cleanup;
	}
	if(params->resumeEnable) {
		ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
		if(ortn) {
			printSslErrStr("SSLSetPeerID", ortn);
			goto cleanup;
		}
	}
	if(params->ciphers != NULL) {
		ortn = sslSetEnabledCiphers(ctx, params->ciphers);
		if(ortn) {
			goto cleanup;
		}
	}
	if(params->authenticate != kNeverAuthenticate) {
		ortn = SSLSetClientSideAuthenticate(ctx, params->authenticate);
		if(ortn) {
			printSslErrStr("SSLSetClientSideAuthenticate", ortn);
			goto cleanup;
		}
	}
	if(params->dhParams) {
		#if JAGUAR_BUILD
		printf("***Diffie-Hellman not supported in this config.\n");
		#else
		ortn = SSLSetDiffieHellmanParams(ctx, params->dhParams, 
			params->dhParamsLen);
		if(ortn) {
			printSslErrStr("SSLSetDiffieHellmanParams", ortn);
			goto cleanup;
		}
		#endif
	}

	/* Perform SSL/TLS handshake */
    do {   
		ortn = SSLHandshake(ctx);
	    if((ortn == errSSLWouldBlock) && !params->silent) {
	    	/* keep UI responsive */ 
	    	sslOutputDot();
	    }
    } while (ortn == errSSLWouldBlock);
	
	SSLGetClientCertificateState(ctx, &params->certState);
	SSLGetNegotiatedCipher(ctx, &params->negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, &params->negVersion);
	
	if(params->verbose) {
		printf("\n");
	}
	if(ortn) {
		goto cleanup;
	}

	/* wait for one complete line */
	char readBuf[READBUF_LEN];
	size_t length;
	while(ortn == errSecSuccess) {
	    length = READBUF_LEN;
	    ortn = SSLRead(ctx, readBuf, length, &length);
	    if (ortn == errSSLWouldBlock) {
			/* keep trying */
	        ortn = errSecSuccess;
			continue;
	    }
	    if(length == 0) {
			/* keep trying */
			continue;
	    }
	    
	    /* poor person's line completion scan */
	    for(unsigned i=0; i<length; i++) {
	    	if((readBuf[i] == '\n') || (readBuf[i] == '\r')) {
	    		goto serverResp;
	    	}
	    }
	}
	
serverResp:
	/* send out canned response */
	ortn = SSLWrite(ctx, SERVER_MESSAGE, strlen(SERVER_MESSAGE), &length);
	if(ortn) {
		printSslErrStr("SSLWrite", ortn);
	}

cleanup:
	/*
	 * always do close, even on error - to flush outgoing write queue 
	 */
	if(ctx) {
		OSStatus cerr = SSLClose(ctx);
		if(ortn == errSecSuccess) {
			ortn = cerr;
		}
	}
	if(acceptSock) {
		while(!params->clientDone && !params->serverAbort) {
			usleep(100);
		}
		endpointShutdown(acceptSock);
	}
	if(listenSock) {
		endpointShutdown(listenSock);
	}
	if(ctx) {
	    SSLDisposeContext(ctx);  
	}    
	params->ortn = ortn;
	sslThrDebug("Server", "done");
	return ortn;
}
Пример #11
0
BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
{
    struct mac_session *s;
    unsigned i;
    int status;

    TRACE("(%p)\n", session);

    s = heap_alloc(sizeof(*s));
    if (!s)
        return FALSE;

    InitializeCriticalSection(&s->cs);
    s->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": mac_session.cs");

    status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
    if (status != noErr)
    {
        ERR("Failed to create session context: %d\n", status);
        goto fail;
    }

    /* We don't handle all the signature algorithms that OS X supports so it is important
     * to limit the enabled ciphers before the handshake happens. That will ensure we
     * only get certificates we can handle (assuming the server has alternate chains to offer).
     */
    status = SSLSetEnabledCiphers(s->context, enabled_cipher_suites, sizeof(enabled_cipher_suites) / sizeof(SSLCipherSuite));
    if (status != noErr)
    {
        ERR("Failed to set enabled ciphers: %d\n", status);
        goto fail;
    }

    status = SSLSetConnection(s->context, s);
    if (status != noErr)
    {
        ERR("Failed to set session connection: %d\n", status);
        goto fail;
    }

    status = SSLSetEnableCertVerify(s->context, FALSE);
    if (status != noErr)
    {
        ERR("Failed to disable certificate verification: %d\n", status);
        goto fail;
    }

    for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) {
        if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
           continue;

        status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
                (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
        if (status != noErr)
        {
            ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status);
            goto fail;
        }
    }

    status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
    if (status != noErr)
    {
        ERR("Failed to set session I/O funcs: %d\n", status);
        goto fail;
    }

    TRACE("    -> %p/%p\n", s, s->context);

    *session = (schan_imp_session)s;
    return TRUE;

fail:
    heap_free(s);
    return FALSE;
}
Пример #12
0
Connection::Connection(Context& ctx, std::ios& ios, OpenMode omode)
: _ctx(&ctx)
, _context(0)
, _ios(&ios)
, _iocount(0)
, _connected(false)
, _wantRead(false)
, _isReading(false)
, _isWriting(false)
, _receivedShutdown(false)
, _sentShutdown(false)
{
    Boolean isServer = (omode == Accept);

    SSLNewContext(isServer, &_context);
    
    SSLSetConnection(_context, (SSLConnectionRef) this);

    SSLSetIOFuncs(_context, 
                  &Connection::sslReadCallback, 
                  &Connection::sslWriteCallback);
   
    SSLSetProtocolVersionEnabled(_context, kSSLProtocolAll, false);

    switch(_ctx->protocol()) 
    {
        case SSLv2:
            SSLSetProtocolVersionEnabled(_context, kSSLProtocol2, true);
            break;

        case SSLv3or2:
            SSLSetProtocolVersionEnabled(_context, kSSLProtocol2, true);
            SSLSetProtocolVersionEnabled(_context, kSSLProtocol3, true);
            break;

        default:
        case SSLv3:
            SSLSetProtocolVersionEnabled(_context, kSSLProtocol3, true);
            break;
      
        case TLSv1:
            SSLSetProtocolVersionEnabled(_context, kTLSProtocol1, true);
            break;
    }

    if(isServer)
    {
#ifdef PT_IOS
        SSLSetEnableCertVerify(_context, false);
        SSLSetSessionOption(_context, kSSLSessionOptionBreakOnClientAuth, true);
#else
        if(_ctx->verifyMode() == NoVerify)
        {
            SSLSetClientSideAuthenticate(_context, kNeverAuthenticate);
        }
        else if(_ctx->verifyMode() == TryVerify)
        {
            SSLSetClientSideAuthenticate(_context, kTryAuthenticate);
        }
        else if(_ctx->verifyMode() == AlwaysVerify)
        {
            SSLSetClientSideAuthenticate(_context, kAlwaysAuthenticate);
        }
        
        CFArrayRef caArr = _ctx->impl()->caCertificates();
        SSLSetCertificateAuthorities(_context, caArr, true);
        SSLSetTrustedRoots(_context, caArr, true);
#endif
    }
    else
    {
        SSLSetEnableCertVerify(_context, false);
        SSLSetSessionOption(_context, kSSLSessionOptionBreakOnServerAuth, true);
    }

    // certificates to present to peer
    CFArrayRef certs = _ctx->impl()->certificates();
    if(certs)
    {
        log_debug("using " << CFArrayGetCount(certs) << " certificates");
        SSLSetCertificate(_context, certs);
    }
}
mongoc_stream_t *
mongoc_stream_tls_secure_transport_new (mongoc_stream_t *base_stream,
                                        const char *host,
                                        mongoc_ssl_opt_t *opt,
                                        int client)
{
   mongoc_stream_tls_t *tls;
   mongoc_stream_tls_secure_transport_t *secure_transport;

   ENTRY;
   BSON_ASSERT (base_stream);
   BSON_ASSERT (opt);

   if (opt->ca_dir) {
      MONGOC_ERROR ("Setting mongoc_ssl_opt_t.ca_dir has no effect when built "
                    "against Secure Transport");
      RETURN (NULL);
   }
   if (opt->crl_file) {
      MONGOC_ERROR (
         "Setting mongoc_ssl_opt_t.crl_file has no effect when built "
         "against Secure Transport");
      RETURN (NULL);
   }

   secure_transport = (mongoc_stream_tls_secure_transport_t *) bson_malloc0 (
      sizeof *secure_transport);

   tls = (mongoc_stream_tls_t *) bson_malloc0 (sizeof *tls);
   tls->parent.type = MONGOC_STREAM_TLS;
   tls->parent.destroy = _mongoc_stream_tls_secure_transport_destroy;
   tls->parent.failed = _mongoc_stream_tls_secure_transport_failed;
   tls->parent.close = _mongoc_stream_tls_secure_transport_close;
   tls->parent.flush = _mongoc_stream_tls_secure_transport_flush;
   tls->parent.writev = _mongoc_stream_tls_secure_transport_writev;
   tls->parent.readv = _mongoc_stream_tls_secure_transport_readv;
   tls->parent.setsockopt = _mongoc_stream_tls_secure_transport_setsockopt;
   tls->parent.get_base_stream =
      _mongoc_stream_tls_secure_transport_get_base_stream;
   tls->parent.check_closed = _mongoc_stream_tls_secure_transport_check_closed;
   tls->parent.timed_out = _mongoc_stream_tls_secure_channel_timed_out;
   memcpy (&tls->ssl_opts, opt, sizeof tls->ssl_opts);
   tls->handshake = mongoc_stream_tls_secure_transport_handshake;
   tls->ctx = (void *) secure_transport;
   tls->timeout_msec = -1;

   secure_transport->ssl_ctx_ref =
      SSLCreateContext (kCFAllocatorDefault,
                        client ? kSSLClientSide : kSSLServerSide,
                        kSSLStreamType);

   SSLSetIOFuncs (secure_transport->ssl_ctx_ref,
                  mongoc_secure_transport_read,
                  mongoc_secure_transport_write);
   SSLSetProtocolVersionMin (secure_transport->ssl_ctx_ref, kTLSProtocol1);

   if (opt->pem_file &&
       !mongoc_secure_transport_setup_certificate (secure_transport, opt)) {
      mongoc_stream_destroy ((mongoc_stream_t *) tls);
      RETURN (NULL);
   }

   if (opt->ca_file &&
       !mongoc_secure_transport_setup_ca (secure_transport, opt)) {
      mongoc_stream_destroy ((mongoc_stream_t *) tls);
      RETURN (NULL);
   }

   /* don't link base_stream to tls until we're sure we won't destroy tls */
   tls->base_stream = base_stream;

   if (client) {
      SSLSetSessionOption (secure_transport->ssl_ctx_ref,
                           kSSLSessionOptionBreakOnServerAuth,
                           opt->weak_cert_validation);
   } else if (!opt->allow_invalid_hostname) {
      /* used only in mock_server_t tests */
      SSLSetClientSideAuthenticate (secure_transport->ssl_ctx_ref,
                                    kAlwaysAuthenticate);
   }

   if (!opt->allow_invalid_hostname) {
      SSLSetPeerDomainName (secure_transport->ssl_ctx_ref, host, strlen (host));
   }
   SSLSetConnection (secure_transport->ssl_ctx_ref, tls);


   mongoc_counter_streams_active_inc ();
   RETURN ((mongoc_stream_t *) tls);
}
int main(int argc, char **argv)
{
	/* user-spec'd variables */
	const char 		*kcName = DEFAULT_KC;
	unsigned 		xferSize = XFERSIZE_DEF;
	int 			port = PORT_DEF;
	const char 		*hostName = HOST_DEF;
	SSLCipherSuite 	cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA;
	SSLProtocol 	prot = kTLSProtocol1Only;
	char 			password[200];
	bool 			clientAuthEnable = false;
	bool 			isServer = false;
	unsigned 		bufSize = BUFSIZE;
	bool			diffieHellman = false;
	int				nonBlocking = 0;
	
	if(argc < 2) {
		usage(argv);
	}
	password[0] = 0;
	switch(argv[1][0]) {
		case 's':
			isServer = true;
			break;
		case 'c':
			isServer = false;
			break;
		default:
			usage(argv);
	}
	
	extern int optind;
	extern char *optarg;
	int arg;
	optind = 2;
	while ((arg = getopt(argc, argv, "h:p:k:x:c:v:w:b:aB")) != -1) {
		switch (arg) {
			case 'h':
				hostName = optarg;
				break;
			case 'p':
				port = atoi(optarg);
				break;
			case 'k':
				kcName = optarg;
				break;
			case 'x':
				xferSize = atoi(optarg);
				break;
			case 'c':
				if(!isServer) {
					printf("***Specify cipherSuite on server side.\n");
					exit(1);
				}
				switch(optarg[0]) {
					case 'r':
						cipherSuite = SSL_RSA_WITH_RC4_128_SHA;
						break;
					case 'd':
						cipherSuite = SSL_RSA_WITH_DES_CBC_SHA;
						break;
					case 'D':
						cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
						break;
					case 'h':
						cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5;
						diffieHellman = true;
						break;
					case 'H':
						cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA;
						diffieHellman = true;
						break;
					case 'A':
						cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA;
						break;
					default:
						usage(argv);
				}
				break;
			case 'v':
				if(!isServer) {
					printf("***Specify protocol on server side.\n");
					exit(1);
				}
				switch(optarg[0]) {
					case 't':
						prot = kTLSProtocol1Only;
						break;
					case '2':
						prot = kSSLProtocol2;
						break;
					case '3':
						prot = kSSLProtocol3Only;
						break;
					default:
						usage(argv);
				}
				break;
			case 'w':
				strcpy(password, optarg);
				break;
			case 'b':
				bufSize = atoi(optarg);
				break;
			case 'a':
				clientAuthEnable = true;
				break;
			case 'B':
				nonBlocking = 1;
				break;
			default:
				usage(argv);
		}
	}
	
	/* per-transfer buffer - make it random for server */
	char *buf = (char *)malloc(bufSize);
	if(isServer) {
		Security::DevRandomGenerator rng;
		rng.random(buf, bufSize);
	}
	
	/* gather Diffie-Hellman params from cwd */
	unsigned char *dhParams = NULL;
	unsigned dhParamsLen = 0;
	if(diffieHellman && isServer) {
		if(readFile(DH_PARAM_FILE, &dhParams, &dhParamsLen)) {
			printf("***Error reading Diffie-Hellman Params. Prepare to "
				"wait for a minute during SSL handshake.\n");
		}
	}
	
	/*
	 * Open keychain; both sides use the same one.
	 */
	OSStatus ortn;
	SecKeychainRef certKc = NULL;
	CFAbsoluteTime kcOpenStart = CFAbsoluteTimeGetCurrent();
	ortn = SecKeychainOpen(kcName, &certKc);
	if(ortn) {
		printf("Error opening keychain %s (%d); aborting.\n",
			kcName, (int)ortn);
		exit(1);
	}
	if(password[0]) {
		ortn = SecKeychainUnlock(certKc, strlen(password), password, true);
		if(ortn) {
			printf("SecKeychainUnlock returned %d\n", (int)ortn);
			/* oh well */
		}
	}
	CFAbsoluteTime kcOpenEnd = CFAbsoluteTimeGetCurrent();
	
	otSocket peerSock = 0;
	otSocket listenSock = 0;			// for server only
    PeerSpec peerId;
	
	if(isServer) {
		printf("...listening for client connection on port %d\n", port);
		ortn = ListenForClients(port, nonBlocking, &listenSock);
		if(ortn) {
			printf("...error establishing a listen socket. Aborting.\n");
			exit(1);
		}
		ortn = AcceptClientConnection(listenSock, &peerSock, &peerId);
		if(ortn) {
			printf("...error listening for connection. Aborting.\n");
			exit(1);
		}
	}
	else {
		printf("...connecting to host %s at port %d\n", hostName, port);
		ortn = MakeServerConnection(hostName, port, nonBlocking, &peerSock,
			&peerId);
		if(ortn) {
			printf("...error connecting to server %s. Aborting.\n",
				hostName);
			exit(1);
		}
	}

	/* start timing SSL setup */
	CFAbsoluteTime setupStart = CFAbsoluteTimeGetCurrent();

	SSLContextRef ctx;
	ortn = SSLNewContext(isServer, &ctx);
	if(ortn) {
		printSslErrStr("SSLNewContext", ortn);
		exit(1);
	} 
	ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
	if(ortn) {
		printSslErrStr("SSLSetIOFuncs", ortn);
		exit(1);
	} 
	ortn = SSLSetConnection(ctx, (SSLConnectionRef)peerSock);
	if(ortn) {
		printSslErrStr("SSLSetConnection", ortn);
		exit(1);
	}
	ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1);
	if(ortn) {
		printSslErrStr("SSLSetPeerDomainName", ortn);
		exit(1);
	}	
	
	/*
	 * Server/client specific setup.
	 *
	 * Client uses the same keychain as server, but it uses it for 
	 * sslAddTrustedRoots() instead of getSslCerts() and 
	 * SSLSetCertificate().
	 */
	CFArrayRef myCerts = NULL;
	if(clientAuthEnable || isServer) {
		myCerts = sslKcRefToCertArray(certKc, CSSM_FALSE, CSSM_FALSE, NULL, NULL);
		if(myCerts == NULL) {
			exit(1);
		}
		ortn = addIdentityAsTrustedRoot(ctx, myCerts);
		if(ortn) {
			exit(1);
		}
		ortn = SSLSetCertificate(ctx, myCerts);
		if(ortn) {
			printSslErrStr("SSLSetCertificate", ortn);
			exit(1);
		}
	}
	if(isServer) {
		SSLAuthenticate auth;
		if(clientAuthEnable) {
			auth = kAlwaysAuthenticate;
		}
		else {
			auth = kNeverAuthenticate;
		}
		ortn = SSLSetClientSideAuthenticate(ctx, auth);
		if(ortn) {
			printSslErrStr("SSLSetClientSideAuthenticate", ortn);
			exit(1);
		}
		ortn = SSLSetEnabledCiphers(ctx, &cipherSuite, 1);
		if(ortn) {
			printSslErrStr("SSLSetEnabledCiphers", ortn);
			exit(1);
		}
		ortn = SSLSetProtocolVersion(ctx, prot);
		if(ortn) {
			printSslErrStr("SSLSetProtocolVersion", ortn);
			exit(1);
		}
		if(dhParams != NULL) {
			ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen);
			if(ortn) {
				printSslErrStr("SSLSetDiffieHellmanParams", ortn);
				exit(1);
			}
		}
	}
	else {
		/* client setup */
		if(!clientAuthEnable) {
			/* We're not presenting a cert; trust the server certs */
			bool foundOne;
			ortn = sslAddTrustedRoots(ctx, certKc, &foundOne);
			if(ortn) {
				printSslErrStr("sslAddTrustedRoots", ortn);
				exit(1);
			}
		}
	}
	
	/*
	 * Context setup complete. Start timing handshake.
	 */
	CFAbsoluteTime hshakeStart = CFAbsoluteTimeGetCurrent();
    do {   
		ortn = SSLHandshake(ctx);
    } while (ortn == errSSLWouldBlock);
	if(ortn) {
		printSslErrStr("SSLHandshake", ortn);
		exit(1);
	}
	CFAbsoluteTime hshakeEnd = CFAbsoluteTimeGetCurrent();
	
	/* snag these before data xfer possibly shuts down connection */
	SSLProtocol	negVersion;
	SSLCipherSuite negCipher;
	SSLClientCertificateState certState;		// RETURNED

	SSLGetNegotiatedCipher(ctx, &negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, &negVersion);
	SSLGetClientCertificateState(ctx, &certState);
	
	/* server sends xferSize bytes to client and shuts down */
	size_t bytesMoved;
	
	CFAbsoluteTime dataStart = CFAbsoluteTimeGetCurrent();
	size_t totalMoved = 0;
	if(isServer) {
		size_t bytesToGo = xferSize;
		bool done = false;
		do {
			size_t thisMove = bufSize;
			if(thisMove > bytesToGo) {
				thisMove = bytesToGo;
			}
			ortn = SSLWrite(ctx, buf, thisMove, &bytesMoved);
			switch(ortn) {
				case noErr:
				case errSSLWouldBlock:
					break;
				default:
					done = true;
					break;
			}
			bytesToGo -= bytesMoved;
			totalMoved += bytesMoved;
			if(bytesToGo == 0) {
				done = true;
			}
		} while(!done);
		if(ortn != noErr) {
			printSslErrStr("SSLWrite", ortn);
			exit(1);
		}
	}
	else {
		/* client reads until error or errSSLClosedGraceful */
		bool done = false;
		do {
			ortn = SSLRead(ctx, buf, bufSize, &bytesMoved);
			switch(ortn) {
				case errSSLClosedGraceful:
					done = true;
					break;
				case noErr:
				case errSSLWouldBlock:
					break;
				default:
					done = true;
					break;
			}
			totalMoved += bytesMoved;
		} while(!done);
		if(ortn != errSSLClosedGraceful) {
			printSslErrStr("SSLRead", ortn);
			exit(1);
		}
	}
	
	/* shut down channel */
	ortn = SSLClose(ctx);
	if(ortn) {
		printSslErrStr("SSLCLose", ortn);
		exit(1);
	}
	CFAbsoluteTime dataEnd = CFAbsoluteTimeGetCurrent();

	/* how'd we do? */
	printf("SSL version          : %s\n", 
		sslGetProtocolVersionString(negVersion));
	printf("CipherSuite          : %s\n",
		sslGetCipherSuiteString(negCipher));
	printf("Client Cert State    : %s\n",
			sslGetClientCertStateString(certState));

	if(password[0]) {
		printf("keychain open/unlock : ");
	}
	else {
		printf("keychain open        : ");
	}
	printf("%f s\n", kcOpenEnd - kcOpenStart);
	printf("SSLContext setup     : %f s\n", hshakeStart - setupStart);
	printf("SSL Handshake        : %f s\n", hshakeEnd - hshakeStart);
	printf("Data Transfer        : %u bytes in %f s\n", (unsigned)totalMoved, 
		dataEnd - dataStart);
	printf("                     : %.1f Kbytes/s\n", 
			totalMoved / (dataEnd - dataStart) / 1024.0);
	return 0;
}
Пример #15
0
int					/* O - 1 on success, 0 on error */
cupsdStartTLS(cupsd_client_t *con)	/* I - Client connection */
{
  OSStatus	error = 0;		/* Error code */
  SecTrustRef	peerTrust;		/* Peer certificates */


  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
                  con->number);

  con->http->encryption = HTTP_ENCRYPTION_ALWAYS;

  con->http->tls_credentials = copy_cdsa_certificate(con);

  if (!con->http->tls_credentials)
  {
   /*
    * No keychain (yet), make a self-signed certificate...
    */

    if (make_certificate(con))
      con->http->tls_credentials = copy_cdsa_certificate(con);
  }

  if (!con->http->tls_credentials)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
        	    "Could not find signing key in keychain \"%s\"",
		    ServerCertificate);
    error = errSSLBadConfiguration;
  }

  if (!error)
    con->http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide,
                                     kSSLStreamType);

  if (!error)
    error = SSLSetIOFuncs(con->http->tls, _httpReadCDSA, _httpWriteCDSA);

  if (!error)
    error = SSLSetConnection(con->http->tls, HTTP(con));

  if (!error)
    error = SSLSetCertificate(con->http->tls, con->http->tls_credentials);

  if (!error)
  {
   /*
    * Perform SSL/TLS handshake
    */

    while ((error = SSLHandshake(con->http->tls)) == errSSLWouldBlock)
      usleep(1000);
  }

  if (error)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to encrypt connection from %s - %s (%d)",
                    con->http->hostname, cssmErrorString(error), (int)error);

    con->http->error  = error;
    con->http->status = HTTP_ERROR;

    if (con->http->tls)
    {
      CFRelease(con->http->tls);
      con->http->tls = NULL;
    }

    if (con->http->tls_credentials)
    {
      CFRelease(con->http->tls_credentials);
      con->http->tls_credentials = NULL;
    }

    return (0);
  }

  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
                  con->http->hostname);

  if (!SSLCopyPeerTrust(con->http->tls, &peerTrust) && peerTrust)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates.",
		    (int)SecTrustGetCertificateCount(peerTrust));
    CFRelease(peerTrust);
  }
  else
    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates.");

  return (1);
}
Пример #16
0
static void
ssl_cdsa_create_context(gpointer data) {
    PurpleSslConnection *gsc = (PurpleSslConnection *)data;
    PurpleAccount *account = gsc->account;
	PurpleSslCDSAData *cdsa_data;
    OSStatus err;
	bool requireFS = purple_account_get_bool(account, "require_forward_secrecy", FALSE);
    
    /*
	 * allocate some memory to store variables for the cdsa connection.
	 * the memory comes zero'd from g_new0 so we don't need to null the
	 * pointers held in this struct.
	 */
    cdsa_data = g_new0(PurpleSslCDSAData, 1);
	gsc->private_data = cdsa_data;
	connections = g_list_append(connections, gsc);
    
    /*
	 * allocate a new SSLContextRef object
	 */
    err = SSLNewContext(false, &cdsa_data->ssl_ctx);
	if (err != noErr) {
		purple_debug_error("cdsa", "SSLNewContext failed\n");
		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
		purple_ssl_close(gsc);
		return;
	}
    
    /*
     * Set up our callbacks for reading/writing the file descriptor
     */
    err = SSLSetIOFuncs(cdsa_data->ssl_ctx, SocketRead, SocketWrite);
    if (err != noErr) {
		purple_debug_error("cdsa", "SSLSetIOFuncs failed\n");
		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
		purple_ssl_close(gsc);
		return;
    }
    
    /*
     * Pass the connection information to the connection to be used by our callbacks
     */
    err = SSLSetConnection(cdsa_data->ssl_ctx, (SSLConnectionRef)(intptr_t)gsc->fd);
    if (err != noErr) {
		purple_debug_error("cdsa", "SSLSetConnection failed: %d\n", err);
		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
		purple_ssl_close(gsc);
		return;
    }
	
	size_t numCiphers = 0;
	
	err = SSLGetNumberEnabledCiphers(cdsa_data->ssl_ctx, &numCiphers);
	
	if (err != noErr) {
		purple_debug_error("cdsa", "SSLGetNumberEnabledCiphers failed: %d\n", err);
        if (gsc->error_cb != NULL)
            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
        purple_ssl_close(gsc);
        return;
	}
	
	SSLCipherSuite ciphers[numCiphers];
    
    err = SSLGetEnabledCiphers(cdsa_data->ssl_ctx, ciphers, &numCiphers);
	if (err != noErr) {
		purple_debug_error("cdsa", "SSLGetSupportedCiphers failed: %d\n", err);
        if (gsc->error_cb != NULL)
            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
        purple_ssl_close(gsc);
        return;
	}
	
	SSLCipherSuite enabledCiphers[numCiphers];
	size_t numEnabledCiphers = 0;
	int i;
	
	for (i = 0; i < numCiphers; i++) {
		if (ssl_cdsa_use_cipher(ciphers[i], requireFS)) {
			enabledCiphers[numEnabledCiphers] = ciphers[i];
			numEnabledCiphers++;
		}
	}
	
    err = SSLSetEnabledCiphers(cdsa_data->ssl_ctx, enabledCiphers, numEnabledCiphers);
    if (err != noErr) {
        purple_debug_error("cdsa", "SSLSetEnabledCiphers failed: %d\n", err);
        if (gsc->error_cb != NULL)
            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                          gsc->connect_cb_data);
        
        purple_ssl_close(gsc);
        return;
    }
    
    if (purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)) {
        purple_debug_info("cdsa", "Explicitly disabling TLS 1.1 and above to try and work around buggy TLS stacks\n");
        
        OSStatus protoErr;
        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocolAll, false);
        if (protoErr != noErr) {
            purple_debug_error("cdsa", "SSLSetProtocolVersionEnabled failed to disable protocols\n");
            if (gsc->error_cb != NULL)
                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data);
            purple_ssl_close(gsc);
            return;
        }
        
        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocol3, true);
        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kTLSProtocol1, true);
    }
    
    if(gsc->host) {
        /*
         * Set the peer's domain name so CDSA can check the certificate's CN
         */
        err = SSLSetPeerDomainName(cdsa_data->ssl_ctx, gsc->host, strlen(gsc->host));
        if (err != noErr) {
            purple_debug_error("cdsa", "SSLSetPeerDomainName failed\n");
            if (gsc->error_cb != NULL)
                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
                              gsc->connect_cb_data);
            
            purple_ssl_close(gsc);
            return;
        }
    }
    
	/*
     * Disable verifying the certificate chain.
	 * We have to do that manually later on! This is the only way to be able to continue with a connection, even though the user
	 * had to manually accept the certificate.
     */
	err = SSLSetEnableCertVerify(cdsa_data->ssl_ctx, false);
    if (err != noErr) {
		purple_debug_error("cdsa", "SSLSetEnableCertVerify failed\n");
        /* error is not fatal */
    }
	
	cdsa_data->handshake_handler = purple_input_add(gsc->fd, PURPLE_INPUT_READ, ssl_cdsa_handshake_cb, gsc);
}
Пример #17
0
BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
{
    struct mac_session *s;
    unsigned i;
    int status;

    TRACE("(%p)\n", session);

    s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
    if (!s)
        return FALSE;

    status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
    if (status != noErr)
    {
        ERR("Failed to create session context: %d\n", status);
        goto fail;
    }

    status = SSLSetConnection(s->context, s);
    if (status != noErr)
    {
        ERR("Failed to set session connection: %d\n", status);
        goto fail;
    }

    status = SSLSetEnableCertVerify(s->context, FALSE);
    if (status != noErr)
    {
        ERR("Failed to disable certificate verification: %d\n", status);
        goto fail;
    }

    for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) {
        if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
           continue;

        status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
                (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
        if (status != noErr)
        {
            ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status);
            goto fail;
        }
    }

    status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
    if (status != noErr)
    {
        ERR("Failed to set session I/O funcs: %d\n", status);
        goto fail;
    }

    TRACE("    -> %p/%p\n", s, s->context);

    *session = (schan_imp_session)s;
    return TRUE;

fail:
    HeapFree(GetProcessHeap(), 0, s);
    return FALSE;
}
Пример #18
0
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
                                        int sockindex)
{
  struct SessionHandle *data = conn->data;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  bool sni = true;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  /*SSLConnectionRef ssl_connection;*/
  OSStatus err = noErr;

#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
  if(SSLCreateContext != NULL) {  /* use the newer API if avaialble */
    if(connssl->ssl_ctx)
      CFRelease(connssl->ssl_ctx);
    connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
    if(!connssl->ssl_ctx) {
      failf(data, "SSL: couldn't create a context!");
      return CURLE_OUT_OF_MEMORY;
    }
  }
  else {
#elif TARGET_OS_EMBEDDED == 0
  if(connssl->ssl_ctx)
    (void)SSLDisposeContext(connssl->ssl_ctx);
  err = SSLNewContext(false, &(connssl->ssl_ctx));
  if(err != noErr) {
    failf(data, "SSL: couldn't create a context: OSStatus %d", err);
    return CURLE_OUT_OF_MEMORY;
  }
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
  }
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */

  /* check to see if we've been told to use an explicit SSL/TLS version */
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
  if(SSLSetProtocolVersionMax != NULL) {
    switch(data->set.ssl.version) {
      case CURL_SSLVERSION_DEFAULT: default:
        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
        break;
      case CURL_SSLVERSION_TLSv1:
        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
        break;
      case CURL_SSLVERSION_SSLv3:
        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
        break;
      case CURL_SSLVERSION_SSLv2:
        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
    }
  }
  else {
#if TARGET_OS_EMBEDDED == 0
    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                       kSSLProtocolAll,
                                       false);
    switch (data->set.ssl.version) {
      case CURL_SSLVERSION_DEFAULT: default:
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kSSLProtocol3,
                                           true);
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol1,
                                           true);
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol11,
                                           true);
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol12,
                                           true);
        break;
      case CURL_SSLVERSION_TLSv1:
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol1,
                                           true);
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol11,
                                           true);
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kTLSProtocol12,
                                           true);
        break;
      case CURL_SSLVERSION_SSLv3:
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kSSLProtocol3,
                                           true);
        break;
      case CURL_SSLVERSION_SSLv2:
        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                           kSSLProtocol2,
                                           true);
        break;
    }
#endif  /* TARGET_OS_EMBEDDED == 0 */
  }
#else
  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
  switch(data->set.ssl.version) {
    default:
    case CURL_SSLVERSION_DEFAULT:
      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                         kSSLProtocol3,
                                         true);
      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                         kTLSProtocol1,
                                         true);
      break;
    case CURL_SSLVERSION_TLSv1:
      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                         kTLSProtocol1,
                                         true);
      break;
    case CURL_SSLVERSION_SSLv2:
      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                         kSSLProtocol2,
                                         true);
      break;
    case CURL_SSLVERSION_SSLv3:
      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                         kSSLProtocol3,
                                         true);
      break;
  }
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */

  /* No need to load certificates here. SecureTransport uses the Keychain
   * (which is also part of the Security framework) to evaluate trust. */

  /* SSL always tries to verify the peer, this only says whether it should
   * fail to connect if the verification fails, or if it should continue
   * anyway. In the latter case the result of the verification is checked with
   * SSL_get_verify_result() below. */
#if defined(__MAC_10_6) || defined(__IPHONE_5_0)
  if(SSLSetSessionOption != NULL) {
    err = SSLSetSessionOption(connssl->ssl_ctx,
                              kSSLSessionOptionBreakOnServerAuth,
                              data->set.ssl.verifypeer?false:true);
    if(err != noErr) {
      failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
  else {
#elif TARGET_OS_EMBEDDED == 0
  err = SSLSetEnableCertVerify(connssl->ssl_ctx,
                               data->set.ssl.verifypeer?true:false);
  if(err != noErr) {
    failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
    return CURLE_SSL_CONNECT_ERROR;
  }
#endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */
#if defined(__MAC_10_6) || defined(__IPHONE_5_0)
  }
#endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */

  /* If this is a domain name and not an IP address, then configure SNI: */
  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
#ifdef ENABLE_IPV6
     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
#endif
     sni) {
    err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
                               strlen(conn->host.name));
    if(err != noErr) {
      infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
            err);
    }
  }

  err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
  if(err != noErr) {
    failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* pass the raw socket into the SSL layers */
  /* We need to store the FD in a constant memory address, because
   * SSLSetConnection() will not copy that address. I've found that
   * conn->sock[sockindex] may change on its own. */
  connssl->ssl_sockfd = sockfd;
  /*ssl_connection = &(connssl->ssl_sockfd);
  err = SSLSetConnection(connssl->ssl_ctx, ssl_connection);*/
  err = SSLSetConnection(connssl->ssl_ctx, connssl);
  if(err != noErr) {
    failf(data, "SSL: SSLSetConnection() failed: %d", err);
    return CURLE_SSL_CONNECT_ERROR;
  }

  connssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}
Пример #19
0
/* relies on SSLSetProtocolVersionEnabled */
OSStatus sslAppClient(
	SslAppTestParams	*params)
{
    PeerSpec            peerId;
	otSocket			sock = 0;
    OSStatus            ortn;
    SSLContextRef       ctx = NULL;
	SecKeychainRef		clientKc = nil;
	CFArrayRef			clientCerts = nil;
	
	sslThrDebug("Client", "starting");
    params->negVersion = kSSLProtocolUnknown;
    params->negCipher  = SSL_NULL_WITH_NULL_NULL;
    params->ortn       = noHardwareErr;
	
	/* first make sure requested server is there */
	ortn = MakeServerConnection(params->hostName, params->port,
		params->nonBlocking, &sock, &peerId);
    if(ortn) {
    	printf("MakeServerConnection returned %d; aborting\n", (int)ortn);
    	return ortn;
    }
	
	/* 
	 * Set up a SecureTransport session.
	 */
	ortn = SSLNewContext(false, &ctx);
	if(ortn) {
		printSslErrStr("SSLNewContext", ortn);
		goto cleanup;
	} 
	ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
	if(ortn) {
		printSslErrStr("SSLSetIOFuncs", ortn);
		goto cleanup;
	} 
	ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock);
	if(ortn) {
		printSslErrStr("SSLSetConnection", ortn);
		goto cleanup;
	}
	if(!params->skipHostNameCheck) {
		ortn = SSLSetPeerDomainName(ctx, params->hostName, 
			strlen(params->hostName));
		if(ortn) {
			printSslErrStr("SSLSetPeerDomainName", ortn);
			goto cleanup;
		}
	}
	
	/* remainder of setup is optional */
	if(params->anchorFile) {
		ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors);
		if(ortn) {
			goto cleanup;
		}
	}
	ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion);
	if(ortn) {
		goto cleanup;
	}
	if(params->resumeEnable) {
		ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
		if(ortn) {
			printSslErrStr("SSLSetPeerID", ortn);
			goto cleanup;
		}
	}
	if(params->disableCertVerify) {
		ortn = SSLSetEnableCertVerify(ctx, false);
		if(ortn) {
			printSslErrStr("SSLSetEnableCertVerify", ortn);
			goto cleanup;
		}
	}
	if(params->ciphers != NULL) {
		ortn = sslSetEnabledCiphers(ctx, params->ciphers);
		if(ortn) {
			goto cleanup;
		}
	}
	if(params->myCertKcName) {
		clientCerts = getSslCerts(params->myCertKcName, false, false, NULL, &clientKc);
		if(clientCerts == nil) {
			exit(1);
		}
		if(params->password) {
			ortn = SecKeychainUnlock(clientKc, strlen(params->password), 
					(void *)params->password, true);
			if(ortn) {
				printf("SecKeychainUnlock returned %d\n", (int)ortn);
				/* oh well */
			}
		}
		if(params->idIsTrustedRoot) {
			/* assume this is a root we want to implicitly trust */
			ortn = addIdentityAsTrustedRoot(ctx, clientCerts);
			if(ortn) {
				goto cleanup;
			}
		}
		ortn = SSLSetCertificate(ctx, clientCerts);
		if(ortn) {
			printSslErrStr("SSLSetCertificate", ortn);
			goto cleanup;
		}
	}
    do {
		ortn = SSLHandshake(ctx);
	    if((ortn == errSSLWouldBlock) && !params->silent) {
	    	/* keep UI responsive */ 
	    	sslOutputDot();
	    }
    } while (ortn == errSSLWouldBlock);
	
	SSLGetClientCertificateState(ctx, &params->certState);
	SSLGetNegotiatedCipher(ctx, &params->negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, &params->negVersion);
	
	if(ortn != errSecSuccess) {
		goto cleanup;
	}

	/* send a GET msg */
	size_t actLen;
	ortn = SSLWrite(ctx, CLIENT_GETMSG, strlen(CLIENT_GETMSG), &actLen);
	if(ortn) {
		printSslErrStr("SSLWrite", ortn);
		goto cleanup;
	}
	
	#if KEEP_CONNECTED
	
	/*
	 * Consume any server data and wait for server to disconnect
	 */
	char readBuf[READBUF_LEN];
    do {
		ortn = SSLRead(ctx, readBuf, READBUF_LEN, &actLen);
    } while (ortn == errSSLWouldBlock);
	
    /* convert normal "shutdown" into zero err rtn */
	if(ortn == errSSLClosedGraceful) {
		ortn = errSecSuccess;
	}
	#endif	/* KEEP_CONNECTED */
	
cleanup:
	if(ctx) {
		OSStatus cerr = SSLClose(ctx);
		if(ortn == errSecSuccess) {
			ortn = cerr;
		}
	}
	if(sock) {
		endpointShutdown(sock);
	}
	if(ctx) {
	    SSLDisposeContext(ctx);  
	}    
	params->ortn = ortn;
	sslThrDebug("Client", "done");
	return ortn;
}