r23890: Allow wbinfo -a to work against Samba4's winbind.
authorAndrew Bartlett <abartlet@samba.org>
Mon, 16 Jul 2007 11:27:29 +0000 (11:27 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 20:01:08 +0000 (15:01 -0500)
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)

source4/librpc/config.mk
source4/librpc/rpc/dcerpc_connect.c
source4/librpc/rpc/dcerpc_secondary.c [new file with mode: 0644]
source4/selftest/test_member.sh
source4/winbind/wb_connect_sam.c
source4/winbind/wb_dom_info.c
source4/winbind/wb_init_domain.c
source4/winbind/wb_pam_auth.c

index f31ccf57f0544b55104871cb0b276c51a243bf71..5cec7e1f676cef1d3197e2922e4ea9f48cbd1136 100644 (file)
@@ -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 \
index 443b8b458a4ab857621fa38f8428698f375b68a7..3e49e6972b1e8c230a3fca137432ae0cf798726b 100644 (file)
@@ -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 (file)
index 0000000..685055d
--- /dev/null
@@ -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;
+}
index a76c10be91b3b3f50f428f944f8266167213c04e..29e3730342d1f9290557037bceb02129ff396100 100755 (executable)
@@ -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
index 3ca4734ae973d66afaac32165d06929f55746041..935ba266d3c3ee2cf813deb0256750fed0657c75 100644 (file)
@@ -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);
index 571ecb39b23fd4a9da1c40668e31fe76888dcb2c..5ec8f1a1597953ccd54c693d30b4d9b254f78c02 100644 (file)
@@ -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;
 
index 69ea9c7533c6fd163b80392d609873011dd50a23..cdc1491f2b3da53e16b635419ac539ca98f0d7ee 100644 (file)
@@ -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;
                }
index fffb7c408c034d3542d383c931f4cc8d6791c0c7..4874254eff91002977f9f115adc79b7df41b872a 100644 (file)
 #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;