Пример #1
0
int
SecureSocket::secureWrite(const void* buffer, int size, int& wrote)
{
	if (m_ssl->m_ssl != NULL) {
		LOG((CLOG_DEBUG2 "writing secure socket:%p", this));

		wrote = SSL_write(m_ssl->m_ssl, buffer, size);
		
		static int retry;

		// Check result will cleanup the connection in the case of a fatal
		checkResult(wrote, retry);

		if (retry) {
			return 0;
		}

		if (isFatal()) {
			return -1;
		}
	}
	// According to SSL spec, r must not be negative and not have an error code
	// from SSL_get_error(). If this happens, it is itself an error. Let the
	// parent handle the case
	return wrote;
}
Пример #2
0
int
SecureSocket::secureRead(void* buffer, int size, int& read)
{
	if (m_ssl->m_ssl != NULL) {
		LOG((CLOG_DEBUG2 "reading secure socket"));
		read = SSL_read(m_ssl->m_ssl, buffer, size);
		
		static int retry;

		// Check result will cleanup the connection in the case of a fatal
		checkResult(read, retry);
		
		if (retry) {
			return 0;
		}

		if (isFatal()) {
			return -1;
		}
	}
	// According to SSL spec, the number of bytes read must not be negative and
	// not have an error code from SSL_get_error(). If this happens, it is
	// itself an error. Let the parent handle the case
	return read;
}
Пример #3
0
void
SecureSocket::close()
{
	isFatal(true);

	SSL_shutdown(m_ssl->m_ssl);

	TCPSocket::close();
}
Пример #4
0
void isr_handler(registers_t* regs)
{

  if(exception_depth++ >= 3){
    printf("Exception depth exceeded 3");
    while(1);
  }
  
  if((regs->int_no < 32) && (isFatal(regs->int_no))){

    terminal_bluescreen();
    char* name = interrupt_name(regs->int_no);

    printf("\t\t\t\t\t\tSOMETHING JUST WENT VERY WRONG\n\nI'd like to");
    printf(" interject for a moment.  What you're referring to as:\n\n\t");
    printf("Interrupt %d\n\nIs in fact, a fatal exception, ", (int) regs->int_no);
    printf("or as I've recently taken to  calling it:\n\n");
    printf("\t%s with error code %p\n", name, (void *) regs->err_code);
    
    //Halt the machine
    while(1);
    
  }

  if(regs->int_no >= 32){
    //Handle our IRQs
    //interrupt numbers 0-31 are reserved by intel, so subtract 32
    //to get the isa irq code.  32 is an arbitary number decided in the
    //PIC initialization code
    int isa_irq = (regs->int_no - 32);
    
    switch(isa_irq){
    case 0:
      //Programmable interval timer interrupt
      break;
    case 1:
      //Keyboard interrupt
      handle_keyboard_interrupt();
      break;
    }
    
    PIC_sendEOI(regs->int_no);
  }else{
    //It is an exception we can (and should) handle
    switch(regs->int_no){
    case 14:
      handle_page_fault(regs->err_code);
      break;
    }
  }

  exception_depth = 0;
  return;
}
Пример #5
0
int
SecureSocket::secureConnect(int socket)
{
	createSSL();

	// attach the socket descriptor
	SSL_set_fd(m_ssl->m_ssl, socket);
	
	LOG((CLOG_DEBUG2 "connecting secure socket"));
	int r = SSL_connect(m_ssl->m_ssl);
	
	static int retry;

	checkResult(r, retry);

	if (isFatal()) {
		LOG((CLOG_ERR "failed to connect secure socket"));
		return -1;
	}

	// If we should retry, not ready and return 0
	if (retry > 0) {
		LOG((CLOG_DEBUG2 "retry connect secure socket"));
		m_secureReady = false;
		return 0;
	}

	// No error, set ready, process and return ok
	m_secureReady = true;
	if (verifyCertFingerprint()) {
		LOG((CLOG_INFO "connected to secure socket"));
		if (!showCertificate()) {
			disconnect();
			return -1;// Cert fail, error
		}
	}
	else {
		LOG((CLOG_ERR "failed to verify server certificate fingerprint"));
		disconnect();
		return -1; // Fingerprint failed, error
	}
	LOG((CLOG_DEBUG2 "connected secure socket"));
	const SSL_CIPHER* cipher = SSL_get_current_cipher(m_ssl->m_ssl);
	if(cipher != NULL) {
		char * cipherVersion = SSL_CIPHER_description(cipher, NULL, 0);
		if(cipherVersion != NULL) {
			LOG((CLOG_INFO "%s", cipherVersion));
			OPENSSL_free(cipherVersion);
		}
	}
	return 1;
}
Пример #6
0
int
SecureSocket::secureConnect(int socket)
{
	createSSL();

	// attach the socket descriptor
	SSL_set_fd(m_ssl->m_ssl, socket);
	
	LOG((CLOG_DEBUG2 "connecting secure socket"));
	int r = SSL_connect(m_ssl->m_ssl);
	
	static int retry;

	checkResult(r, retry);

	if (isFatal()) {
		LOG((CLOG_ERR "failed to connect secure socket"));
		retry = 0;
		return -1;
	}

	// If we should retry, not ready and return 0
	if (retry > 0) {
		LOG((CLOG_DEBUG2 "retry connect secure socket"));
		m_secureReady = false;
		ARCH->sleep(s_retryDelay);
		return 0;
	}

	retry = 0;
	// No error, set ready, process and return ok
	m_secureReady = true;
	if (verifyCertFingerprint()) {
		LOG((CLOG_INFO "connected to secure socket"));
		if (!showCertificate()) {
			disconnect();
			return -1;// Cert fail, error
		}
	}
	else {
		LOG((CLOG_ERR "failed to verify server certificate fingerprint"));
		disconnect();
		return -1; // Fingerprint failed, error
	}
	LOG((CLOG_DEBUG2 "connected secure socket"));
	if (CLOG->getFilter() >= kDEBUG1) {
		showSecureCipherInfo();
	}
	showSecureConnectInfo();
	return 1;
}
Пример #7
0
int
SecureSocket::secureAccept(int socket)
{
	createSSL();

	// set connection socket to SSL state
	SSL_set_fd(m_ssl->m_ssl, socket);
	
	LOG((CLOG_DEBUG2 "accepting secure socket"));
	int r = SSL_accept(m_ssl->m_ssl);
	
	static int retry;

	checkResult(r, retry);

	if (isFatal()) {
		// tell user and sleep so the socket isn't hammered.
		LOG((CLOG_ERR "failed to accept secure socket"));
		LOG((CLOG_INFO "client connection may not be secure"));
		m_secureReady = false;
		ARCH->sleep(1);
		return -1; // Failed, error out
	}

	// If not fatal and no retry, state is good
	if (retry == 0) {
		m_secureReady = true;
		LOG((CLOG_INFO "accepted secure socket"));
		const SSL_CIPHER* cipher = SSL_get_current_cipher(m_ssl->m_ssl);
		if(cipher != NULL) {
			char * cipherVersion = SSL_CIPHER_description(cipher, NULL, 0);
			if(cipherVersion != NULL) {
				LOG((CLOG_INFO "%s", cipherVersion));
				OPENSSL_free(cipherVersion);
			}
		}
		return 1;
	}

	// If not fatal and retry is set, not ready, and return retry
	if (retry > 0) {
		LOG((CLOG_DEBUG2 "retry accepting secure socket"));
		m_secureReady = false;
		return 0;
	}

	// no good state exists here
	LOG((CLOG_ERR "unexpected state attempting to accept connection"));
	return -1;
}
Пример #8
0
int
SecureSocket::secureAccept(int socket)
{
	createSSL();

	// set connection socket to SSL state
	SSL_set_fd(m_ssl->m_ssl, socket);
	
	LOG((CLOG_DEBUG2 "accepting secure socket"));
	int r = SSL_accept(m_ssl->m_ssl);
	
	static int retry;

	checkResult(r, retry);

	if (isFatal()) {
		// tell user and sleep so the socket isn't hammered.
		LOG((CLOG_ERR "failed to accept secure socket"));
		LOG((CLOG_INFO "client connection may not be secure"));
		m_secureReady = false;
		ARCH->sleep(1);
		retry = 0;
		return -1; // Failed, error out
	}

	// If not fatal and no retry, state is good
	if (retry == 0) {
		m_secureReady = true;
		LOG((CLOG_INFO "accepted secure socket"));
		if (CLOG->getFilter() >= kDEBUG1) {
			showSecureCipherInfo();
		}
		showSecureConnectInfo();
		return 1;
	}

	// If not fatal and retry is set, not ready, and return retry
	if (retry > 0) {
		LOG((CLOG_DEBUG2 "retry accepting secure socket"));
		m_secureReady = false;
		ARCH->sleep(s_retryDelay);
		return 0;
	}

	// no good state exists here
	LOG((CLOG_ERR "unexpected state attempting to accept connection"));
	return -1;
}
Пример #9
0
SecureSocket::~SecureSocket()
{
	isFatal(true);
	if (m_ssl->m_ssl != NULL) {
		SSL_shutdown(m_ssl->m_ssl);

		SSL_free(m_ssl->m_ssl);
		m_ssl->m_ssl = NULL;
	}
	if (m_ssl->m_context != NULL) {
		SSL_CTX_free(m_ssl->m_context);
		m_ssl->m_context = NULL;
	}
	ARCH->sleep(1);
	delete m_ssl;
}
Пример #10
0
void
SecureSocket::checkResult(int status, int& retry)
{
	// ssl errors are a little quirky. the "want" errors are normal and
	// should result in a retry.

	int errorCode = SSL_get_error(m_ssl->m_ssl, status);

	switch (errorCode) {
	case SSL_ERROR_NONE:
		retry = 0;
		// operation completed
		break;

	case SSL_ERROR_ZERO_RETURN:
		// connection closed
		isFatal(true);
		LOG((CLOG_DEBUG "ssl connection closed"));
		break;

	case SSL_ERROR_WANT_READ:
	case SSL_ERROR_WANT_WRITE:
	case SSL_ERROR_WANT_CONNECT:
	case SSL_ERROR_WANT_ACCEPT:
		// it seems like these sort of errors are part of openssl's normal behavior,
		// so we should expect a very high amount of these. sleeping doesn't seem to
		// help... maybe you just have to swallow the errors (yuck).
		retry++;
		LOG((CLOG_DEBUG2 "passive ssl error, error=%d, attempt=%d", errorCode, retry));
		break;

	case SSL_ERROR_SYSCALL:
		LOG((CLOG_ERR "ssl error occurred (system call failure)"));
		if (ERR_peek_error() == 0) {
			if (status == 0) {
				LOG((CLOG_ERR "eof violates ssl protocol"));
			}
			else if (status == -1) {
				// underlying socket I/O reproted an error
				try {
					ARCH->throwErrorOnSocket(getSocket());
				}
				catch (XArchNetwork& e) {
					LOG((CLOG_ERR "%s", e.what()));
				}
			}
		}

		isFatal(true);
		break;

	case SSL_ERROR_SSL:
		LOG((CLOG_ERR "ssl error occurred (generic failure)"));
		isFatal(true);
		break;

	default:
		LOG((CLOG_ERR "ssl error occurred (unknown failure)"));
		isFatal(true);
		break;
	}

	// If the retry max would exceed the allowed, treat it as a fatal error
	if (retry > maxRetry()) {
		LOG((CLOG_ERR "passive ssl error limit exceeded: %d", retry));
		isFatal(true);
	}

	if (isFatal()) {
		retry = 0;
		showError();
		disconnect();
	}
}
Пример #11
0
void
SecureSocket::checkResult(int status, int& retry)
{
	// ssl errors are a little quirky. the "want" errors are normal and
	// should result in a retry.

	int errorCode = SSL_get_error(m_ssl->m_ssl, status);

	switch (errorCode) {
	case SSL_ERROR_NONE:
		retry = 0;
		// operation completed
		break;

	case SSL_ERROR_ZERO_RETURN:
		// connection closed
		isFatal(true);
		LOG((CLOG_DEBUG "ssl connection closed"));
		break;

	case SSL_ERROR_WANT_READ:
		retry++;
		LOG((CLOG_DEBUG2 "want to read, error=%d, attempt=%d", errorCode, retry));
		break;

	case SSL_ERROR_WANT_WRITE:
		// Need to make sure the socket is known to be writable so the impending
		// select action actually triggers on a write. This isn't necessary for 
		// m_readable because the socket logic is always readable
		m_writable = true;
		retry++;
		LOG((CLOG_DEBUG2 "want to write, error=%d, attempt=%d", errorCode, retry));
		break;

	case SSL_ERROR_WANT_CONNECT:
		retry++;
		LOG((CLOG_DEBUG2 "want to connect, error=%d, attempt=%d", errorCode, retry));
		break;

	case SSL_ERROR_WANT_ACCEPT:
		retry++;
		LOG((CLOG_DEBUG2 "want to accept, error=%d, attempt=%d", errorCode, retry));
		break;

	case SSL_ERROR_SYSCALL:
		LOG((CLOG_ERR "ssl error occurred (system call failure)"));
		if (ERR_peek_error() == 0) {
			if (status == 0) {
				LOG((CLOG_ERR "eof violates ssl protocol"));
			}
			else if (status == -1) {
				// underlying socket I/O reproted an error
				try {
					ARCH->throwErrorOnSocket(getSocket());
				}
				catch (XArchNetwork& e) {
					LOG((CLOG_ERR "%s", e.what()));
				}
			}
		}

		isFatal(true);
		break;

	case SSL_ERROR_SSL:
		LOG((CLOG_ERR "ssl error occurred (generic failure)"));
		isFatal(true);
		break;

	default:
		LOG((CLOG_ERR "ssl error occurred (unknown failure)"));
		isFatal(true);
		break;
	}

	if (isFatal()) {
		retry = 0;
		showError();
		disconnect();
	}
}