7ab90fbbf7140f41dd0edf6a47546b437f93ecd3
[kamenim/samba.git] / source4 / librpc / rpc / dcerpc_connect.c
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
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 2 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, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26
27 #include "includes.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/ndr_epmapper.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "libcli/raw/libcliraw.h"
33 #include "libcli/composite/composite.h"
34 #include "libcli/smb_composite/smb_composite.h"
35 #include "libcli/smb2/smb2.h"
36
37
38 struct dcerpc_pipe_connect;
39
40 struct pipe_np_smb_state {
41         struct smb_composite_connect conn;
42         struct smbcli_tree *tree;
43         struct dcerpc_pipe_connect io;
44 };
45
46
47 /*
48   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
49 */
50 void continue_pipe_open_smb(struct composite_context *ctx)
51 {
52         struct composite_context *c = talloc_get_type(ctx->async.private_data,
53                                                       struct composite_context);
54         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
55                                                       struct pipe_np_smb_state);
56
57         /* receive result of named pipe open request on smb */
58         c->status = dcerpc_pipe_open_smb_recv(ctx);
59         if (!NT_STATUS_IS_OK(c->status)) {
60                 DEBUG(0,("Failed to open pipe %s - %s\n", s->io.pipe_name, nt_errstr(c->status)));
61                 composite_error(c, c->status);
62                 return;
63         }
64
65         composite_done(c);
66 }
67
68 /*
69   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
70 */
71 void continue_smb_connect(struct composite_context *ctx)
72 {
73         struct composite_context *open_ctx;
74         struct composite_context *c = talloc_get_type(ctx->async.private_data,
75                                                       struct composite_context);
76         struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
77                                                       struct pipe_np_smb_state);
78         
79         /* receive result of smb connect request */
80         c->status = smb_composite_connect_recv(ctx, c);
81         if (!NT_STATUS_IS_OK(c->status)) {
82                 DEBUG(0,("Failed to connect to %s - %s\n", s->io.binding->host, nt_errstr(c->status)));
83                 composite_error(c, c->status);
84                 return;
85         }
86
87         /* prepare named pipe open parameters */
88         s->tree         = s->conn.out.tree;
89         s->io.pipe_name = s->io.binding->endpoint;
90
91         /* send named pipe open request */
92         open_ctx = dcerpc_pipe_open_smb_send(s->io.pipe->conn, s->tree, s->io.pipe_name);
93         if (open_ctx == NULL) {
94                 composite_error(c, NT_STATUS_NO_MEMORY);
95                 return;
96         }
97
98         composite_continue(c, open_ctx, continue_pipe_open_smb, c);
99 }
100
101
102 /*
103   Initiate async open of a rpc connection to a rpc pipe on SMB using
104   the binding structure to determine the endpoint and options
105 */
106 struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *tmp_ctx, 
107                                                                 struct dcerpc_pipe_connect *io)
108 {
109         struct composite_context *c;
110         struct pipe_np_smb_state *s;
111         struct composite_context *conn_req;
112         struct smb_composite_connect *conn;
113
114         /* composite context allocation and setup */
115         c = talloc_zero(tmp_ctx, struct composite_context);
116         if (c == NULL) return NULL;
117
118         s = talloc_zero(c, struct pipe_np_smb_state);
119         if (s == NULL) {
120                 composite_error(c, NT_STATUS_NO_MEMORY);
121                 goto done;
122         }
123
124         c->state = COMPOSITE_STATE_IN_PROGRESS;
125         c->private_data = s;
126         c->event_ctx = io->pipe->conn->event_ctx;
127
128         s->io  = *io;
129         conn   = &s->conn;
130
131         /* prepare smb connection parameters: we're connecting to IPC$ share on
132            remote rpc server */
133         conn->in.dest_host              = s->io.binding->host;
134         conn->in.port                   = 0;
135         conn->in.called_name            = strupper_talloc(tmp_ctx, s->io.binding->host);
136         conn->in.service                = "IPC$";
137         conn->in.service_type           = NULL;
138         conn->in.fallback_to_anonymous  = False;
139         conn->in.workgroup              = lp_workgroup();
140
141         /*
142          * provide proper credentials - user supplied or anonymous in case this is
143          * schannel connection
144          */
145         if (s->io.binding->flags & DCERPC_SCHANNEL) {
146                 struct cli_credentials *anon_creds;
147
148                 anon_creds = cli_credentials_init(tmp_ctx);
149                 if (!anon_creds) {
150                         composite_error(c, NT_STATUS_NO_MEMORY);
151                         goto done;
152                 }
153
154                 cli_credentials_set_anonymous(anon_creds);
155                 cli_credentials_guess(anon_creds);
156
157                 s->conn.in.credentials = anon_creds;
158
159         } else {
160                 s->conn.in.credentials = s->io.creds;
161         }
162
163         /* send smb connect request */
164         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, s->io.pipe->conn->event_ctx);
165         if (!conn_req) {
166                 composite_error(c, NT_STATUS_NO_MEMORY);
167                 goto done;
168         }
169
170         composite_continue(c, conn_req, continue_smb_connect, c);
171
172 done:
173         return c;
174 }
175
176
177 /*
178   Receive result of a rpc connection to a rpc pipe on SMB
179 */
180 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
181 {
182         NTSTATUS status = composite_wait(c);
183
184         talloc_free(c);
185         return status;
186 }
187
188
189 /*
190   Sync version of a rpc connection to a rpc pipe on SMB
191 */
192 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb(TALLOC_CTX *tmp_ctx,
193                                           struct dcerpc_pipe_connect *io)
194 {
195         struct composite_context *c;
196         c = dcerpc_pipe_connect_ncacn_np_smb_send(tmp_ctx, io);
197         return dcerpc_pipe_connect_ncacn_np_smb_recv(c);
198 }
199
200
201 struct pipe_np_smb2_state {
202         struct smb2_tree *tree;
203         struct dcerpc_pipe_connect io;
204 };
205
206
207 /*
208   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
209 */
210 void continue_pipe_open_smb2(struct composite_context *ctx)
211 {
212         struct composite_context *c = talloc_get_type(ctx->async.private_data,
213                                                       struct composite_context);
214         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
215                                                        struct pipe_np_smb2_state);
216
217         /* receive result of named pipe open request on smb2 */
218         c->status = dcerpc_pipe_open_smb2_recv(ctx);
219         if (!NT_STATUS_IS_OK(c->status)) {
220                 DEBUG(0,("Failed to open pipe %s - %s\n", s->io.pipe_name, nt_errstr(c->status)));
221                 composite_error(c, c->status);
222                 return;
223         }
224
225         composite_done(c);
226 }
227
228
229 /*
230   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
231 */
232 void continue_smb2_connect(struct composite_context *ctx)
233 {
234         struct composite_context *open_req;
235         struct composite_context *c = talloc_get_type(ctx->async.private_data,
236                                                       struct composite_context);
237         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
238                                                        struct pipe_np_smb2_state);
239
240         /* receive result of smb2 connect request */
241         c->status = smb2_connect_recv(ctx, c, &s->tree);
242         if (!NT_STATUS_IS_OK(c->status)) {
243                 DEBUG(0,("Failed to connect to %s - %s\n", s->io.binding->host, nt_errstr(c->status)));
244                 composite_error(c, c->status);
245                 return;
246         }
247
248         /* prepare named pipe open parameters */
249         s->io.pipe_name = s->io.binding->endpoint;
250
251         /* send named pipe open request */
252         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe->conn, s->tree, s->io.pipe_name);
253         if (open_req == NULL) {
254                 composite_error(c, NT_STATUS_NO_MEMORY);
255                 return;
256         }
257
258         composite_continue(c, open_req, continue_pipe_open_smb2, c);
259 }
260
261
262 /* 
263    Initiate async open of a rpc connection request on SMB2 using
264    the binding structure to determine the endpoint and options
265 */
266 struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(TALLOC_CTX *mem_ctx,
267                                                                  struct dcerpc_pipe_connect *io)
268 {
269         struct composite_context *c;
270         struct pipe_np_smb2_state *s;
271         struct composite_context *conn_req;
272
273         /* composite context allocation and setup */
274         c = talloc_zero(mem_ctx, struct composite_context);
275         if (c == NULL) return NULL;
276
277         s = talloc_zero(c, struct pipe_np_smb2_state);
278         if (s == NULL) {
279                 composite_error(c, NT_STATUS_NO_MEMORY);
280                 goto done;
281         }
282         
283         c->state = COMPOSITE_STATE_IN_PROGRESS;
284         c->private_data = s;
285         c->event_ctx = io->pipe->conn->event_ctx;
286
287         s->io = *io;
288
289         /*
290          * provide proper credentials - user supplied or anonymous in case this is
291          * schannel connection
292          */
293         if (s->io.binding->flags & DCERPC_SCHANNEL) {
294                 s->io.creds = cli_credentials_init(mem_ctx);
295                 if (s->io.creds) {
296                         composite_error(c, NT_STATUS_NO_MEMORY);
297                         goto done;
298                 }
299
300                 cli_credentials_set_anonymous(s->io.creds);
301                 cli_credentials_guess(s->io.creds);
302         }
303
304         /* send smb2 connect request */
305         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", s->io.creds,
306                                      c->event_ctx);
307         if (conn_req == NULL) {
308                 composite_error(c, NT_STATUS_NO_MEMORY);
309                 goto done;
310         }
311
312         composite_continue(c, conn_req, continue_smb2_connect, c);
313
314 done:
315         return c;
316 }
317
318
319 /*
320   Receive result of a rpc connection to a rpc pipe on SMB2
321 */
322 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
323 {
324         NTSTATUS status = composite_wait(c);
325         
326         talloc_free(c);
327         return status;
328 }
329
330
331 /*
332   Sync version of a rpc connection to a rpc pipe on SMB2
333 */
334 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx,
335                                            struct dcerpc_pipe_connect *io)
336 {
337         struct composite_context *c;
338         c = dcerpc_pipe_connect_ncacn_np_smb2_send(mem_ctx, io);
339         return dcerpc_pipe_connect_ncacn_np_smb2_recv(c);
340 }