summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2006-07-31 15:38:18 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:15:17 -0500
commite48ed74f4a2fe490d70c444dca3aa9419409579f (patch)
tree5dd259e04d4c6e1b3ea8f825923320994e57ffc9
parent7a845bcb0141a895d5685afcef1ffe7f93428d0f (diff)
downloadsamba-e48ed74f4a2fe490d70c444dca3aa9419409579f.tar.gz
samba-e48ed74f4a2fe490d70c444dca3aa9419409579f.tar.bz2
samba-e48ed74f4a2fe490d70c444dca3aa9419409579f.zip
r17342: implement a SamLogon via IRPC in samba4's winbind
metze (This used to be commit c3ce7a0c3708f0c8e784404e86034f7a00685f88)
-rw-r--r--source4/librpc/config.mk7
-rw-r--r--source4/librpc/idl/netlogon.idl4
-rw-r--r--source4/librpc/idl/winbind.idl40
-rw-r--r--source4/winbind/config.mk13
-rw-r--r--source4/winbind/wb_irpc.c86
-rw-r--r--source4/winbind/wb_sam_logon.c168
-rw-r--r--source4/winbind/wb_server.c8
-rw-r--r--source4/winbind/wb_server.h1
8 files changed, 322 insertions, 5 deletions
diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk
index 9e920b9d39..353c58644c 100644
--- a/source4/librpc/config.mk
+++ b/source4/librpc/config.mk
@@ -329,6 +329,13 @@ SO_VERSION = 0
OBJ_FILES = gen_ndr/ndr_winsrepl.o
PUBLIC_DEPENDENCIES = LIBNDR NDR_NBT
+[LIBRARY::NDR_WINBIND]
+VERSION = 0.0.1
+SO_VERSION = 0
+OBJ_FILES = gen_ndr/ndr_winbind.o
+PUBLIC_HEADERS = gen_ndr/winbind.h
+PUBLIC_DEPENDENCIES = LIBNDR NDR_NETLOGON
+
librpc/gen_ndr/tables.c: $(IDL_NDR_PARSE_H_FILES)
@echo Generating librpc/gen_ndr/tables.c
@$(PERL) $(srcdir)/librpc/tables.pl --output=librpc/gen_ndr/tables.c $(IDL_NDR_PARSE_H_FILES) > librpc/gen_ndr/tables.x
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 95289b7ea9..533095eea6 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -118,7 +118,7 @@ interface netlogon
netr_ChallengeResponse lm;
} netr_NetworkInfo;
- typedef [switch_type(uint16)] union {
+ typedef [public,switch_type(uint16)] union {
[case(1)] netr_PasswordInfo *password;
[case(2)] netr_NetworkInfo *network;
[case(3)] netr_PasswordInfo *password;
@@ -221,7 +221,7 @@ interface netlogon
lsa_String unknown4;
} netr_PacInfo;
- typedef [switch_type(uint16)] union {
+ typedef [public,switch_type(uint16)] union {
[case(2)] netr_SamInfo2 *sam2;
[case(3)] netr_SamInfo3 *sam3;
[case(4)] netr_PacInfo *pac;
diff --git a/source4/librpc/idl/winbind.idl b/source4/librpc/idl/winbind.idl
new file mode 100644
index 0000000000..c3f54e0132
--- /dev/null
+++ b/source4/librpc/idl/winbind.idl
@@ -0,0 +1,40 @@
+/*
+ winbind IRPC interface
+*/
+
+#include "idl_types.h"
+
+[
+ uuid("245f3e6b-3c5d-6e21-3a2d-2a3d645b7221"),
+ version(1.0),
+ pointer_default(unique),
+ pointer_default_top(unique),
+ depends(netlogon)
+]
+
+interface winbind
+{
+ declare [switch_type(uint16)] union netr_LogonLevel;
+ declare [switch_type(uint16)] union netr_Validation;
+
+ /* a call to get runtime informations */
+ void winbind_information(/* TODO */);
+
+ /*
+ * a call to trigger some internal events,
+ * for use in torture tests...
+ */
+ NTSTATUS winbind_remote_control(/* TODO */);
+
+ /*
+ * do a netr_LogonSamLogon() against the right DC
+ */
+ NTSTATUS winbind_SamLogon(
+ [in] uint16 logon_level,
+ [in] [switch_is(logon_level)] netr_LogonLevel logon,
+ [in] uint16 validation_level,
+ [out] [switch_is(validation_level)] netr_Validation validation,
+ [out] uint8 authoritative,
+ [in,out] uint32 flags
+ );
+}
diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk
index 26807de86c..3ecf489a93 100644
--- a/source4/winbind/config.mk
+++ b/source4/winbind/config.mk
@@ -8,6 +8,7 @@ SUBSYSTEM = service
PRIVATE_PROTO_HEADER = wb_proto.h
OBJ_FILES = \
wb_server.o \
+ wb_irpc.o \
wb_samba3_protocol.o \
wb_samba3_cmd.o \
wb_init_domain.o \
@@ -22,9 +23,15 @@ OBJ_FILES = \
wb_cmd_userdomgroups.o \
wb_cmd_usersids.o \
wb_cmd_list_trustdom.o \
- wb_pam_auth.o
-PUBLIC_DEPENDENCIES = WB_HELPER RPC_NDR_LSA RPC_NDR_SAMR process_model \
- PAM_ERRORS
+ wb_pam_auth.o \
+ wb_sam_logon.o
+PUBLIC_DEPENDENCIES = \
+ WB_HELPER \
+ NDR_WINBIND \
+ process_model \
+ RPC_NDR_LSA \
+ RPC_NDR_SAMR \
+ PAM_ERRORS
# End SUBSYSTEM WINBIND
#######################
diff --git a/source4/winbind/wb_irpc.c b/source4/winbind/wb_irpc.c
new file mode 100644
index 0000000000..b81948a21d
--- /dev/null
+++ b/source4/winbind/wb_irpc.c
@@ -0,0 +1,86 @@
+/*
+ Unix SMB/CIFS implementation.
+ Main winbindd irpc handlers
+
+ Copyright (C) Stefan Metzmacher 2006
+
+ 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.
+*/
+
+#include "includes.h"
+#include "winbind/wb_server.h"
+#include "lib/messaging/irpc.h"
+#include "libcli/composite/composite.h"
+#include "librpc/gen_ndr/ndr_winbind.h"
+#include "smbd/service_task.h"
+
+struct wb_irpc_SamLogon_state {
+ struct irpc_message *msg;
+ struct winbind_SamLogon *req;
+};
+
+static void wb_irpc_SamLogon_callback(struct composite_context *ctx);
+
+static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg,
+ struct winbind_SamLogon *req)
+{
+ struct wbsrv_service *service = talloc_get_type(msg->private,
+ struct wbsrv_service);
+ struct wb_irpc_SamLogon_state *s;
+ struct composite_context *ctx;
+
+ DEBUG(5, ("wb_irpc_SamLogon called\n"));
+
+ s = talloc(msg, struct wb_irpc_SamLogon_state);
+ NT_STATUS_HAVE_NO_MEMORY(s);
+
+ s->msg = msg;
+ s->req = req;
+
+ ctx = wb_sam_logon_send(msg, service, req);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = wb_irpc_SamLogon_callback;
+ ctx->async.private_data = s;
+
+ msg->defer_reply = True;
+ return NT_STATUS_OK;
+}
+
+static void wb_irpc_SamLogon_callback(struct composite_context *ctx)
+{
+ struct wb_irpc_SamLogon_state *s = talloc_get_type(ctx->async.private_data,
+ struct wb_irpc_SamLogon_state);
+ NTSTATUS status;
+
+ DEBUG(5, ("wb_irpc_SamLogon_callback called\n"));
+
+ status = wb_sam_logon_recv(ctx, s, s->req);
+
+ irpc_send_reply(s->msg, status);
+}
+
+NTSTATUS wbsrv_init_irpc(struct wbsrv_service *service)
+{
+ NTSTATUS status;
+
+ irpc_add_name(service->task->msg_ctx, "winbind_server");
+
+ status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_SAMLOGON,
+ wb_irpc_SamLogon, service);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ return NT_STATUS_OK;
+}
diff --git a/source4/winbind/wb_sam_logon.c b/source4/winbind/wb_sam_logon.c
new file mode 100644
index 0000000000..7906f3f525
--- /dev/null
+++ b/source4/winbind/wb_sam_logon.c
@@ -0,0 +1,168 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Do a netr_LogonSamLogon to a remote DC
+
+ Copyright (C) Volker Lendecke 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ 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.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+#include "libcli/auth/credentials.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/winbind.h"
+
+struct wb_sam_logon_state {
+ struct composite_context *ctx;
+
+ struct winbind_SamLogon *req;
+
+ struct creds_CredentialState *creds_state;
+ struct netr_Authenticator auth1, auth2;
+
+ TALLOC_CTX *r_mem_ctx;
+ struct netr_LogonSamLogon r;
+};
+
+static void wb_sam_logon_recv_domain(struct composite_context *ctx);
+static void wb_sam_logon_recv_samlogon(struct rpc_request *req);
+
+/*
+ Find the connection to the DC (or find an existing connection)
+*/
+struct composite_context *wb_sam_logon_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service,
+ struct winbind_SamLogon *req)
+{
+ struct composite_context *c, *creq;
+ struct wb_sam_logon_state *s;
+
+ c = composite_create(mem_ctx, service->task->event_ctx);
+ if (!c) return NULL;
+
+ s = talloc_zero(c, struct wb_sam_logon_state);
+ if (composite_nomem(s, c)) return c;
+ s->ctx = c;
+ s->req = req;
+
+ c->private_data = s;
+
+ creq = wb_sid2domain_send(s, service, service->primary_sid);
+ composite_continue(c, creq, wb_sam_logon_recv_domain, s);
+ return c;
+}
+
+/*
+ Finish the connection to the DC
+ Send of a SamLogon request to authenticate a user.
+*/
+static void wb_sam_logon_recv_domain(struct composite_context *creq)
+{
+ struct wb_sam_logon_state *s = talloc_get_type(creq->async.private_data,
+ struct wb_sam_logon_state);
+ struct rpc_request *req;
+ struct wbsrv_domain *domain;
+
+ s->ctx->status = wb_sid2domain_recv(creq, &domain);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->creds_state = cli_credentials_get_netlogon_creds(domain->schannel_creds);
+ creds_client_authenticator(s->creds_state, &s->auth1);
+
+ s->r.in.server_name = talloc_asprintf(s, "\\\\%s",
+ dcerpc_server_name(domain->netlogon_pipe));
+ if (composite_nomem(s->r.in.server_name, s->ctx)) return;
+
+ s->r.in.computer_name = cli_credentials_get_workstation(domain->schannel_creds);
+ s->r.in.credential = &s->auth1;
+ s->r.in.return_authenticator = &s->auth2;
+ s->r.in.logon_level = s->req->in.logon_level;
+ s->r.in.logon = s->req->in.logon;
+ s->r.in.validation_level = s->req->in.validation_level;
+ s->r.out.return_authenticator = NULL;
+
+ /*
+ * use a new talloc context for the LogonSamLogon call
+ * because then we can just to a talloc_steal on this context
+ * in the final _recv() function to give the caller all the content of
+ * the s->r.out.validation
+ */
+ s->r_mem_ctx = talloc_new(s);
+ if (composite_nomem(s->r_mem_ctx, s->ctx)) return;
+
+ req = dcerpc_netr_LogonSamLogon_send(domain->netlogon_pipe, s->r_mem_ctx, &s->r);
+ composite_continue_rpc(s->ctx, req, wb_sam_logon_recv_samlogon, s);
+}
+
+/*
+ NTLM Authentication
+
+ Check the SamLogon reply and decrypt the session keys
+*/
+static void wb_sam_logon_recv_samlogon(struct rpc_request *req)
+{
+ struct wb_sam_logon_state *s = talloc_get_type(req->async.private,
+ struct wb_sam_logon_state);
+
+ s->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->ctx->status = s->r.out.result;
+ if (!composite_is_ok(s->ctx)) return;
+
+ if ((s->r.out.return_authenticator == NULL) ||
+ (!creds_client_check(s->creds_state,
+ &s->r.out.return_authenticator->cred))) {
+ DEBUG(0, ("Credentials check failed!\n"));
+ composite_error(s->ctx, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+
+ /* Decrypt the session keys before we reform the info3, so the
+ * person on the other end of winbindd pipe doesn't have to.
+ * They won't have the encryption key anyway */
+ creds_decrypt_samlogon(s->creds_state,
+ s->r.in.validation_level,
+ &s->r.out.validation);
+
+ composite_done(s->ctx);
+}
+
+NTSTATUS wb_sam_logon_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct winbind_SamLogon *req)
+{
+ struct wb_sam_logon_state *s = talloc_get_type(c->private_data,
+ struct wb_sam_logon_state);
+ NTSTATUS status = composite_wait(c);
+
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(mem_ctx, s->r_mem_ctx);
+ req->out.validation = s->r.out.validation;
+ req->out.authoritative = 1;
+ req->out.flags = 0;
+ }
+
+ talloc_free(s);
+ return status;
+}
diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c
index 16663f6161..5588fba0ce 100644
--- a/source4/winbind/wb_server.c
+++ b/source4/winbind/wb_server.c
@@ -177,6 +177,9 @@ static void winbind_task_init(struct task_server *task)
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:
@@ -184,6 +187,11 @@ listen_failed:
listen_socket->socket_path, nt_errstr(status)));
task_server_terminate(task, nt_errstr(status));
return;
+irpc_failed:
+ DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
+ nt_errstr(status)));
+ task_server_terminate(task, nt_errstr(status));
+ return;
nomem:
task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY));
return;
diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h
index 2a2aec20ea..42f11157d2 100644
--- a/source4/winbind/wb_server.h
+++ b/source4/winbind/wb_server.h
@@ -145,6 +145,7 @@ struct wbsrv_samba3_call {
struct netr_LMSessionKey;
struct netr_UserSessionKey;
+struct winbind_SamLogon;
#include "winbind/wb_async_helpers.h"
#include "winbind/wb_proto.h"