Exemplo n.º 1
0
/*
 * Write one byte to an empty fifo, then try to read one byte and make sure
 * we don't get back EAGAIN.
 */
static void
test_nonblocking_one_byte(void)
{
	int reader_fd, ret, timedout, writer_fd;
	ssize_t len;
	u_char ch;

	makefifo("testfifo", __func__);
	if (openfifo("testfifo", __func__, &reader_fd, &writer_fd)
	    < 0) {
		warn("test_nonblocking: openfifo: testfifo");
		cleanfifo2("testfifo", -1, -1);
		exit(-1);
	}

	if (set_nonblocking(reader_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	ch = 0xfe;
	ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_nonblocking_one_byte: timed_write");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (len != sizeof(ch)) {
		warnx("test_nonblocking_one_byte: timed_write: tried to write "
		    "%zu, wrote %zd", sizeof(ch), len);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	ch = 0xab;
	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_nonblocking_one_byte: timed_read");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (len != sizeof(ch)) {
		warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read "
		    "%zd", sizeof(ch), len);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (ch != 0xfe) {
		warnx("test_nonblocking_one_byte: timed_read: expected to read "
		    "0x%02x, read 0x%02x", 0xfe, ch);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	cleanfifo2("testfifo", reader_fd, writer_fd);
}
Exemplo n.º 2
0
Arquivo: kweb.c Projeto: klueska/kweb
static ssize_t serialized_write(struct http_connection *c,
                                const void *buf, size_t count)
{
    tpool_inform_blocking(&tpool);
    mutex_lock(&c->writelock);
    tpool_inform_unblocked(&tpool);
    ssize_t ret = timed_write(c, buf, count);
    mutex_unlock(&c->writelock);
    return ret;
}
Exemplo n.º 3
0
/*
 * First of two test cases involving a 512K buffer: write the buffer into a
 * blocking file descriptor.  We'd like to know it blocks, but the closest we
 * can get is to see if SIGALRM fired during the I/O resulting in a partial
 * write.
 */
static void
test_blocking_partial_write(void)
{
	int reader_fd, ret, timedout, writer_fd;
	u_char *buffer;
	ssize_t len;

	makefifo("testfifo", __func__);
	if (openfifo("testfifo", __func__, &reader_fd, &writer_fd)
	    < 0) {
		warn("test_blocking_partial_write: openfifo: testfifo");
		cleanfifo2("testfifo", -1, -1);
		exit(-1);
	}

	if (set_blocking(writer_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	buffer = malloc(512*1024);
	if (buffer == NULL) {
		warn("test_blocking_partial_write: malloc");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	bzero(buffer, 512*1024);

	ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_blocking_partial_write: timed_write");
		free(buffer);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	if (!timedout) {
		warnx("test_blocking_partial_write: timed_write: blocking "
		    "socket didn't time out");
		free(buffer);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	free(buffer);

	if (drain_fd(reader_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	cleanfifo2("testfifo", reader_fd, writer_fd);
}
Exemplo n.º 4
0
Arquivo: client.c Projeto: kvap/raft
static bool try_query(Message *msg, Message *answer, timeout_t *timeout) {
	int s = get_connection(timeout);
	if (s < 0) return false;

	if (timeout_happened(timeout)) {
		debug("try_query: get_connection() timed out\n");
		return false;
	}

	if (!timed_write(s, msg, sizeof(Message), timeout)) {
		debug("try_query: failed to send the query to the leader\n");
		return false;
	}

	if (!timed_read(s, answer, sizeof(Message), timeout)) {
		debug("try_query: failed to recv the answer from the leader\n");
		return false;
	}

	return true;
}
Exemplo n.º 5
0
ssize_t tls_prng_egd_read(TLS_PRNG_SRC *egd, size_t len)
{
    const char *myname = "tls_prng_egd_read";
    unsigned char buffer[UCHAR_MAX];
    ssize_t count;

    if (len <= 0)
	msg_panic("%s: bad length %ld", myname, (long) len);

    buffer[0] = 1;
    buffer[1] = (len > UCHAR_MAX ? UCHAR_MAX : len);

    if (timed_write(egd->fd, buffer, 2, egd->timeout, (void *) 0) != 2) {
	msg_info("cannot write to EGD server %s: %m", egd->name);
	return (-1);
    }
    if (timed_read(egd->fd, buffer, 1, egd->timeout, (void *) 0) != 1) {
	msg_info("cannot read from EGD server %s: %m", egd->name);
	return (-1);
    }
    count = buffer[0];
    if (count > sizeof(buffer))
	count = sizeof(buffer);
    if (count == 0) {
	msg_info("EGD server %s reports zero bytes available", egd->name);
	return (-1);
    }
    if (timed_read(egd->fd, buffer, count, egd->timeout, (void *) 0) != count) {
	msg_info("cannot read %ld bytes from EGD server %s: %m",
		 (long) count, egd->name);
	return (-1);
    }
    if (msg_verbose)
	msg_info("%s: got %ld bytes from EGD server %s", myname,
		 (long) count, egd->name);
    RAND_seed(buffer, count);
    return (count);
}
Exemplo n.º 6
0
/*
 * Write a 512K buffer to an empty fifo using a non-blocking file descriptor,
 * and make sure it doesn't block.
 */
static void
test_nonblocking_partial_write(void)
{
    int reader_fd, ret, timedout, writer_fd;
    u_char *buffer;
    ssize_t len;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_blocking_partial_write: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    if (set_nonblocking(writer_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    buffer = malloc(512*1024);
    if (buffer == NULL) {
        warn("test_blocking_partial_write: malloc");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    bzero(buffer, 512*1024);

    ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
                      __func__);
    if (ret < 0) {
        warn("test_blocking_partial_write: timed_write");
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (timedout) {
        warnx("test_blocking_partial_write: timed_write: "
              "non-blocking socket timed out");
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (len == 0 || len >= 512*1024) {
        warnx("test_blocking_partial_write: timed_write: requested "
              "%d, sent %zd", 512*1024, len);
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    free(buffer);

    if (drain_fd(reader_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", reader_fd, writer_fd);
}
Exemplo n.º 7
0
/* Parse, a-la IPv6 */
int
parse6(int fd, struct sockaddr_in6 *laddr, struct sockaddr_in6 *faddr)
{
	char	token[21], buf[BUFSIZ], *p;
	struct	sockaddr_in6 laddr2, faddr2;
	struct	passwd *pw;
	uid_t	uid;
	int	n;

	if (debug_flag && syslog_flag)
		syslog(LOG_DEBUG, "In function parse6(), from %s to %s",
		    gethost6(faddr), gethost6(laddr));

	faddr2 = *faddr;
	laddr2 = *laddr;
	lport = fport = 0;

	/* Read query from client */
	if ((n = timed_read(fd, buf, sizeof(buf) - 1, IO_TIMEOUT)) <= 0) {
		if (syslog_flag)
			syslog(LOG_NOTICE,
			    n ? "read from %s: %m" : "read from %s: EOF",
			    gethost6(faddr));
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}
	buf[n] = '\0';

	/* Pull out local and remote ports */
	p = buf;
	while (isspace(*p))
		p++;
	if ((p = strtok(p, " \t,"))) {
		lport = atoi(p);
		if ((p = strtok(NULL, " \t,")))
			fport = atoi(p);
	}

	if (lport < 1 || lport > 65535 || fport < 1 || fport > 65535) {
		if (syslog_flag)
			syslog(LOG_NOTICE,
			    "scanf: invalid-port(s): %d , %d from %s",
			    lport, fport, gethost6(faddr));
		if ((n = snprintf(buf, sizeof(buf), "%d , %d : ERROR : %s\r\n",
		    lport, fport, unknown_flag ? "UNKNOWN-ERROR" :
		    "INVALID-PORT")) >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}
	if (syslog_flag && verbose_flag)
		syslog(LOG_NOTICE, "request for (%d,%d) from %s",
		    lport, fport, gethost6(faddr));

	if (debug_flag && syslog_flag)
		syslog(LOG_DEBUG, "  After fscanf(), before k_getuid6()");

	/*
	 * Next - get the specific TCP connection and return the
	 * uid - user number.
	 */
	if (k_getuid6(&faddr2, htons(fport), laddr, htons(lport), &uid) == -1) {
		if (no_user_token_flag) {
			gentoken(token, sizeof token);
			syslog(LOG_NOTICE, "token %s == NO USER", token);
			if ((n = snprintf(buf, sizeof(buf),
			    "%d , %d : USERID : %s%s%s :%s\r\n", lport, fport,
			    opsys_name, charset_sep, charset_name, token))
			    >= sizeof(buf) || n < 0)
				n = strlen(buf);
			if (timed_write(fd, buf, n, IO_TIMEOUT) != n &&
			    syslog_flag) {
				syslog(LOG_NOTICE, "write to %s: %m",
				    gethost6(faddr));
				return 1;
			}
			return 0;
		}
		if (syslog_flag)
			syslog(LOG_DEBUG, "Returning: %d , %d : NO-USER",
			    lport, fport);
		if ((n = snprintf(buf, sizeof(buf), "%d , %d : ERROR : %s\r\n",
		    lport, fport, unknown_flag ? "UNKNOWN-ERROR" : "NO-USER"))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}
	if (debug_flag && syslog_flag)
		syslog(LOG_DEBUG, "  After k_getuid6(), before getpwuid()");

	pw = getpwuid(uid);
	if (!pw) {
		if (syslog_flag)
			syslog(LOG_WARNING,
			    "getpwuid() could not map uid (%u) to name",
			    uid);
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : USERID : %s%s%s :%u\r\n",
		    lport, fport, opsys_name, charset_sep, charset_name, uid))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}

	if (syslog_flag)
		syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s",
		    lport, fport, pw->pw_name);

	if (noident_flag && check_noident(pw->pw_dir)) {
		if (syslog_flag && verbose_flag)
			syslog(LOG_NOTICE,
			    "user %s requested HIDDEN-USER for host %s: %d, %d",
			    pw->pw_name, gethost6(faddr), lport, fport);
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : ERROR : HIDDEN-USER\r\n", lport, fport))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}

	if (userident_flag && getuserident(pw->pw_dir, token, sizeof token)) {
		syslog(LOG_NOTICE, "token \"%s\" == uid %u (%s)",
		    token, uid, pw->pw_name);
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : USERID : %s%s%s :%s\r\n", lport, fport,
		    opsys_name, charset_sep, charset_name, token))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}

	if (token_flag) {
		gentoken(token, sizeof token);
		syslog(LOG_NOTICE, "token %s == uid %u (%s)", token, uid,
		    pw->pw_name);
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : USERID : %s%s%s :%s\r\n", lport, fport,
		    opsys_name, charset_sep, charset_name, token))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}

	if (number_flag) {
		if ((n = snprintf(buf, sizeof(buf),
		    "%d , %d : USERID : %s%s%s :%u\r\n",
		    lport, fport, opsys_name, charset_sep, charset_name, uid))
		    >= sizeof(buf) || n < 0)
			n = strlen(buf);
		if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
			syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
			return 1;
		}
		return 0;
	}

	if ((n = snprintf(buf, sizeof(buf), "%d , %d : USERID : %s%s%s :%s\r\n",
	    lport, fport, opsys_name, charset_sep, charset_name, pw->pw_name))
	    >= sizeof(buf) || n < 0)
		n = strlen(buf);
	if (timed_write(fd, buf, n, IO_TIMEOUT) != n && syslog_flag) {
		syslog(LOG_NOTICE, "write to %s: %m", gethost6(faddr));
		return 1;
	}
	return 0;
}
Exemplo n.º 8
0
Arquivo: kweb.c Projeto: klueska/kweb
/* This is a wrapped version of the child web server thread */
static void __http_server(struct kqueue *q,
                          struct http_connection *c,
                          struct http_request *r)
{
    struct stat statbuf;
    int j, file_fd, buflen;
    long i = 0, ret = 0;
    char *fstr;
    char *request_line;
    char *saveptr;
    char now[RFC1123_TIME_LEN + 1];
    char mod[RFC1123_TIME_LEN + 1];

    /* Try and extract a request from the connection. */
    ret = extract_request(c, r);

    /* If there was an error, just destroy the connection, as there is
     * nothing more we can do with this connection anyway. */
    if(ret < 0) {
        logger(LOG, "Connection reset by peer.", "", c->conn.id);
        maybe_destroy_connection(q, c);
        return;
    }

    /* If there was no error, but we weren't able to extract a request, finish up
     * if we are the last one to look at the connection. */
    if(ret == 0) {
        maybe_destroy_connection(q, c);
        return;
    }

    /* Otherwise, just reenqueue the connection so another thread can grab the
     * next request and start processing it. */
    if (!c->should_close) {
        if(c->burst_length) {
            c->burst_length--;
            enqueue_connection_head(q, c);
        }
        else {
            c->burst_length = MAX_BURST;
            enqueue_connection_tail(q, c);
        }
    }

    /* Attempt to intercept the request and do something special with it. */
    struct intercept_buf ib;
    if (intercept_request(&ib, r)) {
        /* Send the necessary header info + a blank line */
        logger(LOG, "INTERCEPT URL", &request_line[4], c->conn.id);
        setDateString(NULL, now);
        setDateString(NULL, mod);
        sprintf(r->buf, page_data[OK_HEADER], VERSION,
                now, ib.mime_type, ib.size, mod);
        serialized_write(c, r->buf, strlen(r->buf));
        serialized_write(c, ib.buf, ib.size);
        free(ib.buf);
        maybe_destroy_connection(q, c);
        return;
    }

    /* If not intercepted, parse through the extracted request, grabbing only the
     * first line. */
    request_line = strtok_r(r->buf, "\r\n", &saveptr);
    if (!request_line) {
        logger(LOG, "Unterminated request buffer.", "", c->conn.id);
        maybe_destroy_connection(q, c);
        return;
    }

    /* Make sure it's a GET operation */
    if(strncmp(request_line, "GET ", 4) && strncmp(request_line, "get ", 4)) {
        logger(FORBIDDEN, "Only simple GET operation supported", request_line, c->socketfd);
        serialized_write(c, page_data[FORBIDDEN_PAGE], strlen(page_data[FORBIDDEN_PAGE]));
        maybe_destroy_connection(q, c);
        return;
    }
    logger(LOG, "Request", request_line, c->conn.id);

    /* Strip the version info from the request_line */
    for(i=4; i<strlen(request_line); i++) {
        /* String is "GET URL?<query_data> HTTP_VERSION" */
        if(request_line[i] == ' ') {
            request_line[i] = '\0';
            break;
        }
    }

    /* Strip all query data from the request_line */
    for(i=4; i<strlen(request_line); i++) {
        /* String is "GET URL?<query_data>" */
        if(request_line[i] == '?') {
            request_line[i] = '\0';
            break;
        }
    }

    /* Otherwise, check for illegal parent directory use .. */
    for(j=4; j<i-1; j++) {
        if(request_line[j] == '.' && request_line[j+1] == '.') {
            logger(FORBIDDEN, "Parent directory (..) path names not supported", request_line, c->socketfd);
            serialized_write(c, page_data[FORBIDDEN_PAGE], strlen(page_data[FORBIDDEN_PAGE]));
            maybe_destroy_connection(q, c);
            return;
        }
    }

    /* Convert no filename to index file */
    if(!strncmp(request_line, "GET /\0", 6) || !strncmp(request_line, "get /\0", 6))
        strcpy(request_line, "GET /index.html");

    /* Work out the file type and check we support it */
    buflen=strlen(request_line);
    fstr = 0;
    for(i=0; extensions[i].ext != 0; i++) {
        int len = strlen(extensions[i].ext);
        if(!strncmp(&request_line[buflen-len], extensions[i].ext, len)) {
            fstr =extensions[i].filetype;
            break;
        }
    }
    if(fstr == 0) {
        logger(FORBIDDEN, "File extension type not supported", request_line, c->socketfd);
        serialized_write(c, page_data[FORBIDDEN_PAGE], strlen(page_data[FORBIDDEN_PAGE]));
        maybe_destroy_connection(q, c);
        return;
    }

    /* Open the file for reading */
    if((file_fd = open(&request_line[5], O_RDONLY)) == -1) {
        logger(NOTFOUND, "Failed to open file", &request_line[5], c->socketfd);
        serialized_write(c, page_data[NOTFOUND_PAGE], strlen(page_data[NOTFOUND_PAGE]));
        maybe_destroy_connection(q, c);
        return;
    }

    /* Get the File Stats */
    fstat(file_fd, &statbuf);

    /* Prepopulate the request buf with the beginning of the requested file */
    ret = read(file_fd, r->buf, sizeof(r->buf));
    if (ret < 0) {
        logger(ERROR, "Failed to read file", "...", 0);
        close(file_fd);
        maybe_destroy_connection(q, c);
        return;
    }

    /* Prepare the header info + a blank line */
    setDateString(NULL, now);
    setDateString(&statbuf.st_mtime, mod);
    sprintf(r->rsp_header, page_data[OK_HEADER], VERSION, now,
            fstr, statbuf.st_size, mod);
    logger(LOG, "Header", r->rsp_header, c->conn.id);

    /* Start sending a response */
    logger(LOG, "SEND", &request_line[5], c->conn.id);
    tpool_inform_blocking(&tpool);
    mutex_lock(&c->writelock);
    tpool_inform_unblocked(&tpool);
    timed_write(c, r->rsp_header, strlen(r->rsp_header));
    /* Send the file itself in 8KB chunks - last block may be smaller */
    do {
        if(timed_write(c, r->buf, ret) < 0)
            logger(LOG, "Write error on socket.", "", c->socketfd);
    } while((ret = read(file_fd, r->buf, sizeof(r->buf))) > 0);
    mutex_unlock(&c->writelock);

    close(file_fd);
    maybe_destroy_connection(q, c);
}