summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-07-16 11:27:29 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 15:01:08 -0500
commitc86e98aa8070137834f0587b613e215db8802f27 (patch)
tree1782cf9a4d8aefb40bc962adbb337da90b48682e /source4
parent3ccf9ff2ab468d91b9843139df2dfdccbe24c7a1 (diff)
downloadsamba-c86e98aa8070137834f0587b613e215db8802f27.tar.gz
samba-c86e98aa8070137834f0587b613e215db8802f27.tar.bz2
samba-c86e98aa8070137834f0587b613e215db8802f27.zip
r23890: Allow wbinfo -a to work against Samba4's winbind.
Add a test for wbinfo -a to test_member.sh Reimplement the server-side 'pam_auth' and 'pam_auth_crap' calls to use the same SamLogon code as auth_winbind uses. In my previous code, we did not bind to the LSA and SAMR pipes, before attempting operations. We now do this (how we passed any tests before is beyond me). This required some rework, particularly to make it easier to setup secondary connections. The new rpc_secondary_auth_connection() function also performs the bind. The dcerpc_connect.c file was getting to big, so things have been merged into dcerpc_secondary.c. Andrew Bartlett (This used to be commit 365778a993b7d76af6d53ba2a598b7e271741dc5)
Diffstat (limited to 'source4')
-rw-r--r--source4/librpc/config.mk3
-rw-r--r--source4/librpc/rpc/dcerpc_connect.c185
-rw-r--r--source4/librpc/rpc/dcerpc_secondary.c317
-rwxr-xr-xsource4/selftest/test_member.sh1
-rw-r--r--source4/winbind/wb_connect_sam.c10
-rw-r--r--source4/winbind/wb_dom_info.c14
-rw-r--r--source4/winbind/wb_init_domain.c22
-rw-r--r--source4/winbind/wb_pam_auth.c176
8 files changed, 397 insertions, 331 deletions
diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk
index f31ccf57f0..5cec7e1f67 100644
--- a/source4/librpc/config.mk
+++ b/source4/librpc/config.mk
@@ -476,7 +476,8 @@ OBJ_FILES = \
rpc/dcerpc_smb.o \
rpc/dcerpc_smb2.o \
rpc/dcerpc_sock.o \
- rpc/dcerpc_connect.o
+ rpc/dcerpc_connect.o \
+ rpc/dcerpc_secondary.o
PRIVATE_DEPENDENCIES = \
samba-socket LIBCLI_RESOLVE LIBCLI_SMB LIBCLI_SMB2 \
LIBNDR NDR_DCERPC RPC_NDR_EPMAPPER \
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 443b8b458a..3e49e6972b 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -5,7 +5,7 @@
Copyright (C) Andrew Tridgell 2003
Copyright (C) Jelmer Vernooij 2004
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
Copyright (C) Rafal Szczesniak 2005
This program is free software; you can redistribute it and/or modify
@@ -915,186 +915,3 @@ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
}
-
-struct sec_conn_state {
- struct dcerpc_pipe *pipe;
- struct dcerpc_pipe *pipe2;
- struct dcerpc_binding *binding;
- struct smbcli_tree *tree;
-};
-
-
-static void continue_open_smb(struct composite_context *ctx);
-static void continue_open_tcp(struct composite_context *ctx);
-static void continue_open_pipe(struct composite_context *ctx);
-static void continue_pipe_open(struct composite_context *c);
-
-
-/*
- Send request to create a secondary dcerpc connection from a primary
- connection
-*/
-struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
- struct dcerpc_binding *b)
-{
- struct composite_context *c;
- struct sec_conn_state *s;
- struct composite_context *pipe_smb_req;
- struct composite_context *pipe_tcp_req;
- struct composite_context *pipe_ncalrpc_req;
-
- /* composite context allocation and setup */
- c = composite_create(p, p->conn->event_ctx);
- if (c == NULL) return NULL;
-
- s = talloc_zero(c, struct sec_conn_state);
- if (composite_nomem(s, c)) return c;
- c->private_data = s;
-
- s->pipe = p;
- s->binding = b;
-
- /* initialise second dcerpc pipe based on primary pipe's event context */
- s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx);
- if (composite_nomem(s->pipe2, c)) return c;
-
- /* open second dcerpc pipe using the same transport as for primary pipe */
- switch (s->pipe->conn->transport.transport) {
- case NCACN_NP:
- /* get smb tree of primary dcerpc pipe opened on smb */
- s->tree = dcerpc_smb_tree(s->pipe->conn);
- if (!s->tree) {
- composite_error(c, NT_STATUS_INVALID_PARAMETER);
- return c;
- }
-
- pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2, s->tree,
- s->binding->endpoint);
- composite_continue(c, pipe_smb_req, continue_open_smb, c);
- return c;
-
- case NCACN_IP_TCP:
- pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
- s->binding->host,
- s->binding->target_hostname,
- atoi(s->binding->endpoint));
- composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
- return c;
-
- case NCALRPC:
- pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
- s->binding->endpoint);
- composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
- return c;
-
- default:
- /* looks like a transport we don't support */
- composite_error(c, NT_STATUS_NOT_SUPPORTED);
- }
-
- return c;
-}
-
-
-/*
- Stage 2 of secondary_connection: Receive result of pipe open request on smb
-*/
-static void continue_open_smb(struct composite_context *ctx)
-{
- struct composite_context *c = talloc_get_type(ctx->async.private_data,
- struct composite_context);
-
- c->status = dcerpc_pipe_open_smb_recv(ctx);
- if (!composite_is_ok(c)) return;
-
- continue_pipe_open(c);
-}
-
-
-/*
- Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
-*/
-static void continue_open_tcp(struct composite_context *ctx)
-{
- struct composite_context *c = talloc_get_type(ctx->async.private_data,
- struct composite_context);
-
- c->status = dcerpc_pipe_open_tcp_recv(ctx);
- if (!composite_is_ok(c)) return;
-
- continue_pipe_open(c);
-}
-
-
-/*
- Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
-*/
-static void continue_open_pipe(struct composite_context *ctx)
-{
- struct composite_context *c = talloc_get_type(ctx->async.private_data,
- struct composite_context);
-
- c->status = dcerpc_pipe_open_pipe_recv(ctx);
- if (!composite_is_ok(c)) return;
-
- continue_pipe_open(c);
-}
-
-
-/*
- Stage 3 of secondary_connection: Get binding data and flags from primary pipe
- and say if we're done ok.
-*/
-static void continue_pipe_open(struct composite_context *c)
-{
- struct sec_conn_state *s;
-
- s = talloc_get_type(c->private_data, struct sec_conn_state);
-
- s->pipe2->conn->flags = s->pipe->conn->flags;
- s->pipe2->binding = s->binding;
- if (!talloc_reference(s->pipe2, s->binding)) {
- composite_error(c, NT_STATUS_NO_MEMORY);
- return;
- }
-
- composite_done(c);
-}
-
-
-/*
- Receive result of secondary rpc connection request and return
- second dcerpc pipe.
-*/
-NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
- struct dcerpc_pipe **p2)
-{
- NTSTATUS status = composite_wait(c);
- struct sec_conn_state *s;
-
- s = talloc_get_type(c->private_data, struct sec_conn_state);
-
- if (NT_STATUS_IS_OK(status)) {
- *p2 = talloc_steal(s->pipe, s->pipe2);
- }
-
- talloc_free(c);
- return status;
-}
-
-/*
- Create a secondary dcerpc connection from a primary connection
- - sync version
-
- If the primary is a SMB connection then the secondary connection
- will be on the same SMB connection, but using a new fnum
-*/
-NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
- struct dcerpc_pipe **p2,
- struct dcerpc_binding *b)
-{
- struct composite_context *c;
-
- c = dcerpc_secondary_connection_send(p, b);
- return dcerpc_secondary_connection_recv(c, p2);
-}
diff --git a/source4/librpc/rpc/dcerpc_secondary.c b/source4/librpc/rpc/dcerpc_secondary.c
new file mode 100644
index 0000000000..685055d957
--- /dev/null
+++ b/source4/librpc/rpc/dcerpc_secondary.c
@@ -0,0 +1,317 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ dcerpc connect functions
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Jelmer Vernooij 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
+ Copyright (C) Rafal Szczesniak 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "lib/events/events.h"
+#include "librpc/rpc/dcerpc.h"
+#include "auth/credentials/credentials.h"
+
+
+struct sec_conn_state {
+ struct dcerpc_pipe *pipe;
+ struct dcerpc_pipe *pipe2;
+ struct dcerpc_binding *binding;
+ struct smbcli_tree *tree;
+};
+
+
+static void continue_open_smb(struct composite_context *ctx);
+static void continue_open_tcp(struct composite_context *ctx);
+static void continue_open_pipe(struct composite_context *ctx);
+static void continue_pipe_open(struct composite_context *c);
+
+
+/*
+ Send request to create a secondary dcerpc connection from a primary
+ connection
+*/
+struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
+ struct dcerpc_binding *b)
+{
+ struct composite_context *c;
+ struct sec_conn_state *s;
+ struct composite_context *pipe_smb_req;
+ struct composite_context *pipe_tcp_req;
+ struct composite_context *pipe_ncalrpc_req;
+
+ /* composite context allocation and setup */
+ c = composite_create(p, p->conn->event_ctx);
+ if (c == NULL) return NULL;
+
+ s = talloc_zero(c, struct sec_conn_state);
+ if (composite_nomem(s, c)) return c;
+ c->private_data = s;
+
+ s->pipe = p;
+ s->binding = b;
+
+ /* initialise second dcerpc pipe based on primary pipe's event context */
+ s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx);
+ if (composite_nomem(s->pipe2, c)) return c;
+
+ /* open second dcerpc pipe using the same transport as for primary pipe */
+ switch (s->pipe->conn->transport.transport) {
+ case NCACN_NP:
+ /* get smb tree of primary dcerpc pipe opened on smb */
+ s->tree = dcerpc_smb_tree(s->pipe->conn);
+ if (!s->tree) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER);
+ return c;
+ }
+
+ pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2, s->tree,
+ s->binding->endpoint);
+ composite_continue(c, pipe_smb_req, continue_open_smb, c);
+ return c;
+
+ case NCACN_IP_TCP:
+ pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
+ s->binding->host,
+ s->binding->target_hostname,
+ atoi(s->binding->endpoint));
+ composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
+ return c;
+
+ case NCALRPC:
+ pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
+ s->binding->endpoint);
+ composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
+ return c;
+
+ default:
+ /* looks like a transport we don't support */
+ composite_error(c, NT_STATUS_NOT_SUPPORTED);
+ }
+
+ return c;
+}
+
+
+/*
+ Stage 2 of secondary_connection: Receive result of pipe open request on smb
+*/
+static void continue_open_smb(struct composite_context *ctx)
+{
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+
+ c->status = dcerpc_pipe_open_smb_recv(ctx);
+ if (!composite_is_ok(c)) return;
+
+ continue_pipe_open(c);
+}
+
+
+/*
+ Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
+*/
+static void continue_open_tcp(struct composite_context *ctx)
+{
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+
+ c->status = dcerpc_pipe_open_tcp_recv(ctx);
+ if (!composite_is_ok(c)) return;
+
+ continue_pipe_open(c);
+}
+
+
+/*
+ Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
+*/
+static void continue_open_pipe(struct composite_context *ctx)
+{
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+
+ c->status = dcerpc_pipe_open_pipe_recv(ctx);
+ if (!composite_is_ok(c)) return;
+
+ continue_pipe_open(c);
+}
+
+
+/*
+ Stage 3 of secondary_connection: Get binding data and flags from primary pipe
+ and say if we're done ok.
+*/
+static void continue_pipe_open(struct composite_context *c)
+{
+ struct sec_conn_state *s;
+
+ s = talloc_get_type(c->private_data, struct sec_conn_state);
+
+ s->pipe2->conn->flags = s->pipe->conn->flags;
+ s->pipe2->binding = s->binding;
+ if (!talloc_reference(s->pipe2, s->binding)) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ composite_done(c);
+}
+
+
+/*
+ Receive result of secondary rpc connection request and return
+ second dcerpc pipe.
+*/
+NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
+ struct dcerpc_pipe **p2)
+{
+ NTSTATUS status = composite_wait(c);
+ struct sec_conn_state *s;
+
+ s = talloc_get_type(c->private_data, struct sec_conn_state);
+
+ if (NT_STATUS_IS_OK(status)) {
+ *p2 = talloc_steal(s->pipe, s->pipe2);
+ }
+
+ talloc_free(c);
+ return status;
+}
+
+/*
+ Create a secondary dcerpc connection from a primary connection
+ - sync version
+
+ If the primary is a SMB connection then the secondary connection
+ will be on the same SMB connection, but using a new fnum
+*/
+NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
+ struct dcerpc_pipe **p2,
+ struct dcerpc_binding *b)
+{
+ struct composite_context *c;
+
+ c = dcerpc_secondary_connection_send(p, b);
+ return dcerpc_secondary_connection_recv(c, p2);
+}
+
+/*
+ Create a secondary DCERPC connection, then bind (and possibly
+ authenticate) using the supplied credentials.
+
+ This creates a second connection, to the same host (and on ncacn_np on the same connection) as the first
+*/
+struct sec_auth_conn_state {
+ struct dcerpc_pipe *pipe2;
+ struct dcerpc_binding *binding;
+ const struct dcerpc_interface_table *table;
+ struct cli_credentials *credentials;
+ struct composite_context *ctx;
+};
+
+static void dcerpc_secondary_auth_connection_bind(struct composite_context *ctx);
+static void dcerpc_secondary_auth_connection_continue(struct composite_context *ctx);
+
+struct composite_context* dcerpc_secondary_auth_connection_send(struct dcerpc_pipe *p,
+ struct dcerpc_binding *binding,
+ const struct dcerpc_interface_table *table,
+ struct cli_credentials *credentials)
+{
+
+ struct composite_context *c, *secondary_conn_ctx;
+ struct sec_auth_conn_state *s;
+
+ /* composite context allocation and setup */
+ c = composite_create(p, p->conn->event_ctx);
+ if (c == NULL) return NULL;
+
+ s = talloc_zero(c, struct sec_auth_conn_state);
+ if (composite_nomem(s, c)) return c;
+ c->private_data = s;
+ s->ctx = c;
+
+ s->binding = binding;
+ s->table = table;
+ s->credentials = credentials;
+
+ secondary_conn_ctx = dcerpc_secondary_connection_send(p, binding);
+
+ if (composite_nomem(secondary_conn_ctx, s->ctx)) {
+ talloc_free(c);
+ return NULL;
+ }
+
+ composite_continue(s->ctx, secondary_conn_ctx, dcerpc_secondary_auth_connection_bind,
+ s);
+ return c;
+}
+
+/*
+ Stage 2 of secondary_auth_connection:
+ Having made the secondary connection, we will need to do an (authenticated) bind
+*/
+static void dcerpc_secondary_auth_connection_bind(struct composite_context *ctx)
+{
+ struct composite_context *secondary_auth_ctx;
+ struct sec_auth_conn_state *s = talloc_get_type(ctx->async.private_data,
+ struct sec_auth_conn_state);
+
+ s->ctx->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
+ if (!composite_is_ok(s->ctx)) return;
+
+ secondary_auth_ctx = dcerpc_pipe_auth_send(s->pipe2, s->binding, s->table, s->credentials);
+ composite_continue(s->ctx, secondary_auth_ctx, dcerpc_secondary_auth_connection_continue, s);
+
+}
+
+/*
+ Stage 3 of secondary_auth_connection: Receive result of authenticated bind request
+*/
+static void dcerpc_secondary_auth_connection_continue(struct composite_context *ctx)
+{
+ struct sec_auth_conn_state *s = talloc_get_type(ctx->async.private_data,
+ struct sec_auth_conn_state);
+
+ s->ctx->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe2);
+ if (!composite_is_ok(s->ctx)) return;
+
+ composite_done(s->ctx);
+}
+
+/*
+ Receive an authenticated pipe, created as a secondary connection
+*/
+NTSTATUS dcerpc_secondary_auth_connection_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe **p)
+{
+ NTSTATUS status = composite_wait(c);
+ struct sec_auth_conn_state *s;
+
+ s = talloc_get_type(c->private_data, struct sec_auth_conn_state);
+
+ if (NT_STATUS_IS_OK(status)) {
+ *p = talloc_steal(mem_ctx, s->pipe2);
+ }
+
+ talloc_free(c);
+ return status;
+}
diff --git a/source4/selftest/test_member.sh b/source4/selftest/test_member.sh
index a76c10be91..29e3730342 100755
--- a/source4/selftest/test_member.sh
+++ b/source4/selftest/test_member.sh
@@ -5,3 +5,4 @@ incdir=`dirname $0`
plantest "RPC-ECHO against member server with local creds" member $VALGRIND bin/smbtorture $TORTURE_OPTIONS ncacn_np:"\$NETBIOSNAME" -U"\$NETBIOSNAME\\\\\$USERNAME"%"\$PASSWORD" RPC-ECHO "$*"
plantest "RPC-ECHO against member server with domain creds" member $VALGRIND bin/smbtorture $TORTURE_OPTIONS ncacn_np:"\$NETBIOSNAME" -U"\$DOMAIN\\\\\$DC_USERNAME"%"\$DC_PASSWORD" RPC-ECHO "$*"
+plantest "wbinfo -a against member server with domain creds" member $VALGRIND bin/wbinfo -a "\$DOMAIN\\\\\$DC_USERNAME"%"\$DC_PASSWORD" \ No newline at end of file
diff --git a/source4/winbind/wb_connect_sam.c b/source4/winbind/wb_connect_sam.c
index 3ca4734ae9..935ba266d3 100644
--- a/source4/winbind/wb_connect_sam.c
+++ b/source4/winbind/wb_connect_sam.c
@@ -67,8 +67,10 @@ struct composite_context *wb_connect_samr_send(TALLOC_CTX *mem_ctx,
/* this will make the secondary connection on the same IPC$ share,
secured with SPNEGO, NTLMSSP or SCHANNEL */
- ctx = dcerpc_secondary_connection_send(domain->netlogon_pipe,
- domain->samr_binding);
+ ctx = dcerpc_secondary_auth_connection_send(domain->netlogon_pipe,
+ domain->samr_binding,
+ &dcerpc_table_samr,
+ domain->schannel_creds);
composite_continue(state->ctx, ctx, connect_samr_recv_pipe, state);
return result;
@@ -84,8 +86,8 @@ static void connect_samr_recv_pipe(struct composite_context *ctx)
talloc_get_type(ctx->async.private_data,
struct connect_samr_state);
- state->ctx->status = dcerpc_secondary_connection_recv(ctx,
- &state->samr_pipe);
+ state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state,
+ &state->samr_pipe);
if (!composite_is_ok(state->ctx)) return;
state->connect_handle = talloc(state, struct policy_handle);
diff --git a/source4/winbind/wb_dom_info.c b/source4/winbind/wb_dom_info.c
index 571ecb39b2..5ec8f1a159 100644
--- a/source4/winbind/wb_dom_info.c
+++ b/source4/winbind/wb_dom_info.c
@@ -45,7 +45,7 @@ struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct get_dom_info_state *state;
- struct dom_sid *dup_sid;
+ struct dom_sid *dom_sid;
result = composite_create(mem_ctx, service->task->event_ctx);
if (result == NULL) goto failed;
@@ -57,11 +57,17 @@ struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
state->info = talloc_zero(state, struct wb_dom_info);
if (state->info == NULL) goto failed;
- dup_sid = dom_sid_dup(state, sid);
- if (dup_sid == NULL) goto failed;
+ state->info->name = talloc_strdup(state->info, domain_name);
+ if (state->info->name == NULL) goto failed;
+
+ state->info->sid = dom_sid_dup(state->info, sid);
+ if (state->info->sid == NULL) goto failed;
+
+ dom_sid = dom_sid_dup(mem_ctx, sid);
+ if (dom_sid == NULL) goto failed;
ctx = finddcs_send(mem_ctx, domain_name, NBT_NAME_LOGON,
- dup_sid, lp_name_resolve_order(), service->task->event_ctx,
+ dom_sid, lp_name_resolve_order(), service->task->event_ctx,
service->task->msg_ctx);
if (ctx == NULL) goto failed;
diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c
index 69ea9c7533..cdc1491f2b 100644
--- a/source4/winbind/wb_init_domain.c
+++ b/source4/winbind/wb_init_domain.c
@@ -202,7 +202,7 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
talloc_get_type(ctx->async.private_data,
struct init_domain_state);
- state->ctx->status = dcerpc_pipe_connect_b_recv(ctx, state,
+ state->ctx->status = dcerpc_pipe_connect_b_recv(ctx, state->domain,
&state->domain->netlogon_pipe);
if (!composite_is_ok(state->ctx)) {
@@ -224,13 +224,17 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
/* this will make the secondary connection on the same IPC$ share,
secured with SPNEGO or NTLMSSP */
- ctx = dcerpc_secondary_connection_send(state->domain->netlogon_pipe,
- state->domain->lsa_binding);
+ ctx = dcerpc_secondary_auth_connection_send(state->domain->netlogon_pipe,
+ state->domain->lsa_binding,
+ &dcerpc_table_lsarpc,
+ state->domain->schannel_creds
+ );
composite_continue(state->ctx, ctx, init_domain_recv_lsa_pipe, state);
}
static bool retry_with_schannel(struct init_domain_state *state,
struct dcerpc_binding *binding,
+ const struct dcerpc_interface_table *table,
void (*continuation)(struct composite_context *))
{
struct composite_context *ctx;
@@ -246,8 +250,10 @@ static bool retry_with_schannel(struct init_domain_state *state,
/* Try again, likewise on the same IPC$ share,
secured with SCHANNEL */
- ctx = dcerpc_secondary_connection_send(state->domain->netlogon_pipe,
- binding);
+ ctx = dcerpc_secondary_auth_connection_send(state->domain->netlogon_pipe,
+ binding,
+ table,
+ state->domain->schannel_creds);
composite_continue(state->ctx, ctx, continuation, state);
return true;
} else {
@@ -264,10 +270,11 @@ static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
talloc_get_type(ctx->async.private_data,
struct init_domain_state);
- state->ctx->status = dcerpc_secondary_connection_recv(ctx,
- &state->domain->lsa_pipe);
+ state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state->domain,
+ &state->domain->lsa_pipe);
if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_LOGON_FAILURE)) {
if (retry_with_schannel(state, state->domain->lsa_binding,
+ &dcerpc_table_lsarpc,
init_domain_recv_lsa_pipe)) {
return;
}
@@ -307,6 +314,7 @@ static void init_domain_recv_lsa_policy(struct rpc_request *req)
if ((!NT_STATUS_IS_OK(state->ctx->status)
|| !NT_STATUS_IS_OK(state->lsa_openpolicy.out.result))) {
if (retry_with_schannel(state, state->domain->lsa_binding,
+ &dcerpc_table_lsarpc,
init_domain_recv_lsa_pipe)) {
return;
}
diff --git a/source4/winbind/wb_pam_auth.c b/source4/winbind/wb_pam_auth.c
index fffb7c408c..4874254eff 100644
--- a/source4/winbind/wb_pam_auth.c
+++ b/source4/winbind/wb_pam_auth.c
@@ -28,23 +28,22 @@
#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"
/* Oh, there is so much to keep an eye on when authenticating a user. Oh my! */
struct pam_auth_crap_state {
struct composite_context *ctx;
struct event_context *event_ctx;
- uint32_t logon_parameters;
- const char *domain_name;
- const char *user_name;
+
+ struct winbind_SamLogon *req;
char *unix_username;
- const char *workstation;
- DATA_BLOB chal, nt_resp, lm_resp;
- struct creds_CredentialState *creds_state;
- struct netr_Authenticator auth, auth2;
struct netr_NetworkInfo ninfo;
struct netr_LogonSamLogon r;
+ const char *user_name;
+ const char *domain_name;
+
struct netr_UserSessionKey user_session_key;
struct netr_LMSessionKey lm_key;
DATA_BLOB info3;
@@ -54,8 +53,7 @@ struct pam_auth_crap_state {
* NTLM authentication.
*/
-static void pam_auth_crap_recv_domain(struct composite_context *ctx);
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req);
+static void pam_auth_crap_recv_logon(struct composite_context *ctx);
struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
@@ -69,6 +67,8 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct pam_auth_crap_state *state;
+ struct netr_NetworkInfo *ninfo;
+ DATA_BLOB tmp_nt_resp, tmp_lm_resp;
result = composite_create(mem_ctx, service->task->event_ctx);
if (result == NULL) goto failed;
@@ -78,35 +78,43 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
state->ctx = result;
result->private_data = state;
- state->logon_parameters = logon_parameters;
+ state->req = talloc(state, struct winbind_SamLogon);
+
+ state->req->in.logon_level = 2;
+ state->req->in.validation_level = 3;
+ ninfo = state->req->in.logon.network = talloc(state, struct netr_NetworkInfo);
+ if (ninfo == NULL) goto failed;
+
+ ninfo->identity_info.account_name.string = talloc_strdup(state, user);
+ ninfo->identity_info.domain_name.string = talloc_strdup(state, domain);
+ ninfo->identity_info.parameter_control = logon_parameters;
+ ninfo->identity_info.logon_id_low = 0;
+ ninfo->identity_info.logon_id_high = 0;
+ ninfo->identity_info.workstation.string = talloc_strdup(state, workstation);
+
+ SMB_ASSERT(chal.length == sizeof(ninfo->challenge));
+ memcpy(ninfo->challenge, chal.data,
+ sizeof(ninfo->challenge));
+
+ tmp_nt_resp = data_blob_talloc(ninfo, nt_resp.data, nt_resp.length);
+ if ((nt_resp.data != NULL) &&
+ (tmp_nt_resp.data == NULL)) goto failed;
- state->domain_name = talloc_strdup(state, domain);
- if (state->domain_name == NULL) goto failed;
+ tmp_lm_resp = data_blob_talloc(ninfo, lm_resp.data, lm_resp.length);
+ if ((lm_resp.data != NULL) &&
+ (tmp_lm_resp.data == NULL)) goto failed;
- state->user_name = talloc_strdup(state, user);
- if (state->user_name == NULL) goto failed;
+ ninfo->nt.length = tmp_nt_resp.length;
+ ninfo->nt.data = tmp_nt_resp.data;
+ ninfo->lm.length = tmp_lm_resp.length;
+ ninfo->lm.data = tmp_lm_resp.data;
state->unix_username = NULL;
- state->workstation = talloc_strdup(state, workstation);
- if (state->workstation == NULL) goto failed;
-
- state->chal = data_blob_talloc(state, chal.data, chal.length);
- if ((chal.data != NULL) && (state->chal.data == NULL)) goto failed;
-
- state->nt_resp = data_blob_talloc(state, nt_resp.data, nt_resp.length);
- if ((nt_resp.data != NULL) &&
- (state->nt_resp.data == NULL)) goto failed;
-
- state->lm_resp = data_blob_talloc(state, lm_resp.data, lm_resp.length);
- if ((lm_resp.data != NULL) &&
- (state->lm_resp.data == NULL)) goto failed;
-
- ctx = wb_sid2domain_send(state, service, service->primary_sid);
+ ctx = wb_sam_logon_send(mem_ctx, service, state->req);
if (ctx == NULL) goto failed;
- ctx->async.fn = pam_auth_crap_recv_domain;
- ctx->async.private_data = state;
+ composite_continue(result, ctx, pam_auth_crap_recv_logon, state);
return result;
failed:
@@ -119,95 +127,19 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
Send of a SamLogon request to authenticate a user.
*/
-static void pam_auth_crap_recv_domain(struct composite_context *ctx)
+static void pam_auth_crap_recv_logon(struct composite_context *ctx)
{
+ DATA_BLOB tmp_blob;
+ struct netr_SamBaseInfo *base;
struct pam_auth_crap_state *state =
talloc_get_type(ctx->async.private_data,
struct pam_auth_crap_state);
- struct rpc_request *req;
- struct wbsrv_domain *domain;
-
- state->ctx->status = wb_sid2domain_recv(ctx, &domain);
- if (!composite_is_ok(state->ctx)) return;
- state->creds_state =
- cli_credentials_get_netlogon_creds(domain->schannel_creds);
-
- creds_client_authenticator(state->creds_state, &state->auth);
-
- state->ninfo.identity_info.account_name.string = state->user_name;
- state->ninfo.identity_info.domain_name.string = state->domain_name;
- state->ninfo.identity_info.parameter_control = state->logon_parameters;
- state->ninfo.identity_info.logon_id_low = 0;
- state->ninfo.identity_info.logon_id_high = 0;
- state->ninfo.identity_info.workstation.string = state->workstation;
-
- SMB_ASSERT(state->chal.length == sizeof(state->ninfo.challenge));
- memcpy(state->ninfo.challenge, state->chal.data,
- sizeof(state->ninfo.challenge));
-
- state->ninfo.nt.length = state->nt_resp.length;
- state->ninfo.nt.data = state->nt_resp.data;
- state->ninfo.lm.length = state->lm_resp.length;
- state->ninfo.lm.data = state->lm_resp.data;
-
- state->r.in.server_name = talloc_asprintf(
- state, "\\\\%s", dcerpc_server_name(domain->netlogon_pipe));
- if (composite_nomem(state->r.in.server_name, state->ctx)) return;
-
- ZERO_STRUCT(state->auth2);
-
- state->r.in.computer_name =
- cli_credentials_get_workstation(domain->schannel_creds);
- state->r.in.credential = &state->auth;
- state->r.in.return_authenticator = &state->auth2;
- state->r.in.logon_level = 2;
- state->r.in.validation_level = 3;
- state->r.in.logon.network = &state->ninfo;
- state->r.out.return_authenticator = NULL;
-
- req = dcerpc_netr_LogonSamLogon_send(domain->netlogon_pipe, state,
- &state->r);
- composite_continue_rpc(state->ctx, req, pam_auth_crap_recv_samlogon,
- state);
-}
-
-/*
- NTLM Authentication
-
- Check the SamLogon reply, decrypt and parse out the session keys and the
- info3 structure.
-*/
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
-{
- struct pam_auth_crap_state *state =
- talloc_get_type(req->async.private_data,
- struct pam_auth_crap_state);
- struct netr_SamBaseInfo *base;
- DATA_BLOB tmp_blob;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = wb_sam_logon_recv(ctx, state, state->req);
if (!composite_is_ok(state->ctx)) return;
- if ((state->r.out.return_authenticator == NULL) ||
- (!creds_client_check(state->creds_state,
- &state->r.out.return_authenticator->cred))) {
- DEBUG(0, ("Credentials check failed!\n"));
- composite_error(state->ctx, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- state->ctx->status = state->r.out.result;
- if (!composite_is_ok(state->ctx)) 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(state->creds_state,
- state->r.in.validation_level,
- &state->r.out.validation);
-
state->ctx->status = ndr_push_struct_blob(
- &tmp_blob, state, state->r.out.validation.sam3,
+ &tmp_blob, state, state->req->out.validation.sam3,
(ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
if (!composite_is_ok(state->ctx)) return;
@@ -220,25 +152,7 @@ static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
SIVAL(state->info3.data, 0, 1);
memcpy(state->info3.data+4, tmp_blob.data, tmp_blob.length);
- /* We actually only ask for level 3, and assume it above, but
- * anyway... */
-
- base = NULL;
- switch(state->r.in.validation_level) {
- case 2:
- base = &state->r.out.validation.sam2->base;
- break;
- case 3:
- base = &state->r.out.validation.sam3->base;
- break;
- case 6:
- base = &state->r.out.validation.sam6->base;
- break;
- }
- if (base == NULL) {
- composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
- return;
- }
+ base = &state->req->out.validation.sam3->base;
state->user_session_key = base->key;
state->lm_key = base->LMSessKey;