コード例 #1
0
ファイル: tcp.c プロジェクト: pandyxu/corona
static inline void
errno_cnt_dump(FILE *fp, char *name, errno_cnt_t *ecp) {
    int i;

    if (errno_cnt_empty(ecp)) {
        return;
    }

    fprintf(fp, "%s: ", name);
    for (i = 0; i <= ELAST; i++) {
        char *name;

        if ((*ecp)[i] == 0) {
            continue;
        }

        if ((name = errno_name(i))) {
            fprintf(fp, "%s", name);
        } else {
            fprintf(fp, "%d", i);
        }            

        fprintf(fp, "=%lu ", (*ecp)[i]);
    }
    fprintf(fp, "\n");
}
コード例 #2
0
ファイル: tls.c プロジェクト: lavabit/magma
/**
 * @brief	Return -1 if the connection is invalid, 0 if the operation should be retried, or a positive number indicating the
 * 			number of bytes processed.
 */
int tls_continue(TLS *tls, int result, int syserror) {

	int holder = 0;
	unsigned long tlserror = 0;
	chr_t *message = MEMORYBUF(1024);

	// Check that the daemon hasn't initiated a shutdown.
	if (!status()) return -1;

	// Data was processed, so there is no need to retry the operation.
	else if (result > 0) return result;

	// Switch statement will process neutral/negative result codes.
	switch ((holder = SSL_get_error_d(tls, result))) {

		// This result is expected when no more data is expected, such as when the end-of-file terminator ir reached.
		case SSL_ERROR_ZERO_RETURN:
			// This indicates a non-error occurred, such as a timeout lapse, or shutdown/close notifcation is reccieved.
		case SSL_ERROR_NONE:
			result = -1;
			break;

			// This indicates the operation should be retried, possibly because of a renegotiation, or other out-of-band
			// interrupted the operation.
		case SSL_ERROR_WANT_WRITE:
		case SSL_ERROR_WANT_READ:
			result = 0;
			break;

			// A TLS error ocurred, check the error stack to find out more.
		case SSL_ERROR_SSL:
			ERR_error_string_n_d((tlserror = ERR_get_error_d()), message, 1024);
			log_pedantic("A TLS error occurred. { error = %lu / message = %s", tlserror, message);
			result = -1;
			break;

			// Indicates the call returned because of a transport error. Check errno for more information.
		case SSL_ERROR_SYSCALL:
			log_pedantic("A TCP error occurred. { errno = %i / error = %s / message = %s }", syserror, errno_name(syserror),
				strerror_r(syserror, message, 1024));
			result = -1;
			break;

		default:
			log_pedantic("An unexpected TLS error result was encountered. { error = %i }", holder);
			result = 0;
			break;
	}

	return result;
}
コード例 #3
0
ファイル: tls.c プロジェクト: lavabit/magma
/**
 * @brief	Create a TLS session for a file descriptor, and accept the client TLS/SSL handshake.
 * @see		SSL_accept()
 * @see		BIO_new_socket()
 * @param	server	a server object which contains the underlying SSL context.
 * @param	sockd	the file descriptor of the TCP connection to be made SSL-ready.
 * @param	flags	passed to BIO_new_socket(), determines whether the socket is shut down when the BIO is freed.
 */
TLS * tls_server_alloc(void *server, int sockd, int flags) {

	SSL *tls;
	BIO *bio;
	server_t *local = server;
	int_t error = 0, result = 0, counter = 0;

	// Clear the error state, so we get accurate indications of a problem.
	errno = 0;
	ERR_clear_error_d();

#ifdef MAGMA_PEDANTIC
	if (!local) {
		log_pedantic("Passed a NULL server pointer.");
	}
	else if (!local->tls.context) {
		log_pedantic("Passed a NULL SSL context pointer.");
	}
	else if (sockd < 0) {
		log_pedantic("Passed an invalid socket. { sockd = %i }", sockd);
	}
#endif

	if (!local || !local->tls.context || sockd < 0) {
		return NULL;
	}
	else if (!(tls = SSL_new_d(local->tls.context)) || !(bio = BIO_new_socket_d(sockd, flags))) {
		log_pedantic("TLS/BIO allocation error. { error = %s }", ssl_error_string(MEMORYBUF(256), 256));

		if (tls) {
			SSL_free_d(tls);
		}

		return NULL;
	}

	SSL_set_bio_d(tls, bio, bio);
	SSL_set_accept_state_d(tls);

	// If the result code indicates a handshake error, but the TCP connection is still alive, we retry the handshake.
	do {
		// Attempt the server connection setup.
		if ((result = SSL_accept_d(tls)) <= 0 && status()) {

			switch ((error = SSL_get_error_d(tls, result))) {

				// Log these errors with extra information.
				case (SSL_ERROR_SSL):
					log_pedantic("TLS accept error. { accept = %i / error = SSL_ERROR_SSL, message = %s }", result,
						ssl_error_string(MEMORYBUF(512), 512));
					break;
				case (SSL_ERROR_SYSCALL):
					log_pedantic("TLS accept error. { accept = %i / error = SSL_ERROR_SYSCALL / errno = %i / message = %s }", result,
						errno, errno_name(errno));
					break;

				// A zero return indicates a socket shutdown. The latter should never happen.
				case (SSL_ERROR_ZERO_RETURN):
				case (SSL_ERROR_NONE):
					break;

				default:
					log_pedantic("TLS accept error. { accept = %i / error = %i }", result, error);
					break;
			}
		}

	} while (result < 0 && counter++ < 10);

	if (result != 1) {
		SSL_free_d(tls);
		return NULL;
	}

	return tls;
}