root/source4/librpc/rpc/dcerpc_secondary.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dcerpc_secondary_connection_send
  2. continue_open_smb
  3. continue_open_tcp
  4. continue_open_pipe
  5. continue_pipe_open
  6. dcerpc_secondary_connection_recv
  7. dcerpc_secondary_connection
  8. dcerpc_secondary_auth_connection_send
  9. dcerpc_secondary_auth_connection_bind
  10. dcerpc_secondary_auth_connection_continue
  11. dcerpc_secondary_auth_connection_recv

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    dcerpc connect functions
   5 
   6    Copyright (C) Andrew Tridgell 2003
   7    Copyright (C) Jelmer Vernooij 2004
   8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
   9    Copyright (C) Rafal Szczesniak  2005
  10    
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15    
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20    
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 
  26 #include "includes.h"
  27 #include "libcli/composite/composite.h"
  28 #include "lib/events/events.h"
  29 #include "librpc/rpc/dcerpc.h"
  30 #include "librpc/rpc/dcerpc_proto.h"
  31 #include "auth/credentials/credentials.h"
  32 #include "param/param.h"
  33 #include "libcli/resolve/resolve.h"
  34 #include "lib/socket/socket.h"
  35 
  36 struct sec_conn_state {
  37         struct dcerpc_pipe *pipe;
  38         struct dcerpc_pipe *pipe2;
  39         struct dcerpc_binding *binding;
  40         struct smbcli_tree *tree;
  41         struct socket_address *peer_addr;
  42 };
  43 
  44 
  45 static void continue_open_smb(struct composite_context *ctx);
  46 static void continue_open_tcp(struct composite_context *ctx);
  47 static void continue_open_pipe(struct composite_context *ctx);
  48 static void continue_pipe_open(struct composite_context *c);
  49 
  50 
  51 /*
  52   Send request to create a secondary dcerpc connection from a primary
  53   connection
  54 */
  55 _PUBLIC_ struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
     /* [<][>][^][v][top][bottom][index][help] */
  56                                                            struct dcerpc_binding *b)
  57 {
  58         struct composite_context *c;
  59         struct sec_conn_state *s;
  60         struct composite_context *pipe_smb_req;
  61         struct composite_context *pipe_tcp_req;
  62         struct composite_context *pipe_ncalrpc_req;
  63         
  64         /* composite context allocation and setup */
  65         c = composite_create(p, p->conn->event_ctx);
  66         if (c == NULL) return NULL;
  67 
  68         s = talloc_zero(c, struct sec_conn_state);
  69         if (composite_nomem(s, c)) return c;
  70         c->private_data = s;
  71 
  72         s->pipe     = p;
  73         s->binding  = b;
  74 
  75         /* initialise second dcerpc pipe based on primary pipe's event context */
  76         s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx, s->pipe->conn->iconv_convenience);
  77         if (composite_nomem(s->pipe2, c)) return c;
  78 
  79         if (DEBUGLEVEL >= 10)
  80                 s->pipe2->conn->packet_log_dir = s->pipe->conn->packet_log_dir;
  81 
  82         /* open second dcerpc pipe using the same transport as for primary pipe */
  83         switch (s->pipe->conn->transport.transport) {
  84         case NCACN_NP:
  85                 /* get smb tree of primary dcerpc pipe opened on smb */
  86                 s->tree = dcerpc_smb_tree(s->pipe->conn);
  87                 if (!s->tree) {
  88                         composite_error(c, NT_STATUS_INVALID_PARAMETER);
  89                         return c;
  90                 }
  91 
  92                 pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2, s->tree,
  93                                                          s->binding->endpoint);
  94                 composite_continue(c, pipe_smb_req, continue_open_smb, c);
  95                 return c;
  96 
  97         case NCACN_IP_TCP:
  98                 s->peer_addr = dcerpc_socket_peer_addr(s->pipe->conn, s);
  99                 if (!s->peer_addr) {
 100                         composite_error(c, NT_STATUS_INVALID_PARAMETER);
 101                         return c;
 102                 }
 103 
 104                 pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
 105                                                          s->peer_addr->addr,
 106                                                          s->binding->target_hostname,
 107                                                          atoi(s->binding->endpoint),
 108                                                          resolve_context_init(s));
 109                 composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
 110                 return c;
 111 
 112         case NCALRPC:
 113         case NCACN_UNIX_STREAM:
 114                 pipe_ncalrpc_req = dcerpc_pipe_open_unix_stream_send(s->pipe2->conn, 
 115                                                               dcerpc_unix_socket_path(s->pipe->conn));
 116                 composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
 117                 return c;
 118 
 119         default:
 120                 /* looks like a transport we don't support */
 121                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
 122         }
 123 
 124         return c;
 125 }
 126 
 127 
 128 /*
 129   Stage 2 of secondary_connection: Receive result of pipe open request on smb
 130 */
 131 static void continue_open_smb(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 134                                                       struct composite_context);
 135         
 136         c->status = dcerpc_pipe_open_smb_recv(ctx);
 137         if (!composite_is_ok(c)) return;
 138 
 139         continue_pipe_open(c);
 140 }
 141 
 142 
 143 /*
 144   Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
 145 */
 146 static void continue_open_tcp(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 149                                                       struct composite_context);
 150         
 151         c->status = dcerpc_pipe_open_tcp_recv(ctx);
 152         if (!composite_is_ok(c)) return;
 153 
 154         continue_pipe_open(c);
 155 }
 156 
 157 
 158 /*
 159   Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
 160 */
 161 static void continue_open_pipe(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 164                                                       struct composite_context);
 165 
 166         c->status = dcerpc_pipe_open_pipe_recv(ctx);
 167         if (!composite_is_ok(c)) return;
 168 
 169         continue_pipe_open(c);
 170 }
 171 
 172 
 173 /*
 174   Stage 3 of secondary_connection: Get binding data and flags from primary pipe
 175   and say if we're done ok.
 176 */
 177 static void continue_pipe_open(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 178 {
 179         struct sec_conn_state *s;
 180 
 181         s = talloc_get_type(c->private_data, struct sec_conn_state);
 182 
 183         s->pipe2->conn->flags = s->pipe->conn->flags;
 184         s->pipe2->binding     = s->binding;
 185         if (!talloc_reference(s->pipe2, s->binding)) {
 186                 composite_error(c, NT_STATUS_NO_MEMORY);
 187                 return;
 188         }
 189 
 190         composite_done(c);
 191 }
 192 
 193 
 194 /*
 195   Receive result of secondary rpc connection request and return
 196   second dcerpc pipe.
 197 */
 198 _PUBLIC_ NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 199                                           struct dcerpc_pipe **p2)
 200 {
 201         NTSTATUS status = composite_wait(c);
 202         struct sec_conn_state *s;
 203 
 204         s = talloc_get_type(c->private_data, struct sec_conn_state);
 205 
 206         if (NT_STATUS_IS_OK(status)) {
 207                 *p2 = talloc_steal(s->pipe, s->pipe2);
 208         }
 209 
 210         talloc_free(c);
 211         return status;
 212 }
 213 
 214 /*
 215   Create a secondary dcerpc connection from a primary connection
 216   - sync version
 217 
 218   If the primary is a SMB connection then the secondary connection
 219   will be on the same SMB connection, but using a new fnum
 220 */
 221 _PUBLIC_ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
     /* [<][>][^][v][top][bottom][index][help] */
 222                                      struct dcerpc_pipe **p2,
 223                                      struct dcerpc_binding *b)
 224 {
 225         struct composite_context *c;
 226         
 227         c = dcerpc_secondary_connection_send(p, b);
 228         return dcerpc_secondary_connection_recv(c, p2);
 229 }
 230 
 231 /*
 232   Create a secondary DCERPC connection, then bind (and possibly
 233   authenticate) using the supplied credentials.
 234 
 235   This creates a second connection, to the same host (and on ncacn_np on the same connection) as the first
 236 */
 237 struct sec_auth_conn_state {
 238         struct dcerpc_pipe *pipe2;
 239         struct dcerpc_binding *binding;
 240         const struct ndr_interface_table *table;
 241         struct cli_credentials *credentials;
 242         struct composite_context *ctx;
 243         struct loadparm_context *lp_ctx;
 244 };
 245 
 246 static void dcerpc_secondary_auth_connection_bind(struct composite_context *ctx);
 247 static void dcerpc_secondary_auth_connection_continue(struct composite_context *ctx);
 248 
 249 _PUBLIC_ struct composite_context* dcerpc_secondary_auth_connection_send(struct dcerpc_pipe *p,
     /* [<][>][^][v][top][bottom][index][help] */
 250                                                                 struct dcerpc_binding *binding,
 251                                                                 const struct ndr_interface_table *table,
 252                                                                 struct cli_credentials *credentials,
 253                                                                 struct loadparm_context *lp_ctx)
 254 {
 255 
 256         struct composite_context *c, *secondary_conn_ctx;
 257         struct sec_auth_conn_state *s;
 258         
 259         /* composite context allocation and setup */
 260         c = composite_create(p, p->conn->event_ctx);
 261         if (c == NULL) return NULL;
 262 
 263         s = talloc_zero(c, struct sec_auth_conn_state);
 264         if (composite_nomem(s, c)) return c;
 265         c->private_data = s;
 266         s->ctx = c;
 267 
 268         s->binding  = binding;
 269         s->table    = table;
 270         s->credentials = credentials;
 271         s->lp_ctx = lp_ctx;
 272         
 273         secondary_conn_ctx = dcerpc_secondary_connection_send(p, binding);
 274         
 275         if (composite_nomem(secondary_conn_ctx, s->ctx)) {
 276                 talloc_free(c);
 277                 return NULL;
 278         }
 279 
 280         composite_continue(s->ctx, secondary_conn_ctx, dcerpc_secondary_auth_connection_bind,
 281                            s);
 282         return c;
 283 }
 284 
 285 /*
 286   Stage 2 of secondary_auth_connection: 
 287   Having made the secondary connection, we will need to do an (authenticated) bind
 288 */
 289 static void dcerpc_secondary_auth_connection_bind(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 290 {
 291         struct composite_context *secondary_auth_ctx;
 292         struct sec_auth_conn_state *s = talloc_get_type(ctx->async.private_data,
 293                                                         struct sec_auth_conn_state);
 294         
 295         s->ctx->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
 296         if (!composite_is_ok(s->ctx)) return;
 297         
 298         secondary_auth_ctx = dcerpc_pipe_auth_send(s->pipe2, s->binding, s->table, s->credentials,
 299                                                    s->lp_ctx);
 300         composite_continue(s->ctx, secondary_auth_ctx, dcerpc_secondary_auth_connection_continue, s);
 301         
 302 }
 303 
 304 /*
 305   Stage 3 of secondary_auth_connection: Receive result of authenticated bind request
 306 */
 307 static void dcerpc_secondary_auth_connection_continue(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 308 {
 309         struct sec_auth_conn_state *s = talloc_get_type(ctx->async.private_data,
 310                                                         struct sec_auth_conn_state);
 311 
 312         s->ctx->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe2);
 313         if (!composite_is_ok(s->ctx)) return;
 314         
 315         composite_done(s->ctx);
 316 }
 317 
 318 /*
 319   Receive an authenticated pipe, created as a secondary connection
 320 */
 321 _PUBLIC_ NTSTATUS dcerpc_secondary_auth_connection_recv(struct composite_context *c, 
     /* [<][>][^][v][top][bottom][index][help] */
 322                                                TALLOC_CTX *mem_ctx,
 323                                                struct dcerpc_pipe **p)
 324 {
 325         NTSTATUS status = composite_wait(c);
 326         struct sec_auth_conn_state *s;
 327 
 328         s = talloc_get_type(c->private_data, struct sec_auth_conn_state);
 329 
 330         if (NT_STATUS_IS_OK(status)) {
 331                 *p = talloc_steal(mem_ctx, s->pipe2);
 332         }
 333 
 334         talloc_free(c);
 335         return status;
 336 }

/* [<][>][^][v][top][bottom][index][help] */