Пример #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
SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
{
    struct mac_session *s = (struct mac_session*)session;
    int status;

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

    status = SSLHandshake(s->context);
    if (status == noErr)
    {
        TRACE("Handshake completed\n");
        return SEC_E_OK;
    }
    else if (status == errSSLWouldBlock)
    {
        TRACE("Continue...\n");
        return SEC_I_CONTINUE_NEEDED;
    }
    else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
    {
        ERR("Handshake failed: %s\n", strerror(status));
        return SEC_E_INTERNAL_ERROR;
    }
    else
    {
        ERR("Handshake failed: %d\n", status);
        cssmPerror("SSLHandshake", status);
        return SEC_E_INTERNAL_ERROR;
    }

    /* Never reached */
    return SEC_E_OK;
}
Пример #3
0
Transition ConnectionHandle::ProcessWrite_SSLHandshake() {
  // Flush out all the response first
  if (HasResponse()) {
    auto write_ret = ProcessWrite();
    if (write_ret != Transition::PROCEED) {
      return write_ret;
    }
  }

  return SSLHandshake();
}
static CURLcode
darwinssl_connect_step2(struct connectdata *conn, int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  OSStatus err;
  SSLCipherSuite cipher;

  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
              || ssl_connect_2_reading == connssl->connecting_state
              || ssl_connect_2_writing == connssl->connecting_state);

  /* Here goes nothing: */
  err = SSLHandshake(connssl->ssl_ctx);

  if(err != noErr) {
    switch (err) {
      case errSSLWouldBlock:  /* they're not done with us yet */
        connssl->connecting_state = connssl->ssl_direction ?
            ssl_connect_2_writing : ssl_connect_2_reading;
        return CURLE_OK;
        break;

      case errSSLServerAuthCompleted:
        /* the documentation says we need to call SSLHandshake() again */
        return darwinssl_connect_step2(conn, sockindex);

      case errSSLXCertChainInvalid:
      case errSSLUnknownRootCert:
      case errSSLNoRootCert:
      case errSSLCertExpired:
        failf(data, "SSL certificate problem: OSStatus %d", err);
        return CURLE_SSL_CACERT;
        break;

      default:
        failf(data, "Unknown SSL protocol error in connection to %s:%d",
              conn->host.name, err);
        return CURLE_SSL_CONNECT_ERROR;
        break;
    }
  }
  else {
    /* we have been connected fine, we're not waiting for anything else. */
    connssl->connecting_state = ssl_connect_3;

    /* Informational message */
    (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
    infof (data, "SSL connection using %s\n", CipherNameForNumber(cipher));

    return CURLE_OK;
  }
}
Пример #5
0
static int stransport_connect(git_stream *stream)
{
	stransport_stream *st = (stransport_stream *) stream;
	int error;
	SecTrustRef trust = NULL;
	SecTrustResultType sec_res;
	OSStatus ret;

	if ((error = git_stream_connect(st->io)) < 0)
		return error;

	ret = SSLHandshake(st->ctx);
	if (ret != errSSLServerAuthCompleted) {
		giterr_set(GITERR_SSL, "unexpected return value from ssl handshake %d", (int)ret);
		return -1;
	}

	if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
		goto on_error;

	if (!trust)
		return GIT_ECERTIFICATE;

	if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
		goto on_error;

	CFRelease(trust);

	if (sec_res == kSecTrustResultInvalid || sec_res == kSecTrustResultOtherError) {
		giterr_set(GITERR_SSL, "internal security trust error");
		return -1;
	}

	if (sec_res == kSecTrustResultDeny || sec_res == kSecTrustResultRecoverableTrustFailure ||
	    sec_res == kSecTrustResultFatalTrustFailure) {
		giterr_set(GITERR_SSL, "untrusted connection error");
		return GIT_ECERTIFICATE;
	}

	return 0;

on_error:
	if (trust)
		CFRelease(trust);

	return stransport_error(ret);
}
bool
mongoc_stream_tls_secure_transport_handshake (mongoc_stream_t *stream,
                                              const char *host,
                                              int *events,
                                              bson_error_t *error)
{
   OSStatus ret = 0;
   CFStringRef err;
   char *err_str;
   mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
   mongoc_stream_tls_secure_transport_t *secure_transport =
      (mongoc_stream_tls_secure_transport_t *) tls->ctx;

   ENTRY;
   BSON_ASSERT (secure_transport);

   ret = SSLHandshake (secure_transport->ssl_ctx_ref);
   /* Weak certificate validation requested, eg: none */

   if (ret == errSSLServerAuthCompleted) {
      ret = errSSLWouldBlock;
   }

   if (ret == noErr) {
      RETURN (true);
   }

   if (ret == errSSLWouldBlock) {
      *events = POLLIN | POLLOUT;
   } else {
      *events = 0;
      err = SecCopyErrorMessageString (ret, NULL);
      err_str = _mongoc_cfstringref_to_cstring (err);
      bson_set_error (error,
                      MONGOC_ERROR_STREAM,
                      MONGOC_ERROR_STREAM_SOCKET,
                      "TLS handshake failed: %s (%d)",
                      err_str,
                      ret);

      bson_free (err_str);
      CFRelease (err);
   }

   RETURN (false);
}
static void *securetransport_ssl_thread(void *arg)
{
    OSStatus ortn;
    int sock = (int)arg;

    int socket = accept(sock, NULL, NULL);

    CFArrayRef server_certs = server_chain();
    ssl_test_handle * ssl = ssl_test_handle_create(socket, server_certs);
    SSLContextRef ctx = ssl->st;

    pthread_setname_np("server thread");

    //uint64_t start = mach_absolute_time();
    do {
        ortn = SSLHandshake(ctx);
    } while (ortn == errSSLWouldBlock);

    require_noerr_action_quiet(ortn, out,
                               fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));

    //uint64_t elapsed = mach_absolute_time() - start;
    //fprintf(stderr, "setr elapsed: %lld\n", elapsed);

    /*
    SSLProtocol proto = kSSLProtocolUnknown;
    require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */

    SSLCipherSuite cipherSuite;
    require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
    //fprintf(stderr, "st negotiated %s\n", sslcipher_itoa(cipherSuite));


out:
    CFRelease(server_certs);

    SSLClose(ctx);
    CFRelease(ctx);
    if(ssl) {
        close(ssl->comm);
        free(ssl);
    }
    pthread_exit((void *)(intptr_t)ortn);
    return NULL;
}
Пример #8
0
/*
 * @return -1 on fatal error, 0 on successful handshake completion,
 * 1 if more would-be blocking recv is needed,
 * 2 if more would-be blocking send is required.
 */
static int st_Handshake (vlc_tls_t *session, const char *host,
                         const char *service) {
    VLC_UNUSED(service);

    vlc_tls_sys_t *sys = session->sys;

    OSStatus retValue = SSLHandshake(sys->p_context);

    if (retValue == errSSLWouldBlock) {
        msg_Dbg(session, "handshake is blocked, try again later");
        return 1 + (sys->b_blocking_send ? 1 : 0);
    }

    switch (retValue) {
    case noErr:
        if(st_validateServerCertificate(session, host) != 0) {
            return -1;
        }
        msg_Dbg(session, "handshake completed successfully");
        sys->b_handshaked = true;
        return 0;

    case errSSLServerAuthCompleted:
        return st_Handshake (session, host, service);

    case errSSLConnectionRefused:
        msg_Err(session, "connection was refused");
        return -1;
    case errSSLNegotiation:
        msg_Err(session, "cipher suite negotiation failed");
        return -1;
    case errSSLFatalAlert:
        msg_Err(session, "fatal error occured during handshake");
        return -1;

    default:
        msg_Err(session, "handshake returned error %d", (int)retValue);
        return -1;
    }
}
Пример #9
0
bool Connection::writeHandshake()
{
    log_trace("Connection::writeHandshake");

    _iocount = 0;
    _isWriting = true;
    OSStatus status = SSLHandshake(_context);
    _isWriting = false;

    log_debug("SSLHandshake returns " << status);

    if(status == noErr)
    {       
        log_debug("SSL handshake completed");
        _connected = true;
    }
    else if(status != errSSLWouldBlock)
    {
        throw HandshakeFailed("SSL handshake failed");
    }

    return _iocount > 0;
}
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;
}
Пример #11
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;
}
Пример #12
0
static CURLcode
darwinssl_connect_step2(struct connectdata *conn, int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  OSStatus err;
  SSLCipherSuite cipher;
  SSLProtocol protocol = 0;

  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
              || ssl_connect_2_reading == connssl->connecting_state
              || ssl_connect_2_writing == connssl->connecting_state);

  /* Here goes nothing: */
  err = SSLHandshake(connssl->ssl_ctx);

  if(err != noErr) {
    switch (err) {
      case errSSLWouldBlock:  /* they're not done with us yet */
        connssl->connecting_state = connssl->ssl_direction ?
            ssl_connect_2_writing : ssl_connect_2_reading;
        return CURLE_OK;

      case errSSLServerAuthCompleted:
        /* the documentation says we need to call SSLHandshake() again */
        return darwinssl_connect_step2(conn, sockindex);

      case errSSLXCertChainInvalid:
      case errSSLUnknownRootCert:
      case errSSLNoRootCert:
      case errSSLCertExpired:
        failf(data, "SSL certificate problem: OSStatus %d", err);
        return CURLE_SSL_CACERT;

      case errSSLHostNameMismatch:
        failf(data, "SSL certificate peer verification failed, the "
              "certificate did not match \"%s\"\n", conn->host.dispname);
        return CURLE_PEER_FAILED_VERIFICATION;

      default:
        failf(data, "Unknown SSL protocol error in connection to %s:%d",
              conn->host.name, err);
        return CURLE_SSL_CONNECT_ERROR;
    }
  }
  else {
    /* we have been connected fine, we're not waiting for anything else. */
    connssl->connecting_state = ssl_connect_3;

    /* Informational message */
    (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
    (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
    switch (protocol) {
      case kSSLProtocol2:
        infof(data, "SSL 2.0 connection using %s\n",
              SSLCipherNameForNumber(cipher));
        break;
      case kSSLProtocol3:
        infof(data, "SSL 3.0 connection using %s\n",
              SSLCipherNameForNumber(cipher));
        break;
      case kTLSProtocol1:
        infof(data, "TLS 1.0 connection using %s\n",
              TLSCipherNameForNumber(cipher));
        break;
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
      case kTLSProtocol11:
        infof(data, "TLS 1.1 connection using %s\n",
              TLSCipherNameForNumber(cipher));
        break;
      case kTLSProtocol12:
        infof(data, "TLS 1.2 connection using %s\n",
              TLSCipherNameForNumber(cipher));
        break;
#endif
      default:
        infof(data, "Unknown protocol connection\n");
        break;
    }

    return CURLE_OK;
  }
}
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;
}
Пример #14
0
    return result;
}

/*
 * @return -1 on fatal error, 0 on successful handshake completion,
 * 1 if more would-be blocking recv is needed,
 * 2 if more would-be blocking send is required.
 */
static int st_Handshake (vlc_tls_creds_t *crd, vlc_tls_t *session,
                         const char *host, const char *service,
                         char **restrict alp) {
    VLC_UNUSED(service);

    vlc_tls_sys_t *sys = session->sys;

    OSStatus retValue = SSLHandshake(sys->p_context);
    if (alp != NULL) {
        *alp = NULL;
    }

    if (retValue == errSSLWouldBlock) {
        msg_Dbg(crd, "handshake is blocked, try again later");
        return 1 + (sys->b_blocking_send ? 1 : 0);
    }

    switch (retValue) {
        case noErr:
            if (sys->b_server_mode == false && st_validateServerCertificate(session, host) != 0) {
                return -1;
            }
            msg_Dbg(crd, "handshake completed successfully");
Пример #15
0
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
{
    TLSContext *c = h->priv_data;
    TLSShared *s = &c->tls_shared;
    int ret;

    if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
        goto fail;

    c->ssl_context = SSLCreateContext(NULL, s->listen ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
    if (!c->ssl_context) {
        av_log(h, AV_LOG_ERROR, "Unable to create SSL context\n");
        ret = AVERROR(ENOMEM);
        goto fail;
    }
    if (s->ca_file) {
        if ((ret = load_ca(h)) < 0)
            goto fail;
    }
    if (s->ca_file || !s->verify)
        CHECK_ERROR(SSLSetSessionOption, c->ssl_context, kSSLSessionOptionBreakOnServerAuth, true);
    if (s->cert_file)
        if ((ret = load_cert(h)) < 0)
            goto fail;
    CHECK_ERROR(SSLSetPeerDomainName, c->ssl_context, s->host, strlen(s->host));
    CHECK_ERROR(SSLSetIOFuncs, c->ssl_context, tls_read_cb, tls_write_cb);
    CHECK_ERROR(SSLSetConnection, c->ssl_context, h);
    while (1) {
        OSStatus status = SSLHandshake(c->ssl_context);
        if (status == errSSLServerAuthCompleted) {
            SecTrustRef peerTrust;
            SecTrustResultType trustResult;
            if (!s->verify)
                continue;

            if (SSLCopyPeerTrust(c->ssl_context, &peerTrust) != noErr) {
                ret = AVERROR(ENOMEM);
                goto fail;
            }

            if (SecTrustSetAnchorCertificates(peerTrust, c->ca_array) != noErr) {
                ret = AVERROR_UNKNOWN;
                goto fail;
            }

            if (SecTrustEvaluate(peerTrust, &trustResult) != noErr) {
                ret = AVERROR_UNKNOWN;
                goto fail;
            }

            if (trustResult == kSecTrustResultProceed ||
                trustResult == kSecTrustResultUnspecified) {
                // certificate is trusted
                status = errSSLWouldBlock; // so we call SSLHandshake again
            } else if (trustResult == kSecTrustResultRecoverableTrustFailure) {
                // not trusted, for some reason other than being expired
                status = errSSLXCertChainInvalid;
            } else {
                // cannot use this certificate (fatal)
                status = errSSLBadCert;
            }

            if (peerTrust)
                CFRelease(peerTrust);
        }
        if (status == noErr)
            break;

        av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status);
        ret = AVERROR(EIO);
        goto fail;
    }

    return 0;
fail:
    tls_close(h);
    return ret;
}
Пример #16
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);
}
static OSStatus securetransport(ssl_test_handle * ssl)
{
    OSStatus ortn;
    SSLContextRef ctx = ssl->st;
    SecTrustRef trust = NULL;
    bool got_server_auth = false, got_client_cert_req = false;

    ortn = SSLHandshake(ctx);
    //fprintf(stderr, "Fell out of SSLHandshake with error: %ld\n", (long)ortn);
    
    size_t sent, received;
    const char *r=request;
    size_t l=sizeof(request);

    do {
        
        ortn = SSLWrite(ctx, r, l, &sent);
        
        if(ortn == errSSLWouldBlock) {
                r+=sent;
                l-=sent;
        }
        
        if (ortn == errSSLServerAuthCompleted)
        {
            require_string(!got_server_auth, out, "second server auth");
            require_string(!got_client_cert_req, out, "got client cert req before server auth");
            got_server_auth = true;
            require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
            /* verify peer cert chain */
            require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
            SecTrustResultType trust_result = 0;
            /* this won't verify without setting up a trusted anchor */
            require_noerr(SecTrustEvaluate(trust, &trust_result), out);
        }
    } while(ortn == errSSLWouldBlock || ortn == errSSLServerAuthCompleted);

    //fprintf(stderr, "\nHTTP Request Sent\n");

    require_noerr_action_quiet(ortn, out, printf("SSLWrite failed with err %ld\n", (long)ortn));

    require_string(got_server_auth, out, "never got server auth");

    do {
        ortn = SSLRead(ctx, reply, sizeof(reply)-1, &received);
        //fprintf(stderr, "r"); usleep(1000);
    } while(ortn == errSSLWouldBlock);
    
    //fprintf(stderr, "\n");
    
    require_noerr_action_quiet(ortn, out, printf("SSLRead failed with err %ld\n", (long)ortn));

    reply[received]=0;

    //fprintf(stderr, "HTTP reply:\n");
    //fprintf(stderr, "%s\n",reply);
    
out:
    SSLClose(ctx);
    SSLDisposeContext(ctx);
    if (trust) CFRelease(trust);

    return ortn;
}
Пример #18
0
bool Connection::readHandshake()
{
    log_trace("Connection::readHandshake");

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return true;

    _maxImport = sb->in_avail();
    _wantRead = false;
    _isReading = true;
    OSStatus status = SSLHandshake(_context);
    _isReading = false;

    log_debug("SSLHandshake returns " << status);
    
    if( status == noErr )
    {
        log_debug("SSL handshake completed");
        _connected = true;
        return false;
    }

#ifdef PT_IOS
    if(status == errSSLPeerAuthCompleted)
#else
    if(status == errSSLServerAuthCompleted)
#endif
    {
        log_debug("authenticating peer");

        if( _ctx->verifyMode() != NoVerify )
        {
            log_debug("evaluating trust");
            
            SecTrustRef trust = NULL;
            SSLCopyPeerTrust(_context, &trust);

            CFArrayRef caArr = _ctx->impl()->caCertificates();
            SecTrustSetAnchorCertificates(trust, caArr);
            SecTrustSetAnchorCertificatesOnly(trust, true);

            SecTrustResultType result;
            OSStatus evalErr = SecTrustEvaluate(trust, &result);
            if(evalErr)
                throw HandshakeFailed("SSL handshake failed");
        
            CFIndex count = SecTrustGetCertificateCount(trust);
            log_debug("SecTrustEvaluate: " << result << " certs: " << count);
            
            if(trust)
                CFRelease(trust);
            
            // if peer presented no certificate, SecTrustGetCertificateCount
            // should return 0. If we require one because AlwaysVerify is
            // set, the handshake is considered to be failed
            if(_ctx->verifyMode() == AlwaysVerify && count == 0)
                throw HandshakeFailed("SSL handshake failed");

            if( (result != kSecTrustResultProceed) && 
                (result != kSecTrustResultUnspecified) )
                throw HandshakeFailed("SSL handshake failed");

            log_debug("authentication successful");
        }

        return readHandshake();
    }
    
    if( status != errSSLWouldBlock )
    {
        throw HandshakeFailed("SSL handshake failed");
    }

    return _wantRead;
}
Пример #19
0
/*
 * ssl_cdsa_handshake_cb
 */
static void
ssl_cdsa_handshake_cb(gpointer data, gint source, PurpleInputCondition cond)
{
	PurpleSslConnection *gsc = (PurpleSslConnection *)data;
	PurpleAccount *account = gsc->account;
	PurpleSslCDSAData *cdsa_data = PURPLE_SSL_CDSA_DATA(gsc);
    OSStatus err;
	
	purple_debug_info("cdsa", "Connecting\n");
	
	/*
	 * do the negotiation that sets up the SSL connection between
	 * here and there.
	 */
	err = SSLHandshake(cdsa_data->ssl_ctx);
    if (err == errSSLPeerBadRecordMac
		&& !purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)
		&& !strcmp(purple_account_get_protocol_id(account),"prpl-jabber")) {
        /*
         * Set a flag so we know to explicitly disable TLS 1.1 and 1.2 on our next (immediate) connection attempt for this account.
         * Some XMPP servers use buggy TLS stacks that incorrectly report their capabilities, which breaks things with 10.8's new support
         * for TLS 1.1 and 1.2.
         */
        purple_debug_info("cdsa", "SSLHandshake reported that the server rejected our MAC, which most likely means it lied about the TLS versions it supports.");
        purple_debug_info("cdsa", "Setting a flag in this account to only use TLS 1.0 and below on the next connection attempt.");
    
        purple_account_set_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, true);
        if (gsc->error_cb != NULL)
            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data);
        purple_ssl_close(gsc);
        return;
    } else if (err != noErr) {
		if(err == errSSLWouldBlock)
			return;
		fprintf(stderr,"cdsa: SSLHandshake failed with error %d\n",(int)err);
		purple_debug_error("cdsa", "SSLHandshake failed with error %d\n",(int)err);
		if (gsc->error_cb != NULL)
			gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
						  gsc->connect_cb_data);
		
		purple_ssl_close(gsc);
		return;
	}
	
	SSLCipherSuite cipher;
	SSLProtocol protocol;
	
	err = SSLGetNegotiatedCipher(cdsa_data->ssl_ctx, &cipher);
	
	if (err == noErr) {
		err = SSLGetNegotiatedProtocolVersion(cdsa_data->ssl_ctx, &protocol);
		
		purple_debug_info("cdsa", "Your connection is using %s with %s encryption, using %s for message authentication and %s key exchange (%X).\n",
						  SSLVersionToString(protocol),
						  SSLCipherName(cipher),
						  SSLMACName(cipher),
						  SSLKeyExchangeName(cipher),
						  cipher);
	}
	
	purple_input_remove(cdsa_data->handshake_handler);
	cdsa_data->handshake_handler = 0;
	
	purple_debug_info("cdsa", "SSL_connect: verifying certificate\n");
	
	if(certificate_ui_cb) { // does the application want to verify the certificate?
		struct query_cert_userdata *userdata = (struct query_cert_userdata*)malloc(sizeof(struct query_cert_userdata));
		size_t hostnamelen = 0;
		
		SSLGetPeerDomainNameLength(cdsa_data->ssl_ctx, &hostnamelen);
		userdata->hostname = (char*)malloc(hostnamelen+1);
		SSLGetPeerDomainName(cdsa_data->ssl_ctx, userdata->hostname, &hostnamelen);
		userdata->hostname[hostnamelen] = '\0'; // just make sure it's zero-terminated
		userdata->cond = cond;
		userdata->gsc = gsc;
		SSLCopyPeerCertificates(cdsa_data->ssl_ctx, &userdata->certs);
		
		certificate_ui_cb(gsc, userdata->hostname, userdata->certs, query_cert_result, userdata);
	} else {
		purple_debug_info("cdsa", "SSL_connect complete (did not verify certificate)\n");
		
		/* SSL connected now */
		gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
	}
	
	SSLCipherSuite suite;
	SSLGetNegotiatedCipher(cdsa_data->ssl_ctx, &suite);
	
	purple_debug_info("cdsa", "Using cipher %x.\n", suite);
}
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;
}
int dtls_client(const char *hostname, int bypass)
{
    int fd;
    int tlsfd;
    struct sockaddr_in sa;
    
    printf("Running dtls_client test with hostname=%s, bypass=%d\n", hostname, bypass);

    if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) {
        perror("socket");
        exit(-1);
    }
    
    memset((char *) &sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(PORT);
    if (inet_aton(hostname, &sa.sin_addr)==0) {
        fprintf(stderr, "inet_aton() failed\n");
        exit(1);
    }
    
    if(connect(fd, (struct sockaddr *)&sa, sizeof(sa))==-1)
    {
        perror("connect");
        return errno;
    }
    
    /* Change to non blocking io */
    fcntl(fd, F_SETFL, O_NONBLOCK);
    
    SSLRecordContextRef c=(intptr_t)fd;
    
    
    OSStatus            ortn;
    SSLContextRef       ctx = NULL;
    
    SSLClientCertificateState certState;
    SSLCipherSuite negCipher;
    SSLProtocol negVersion;
    
	/*
	 * Set up a SecureTransport session.
	 */
    
    ctx = SSLCreateContextWithRecordFuncs(kCFAllocatorDefault, kSSLClientSide, kSSLDatagramType, &TLSSocket_Funcs);
    if(!ctx) {
        printSslErrStr("SSLCreateContextWithRecordFuncs", -1);
        return -1;
    }

    printf("Attaching filter\n");
    ortn = TLSSocket_Attach(fd);
    if(ortn) {
		printSslErrStr("TLSSocket_Attach", ortn);
		return ortn;        
    }
    
    if(bypass) {
        tlsfd = open("/dev/tlsnke", O_RDWR);
        if(tlsfd<0) {
            perror("opening tlsnke dev");
            exit(-1);
        }
    }

    ortn = SSLSetRecordContext(ctx, c);
	if(ortn) {
		printSslErrStr("SSLSetRecordContext", ortn);
		return ortn;
	}
    
    ortn = SSLSetMaxDatagramRecordSize(ctx, 600);
    if(ortn) {
		printSslErrStr("SSLSetMaxDatagramRecordSize", ortn);
        return ortn;
	}
    
    /* Lets not verify the cert, which is a random test cert */
    ortn = SSLSetEnableCertVerify(ctx, false);
    if(ortn) {
        printSslErrStr("SSLSetEnableCertVerify", ortn);
        return ortn;
    }
    
    ortn = SSLSetCertificate(ctx, server_chain());
    if(ortn) {
        printSslErrStr("SSLSetCertificate", ortn);
        return ortn;
    }
    
    printf("Handshake...\n");

    do {
		ortn = SSLHandshake(ctx);
	    if(ortn == errSSLWouldBlock) {
            /* keep UI responsive */
            sslOutputDot();
	    }
    } while (ortn == errSSLWouldBlock);
    
    
    SSLGetClientCertificateState(ctx, &certState);
	SSLGetNegotiatedCipher(ctx, &negCipher);
	SSLGetNegotiatedProtocolVersion(ctx, &negVersion);
    
    int count;
    size_t len;
    ssize_t sreadLen, swriteLen;
    size_t readLen, writeLen;

    char buffer[BUFLEN];
    
    count = 0;
    while(count<COUNT) {
        int timeout = 10000;
        
        snprintf(buffer, BUFLEN, "Message %d", count);
        len = strlen(buffer);
        
        if(bypass) {
            /* Send data through the side channel, kind of like utun would */
            swriteLen=write(tlsfd, buffer, len);
            if(swriteLen<0) {
                perror("write to tlsfd");
                break;
            }
            writeLen=swriteLen;
        } else {
            ortn=SSLWrite(ctx, buffer, len, &writeLen);
            if(ortn) {
                printSslErrStr("SSLWrite", ortn);
                break;
            }
        }

        printf("Wrote %lu bytes\n", writeLen);
        
        count++;
        
        if(bypass) {
            do {
                sreadLen=read(tlsfd, buffer, BUFLEN);
            } while((sreadLen==-1) && (errno==EAGAIN) && (timeout--));
            if((sreadLen==-1) && (errno==EAGAIN)) {
                printf("Read timeout...\n");
                continue;
            }
            if(sreadLen<0) {
                perror("read from tlsfd");
                break;
            }
            readLen=sreadLen;
        }
        else {
            do {
                ortn=SSLRead(ctx, buffer, BUFLEN, &readLen);
            } while((ortn==errSSLWouldBlock) && (timeout--));
            if(ortn==errSSLWouldBlock) {
                printf("SSLRead timeout...\n");
                continue;
            }
            if(ortn) {
                printSslErrStr("SSLRead", ortn);
                break;
            }
        }

        buffer[readLen]=0;
        printf("Received %lu bytes: %s\n", readLen, buffer);
        
    }
    
    SSLClose(ctx);
    
    SSLDisposeContext(ctx);
    
    return ortn;
}
Пример #22
0
int main_impl(const char *deviceName, const char *serverName, int port, const char *certFile, const char *keyFile, const char *caCertFile, const char *logFile)
{
	struct hostent *srv;
	int dev = -1;
	FILE* log = NULL;
	SOCKET sock = SOCKET_ERROR;
	struct sockaddr_in srvaddr;
	int keepalive = 1, hasCert, retCode;
	SSL_CTX *sslContext = NULL;
	SSL *sslSession = NULL;
	int sslRead;
	char b[100];

	// initial validation

	if (port < 1 || port > 65535)
	{
		printf("Port must be between 1 and 65535\n");
		return 3;
	}

	srv = gethostbyname(serverName);
	if (srv == NULL)
	{
		srv = gethostbyaddr(serverName, 4, AF_INET);
		if (srv == NULL)
		{
			printf("Cannot resolve server address: %s\n", serverName);
			return 3;
		}
	}

	hasCert = HAS_STR(certFile) + HAS_STR(keyFile) + HAS_STR(caCertFile);
	if (hasCert != 0 && hasCert != 3)
	{
		printf("Either all or none certificates must be specified\n");
		return 3;
	}

	// initial validation complete
	// connecting to server and opening device

	OpenLog(logFile);

	INFO("Opening device...\n");

	dev = open(deviceName, O_BINARY | O_RDWR | O_NOCTTY);
	if (dev == -1)
	{
		ERR("Failed to open device: %s\n", strerror(errno));
		RETURN(3);
	}

	DBG("Configuring device...\n");

	ConfigureDevice(dev);

	DBG("Creating a socket...\n");

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == SOCKET_ERROR)
	{
		ERR("Cannot create a socket\n");
		RETURN(3);
	}

	DBG("Enabling keep-alives on the socket...\n");
	if (0 != setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))
	{
		WARN("Failed to enable keep-alives\n");
	}
	
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons((u_short) port);
	memcpy(&srvaddr.sin_addr, srv->h_addr_list[0], 4);
	
	INFO("Connecting to server...\n");

	if (0 != connect(sock, (const struct sockaddr *) &srvaddr, sizeof(srvaddr)))
	{
		ERR("Cannot connect to %s:%d\n", serverName, port);
		RETURN(3);
	}

	if (0 != hasCert)
	{
		if (0 != SSLInit())
		{
			RETURN(3);
		}

		sslContext = SSLCreateContext(certFile, keyFile, caCertFile);
		if (sslContext == NULL)
		{
			RETURN(3);
		}

		sslSession = SSLHandshake(sock, sslContext);
		if (sslSession == NULL)
		{
			RETURN(3);
		}

		sslRead = SSL_read(sslSession, b, sizeof(b));
		switch (SSL_get_error(sslSession, sslRead))
		{
		case SSL_ERROR_NONE:
			break;

		case SSL_ERROR_ZERO_RETURN:
			DBG("Server has closed the SSL connection\n");

			SSLCloseSession(sslSession);

			sslSession = SSLHandshake(sock, sslContext);
			if (sslSession == NULL)
			{
				RETURN(3);
			}
			break;

		default:
			DEFAULT_HANDLER("Failed to receive server response", sslSession, sslRead);
			RETURN(3);
		}
	}
	
	
	IsTerminating = 0;

	signal(SIGTERM, sig_handler);
	signal(SIGINT, sig_handler);
#ifdef WIN32
	signal(SIGBREAK, sig_handler);
#endif

	retCode = worker(dev, sock, sslSession, certFile, keyFile, caCertFile);

	RETURN(retCode);
}
Пример #23
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;
}
Пример #24
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;
}