s4/web_server: fix panic from wrong type extracted from conn
[sfrench/samba-autobuild/.git] / source4 / web_server / web_server.c
index c43b2cfc7b17a268a8e9d6e86f45e1895eb703b4..9c4da2c23c9f8e008750e0dbf36b54ed82e7ef3d 100644 (file)
@@ -28,7 +28,7 @@
 #include "lib/socket/netif.h"
 #include "param/param.h"
 
-NTSTATUS server_service_web_init(void);
+NTSTATUS server_service_web_init(TALLOC_CTX *);
 
 /* don't allow connections to hang around forever */
 #define HTTP_TIMEOUT 120
@@ -49,7 +49,7 @@ static void websrv_timeout(struct tevent_context *event_context,
                           struct tevent_timer *te, 
                           struct timeval t, void *private_data)
 {
-       struct websrv_context *web = talloc_get_type(private_data, struct websrv_context);
+       struct websrv_context *web = talloc_get_type_abort(private_data, struct websrv_context);
        struct stream_connection *conn = web->conn;
        web->conn = NULL;
        /* TODO: send a message to any running esp context on this connection
@@ -93,11 +93,11 @@ void websrv_output_headers(struct websrv_context *web, const char *status, struc
        data_blob_free(&b);
 }
 
-void websrv_output(struct websrv_context *web, void *data, size_t length)
+void websrv_output(struct websrv_context *web, const void *data, size_t length)
 {
        data_blob_append(web, &web->output.content, data, length);
-       EVENT_FD_NOT_READABLE(web->conn->event.fde);
-       EVENT_FD_WRITEABLE(web->conn->event.fde);
+       TEVENT_FD_NOT_READABLE(web->conn->event.fde);
+       TEVENT_FD_WRITEABLE(web->conn->event.fde);
        web->output.output_pending = true;
 }
 
@@ -142,8 +142,8 @@ NTSTATUS http_parse_header(struct websrv_context *web, const char *line)
 static void websrv_recv(struct stream_connection *conn, uint16_t flags)
 {
        struct web_server_data *wdata;
-       struct websrv_context *web = talloc_get_type(conn->private_data,
-                                                    struct websrv_context);
+       struct websrv_context *web = talloc_get_type_abort(conn->private_data,
+                                                          struct websrv_context);
        NTSTATUS status;
        uint8_t buf[1024];
        size_t nread;
@@ -189,7 +189,7 @@ static void websrv_recv(struct stream_connection *conn, uint16_t flags)
                if (web->input.partial.length > web->input.content_length) {
                        web->input.partial.data[web->input.content_length] = 0;
                }
-               EVENT_FD_NOT_READABLE(web->conn->event.fde);
+               TEVENT_FD_NOT_READABLE(web->conn->event.fde);
 
                /* the reference/unlink code here is quite subtle. It
                 is needed because the rendering of the web-pages, and
@@ -199,7 +199,7 @@ static void websrv_recv(struct stream_connection *conn, uint16_t flags)
                 destroy the stack variables being used by that
                 rendering process when we handle the timeout. */
                if (!talloc_reference(web->task, web)) goto failed;
-               wdata = talloc_get_type(web->task->private_data, struct web_server_data);
+               wdata = talloc_get_type_abort(web->task->private_data, struct web_server_data);
                if (wdata == NULL) goto failed;
                wdata->http_process_input(wdata, web);
                talloc_unlink(web->task, web);
@@ -217,8 +217,8 @@ failed:
 */
 static void websrv_send(struct stream_connection *conn, uint16_t flags)
 {
-       struct websrv_context *web = talloc_get_type(conn->private_data,
-                                                    struct websrv_context);
+       struct websrv_context *web = talloc_get_type_abort(conn->private_data,
+                                                          struct websrv_context);
        NTSTATUS status;
        size_t nsent;
        DATA_BLOB b;
@@ -248,20 +248,19 @@ static void websrv_send(struct stream_connection *conn, uint16_t flags)
 */
 static void websrv_accept(struct stream_connection *conn)
 {
-       struct task_server *task = talloc_get_type(conn->private_data, struct task_server);
-       struct web_server_data *wdata = talloc_get_type(task->private_data, struct web_server_data);
+       struct web_server_data *wdata = talloc_get_type_abort(conn->private_data, struct web_server_data);
        struct websrv_context *web;
        struct socket_context *tls_socket;
 
        web = talloc_zero(conn, struct websrv_context);
        if (web == NULL) goto failed;
 
-       web->task = task;
+       web->task = wdata->task;
        web->conn = conn;
        conn->private_data = web;
        talloc_set_destructor(web, websrv_destructor);
 
-       event_add_timed(conn->event.ctx, web, 
+       tevent_add_timer(conn->event.ctx, web,
                        timeval_current_ofs(HTTP_TIMEOUT, 0),
                        websrv_timeout, web);
 
@@ -298,20 +297,16 @@ static void websrv_task_init(struct task_server *task)
 {
        NTSTATUS status;
        uint16_t port = lpcfg_web_port(task->lp_ctx);
-       const struct model_ops *model_ops;
        struct web_server_data *wdata;
 
        task_server_set_title(task, "task[websrv]");
 
-       /* run the web server as a single process */
-       model_ops = process_model_startup("single");
-       if (!model_ops) goto failed;
-
        /* startup the Python processor - unfortunately we can't do this
           per connection as that wouldn't allow for session variables */
        wdata = talloc_zero(task, struct web_server_data);
        if (wdata == NULL) goto failed;
 
+       wdata->task = task;
        task->private_data = wdata;
 
        if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) {
@@ -319,37 +314,42 @@ static void websrv_task_init(struct task_server *task)
                int i;
                struct interface *ifaces;
 
-               load_interface_list(NULL, lpcfg_interfaces(task->lp_ctx), &ifaces);
+               load_interface_list(NULL, task->lp_ctx, &ifaces);
 
                num_interfaces = iface_list_count(ifaces);
                for(i = 0; i < num_interfaces; i++) {
                        const char *address = iface_list_n_ip(ifaces, i);
                        status = stream_setup_socket(task,
                                                     task->event_ctx,
-                                                    task->lp_ctx, model_ops,
-                                                    &web_stream_ops, 
-                                                    "ipv4", address, 
-                                                    &port, lpcfg_socket_options(task->lp_ctx),
-                                                    task);
+                                                    task->lp_ctx,
+                                                    task->model_ops,
+                                                    &web_stream_ops,
+                                                    "ip", address,
+                                                    &port,
+                                                    lpcfg_socket_options(task->lp_ctx),
+                                                    task,
+                                                    task->process_context);
                        if (!NT_STATUS_IS_OK(status)) goto failed;
                }
 
                talloc_free(ifaces);
        } else {
-               const char **wcard;
+               char **wcard;
                int i;
-               wcard = iface_list_wildcard(task, task->lp_ctx);
+               wcard = iface_list_wildcard(task);
                if (wcard == NULL) {
                        DEBUG(0,("No wildcard addresses available\n"));
                        goto failed;
                }
                for (i=0; wcard[i]; i++) {
                        status = stream_setup_socket(task, task->event_ctx,
-                                                    task->lp_ctx, model_ops,
+                                                    task->lp_ctx,
+                                                    task->model_ops,
                                                     &web_stream_ops,
                                                     "ip", wcard[i],
                                                     &port, lpcfg_socket_options(task->lp_ctx),
-                                                    wdata);
+                                                    wdata,
+                                                    task->process_context);
                        if (!NT_STATUS_IS_OK(status)) goto failed;
                }
                talloc_free(wcard);
@@ -369,7 +369,11 @@ failed:
 
 
 /* called at smbd startup - register ourselves as a server service */
-NTSTATUS server_service_web_init(void)
+NTSTATUS server_service_web_init(TALLOC_CTX *ctx)
 {
-       return register_server_service("web", websrv_task_init);
+       struct service_details details = {
+               .inhibit_fork_on_accept = true,
+               .inhibit_pre_fork = true
+       };
+       return register_server_service(ctx, "web", websrv_task_init, &details);
 }