From 9a1ceab6d60549f3c983dd1cf1f9a9ea2ba5dc79 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 20 Sep 2005 20:54:25 +0000 Subject: r10363: Nobody loudly screamed "noo", so commit the samba3 winbind interface to samba4. Ok, maybe the silence is due to timezones, but what can you do... ;-) Volker (This used to be commit 9a5d8f55ab2841572b94fbc3a86a47f65a7d74a6) --- source4/winbind/wb_server.c | 190 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 3 deletions(-) (limited to 'source4/winbind/wb_server.c') diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c index e35651c6e5..0bea86f38e 100644 --- a/source4/winbind/wb_server.c +++ b/source4/winbind/wb_server.c @@ -28,12 +28,14 @@ #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 @@ -126,13 +128,184 @@ static void winbind_send(struct stream_connection *conn, uint16_t flags) EVENT_FD_NOT_WRITEABLE(conn->event.fde); } -static const struct stream_server_ops winbind_stream_ops = { +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"); + return; + } + + wbconn->request = NULL; + wbconn->response = NULL; + ZERO_STRUCT(wbconn->partial); + conn->private = wbconn; +} + +static void winbind_samba3_recv(struct stream_connection *conn, uint16_t flags) +{ + 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"); + 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"); + return; + } + + wbconn->partial.length += received; + + if (wbconn->partial.length < sizeof(struct winbindd_request)) { + 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"); + 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); +} + +static void winbind_samba3_send(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; + } + + talloc_free(wbconn->response); + wbconn->response = NULL; + wbconn->partial.data = NULL; + EVENT_FD_NOT_WRITEABLE(conn->event.fde); + EVENT_FD_READABLE(conn->event.fde); +} + +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, +}; + /* startup the winbind task */ @@ -156,7 +329,7 @@ static void winbind_task_init(struct task_server *task) mkdir(WINBINDD_DIR, 0755); } - status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops, + 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", @@ -165,9 +338,20 @@ static void winbind_task_init(struct task_server *task) 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"); + return; + } + port = WINBINDD_ECHO_PORT; - status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops, + 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", -- cgit