r21535: - fixed a crash in the RAW-ACLS test. When a dcerpc_pipe is created
[samba.git] / source4 / winbind / wb_connect_lsa.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Connect to the LSA 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_lsa_c.h"
29
30 /* Helper to initialize LSA with a specific auth methods. Verify by opening
31  * the LSA policy. */
32
33 struct init_lsa_state {
34         struct composite_context *ctx;
35         struct dcerpc_pipe *lsa_pipe;
36
37         uint8_t auth_type;
38         struct cli_credentials *creds;
39
40         struct lsa_ObjectAttribute objectattr;
41         struct lsa_OpenPolicy2 openpolicy;
42         struct policy_handle *handle;
43 };
44
45 static void init_lsa_recv_pipe(struct composite_context *ctx);
46 static void init_lsa_recv_anon_bind(struct composite_context *ctx);
47 static void init_lsa_recv_auth_bind(struct composite_context *ctx);
48 static void init_lsa_recv_openpol(struct rpc_request *req);
49
50 struct composite_context *wb_init_lsa_send(TALLOC_CTX *mem_ctx,
51                                            struct smbcli_tree *tree,
52                                            uint8_t auth_type,
53                                            struct cli_credentials *creds)
54 {
55         struct composite_context *result, *ctx;
56         struct init_lsa_state *state;
57
58         result = talloc(mem_ctx, struct composite_context);
59         if (result == NULL) goto failed;
60         result->state = COMPOSITE_STATE_IN_PROGRESS;
61         result->async.fn = NULL;
62         result->event_ctx = tree->session->transport->socket->event.ctx;
63
64         state = talloc(result, struct init_lsa_state);
65         if (state == NULL) goto failed;
66         state->ctx = result;
67         result->private_data = state;
68
69         state->auth_type = auth_type;
70         state->creds = creds;
71
72         state->lsa_pipe = dcerpc_pipe_init(state, result->event_ctx);
73         if (state->lsa_pipe == NULL) goto failed;
74
75         ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe, tree,
76                                         "\\lsarpc");
77         ctx->async.fn = init_lsa_recv_pipe;
78         ctx->async.private_data = state;
79         return result;
80         
81  failed:
82         talloc_free(result);
83         return NULL;
84 }
85
86 static void init_lsa_recv_pipe(struct composite_context *ctx)
87 {
88         struct init_lsa_state *state =
89                 talloc_get_type(ctx->async.private_data,
90                                 struct init_lsa_state);
91
92         state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
93         if (!composite_is_ok(state->ctx)) return;
94
95         switch (state->auth_type) {
96         case DCERPC_AUTH_TYPE_NONE:
97                 ctx = dcerpc_bind_auth_none_send(state, state->lsa_pipe,
98                                                  &dcerpc_table_lsarpc);
99                 composite_continue(state->ctx, ctx, init_lsa_recv_anon_bind,
100                                    state);
101                 break;
102         case DCERPC_AUTH_TYPE_NTLMSSP:
103         case DCERPC_AUTH_TYPE_SCHANNEL:
104         {
105                 uint8_t auth_type;
106                 if (lp_winbind_sealed_pipes()) {
107                         auth_type = DCERPC_AUTH_LEVEL_PRIVACY;
108                 } else {
109                         auth_type = DCERPC_AUTH_LEVEL_INTEGRITY;
110                 }
111                 if (state->creds == NULL) {
112                         composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
113                         return;
114                 }
115                 ctx = dcerpc_bind_auth_send(state, state->lsa_pipe,
116                                             &dcerpc_table_lsarpc,
117                                             state->creds, state->auth_type,
118                                             auth_type,
119                                             NULL);
120                 composite_continue(state->ctx, ctx, init_lsa_recv_auth_bind,
121                                    state);
122                 break;
123         }
124         default:
125                 composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
126         }
127 }
128
129 static void init_lsa_recv_anon_bind(struct composite_context *ctx)
130 {
131         struct init_lsa_state *state =
132                 talloc_get_type(ctx->async.private_data,
133                                 struct init_lsa_state);
134         struct rpc_request *req;
135
136         state->ctx->status = dcerpc_bind_auth_none_recv(ctx);
137         if (!composite_is_ok(state->ctx)) return;
138                         
139         state->handle = talloc(state, struct policy_handle);
140         if (composite_nomem(state->handle, state->ctx)) return;
141
142         state->openpolicy.in.system_name =
143                 talloc_asprintf(state, "\\\\%s",
144                                 dcerpc_server_name(state->lsa_pipe));
145         ZERO_STRUCT(state->objectattr);
146         state->openpolicy.in.attr = &state->objectattr;
147         state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
148         state->openpolicy.out.handle = state->handle;
149
150         req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
151                                           &state->openpolicy);
152         composite_continue_rpc(state->ctx, req, init_lsa_recv_openpol, state);
153 }
154
155 static void init_lsa_recv_auth_bind(struct composite_context *ctx)
156 {
157         struct init_lsa_state *state =
158                 talloc_get_type(ctx->async.private_data,
159                                 struct init_lsa_state);
160         struct rpc_request *req;
161
162         state->ctx->status = dcerpc_bind_auth_recv(ctx);
163         if (!composite_is_ok(state->ctx)) return;
164                         
165         state->handle = talloc(state, struct policy_handle);
166         if (composite_nomem(state->handle, state->ctx)) return;
167
168         state->openpolicy.in.system_name =
169                 talloc_asprintf(state, "\\\\%s",
170                                 dcerpc_server_name(state->lsa_pipe));
171         ZERO_STRUCT(state->objectattr);
172         state->openpolicy.in.attr = &state->objectattr;
173         state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
174         state->openpolicy.out.handle = state->handle;
175
176         req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
177                                           &state->openpolicy);
178         composite_continue_rpc(state->ctx, req, init_lsa_recv_openpol, state);
179 }
180
181 static void init_lsa_recv_openpol(struct rpc_request *req)
182 {
183         struct init_lsa_state *state =
184                 talloc_get_type(req->async.private,
185                                 struct init_lsa_state);
186
187         state->ctx->status = dcerpc_ndr_request_recv(req);
188         if (!composite_is_ok(state->ctx)) return;
189         state->ctx->status = state->openpolicy.out.result;
190         if (!composite_is_ok(state->ctx)) return;
191
192         composite_done(state->ctx);
193 }
194
195 NTSTATUS wb_init_lsa_recv(struct composite_context *c,
196                           TALLOC_CTX *mem_ctx,
197                           struct dcerpc_pipe **lsa_pipe,
198                           struct policy_handle **lsa_policy)
199 {
200         NTSTATUS status = composite_wait(c);
201         if (NT_STATUS_IS_OK(status)) {
202                 struct init_lsa_state *state =
203                         talloc_get_type(c->private_data,
204                                         struct init_lsa_state);
205                 *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe);
206                 *lsa_policy = talloc_steal(mem_ctx, state->handle);
207         }
208         talloc_free(c);
209         return status;
210 }
211
212
213 /*
214  * Connect to LSA using the credentials, try NTLMSSP and SCHANNEL using the
215  * given credentials. If both fail or no credentials are available, fall back
216  * to an anonymous bind.
217  */
218
219 struct connect_lsa_state {
220         struct composite_context *ctx;
221         struct smbcli_tree *tree;
222         struct cli_credentials *credentials;
223
224         uint8_t auth_type;
225         struct dcerpc_pipe *lsa_pipe;
226         struct policy_handle *lsa_policy;
227 };
228
229 static void connect_lsa_recv_ntlmssp(struct composite_context *ctx);
230 static void connect_lsa_recv_schannel(struct composite_context *ctx);
231 static void connect_lsa_recv_anon(struct composite_context *ctx);
232
233 struct composite_context *wb_connect_lsa_send(TALLOC_CTX *mem_ctx,
234                                               struct smbcli_tree *tree,
235                                               struct cli_credentials *credentials)
236 {
237         struct composite_context *result, *ctx;
238         struct connect_lsa_state *state;
239
240         result = talloc(mem_ctx, struct composite_context);
241         if (result == NULL) goto failed;
242         result->state = COMPOSITE_STATE_IN_PROGRESS;
243         result->async.fn = NULL;
244         result->event_ctx = tree->session->transport->socket->event.ctx;
245
246         state = talloc(result, struct connect_lsa_state);
247         if (state == NULL) goto failed;
248         state->ctx = result;
249         result->private_data = state;
250
251         state->tree = tree;
252         state->credentials = credentials;
253
254         if (credentials == NULL) {
255                 ctx = wb_init_lsa_send(state, tree, DCERPC_AUTH_TYPE_NONE,
256                                        NULL);
257                 if (ctx == NULL) goto failed;
258                 ctx->async.fn = connect_lsa_recv_anon;
259                 ctx->async.private_data = state;
260                 return result;
261         }
262
263         ctx = wb_init_lsa_send(state, tree, DCERPC_AUTH_TYPE_NTLMSSP,
264                                credentials);
265         if (ctx == NULL) goto failed;
266         ctx->async.fn = connect_lsa_recv_ntlmssp;
267         ctx->async.private_data = state;
268         return result;
269
270  failed:
271         talloc_free(result);
272         return NULL;
273 }
274
275 static void connect_lsa_recv_ntlmssp(struct composite_context *ctx)
276 {
277         struct connect_lsa_state *state =
278                 talloc_get_type(ctx->async.private_data,
279                                 struct connect_lsa_state);
280
281         state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
282                                               &state->lsa_policy);
283
284         if (NT_STATUS_IS_OK(state->ctx->status)) {
285                 state->auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
286                 composite_done(state->ctx);
287                 return;
288         }
289
290         ctx = wb_init_lsa_send(state, state->tree, DCERPC_AUTH_TYPE_SCHANNEL,
291                                state->credentials);
292         composite_continue(state->ctx, ctx,
293                            connect_lsa_recv_schannel, state);
294 }
295
296 static void connect_lsa_recv_schannel(struct composite_context *ctx)
297 {
298         struct connect_lsa_state *state =
299                 talloc_get_type(ctx->async.private_data,
300                                 struct connect_lsa_state);
301
302         state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
303                                               &state->lsa_policy);
304
305         if (NT_STATUS_IS_OK(state->ctx->status)) {
306                 state->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
307                 composite_done(state->ctx);
308                 return;
309         }
310
311         ctx = wb_init_lsa_send(state, state->tree, DCERPC_AUTH_TYPE_NONE,
312                                state->credentials);
313         composite_continue(state->ctx, ctx,
314                            connect_lsa_recv_anon, state);
315 }
316
317 static void connect_lsa_recv_anon(struct composite_context *ctx)
318 {
319         struct connect_lsa_state *state =
320                 talloc_get_type(ctx->async.private_data,
321                                 struct connect_lsa_state);
322
323         state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
324                                               &state->lsa_policy);
325         if (!composite_is_ok(state->ctx)) return;
326
327         state->auth_type = DCERPC_AUTH_TYPE_NONE;
328         composite_done(state->ctx);
329 }
330
331 NTSTATUS wb_connect_lsa_recv(struct composite_context *c,
332                              TALLOC_CTX *mem_ctx,
333                              uint8_t *auth_type,
334                              struct dcerpc_pipe **lsa_pipe,
335                              struct policy_handle **lsa_policy)
336 {
337         NTSTATUS status = composite_wait(c);
338         if (NT_STATUS_IS_OK(status)) {
339                 struct connect_lsa_state *state =
340                         talloc_get_type(c->private_data,
341                                         struct connect_lsa_state);
342                 *auth_type = state->auth_type;
343                 *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe);
344                 *lsa_policy = talloc_steal(mem_ctx, state->lsa_policy);
345         }
346         talloc_free(c);
347         return status;
348 }
349
350 NTSTATUS wb_connect_lsa(TALLOC_CTX *mem_ctx,
351                         struct smbcli_tree *tree,
352                         struct cli_credentials *credentials,
353                         uint8_t *auth_type,
354                         struct dcerpc_pipe **lsa_pipe,
355                         struct policy_handle **lsa_policy)
356 {
357         struct composite_context *c;
358         c = wb_connect_lsa_send(mem_ctx, tree, credentials);
359         return wb_connect_lsa_recv(c, mem_ctx, auth_type, lsa_pipe,
360                                    lsa_policy);
361 }