summaryrefslogtreecommitdiff
path: root/source4/winbind
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2005-09-25 21:01:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:38:54 -0500
commit9593101ec118dd242bf25fabf3e17c58269e632c (patch)
treec06ef0370effd18294efff90624a177dae059bb7 /source4/winbind
parent06085e7bc09e46c74fbe050633203fab619d501c (diff)
downloadsamba-9593101ec118dd242bf25fabf3e17c58269e632c.tar.gz
samba-9593101ec118dd242bf25fabf3e17c58269e632c.tar.bz2
samba-9593101ec118dd242bf25fabf3e17c58269e632c.zip
r10491: First step towards wbinfo -t: This issues a name request for the primary
domain and gets the DC's name via a mailslot call. Metze, I renamed wbsrv_queue_reply to wbsrv_send_reply in accordance with irpc_send_reply. Having _queue_ here and _send_ there is a bit confusing. And as everything is async anyway, the semantics should not be too much of a problem. Volker (This used to be commit 4637964b19c6e9f7d201b287e2d409d029fced01)
Diffstat (limited to 'source4/winbind')
-rw-r--r--source4/winbind/config.mk3
-rw-r--r--source4/winbind/wb_async_helpers.c206
-rw-r--r--source4/winbind/wb_async_helpers.h36
-rw-r--r--source4/winbind/wb_samba3_cmd.c64
-rw-r--r--source4/winbind/wb_samba3_protocol.c3
-rw-r--r--source4/winbind/wb_server.c4
-rw-r--r--source4/winbind/wb_server.h21
7 files changed, 324 insertions, 13 deletions
diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk
index dea0782575..5f055768c0 100644
--- a/source4/winbind/config.mk
+++ b/source4/winbind/config.mk
@@ -8,7 +8,8 @@ SUBSYSTEM = SERVER_SERVICE
INIT_OBJ_FILES = \
winbind/wb_server.o \
winbind/wb_samba3_protocol.o \
- winbind/wb_samba3_cmd.o
+ winbind/wb_samba3_cmd.o \
+ winbind/wb_async_helpers.o
REQUIRED_SUBSYSTEMS =
# End MODULE server_service_winbind
################################################
diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c
new file mode 100644
index 0000000000..17efd06c81
--- /dev/null
+++ b/source4/winbind/wb_async_helpers.c
@@ -0,0 +1,206 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Volker Lendecke 2005
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+/*
+ a composite API for finding a DC and its name
+*/
+
+#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_async_helpers.h"
+
+#include "librpc/gen_ndr/nbt.h"
+#include "librpc/gen_ndr/samr.h"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/irpc.h"
+#include "librpc/gen_ndr/ndr_irpc.h"
+
+struct finddcs_state {
+ struct wb_finddcs *io;
+ struct composite_context *creq;
+
+ struct nbtd_getdcname *r;
+ struct irpc_request *ireq;
+};
+
+static void finddcs_getdc(struct irpc_request *req)
+{
+ struct composite_context *c = talloc_get_type(req->async.private,
+ struct composite_context);
+ struct finddcs_state *state =
+ talloc_get_type(c->private, struct finddcs_state);
+
+ c->status = irpc_call_recv(req);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ goto done;
+ }
+
+ state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs,
+ state->r->out.dcname);
+
+ c->status = NT_STATUS_OK;
+ c->state = SMBCLI_REQUEST_DONE;
+
+ done:
+ if (!NT_STATUS_IS_OK(c->status)) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ }
+
+ if (c->state >= SMBCLI_REQUEST_DONE &&
+ c->async.fn) {
+ c->async.fn(c);
+ }
+}
+
+/*
+ called when name resolution is finished
+*/
+static void finddcs_resolve(struct composite_context *res_ctx)
+{
+ struct composite_context *c = talloc_get_type(res_ctx->async.private,
+ struct composite_context);
+ struct finddcs_state *state =
+ talloc_get_type(c->private, struct finddcs_state);
+ uint32_t *nbt_servers;
+
+ state->io->out.num_dcs = 1;
+ state->io->out.dcs = talloc_array(state, struct nbt_dc_name,
+ state->io->out.num_dcs);
+ if (state->io->out.dcs == NULL) {
+ c->status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ c->status = resolve_name_recv(res_ctx, state->io->out.dcs,
+ &state->io->out.dcs[0].address);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ goto done;
+ }
+
+ nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server");
+ if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
+ c->status = NT_STATUS_NO_LOGON_SERVERS;
+ goto done;
+ }
+
+ state->r = talloc(state, struct nbtd_getdcname);
+ if (state->r == NULL) {
+ c->status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ state->r->in.domainname = talloc_strdup(state->r, lp_workgroup());
+ state->r->in.ip_address = state->io->out.dcs[0].address;
+ state->r->in.my_computername = lp_netbios_name();
+ state->r->in.my_accountname = talloc_asprintf(state->r, "%s$",
+ lp_netbios_name());
+ state->r->in.account_control = ACB_WSTRUST;
+ state->r->in.domain_sid = secrets_get_domain_sid(state->r,
+ lp_workgroup());
+
+ if ((state->r->in.domainname == NULL) ||
+ (state->r->in.my_accountname == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ c->status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ if (state->r->in.domain_sid == NULL) {
+ c->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto done;
+ }
+
+ state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0],
+ &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
+ state->r, state);
+
+ if (state->ireq == NULL) {
+ c->status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ c->status = NT_STATUS_OK;
+ state->ireq->async.fn = finddcs_getdc;
+ state->ireq->async.private = c;
+
+ done:
+ if (!NT_STATUS_IS_OK(c->status)) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ }
+
+ if (c->state >= SMBCLI_REQUEST_DONE &&
+ c->async.fn) {
+ c->async.fn(c);
+ }
+}
+
+struct composite_context *wb_finddcs_send(struct wb_finddcs *io,
+ struct event_context *event_ctx)
+{
+ struct composite_context *c;
+ struct finddcs_state *state;
+ struct nbt_name name;
+
+ c = talloc_zero(NULL, struct composite_context);
+ if (c == NULL) goto failed;
+ c->state = SMBCLI_REQUEST_SEND;
+ c->event_ctx = event_ctx;
+
+ state = talloc(c, struct finddcs_state);
+ if (state == NULL) goto failed;
+
+ state->io = io;
+
+ make_nbt_name(&name, io->in.domain, 0x1c);
+ state->creq = resolve_name_send(&name, c->event_ctx,
+ lp_name_resolve_order());
+
+ if (state->creq == NULL) goto failed;
+ state->creq->async.private = c;
+ state->creq->async.fn = finddcs_resolve;
+ c->private = state;
+
+ return c;
+failed:
+ talloc_free(c);
+ return NULL;
+}
+
+NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+
+ status = composite_wait(c);
+
+ if (NT_STATUS_IS_OK(status)) {
+ struct finddcs_state *state =
+ talloc_get_type(c->private, struct finddcs_state);
+ talloc_steal(mem_ctx, state->io->out.dcs);
+ }
+
+ talloc_free(c);
+ return status;
+}
+
+NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx,
+ struct event_context *ev)
+{
+ struct composite_context *c = wb_finddcs_send(io, ev);
+ return wb_finddcs_recv(c, mem_ctx);
+}
diff --git a/source4/winbind/wb_async_helpers.h b/source4/winbind/wb_async_helpers.h
new file mode 100644
index 0000000000..6c4f1d84a8
--- /dev/null
+++ b/source4/winbind/wb_async_helpers.h
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ SMB composite request interfaces
+
+ Copyright (C) Volker Lendecke 2005
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+struct wb_finddcs {
+ struct {
+ struct messaging_context *msg_ctx;
+ const char *domain;
+ } in;
+
+ struct {
+ int num_dcs;
+ struct nbt_dc_name {
+ const char *address;
+ const char *name;
+ } *dcs;
+ } out;
+};
diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c
index 14e9ac9e6d..4ff54e25b4 100644
--- a/source4/winbind/wb_samba3_cmd.c
+++ b/source4/winbind/wb_samba3_cmd.c
@@ -26,6 +26,10 @@
#include "nsswitch/winbindd_nss.h"
#include "winbind/wb_server.h"
#include "winbind/wb_samba3_protocol.h"
+#include "winbind/wb_async_helpers.h"
+#include "librpc/gen_ndr/nbt.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
{
@@ -48,3 +52,63 @@ NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
s3call->response.result = WINBINDD_OK;
return NT_STATUS_OK;
}
+
+struct check_machacc_state {
+ struct wb_finddcs *io;
+};
+
+static void wbsrv_samba3_check_machacc_reply(struct composite_context *action)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(action->async.private,
+ struct wbsrv_samba3_call);
+ struct check_machacc_state *state =
+ talloc_get_type(s3call->private_data,
+ struct check_machacc_state);
+ NTSTATUS status;
+
+ status = wb_finddcs_recv(action, s3call);
+ if (NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("Got name %s\n", state->io->out.dcs[0].name));
+ s3call->response.result = WINBINDD_OK;
+ } else {
+ DEBUG(10, ("Got no addr: %s\n", nt_errstr(status)));
+ s3call->response.result = WINBINDD_ERROR;
+ }
+
+ status = wbsrv_send_reply(s3call->call);
+ if (!NT_STATUS_IS_OK(status)) {
+ wbsrv_terminate_connection(s3call->call->wbconn,
+ "wbsrv_queue_reply() failed");
+ return;
+ }
+}
+
+NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
+{
+ struct composite_context *resolve_req;
+ struct check_machacc_state *state;
+
+ DEBUG(5, ("check_machacc called\n"));
+
+ state = talloc(s3call, struct check_machacc_state);
+ NT_STATUS_HAVE_NO_MEMORY(state);
+
+ state->io = talloc(s3call, struct wb_finddcs);
+ NT_STATUS_HAVE_NO_MEMORY(state->io);
+ s3call->private_data = state;
+
+ state->io->in.msg_ctx = s3call->call->wbconn->conn->msg_ctx;
+ state->io->in.domain = lp_workgroup();
+
+ resolve_req = wb_finddcs_send(state->io, s3call->call->event_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(resolve_req);
+
+ /* setup the callbacks */
+ resolve_req->async.fn = wbsrv_samba3_check_machacc_reply;
+ resolve_req->async.private = s3call;
+
+ /* tell the caller we reply later */
+ s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
+ return NT_STATUS_OK;
+}
diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c
index a5ad66ae16..4519f89540 100644
--- a/source4/winbind/wb_samba3_protocol.c
+++ b/source4/winbind/wb_samba3_protocol.c
@@ -77,6 +77,9 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_call *call)
case WINBINDD_PING:
return wbsrv_samba3_ping(s3call);
+
+ case WINBINDD_CHECK_MACHACC:
+ return wbsrv_samba3_check_machacc(s3call);
}
s3call->response.result = WINBINDD_ERROR;
diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c
index d8d8f19465..e18ea16662 100644
--- a/source4/winbind/wb_server.c
+++ b/source4/winbind/wb_server.c
@@ -149,7 +149,7 @@ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
* and queue the reply, this implies talloc_free(call),
* and set the socket to readable again
*/
- status = wbsrv_queue_reply(call);
+ status = wbsrv_send_reply(call);
if (!NT_STATUS_IS_OK(status)) goto failed;
return;
@@ -170,7 +170,7 @@ failed:
* return;
* to drop the connection
*/
-NTSTATUS wbsrv_queue_reply(struct wbsrv_call *call)
+NTSTATUS wbsrv_send_reply(struct wbsrv_call *call)
{
struct wbsrv_connection *wbconn = call->wbconn;
const struct wbsrv_protocol_ops *ops = wbconn->listen_socket->ops;
diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h
index 2c93c02323..0c00394f7d 100644
--- a/source4/winbind/wb_server.h
+++ b/source4/winbind/wb_server.h
@@ -91,16 +91,17 @@ struct wbsrv_connection {
NOTE about async replies:
if the backend wants to reply later:
- - it should set the WBSRV_CALL_FLAGS_REPLY_ASYNC flag, and may set a talloc_destructor
- on the this structure or on the private_data (if it's a talloc child of this structure),
- so that wbsrv_terminate_connection called by another call clean up the whole connection
- correct.
- - When the backend is ready to reply it should call wbsrv_queue_reply(call),
- wbsrv_queue_reply implies talloc_free(call), so the backend should use talloc_reference(call),
- if it needs it later.
- - If wbsrv_queue_reply doesn't return NT_STATUS_OK, the backend function should call,
- wbsrv_terminate_connection(call->wbconn, nt_errstr(status));
- return;
+
+ - it should set the WBSRV_CALL_FLAGS_REPLY_ASYNC flag, and may set a
+ talloc_destructor on the this structure or on the private_data (if it's a
+ talloc child of this structure), so that wbsrv_terminate_connection
+ called by another call clean up the whole connection correct.
+ - When the backend is ready to reply it should call wbsrv_send_reply(call),
+ wbsrv_send_reply implies talloc_free(call), so the backend should use
+ talloc_reference(call), if it needs it later.
+ - If wbsrv_send_reply doesn't return NT_STATUS_OK, the backend function
+ should call, wbsrv_terminate_connection(call->wbconn, nt_errstr(status));
+ return;
*/
struct wbsrv_call {