Beispiel #1
0
int connection_proxy_req_parse(Connection *conn)
{
    int rc = 0;
    Host *target_host = conn->req->target_host;
    Backend *req_action = conn->req->action;

    check_debug(!IOBuf_closed(conn->iob), "Client closed, goodbye.");

    rc = Connection_read_header(conn, conn->req);

    check_debug(rc > 0, "Failed to read another header.");
    error_unless(Request_is_http(conn->req), conn, 400,
            "Someone tried to change the protocol on us from HTTP.");

    Backend *found = Host_match_backend(target_host, Request_path(conn->req), NULL);
    error_unless(found, conn, 404, 
            "Handler not found: %s", bdata(Request_path(conn->req)));

    // break out of PROXY if the actions don't match
    if(found != req_action) {
        Request_set_action(conn->req, found);
        return Connection_backend_event(found, conn);
    } else {
        return HTTP_REQ;
    }

    error_response(conn, 500, "Invalid code branch, tell Zed.");
error:
    return REMOTE_CLOSE;
}
Beispiel #2
0
int connection_msg_to_handler(Connection *conn)
{
    Handler *handler = Request_get_action(conn->req, handler);
    int rc = 0;
    int header_len = Request_header_length(conn->req);
    // body_len will include \0
    int body_len = Request_content_length(conn->req);

    check(handler, "JSON request doesn't match any handler: %s", 
            bdata(Request_path(conn->req)));

    if(pattern_match(IOBuf_start(conn->iob), header_len + body_len, bdata(&PING_PATTERN))) {
        Register_ping(IOBuf_fd(conn->iob));
    } else {
        check(body_len >= 0, "Parsing error, body length ended up being: %d", body_len);

        bstring payload = Request_to_payload(conn->req, handler->send_ident,
                IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                body_len - 1);  // drop \0 on payloads


        rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
        bdestroy(payload);
    
        check(rc == 0, "Failed to deliver to handler: %s", bdata(Request_path(conn->req)));
    }

    // consumes \0 from body_len
    IOBuf_read_commit(conn->iob, header_len + body_len);

    return REQ_SENT;

error:
    return CLOSE;
}
Beispiel #3
0
int connection_route_request(Connection *conn)
{
    Host *host = NULL;
    Route *route = NULL;

    bstring path = Request_path(conn->req);

    if(conn->req->host_name) {
        host = Server_match_backend(conn->server, conn->req->host_name);
    } else {
        host = conn->server->default_host;
    }

    error_unless(host, conn, 404, "Request for a host we don't have registered: %s", bdata(conn->req->host_name));

    Backend *found = Host_match_backend(host, path, &route);
    error_unless(found, conn, 404, "Handler not found: %s", bdata(path));

    Request_set_action(conn->req, found);

    conn->req->target_host = host;
    conn->req->pattern = route->pattern;
    conn->req->prefix = route->prefix;

    return Connection_backend_event(found, conn);

error:
    return CLOSE;
}
Beispiel #4
0
int connection_route_request(Connection *conn)
{
    Host *host = NULL;
    Route *route = NULL;

    bstring path = Request_path(conn->req);
    check_debug(path != NULL, "No path given, in request, ignoring.");

    Server *server = Server_queue_latest();
    check(server != NULL, "No server in the server queue, tell Zed.");

    if(conn->req->host_name) {
        host = Server_match_backend(server, conn->req->host_name);
    } else {
        host = server->default_host;
    }

    error_unless(host, conn, 404, "Request for a host we don't have registered: %s", bdata(conn->req->host_name));

    Backend *found = Host_match_backend(host, path, &route);
    error_unless(found, conn, 404, "Handler not found: %s", bdata(path));

    Request_set_action(conn->req, found);

    conn->req->target_host = host;
    conn->req->pattern = route->pattern;
    conn->req->prefix = route->prefix;

    return Connection_backend_event(found, conn);

error:
    return CLOSE;
}
Beispiel #5
0
int connection_msg_to_handler(Connection *conn)
{
    Handler *handler = Request_get_action(conn->req, handler);
    int rc = 0;
    int header_len = Request_header_length(conn->req);
    // body_len will include \0
    int body_len = Request_content_length(conn->req);

    check(handler, "JSON request doesn't match any handler: %s", 
            bdata(Request_path(conn->req)));

    if(pattern_match(IOBuf_start(conn->iob), header_len + body_len, bdata(&PING_PATTERN))) {
        Register_ping(IOBuf_fd(conn->iob));
    } else {
        check(body_len >= 0, "Parsing error, body length ended up being: %d", body_len);
        bstring payload = NULL;

        if(handler->protocol == HANDLER_PROTO_TNET) {
            payload = Request_to_tnetstring(conn->req, handler->send_ident,
                    IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                    body_len - 1);  // drop \0 on payloads
        } else if(handler->protocol == HANDLER_PROTO_JSON) {
            payload = Request_to_payload(conn->req, handler->send_ident,
                    IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                    body_len - 1);  // drop \0 on payloads
        } else {
            sentinel("Invalid protocol type: %d", handler->protocol);
        }

        debug("SENT: %s", bdata(payload));
        check(payload != NULL, "Failed to generate payload.");
        check(handler->send_socket != NULL, "Handler socket is NULL, tell Zed.");

        rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
        free(payload);
    
        check(rc == 0, "Failed to deliver to handler: %s", bdata(Request_path(conn->req)));
    }

    // consumes \0 from body_len
    check(IOBuf_read_commit(conn->iob, header_len + body_len) != -1, "Final commit failed.");

    return REQ_SENT;

error:
    return CLOSE;
}
Beispiel #6
0
int connection_identify_request(Connection *conn)
{
    int next = CLOSE;

    if(Request_is_xml(conn->req)) {
        if(biseq(Request_path(conn->req), &POLICY_XML_REQUEST)) {
            debug("XML POLICY CONNECTION: %s", bdata(Request_path(conn->req)));
            conn->type = CONN_TYPE_SOCKET;
            taskname("XML");
            next = SOCKET_REQ;
        } else {
            debug("XML MESSAGE");
            conn->type = CONN_TYPE_MSG;
            taskname("MSG");
            next = MSG_REQ;
        }
    } else if(Request_is_json(conn->req)) {
        debug("JSON SOCKET MESSAGE");
        conn->type = CONN_TYPE_MSG;
        taskname("MSG");
        next = MSG_REQ;
    } else if(Request_is_websocket(conn->req)) {
        debug("WEBSOCKET MESSAGE");
        conn->type = CONN_TYPE_SOCKET;
        taskname("WS");
        next = WS_REQ;
    } else if(Request_is_http(conn->req)) {
        debug("HTTP MESSAGE");
        conn->type = CONN_TYPE_HTTP;
        taskname("HTTP");
        next = HTTP_REQ;
    } else {
        error_response(conn, 500, "Invalid code branch, tell Zed.");
    }

    return next;

error:
    return CLOSE;

}
Beispiel #7
0
int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len)
{
    int rc = 0;
    bstring payload = NULL;

    if(conn->iob->use_ssl)
	Connection_fingerprint_from_cert(conn);

    error_unless(handler->running, conn, 404,
            "Handler shutdown while trying to deliver: %s", bdata(Request_path(conn->req)));

    if(handler->protocol == HANDLER_PROTO_TNET) {
        payload = Request_to_tnetstring(conn->req, handler->send_ident, 
                IOBuf_fd(conn->iob), body, content_len);
    } else if(handler->protocol == HANDLER_PROTO_JSON) {
        payload = Request_to_payload(conn->req, handler->send_ident, 
                IOBuf_fd(conn->iob), body, content_len);
    } else {
        sentinel("Invalid protocol type: %d", handler->protocol);
    }

    check(payload, "Failed to create payload for request.");
    debug("HTTP TO HANDLER: %.*s", blength(payload) - content_len, bdata(payload));

    rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
    free(payload); payload = NULL;

    error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s", 
            bdata(Request_path(conn->req)));

    return 0;

error:
    if(payload) free(payload);
    return -1;
}
Beispiel #8
0
static inline bstring make_log_message(Request *req, const char *remote_addr,
        int remote_port, int status, int size)
{
    bstring request_method = NULL;

    if (Request_is_json(req)) {
        request_method = &JSON_METHOD;
    } else if (Request_is_xml(req)) {
        request_method = &XML_METHOD;
    } else {
        request_method = req->request_method;
    }

    tns_outbuf outbuf = {.buffer = NULL};
    bstring b_temp;

    check(tns_render_log_start(&outbuf), "Could not initialize buffer");

    tns_render_number_prepend(&outbuf, size);
    tns_render_number_prepend(&outbuf, status);

    b_temp = bfromcstr(Request_is_json(req) ? "" : bdata(req->version));
    tns_render_string_prepend(&outbuf, b_temp);
    bdestroy(b_temp);

    tns_render_string_prepend(&outbuf, Request_path(req));
    tns_render_string_prepend(&outbuf, request_method);
    tns_render_number_prepend(&outbuf, (int) time(NULL));
    tns_render_number_prepend(&outbuf, remote_port);

    b_temp = bfromcstr(remote_addr);
    tns_render_string_prepend(&outbuf, b_temp);
    bdestroy(b_temp);

    tns_render_string_prepend(&outbuf, req->target_host->name);

    tns_render_log_end(&outbuf);

    // log_data now owns the outbuf buffer
    bstring log_data = tns_outbuf_to_bstring(&outbuf);
    bconchar(log_data, '\n');

    return log_data;

error:

    return NULL;
}
Beispiel #9
0
int Dir_serve_file(Dir *dir, Request *req, Connection *conn)
{
    FileRecord *file = NULL;
    bstring resp = NULL;
    bstring path = Request_path(req);
    bstring pattern = req->pattern;
    int rc = 0;
    int is_get = biseq(req->request_method, &HTTP_GET);
    int is_head = is_get ? 0 : biseq(req->request_method, &HTTP_HEAD);

    check(path, "Request had not path. That's weird.");
    req->response_size = 0;

    if(!(is_get || is_head)) {
        req->status_code = 405;
        rc = Response_send_status(conn, &HTTP_405);
        check_debug(rc == blength(&HTTP_405), "Failed to send 405 to client.");
        return -1;
    } else {
        file = Dir_resolve_file(dir, pattern, path);
        resp = Dir_calculate_response(req, file);

        if(resp) {
            rc = Response_send_status(conn, resp);
            check_debug(rc == blength(resp), "Failed to send error response on file serving.");
        } else if(is_get) {
            rc = Dir_stream_file(file, conn);
            req->response_size = rc;
            check_debug(rc == file->sb.st_size, "Didn't send all of the file, sent %d of %s.", rc, bdata(path));
        } else if(is_head) {
            rc = Dir_send_header(file, conn);
            check_debug(rc, "Failed to write header to socket.");
        } else {
            sentinel("How the hell did you get to here. Tell Zed.");
        }

        FileRecord_release(file);
        return 0;
    }

    sentinel("Invalid code branch, Tell Zed you have magic.");
error:
    FileRecord_release(file);
    return -1;
}
Beispiel #10
0
int connection_http_to_handler(Connection *conn)
{
    int content_len = Request_content_length(conn->req);
    int rc = 0;
    char *body = NULL;

    Handler *handler = Request_get_action(conn->req, handler);
    error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req)));

    // we don't need the header anymore, so commit the buffer and deal with the body
    IOBuf_read_commit(conn->iob, Request_header_length(conn->req));

    if(content_len == 0) {
        body = "";
        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    } else if(content_len > MAX_CONTENT_LENGTH) {
        rc = Upload_file(conn, handler, content_len);
        check(rc == 0, "Failed to upload file.");
    } else {
        if(content_len > conn->iob->len) {
            // temporarily grow the buffer
            IOBuf_resize(conn->iob, content_len);
        }

        debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH);

        body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES);
        check(body != NULL, "Client closed the connection during upload.");

        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    }

    Log_request(conn, 200, content_len);

    return REQ_SENT;

error:
    return CLOSE;
}
Beispiel #11
0
int connection_http_to_directory(Connection *conn)
{
    Dir *dir = Request_get_action(conn->req, dir);

    int rc = Dir_serve_file(dir, conn->req, conn);
    check_debug(rc == 0, "Failed to serve file: %s", bdata(Request_path(conn->req)));

    IOBuf_read_commit(conn->iob,
            Request_header_length(conn->req) + Request_content_length(conn->req));

    Log_request(conn, conn->req->status_code, conn->req->response_size);

    if(conn->close) {
        return CLOSE;
    } else {
        return RESP_SENT;
    }

error:
    return CLOSE;
}
Beispiel #12
0
int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len)
{
    int rc = 0;
    bstring result = NULL;

    result = Request_to_payload(conn->req, handler->send_ident, 
            IOBuf_fd(conn->iob), body, content_len);
    check(result, "Failed to create payload for request.");

    debug("HTTP TO HANDLER: %.*s", blength(result) - content_len, bdata(result));

    rc = Handler_deliver(handler->send_socket, bdata(result), blength(result));
    error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s", 
            bdata(Request_path(conn->req)));

    bdestroy(result);
    return 0;

error:
    bdestroy(result);
    return -1;
}
Beispiel #13
0
static inline int ident_and_register(Connection *conn, int reg_too)
{
    int next = CLOSE;

    if(Request_is_xml(conn->req)) {
        if(biseq(Request_path(conn->req), &POLICY_XML_REQUEST)) {
            debug("XML POLICY CONNECTION");
            conn->type = CONN_TYPE_SOCKET;
            taskname("XML");
            next = SOCKET_REQ;
        } else {
            debug("XML MESSAGE");
            conn->type = CONN_TYPE_MSG;
            taskname("MSG");
            next = MSG_REQ;
        }
    } else if(Request_is_json(conn->req)) {
        debug("JSON SOCKET MESSAGE");
        conn->type = CONN_TYPE_MSG;
        taskname("MSG");
        next = MSG_REQ;
    } else if(Request_is_http(conn->req)) {
        debug("HTTP MESSAGE");
        conn->type = CONN_TYPE_HTTP;
        taskname("HTTP");
        next = HTTP_REQ;
    } else {
        error_response(conn, 500, "Invalid code branch, tell Zed.");
    }

    if(reg_too) Register_connect(IOBuf_fd(conn->iob), (void*)conn);
    return next;

error:
    return CLOSE;

}
Beispiel #14
0
int connection_http_to_handler(Connection *conn)
{
    int content_len = Request_content_length(conn->req);
    int rc = 0;
    char *body = NULL;

    Handler *handler = Request_get_action(conn->req, handler);
    error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req)));

    bstring expects = Request_get(conn->req, &HTTP_EXPECT);

    if (expects != NULL) {
        if (biseqcstr(expects, "100-continue")) {
            Response_send_status(conn, &HTTP_100);
        } else {
            Response_send_status(conn, &HTTP_417);
            log_info("Client requested unsupported expectation: %s.", bdata(expects));
            goto error;
        }
    }

    // we don't need the header anymore, so commit the buffer and deal with the body
    check(IOBuf_read_commit(conn->iob, Request_header_length(conn->req)) != -1, "Finaly commit failed streaming the connection to http handlers.");

    if(is_websocket(conn)) {
        bstring wsKey = Request_get(conn->req, &WS_SEC_WS_KEY);
        bstring response= websocket_challenge(wsKey);
        conn->handler = handler;

        //Response_send_status(conn,response);
        bdestroy(conn->req->request_method);
        conn->req->request_method=bfromcstr("WEBSOCKET_HANDSHAKE");
        Connection_send_to_handler(conn, handler, bdata(response), blength(response));
        bdestroy(response);

        bdestroy(conn->req->request_method);
        conn->req->request_method=bfromcstr("WEBSOCKET");
        return REQ_SENT;
    }

    if(content_len == 0) {
        body = "";
        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    } else if(content_len > MAX_CONTENT_LENGTH) {
        rc = Upload_file(conn, handler, content_len);
        check(rc == 0, "Failed to upload file.");
    } else {
        debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH);

        body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES);
        check(body != NULL, "Client closed the connection during upload.");

        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    }

    Log_request(conn, 200, content_len);

    return REQ_SENT;

error:
    return CLOSE;
}