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
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ 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,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libcli/smb2/smb2_calls.h"
#include "librpc/rpc/dcerpc.h"
#include "auth/credentials/credentials.h"
-#include "auth/credentials/credentials_krb5.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
struct pipe_np_smb_state {
remote rpc server */
conn->in.dest_host = s->io.binding->host;
conn->in.port = 0;
- conn->in.called_name = s->io.binding->target_hostname;
+ if (s->io.binding->target_hostname == NULL)
+ conn->in.called_name = "*SMBSERVER"; /* FIXME: This is invalid */
+ else
+ conn->in.called_name = s->io.binding->target_hostname;
conn->in.service = "IPC$";
conn->in.service_type = NULL;
- conn->in.workgroup = lp_workgroup();
+ conn->in.workgroup = lp_workgroup(global_loadparm);
/*
* provide proper credentials - user supplied, but allow a
*/
s->conn.in.credentials = s->io.creds;
if (s->io.binding->flags & DCERPC_SCHANNEL) {
- conn->in.fallback_to_anonymous = True;
+ conn->in.fallback_to_anonymous = true;
} else {
- conn->in.fallback_to_anonymous = False;
+ conn->in.fallback_to_anonymous = false;
}
/* send smb connect request */
Initiate async open of a rpc connection request on SMB2 using
the binding structure to determine the endpoint and options
*/
-static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(TALLOC_CTX *mem_ctx,
- struct dcerpc_pipe_connect *io)
+static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
+ TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe_connect *io)
{
struct composite_context *c;
struct pipe_np_smb2_state *s;
s->io.creds = cli_credentials_init(mem_ctx);
if (composite_nomem(s->io.creds, c)) return c;
- cli_credentials_set_anonymous(s->io.creds);
- cli_credentials_guess(s->io.creds);
+ cli_credentials_guess(s->io.creds, global_loadparm);
}
/* send smb2 connect request */
- conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", s->io.creds,
+ conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$",
+ s->io.resolve_ctx,
+ s->io.creds,
c->event_ctx);
composite_continue(c, conn_req, continue_smb2_connect, c);
return c;
/* send pipe open request on tcp/ip */
pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname,
- s->port);
+ s->port, io->resolve_ctx);
composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
return c;
}
s->io = *io;
/* send pipe open request */
- pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, s->io.binding->endpoint);
+ pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, lp_ncalrpc_dir(global_loadparm),
+ s->io.binding->endpoint);
composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
return c;
}
struct pipe_connect_state {
struct dcerpc_pipe *pipe;
struct dcerpc_binding *binding;
- const struct dcerpc_interface_table *table;
+ const struct ndr_interface_table *table;
struct cli_credentials *credentials;
+ struct loadparm_context *lp_ctx;
};
pc.binding = s->binding;
pc.interface = s->table;
pc.creds = s->credentials;
+ pc.resolve_ctx = lp_resolve_context(global_loadparm);
/* connect dcerpc pipe depending on required transport */
switch (s->binding->transport) {
}
auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
- s->credentials);
+ s->credentials, s->lp_ctx);
composite_continue(c, auth_bind_req, continue_pipe_auth, c);
}
*/
struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
struct dcerpc_binding *binding,
- const struct dcerpc_interface_table *table,
+ const struct ndr_interface_table *table,
struct cli_credentials *credentials,
- struct event_context *ev)
+ struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
struct composite_context *c;
struct pipe_connect_state *s;
s->binding = binding;
s->table = table;
s->credentials = credentials;
+ s->lp_ctx = lp_ctx;
event_add_timed(c->event_ctx, c,
timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
dcerpc_connect_timeout_handler, c);
switch (s->binding->transport) {
+ case NCA_UNKNOWN: {
+ struct composite_context *binding_req;
+ binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
+ s->pipe->conn->event_ctx,
+ s->lp_ctx);
+ composite_continue(c, binding_req, continue_map_binding, c);
+ return c;
+ }
+
case NCACN_NP:
case NCACN_IP_TCP:
case NCALRPC:
if (!s->binding->endpoint) {
struct composite_context *binding_req;
binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
- s->pipe->conn->event_ctx);
+ s->pipe->conn->event_ctx,
+ s->lp_ctx);
composite_continue(c, binding_req, continue_map_binding, c);
return c;
}
NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
struct dcerpc_pipe **pp,
struct dcerpc_binding *binding,
- const struct dcerpc_interface_table *table,
+ const struct ndr_interface_table *table,
struct cli_credentials *credentials,
- struct event_context *ev)
+ struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
struct composite_context *c;
c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
- credentials, ev);
+ credentials, ev, lp_ctx);
return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
}
*/
struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
const char *binding,
- const struct dcerpc_interface_table *table,
+ const struct ndr_interface_table *table,
struct cli_credentials *credentials,
- struct event_context *ev)
+ struct event_context *ev, struct loadparm_context *lp_ctx)
{
struct composite_context *c;
struct pipe_conn_state *s;
is established
*/
pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
- credentials, ev);
+ credentials, ev, lp_ctx);
composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
return c;
}
struct pipe_conn_state *s;
status = composite_wait(c);
- s = talloc_get_type(c->private_data, struct pipe_conn_state);
- *pp = talloc_steal(mem_ctx, s->pipe);
-
+ if (NT_STATUS_IS_OK(status)) {
+ s = talloc_get_type(c->private_data, struct pipe_conn_state);
+ *pp = talloc_steal(mem_ctx, s->pipe);
+ }
talloc_free(c);
return status;
}
NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
struct dcerpc_pipe **pp,
const char *binding,
- const struct dcerpc_interface_table *table,
+ const struct ndr_interface_table *table,
struct cli_credentials *credentials,
- struct event_context *ev)
+ struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
struct composite_context *c;
c = dcerpc_pipe_connect_send(parent_ctx, binding,
- table,
- credentials, ev);
+ table, credentials, ev, lp_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);
-}