int FlushBuffer(StreamSocket* sock)
	{
		// If GnuTLS has some data buffered, write it
		if (gbuffersize)
			return HandleWriteRet(sock, gnutls_record_uncork(this->sess, 0));
		return 1;
	}
Exemple #2
0
int cstp_uncork(worker_st *ws)
{
	if (ws->session) {
		return gnutls_record_uncork(ws->session, GNUTLS_RECORD_WAIT);
	} else {
		int state = 0;
#if defined(__linux__)
		setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
#elif defined(TCP_NOPUSH)
		setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_NOPUSH, &state, sizeof(state));
#endif
		return 0;
	}
}
Exemple #3
0
static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex)
{
    gnutls_session_t session = tls->sys;
    ssize_t val;

    /* Flush any pending data */
    val = gnutls_record_uncork(session, 0);
    if (val < 0)
        return gnutls_Error(tls, val);

    val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
    if (val < 0)
        return gnutls_Error(tls, val);

    return 0;
}
Exemple #4
0
static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
                            unsigned count)
{
    gnutls_session_t session = tls->sys;
    ssize_t val;

    if (!gnutls_record_check_corked(session))
    {
        gnutls_record_cork(session);

        while (count > 0)
        {
            val = gnutls_record_send(session, iov->iov_base, iov->iov_len);
            if (val < (ssize_t)iov->iov_len)
                break;

            iov++;
            count--;
        }
    }

    val = gnutls_record_uncork(session, 0);
    return (val < 0) ? gnutls_Error (tls, val) : val;
}
static void do_gnutls_write(liGnuTLSFilter *f) {
	const ssize_t blocksize = 16*1024; /* 16k */
	char *block_data;
	off_t block_len;
	ssize_t r;
	off_t write_max;
#ifdef USE_CORK
	gboolean corked = FALSE;
#endif
	liChunkQueue *cq = f->plain_drain.out;

	f_acquire(f);

	f->write_wants_read = FALSE;

	/* use space in (encrypted) outgoing buffer as amounts of bytes we try to write from (plain) output
	 * don't care if we write a little bit more than the limit allowed */
	write_max = li_chunkqueue_limit_available(f->crypt_source.out);
	LI_FORCE_ASSERT(write_max >= 0); /* we set a limit! */
	if (0 == write_max) goto out;
	/* if we start writing, try to write at least blocksize bytes */
	if (write_max < blocksize) write_max = blocksize;

	if (NULL != f->session && !f->initial_handshaked_finished && !do_gnutls_handshake(f, TRUE)) goto out;
	if (NULL == f->session) {
		f_abort_gnutls(f);
		goto out;
	}

#ifdef USE_CORK
	if (0 != cq->length && cq->queue.length > 1) {
		corked = TRUE;
		gnutls_record_cork(f->session);
	}
#endif

	do {
		GError *err = NULL;
		liChunkIter ci;

		if (0 == cq->length) break;

		ci = li_chunkqueue_iter(cq);
		switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, &err)) {
		case LI_HANDLER_GO_ON:
			break;
		case LI_HANDLER_ERROR:
			if (NULL != err) {
				_ERROR(f->srv, f->wrk, f->log_context, "Couldn't read data from chunkqueue: %s", err->message);
				g_error_free(err);
			}
			/* fall through */
		default:
			f_abort_gnutls(f);
			goto out;
		}

		r = gnutls_record_send(f->session, block_data, block_len);
		if (r <= 0) {
			do_handle_error(f, "gnutls_record_send", r, TRUE);
			goto out;
		}

		li_chunkqueue_skip(cq, r);
		write_max -= r;
	} while (r == block_len && write_max > 0);

	if (cq->is_closed && 0 == cq->length) {
		r = gnutls_bye(f->session, GNUTLS_SHUT_RDWR);
		switch (r) {
		case GNUTLS_E_SUCCESS:
		case GNUTLS_E_AGAIN:
		case GNUTLS_E_INTERRUPTED:
			f->plain_source.out->is_closed = TRUE;
			f->crypt_source.out->is_closed = TRUE;
			f->crypt_drain.out->is_closed = TRUE;
			li_stream_disconnect(&f->crypt_source); /* plain in -> crypt out */
			f_close_gnutls(f);
			break;
		default:
			do_handle_error(f, "gnutls_bye", r, TRUE);
			f_abort_gnutls(f);
			break;
		}
	} else if (0 < cq->length && 0 != li_chunkqueue_limit_available(f->crypt_source.out)) {
		li_stream_again_later(&f->plain_drain);
	}

out:
#ifdef USE_CORK
	if (NULL != f->session && corked) {
		corked = TRUE;
		gnutls_record_uncork(f->session, 0);
	}
#endif

	f_release(f);
}
Exemple #6
0
static void server(int fd)
{
	int ret;
	char buffer[MAX_BUF + 1];
	gnutls_session_t session;
	gnutls_anon_server_credentials_t anoncred;
	/* this must be called once in the program
	 */
	global_init();

	if (debug) {
		gnutls_global_set_log_function(server_log_func);
		gnutls_global_set_log_level(4711);
	}

	gnutls_anon_allocate_server_credentials(&anoncred);

	gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
	gnutls_dtls_set_mtu(session, 1500);

	/* avoid calling all the priority functions, since the defaults
	 * are adequate.
	 */
	gnutls_priority_set_direct(session,
				   "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
				   NULL);

	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_transport_set_int(session, fd);

	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
	if (ret < 0) {
		close(fd);
		gnutls_deinit(session);
		terminate();
		fail("server: Handshake has failed (%s)\n\n",
		     gnutls_strerror(ret));
	}
	if (debug)
		success("server: Handshake was completed\n");

	if (debug)
		success("server: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	/* see the Getting peer's information example */
	/* print_info(session); */

	/* avoid uninitialized warnings */
	memset(buffer, 1, sizeof(buffer));

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session) + 12);
	if (ret != GNUTLS_E_LARGE_PACKET) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session) + 5048);
	if (ret != GNUTLS_E_LARGE_PACKET) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session));
	if (ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	gnutls_dtls_set_mtu(session, MAX_MTU);
	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session) + 12);
	if (ret != GNUTLS_E_LARGE_PACKET) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session) + 5048);
	if (ret != GNUTLS_E_LARGE_PACKET) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session));
	if (ret > 16384 || ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	/* test cork and uncork */
	gnutls_record_cork(session);

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session));
	if (ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret = gnutls_record_uncork(session, 0);
	if (ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	gnutls_record_cork(session);

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session) - 16);
	if (ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret =
	    gnutls_record_send(session, buffer,
				gnutls_dtls_get_data_mtu(session));
	if (ret != GNUTLS_E_LARGE_PACKET) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	ret = gnutls_record_uncork(session, GNUTLS_RECORD_WAIT);
	if (ret < 0) {
		terminate();
		fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret));
	}

	/* do not wait for the peer to close the connection.
	 */
	gnutls_bye(session, GNUTLS_SHUT_WR);

	close(fd);
	gnutls_deinit(session);

	gnutls_anon_free_server_credentials(anoncred);

	gnutls_global_deinit();

	if (debug)
		success("server: finished\n");
}