Example #1
0
ssize_t
fetch_ssl_read_wrapper(SSL *ssl, char *buf, size_t buflen)
{
#ifdef NO_SANDBOX
	return (fetch_ssl_read(ssl, buf, buflen));
#else
	return (fetch_ssl_read_insandbox(buf, buflen));
#endif
}
Example #2
0
/* Called in sandbox and wraps the actual fetch_ssl_read */
static void
sandbox_fetch_ssl_read(struct sandbox_cb *scb, uint32_t opno, uint32_t seqno, char
	*buffer, size_t len)
{
	struct ssl_req req;
	struct ssl_rep *rep;
	struct iovec iov;
	size_t rep_msg_size;
	ssize_t rlen;

	if (len != sizeof(req)) {
		err(-1, "sandbox_fetch_ssl_read: received msg len %zu", len);
		return;
	}

	/* Demangle data */
	memmove(&req, buffer, sizeof(req));

	/* Type should be set correctly */
	if (req.type != SSL_READ)
		return;


	rep_msg_size = sizeof(*rep);
	if(req.rargs.len)
		rep_msg_size += req.rargs.len;

	rep = malloc(rep_msg_size);
	if(!rep) {
		DPRINTF("[XXX] malloc() failed");
		exit(-1);
	}
	rep->type = SSL_READ;
	rlen = fetch_ssl_read(sconn.ssl, rep->rbuf, req.rargs.len);
	rep->retval = rep->rbuf_len = rlen;

	iov.iov_base = rep;
	iov.iov_len = rep_msg_size;
	if (sandbox_sendrpc(scb, opno, seqno, &iov, 1) < 0)
		err(-1, "sandbox_sendrpc");
	
	/* Release resources */
	free(rep);
}
Example #3
0
/*
 * Read a character from a connection w/ timeout
 */
ssize_t
fetch_read(conn_t *conn, char *buf, size_t len)
{
	struct timeval now, timeout, delta;
	fd_set readfds;
	ssize_t rlen, total;
	int r;
	char *start;

	if (fetchTimeout) {
		FD_ZERO(&readfds);
		gettimeofday(&timeout, NULL);
		timeout.tv_sec += fetchTimeout;
	}

	total = 0;
	start = buf;

	if (conn->cache.len > 0) {
		/*
		 * The last invocation of fetch_read was interrupted by a
		 * signal after some data had been read from the socket. Copy
		 * the cached data into the supplied buffer before trying to
		 * read from the socket again.
		 */
		total = (conn->cache.len < len) ? conn->cache.len : len;
		memcpy(buf, conn->cache.buf, total);

		conn->cache.len -= total;
		conn->cache.pos += total;
		len -= total;
		buf += total;
	}

	while (len > 0) {
		/*
		 * The socket is non-blocking.  Instead of the canonical
		 * select() -> read(), we do the following:
		 *
		 * 1) call read() or SSL_read().
		 * 2) if an error occurred, return -1.
		 * 3) if we received data but we still expect more,
		 *    update our counters and loop.
		 * 4) if read() or SSL_read() signaled EOF, return.
		 * 5) if we did not receive any data but we're not at EOF,
		 *    call select().
		 *
		 * In the SSL case, this is necessary because if we
		 * receive a close notification, we have to call
		 * SSL_read() one additional time after we've read
		 * everything we received.
		 *
		 * In the non-SSL case, it may improve performance (very
		 * slightly) when reading small amounts of data.
		 */
#ifdef WITH_SSL
		if (conn->ssl != NULL)
			rlen = fetch_ssl_read(conn->ssl, buf, len);
		else
#endif
			rlen = fetch_socket_read(conn->sd, buf, len);
		if (rlen == 0) {
			break;
		} else if (rlen > 0) {
			len -= rlen;
			buf += rlen;
			total += rlen;
			continue;
		} else if (rlen == FETCH_READ_ERROR) {
			if (errno == EINTR)
				fetch_cache_data(conn, start, total);
			return (-1);
		}
		// assert(rlen == FETCH_READ_WAIT);
		while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
			FD_SET(conn->sd, &readfds);
			gettimeofday(&now, NULL);
			delta.tv_sec = timeout.tv_sec - now.tv_sec;
			delta.tv_usec = timeout.tv_usec - now.tv_usec;
			if (delta.tv_usec < 0) {
				delta.tv_usec += 1000000;
				delta.tv_sec--;
			}
			if (delta.tv_sec < 0) {
				errno = ETIMEDOUT;
				fetch_syserr();
				return (-1);
			}
			errno = 0;
			r = select(conn->sd + 1, &readfds, NULL, NULL, &delta);
			if (r == -1) {
				if (errno == EINTR) {
					if (fetchRestartCalls)
						continue;
					/* Save anything that was read. */
					fetch_cache_data(conn, start, total);
				}
				fetch_syserr();
				return (-1);
			}
		}
	}
	return (total);
}