Ejemplo n.º 1
0
void init_fir(fir_t *fs, int N, int window, double alpha)
{
    int i;
    double sw = 0.0;

    for (i = 0; i < NSTAGE; i++) {
        fs->sum[i] = 0;
        fs->i_w[i] = i * N / NSTAGE;
    }

    fs->out = 0;
    fs->ns = N;

    fs->w = (double *) balloc(fatal, N * sizeof(double));

    if (window < wind_oldblast || window > wind_rect) window = wind_oldblast;
    for (i = 0; i < N; i++) {
        fs->w[i] = window_filt[window](i, N, alpha);
        sw += fs->w[i];
    }
    for (i = 0; i < N; i++) {
        fs->w[i] /= sw;
    }
}
int
main(int argc, char *argv[]) {
	int r;
	DIR *root_dir;

	if (argc < 2) {
		fprintf(stderr, "Usage: mkfs fs.img files...\n");
		exit(1);
	}

	assert((512 % sizeof(struct dinode)) == 0);
	assert((512 % sizeof(struct xv6_dirent)) == 0);

	fsfd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666);

	if (fsfd < 0) {
		perror(argv[1]);
		exit(1);
	}

	mkfs(985, LOGSIZE, 1024);

	root_dir = opendir(argv[2]);

	root_inode = ialloc(T_DIR);
	assert(root_inode == ROOTINO);

	r = add_dir(root_dir, root_inode, root_inode);

	if (r != 0) {
		exit(EXIT_FAILURE);
	}

	balloc(usedblocks);
	exit(0);
}
Ejemplo n.º 3
0
int
stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
{
    if (cipher_ctx == NULL)
        return CRYPTO_ERROR;

    cipher_t *cipher = cipher_ctx->cipher;

    static buffer_t tmp = { 0, 0, 0, NULL };

    int err = CRYPTO_OK;

    brealloc(&tmp, ciphertext->len, capacity);
    buffer_t *plaintext = &tmp;
    plaintext->len = ciphertext->len;

    if (!cipher_ctx->init) {
        if (cipher_ctx->chunk == NULL) {
            cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));
            memset(cipher_ctx->chunk, 0, sizeof(buffer_t));
            balloc(cipher_ctx->chunk, cipher->nonce_len);
        }

        size_t left_len = min(cipher->nonce_len - cipher_ctx->chunk->len,
                              ciphertext->len);

        if (left_len > 0) {
            memcpy(cipher_ctx->chunk->data + cipher_ctx->chunk->len, ciphertext->data, left_len);
            memmove(ciphertext->data, ciphertext->data + left_len,
                    ciphertext->len - left_len);
            cipher_ctx->chunk->len += left_len;
            ciphertext->len        -= left_len;
        }

        if (cipher_ctx->chunk->len < cipher->nonce_len)
            return CRYPTO_NEED_MORE;

        uint8_t *nonce   = cipher_ctx->nonce;
        size_t nonce_len = cipher->nonce_len;
        plaintext->len -= left_len;

        memcpy(nonce, cipher_ctx->chunk->data, nonce_len);
        cipher_ctx_set_nonce(cipher_ctx, nonce, nonce_len, 0);
        cipher_ctx->counter = 0;
        cipher_ctx->init    = 1;

        if (cipher->method >= RC4_MD5) {
            if (ppbloom_check((void *)nonce, nonce_len) == 1) {
                LOGE("crypto: stream: repeat IV detected");
                return CRYPTO_ERROR;
            }
        }
    }

    if (ciphertext->len <= 0)
        return CRYPTO_NEED_MORE;

    if (cipher->method >= SALSA20) {
        int padding = cipher_ctx->counter % SODIUM_BLOCK_SIZE;
        brealloc(plaintext, (plaintext->len + padding) * 2, capacity);

        if (padding) {
            brealloc(ciphertext, ciphertext->len + padding, capacity);
            memmove(ciphertext->data + padding, ciphertext->data,
                    ciphertext->len);
            sodium_memzero(ciphertext->data, padding);
        }
        crypto_stream_xor_ic((uint8_t *)plaintext->data,
                             (const uint8_t *)(ciphertext->data),
                             (uint64_t)(ciphertext->len + padding),
                             (const uint8_t *)cipher_ctx->nonce,
                             cipher_ctx->counter / SODIUM_BLOCK_SIZE, cipher->key,
                             cipher->method);
        cipher_ctx->counter += ciphertext->len;
        if (padding) {
            memmove(plaintext->data, plaintext->data + padding, plaintext->len);
        }
    } else {
        err = cipher_ctx_update(cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,
                                (const uint8_t *)(ciphertext->data),
                                ciphertext->len);
    }

    if (err)
        return CRYPTO_ERROR;

#ifdef SS_DEBUG
    dump("PLAIN", plaintext->data, plaintext->len);
    dump("CIPHER", ciphertext->data, ciphertext->len);
#endif

    brealloc(ciphertext, plaintext->len, capacity);
    memcpy(ciphertext->data, plaintext->data, plaintext->len);
    ciphertext->len = plaintext->len;

    // Add to bloom filter
    if (cipher_ctx->init == 1) {
        if (cipher->method >= RC4_MD5) {
            ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len);
            cipher_ctx->init = 2;
        }
    }

    return CRYPTO_OK;
}
Ejemplo n.º 4
0
static void
server_recv_cb(EV_P_ ev_io *w, int revents)
{
    server_ctx_t *server_ctx = (server_ctx_t *)w;
    struct sockaddr_storage src_addr;
    memset(&src_addr, 0, sizeof(struct sockaddr_storage));

    buffer_t *buf = ss_malloc(sizeof(buffer_t));
    balloc(buf, buf_size);

    socklen_t src_addr_len = sizeof(struct sockaddr_storage);
    unsigned int offset    = 0;

#ifdef MODULE_REDIR
    char control_buffer[64] = { 0 };
    struct msghdr msg;
    memset(&msg, 0, sizeof(struct msghdr));
    struct iovec iov[1];
    struct sockaddr_storage dst_addr;
    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));

    msg.msg_name       = &src_addr;
    msg.msg_namelen    = src_addr_len;
    msg.msg_control    = control_buffer;
    msg.msg_controllen = sizeof(control_buffer);

    iov[0].iov_base = buf->data;
    iov[0].iov_len  = buf_size;
    msg.msg_iov     = iov;
    msg.msg_iovlen  = 1;

    buf->len = recvmsg(server_ctx->fd, &msg, 0);
    if (buf->len == -1) {
        ERROR("[udp] server_recvmsg");
        goto CLEAN_UP;
    } else if (buf->len > packet_size) {
        if (verbose) {
            LOGI("[udp] UDP server_recv_recvmsg fragmentation");
        }
    }

    if (get_dstaddr(&msg, &dst_addr)) {
        LOGE("[udp] unable to get dest addr");
        goto CLEAN_UP;
    }

    src_addr_len = msg.msg_namelen;
#else
    ssize_t r;
    r = recvfrom(server_ctx->fd, buf->data, buf_size,
                 0, (struct sockaddr *)&src_addr, &src_addr_len);

    if (r == -1) {
        // error on recv
        // simply drop that packet
        ERROR("[udp] server_recv_recvfrom");
        goto CLEAN_UP;
    } else if (r > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_recvfrom fragmentation");
        }
    }

    buf->len = r;
#endif

    if (verbose) {
        LOGI("[udp] server receive a packet");
    }

#ifdef MODULE_REMOTE
    tx += buf->len;

    int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size);
    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }
#endif

#ifdef MODULE_LOCAL
#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)
#ifdef __ANDROID__
    tx += buf->len;
#endif
    uint8_t frag = *(uint8_t *)(buf->data + 2);
    offset += 3;
#endif
#endif

    /*
     *
     * SOCKS5 UDP Request
     * +----+------+------+----------+----------+----------+
     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +----+------+------+----------+----------+----------+
     * | 2  |  1   |  1   | Variable |    2     | Variable |
     * +----+------+------+----------+----------+----------+
     *
     * SOCKS5 UDP Response
     * +----+------+------+----------+----------+----------+
     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +----+------+------+----------+----------+----------+
     * | 2  |  1   |  1   | Variable |    2     | Variable |
     * +----+------+------+----------+----------+----------+
     *
     * shadowsocks UDP Request (before encrypted)
     * +------+----------+----------+----------+
     * | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +------+----------+----------+----------+
     * |  1   | Variable |    2     | Variable |
     * +------+----------+----------+----------+
     *
     * shadowsocks UDP Response (before encrypted)
     * +------+----------+----------+----------+
     * | ATYP | DST.ADDR | DST.PORT |   DATA   |
     * +------+----------+----------+----------+
     * |  1   | Variable |    2     | Variable |
     * +------+----------+----------+----------+
     *
     * shadowsocks UDP Request and Response (after encrypted)
     * +-------+--------------+
     * |   IV  |    PAYLOAD   |
     * +-------+--------------+
     * | Fixed |   Variable   |
     * +-------+--------------+
     *
     */

#ifdef MODULE_REDIR
    char addr_header[512] = { 0 };
    int addr_header_len   = construct_udprelay_header(&dst_addr, addr_header);

    if (addr_header_len == 0) {
        LOGE("[udp] failed to parse tproxy addr");
        goto CLEAN_UP;
    }

    // reconstruct the buffer
    brealloc(buf, buf->len + addr_header_len, buf_size);
    memmove(buf->data + addr_header_len, buf->data, buf->len);
    memcpy(buf->data, addr_header, addr_header_len);
    buf->len += addr_header_len;

#elif MODULE_TUNNEL

    char addr_header[512] = { 0 };
    char *host            = server_ctx->tunnel_addr.host;
    char *port            = server_ctx->tunnel_addr.port;
    uint16_t port_num     = (uint16_t)atoi(port);
    uint16_t port_net_num = htons(port_num);
    int addr_header_len   = 0;

    struct cork_ip ip;
    if (cork_ip_init(&ip, host) != -1) {
        if (ip.version == 4) {
            // send as IPv4
            struct in_addr host_addr;
            memset(&host_addr, 0, sizeof(struct in_addr));
            int host_len = sizeof(struct in_addr);

            if (dns_pton(AF_INET, host, &host_addr) == -1) {
                FATAL("IP parser error");
            }
            addr_header[addr_header_len++] = 1;
            memcpy(addr_header + addr_header_len, &host_addr, host_len);
            addr_header_len += host_len;
        } else if (ip.version == 6) {
            // send as IPv6
            struct in6_addr host_addr;
            memset(&host_addr, 0, sizeof(struct in6_addr));
            int host_len = sizeof(struct in6_addr);

            if (dns_pton(AF_INET6, host, &host_addr) == -1) {
                FATAL("IP parser error");
            }
            addr_header[addr_header_len++] = 4;
            memcpy(addr_header + addr_header_len, &host_addr, host_len);
            addr_header_len += host_len;
        } else {
            FATAL("IP parser error");
        }
    } else {
        // send as domain
        int host_len = strlen(host);

        addr_header[addr_header_len++] = 3;
        addr_header[addr_header_len++] = host_len;
        memcpy(addr_header + addr_header_len, host, host_len);
        addr_header_len += host_len;
    }
    memcpy(addr_header + addr_header_len, &port_net_num, 2);
    addr_header_len += 2;

    // reconstruct the buffer
    brealloc(buf, buf->len + addr_header_len, buf_size);
    memmove(buf->data + addr_header_len, buf->data, buf->len);
    memcpy(buf->data, addr_header, addr_header_len);
    buf->len += addr_header_len;

#else

    char host[257] = { 0 };
    char port[64]  = { 0 };
    struct sockaddr_storage dst_addr;
    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));

    int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset,
                                                host, port, &dst_addr);
    if (addr_header_len == 0) {
        // error in parse header
        goto CLEAN_UP;
    }

    char *addr_header = buf->data + offset;
#endif

#ifdef MODULE_LOCAL
    char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr);
#else
    char *key = hash_key(dst_addr.ss_family, &src_addr);
#endif

    struct cache *conn_cache = server_ctx->conn_cache;

    remote_ctx_t *remote_ctx = NULL;
    cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx);

    if (remote_ctx != NULL) {
        if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) {
            remote_ctx = NULL;
        }
    }

    // reset the timer
    if (remote_ctx != NULL) {
        ev_timer_again(EV_A_ & remote_ctx->watcher);
    }

    if (remote_ctx == NULL) {
        if (verbose) {
#ifdef MODULE_REDIR
            char src[SS_ADDRSTRLEN];
            char dst[SS_ADDRSTRLEN];
            strcpy(src, get_addr_str((struct sockaddr *)&src_addr));
            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr));
            LOGI("[udp] cache miss: %s <-> %s", dst, src);
#else
            LOGI("[udp] cache miss: %s:%s <-> %s", host, port,
                 get_addr_str((struct sockaddr *)&src_addr));
#endif
        }
    } else {
        if (verbose) {
#ifdef MODULE_REDIR
            char src[SS_ADDRSTRLEN];
            char dst[SS_ADDRSTRLEN];
            strcpy(src, get_addr_str((struct sockaddr *)&src_addr));
            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr));
            LOGI("[udp] cache hit: %s <-> %s", dst, src);
#else
            LOGI("[udp] cache hit: %s:%s <-> %s", host, port,
                 get_addr_str((struct sockaddr *)&src_addr));
#endif
        }
    }

#ifdef MODULE_LOCAL

#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)
    if (frag) {
        LOGE("[udp] drop a message since frag is not 0, but %d", frag);
        goto CLEAN_UP;
    }
#endif

    const struct sockaddr *remote_addr = server_ctx->remote_addr;
    const int remote_addr_len          = server_ctx->remote_addr_len;

    if (remote_ctx == NULL) {
        // Bind to any port
        int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6);
        if (remotefd < 0) {
            ERROR("[udp] udprelay bind() error");
            goto CLEAN_UP;
        }
        setnonblocking(remotefd);

#ifdef SO_NOSIGPIPE
        set_nosigpipe(remotefd);
#endif
#ifdef IP_TOS
        // Set QoS flag
        int tos = 46;
        setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
#ifdef SET_INTERFACE
        if (server_ctx->iface) {
            if (setinterface(remotefd, server_ctx->iface) == -1)
                ERROR("setinterface");
        }
#endif

#ifdef __ANDROID__
        if (vpn) {
            if (protect_socket(remotefd) == -1) {
                ERROR("protect_socket");
                close(remotefd);
                goto CLEAN_UP;
            }
        }
#endif

        // Init remote_ctx
        remote_ctx                  = new_remote(remotefd, server_ctx);
        remote_ctx->src_addr        = src_addr;
        remote_ctx->af              = remote_addr->sa_family;
        remote_ctx->addr_header_len = addr_header_len;
        memcpy(remote_ctx->addr_header, addr_header, addr_header_len);

        // Add to conn cache
        cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);

        // Start remote io
        ev_io_start(EV_A_ & remote_ctx->io);
        ev_timer_start(EV_A_ & remote_ctx->watcher);
    }

    if (offset > 0) {
        buf->len -= offset;
        memmove(buf->data, buf->data + offset, buf->len);
    }

    int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size);

    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }

    if (buf->len > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_sendto fragmentation");
        }
    }

    int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len);

    if (s == -1) {
        ERROR("[udp] server_recv_sendto");
    }

#else

    int cache_hit  = 0;
    int need_query = 0;

    if (buf->len - addr_header_len > packet_size) {
        if (verbose) {
            LOGI("[udp] server_recv_sendto fragmentation");
        }
    }

    if (remote_ctx != NULL) {
        cache_hit = 1;
        // detect destination mismatch
        if (remote_ctx->addr_header_len != addr_header_len
            || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) {
            if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) {
                need_query = 1;
            }
        } else {
            memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage));
        }
    } else {
        if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) {
            int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6);
            if (remotefd != -1) {
                setnonblocking(remotefd);
#ifdef SO_BROADCAST
                set_broadcast(remotefd);
#endif
#ifdef SO_NOSIGPIPE
                set_nosigpipe(remotefd);
#endif
#ifdef IP_TOS
                // Set QoS flag
                int tos = 46;
                setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
#ifdef SET_INTERFACE
                if (server_ctx->iface) {
                    if (setinterface(remotefd, server_ctx->iface) == -1)
                        ERROR("setinterface");
                }
#endif
                remote_ctx                  = new_remote(remotefd, server_ctx);
                remote_ctx->src_addr        = src_addr;
                remote_ctx->server_ctx      = server_ctx;
                remote_ctx->addr_header_len = addr_header_len;
                memcpy(remote_ctx->addr_header, addr_header, addr_header_len);
                memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage));
            } else {
                ERROR("[udp] bind() error");
                goto CLEAN_UP;
            }
        }
    }

    if (remote_ctx != NULL && !need_query) {
        size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);
        int s           = sendto(remote_ctx->fd, buf->data + addr_header_len,
                                 buf->len - addr_header_len, 0,
                                 (struct sockaddr *)&dst_addr, addr_len);

        if (s == -1) {
            ERROR("[udp] sendto_remote");
            if (!cache_hit) {
                close_and_free_remote(EV_A_ remote_ctx);
            }
        } else {
            if (!cache_hit) {
                // Add to conn cache
                remote_ctx->af = dst_addr.ss_family;
                char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr);
                cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);

                ev_io_start(EV_A_ & remote_ctx->io);
                ev_timer_start(EV_A_ & remote_ctx->watcher);
            }
        }
    } else {
        struct addrinfo hints;
        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family   = AF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = IPPROTO_UDP;

        struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len,
                                                    buf->len - addr_header_len);
        query_ctx->server_ctx      = server_ctx;
        query_ctx->addr_header_len = addr_header_len;
        query_ctx->src_addr        = src_addr;
        memcpy(query_ctx->addr_header, addr_header, addr_header_len);

        if (need_query) {
            query_ctx->remote_ctx = remote_ctx;
        }

        struct ResolvQuery *query = resolv_query(host, query_resolve_cb,
                                                 NULL, query_ctx, htons(atoi(port)));
        if (query == NULL) {
            ERROR("[udp] unable to create DNS query");
            close_and_free_query(EV_A_ query_ctx);
            goto CLEAN_UP;
        }
        query_ctx->query = query;
    }
#endif

CLEAN_UP:
    bfree(buf);
    ss_free(buf);
}
Ejemplo n.º 5
0
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
{
	sym_tabent_t	*tp;
	sym_t			*sp, *last;
	char_t			*cp;
	int				hindex;

	a_assert(name);
	a_assert(0 <= sd && sd < symMax);
	tp = sym[sd];
	a_assert(tp);

/*
 *	Calculate the first daisy-chain from the hash table. If non-zero, then
 *	we have daisy-chain, so scan it and look for the symbol.
 */
	last = NULL;
	hindex = hashIndex(tp, name);
	if ((sp = tp->hash_table[hindex]) != NULL) {
		for (; sp; sp = sp->forw) {
			cp = sp->name.value.string;
			if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
				break;
			}
			last = sp;
		}
		if (sp) {
/*
 *			Found, so update the value
 *			If the caller stores handles which require freeing, they
 *			will be lost here. It is the callers responsibility to free
 *			resources before overwriting existing contents. We will here
 *			free allocated strings which occur due to value_instring().
 *			We should consider providing the cleanup function on the open rather
 *			than the close and then we could call it here and solve the problem.
 */
			if (sp->content.valid) {
				valueFree(&sp->content);
			}
			sp->content = v;
			sp->arg = arg;
			return sp;
		}
/*
 *		Not found so allocate and append to the daisy-chain
 */
		sp = (sym_t*) balloc(B_L, sizeof(sym_t));
		if (sp == NULL) {
			return NULL;
		}
		sp->name = valueString(name, VALUE_ALLOCATE);
		sp->content = v;
		sp->forw = (sym_t*) NULL;
		sp->arg = arg;
		last->forw = sp;

	} else {
/*
 *		Daisy chain is empty so we need to start the chain
 */
		sp = (sym_t*) balloc(B_L, sizeof(sym_t));
		if (sp == NULL) {
			return NULL;
		}
		tp->hash_table[hindex] = sp;
		tp->hash_table[hashIndex(tp, name)] = sp;

		sp->forw = (sym_t*) NULL;
		sp->content = v;
		sp->arg = arg;
		sp->name = valueString(name, VALUE_ALLOCATE);
	}
	return sp;
}
Ejemplo n.º 6
0
struct sensor_sba_info *sensor_config_bus(int slave_addr, uint8_t dev_id,
					  SBA_BUSID bus_id,
					  SENSOR_BUS_TYPE bus_type, int req_num,
					  BLOCK_TYPE block_type)
{
	struct sensor_sba_req *reqs = NULL;
	struct sensor_sba_info *info = NULL;
	int i;

	reqs = (struct sensor_sba_req *)balloc(
		sizeof(struct sensor_sba_req) * req_num, NULL);
	if (!reqs)
		return NULL;

	info = (struct sensor_sba_info *)balloc(sizeof(struct sensor_sba_info),
						NULL);
	if (!info)
		goto FAIL;

	info->reqs = reqs;
	info->bitmap = 0;
	info->req_cnt = req_num;
	info->dev_id = dev_id;
	info->bus_type = bus_type;
	info->block_type = block_type;

	for (i = 0; i < req_num; i++) {
		reqs[i].req.bus_id = bus_id;
		reqs[i].req.status = 1;

		if (block_type == SPIN) {
			reqs[i].req.callback = sensor_bus_callback_spin;
			reqs[i].complete_flag = 0;
		} else {
			reqs[i].req.callback = sensor_bus_callback_sleep;
			reqs[i].sem = semaphore_create(0);
			if (!reqs[i].sem)
				goto FAIL;
		}

		reqs[i].req.full_duplex = 0;

		reqs[i].req.addr.slave_addr = slave_addr;
	}

	pr_debug(LOG_MODULE_DRV, "%s: Serial BUS[%d] initialized", __func__,
		 bus_id);

	return info;

FAIL:
	for (i = 0; i < req_num; i++) {
		if (reqs[i].sem) {
			semaphore_delete(reqs[i].sem);
			reqs[i].sem = NULL;
		}
	}
	if (reqs)
		bfree(reqs);

	if (info)
		bfree(info);

	pr_debug(LOG_MODULE_DRV, "%s: Serial BUS[%d] init failed", __func__,
		 bus_id);
	return NULL;
}
Ejemplo n.º 7
0
int websValidateUrl(webs_t wp, char_t *path)
{
	char_t	*parts[64];					/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath;
	int		i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * 22 Jul 02 -- there were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.

    *  However, by encoding the '/' character, it is possible to break out of
    *  the
    *  web root and read arbitrary files from the server.
    *  Hence a request like:
    *
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
   token = gstrchr(path, '\\');
   while (token != NULL)
   {
      *token = '/';
      token = gstrchr(token, '\\');
   }

	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web.
 */
	while (token != NULL) {
		if (gstrcmp(token, T("..")) == 0) {
			if (npart > 0) {
				npart--;
			}

		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);

	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
/*
	Primary MatrixSSL read function that transparently handles SSL handshakes
	and the subsequent incoming application data records.

	A NULL inbuf parameter is an indication that this is a call to perform a
	new SSL handshake with an incoming client and no out data is expected

	Params:
	inbuf	allocated storage for plaintext data to be copied to
	inlen	length of inbuf

	Return codes:
	-1	EOF or internal failure.  caller should free sess and close socket
	0	success status.  no data is being returned to the caller
	>0	success status.  number of plaintext bytes written to inbuf

	Note that unlike a standard "socket read", a read of an SSL record can
	produce data that must be written, for example, a response to a handshake
	message that must be sent before any more data is read. Also, data can
	be read from the network such as an SSL alert, that produces no data to
	pass back to caller.

	Because webs doesn't have the concept of a read forcing a write, we
	do the write here, inline. If we are non-blocking, this presents an issue
	because we can't block indefinitely on a send, and we also can't indicate
	that the send be done later. The workaround below uses select() to
	implement a "timed send", which will fail and indicate the connection be
	closed if not complete within a time threshold.

	This situation is extremely unlikely in normal operation, since the only
	records that must be sent as a result of a recv are handshake messages,
	and TCP buffers would not typically be full enough at that point to
	result in an EWOULDBLOCK on send. Conceivably, it could occur on a client
	initiated SSl re-handshake that is sent by a slow-reading client to a
	server with full TCP buffers. A non-malicious client in this situation
	would read immediately after a re-handshake request and fail anyway
	because a buffered appdata record would be read.
*/
int	sslRead(sslConn_t *cp, char *inbuf, int inlen)
{
    unsigned char	*buf;
    int				rc, len, transferred;

    /*
    	Always first look to see if any plaintext application data is waiting
    	We have two levels of buffer here, one for decoded data and one for
    	partial, still encoded SSL records. The partial SSL records are stored
    	transparently in MatrixSSL, but the plaintext is stored in 'cp'.
     */
    if (inbuf != NULL && inlen > 0 && cp->ptBytes > 0 && cp->pt) {
        if (cp->ptBytes < inlen) {
            inlen = cp->ptBytes;
        }
        memcpy(inbuf, cp->currPt, inlen);
        cp->currPt += inlen;
        cp->ptBytes -= inlen;
        /* Free buffer as we go if empty */
        if (cp->ptBytes == 0) {
            bfree(B_L, cp->pt);
            cp->pt = cp->currPt = NULL;
        }
        return inlen;
    }
    /*
    	If there is outgoing data buffered, just try to write it here before
    	doing our read on the socket. Because the read could produce data to
    	be written, this will ensure we have as much room as possible in that
    	case for the written record. Note that there may be data here to send
    	because of a previous sslWrite that got EWOULDBLOCK.
    */
WRITE_MORE:
    if ((len = matrixSslGetOutdata(cp->ssl, &buf)) > 0) {
        transferred = send(cp->fd, buf, len, MSG_NOSIGNAL);
        if (transferred <= 0) {
            if (socketGetError() != EWOULDBLOCK) {
                return -1;
            }
            if (waitForWriteEvent(cp->fd, MAX_WRITE_MSEC) == 0) {
                goto WRITE_MORE;
            }
            return -1;
        } else {
            /* Indicate that we've written > 0 bytes of data */
            if ((rc = matrixSslSentData(cp->ssl, transferred)) < 0) {
                return -1;
            }
            if (rc == MATRIXSSL_REQUEST_CLOSE) {
                return -1;
            } else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) {
                /* If called via sslAccept (NULL buf), then we can just leave */
                return 0;
            }
            /* Try to send again if more data to send */
            if (rc == MATRIXSSL_REQUEST_SEND || transferred < len) {
                goto WRITE_MORE;
            }
        }
    } else if (len < 0) {
        return -1;
    }

READ_MORE:
    /* Get the ssl buffer and how much data it can accept */
    /* Note 0 is a return failure, unlike with matrixSslGetOutdata */
    if ((len = matrixSslGetReadbuf(cp->ssl, &buf)) <= 0) {
        return -1;
    }
    if ((transferred = recv(cp->fd, buf, len, MSG_NOSIGNAL)) < 0) {
        /* Support non-blocking sockets if turned on */
        if (socketGetError() == EWOULDBLOCK) {
            return 0;
        }
        trace(1, T("RECV error: %d\n"), socketGetError());
        return -1;
    }
    if (transferred == 0) {
        /* If EOF, remote socket closed. This is semi-normal closure. */
        trace(4, T("Closing connection %d on EOF\n"), cp->fd);
        return -1;
    }
    /*
    	Notify SSL state machine that we've received more data into the
    	ssl buffer retreived with matrixSslGetReadbuf.
     */
    if ((rc = matrixSslReceivedData(cp->ssl, transferred, &buf,
                                    (uint32*)&len)) < 0) {
        return -1;
    }

PROCESS_MORE:
    switch (rc) {
    case MATRIXSSL_REQUEST_SEND:
        /* There is a handshake response we must send */
        goto WRITE_MORE;
    case MATRIXSSL_REQUEST_RECV:
        goto READ_MORE;
    case MATRIXSSL_HANDSHAKE_COMPLETE:
        /* Session resumption handshake */
        goto READ_MORE;
    case MATRIXSSL_RECEIVED_ALERT:
        /* Any fatal alert will simply cause a read error and exit */
        if (*buf == SSL_ALERT_LEVEL_FATAL) {
            trace(1, T("Fatal alert: %d, closing connection.\n"),
                  *(buf + 1));
            return -1;
        }
        /* Closure alert is normal (and best) way to close */
        if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) {
            return -1;
        }
        /* Eating warning alerts */
        trace(4, T("Warning alert: %d\n"), *(buf + 1));
        if ((rc = matrixSslProcessedData(cp->ssl, &buf, (uint32*)&len))
            == 0) {
            /* Possible there was plaintext before the alert */
            if (inbuf != NULL && inlen > 0 && cp->ptBytes > 0 && cp->pt) {
                if (cp->ptBytes < inlen) {
                    inlen = cp->ptBytes;
                }
                memcpy(inbuf, cp->currPt, inlen);
                cp->currPt += inlen;
                cp->ptBytes -= inlen;
                /* Free buffer as we go if empty */
                if (cp->ptBytes == 0) {
                    bfree(B_L, cp->pt);
                    cp->pt = cp->currPt = NULL;
                }
                return inlen;
            } else {
                return 0;
            }
        }
        goto PROCESS_MORE;

    case MATRIXSSL_APP_DATA:
        if (cp->ptBytes == 0) {
            /*
            				Catching here means this is new app data just grabbed off the
            				wire.
            */
            cp->ptBytes = len;
            cp->pt = balloc(B_L, len);
            memcpy(cp->pt, buf, len);
            cp->currPt = cp->pt;
        } else {
            /*
            				Multi-record.  This case should only ever be possible if no
            				data has already been read out of the 'pt' cache so it is
            				fine to assume an unprocessed buffer.
            */
            psAssert(cp->pt == cp->currPt);
            cp->pt = brealloc(B_L, cp->pt, cp->ptBytes + len);
            memcpy(cp->pt + cp->ptBytes, buf, len);
            cp->currPt = cp->pt;
            cp->ptBytes += len;
        }
        if ((rc = matrixSslProcessedData(cp->ssl, &buf, (uint32*)&len))
            < 0) {
            return -1;
        }
        /* Check for multi-record app data*/
        if (rc > 0) {
            goto PROCESS_MORE;
        }
        /*
        			Otherwise pass back how much the caller wants to read (if any)
        */
        if (inbuf != 0 && inlen > 0) {
            if (cp->ptBytes < inlen) {
                inlen = cp->ptBytes;
            }
            memcpy(inbuf, cp->currPt, inlen);
            cp->currPt += inlen;
            cp->ptBytes -= inlen;
            return inlen; /* Just a breakpoint holder */
        }
        return 0; /* Have it stored, but caller didn't want any data */
    default:
        return -1;
    }

    return 0; /* really can never hit this */
}
Ejemplo n.º 9
0
Archivo: Reader.c Proyecto: denji/mdr
char * getHTML()
{
    bstring html = bfromcstr("<!DOCTYPE html>\n<html>\n");
    balloc(html, style_css_len);
    bcatcstr(html, "<head>");
    bcatcstr(html, "<title>mdr</title>");
    bcatcstr(html, "<style type='text/css'>");
    bcatcstr(html, (char *)style_css);
    bcatcstr(html, "</style>");
    bcatcstr(html, "</head>");
    bcatcstr(html, "<body>\n<table cellpadding='0'>\n");

    // Read from stdin
    bstring stdinContents = bread ((bNread) fread, stdin);
    if (stdinContents == NULL)
    {
        return "There was an error reading from stdin.";
    }

    // Split into lines
    struct bstrList * inputLines;
    if ((inputLines = bsplit(stdinContents, '\n')) != NULL)
    {

        // We are going to build a map showing which lines in the input belong
        // in which lines in the output and how they should be displayed. We'll
        // allocate the left and right maps to be big enough to each hold all
        // the input data, which is more than enough.
        lineData * lineMapL = malloc(inputLines->qty * sizeof(lineData));
        if (lineMapL == NULL)
        {
            free(lineMapL);
            printf("Memory allocation error.\n");
            exit(-1);
        }
        lineData * lineMapR = malloc(inputLines->qty * sizeof(lineData));
        if (lineMapR == NULL)
        {
            free(lineMapR);
            printf("Memory allocation error.\n");
            exit(-1);
        }
        int lineMapPosL = 0;
        int lineMapPosR = 0;

        int useL;
        int useR;
        enum lineType type;
        int padding;
        int lineNoL = 0;
        int lineNoR = 0;
        int firstInfoLine = TRUE;
        int startNewFileOk = TRUE;
        int startOldFileOk = TRUE;

        // Map input lines to their output column (left, right, or both)
        int i;
        for (i = 0; i < inputLines->qty; i++) {

            useL = 0;
            useR = 0;
            type = SHARED;
            padding = 1;

            if (startOldFileOk && stringStartsWith(inputLines->entry[i], "---"))
            {
                type = OLD_FILE;
                useL = 1;
                padding = 4;
                lineNoL = -1;
                lineNoR = -1;
                startOldFileOk = FALSE;
            }
            else if (startNewFileOk && stringStartsWith(inputLines->entry[i], "+++"))
            {
                type = NEW_FILE;
                useR = 1;
                padding = 4;
                lineNoL = -1;
                lineNoR = -1;
                startNewFileOk = FALSE;
            }
            else if (stringStartsWith(inputLines->entry[i], "@@"))
            {
                syncLineNumbers(inputLines->entry[i], &lineNoL, &lineNoR);
                if (firstInfoLine)
                {
                    // Don't print the info row but still increment the line
                    // numbers normally.
                    // TODO: Might be better to mark the row as the first and
                    // hide it with CSS instead of just not printing it.
                    lineNoL++;
                    lineNoR++;
                }
                else
                {
                    type = INFO;
                    useR = 1;
                    useL = 1;
                    padding = 1;
                }
                firstInfoLine = FALSE;
            }
            else if (bdata(inputLines->entry[i])[0] == '-')
            {
                type = OLD;
                useL = 1;
            }
            else if (bdata(inputLines->entry[i])[0] == '+')
            {
                type = NEW;
                useR = 1;
            }
            else if (bdata(inputLines->entry[i])[0] == ' ')
            {
                type = SHARED;
                useL = 1;
                useR = 1;
            }
            else
            {
                type = HEADER;
                lineNoL = 0;
                lineNoR = 0;
                firstInfoLine = TRUE;
                startNewFileOk = TRUE;
                startOldFileOk = TRUE;
            }

            // Balance.
            if (type == HEADER ||
                (type == SHARED && (useL || useR)) ||
                i == inputLines->qty - 1)
            {
                int difference = lineMapPosL - lineMapPosR;
                int j;

                if (difference > 0)
                {
                    for (j = 0; j < difference; j++)
                    {
                        lineMapR[lineMapPosR].type = EMPTY;
                        lineMapPosR++;
                    }
                }
                else if (difference < 0)
                {
                    for (j = 0; j < (difference * -1); j++)
                    {
                        lineMapL[lineMapPosL].type = EMPTY;
                        lineMapPosL++;
                    }
                }
            }

            if (useL)
            {
                lineMapL[lineMapPosL].inputPos = i;
                lineMapL[lineMapPosL].type = type;
                lineMapL[lineMapPosL].padding = padding;
                lineMapL[lineMapPosL].lineNo = lineNoL - 1;
                lineMapL[lineMapPosL].leadingSpaces = 0;
                lineMapPosL++;
                lineNoL++;
            }

            if (useR)
            {
                lineMapR[lineMapPosR].inputPos = i;
                lineMapR[lineMapPosR].type = type;
                lineMapR[lineMapPosR].padding = padding;
                lineMapR[lineMapPosR].lineNo = lineNoR - 1;
                lineMapR[lineMapPosR].leadingSpaces = 0;
                lineMapPosR++;
                lineNoR++;
            }

        }

        // Mapping complete. Quick sanity check that both L and R cols have the
        // same length.
        if (lineMapPosL != lineMapPosR)
        {
            return "Error displaying diff (generated columns not equal in length).";
        }

        // Now we do the formatting work based on the map.
        for (i = 0; i < lineMapPosL; i++)
        {
            int * highlightMaskA = NULL;
            int * highlightMaskB = NULL;
            bstring contentL;
            bstring contentR;
            int leadingSpacesL = 0;
            int leadingSpacesR = 0;

            if (lineMapL[i].type != EMPTY)
            {
                contentL = getContentFromLine(
                    inputLines->entry[lineMapL[i].inputPos],
                    lineMapL[i].padding,
                    &leadingSpacesL
                );
                lineMapL[i].leadingSpaces = leadingSpacesL;
            }

            if (lineMapR[i].type != EMPTY)
            {
                contentR = getContentFromLine(
                    inputLines->entry[lineMapR[i].inputPos],
                    lineMapR[i].padding,
                    &leadingSpacesR
                );
                lineMapR[i].leadingSpaces = leadingSpacesR;
            }

            // Compare changed lines
            if (lineMapL[i].type == OLD && lineMapR[i].type == NEW) {

                lineMapL[i].type = CHANGE;
                lineMapR[i].type = CHANGE;

                determineLineHighlighting(
                    contentL,
                    contentR,
                    &highlightMaskA,
                    &highlightMaskB
                );

            }

            // Format output
            bcatcstr(html, "<tr>\n");

            if (lineMapL[i].type == EMPTY)
            {
                createEmptyLine(html);
            }
            else
            {
                createLine(LEFT, html, contentL, lineMapL[i], highlightMaskA);
                bdestroy(contentL);
            }

            if (lineMapR[i].type == EMPTY)
            {
                createEmptyLine(html);
            }
            else
            {
                createLine(RIGHT, html, contentR, lineMapR[i], highlightMaskB);
                bdestroy(contentR);
            }

            bcatcstr(html, "</tr>\n");

            free(highlightMaskA);
            free(highlightMaskB);
        }

        bcatcstr(html, "</table>\n</body>\n</html>\n");

        free(lineMapL);
        free(lineMapR);
    }

    bdestroy(stdinContents);
    bstrListDestroy(inputLines);

    char * result = bstr2cstr(html, '-');
    bdestroy(html);

    return result; // Caller should free()
}
Ejemplo n.º 10
0
int socketSelect(int sid, int timeout)
{
	socket_t		*sp;
	struct timeval	tv;
	fd_mask 		*readFds, *writeFds, *exceptFds;
	int 			all, len, nwords, index, bit, nEvents;

/*
 *	Allocate and zero the select masks
 */
	nwords = (socketHighestFd + NFDBITS) / NFDBITS;
	len = nwords * sizeof(int);

	readFds = balloc(B_L, len);
	memset(readFds, 0, len);
	writeFds = balloc(B_L, len);
	memset(writeFds, 0, len);
	exceptFds = balloc(B_L, len);
	memset(exceptFds, 0, len);

	tv.tv_sec = timeout / 1000;
	tv.tv_usec = (timeout % 1000) * 1000;

/*
 *	Set the select event masks for events to watch
 */
	all = nEvents = 0;

	if (sid < 0) {
		all++;
		sid = 0;
	}

	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			if (all == 0) {
				break;
			} else {
				continue;
			}
		}
		a_assert(sp);

/*
 * 		Initialize the ready masks and compute the mask offsets.
 */
		index = sp->sock / (NBBY * sizeof(fd_mask));
		bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));

/*
 * 		Set the appropriate bit in the ready masks for the sp->sock.
 */
		if (sp->handlerMask & SOCKET_READABLE) {
			readFds[index] |= bit;
			nEvents++;
			if (socketInputBuffered(sid) > 0) {
				tv.tv_sec = 0;
				tv.tv_usec = 0;
			}
		}
		if (sp->handlerMask & SOCKET_WRITABLE) {
			writeFds[index] |= bit;
			nEvents++;
		}
		if (sp->handlerMask & SOCKET_EXCEPTION) {
			exceptFds[index] |= bit;
			nEvents++;
		}
		if (! all) {
			break;
		}
	}

/*
 * 	Wait for the event or a timeout. Reset nEvents to be the number of actual
 *	events now.
 */
	nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
		(fd_set *) writeFds, (fd_set *) exceptFds, &tv);

	if (nEvents > 0) {
		if (all) {
			sid = 0;
		}
		for (; sid < socketMax; sid++) {
			if ((sp = socketList[sid]) == NULL) {
				if (all == 0) {
					break;
				} else {
					continue;
				}
			}

			index = sp->sock / (NBBY * sizeof(fd_mask));
			bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));

			if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
				sp->currentEvents |= SOCKET_READABLE;
			}
			if (writeFds[index] & bit) {
				sp->currentEvents |= SOCKET_WRITABLE;
			}
			if (exceptFds[index] & bit) {
				sp->currentEvents |= SOCKET_EXCEPTION;
			}
			if (! all) {
				break;
			}
		}
	}

	bfree(B_L, readFds);
	bfree(B_L, writeFds);
	bfree(B_L, exceptFds);

	return nEvents;
}
Ejemplo n.º 11
0
/*
 *	Process a form request. Returns 1 always to indicate it handled the URL
 */
int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
		char_t *url, char_t *path, char_t* query)
{
	cgiRec		*cgip;
	sym_t		*s;
	char_t		cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE];
	char_t		*cp, *cgiName, *cgiPath, **argp, **envp, **ep;
	int			n, envpsize, argpsize, pHandle, cid;
	a_assert(websValid(wp));
	a_assert(url && *url);
	a_assert(path && *path == '/');
	websStats.cgiHits++;
/*
 *	Extract the form name and then build the full path name.  The form
 *	name will follow the first '/' in path.
 */
	gstrncpy(cgiBuf, path, TSZ(cgiBuf));
	if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) {
		websError(wp, 200, T("Missing CGI name"));
		return 1;
	}
	cgiName++;
	if ((cp = gstrchr(cgiName, '/')) != NULL) {
		*cp = '\0';
	}
	fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(),
		CGI_BIN, cgiName);
#ifndef VXWORKS
/*
 *	See if the file exists and is executable.  If not error out.
 *	Don't do this step for VxWorks, since the module may already
 *	be part of the OS image, rather than in the file system.
 */
	{
		gstat_t		sbuf;
		if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) {
			websError(wp, 200, T("CGI process file does not exist"));
			bfree(B_L, cgiPath);
			return 1;
		}
#if (defined (WIN) || defined (CE))
		if (gstrstr(cgiPath, T(".exe")) == NULL &&
			gstrstr(cgiPath, T(".bat")) == NULL) {
#elif (defined (NW))
			if (gstrstr(cgiPath, T(".nlm")) == NULL) {
#else
		if (gaccess(cgiPath, X_OK) != 0) {
#endif /* WIN || CE */
			websError(wp, 200, T("CGI process file is not executable"));
			bfree(B_L, cgiPath);
			return 1;
		}
	}
#endif /* ! VXWORKS */

         
/*
 *	Get the CWD for resetting after launching the child process CGI
 */
	ggetcwd(cwd, FNAMESIZE);
/*
 *	Retrieve the directory of the child process CGI
 */
	if ((cp = gstrrchr(cgiPath, '/')) != NULL) {
		*cp = '\0';
		gchdir(cgiPath);
		*cp = '/';
	}

/*
 *	Build command line arguments.  Only used if there is no non-encoded
 *	= character.  This is indicative of a ISINDEX query.  POST separators
 *	are & and others are +.  argp will point to a balloc'd array of 
 *	pointers.  Each pointer will point to substring within the
 *	query string.  This array of string pointers is how the spawn or 
 *	exec routines expect command line arguments to be passed.  Since 
 *	we don't know ahead of time how many individual items there are in
 *	the query string, the for loop includes logic to grow the array 
 *	size via brealloc.
 */

	argpsize = 10;
	argp = balloc(B_L, argpsize * sizeof(char_t *));
	*argp = cgiPath;

	n = 1;
	if (gstrchr(query, '=') == NULL) {

		websDecodeUrl(query, query, gstrlen(query));
		for (cp = gstrtok(query, T(" ")); cp != NULL; ) {
			*(argp+n) = cp;
			n++;

			if (n >= argpsize) {
				argpsize *= 2;
				argp = brealloc(B_L, argp, argpsize * sizeof(char_t *));

			}
			cp = gstrtok(NULL, T(" "));

		}
	}
	*(argp+n) = NULL;

/*
 *	Add all CGI variables to the environment strings to be passed
 *	to the spawned CGI process.  This includes a few we don't 
 *	already have in the symbol table, plus all those that are in
 *	the cgiVars symbol table.  envp will point to a balloc'd array of 
 *	pointers.  Each pointer will point to a balloc'd string containing
 *	the keyword value pair in the form keyword=value.  Since we don't
 *	know ahead of time how many environment strings there will be the
 *	for loop includes logic to grow the array size via brealloc.
 */

	envpsize = WEBS_SYM_INIT;
	envp = balloc(B_L, envpsize * sizeof(char_t *));
	n = 0;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"),
		CGI_BIN, cgiName);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType);

	n++;
	for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) {

		if (s->content.valid && s->content.type == string &&
			gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 &&
			gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) {
			fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string,
				s->content.value.string);

			n++;
			if (n >= envpsize) {

				envpsize *= 2;
				envp = brealloc(B_L, envp, envpsize * sizeof(char_t *));
			}
		}
	}


	if (wp->flags & WEBS_CGI_UPLOAD){
		// set filename into enviornment variables 
		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), wp->cgiStdin);
		n++;
	}


	*(envp+n) = NULL;
/*
 *	Create temporary file name(s) for the child's stdin and stdout.
 *	For POST data the stdin temp file (and name) should already exist.
 */

	if (wp->cgiStdin == NULL) {
		wp->cgiStdin = websGetCgiCommName(wp);
	} 
	stdIn = wp->cgiStdin;
	stdOut = websGetCgiCommName(wp);

/*
 *	Now launch the process.  If not successful, do the cleanup of resources.
 *	If successful, the cleanup will be done after the process completes.
 */
	if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut)) 
		== -1) {
		websError(wp, 200, T("failed to spawn CGI task"));
		for (ep = envp; *ep != NULL; ep++) {
			bfreeSafe(B_L, *ep);
		}
		bfreeSafe(B_L, cgiPath);
		bfreeSafe(B_L, argp);
		bfreeSafe(B_L, envp);
		bfreeSafe(B_L, stdOut);
	} else {
/*
 *		If the spawn was successful, put this wp on a queue to be
 *		checked for completion.
 */
		cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec));
		cgip = cgiList[cid];
		cgip->handle = pHandle;
		cgip->stdIn = stdIn;
		cgip->stdOut = stdOut;
		cgip->cgiPath = cgiPath;
		cgip->argp = argp;
		cgip->envp = envp;
		cgip->wp = wp;
		cgip->fplacemark = 0;
		websTimeoutCancel(wp);
	}
/*
 *	Restore the current working directory after spawning child CGI
 */
 	gchdir(cwd);
	return 1;
}



/******************************************************************************/
/*
 *	Any entry in the cgiList need to be checked to see if it has
 */
void websCgiGatherOutput (cgiRec *cgip)
{
	gstat_t	sbuf;
	char_t	cgiBuf[FNAMESIZE];
	if ((gstat(cgip->stdOut, &sbuf) == 0) && 
		(sbuf.st_size > cgip->fplacemark)) {
		int fdout;
		fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 );
/*
 *		Check to see if any data is available in the
 *		output file and send its contents to the socket.
 */
		if (fdout >= 0) {
			webs_t	wp = cgip->wp;
			int		nRead;
/*
 *			Write the HTTP header on our first pass
 */
			if (cgip->fplacemark == 0) {
				websWrite(wp, T("HTTP/1.0 200 OK\r\n"));
			}
			glseek(fdout, cgip->fplacemark, SEEK_SET);
			while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) {
				websWriteBlock(wp, cgiBuf, nRead);
				cgip->fplacemark += nRead;
			}
			gclose(fdout);
		}
	}
}


/******************************************************************************/
/*
 *	Any entry in the cgiList need to be checked to see if it has
 *	completed, and if so, process its output and clean up.
 */
void websCgiCleanup()
{
	cgiRec	*cgip;
	webs_t	wp;
	char_t	**ep;
	int		cid, nTries;
	for (cid = 0; cid < cgiMax; cid++) {
		if ((cgip = cgiList[cid]) != NULL) {
			int exit_status;
			wp = cgip->wp;
			websCgiGatherOutput (cgip);
			if ( websCheckCgiProc(cgip->handle, &exit_status) == 0) {
/*
 *				We get here if the CGI process has terminated.  Clean up.
 */
				nTries = 0;
/*				
 *				Make sure we didn't miss something during a task switch.
 *				Maximum wait is 100 times 10 msecs (1 second).
 */
				while ((cgip->fplacemark == 0) && (nTries < 100)) {
					websCgiGatherOutput(cgip);
/*					
 *					There are some cases when we detect app exit 
 *					before the file is ready. 
 */
					if (cgip->fplacemark == 0) {
#ifdef WIN
						Sleep(10);
#endif /* WIN*/
					}
					nTries++;
				}
				if (cgip->fplacemark == 0) {
					websError(wp, 200, T("CGI generated no output"));
				} else {
					websDone(wp, 200);
				}
/*
 *				Remove the temporary re-direction files
 */
				gunlink(cgip->stdIn);
				gunlink(cgip->stdOut);
/*
 *				Free all the memory buffers pointed to by cgip.
 *				The stdin file name (wp->cgiStdin) gets freed as
 *				part of websFree().
 */
				cgiMax = hFree((void***) &cgiList, cid);
				for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) {
					bfreeSafe(B_L, *ep);
				}
				bfreeSafe(B_L, cgip->cgiPath);
				bfreeSafe(B_L, cgip->argp);
				bfreeSafe(B_L, cgip->envp);
				bfreeSafe(B_L, cgip->stdOut);
				bfreeSafe(B_L, cgip);
#if 0 //DAVIDM - we do not want this, netflash does it for us
				if(wp->has_firmware_upload_clean){
					if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) != 0)
						return;
					sync();
					doSystem("sleep 3 && reboot &");
				}
#endif
			}
		}
	}
}
Ejemplo n.º 12
0
/* ----------------------------------------------------------------------
 * my_mkdir: 
 *      (1) Allocate INODE space on device using ialloc, which will
 *              return the new directory's inumber 
 *      (2) Allocate a block on the device using balloc, which will
 *              return the new directory's block_number 
 *      (3) get a newMinode for the new directory using 
 *              newdir = iget(dev, inumber)
 *      (4) Setup newdir information 
 *      (5) iput(newdir) - release from MINODE table and write to disk 
 *      (6) Write . and .. into buf and put the buf to the disk block    
 *      (7) Add the name to parent dir 
 *              May require "trimming" the length of the last dir entry 
 *              in the block. 
 * 
 *              To trim, calculate needed_len and ideal_len and trim 
 *              the last entry's size to ideal_len 
 *      (8) write data back to the disk using put_block(dev, block_number, buf)
 ------------------------------------------------------------------ */
void my_mkdir(MINODE* pip, char* name) 
{
    // (1) pip points to the parent directory, which we'll be adding to 
    
    int inumber, bnumber;       // ino number, blocknumber 
    MINODE* newdir;             // directory to be added
    int i;
    char* cp;                   // for iterating through the block
    DIR* dp;                    // points to DIR structs within the block 
    int ideallen, neededlen;    // ideal_length, needed_length 
    char buf[BLOCK_SIZE];
    int dev = pip->dev;         // same dev as parent's directory 
    int count = 0; 

    // (2) Allocate inode and a disk block 
    inumber = ialloc(dev);      // allocate inumber 
    // Block number will be i_block[0], where this directory's data block begins 
    bnumber = balloc(dev);      // allocate blocknumber
    

    if (inumber < 1) 
    {
        printf("my_mkdir() -- ialloc failed with dev %d", dev);
    }
    if (bnumber < 1) 
    {
        printf("my_mkdir() -- balloc failed with dev %d", pip->dev);
    }
        
    // (3) load inode into minode[] in 
        // order to write contents to intended inode in memory 
    newdir = iget(dev, inumber); 

    // (4) Write contents into newdir->INODE 
    newdir->dirty = 1;
    
    // Initialize all i_blocks to 0 
    for (i = 0; i < 15; i++) {
        newdir->INODE.i_block[i] = 0;
    }
    
    // Directories data blocks start at i_block[0], block number of this directory
    newdir->INODE.i_block[0] = bnumber;
    newdir->INODE.i_mode = DIR_MODE;
    newdir->INODE.i_uid = running->uid;
    newdir->INODE.i_gid = running->gid;
    newdir->INODE.i_size = BLOCK_SIZE;          // size in bytes 
    newdir->INODE.i_atime = newdir->INODE.i_ctime = newdir->INODE.i_mtime = time(0L);
    newdir->INODE.i_blocks = 2;  // 2-512 bytes
    newdir->INODE.i_links_count = 2;

    // (5) write inode to disk
    iput(newdir);

    // (6) now write the . and .. entries into a buf[BLOCK_SIZE]
    // then write buf back to disk block allocated to this directory
    bzero(buf, BLOCK_SIZE);             // clear buf
    
    // doing "."
    dp = (DIR*)buf; // get dir pointer
    dp->inode = inumber; //inumber = same inumber as new dir
    strncpy(dp->name, ".", 1);
    dp->name_len = 1;
    dp->rec_len = 12; // 8 + multiple of 4 closest and greater than name length
    
    // doing ".." 
    dp = (DIR *)(buf + dp->rec_len);    
    dp->inode = pip->ino;       // inumber = parent inumber
    dp->name_len = 2;
    strncpy(dp->name, "..", 2);
    dp->rec_len = (BLOCK_SIZE - 12); //take up remainder of block

    //write block to disk:
    put_block(dev, bnumber, buf);

    // (7) Finally, write the directory to it's parent's data blocks 
    //this is the minimum length we need for our new directory 
    
    /* -------------- NOTES -----------------------------------
     *  - each EXT2 DIR entry has rec_len and name_len 
     *  - the rec_len of the LAST entry in the datablock is to the end of the block 
     *  - When entering a new directory with name_len = n
     *          need_length = 4*((8 + name_len + 3)/4) 
     *  - Step to the last entry in the data block, it's IDEAL_LENGTH is 
     *          IDEAL_LENGTH = 4 *((8 + name_len + 3)/4)
     *          
     *          if(rec_len - IDEAL_LENGTH >= need_length)
     *                  Enter new directory as the last entry and trim the
     *                  previous entry to its IDEAL_LENGTH 
     *          else 
     *                  allocate a new data block and enter new directory as 
     *                  first entry in new data block 
    ---------------------------------------------------------------- */
    
    // neededlen = #bytes needed by this new directory 
    neededlen = 4 * ((8 + strlen(name) + 3) / 4); 
    bzero(buf, BLOCK_SIZE); //clear buf

    // check all the direct blocks for free space 
    for (i = 0; i < 12; i++) 
    { 
        count = 0; 
       // break if the iblock is empty 
        if(pip->INODE.i_block[i] == 0)
            break; 
        
        // read parent's data block into buf
        get_block(dev, pip->INODE.i_block[i], buf); 
        

        cp = buf;
        dp = (DIR*) buf;

        // Step to the last entry of the data block 
        while (cp < &buf[BLOCK_SIZE]) 
        {
            // ideallen = minimum length that last record takes up? 
            ideallen = 4 * ((8 + dp->name_len + 3) / 4); // calculate ideal length of record (to end of block)

            if ((dp->rec_len - ideallen) >= neededlen) // There's room in this block 
            {   
                DIR* lastDir;
                int lastBlockBool;

                if ((cp + dp->rec_len) < &buf[BLOCK_SIZE])
                    lastBlockBool = 0; //not the last block
                else
                    lastBlockBool = 1; //it is the last block!

                // Trim the length of the last record 
                dp->rec_len = ideallen;

                //move to beginning of new last entry
                cp += ideallen;
                count += ideallen;

                // add last entry
                lastDir = (DIR*)cp;
                lastDir->inode = inumber;
                lastDir->name_len = strlen(name);
                strncpy(lastDir->name, name, lastDir->name_len);

                // If this is the last entry in the data block
                        // it's length extends to the end of the block 
                if (lastBlockBool) 
                    lastDir->rec_len = BLOCK_SIZE - count;
                else
                    lastDir->rec_len = neededlen;

                // (8) write parent's data block back to disk
                put_block(dev, pip->INODE.i_block[i], buf);

                //update parent inode link count
                pip->INODE.i_links_count++;
                pip->INODE.i_atime = time(0L); 
                pip->dirty = 1;
                
                
                iput(pip);      // Write back to disk 
                // Update group descriptor free_inodes and such 
                updateGD();
                return;

            }

            //advance dp to next dir entry in it's block:
            count += dp->rec_len;
            cp += dp->rec_len;
            dp = (DIR*) cp;
        }
    }

    return;
}
Ejemplo n.º 13
0
void* AllocateExecutableMemory(size_t size, bool low)
{
#ifdef _XBOX
	void* ptr = balloc(size);
#elif defined(_WIN32)
	void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(__SYMBIAN32__)
	//This function may be called more than once, and we want to create only one big
	//memory chunk for all the executable code for the JIT
	if( g_code_chunk == NULL && g_code_heap == NULL)
	{
		g_code_chunk = new RChunk();
		g_code_chunk->CreateLocalCode(CODECHUNK_SIZE, CODECHUNK_SIZE + 3*GetPageSize());
		g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, CODECHUNK_SIZE, 1, CODECHUNK_SIZE + 3*GetPageSize());
		g_next_ptr = reinterpret_cast<u8*>(g_code_heap->AllocZ(CODECHUNK_SIZE));
		g_orig_ptr = g_next_ptr;
	}
	void* ptr = (void*)g_next_ptr;
	g_next_ptr += size;
#else
	static char *map_hint = 0;
#if defined(__x86_64__) && !defined(MAP_32BIT)
	// This OS has no flag to enforce allocation below the 4 GB boundary,
	// but if we hint that we want a low address it is very likely we will
	// get one.
	// An older version of this code used MAP_FIXED, but that has the side
	// effect of discarding already mapped pages that happen to be in the
	// requested virtual memory range (such as the emulated RAM, sometimes).
	if (low && (!map_hint))
		map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
#endif
	void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE	| PROT_EXEC,
		MAP_ANON | MAP_PRIVATE
#if defined(__x86_64__) && defined(MAP_32BIT)
		| (low ? MAP_32BIT : 0)
#endif
		, -1, 0);
#endif /* defined(_WIN32) */

	// printf("Mapped executable memory at %p (size %ld)\n", ptr,
	//	(unsigned long)size);

#if defined(__FreeBSD__)
	if (ptr == MAP_FAILED)
	{
		ptr = NULL;
#else
	if (ptr == NULL)
	{
#endif
		PanicAlert("Failed to allocate executable memory");
	}
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
	else if (low)
	{
		map_hint += size;
		map_hint = (char*)round_page(map_hint); /* round up to the next page */
		// printf("Next map will (hopefully) be at %p\n", map_hint);
	}
#endif

	return ptr;
}

void* AllocateMemoryPages(size_t size)
{
	size = (size + 4095) & (~4095);
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#elif defined(__SYMBIAN32__)
	void* ptr = malloc(size);
#else
	void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
#endif

	// printf("Mapped memory at %p (size %ld)\n", ptr,
	//	(unsigned long)size);
	if (ptr == NULL)
		PanicAlert("Failed to allocate raw memory");

	return ptr;
}
Ejemplo n.º 14
0
static void
remote_send_cb(EV_P_ ev_io *w, int revents)
{
    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;
    remote_t *remote              = remote_send_ctx->remote;
    server_t *server              = remote->server;

    ev_timer_stop(EV_A_ & remote_send_ctx->watcher);

    if (!remote_send_ctx->connected) {
        int r = 0;
        if (remote->addr == NULL) {
            struct sockaddr_storage addr;
            memset(&addr, 0, sizeof(struct sockaddr_storage));
            socklen_t len = sizeof addr;
            r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        }
        if (r == 0) {
            remote_send_ctx->connected = 1;

            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_stop(EV_A_ & server->recv_ctx->io);
            ev_io_start(EV_A_ & remote->recv_ctx->io);
            ev_timer_start(EV_A_ & remote->recv_ctx->watcher);

            // send destaddr
            buffer_t ss_addr_to_send;
            buffer_t *abuf = &ss_addr_to_send;
            balloc(abuf, BUF_SIZE);

            if (server->hostname_len > 0
                    && validate_hostname(server->hostname, server->hostname_len)) { // HTTP/SNI
                uint16_t port;
                if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                    port = (((struct sockaddr_in6 *)&(server->destaddr))->sin6_port);
                } else {                             // IPv4
                    port = (((struct sockaddr_in *)&(server->destaddr))->sin_port);
                }

                abuf->data[abuf->len++] = 3;          // Type 3 is hostname
                abuf->data[abuf->len++] = server->hostname_len;
                memcpy(abuf->data + abuf->len, server->hostname, server->hostname_len);
                abuf->len += server->hostname_len;
                memcpy(abuf->data + abuf->len, &port, 2);
            } else if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                abuf->data[abuf->len++] = 4;          // Type 4 is IPv6 address

                size_t in6_addr_len = sizeof(struct in6_addr);
                memcpy(abuf->data + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),
                       in6_addr_len);
                abuf->len += in6_addr_len;
                memcpy(abuf->data + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),
                       2);
            } else {                             // IPv4
                abuf->data[abuf->len++] = 1; // Type 1 is IPv4 address

                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(abuf->data + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len);
                abuf->len += in_addr_len;
                memcpy(abuf->data + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2);
            }

            abuf->len += 2;

            int err = crypto->encrypt(abuf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                bfree(abuf);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            err = crypto->encrypt(remote->buf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                bfree(abuf);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            bprepend(remote->buf, abuf, BUF_SIZE);
            bfree(abuf);
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    if (remote->buf->len == 0) {
        // close and free
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else {
        // has data to send
        ssize_t s;
        if (remote->addr != NULL) {
            s = sendto(remote->fd, remote->buf->data + remote->buf->idx,
                       remote->buf->len, MSG_FASTOPEN, remote->addr,
                       get_sockaddr_len(remote->addr));

            if (s == -1 && (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||
                errno == ENOPROTOOPT)) {
                fast_open = 0;
                LOGE("fast open is not supported on this platform");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            remote->addr = NULL;

            if (s == -1) {
                if (errno == CONNECT_IN_PROGRESS || errno == EAGAIN
                    || errno == EWOULDBLOCK) {
                    ev_io_start(EV_A_ & remote_send_ctx->io);
                    ev_timer_start(EV_A_ & remote_send_ctx->watcher);
                } else {
                    ERROR("connect");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                }
                return;
            }
        } else {
            s = send(remote->fd, remote->buf->data + remote->buf->idx,
                     remote->buf->len, 0);
        }

        if (s == -1) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                ERROR("send");
                // close and free
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }
            return;
        } else if (s < remote->buf->len) {
            // partly sent, move memory, wait for the next time to send
            remote->buf->len -= s;
            remote->buf->idx += s;
            ev_io_start(EV_A_ & remote_send_ctx->io);
            return;
        } else {
            // all sent out, wait for reading
            remote->buf->len = 0;
            remote->buf->idx = 0;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);
        }
    }
}
Ejemplo n.º 15
0
int websAspRequest(webs_t wp, char_t *lpath)
{
	websStatType	sbuf;
	char			*rbuf;
	char_t			*token, *lang, *result, *path, *ep, *cp, *buf, *nextp;
	char_t			*last;
	int				rc, engine, len, ejid;

	a_assert(websValid(wp));
	a_assert(lpath && *lpath);

	rc = -1;
	buf = NULL;
	rbuf = NULL;
	engine = EMF_SCRIPT_EJSCRIPT;
	wp->flags |= WEBS_HEADER_DONE;
	path = websGetRequestPath(wp);

/*
 *	Create Ejscript instance in case it is needed
 */
	ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
	if (ejid < 0) {
		websError(wp, 200, T("Can't create Ejscript engine"));
		goto done;
	}
	ejSetUserHandle(ejid, (int) wp);

	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
		websError(wp, 200, T("Can't stat %s"), lpath);
		goto done;
	}

/*
 *	Create a buffer to hold the ASP file in-memory
 */
	len = sbuf.size * sizeof(char);
	if ((rbuf = balloc(B_L, len + 1)) == NULL) {
		websError(wp, 200, T("Can't get memory"));
		goto done;
	}
	rbuf[len] = '\0';

	if (websPageReadData(wp, rbuf, len) != len) {
		websError(wp, 200, T("Cant read %s"), lpath);
		goto done;
	}
	websPageClose(wp);

/*
 *	Convert to UNICODE if necessary.
 */
	if ((buf = ballocAscToUni(rbuf, len)) == NULL) {
		websError(wp, 200, T("Can't get memory"));
		goto done;
	}

/*
 *	Scan for the next "<%"
 */
	last = buf;
	rc = 0;
	while (rc == 0 && *last && ((nextp = gstrstr(last, T("<%"))) != NULL)) {
		websWriteBlock(wp, last, (nextp - last));
		nextp = skipWhite(nextp + 2);

/*
 *		Decode the language
 */
		token = T("language");

		if ((lang = strtokcmp(nextp, token)) != NULL) {
			if ((cp = strtokcmp(lang, T("=javascript"))) != NULL) {
				engine = EMF_SCRIPT_EJSCRIPT;
			} else {
				cp = nextp;
			}
			nextp = cp;
		}

/*
 *		Find tailing bracket and then evaluate the script
 */
		if ((ep = gstrstr(nextp, T("%>"))) != NULL) {

			*ep = '\0';
			last = ep + 2;
			nextp = skipWhite(nextp);
/*
 *			Handle backquoted newlines
 */
			for (cp = nextp; *cp; ) {
				if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) {
					*cp++ = ' ';
					while (*cp == '\r' || *cp == '\n') {
						*cp++ = ' ';
					}
				} else {
					cp++;
				}
			}

/*
 *			Now call the relevant script engine. Output is done directly
 *			by the ASP script procedure by calling websWrite()
 */
			if (*nextp) {
				result = NULL;
				if (engine == EMF_SCRIPT_EJSCRIPT) {
					rc = scriptEval(engine, nextp, &result, ejid);
				} else {
					rc = scriptEval(engine, nextp, &result, (int) wp);
				}
				if (rc < 0) {
/*
 *					On an error, discard all output accumulated so far
 *					and store the error in the result buffer. Be careful if the
 *					user has called websError() already.
 */
					if (websValid(wp)) {
						if (result) {
							websWrite(wp, T("<h2><b>ASP Error: %s</b></h2>\n"), 
								result);
							websWrite(wp, T("<pre>%s</pre>"), nextp);
							bfree(B_L, result);
						} else {
							websWrite(wp, T("<h2><b>ASP Error</b></h2>\n%s\n"),
								nextp);
						}
						websWrite(wp, T("</body></html>\n"));
						rc = 0;
					}
					goto done;
				}
			}

		} else {
			websError(wp, 200, T("Unterminated script in %s: \n"), lpath);
			rc = -1;
			goto done;
		}
	}
/*
 *	Output any trailing HTML page text
 */
	if (last && *last && rc == 0) {
		websWriteBlock(wp, last, gstrlen(last));
	}
	rc = 0;

/*
 *	Common exit and cleanup
 */
done:
	if (websValid(wp)) {
		websPageClose(wp);
		if (ejid >= 0) {
			ejCloseEngine(ejid);
		}
	}
	bfreeSafe(B_L, buf);
	bfreeSafe(B_L, rbuf);
	return rc;
}
Ejemplo n.º 16
0
int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath, 
	char_t **pport, char_t **pquery, char_t **pproto, char_t **ptag, 
	char_t **pext)
{
	char_t		*tok, *cp, *host, *path, *port, *proto, *tag, *query, *ext;
	char_t		*last_delim, *hostbuf, *portbuf, *buf;
	int			c, len, ulen;

	a_assert(url);
	a_assert(pbuf);

	ulen = gstrlen(url);
/*
 *	We allocate enough to store separate hostname and port number fields.
 *	As there are 3 strings in the one buffer, we need room for 3 null chars.
 *	We allocate MAX_PORT_LEN char_t's for the port number.
 */
	len = ulen * 2 + MAX_PORT_LEN + 3;
	if ((buf = balloc(B_L, len * sizeof(char_t))) == NULL) {
		return -1;
	}
	portbuf = &buf[len - MAX_PORT_LEN - 1];
	hostbuf = &buf[ulen+1];
	gstrcpy(buf, url);
	url = buf;

/*
 *	Convert the current listen port to a string. We use this if the URL has
 *	no explicit port setting
 */
	stritoa(websGetPort(), portbuf, MAX_PORT_LEN);
	port = portbuf;
	path = T("/");
	proto = T("http");
	host = T("localhost");
	query = T("");
	ext = htmExt;
	tag = T("");

	if (gstrncmp(url, T("http://"), 7) == 0) {
		tok = &url[7];
		tok[-3] = '\0';
		proto = url;
		host = tok;
		for (cp = tok; *cp; cp++) {
			if (*cp == '/') {
				break;
			}
			if (*cp == ':') {
				*cp++ = '\0';
				port = cp;
				tok = cp;
			}
		}
		if ((cp = gstrchr(tok, '/')) != NULL) {
/*
 *			If a full URL is supplied, we need to copy the host and port 
 *			portions into static buffers.
 */
			c = *cp;
			*cp = '\0';
			gstrncpy(hostbuf, host, ulen);
			gstrncpy(portbuf, port, MAX_PORT_LEN);
			*cp = c;
			host = hostbuf;
			port = portbuf;
			path = cp;
			tok = cp;
		}

	} else {
		path = url;
		tok = url;
	}

/*
 *	Parse the query string
 */
	if ((cp = gstrchr(tok, '?')) != NULL) {
		*cp++ = '\0';
		query = cp;
		path = tok;
		tok = query;
	} 

/*
 *	Parse the fragment identifier
 */
	if ((cp = gstrchr(tok, '#')) != NULL) {
		*cp++ = '\0';
		if (*query == 0) {
			path = tok;
		}
	}

/*
 *	Only do the following if asked for the extension
 */
	if (pext) {
		if ((cp = gstrrchr(path, '.')) != NULL) {
			if ((last_delim = gstrrchr(path, '/')) != NULL) {
				if (last_delim > cp) {
					ext = htmExt;
				} else {
					ext = cp;
				}
			} else {
				ext = cp;
			}
		} else {
			if (path[gstrlen(path) - 1] == '/') {
				ext = htmExt;
			}
		}
	}

/*
 *	Pass back the fields requested (if not NULL)
 */
	if (phost)
		*phost = host;
	if (ppath)
		*ppath = path;
	if (pport)
		*pport = port;
	if (pproto)
		*pproto = proto;
	if (pquery)
		*pquery = query;
	if (ptag)
		*ptag = tag;
	if (pext)
		*pext = ext;
	*pbuf = buf;
	return 0;
}
Ejemplo n.º 17
0
void eval_jerry_script (int argc, char *argv[], struct tcmd_handler_ctx *ctx)
{
  if (argc < 3)
  {
    TCMD_RSP_ERROR (ctx, NULL);
    help ();
    return;
  }
  else
  {
    OS_ERR_TYPE err;
    size_t str_total_length = 0;
    size_t *str_lens = (size_t *) balloc ((argc - 2) * sizeof(size_t), &err);
    if (str_lens == NULL || err != E_OS_OK)
    {
      printk ("%s: allocate memory failed!", __func__);
      TCMD_RSP_ERROR (ctx, NULL);
      return;
    }
    for (int i = 2; i < argc; ++i)
    {
      str_lens[i - 2] = strlen (argv[i]);
      str_total_length += str_lens[i - 2] + 1;
    }
    err = E_OS_OK;
    char *buffer = (char *) balloc (str_total_length, &err);
    if (buffer == NULL || err != E_OS_OK)
    {
      printk ("%s: allocate memory failed!", __func__);
      TCMD_RSP_ERROR (ctx, NULL);
      return;
    }

    char *p = buffer;
    for (int i = 2; i < argc; ++i)
    {
      for (int j =0; j < str_lens[i - 2]; ++j)
      {
        *p = argv[i][j];
        ++p;
      }
      *p = ' ';
      ++p;
    }
    *p = '\0';

    jerry_value_t eval_ret = jerry_eval (buffer, str_total_length - 1, false);

    if (jerry_value_is_error (eval_ret))
    {
      jerry_resolve_error (eval_ret);
      TCMD_RSP_ERROR (ctx, NULL);
    }
    else
    {
      jerry_value_t args[] = {eval_ret};
      jerry_value_t ret_val_print = jerry_call_function (print_function,
                                                         jerry_create_undefined (),
                                                         args,
                                                         1);
      jerry_release_value (ret_val_print);
      TCMD_RSP_FINAL (ctx, NULL);
    }
    jerry_release_value (eval_ret);
    bfree (buffer);
    bfree (str_lens);
  }
}
Ejemplo n.º 18
0
int mkfile(char * filename,struct m_inode* inode)// inode为待添加文件的目录的主存索引节点
{
    if(inode==NULL)
        return -1;
    if(inode->finode.mode!=1)
    {
        cout<<"非目录文件"<<endl;
        return -1;
    }
    int count=inode->finode.fileSize/sizeof(struct direct);
    if(count>ADDRN*DIRNUM)
    {
        cout<<"目录项已最大"<<endl;
        return -1;
    }
    dir * dir=(struct dir*)calloc(1,sizeof(struct dir));

    for(int addr=0; addr<inode->finode.addrnum; addr++)
    {
        bread(dir,inode->finode.addr[addr],0,sizeof(struct dir),1);
        for(int i=0; i<dir->dirNum; i++)
            if(strcmp(dir->direct[i].directName,filename)==0)
            {
                cout.write(filename,strlen(filename));
                cout<<"目录项已存在"<<endl;
                return -1;
            }
    }
    bread(dir,inode->finode.addr[inode->finode.addrnum-1],0,sizeof(struct dir),1);//读出最后一个数据块的目录
    struct m_inode * tmpinode=ialloc();//分配子目录I节点
    tmpinode->finode.addr[0]=balloc();//分配子目录磁盘块
    tmpinode->finode.mode=0;
    write_finode(tmpinode);

    if(dir->dirNum==DIRNUM)//当前数据块可容纳目录已满,再申请数据块
    {
        inode->finode.addr[inode->finode.addrnum]=balloc();

        memset(dir,0,sizeof(struct dir));
        strcpy(dir->direct[0].directName,filename);//修改目录
        dir->direct[0].inodeID=tmpinode->inodeID;
        dir->dirNum=1;
        bwrite(dir,inode->finode.addr[inode->finode.addrnum],0,sizeof(struct dir),1);
        inode->finode.addrnum++;
        inode->finode.fileSize+=sizeof(struct direct);//更新inodeI节点
        write_finode(inode);
        return 1;
    }
    else
    {

        strcpy(dir->direct[dir->dirNum].directName,filename);//修改目录目录项
        dir->direct[dir->dirNum].inodeID=tmpinode->inodeID;
        dir->dirNum+=1;
        bwrite(dir,inode->finode.addr[inode->finode.addrnum-1],0,sizeof(struct dir),1);

        inode->finode.fileSize+=sizeof(struct direct);//更新I节点
        write_finode(inode);
        return 1;
    }

}
Ejemplo n.º 19
0
static const char *parse_string(opstack ** stack, const char *in,
    const void *userdata)
{                               /* (char*) -> char* */
    char *c;
    char *buffer = balloc(TOKENSIZE);
    size_t size = TOKENSIZE - 1;
    const char *ic = in;
    char *oc = buffer;
    /* mode flags */
    bool f_escape = false;
    bool bDone = false;
    variant var;

    while (*ic && !bDone) {
        if (f_escape) {
            f_escape = false;
            switch (*ic) {
            case 'n':
                if (size > 0) {
                    *oc++ = '\n';
                    --size;
                }
                break;
            case 't':
                if (size > 0) {
                    *oc++ = '\t';
                    --size;
                }
                break;
            default:
                if (size > 0) {
                    *oc++ = *ic++;
                    --size;
                }
            }
        }
        else {
            int ch = (unsigned char)(*ic);
            size_t bytes;

            switch (ch) {
            case '\\':
                f_escape = true;
                ++ic;
                break;
            case '"':
                bDone = true;
                ++ic;
                break;
            case '$':
                ic = parse_symbol(stack, ++ic, userdata);
                if (ic == NULL)
                    return NULL;
                c = (char *)opop_v(stack);
                bytes = (c ? strlcpy(oc, c, size) : 0);
                if (bytes < size)
                    oc += bytes;
                else
                    oc += size;
                bfree(c);
                break;
            default:
                if (size > 0) {
                    *oc++ = *ic++;
                    --size;
                }
                else
                    ++ic;
            }
        }
    }
    *oc++ = '\0';
    bfree(oc);
    var.v = buffer;
    opush(stack, var);
    return ic;
}
Ejemplo n.º 20
0
int websValidateUrl(webs_t wp, char_t *path)
{
   /*
     Thanks to Dhanwa T ([email protected]) for this fix -- previously,
     if an URL was requested having more than (the hardcoded) 64 parts,
     the webServer would experience a hard crash as it attempted to
     write past the end of the array 'parts'.
	 Also fixes: http://www.securiteam.com/securitynews/5MP0C1580W.html
    */
	char_t	*parts[MAX_URL_DEPTH];	/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath; 
	int	      i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * Fixed by Matt Moore, 22 Jul 02
	* http://www.securiteam.com/securitynews/5RP0I007PG.html
	* http://www.securiteam.com/securitynews/5QP010U3FS.html
	* 
	* There were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *  
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.
    *  However, by encoding the '/' character, it is possible to break out of
    *  the web root and read arbitrary files from the server.
    *  Hence a request like:
    * 
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
	token = gstrchr(path, '\\');
	while (token != NULL) {
		*token = '/';
		token = gstrchr(token, '\\');
	}
	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web. 
 */
	while (token != NULL) 
   {
      if (npart >= MAX_URL_DEPTH)
      {
         /*
          * malformed URL -- too many parts for us to process.
          */
         bfree(B_L, path);
         return -1;
      }
		if (gstrcmp(token, T("..")) == 0) 
      {
			if (npart > 0) 
         {
				npart--;
			}
		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

#ifdef WIN32
   if (isBadWindowsPath(parts, npart))
   {
      bfree(B_L, path);
      return -1;
   }

#endif

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);
	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
Ejemplo n.º 21
0
Archivo: mkfs.c Proyecto: Dsdubov/xv6
int
main(int argc, char *argv[])
{
  int i, cc, fd;
  uint rootino, inum, off;
  struct dirent de;
  char buf[BSIZE];
  struct dinode din;


  static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");

  if(argc < 2){
    fprintf(stderr, "Usage: mkfs fs.img files...\n");
    exit(1);
  }

  assert((BSIZE % sizeof(struct dinode)) == 0);
  assert((BSIZE % sizeof(struct dirent)) == 0);

  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
  if(fsfd < 0){
    perror(argv[1]);
    exit(1);
  }

  // 1 fs block = 1 disk sector
  nmeta = 2 + nlog + ninodeblocks + nbitmap;
  nblocks = FSSIZE - nmeta;

  sb.size = xint(FSSIZE);
  sb.nblocks = xint(nblocks);
  sb.ninodes = xint(NINODES);
  sb.nlog = xint(nlog);
  sb.logstart = xint(2);
  sb.inodestart = xint(2+nlog);
  sb.bmapstart = xint(2+nlog+ninodeblocks);

  printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
         nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);

  freeblock = nmeta;     // the first free block that we can allocate

  for(i = 0; i < FSSIZE; i++)
    wsect(i, zeroes);

  memset(buf, 0, sizeof(buf));
  memmove(buf, &sb, sizeof(sb));
  wsect(1, buf);

  rootino = ialloc(T_DIR);
  assert(rootino == ROOTINO);

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, ".");
  iappend(rootino, &de, sizeof(de));

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, "..");
  iappend(rootino, &de, sizeof(de));

  for(i = 2; i < argc; i++){
    assert(index(argv[i], '/') == 0);

    if((fd = open(argv[i], 0)) < 0){
      perror(argv[i]);
      exit(1);
    }
    
    // Skip leading _ in name when writing to file system.
    // The binaries are named _rm, _cat, etc. to keep the
    // build operating system from trying to execute them
    // in place of system binaries like rm and cat.
    if(argv[i][0] == '_')
      ++argv[i];

    inum = ialloc(T_FILE);

    bzero(&de, sizeof(de));
    de.inum = xshort(inum);
    strncpy(de.name, argv[i], DIRSIZ);
    iappend(rootino, &de, sizeof(de));

    while((cc = read(fd, buf, sizeof(buf))) > 0)
      iappend(inum, buf, cc);

    close(fd);
  }

  // fix size of root inode dir
  rinode(rootino, &din);
  off = xint(din.size);
  off = ((off/BSIZE) + 1) * BSIZE;
  din.size = xint(off);
  winode(rootino, &din);

  balloc(freeblock);

  exit(0);
}
Ejemplo n.º 22
0
static int websBuildWhitelistRecursive(char *_path, fileNode_t *dir, int level)
{
	WIN32_FIND_DATA	findData;
	HANDLE	fh;
	fileNode_t	*cnode, *nnode; /* current node, next node */
#ifdef WEBS_SSL_SUPPORT
	sslList_t	*l;
#endif
	int		rc = 0;
	int		firstTime;
	char	path[MAX_PATH];
	char	tmppath[MAX_PATH];

	firstTime = 1;
	cnode = dir;
	websMakePath(path, _path, NULL, 1);
	fh = FindFirstFile((LPCSTR)path, &findData);
	while (fh != INVALID_HANDLE_VALUE) {
		if ((strcmp(findData.cFileName, ".") == 0) ||
				(strcmp(findData.cFileName, "..") == 0) ||
				(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
				(findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
			goto nextFile;
		}
		nnode = balloc(B_L, sizeof(fileNode_t));
		memset(nnode, 0x0, sizeof(fileNode_t));
		if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			fmtAlloc(&(nnode->name), MAX_PATH, "%s/", findData.cFileName);
			nnode->flags |= WHITELIST_DIR;
		} else {
			nnode->name = bstrdup(B_L, findData.cFileName);
		}
		if (firstTime) {
			cnode->child = nnode;
			firstTime = 0;
		} else {
			cnode->next = nnode;
		}
		cnode = nnode;
		if (strncmp(path + strlen(websDefaultDir), "/" CGI_BIN, 
				strlen(CGI_BIN) + 1) == 0) {
			cnode->flags |= WHITELIST_CGI;
		}
#ifdef WEBS_SSL_SUPPORT
		for (l = sslList; l != NULL; l = l->next) {
			if (strncmp(path + strlen(websDefaultDir), l->url, 
					strlen(l->url)) == 0) {
				cnode->flags |= WHITELIST_SSL;
			}
		}
#endif /* WEBS_SSL_SUPPORT */
		if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			websMakePath(tmppath, path, findData.cFileName, 1);
			if (level < MAX_URL_DEPTH) {
				if (websBuildWhitelistRecursive(tmppath, cnode, level + 1) < 0){
					cnode->flags |= WHITELIST_BLOCKED;
				}
			}
		}
nextFile:
		if (FindNextFile(fh, &findData) == 0) {
			if (GetLastError() != ERROR_NO_MORE_FILES) {
				rc = -1;
			}
			break;
		}
	}
	FindClose(fh);
	return rc;
}
Ejemplo n.º 23
0
Archivo: mkfs.c Proyecto: swetland/xv6
int
main(int argc, char *argv[])
{
  int i, cc, fd;
  uint rootino, inum, off;
  struct dirent de;
  char buf[512];
  struct dinode din;


  static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");

  if(argc < 2){
    fprintf(stderr, "Usage: mkfs fs.img files...\n");
    exit(1);
  }

  assert((512 % sizeof(struct dinode)) == 0);
  assert((512 % sizeof(struct dirent)) == 0);

  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
  if(fsfd < 0){
    perror(argv[1]);
    exit(1);
  }

  sb.size = xint(size);
  sb.nblocks = xint(nblocks); // so whole disk is size sectors
  sb.ninodes = xint(ninodes);
  sb.nlog = xint(nlog);

  bitblocks = size/(512*8) + 1;
  usedblocks = ninodes / IPB + 3 + bitblocks;
  freeblock = usedblocks;

  printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks,
         bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog);

  assert(nblocks + usedblocks + nlog == size);

  for(i = 0; i < nblocks + usedblocks + nlog; i++)
    wsect(i, zeroes);

  memset(buf, 0, sizeof(buf));
  memmove(buf, &sb, sizeof(sb));
  wsect(1, buf);

  rootino = ialloc(T_DIR);
  assert(rootino == ROOTINO);

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, ".");
  iappend(rootino, &de, sizeof(de));

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, "..");
  iappend(rootino, &de, sizeof(de));

  for(i = 2; i < argc; i++){
    char *name = argv[i];

    if (!strncmp(name, "fs/", 3))
      name += 3;

    assert(index(name, '/') == 0);

    if((fd = open(argv[i], 0)) < 0){
      perror(argv[i]);
      exit(1);
    }
    
    inum = ialloc(T_FILE);

    bzero(&de, sizeof(de));
    de.inum = xshort(inum);
    strncpy(de.name, name, DIRSIZ);
    iappend(rootino, &de, sizeof(de));

    while((cc = read(fd, buf, sizeof(buf))) > 0)
      iappend(inum, buf, cc);

    close(fd);
  }

  // fix size of root inode dir
  rinode(rootino, &din);
  off = xint(din.size);
  off = ((off/BSIZE) + 1) * BSIZE;
  din.size = xint(off);
  winode(rootino, &din);

  balloc(usedblocks);

  exit(0);
}
Ejemplo n.º 24
0
/*
 *	LINUX, MACOSX, ETC: Build whitelist
 */
#else /* !WIN */
static int websBuildWhitelistRecursive(char *_path, fileNode_t *dir, int level)
{
	struct dirent	*findData, *result;
	DIR				*fh;
	fileNode_t		*cnode, *nnode; /* current node, next node */
	int		firstTime;
	char	path[PATH_MAX];
	char	tmppath[PATH_MAX];

	firstTime = 1;
	cnode = dir;
	/* On some platforms such as Solaris, struct dirent includes only one
	 * byte for d_name field, meaning we would overflow the field when
	 * readdir_r is called.  So we check for this here.
	 * Another potential issue is if somehow a filesystem is mounted or linked
	 * in a subdirectory or file that has name longer than PATH_MAX.  We 
	 * ignore that possibility here, and leave it to the user to ensure that
	 * the wwwroot directory does not contain this configuration.
	 * http://womble.decadentplace.org.uk/readdir_r-advisory.html
	 */ 
	if (sizeof(struct dirent) > PATH_MAX) {
		findData = balloc(B_L, sizeof(struct dirent));
	} else {
		findData = balloc(B_L, sizeof(struct dirent) + PATH_MAX);
	}
	websMakePath(path, _path, NULL, 0);
	if ((fh = opendir(path)) == NULL) {
		bfree(B_L, findData);
		return -1;	/* Likely no permission to access this directory */
	}
	while ((readdir_r(fh, findData, &result) == 0) && result) {
		if ((strcmp(findData->d_name, ".") == 0) ||
				(strcmp(findData->d_name, "..") == 0) ||
				(findData->d_type != DT_REG && findData->d_type != DT_DIR)) {
			continue;
		}
		nnode = balloc(B_L, sizeof(fileNode_t));
		memset(nnode, 0x0, sizeof(fileNode_t));
		if (findData->d_type == DT_DIR) {
			fmtAlloc(&(nnode->name), PATH_MAX, "%s/", findData->d_name);
			nnode->flags |= WHITELIST_DIR;
		} else {
			nnode->name = bstrdup(B_L, findData->d_name);
		}
		if (firstTime) {
			cnode->child = nnode;
			firstTime = 0;
		} else {
			cnode->next = nnode;
		}
		cnode = nnode;
		if (strncmp(path + strlen(websDefaultDir), "/" CGI_BIN, 
				strlen(CGI_BIN) + 1) == 0) {
			cnode->flags |= WHITELIST_CGI;
		}
#ifdef WEBS_SSL_SUPPORT
		sslList_t	*l;
		for (l = sslList; l != NULL; l = l->next) {
			if (strncmp(path + strlen(websDefaultDir), l->url, 
					strlen(l->url)) == 0) {
				cnode->flags |= WHITELIST_SSL;
				break;
			}
		}
#endif /* WEBS_SSL_SUPPORT */
		if (findData->d_type == DT_DIR) {
			websMakePath(tmppath, path, findData->d_name, 0);
			if (level < MAX_URL_DEPTH) {
				if (websBuildWhitelistRecursive(tmppath, cnode, level + 1) < 0){
					cnode->flags |= WHITELIST_BLOCKED;
				}
			}
		}
	}
	bfree(B_L, findData);
	closedir(fh);
	return 0;
}
Ejemplo n.º 25
0
static void
remote_recv_cb(EV_P_ ev_io *w, int revents)
{
    ssize_t r;
    remote_ctx_t *remote_ctx = (remote_ctx_t *)w;
    server_ctx_t *server_ctx = remote_ctx->server_ctx;

    // server has been closed
    if (server_ctx == NULL) {
        LOGE("[udp] invalid server");
        close_and_free_remote(EV_A_ remote_ctx);
        return;
    }

    if (verbose) {
        LOGI("[udp] remote receive a packet");
    }

    struct sockaddr_storage src_addr;
    socklen_t src_addr_len = sizeof(struct sockaddr_storage);
    memset(&src_addr, 0, src_addr_len);

    buffer_t *buf = ss_malloc(sizeof(buffer_t));
    balloc(buf, buf_size);

    // recv
    r = recvfrom(remote_ctx->fd, buf->data, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len);

    if (r == -1) {
        // error on recv
        // simply drop that packet
        ERROR("[udp] remote_recv_recvfrom");
        goto CLEAN_UP;
    } else if (r > packet_size) {
        if (verbose) {
            LOGI("[udp] remote_recv_recvfrom fragmentation");
        }
    }

    buf->len = r;

#ifdef MODULE_LOCAL
    int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size);
    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }

#ifdef MODULE_REDIR
    struct sockaddr_storage dst_addr;
    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));
    int len = parse_udprelay_header(buf->data, buf->len, NULL, NULL, &dst_addr);

    if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) {
        LOGI("[udp] ss-redir does not support domain name");
        goto CLEAN_UP;
    }
#else
    int len = parse_udprelay_header(buf->data, buf->len, NULL, NULL, NULL);
#endif

    if (len == 0) {
        LOGI("[udp] error in parse header");
        // error in parse header
        goto CLEAN_UP;
    }

    // server may return using a different address type other than the type we
    // have used during sending
#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR)
    // Construct packet
    buf->len -= len;
    memmove(buf->data, buf->data + len, buf->len);
#else
#ifdef __ANDROID__
    rx += buf->len;
    stat_update_cb();
#endif
    // Construct packet
    brealloc(buf, buf->len + 3, buf_size);
    memmove(buf->data + 3, buf->data, buf->len);
    memset(buf->data, 0, 3);
    buf->len += 3;
#endif

#endif

#ifdef MODULE_REMOTE

    rx += buf->len;

    char addr_header_buf[512];
    char *addr_header   = remote_ctx->addr_header;
    int addr_header_len = remote_ctx->addr_header_len;

    if (remote_ctx->af == AF_INET || remote_ctx->af == AF_INET6) {
        addr_header_len = construct_udprelay_header(&src_addr, addr_header_buf);
        addr_header     = addr_header_buf;
    }

    // Construct packet
    brealloc(buf, buf->len + addr_header_len, buf_size);
    memmove(buf->data + addr_header_len, buf->data, buf->len);
    memcpy(buf->data, addr_header, addr_header_len);
    buf->len += addr_header_len;

    int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size);
    if (err) {
        // drop the packet silently
        goto CLEAN_UP;
    }

#endif

    if (buf->len > packet_size) {
        if (verbose) {
            LOGI("[udp] remote_recv_sendto fragmentation");
        }
    }

    size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr);

#ifdef MODULE_REDIR

    size_t remote_dst_addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);

    int src_fd = socket(remote_ctx->src_addr.ss_family, SOCK_DGRAM, 0);
    if (src_fd < 0) {
        ERROR("[udp] remote_recv_socket");
        goto CLEAN_UP;
    }
    int opt = 1;
    if (setsockopt(src_fd, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt))) {
        ERROR("[udp] remote_recv_setsockopt");
        close(src_fd);
        goto CLEAN_UP;
    }
    if (setsockopt(src_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
        ERROR("[udp] remote_recv_setsockopt");
        close(src_fd);
        goto CLEAN_UP;
    }
#ifdef IP_TOS
    // Set QoS flag
    int tos = 46;
    setsockopt(src_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
#endif
    if (bind(src_fd, (struct sockaddr *)&dst_addr, remote_dst_addr_len) != 0) {
        ERROR("[udp] remote_recv_bind");
        close(src_fd);
        goto CLEAN_UP;
    }

    int s = sendto(src_fd, buf->data, buf->len, 0,
                   (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len);
    if (s == -1) {
        ERROR("[udp] remote_recv_sendto");
        close(src_fd);
        goto CLEAN_UP;
    }
    close(src_fd);

#else

    int s = sendto(server_ctx->fd, buf->data, buf->len, 0,
                   (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len);
    if (s == -1) {
        ERROR("[udp] remote_recv_sendto");
        goto CLEAN_UP;
    }

#endif

    // handle the UDP packet successfully,
    // triger the timer
    ev_timer_again(EV_A_ & remote_ctx->watcher);

CLEAN_UP:

    bfree(buf);
    ss_free(buf);
}
Ejemplo n.º 26
0
// Return the disk block address of the nth block in inode ip.
// If there is no such block, alloc controls whether one is allocated.
uint
bmap(struct inode *ip, uint bn, int alloc)
{
  uint addr, *a;
  struct buf *bp;

  if(bn < NDIRECT){
    if((addr = ip->addrs[bn]) == 0){
      if(!alloc)
        return -1;
      ip->addrs[bn] = addr = balloc(ip->dev);
    }
    return addr;
  }
  bn -= NDIRECT;

  //check indirect
  if(bn < NINDIRECT){

    // Load indirect block, allocating if necessary.
    if((addr = ip->addrs[INDIRECT]) == 0){
      if(!alloc)
        return -1;
      //cprintf("allocating indirect block %d in indirect\n", bn);
      ip->addrs[INDIRECT] = addr = balloc(ip->dev);
    }
    bp = bread(ip->dev, addr);
    a = (uint*)bp->data;
  
    if((addr = a[bn]) == 0){
      if(!alloc){
        brelse(bp);
        return -1;
      }
      //cprintf("allocating data block %d in indirect\n", bn);
      a[bn] = addr = balloc(ip->dev);
      bwrite(bp);
    }
    brelse(bp);
    return addr;
  }

  //NEW CODE
  //decrement block number for new reference
  bn -= NINDIRECT;


  //DOUBLE INDIRECT
  if(bn < NDINDIRECT){

	  //cprintf("bn is %d\n", bn);

	  if((addr = ip->addrs[DINDIRECT]) == 0){
	     if(!alloc)
	        return -1;
	     ip->addrs[DINDIRECT] = addr = balloc(ip->dev);
	  }
	  bp = bread(ip->dev, addr);
	  a = (uint*)bp->data;

	  //calculate base and offset indirect block in double indirect block
	  uint base = bn / NINDIRECT;
	  uint offset = bn % NINDIRECT;

	  //grab indirect block and allocate if necessary
	  if((addr = a[base]) == 0){
	        if(!alloc){
	          brelse(bp);
	          return -1;
	        }
	        //cprintf("allocating new indirect block for bn = %d\n", bn);
	        a[base] = addr = balloc(ip->dev);
	        bwrite(bp);
	  }

	  brelse(bp);
	  bp = bread(ip->dev, addr);
	  a = (uint*)bp->data;

	  //get data block from indirect block
	  if((addr = a[offset]) == 0){
	        if(!alloc){
	          brelse(bp);
	          return -1;
	        }
	        //cprintf("allocating new data block with bn = %d\n", bn);
	        a[offset] = addr = balloc(ip->dev);
	        bwrite(bp);
	  }
	  brelse(bp);
	  return addr;

  }

  panic("bmap: out of range");
}
Ejemplo n.º 27
0
int
main(int argc, char *argv[])
{
  int i, cc, fd;
  uint rootino, inum, off;
  struct dirent de;
  char buf[512];
  struct dinode din;

  if(argc < 2){
    fprintf(stderr, "Usage: mkfs fs.img files...\n");
    exit(1);
  }

  assert((512 % sizeof(struct dinode)) == 0);
  assert((512 % sizeof(struct dirent)) == 0);

  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
  if(fsfd < 0){
    perror(argv[1]);
    exit(1);
  }

  sb.size = xint(size);
  sb.nblocks = xint(nblocks); // so whole disk is size sectors
  sb.ninodes = xint(ninodes);

  bitblocks = size/(512*8) + 1;
  usedblocks = ninodes / IPB + 3 + bitblocks;
  freeblock = usedblocks;

  printf("used %d (bit %d ninode %zu) free %u total %d\n", usedblocks,
         bitblocks, ninodes/IPB + 1, freeblock, nblocks+usedblocks);

  assert(nblocks + usedblocks == size);

  for(i = 0; i < nblocks + usedblocks; i++)
    wsect(i, zeroes);

  wsect(1, &sb);

  rootino = ialloc(T_DIR);
  assert(rootino == ROOTINO);

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, ".");
  iappend(rootino, &de, sizeof(de));

  bzero(&de, sizeof(de));
  de.inum = xshort(rootino);
  strcpy(de.name, "..");
  iappend(rootino, &de, sizeof(de));

  for(i = 2; i < argc; i++){
    assert(index(argv[i], '/') == 0);

    if((fd = open(argv[i], 0)) < 0){
      perror(argv[i]);
      exit(1);
    }
    
    // Skip leading _ in name when writing to file system.
    // The binaries are named _rm, _cat, etc. to keep the
    // build operating system from trying to execute them
    // in place of system binaries like rm and cat.
    if(argv[i][0] == '_')
      ++argv[i];

    inum = ialloc(T_FILE);

    bzero(&de, sizeof(de));
    de.inum = xshort(inum);
    strncpy(de.name, argv[i], DIRSIZ);
    iappend(rootino, &de, sizeof(de));

    while((cc = read(fd, buf, sizeof(buf))) > 0)
      iappend(inum, buf, cc);

    close(fd);
  }

  // fix size of root inode dir
  rinode(rootino, &din);
  off = xint(din.size);
  off = ((off/BSIZE) + 1) * BSIZE;
  din.size = xint(off);
  winode(rootino, &din);

  balloc(usedblocks);

  exit(0);
}
Ejemplo n.º 28
0
int
menuhit(int but, Mouse *m, Menu *menu)
{
    int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem;
    bool scrolling;
    Rectangle r, menur, sc, textr, scrollr;
    Bitmap *b;
    Point pt;
    char *item;
    extern unsigned int cursor;
    unsigned int oldcursor = cursor;

    cursorswitch(ArrowCursor);
    sc = screen.clipr;
    clipr(&screen, screen.r);
    maxwid = 0;
    for(nitem = 0;
        (item = menu->item? menu->item[nitem] : (*menu->gen)(nitem));
        nitem++){
        i = strwidth(font, item);
        if(i > maxwid)
            maxwid = i;
    }
    if(menu->lasthit<0 || menu->lasthit>=nitem)
        menu->lasthit = 0;
    screenitem = (Dy(screen.r)-10)/(fontheight()+Vspacing);
    if(nitem>Maxunscroll || nitem>screenitem){
        scrolling = true;
        nitemdrawn = Nscroll;
        if(nitemdrawn > screenitem)
            nitemdrawn = screenitem;
        wid = maxwid + Gap + Scrollwid;
        off = menu->lasthit - nitemdrawn/2;
        if(off < 0)
            off = 0;
        if(off > nitem-nitemdrawn)
            off = nitem-nitemdrawn;
        lasti = menu->lasthit-off;
    }else{
        scrolling = false;
        nitemdrawn = nitem;
        wid = maxwid;
        off = 0;
        lasti = menu->lasthit;
    }
    r = inset(Rect(0, 0, wid, nitemdrawn*(fontheight()+Vspacing)), -Margin);
    r = rsubp(r, Pt(wid/2, lasti*(fontheight()+Vspacing)+fontheight()/2));
    r = raddp(r, m->xy);
    pt = Pt(0, 0);
    if(r.max.x>screen.r.max.x)
        pt.x = screen.r.max.x-r.max.x;
    if(r.max.y>screen.r.max.y)
        pt.y = screen.r.max.y-r.max.y;
    if(r.min.x<screen.r.min.x)
        pt.x = screen.r.min.x-r.min.x;
    if(r.min.y<screen.r.min.y)
        pt.y = screen.r.min.y-r.min.y;
    menur = raddp(r, pt);
    textr.max.x = menur.max.x-Margin;
    textr.min.x = textr.max.x-maxwid;
    textr.min.y = menur.min.y+Margin;
    textr.max.y = textr.min.y + nitemdrawn*(fontheight()+Vspacing);
    if(scrolling){
        scrollr = inset(menur, Border);
        scrollr.max.x = scrollr.min.x+Scrollwid;
    }else
        scrollr = Rect(0, 0, 0, 0);

    b = balloc(menur, screen.ldepth);
    if(b == 0)
        b = &screen;
    bitblt(b, menur.min, &screen, menur, S);
    bitblt(&screen, menur.min, &screen, menur, 0);
    border(&screen, menur, Blackborder, F, _bgpixel);
    r = menurect(textr, lasti);
    cursorset(divpt(add(r.min, r.max), 2));
    menupaint(menu, textr, off, nitemdrawn);
    if(scrolling)
        menuscrollpaint(scrollr, off, nitem, nitemdrawn);
    r = menurect(textr, lasti);
    cursorset(divpt(add(r.min, r.max), 2));
    menupaint(menu, textr, off, nitemdrawn);
    if(scrolling)
        menuscrollpaint(scrollr, off, nitem, nitemdrawn);
    while(m->buttons & (1<<(but-1))){
        lasti = menuscan(but, m, textr, lasti);
        if(lasti >= 0)
            break;
        while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){
            if(scrolling && ptinrect(m->xy, scrollr)){
                noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scrollr);
                noff -= nitemdrawn/2;
                if(noff < 0)
                    noff = 0;
                if(noff > nitem-nitemdrawn)
                    noff = nitem-nitemdrawn;
                if(noff != off){
                    off = noff;
                    menupaint(menu, textr, off, nitemdrawn);
                    menuscrollpaint(scrollr, off, nitem, nitemdrawn);
                }
            }
            *m = emouse();
        }
    }
    bitblt(&screen, menur.min, b, menur, S);
    if(b != &screen)
        bfree(b);
    clipr(&screen, sc);
    if(lasti >= 0){
        menu->lasthit = lasti+off;
        return cursorswitch(oldcursor), menu->lasthit;
    }
    cursorswitch(oldcursor);
    return -1;
}
Ejemplo n.º 29
0
static void
remote_send_cb(EV_P_ ev_io *w, int revents)
{
    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;
    remote_t *remote              = remote_send_ctx->remote;
    server_t *server              = remote->server;

    if (!remote_send_ctx->connected) {
        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;
        int r         = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_stop(EV_A_ & server->recv_ctx->io);
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);
            ev_timer_start(EV_A_ & remote->recv_ctx->watcher);

            // send destaddr
            buffer_t ss_addr_to_send;
            buffer_t *abuf = &ss_addr_to_send;
            balloc(abuf, BUF_SIZE);

            if (server->hostname_len > 0) { // HTTP/SNI
                uint16_t port;
                if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                    port = (((struct sockaddr_in6 *)&(server->destaddr))->sin6_port);
                } else {                             // IPv4
                    port = (((struct sockaddr_in *)&(server->destaddr))->sin_port);
                }

                abuf->array[abuf->len++] = 3;          // Type 3 is hostname
                abuf->array[abuf->len++] = server->hostname_len;
                memcpy(abuf->array + abuf->len, server->hostname, server->hostname_len);
                abuf->len += server->hostname_len;
                memcpy(abuf->array + abuf->len, &port, 2);
            } else if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                abuf->array[abuf->len++] = 4;          // Type 4 is IPv6 address

                size_t in6_addr_len = sizeof(struct in6_addr);
                memcpy(abuf->array + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),
                       in6_addr_len);
                abuf->len += in6_addr_len;
                memcpy(abuf->array + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),
                       2);
            } else {                             // IPv4
                abuf->array[abuf->len++] = 1; // Type 1 is IPv4 address

                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(abuf->array + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len);
                abuf->len += in_addr_len;
                memcpy(abuf->array + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2);
            }

            abuf->len += 2;

            if (auth) {
                abuf->array[0] |= ONETIMEAUTH_FLAG;
                ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE);
            }

            brealloc(remote->buf, remote->buf->len + abuf->len, BUF_SIZE);
            memmove(remote->buf->array + abuf->len, remote->buf->array, remote->buf->len);
            memcpy(remote->buf->array, abuf->array, abuf->len);
            remote->buf->len += abuf->len;
            bfree(abuf);

            int err = ss_encrypt(remote->buf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            ev_io_start(EV_A_ & remote->recv_ctx->io);
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    if (remote->buf->len == 0) {
        // close and free
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else {
        // has data to send
        ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
                         remote->buf->len, 0);
        if (s == -1) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                ERROR("send");
                // close and free
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }
            return;
        } else if (s < remote->buf->len) {
            // partly sent, move memory, wait for the next time to send
            remote->buf->len -= s;
            remote->buf->idx += s;
            return;
        } else {
            // all sent out, wait for reading
            remote->buf->len = 0;
            remote->buf->idx = 0;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);
        }
    }
}
static void * usb_alloc(int size)
{
	void *tmp =  balloc(size, NULL);
	track_address(tmp);
	return tmp;
}