Upgrade the librpc and libnet code.
[samba-svnmirror.git] / source / winbind / wb_connect_sam.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Connect to the SAMR pipe, given an smbcli_tree and possibly some
5    credentials. Try ntlmssp, schannel and anon in that order.
6
7    Copyright (C) Volker Lendecke 2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "libcli/composite/composite.h"
26
27 #include "libcli/raw/libcliraw.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
29
30
31 /* Helper to initialize SAMR with a specific auth methods. Verify by opening
32  * the SAM handle */
33
34 struct connect_samr_state {
35         struct composite_context *ctx;
36         uint8_t auth_type;
37         struct cli_credentials *creds;
38         struct dom_sid *sid;
39
40         struct dcerpc_pipe *samr_pipe;
41         struct policy_handle *connect_handle;
42         struct policy_handle *domain_handle;
43
44         struct samr_Connect2 c;
45         struct samr_OpenDomain o;
46 };
47
48 static void connect_samr_recv_pipe(struct composite_context *ctx);
49 static void connect_samr_recv_anon_bind(struct composite_context *ctx);
50 static void connect_samr_recv_auth_bind(struct composite_context *ctx);
51 static void connect_samr_recv_conn(struct rpc_request *req);
52 static void connect_samr_recv_open(struct rpc_request *req);
53
54 struct composite_context *wb_connect_sam_send(TALLOC_CTX *mem_ctx,
55                                               struct smbcli_tree *tree,
56                                               uint8_t auth_type,
57                                               struct cli_credentials *creds,
58                                               const struct dom_sid *domain_sid)
59 {
60         struct composite_context *result, *ctx;
61         struct connect_samr_state *state;
62
63         result = talloc(mem_ctx, struct composite_context);
64         if (result == NULL) goto failed;
65         result->state = COMPOSITE_STATE_IN_PROGRESS;
66         result->async.fn = NULL;
67         result->event_ctx = tree->session->transport->socket->event.ctx;
68
69         state = talloc(result, struct connect_samr_state);
70         if (state == NULL) goto failed;
71         state->ctx = result;
72         result->private_data = state;
73
74         state->auth_type = auth_type;
75         state->creds = creds;
76         state->sid = dom_sid_dup(state, domain_sid);
77         if (state->sid == NULL) goto failed;
78
79         state->samr_pipe = dcerpc_pipe_init(state, result->event_ctx);
80         if (state->samr_pipe == NULL) goto failed;
81
82         ctx = dcerpc_pipe_open_smb_send(state->samr_pipe->conn, tree,
83                                         "\\samr");
84         ctx->async.fn = connect_samr_recv_pipe;
85         ctx->async.private_data = state;
86         return result;
87         
88  failed:
89         talloc_free(result);
90         return NULL;
91 }
92
93 static void connect_samr_recv_pipe(struct composite_context *ctx)
94 {
95         struct connect_samr_state *state =
96                 talloc_get_type(ctx->async.private_data,
97                                 struct connect_samr_state);
98
99         state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
100         if (!composite_is_ok(state->ctx)) return;
101
102         switch (state->auth_type) {
103         case DCERPC_AUTH_TYPE_NONE:
104                 ctx = dcerpc_bind_auth_none_send(state, state->samr_pipe,
105                                                  &dcerpc_table_samr);
106                 composite_continue(state->ctx, ctx,
107                                    connect_samr_recv_anon_bind, state);
108                 break;
109         case DCERPC_AUTH_TYPE_NTLMSSP:
110         case DCERPC_AUTH_TYPE_SCHANNEL:
111         {
112                 uint8_t auth_type;
113                 if (lp_winbind_sealed_pipes()) {
114                         auth_type = DCERPC_AUTH_LEVEL_PRIVACY;
115                 } else {
116                         auth_type = DCERPC_AUTH_LEVEL_INTEGRITY;
117                 }
118                 if (state->creds == NULL) {
119                         composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
120                         return;
121                 }
122                 ctx = dcerpc_bind_auth_send(state, state->samr_pipe,
123                                             &dcerpc_table_samr,
124                                             state->creds, state->auth_type,
125                                             auth_type,
126                                             NULL);
127                 composite_continue(state->ctx, ctx,
128                                    connect_samr_recv_auth_bind, state);
129                 break;
130         }
131         default:
132                 composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
133         }
134 }
135
136 static void connect_samr_recv_anon_bind(struct composite_context *ctx)
137 {
138         struct connect_samr_state *state =
139                 talloc_get_type(ctx->async.private_data,
140                                 struct connect_samr_state);
141         struct rpc_request *req;
142
143         state->ctx->status = dcerpc_bind_auth_none_recv(ctx);
144         if (!composite_is_ok(state->ctx)) return;
145                         
146         state->connect_handle = talloc(state, struct policy_handle);
147         if (composite_nomem(state->connect_handle, state->ctx)) return;
148
149         state->c.in.system_name =
150                 talloc_asprintf(state, "\\\\%s",
151                                 dcerpc_server_name(state->samr_pipe));
152         state->c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
153         state->c.out.connect_handle = state->connect_handle;
154
155         req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c);
156         composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state);
157 }
158
159 static void connect_samr_recv_auth_bind(struct composite_context *ctx)
160 {
161         struct connect_samr_state *state =
162                 talloc_get_type(ctx->async.private_data,
163                                 struct connect_samr_state);
164         struct rpc_request *req;
165
166         state->ctx->status = dcerpc_bind_auth_recv(ctx);
167         if (!composite_is_ok(state->ctx)) return;
168                         
169         state->connect_handle = talloc(state, struct policy_handle);
170         if (composite_nomem(state->connect_handle, state->ctx)) return;
171
172         state->c.in.system_name =
173                 talloc_asprintf(state, "\\\\%s",
174                                 dcerpc_server_name(state->samr_pipe));
175         state->c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
176         state->c.out.connect_handle = state->connect_handle;
177
178         req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c);
179         composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state);
180 }
181
182 static void connect_samr_recv_conn(struct rpc_request *req)
183 {
184         struct connect_samr_state *state =
185                 talloc_get_type(req->async.private,
186                                 struct connect_samr_state);
187
188         state->ctx->status = dcerpc_ndr_request_recv(req);
189         if (!composite_is_ok(state->ctx)) return;
190         state->ctx->status = state->c.out.result;
191         if (!composite_is_ok(state->ctx)) return;
192
193         state->domain_handle = talloc(state, struct policy_handle);
194         if (composite_nomem(state->domain_handle, state->ctx)) return;
195
196         state->o.in.connect_handle = state->connect_handle;
197         state->o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
198         state->o.in.sid = state->sid;
199         state->o.out.domain_handle = state->domain_handle;
200
201         req = dcerpc_samr_OpenDomain_send(state->samr_pipe, state, &state->o);
202         composite_continue_rpc(state->ctx, req,
203                                connect_samr_recv_open, state);
204 }
205
206 static void connect_samr_recv_open(struct rpc_request *req)
207 {
208         struct connect_samr_state *state =
209                 talloc_get_type(req->async.private,
210                                 struct connect_samr_state);
211
212         state->ctx->status = dcerpc_ndr_request_recv(req);
213         if (!composite_is_ok(state->ctx)) return;
214         state->ctx->status = state->o.out.result;
215         if (!composite_is_ok(state->ctx)) return;
216
217         composite_done(state->ctx);
218 }
219
220 NTSTATUS wb_connect_sam_recv(struct composite_context *c,
221                              TALLOC_CTX *mem_ctx,
222                              struct dcerpc_pipe **samr_pipe,
223                              struct policy_handle **connect_handle,
224                              struct policy_handle **domain_handle)
225 {
226         NTSTATUS status = composite_wait(c);
227         if (NT_STATUS_IS_OK(status)) {
228                 struct connect_samr_state *state =
229                         talloc_get_type(c->private_data,
230                                         struct connect_samr_state);
231                 *samr_pipe = talloc_steal(mem_ctx, state->samr_pipe);
232                 *connect_handle = talloc_steal(mem_ctx, state->connect_handle);
233                 *domain_handle = talloc_steal(mem_ctx, state->domain_handle);
234         }
235         talloc_free(c);
236         return status;
237 }
238
239 NTSTATUS wb_connect_sam(TALLOC_CTX *mem_ctx,
240                         struct smbcli_tree *tree,
241                         uint8_t auth_type,
242                         struct cli_credentials *creds,
243                         const struct dom_sid *domain_sid,
244                         struct dcerpc_pipe **samr_pipe,
245                         struct policy_handle **connect_handle,
246                         struct policy_handle **domain_handle)
247 {
248         struct composite_context *c =
249                 wb_connect_sam_send(mem_ctx, tree, auth_type, creds,
250                                     domain_sid);
251         return wb_connect_sam_recv(c, mem_ctx, samr_pipe, connect_handle,
252                                    domain_handle);
253 }