s4-secrets: fetch secure channel type with domain SID
[kamenim/samba.git] / source4 / winbind / wb_server.c
index 0bea86f38e6ad863951b08134fdb9811a4cc6668..96dab0acd525438c5d0d2c5057a56ce242147571 100644 (file)
@@ -2,12 +2,13 @@
    Unix SMB/CIFS implementation.
    Main winbindd server routines
 
-   Copyright (C) Stefan Metzmacher     2005
+   Copyright (C) Stefan Metzmacher     2005-2008
    Copyright (C) Andrew Tridgell       2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "lib/socket/socket.h"
-#include "system/dir.h"
-#include "system/filesys.h"
-#include "dlinklist.h"
-#include "lib/events/events.h"
-#include "smbd/service_task.h"
-#include "smbd/service_stream.h"
-#include "winbind/winbindd_nss.h"
-
-#define WINBINDD_DIR "/tmp/.winbindd/"
-#define WINBINDD_ECHO_SOCKET  WINBINDD_DIR"echo"
-#define WINBINDD_ADDR_PREFIX "127.0.255."
-#define WINBINDD_ECHO_ADDR WINBINDD_ADDR_PREFIX"1"
-#define WINBINDD_ECHO_PORT 55555
-#define WINBINDD_SAMBA3_SOCKET WINBINDD_DIR"pipe"
-
-/*
-  state of an open winbind connection
-*/
-struct wbserver_connection {
-       DATA_BLOB input;
-       struct data_blob_list_item *send_queue;
-};
-
-
-/*
-  called when we get a new connection
-*/
-static void winbind_accept(struct stream_connection *conn)
+#include "smbd/process_model.h"
+#include "winbind/wb_server.h"
+#include "lib/stream/packet.h"
+#include "lib/tsocket/tsocket.h"
+#include "libcli/util/tstream.h"
+#include "param/param.h"
+#include "param/secrets.h"
+
+void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *reason)
 {
-       struct wbserver_connection *wbconn;
-
-       wbconn = talloc_zero(conn, struct wbserver_connection);
-       wbconn->input = data_blob_talloc(wbconn, NULL, 1024);
-       
-       conn->private = wbconn;
+       stream_terminate_connection(wbconn->conn, reason);
 }
 
-/*
-  receive some data on a winbind connection
-*/
-static void winbind_recv(struct stream_connection *conn, uint16_t flags)
+static void wbsrv_call_loop(struct tevent_req *subreq)
 {
-       struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
+       struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq,
+                                     struct wbsrv_connection);
+       struct wbsrv_samba3_call *call;
        NTSTATUS status;
-       size_t nread;
-       struct data_blob_list_item *q;
 
-       status = socket_recv(conn->socket, wbconn->input.data, wbconn->input.length, &nread, 0);
-       if (NT_STATUS_IS_ERR(status)) {
-               DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
-               stream_terminate_connection(conn, "socket_recv: failed\n");
+       call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call);
+       if (call == NULL) {
+               wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
+                               "no memory for wbsrv_samba3_call");
                return;
        }
+       call->wbconn = wbsrv_conn;
 
-       /* just reflect the data back down the socket */
-       q = talloc(wbconn, struct data_blob_list_item);
-       if (q == NULL) {
-               stream_terminate_connection(conn, "winbind_recv: out of memory\n");
-               return;
-       }
+       status = tstream_read_pdu_blob_recv(subreq,
+                                           call,
+                                           &call->in);
+       TALLOC_FREE(subreq);
+       if (!NT_STATUS_IS_OK(status)) {
+               const char *reason;
+
+               reason = talloc_asprintf(call, "wbsrv_call_loop: "
+                                        "tstream_read_pdu_blob_recv() - %s",
+                                        nt_errstr(status));
+               if (!reason) {
+                       reason = nt_errstr(status);
+               }
 
-       q->blob = data_blob_talloc(q, wbconn->input.data, nread);
-       if (q->blob.data == NULL) {
-               stream_terminate_connection(conn, "winbind_recv: out of memory\n");
+               wbsrv_terminate_connection(wbsrv_conn, reason);
                return;
        }
 
-       DLIST_ADD_END(wbconn->send_queue, q, struct data_blob_list_item *);
+       DEBUG(10,("Received winbind TCP packet of length %lu from %s\n",
+                (long) call->in.length,
+                tsocket_address_string(wbsrv_conn->conn->remote_address, call)));
 
-       EVENT_FD_WRITEABLE(conn->event.fde);
-}
-
-/*
-  called when we can write to a connection
-*/
-static void winbind_send(struct stream_connection *conn, uint16_t flags)
-{
-       struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
-
-       while (wbconn->send_queue) {
-               struct data_blob_list_item *q = wbconn->send_queue;
-               NTSTATUS status;
-               size_t sendlen;
+       status = wbsrv_samba3_process(call);
+       if (!NT_STATUS_IS_OK(status)) {
+               const char *reason;
 
-               status = socket_send(conn->socket, &q->blob, &sendlen, 0);
-               if (NT_STATUS_IS_ERR(status)) {
-                       DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
-                       stream_terminate_connection(conn, "socket_send: failed\n");
-                       return;
+               reason = talloc_asprintf(call, "wbsrv_call_loop: "
+                                        "tstream_read_pdu_blob_recv() - %s",
+                                        nt_errstr(status));
+               if (!reason) {
+                       reason = nt_errstr(status);
                }
-               if (!NT_STATUS_IS_OK(status)) {
-                       return;
-               }
-
-               q->blob.length -= sendlen;
-               q->blob.data   += sendlen;
 
-               if (q->blob.length == 0) {
-                       DLIST_REMOVE(wbconn->send_queue, q);
-                       talloc_free(q);
-               }
+               wbsrv_terminate_connection(wbsrv_conn, reason);
+               return;
        }
 
-       EVENT_FD_NOT_WRITEABLE(conn->event.fde);
-}
-
-static const struct stream_server_ops winbind_echo_ops = {
-       .name                   = "winbind_echo",
-       .accept_connection      = winbind_accept,
-       .recv_handler           = winbind_recv,
-       .send_handler           = winbind_send,
-};
-
-struct winbind3_connection {
-       struct winbindd_request *request;
-       struct winbindd_response *response;
-       DATA_BLOB partial;
-       size_t nsent;
-};
-
-static void winbind_samba3_accept(struct stream_connection *conn)
-{
-       struct winbind3_connection *wbconn;
-
-       wbconn = talloc(conn, struct winbind3_connection);
-       if (wbconn == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               stream_terminate_connection(conn, "talloc failed");
+       /*
+        * The winbind pdu's has the length as 4 byte (initial_read_size),
+        * wbsrv_samba3_packet_full_request provides the pdu length then.
+        */
+       subreq = tstream_read_pdu_blob_send(wbsrv_conn,
+                                           wbsrv_conn->conn->event.ctx,
+                                           wbsrv_conn->tstream,
+                                           4, /* initial_read_size */
+                                           wbsrv_samba3_packet_full_request,
+                                           wbsrv_conn);
+       if (subreq == NULL) {
+               wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
+                               "no memory for tstream_read_pdu_blob_send");
                return;
        }
-
-       wbconn->request = NULL;
-       wbconn->response = NULL;
-       ZERO_STRUCT(wbconn->partial);
-       conn->private = wbconn;
+       tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
 }
 
-static void winbind_samba3_recv(struct stream_connection *conn, uint16_t flags)
+static void wbsrv_accept(struct stream_connection *conn)
 {
-       struct winbind3_connection *wbconn =
-               talloc_get_type(conn->private, struct winbind3_connection);
-       size_t npending, received;
-       NTSTATUS res;
-
-       if (!NT_STATUS_IS_OK(socket_pending(conn->socket, &npending))) {
-               stream_terminate_connection(conn, "socket_pending() failed");
-               return;
-       }
-
-       if (npending == 0) {
-               stream_terminate_connection(conn, "EOF from client");
-               return;
-       }
-
-       if (wbconn->partial.length + npending >
-           sizeof(struct winbindd_request)) {
-               npending = sizeof(struct winbindd_request) -
-                       wbconn->partial.length;
-       }
-
-       wbconn->partial.data =
-               talloc_realloc_size(wbconn, wbconn->partial.data,
-                                   wbconn->partial.length + npending);
-       if (wbconn->partial.data == NULL) {
-               stream_terminate_connection(conn, "talloc_realloc failed");
+       struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data,
+                                                                  struct wbsrv_listen_socket);
+       struct wbsrv_connection *wbsrv_conn;
+       struct tevent_req *subreq;
+       int rc;
+
+       wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
+       if (wbsrv_conn == NULL) {
+               stream_terminate_connection(conn, "wbsrv_accept: out of memory");
                return;
        }
 
-       res = socket_recv(conn->socket,
-                         &wbconn->partial.data[wbconn->partial.length],
-                         npending, &received, 0);
-
-       if (!NT_STATUS_IS_OK(res)) {
-               DEBUG(5, ("sock_recv failed: %s\n", nt_errstr(res)));
-               stream_terminate_connection(conn, "talloc_realloc failed");
+       wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept");
+       if (wbsrv_conn->send_queue == NULL) {
+               stream_terminate_connection(conn,
+                               "wbsrv_accept: out of memory");
                return;
        }
 
-       wbconn->partial.length += received;
+       TALLOC_FREE(conn->event.fde);
 
-       if (wbconn->partial.length < sizeof(struct winbindd_request)) {
+       rc = tstream_bsd_existing_socket(wbsrv_conn,
+                       socket_get_fd(conn->socket),
+                       &wbsrv_conn->tstream);
+       if (rc < 0) {
+               stream_terminate_connection(conn,
+                               "wbsrv_accept: out of memory");
                return;
        }
 
-       wbconn->request = (struct winbindd_request *)wbconn->partial.data;
-
-       SMB_ASSERT(wbconn->response == NULL);
-
-       wbconn->response = talloc_zero(wbconn, struct winbindd_response);
-       if (wbconn->response == NULL) {
-               stream_terminate_connection(conn, "talloc_zero failed");
+       wbsrv_conn->conn = conn;
+       wbsrv_conn->listen_socket = wbsrv_socket;
+       wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx;
+       conn->private_data = wbsrv_conn;
+
+       /*
+        * The winbind pdu's has the length as 4 byte (initial_read_size),
+        * wbsrv_samba3_packet_full_request provides the pdu length then.
+        */
+       subreq = tstream_read_pdu_blob_send(wbsrv_conn,
+                                           wbsrv_conn->conn->event.ctx,
+                                           wbsrv_conn->tstream,
+                                           4, /* initial_read_size */
+                                           wbsrv_samba3_packet_full_request,
+                                           wbsrv_conn);
+       if (subreq == NULL) {
+               wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: "
+                               "no memory for tstream_read_pdu_blob_send");
                return;
        }
-
-       wbconn->response->length = sizeof(struct winbindd_response);
-       wbconn->response->result = WINBINDD_ERROR;
-
-       if (wbconn->request->length != sizeof(struct winbindd_request)) {
-               DEBUG(10, ("Got invalid request length %d\n",
-                          wbconn->request->length));
-               goto done;
-       }
-
-       DEBUG(10, ("Got winbind request %d\n", wbconn->request->cmd));
-
-       switch(wbconn->request->cmd) {
-       case WINBINDD_INTERFACE_VERSION:
-               wbconn->response->result = WINBINDD_OK;
-               wbconn->response->data.interface_version =
-                       WINBIND_INTERFACE_VERSION;
-               break;
-       case WINBINDD_PRIV_PIPE_DIR:
-               wbconn->response->result = WINBINDD_OK;
-               wbconn->response->extra_data =
-                       smbd_tmp_path(wbconn->response, "winbind_priv/pipe");
-               if (wbconn->response->extra_data == NULL) {
-                       stream_terminate_connection(conn,
-                                                   "smbd_tmp_path failed");
-                       return;
-               }
-               wbconn->response->length +=
-                       strlen(wbconn->response->extra_data) + 1;
-               break;
-       case WINBINDD_PING:
-               wbconn->response->result = WINBINDD_OK;
-               break;
-       default:
-               break;
-       }
-
- done:
-       talloc_free(wbconn->partial.data);
-       wbconn->partial.data = NULL;
-       wbconn->nsent = 0;
-
-       wbconn->partial.data = (char *)wbconn->response;
-       wbconn->partial.length = sizeof(struct winbindd_response);
-
-       EVENT_FD_NOT_READABLE(conn->event.fde);
-       EVENT_FD_WRITEABLE(conn->event.fde);
+       tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
 }
 
-static void winbind_samba3_send(struct stream_connection *conn, uint16_t flags)
+/*
+  called on a tcp recv
+*/
+static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
 {
-       struct winbind3_connection *wbconn =
-               talloc_get_type(conn->private, struct winbind3_connection);
-       size_t nsent;
-       NTSTATUS res;
-
-       res = socket_send(conn->socket, &wbconn->partial, &nsent, 0);
-       if (!NT_STATUS_IS_OK(res)) {
-               stream_terminate_connection(conn, "socket_send() failed");
-               return;
-       }
-
-       wbconn->partial.data += nsent;
-       wbconn->partial.length -= nsent;
-
-       if (wbconn->partial.length != 0) {
-               return;
-       }
-
-       if (wbconn->response->extra_data != NULL) {
-               wbconn->partial.data = wbconn->response->extra_data;
-               wbconn->partial.length = wbconn->response->length -
-                       sizeof(struct winbindd_response);
-               wbconn->response->extra_data = NULL;
-               return;
-       }
+       struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
+                                                       struct wbsrv_connection);
+       wbsrv_terminate_connection(wbsrv_conn, "wbsrv_recv: called");
+}
 
-       talloc_free(wbconn->response);
-       wbconn->response = NULL;
-       wbconn->partial.data = NULL;
-       EVENT_FD_NOT_WRITEABLE(conn->event.fde);
-       EVENT_FD_READABLE(conn->event.fde);
+/*
+  called when we can write to a connection
+*/
+static void wbsrv_send(struct stream_connection *conn, uint16_t flags)
+{
+       struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
+                                                       struct wbsrv_connection);
+       /* this should never be triggered! */
+       wbsrv_terminate_connection(wbsrv_conn, "wbsrv_send: called");
 }
 
-static const struct stream_server_ops winbind_samba3_ops = {
-       .name                   = "winbind_samba3",
-       .accept_connection      = winbind_samba3_accept,
-       .recv_handler           = winbind_samba3_recv,
-       .send_handler           = winbind_samba3_send,
+static const struct stream_server_ops wbsrv_ops = {
+       .name                   = "winbind samba3 protocol",
+       .accept_connection      = wbsrv_accept,
+       .recv_handler           = wbsrv_recv,
+       .send_handler           = wbsrv_send
 };
 
 /*
@@ -314,59 +195,155 @@ static void winbind_task_init(struct task_server *task)
        uint16_t port = 1;
        const struct model_ops *model_ops;
        NTSTATUS status;
+       struct wbsrv_service *service;
+       struct wbsrv_listen_socket *listen_socket;
+       char *errstring;
+       struct dom_sid *primary_sid;
+
+       task_server_set_title(task, "task[winbind]");
 
        /* within the winbind task we want to be a single process, so
           ask for the single process model ops and pass these to the
           stream_setup_socket() call. */
-       model_ops = process_model_byname("single");
+       model_ops = process_model_startup(task->event_ctx, "single");
        if (!model_ops) {
-               task_server_terminate(task, "Can't find 'single' process model_ops");
+               task_server_terminate(task,
+                                     "Can't find 'single' process model_ops", true);
                return;
        }
 
-       /* Make sure the directory for NCALRPC exists */
-       if (!directory_exist(WINBINDD_DIR)) {
-               mkdir(WINBINDD_DIR, 0755);
-       }
-
-       status = stream_setup_socket(task->event_ctx, model_ops, &winbind_echo_ops, 
-                                    "unix", WINBINDD_ECHO_SOCKET, &port, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
-                        WINBINDD_ECHO_SOCKET, nt_errstr(status)));
-               task_server_terminate(task, "winbind Failed to find to ECHO unix socket");
+       /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
+       if (!directory_create_or_exist(lpcfg_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
+               task_server_terminate(task,
+                                     "Cannot create winbindd pipe directory", true);
                return;
        }
 
-       status = stream_setup_socket(task->event_ctx, model_ops,
-                                    &winbind_samba3_ops, "unix",
-                                    WINBINDD_SAMBA3_SOCKET, &port, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
-                        WINBINDD_ECHO_SOCKET, nt_errstr(status)));
-               task_server_terminate(task, "winbind Failed to find to "
-                                     "SAMBA3 unix socket");
+       /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
+       if (!directory_create_or_exist(lpcfg_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750)) {
+               task_server_terminate(task,
+                                     "Cannot create winbindd privileged pipe directory", true);
                return;
        }
 
-       port = WINBINDD_ECHO_PORT;
+       service = talloc_zero(task, struct wbsrv_service);
+       if (!service) goto nomem;
+       service->task   = task;
+
+
+       /* Find the primary SID, depending if we are a standalone
+        * server (what good is winbind in this case, but anyway...),
+        * or are in a domain as a member or a DC */
+       switch (lpcfg_server_role(service->task->lp_ctx)) {
+       case ROLE_STANDALONE:
+               primary_sid = secrets_get_domain_sid(service,
+                                                    service->task->event_ctx,
+                                                    service->task->lp_ctx,
+                                                    lpcfg_netbios_name(service->task->lp_ctx),
+                                                    &service->sec_channel_type,
+                                                    &errstring);
+               if (!primary_sid) {
+                       char *message = talloc_asprintf(task, 
+                                                       "Cannot start Winbind (standalone configuration): %s: "
+                                                       "Have you provisioned this server (%s) or changed it's name?", 
+                                                       errstring, lpcfg_netbios_name(service->task->lp_ctx));
+                       task_server_terminate(task, message, true);
+                       return;
+               }
+               break;
+       case ROLE_DOMAIN_MEMBER:
+               primary_sid = secrets_get_domain_sid(service,
+                                                    service->task->event_ctx,
+                                                    service->task->lp_ctx,
+                                                    lpcfg_workgroup(service->task->lp_ctx),
+                                                    &service->sec_channel_type,
+                                                    &errstring);
+               if (!primary_sid) {
+                       char *message = talloc_asprintf(task, "Cannot start Winbind (domain member): %s: "
+                                                       "Have you joined the %s domain?", 
+                                                       errstring, lpcfg_workgroup(service->task->lp_ctx));
+                       task_server_terminate(task, message, true);
+                       return;
+               }
+               break;
+       case ROLE_DOMAIN_CONTROLLER:
+               primary_sid = secrets_get_domain_sid(service,
+                                                    service->task->event_ctx,
+                                                    service->task->lp_ctx,
+                                                    lpcfg_workgroup(service->task->lp_ctx),
+                                                    &service->sec_channel_type,
+                                                    &errstring);
+               if (!primary_sid) {
+                       char *message = talloc_asprintf(task, "Cannot start Winbind (domain controller): %s: "
+                                                       "Have you provisioned the %s domain?", 
+                                                       errstring, lpcfg_workgroup(service->task->lp_ctx));
+                       task_server_terminate(task, message, true);
+                       return;
+               }
+               break;
+       }
+       service->primary_sid = primary_sid;
 
-       status = stream_setup_socket(task->event_ctx, model_ops, &winbind_echo_ops,
-                                    "ipv4", WINBINDD_ECHO_ADDR, &port, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
-                        WINBINDD_ECHO_ADDR, port, nt_errstr(status)));
-               task_server_terminate(task, "winbind Failed to find to ECHO tcp socket");
+       service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx);
+       if (service->idmap_ctx == NULL) {
+               task_server_terminate(task, "Failed to load idmap database", true);
                return;
        }
-}
 
-/*
-  initialise the winbind server
- */
-static NTSTATUS winbind_init(struct event_context *event_ctx, const struct model_ops *model_ops)
-{
-       return task_server_startup(event_ctx, model_ops, winbind_task_init);
+       service->priv_pipe_dir = lpcfg_winbindd_privileged_socket_directory(task->lp_ctx);
+       service->pipe_dir = lpcfg_winbindd_socket_directory(task->lp_ctx);
+
+       /* setup the unprivileged samba3 socket */
+       listen_socket = talloc(service, struct wbsrv_listen_socket);
+       if (!listen_socket) goto nomem;
+       listen_socket->socket_path      = talloc_asprintf(listen_socket, "%s/%s", 
+                                                         service->pipe_dir, 
+                                                         WINBINDD_SOCKET_NAME);
+       if (!listen_socket->socket_path) goto nomem;
+       listen_socket->service          = service;
+       listen_socket->privileged       = false;
+       status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
+                                    &wbsrv_ops, "unix",
+                                    listen_socket->socket_path, &port,
+                                    lpcfg_socket_options(task->lp_ctx),
+                                    listen_socket);
+       if (!NT_STATUS_IS_OK(status)) goto listen_failed;
+
+       /* setup the privileged samba3 socket */
+       listen_socket = talloc(service, struct wbsrv_listen_socket);
+       if (!listen_socket) goto nomem;
+       listen_socket->socket_path 
+               = talloc_asprintf(listen_socket, "%s/%s", 
+                                 service->priv_pipe_dir,
+                                 WINBINDD_SOCKET_NAME);
+       if (!listen_socket->socket_path) goto nomem;
+       listen_socket->service          = service;
+       listen_socket->privileged       = true;
+       status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
+                                    &wbsrv_ops, "unix",
+                                    listen_socket->socket_path, &port,
+                                    lpcfg_socket_options(task->lp_ctx),
+                                    listen_socket);
+       if (!NT_STATUS_IS_OK(status)) goto listen_failed;
+
+       status = wbsrv_init_irpc(service);
+       if (!NT_STATUS_IS_OK(status)) goto irpc_failed;
+
+       return;
+
+listen_failed:
+       DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n",
+                listen_socket->socket_path, nt_errstr(status)));
+       task_server_terminate(task, nt_errstr(status), true);
+       return;
+irpc_failed:
+       DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
+                nt_errstr(status)));
+       task_server_terminate(task, nt_errstr(status), true);
+       return;
+nomem:
+       task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true);
+       return;
 }
 
 /*
@@ -374,5 +351,5 @@ static NTSTATUS winbind_init(struct event_context *event_ctx, const struct model
 */
 NTSTATUS server_service_winbind_init(void)
 {
-       return register_server_service("winbind", winbind_init);
+       return register_server_service("winbind", winbind_task_init);
 }